Added the beginnings of a small private API for debug support.
Entirely implemented on top of the public <debugger.h> API, but more convenient to use. Lives in a separate library libdebug.so. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@11925 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _DEBUG_SUPPORT_H
|
||||
#define _DEBUG_SUPPORT_H
|
||||
|
||||
#include <debugger.h>
|
||||
#include <OS.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct debug_context {
|
||||
port_id nub_port;
|
||||
port_id reply_port;
|
||||
} debug_context;
|
||||
|
||||
|
||||
status_t init_debug_context(debug_context *context, port_id nubPort);
|
||||
void destroy_debug_context(debug_context *context);
|
||||
|
||||
status_t send_debug_message(debug_context *context, int32 messageCode,
|
||||
const void *message, int32 messageSize, void *reply,
|
||||
int32 replySize);
|
||||
|
||||
ssize_t debug_read_memory_partial(debug_context *context, const void *address,
|
||||
void *buffer, size_t size);
|
||||
ssize_t debug_read_memory(debug_context *context, const void *address,
|
||||
void *buffer, size_t size);
|
||||
ssize_t debug_read_string(debug_context *context, const void *_address,
|
||||
char *buffer, size_t size);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _DEBUG_SUPPORT_H
|
||||
@@ -102,6 +102,7 @@ SEARCH on [ FGristFiles KMessage.cpp ]
|
||||
= [ FDirName $(OBOS_TOP) src kernel core messaging ] ;
|
||||
|
||||
SubInclude OBOS_TOP src kits app ;
|
||||
SubInclude OBOS_TOP src kits debug ;
|
||||
SubInclude OBOS_TOP src kits interface ;
|
||||
SubInclude OBOS_TOP src kits mail ;
|
||||
SubInclude OBOS_TOP src kits media ;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
SubDir OBOS_TOP src kits debug ;
|
||||
|
||||
UsePrivateHeaders debug ;
|
||||
UsePrivateHeaders shared ;
|
||||
|
||||
SharedLibrary debug :
|
||||
debug_support.cpp
|
||||
;
|
||||
|
||||
LinkSharedOSLibs libdebug.so :
|
||||
libroot.so
|
||||
;
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <debug_support.h>
|
||||
|
||||
// init_debug_context
|
||||
status_t
|
||||
init_debug_context(debug_context *context, port_id nubPort)
|
||||
{
|
||||
if (!context || nubPort < 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
context->nub_port = nubPort;
|
||||
|
||||
// create the reply port
|
||||
context->reply_port = create_port(1, "debug reply port");
|
||||
if (context->reply_port < 0)
|
||||
return context->reply_port;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// destroy_debug_context
|
||||
void
|
||||
destroy_debug_context(debug_context *context)
|
||||
{
|
||||
if (context) {
|
||||
if (context->reply_port >= 0)
|
||||
delete_port(context->reply_port);
|
||||
}
|
||||
}
|
||||
|
||||
// send_debug_message
|
||||
status_t
|
||||
send_debug_message(debug_context *context, int32 messageCode,
|
||||
const void *message, int32 messageSize, void *reply, int32 replySize)
|
||||
{
|
||||
if (!context)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// send message
|
||||
while (true) {
|
||||
status_t result = write_port(context->nub_port, messageCode, message,
|
||||
messageSize);
|
||||
if (result == B_OK)
|
||||
break;
|
||||
if (result != B_INTERRUPTED)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!reply)
|
||||
return B_OK;
|
||||
|
||||
// read reply
|
||||
while (true) {
|
||||
int32 code;
|
||||
ssize_t bytesRead = read_port(context->reply_port, &code, reply,
|
||||
replySize);
|
||||
if (bytesRead > 0)
|
||||
return B_OK;
|
||||
if (bytesRead != B_INTERRUPTED)
|
||||
return bytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
// debug_read_memory_partial
|
||||
ssize_t
|
||||
debug_read_memory_partial(debug_context *context, const void *address,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
if (!context)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
if (size > B_MAX_READ_WRITE_MEMORY_SIZE)
|
||||
size = B_MAX_READ_WRITE_MEMORY_SIZE;
|
||||
|
||||
// prepare the message
|
||||
debug_nub_read_memory message;
|
||||
message.reply_port = context->reply_port;
|
||||
message.address = (void*)address;
|
||||
message.size = size;
|
||||
|
||||
// send the message
|
||||
debug_nub_read_memory_reply reply;
|
||||
status_t error = send_debug_message(context, B_DEBUG_MESSAGE_READ_MEMORY,
|
||||
&message, sizeof(message), &reply, sizeof(reply));
|
||||
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
if (reply.error != B_OK)
|
||||
return reply.error;
|
||||
|
||||
// copy the read data
|
||||
memcpy(buffer, reply.data, reply.size);
|
||||
return reply.size;
|
||||
}
|
||||
|
||||
// debug_read_memory
|
||||
ssize_t
|
||||
debug_read_memory(debug_context *context, const void *_address, void *_buffer,
|
||||
size_t size)
|
||||
{
|
||||
const char *address = (const char *)_address;
|
||||
char *buffer = (char*)_buffer;
|
||||
|
||||
// check parameters
|
||||
if (!context || !address || !buffer)
|
||||
return B_BAD_VALUE;
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
// read as long as we can read data
|
||||
ssize_t sumRead = 0;
|
||||
while (size > 0) {
|
||||
ssize_t bytesRead = debug_read_memory_partial(context, address, buffer,
|
||||
size);
|
||||
if (bytesRead < 0) {
|
||||
if (sumRead > 0)
|
||||
return sumRead;
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
address += bytesRead;
|
||||
buffer += bytesRead;
|
||||
sumRead += bytesRead;
|
||||
size -= bytesRead;
|
||||
}
|
||||
|
||||
return sumRead;
|
||||
}
|
||||
|
||||
// debug_read_string
|
||||
ssize_t
|
||||
debug_read_string(debug_context *context, const void *_address, char *buffer,
|
||||
size_t size)
|
||||
{
|
||||
const char *address = (const char *)_address;
|
||||
|
||||
// check parameters
|
||||
if (!context || !address || !buffer || size == 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// read as long as we can read data
|
||||
ssize_t sumRead = 0;
|
||||
while (size > 0) {
|
||||
ssize_t bytesRead = debug_read_memory_partial(context, address, buffer,
|
||||
size);
|
||||
if (bytesRead < 0) {
|
||||
// always null-terminate what we have (even, if it is an empty
|
||||
// string) and be done
|
||||
*buffer = '\0';
|
||||
return (sumRead > 0 ? sumRead : bytesRead);
|
||||
}
|
||||
|
||||
int chunkSize = strnlen(buffer, bytesRead);
|
||||
if (chunkSize < bytesRead) {
|
||||
// we found a terminating null
|
||||
sumRead += chunkSize;
|
||||
return sumRead;
|
||||
}
|
||||
|
||||
address += bytesRead;
|
||||
buffer += bytesRead;
|
||||
sumRead += bytesRead;
|
||||
size -= bytesRead;
|
||||
}
|
||||
|
||||
// We filled the complete buffer without encountering a terminating null
|
||||
// replace the last char. But nevertheless return the full size to indicate
|
||||
// that the buffer was too small.
|
||||
buffer[-1] = '\0';
|
||||
|
||||
return sumRead;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user