Added support for looking up symbols of other team to libdebug. The
debug_server uses this feature to print stack traces with symbols. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13698 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -13,12 +13,14 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct debug_context {
|
||||
team_id team;
|
||||
port_id nub_port;
|
||||
port_id reply_port;
|
||||
} debug_context;
|
||||
|
||||
|
||||
status_t init_debug_context(debug_context *context, port_id nubPort);
|
||||
status_t init_debug_context(debug_context *context, team_id team,
|
||||
port_id nubPort);
|
||||
void destroy_debug_context(debug_context *context);
|
||||
|
||||
status_t send_debug_message(debug_context *context, int32 messageCode,
|
||||
@@ -50,6 +52,21 @@ status_t debug_get_stack_frame(debug_context *context,
|
||||
void *stackFrameAddress, debug_stack_frame_info *stackFrameInfo);
|
||||
|
||||
|
||||
// symbol lookup support
|
||||
|
||||
typedef struct debug_symbol_lookup_context debug_symbol_lookup_context;
|
||||
|
||||
status_t debug_create_symbol_lookup_context(debug_context *debugContext,
|
||||
debug_symbol_lookup_context **lookupContext);
|
||||
void debug_delete_symbol_lookup_context(
|
||||
debug_symbol_lookup_context *lookupContext);
|
||||
|
||||
status_t debug_lookup_symbol_address(debug_symbol_lookup_context *lookupContext,
|
||||
const void *address, void **baseAddress, char *symbolName,
|
||||
int32 symbolNameSize, char *imageName, int32 imageNameSize,
|
||||
bool *exactMatch);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
SubDir OBOS_TOP src kits debug ;
|
||||
|
||||
UseArchHeaders $(OBOS_ARCH) ;
|
||||
UsePrivateHeaders debug ;
|
||||
UsePrivateHeaders kernel ;
|
||||
UsePrivateHeaders runtime_loader ;
|
||||
UsePrivateHeaders shared ;
|
||||
SubDirHdrs [ FDirName $(SUBDIR) arch ] ;
|
||||
|
||||
@@ -8,7 +11,9 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) arch $(OBOS_ARCH) ] ;
|
||||
|
||||
SharedLibrary debug :
|
||||
debug_support.cpp
|
||||
SymbolLookup.cpp
|
||||
|
||||
# architecture specific
|
||||
arch_debug_support.cpp
|
||||
;
|
||||
|
||||
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <runtime_loader.h>
|
||||
|
||||
#include "SymbolLookup.h"
|
||||
|
||||
using namespace BPrivate;
|
||||
|
||||
// PrepareAddress
|
||||
const void *
|
||||
Area::PrepareAddress(const void *address)
|
||||
{
|
||||
TRACE(("Area::PrepareAddress(%p): area: %ld\n", address, fRemoteID));
|
||||
|
||||
// clone the area, if not done already
|
||||
if (fLocalID < 0) {
|
||||
fLocalID = clone_area("cloned area", &fLocalAddress, B_ANY_ADDRESS,
|
||||
B_READ_AREA, fRemoteID);
|
||||
if (fLocalID < 0) {
|
||||
TRACE(("Area::PrepareAddress(): Failed to clone area %ld: %s\n",
|
||||
fRemoteID, strerror(fLocalID)));
|
||||
throw Exception(fLocalID);
|
||||
}
|
||||
}
|
||||
|
||||
// translate the address
|
||||
const void *result = (const void*)((addr_t)address - (addr_t)fRemoteAddress
|
||||
+ (addr_t)fLocalAddress);
|
||||
|
||||
TRACE(("Area::PrepareAddress(%p) done: %p\n", address, result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// constructor
|
||||
RemoteMemoryAccessor::RemoteMemoryAccessor(team_id team)
|
||||
: fTeam(team),
|
||||
fAreas()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
RemoteMemoryAccessor::~RemoteMemoryAccessor()
|
||||
{
|
||||
// delete the areas
|
||||
while (Area *area = fAreas.Head()) {
|
||||
fAreas.Remove(area);
|
||||
delete area;
|
||||
}
|
||||
}
|
||||
|
||||
// Init
|
||||
status_t
|
||||
RemoteMemoryAccessor::Init()
|
||||
{
|
||||
// get a list of the team's areas
|
||||
area_info areaInfo;
|
||||
int32 cookie = 0;
|
||||
status_t error;
|
||||
while ((error = get_next_area_info(fTeam, &cookie, &areaInfo)) == B_OK) {
|
||||
|
||||
TRACE(("area %ld: address: %p, size: %ld, name: %s\n", areaInfo.area,
|
||||
areaInfo.address, areaInfo.size, areaInfo.name));
|
||||
|
||||
Area *area = new(nothrow) Area(areaInfo.area, areaInfo.address,
|
||||
areaInfo.size);
|
||||
if (!area)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fAreas.Add(area);
|
||||
}
|
||||
|
||||
if (fAreas.IsEmpty())
|
||||
return error;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// PrepareAddress
|
||||
const void *
|
||||
RemoteMemoryAccessor::PrepareAddress(const void *remoteAddress, int32 size)
|
||||
{
|
||||
TRACE(("RemoteMemoryAccessor::PrepareAddress(%p, %ld)\n", remoteAddress,
|
||||
size));
|
||||
|
||||
if (!remoteAddress) {
|
||||
TRACE(("RemoteMemoryAccessor::PrepareAddress(): Got null address!\n"));
|
||||
throw Exception(B_BAD_VALUE);
|
||||
}
|
||||
|
||||
return _FindArea(remoteAddress, size).PrepareAddress(remoteAddress);
|
||||
}
|
||||
|
||||
// _FindArea
|
||||
Area &
|
||||
RemoteMemoryAccessor::_FindArea(const void *address, int32 size)
|
||||
{
|
||||
TRACE(("RemoteMemoryAccessor::_FindArea(%p, %ld)\n", address, size));
|
||||
|
||||
for (AreaList::Iterator it = fAreas.GetIterator(); it.HasNext();) {
|
||||
Area *area = it.Next();
|
||||
if (area->ContainsAddress(address, size))
|
||||
return *area;
|
||||
}
|
||||
|
||||
TRACE(("RemoteMemoryAccessor::_FindArea(): No area found for address %p\n",
|
||||
address));
|
||||
throw Exception(B_ENTRY_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// constructor
|
||||
SymbolLookup::SymbolLookup(team_id team)
|
||||
: RemoteMemoryAccessor(team),
|
||||
fDebugArea(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
SymbolLookup::~SymbolLookup()
|
||||
{
|
||||
}
|
||||
|
||||
// Init
|
||||
status_t
|
||||
SymbolLookup::Init()
|
||||
{
|
||||
TRACE(("SymbolLookup::Init()\n"));
|
||||
|
||||
status_t error = RemoteMemoryAccessor::Init();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
TRACE(("SymbolLookup::Init(): searching debug area...\n"));
|
||||
|
||||
// find the runtime loader debug area
|
||||
runtime_loader_debug_area *remoteDebugArea = NULL;
|
||||
int32 cookie = 0;
|
||||
area_info areaInfo;
|
||||
while (get_next_area_info(fTeam, &cookie, &areaInfo) == B_OK) {
|
||||
if (strcmp(areaInfo.name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0) {
|
||||
remoteDebugArea = (runtime_loader_debug_area*)areaInfo.address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!remoteDebugArea) {
|
||||
TRACE(("SymbolLookup::Init(): Couldn't find debug area!\n"));
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
TRACE(("SymbolLookup::Init(): found debug area, translating address...\n"));
|
||||
|
||||
// translate the address
|
||||
try {
|
||||
fDebugArea = &Read(*remoteDebugArea);
|
||||
|
||||
TRACE(("SymbolLookup::Init(): translated debug area is at: %p, "
|
||||
"loaded_images: %p\n", fDebugArea, fDebugArea->loaded_images));
|
||||
|
||||
} catch (Exception exception) {
|
||||
return exception.Error();
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// LookupSymbolAddress
|
||||
status_t
|
||||
SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
|
||||
const char **_symbolName, const char **_imageName, bool *_exactMatch)
|
||||
{
|
||||
TRACE(("SymbolLookup::LookupSymbolAddress(%p)\n", (void*)address));
|
||||
|
||||
// get the image for the address
|
||||
const image_t *image = _FindImageAtAddress(address);
|
||||
if (!image)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
TRACE(("SymbolLookup::LookupSymbolAddress(): found image: ID: %ld, text: "
|
||||
"address: %p, size: %ld\n",
|
||||
image->id, (void*)image->regions[0].vmstart, image->regions[0].size));
|
||||
|
||||
// search the image for the symbol
|
||||
const struct Elf32_Sym *symbolFound = NULL;
|
||||
addr_t deltaFound = INT_MAX;
|
||||
bool exactMatch = false;
|
||||
const char *symbolName = NULL; // remote
|
||||
|
||||
int32 hashTabSize = Read(image->symhash[0]);
|
||||
const uint32 *hashBuckets = image->symhash + 2; // remote
|
||||
const uint32 *hashChains = image->symhash + 2 + hashTabSize; // remote
|
||||
const elf_region_t *textRegion = image->regions; // local
|
||||
|
||||
for (int32 i = 0; i < hashTabSize; i++) {
|
||||
for (int32 j = Read(hashBuckets[i]);
|
||||
j != STN_UNDEF;
|
||||
j = Read(hashChains[j])) {
|
||||
const struct Elf32_Sym *symbol = &Read(image->syms[j]);
|
||||
|
||||
// skip invalid symbols
|
||||
if (symbol->st_value == 0
|
||||
|| symbol->st_value + symbol->st_size + textRegion->delta
|
||||
> textRegion->vmstart + textRegion->size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip symbols starting after the given address
|
||||
addr_t symbolAddress = symbol->st_value + textRegion->delta;
|
||||
|
||||
if (symbolAddress > address)
|
||||
continue;
|
||||
addr_t symbolDelta = address - symbolAddress;
|
||||
|
||||
if (!symbolFound || symbolDelta < deltaFound) {
|
||||
deltaFound = symbolDelta;
|
||||
symbolFound = symbol;
|
||||
symbolName = SYMNAME(image, symbol);
|
||||
|
||||
if (symbolDelta >= 0 && symbolDelta < symbol->st_size) {
|
||||
// exact match
|
||||
exactMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRACE(("SymbolLookup::LookupSymbolAddress(): done: symbol: %p, image name: "
|
||||
"%s, exact match: %d\n", symbolFound, image->name, exactMatch));
|
||||
|
||||
if (_baseAddress) {
|
||||
if (symbolFound)
|
||||
*_baseAddress = symbolFound->st_value + textRegion->delta;
|
||||
else
|
||||
*_baseAddress = textRegion->vmstart;
|
||||
}
|
||||
|
||||
if (_imageName)
|
||||
*_imageName = image->name;
|
||||
|
||||
if (_symbolName)
|
||||
*_symbolName = symbolName; // remote address
|
||||
|
||||
if (_exactMatch)
|
||||
*_exactMatch = exactMatch;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// _FindImageAtAddress
|
||||
const image_t *
|
||||
SymbolLookup::_FindImageAtAddress(addr_t address)
|
||||
{
|
||||
TRACE(("SymbolLookup::_FindImageAtAddress(%p)\n", (void*)address));
|
||||
|
||||
// iterate through the images
|
||||
for (const image_t *image = &Read(*Read(fDebugArea->loaded_images->head));
|
||||
image;
|
||||
image = &Read(*image->next)) {
|
||||
if (image->regions[0].vmstart <= address
|
||||
&& address < image->regions[0].vmstart + image->regions[0].size) {
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _SYMBOL_LOOKUP_H
|
||||
#define _SYMBOL_LOOKUP_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
//#define TRACE_DEBUG_SYMBOL_LOOKUP
|
||||
#ifdef TRACE_DEBUG_SYMBOL_LOOKUP
|
||||
# define TRACE(x) printf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
struct image_t;
|
||||
struct runtime_loader_debug_area;
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
// Exception
|
||||
class Exception {
|
||||
public:
|
||||
Exception(status_t error)
|
||||
: fError(error)
|
||||
{
|
||||
}
|
||||
|
||||
Exception(const Exception &other)
|
||||
: fError(other.fError)
|
||||
{
|
||||
}
|
||||
|
||||
status_t Error() const { return fError; }
|
||||
|
||||
private:
|
||||
status_t fError;
|
||||
};
|
||||
|
||||
// Area
|
||||
class Area : public DoublyLinkedListLinkImpl<Area> {
|
||||
public:
|
||||
Area(area_id id, const void *address, int32 size)
|
||||
: fRemoteID(id),
|
||||
fLocalID(-1),
|
||||
fRemoteAddress(address),
|
||||
fLocalAddress(NULL),
|
||||
fSize(size)
|
||||
{
|
||||
}
|
||||
|
||||
~Area()
|
||||
{
|
||||
if (fLocalID >= 0)
|
||||
delete_area(fLocalID);
|
||||
}
|
||||
|
||||
const void* RemoteAddress() const { return fRemoteAddress; }
|
||||
const void* LocalAddress() const { return fLocalAddress; }
|
||||
int32 Size() const { return fSize; }
|
||||
|
||||
bool ContainsAddress(const void *address, int32 size) const
|
||||
{
|
||||
return ((addr_t)fRemoteAddress <= (addr_t)address
|
||||
&& (addr_t)address + size <= (addr_t)fRemoteAddress + fSize);
|
||||
}
|
||||
|
||||
const void *PrepareAddress(const void *address);
|
||||
|
||||
private:
|
||||
area_id fRemoteID;
|
||||
area_id fLocalID;
|
||||
const void *fRemoteAddress;
|
||||
void *fLocalAddress;
|
||||
int32 fSize;
|
||||
};
|
||||
|
||||
// RemoteMemoryAccessor
|
||||
class RemoteMemoryAccessor {
|
||||
public:
|
||||
RemoteMemoryAccessor(team_id team);
|
||||
~RemoteMemoryAccessor();
|
||||
|
||||
status_t Init();
|
||||
|
||||
const void *PrepareAddress(const void *remoteAddress, int32 size);
|
||||
|
||||
template<typename Type> inline const Type &Read(const Type &remoteData)
|
||||
{
|
||||
const void *remoteAddress = &remoteData;
|
||||
const void *localAddress = PrepareAddress(remoteAddress,
|
||||
sizeof(remoteData));
|
||||
return *(const Type*)localAddress;
|
||||
}
|
||||
|
||||
private:
|
||||
Area &_FindArea(const void *address, int32 size);
|
||||
|
||||
typedef DoublyLinkedList<Area> AreaList;
|
||||
|
||||
protected:
|
||||
team_id fTeam;
|
||||
|
||||
private:
|
||||
AreaList fAreas;
|
||||
};
|
||||
|
||||
// SymbolLookup
|
||||
class SymbolLookup : private RemoteMemoryAccessor {
|
||||
public:
|
||||
SymbolLookup(team_id team);
|
||||
~SymbolLookup();
|
||||
|
||||
status_t Init();
|
||||
|
||||
status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
|
||||
const char **_symbolName, const char **_imageName, bool *_exactMatch);
|
||||
|
||||
private:
|
||||
const image_t *_FindImageAtAddress(addr_t address);
|
||||
|
||||
const runtime_loader_debug_area *fDebugArea;
|
||||
};
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
using BPrivate::SymbolLookup;
|
||||
|
||||
#endif // _SYMBOL_LOOKUP_H
|
||||
@@ -3,21 +3,30 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <debug_support.h>
|
||||
|
||||
#include "arch_debug_support.h"
|
||||
#include "SymbolLookup.h"
|
||||
|
||||
struct debug_symbol_lookup_context {
|
||||
debug_context context;
|
||||
SymbolLookup *lookup;
|
||||
};
|
||||
|
||||
|
||||
// init_debug_context
|
||||
status_t
|
||||
init_debug_context(debug_context *context, port_id nubPort)
|
||||
init_debug_context(debug_context *context, team_id team, port_id nubPort)
|
||||
{
|
||||
if (!context || nubPort < 0)
|
||||
if (!context || team < 0 || nubPort < 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
context->team = team;
|
||||
context->nub_port = nubPort;
|
||||
|
||||
// create the reply port
|
||||
@@ -183,7 +192,7 @@ debug_read_string(debug_context *context, const void *_address, char *buffer,
|
||||
return sumRead;
|
||||
}
|
||||
|
||||
|
||||
// debug_get_cpu_state
|
||||
status_t
|
||||
debug_get_cpu_state(debug_context *context, thread_id thread,
|
||||
debug_debugger_message *messageCode, debug_cpu_state *cpuState)
|
||||
@@ -214,6 +223,9 @@ debug_get_cpu_state(debug_context *context, thread_id thread,
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// debug_get_instruction_pointer
|
||||
status_t
|
||||
debug_get_instruction_pointer(debug_context *context, thread_id thread,
|
||||
void **ip, void **stackFrameAddress)
|
||||
@@ -225,7 +237,7 @@ debug_get_instruction_pointer(debug_context *context, thread_id thread,
|
||||
stackFrameAddress);
|
||||
}
|
||||
|
||||
|
||||
// debug_get_stack_frame
|
||||
status_t
|
||||
debug_get_stack_frame(debug_context *context, void *stackFrameAddress,
|
||||
debug_stack_frame_info *stackFrameInfo)
|
||||
@@ -236,3 +248,100 @@ debug_get_stack_frame(debug_context *context, void *stackFrameAddress,
|
||||
return arch_debug_get_stack_frame(context, stackFrameAddress,
|
||||
stackFrameInfo);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// debug_create_symbol_lookup_context
|
||||
status_t
|
||||
debug_create_symbol_lookup_context(debug_context *debugContext,
|
||||
debug_symbol_lookup_context **_lookupContext)
|
||||
{
|
||||
if (!debugContext || !_lookupContext)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// create the lookup context
|
||||
debug_symbol_lookup_context *lookupContext
|
||||
= new(nothrow) debug_symbol_lookup_context;
|
||||
lookupContext->context = *debugContext;
|
||||
ObjectDeleter<debug_symbol_lookup_context> contextDeleter(lookupContext);
|
||||
|
||||
// create and init symbol lookup
|
||||
SymbolLookup *lookup = new(nothrow) SymbolLookup(debugContext->team);
|
||||
if (!lookup)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = lookup->Init();
|
||||
if (error != B_OK) {
|
||||
delete lookup;
|
||||
return error;
|
||||
}
|
||||
|
||||
// everything went fine: return the result
|
||||
lookupContext->lookup = lookup;
|
||||
*_lookupContext = lookupContext;
|
||||
contextDeleter.Detach();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// debug_delete_symbol_lookup_context
|
||||
void
|
||||
debug_delete_symbol_lookup_context(debug_symbol_lookup_context *lookupContext)
|
||||
{
|
||||
if (lookupContext) {
|
||||
delete lookupContext->lookup;
|
||||
delete lookupContext;
|
||||
}
|
||||
}
|
||||
|
||||
// debug_lookup_symbol_address
|
||||
status_t
|
||||
debug_lookup_symbol_address(debug_symbol_lookup_context *lookupContext,
|
||||
const void *address, void **baseAddress, char *symbolName,
|
||||
int32 symbolNameSize, char *imageName, int32 imageNameSize,
|
||||
bool *exactMatch)
|
||||
{
|
||||
if (!lookupContext || !lookupContext->lookup)
|
||||
return B_BAD_VALUE;
|
||||
SymbolLookup *lookup = lookupContext->lookup;
|
||||
|
||||
// find the symbol
|
||||
addr_t _baseAddress;
|
||||
const char *_symbolName;
|
||||
const char *_imageName;
|
||||
try {
|
||||
status_t error = lookup->LookupSymbolAddress((addr_t)address, &_baseAddress,
|
||||
&_symbolName, &_imageName, exactMatch);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
} catch (BPrivate::Exception exception) {
|
||||
return exception.Error();
|
||||
}
|
||||
|
||||
// translate/copy the results
|
||||
if (baseAddress)
|
||||
*baseAddress = (void*)_baseAddress;
|
||||
|
||||
if (symbolName && symbolNameSize > 0) {
|
||||
// _symbolName is a remote address: We read the string from the
|
||||
// remote memory. The reason for not using the cloned area is that
|
||||
// we don't trust that the data therein is valid (i.e. null-terminated)
|
||||
// and thus strlcpy() could segfault when hitting the cloned area end.
|
||||
if (_symbolName) {
|
||||
ssize_t sizeRead = debug_read_string(&lookupContext->context,
|
||||
_symbolName, symbolName, symbolNameSize);
|
||||
if (sizeRead < 0)
|
||||
return sizeRead;
|
||||
} else
|
||||
symbolName[0] = '\0';
|
||||
}
|
||||
|
||||
if (imageName) {
|
||||
if (imageNameSize > B_OS_NAME_LENGTH)
|
||||
imageNameSize = B_OS_NAME_LENGTH;
|
||||
strlcpy(imageName, _imageName, imageNameSize);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -107,6 +107,10 @@ private:
|
||||
|
||||
bool _HandleMessage(DebugMessage *message);
|
||||
|
||||
void _LookupSymbolAddress(debug_symbol_lookup_context *lookupContext,
|
||||
const void *address, char *buffer, int32 bufferSize);
|
||||
void _PrintStackTrace(thread_id thread);
|
||||
|
||||
status_t _InitGUI();
|
||||
|
||||
static status_t _HandlerThreadEntry(void *data);
|
||||
@@ -333,7 +337,7 @@ TeamDebugHandler::Init(port_id nubPort)
|
||||
}
|
||||
|
||||
// init a debug context for the handler
|
||||
error = init_debug_context(&fDebugContext, nubPort);
|
||||
error = init_debug_context(&fDebugContext, fTeam, nubPort);
|
||||
if (error != B_OK) {
|
||||
printf("debug_server: TeamDebugHandler::Init(): Failed to init "
|
||||
"debug context for team %ld, port %ld: %s\n", fTeam, nubPort,
|
||||
@@ -536,53 +540,7 @@ TeamDebugHandler::_HandleMessage(DebugMessage *message)
|
||||
printf("debug_server: Thread %ld entered the debugger: %s\n", thread,
|
||||
buffer);
|
||||
|
||||
// TODO: Temporary solution. Remove when attaching gdb is working.
|
||||
#if 1
|
||||
// print a stacktrace
|
||||
void *ip = NULL;
|
||||
void *stackFrameAddress = NULL;
|
||||
status_t error = debug_get_instruction_pointer(&fDebugContext, thread, &ip,
|
||||
&stackFrameAddress);
|
||||
|
||||
if (error == B_OK) {
|
||||
printf("stack trace, current PC %p:\n", ip);
|
||||
|
||||
for (int32 i = 0; i < 50; i++) {
|
||||
debug_stack_frame_info stackFrameInfo;
|
||||
|
||||
error = debug_get_stack_frame(&fDebugContext, stackFrameAddress,
|
||||
&stackFrameInfo);
|
||||
if (error < B_OK || stackFrameInfo.parent_frame == NULL)
|
||||
break;
|
||||
|
||||
// find area containing the IP
|
||||
team_id team = fTeam;
|
||||
bool useAreaInfo = false;
|
||||
area_info info;
|
||||
int32 cookie = 0;
|
||||
while (get_next_area_info(team, &cookie, &info) == B_OK) {
|
||||
if ((addr_t)info.address
|
||||
<= (addr_t)stackFrameInfo.return_address
|
||||
&& (addr_t)info.address + info.size
|
||||
> (addr_t)stackFrameInfo.return_address) {
|
||||
useAreaInfo = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf(" (%p) %p", stackFrameInfo.frame,
|
||||
stackFrameInfo.return_address);
|
||||
if (useAreaInfo) {
|
||||
printf(" (%s + %#lx)\n", info.name,
|
||||
(addr_t)stackFrameInfo.return_address
|
||||
- (addr_t)info.address);
|
||||
} else
|
||||
putchar('\n');
|
||||
|
||||
stackFrameAddress = stackFrameInfo.parent_frame;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
_PrintStackTrace(thread);
|
||||
|
||||
bool kill = true;
|
||||
|
||||
@@ -615,6 +573,111 @@ TeamDebugHandler::_HandleMessage(DebugMessage *message)
|
||||
return kill;
|
||||
}
|
||||
|
||||
// _LookupSymbolAddress
|
||||
void
|
||||
TeamDebugHandler::_LookupSymbolAddress(
|
||||
debug_symbol_lookup_context *lookupContext, const void *address,
|
||||
char *buffer, int32 bufferSize)
|
||||
{
|
||||
// lookup the symbol
|
||||
void *baseAddress;
|
||||
char symbolName[1024];
|
||||
char imageName[B_OS_NAME_LENGTH];
|
||||
bool exactMatch;
|
||||
bool lookupSucceeded = false;
|
||||
if (lookupContext) {
|
||||
status_t error = debug_lookup_symbol_address(lookupContext, address,
|
||||
&baseAddress, symbolName, sizeof(symbolName), imageName,
|
||||
sizeof(imageName), &exactMatch);
|
||||
lookupSucceeded = (error == B_OK);
|
||||
}
|
||||
|
||||
if (lookupSucceeded) {
|
||||
// we were able to look something up
|
||||
if (strlen(symbolName) > 0) {
|
||||
// we even got a symbol
|
||||
snprintf(buffer, bufferSize, "%s + %#lx%s", symbolName,
|
||||
(addr_t)address - (addr_t)baseAddress,
|
||||
(exactMatch ? "" : " (closest symbol)"));
|
||||
|
||||
} else {
|
||||
// no symbol: image relative address
|
||||
snprintf(buffer, bufferSize, "(%s + %#lx)", symbolName,
|
||||
(addr_t)address - (addr_t)baseAddress);
|
||||
}
|
||||
|
||||
} else {
|
||||
// lookup failed: find area containing the IP
|
||||
bool useAreaInfo = false;
|
||||
area_info info;
|
||||
int32 cookie = 0;
|
||||
while (get_next_area_info(fTeam, &cookie, &info) == B_OK) {
|
||||
if ((addr_t)info.address <= (addr_t)address
|
||||
&& (addr_t)info.address + info.size > (addr_t)address) {
|
||||
useAreaInfo = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (useAreaInfo) {
|
||||
snprintf(buffer, bufferSize, "(%s + %#lx)", info.name,
|
||||
(addr_t)address - (addr_t)info.address);
|
||||
} else if (bufferSize > 0)
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// _PrintStackTrace
|
||||
void
|
||||
TeamDebugHandler::_PrintStackTrace(thread_id thread)
|
||||
{
|
||||
// print a stacktrace
|
||||
void *ip = NULL;
|
||||
void *stackFrameAddress = NULL;
|
||||
status_t error = debug_get_instruction_pointer(&fDebugContext, thread, &ip,
|
||||
&stackFrameAddress);
|
||||
|
||||
if (error == B_OK) {
|
||||
// create a symbol lookup context
|
||||
debug_symbol_lookup_context *lookupContext = NULL;
|
||||
error = debug_create_symbol_lookup_context(&fDebugContext,
|
||||
&lookupContext);
|
||||
if (error != B_OK) {
|
||||
printf("debug_server: Failed to create symbol lookup context: %s\n",
|
||||
strerror(error));
|
||||
}
|
||||
|
||||
// lookup the IP
|
||||
char symbolBuffer[2048];
|
||||
_LookupSymbolAddress(lookupContext, ip, symbolBuffer,
|
||||
sizeof(symbolBuffer) - 1);
|
||||
|
||||
printf("stack trace, current PC %p %s:\n", ip, symbolBuffer);
|
||||
|
||||
for (int32 i = 0; i < 50; i++) {
|
||||
debug_stack_frame_info stackFrameInfo;
|
||||
|
||||
error = debug_get_stack_frame(&fDebugContext, stackFrameAddress,
|
||||
&stackFrameInfo);
|
||||
if (error < B_OK || stackFrameInfo.parent_frame == NULL)
|
||||
break;
|
||||
|
||||
// lookup the return address
|
||||
_LookupSymbolAddress(lookupContext, stackFrameInfo.return_address,
|
||||
symbolBuffer, sizeof(symbolBuffer) - 1);
|
||||
|
||||
printf(" (%p) %p %s\n", stackFrameInfo.frame,
|
||||
stackFrameInfo.return_address, symbolBuffer);
|
||||
|
||||
stackFrameAddress = stackFrameInfo.parent_frame;
|
||||
}
|
||||
|
||||
// delete the symbol lookup context
|
||||
if (lookupContext)
|
||||
debug_delete_symbol_lookup_context(lookupContext);
|
||||
}
|
||||
}
|
||||
|
||||
// _InitGUI
|
||||
status_t
|
||||
TeamDebugHandler::_InitGUI()
|
||||
|
||||
Reference in New Issue
Block a user