Added functionality for iterating through the symbols of a debugged
team's image to libdebug. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27526 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
0bec71008b
commit
68e6763b07
@ -55,6 +55,7 @@ status_t debug_get_stack_frame(debug_context *context,
|
||||
// symbol lookup support
|
||||
|
||||
typedef struct debug_symbol_lookup_context debug_symbol_lookup_context;
|
||||
typedef struct debug_symbol_iterator debug_symbol_iterator;
|
||||
|
||||
status_t debug_create_symbol_lookup_context(debug_context *debugContext,
|
||||
debug_symbol_lookup_context **lookupContext);
|
||||
@ -66,6 +67,14 @@ status_t debug_lookup_symbol_address(debug_symbol_lookup_context *lookupContext,
|
||||
int32 symbolNameSize, char *imageName, int32 imageNameSize,
|
||||
bool *exactMatch);
|
||||
|
||||
status_t debug_create_image_symbol_iterator(
|
||||
debug_symbol_lookup_context* lookupContext, image_id imageID,
|
||||
debug_symbol_iterator** _iterator);
|
||||
void debug_delete_image_symbol_iterator(debug_symbol_iterator* iterator);
|
||||
|
||||
status_t debug_next_image_symbol(debug_symbol_iterator* iterator,
|
||||
char* nameBuffer, size_t nameBufferLength, int32* _symbolType,
|
||||
void** _symbolLocation, size_t* _symbolSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
|
||||
* Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@ -278,6 +278,55 @@ SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// InitSymbolIterator
|
||||
status_t
|
||||
SymbolLookup::InitSymbolIterator(image_id imageID, SymbolIterator& iterator)
|
||||
{
|
||||
// find the image
|
||||
const image_t* image = _FindImageByID(imageID);
|
||||
if (image == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
iterator.image = image;
|
||||
iterator.symbolCount = Read(image->symhash[1]);
|
||||
iterator.textDelta = image->regions->delta;
|
||||
iterator.currentIndex = -1;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// NextSymbol
|
||||
status_t
|
||||
SymbolLookup::NextSymbol(SymbolIterator& iterator, const char** _symbolName,
|
||||
addr_t* _symbolAddress, size_t* _symbolSize, int32* _symbolType)
|
||||
{
|
||||
const image_t* image = iterator.image;
|
||||
|
||||
while (true) {
|
||||
if (++iterator.currentIndex >= iterator.symbolCount)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
const struct Elf32_Sym* symbol = &Read(image->syms[
|
||||
iterator.currentIndex]);
|
||||
if ((ELF32_ST_TYPE(symbol->st_info) != STT_FUNC
|
||||
&& ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT)
|
||||
|| symbol->st_value == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
*_symbolName = SYMNAME(image, symbol);
|
||||
*_symbolAddress = symbol->st_value + iterator.textDelta;
|
||||
*_symbolSize = symbol->st_size;
|
||||
*_symbolType = ELF32_ST_TYPE(symbol->st_info) == STT_FUNC
|
||||
? B_SYMBOL_TYPE_TEXT : B_SYMBOL_TYPE_DATA;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// _FindImageAtAddress
|
||||
const image_t *
|
||||
SymbolLookup::_FindImageAtAddress(addr_t address)
|
||||
@ -297,3 +346,18 @@ SymbolLookup::_FindImageAtAddress(addr_t address)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// _FindImageByID
|
||||
const image_t*
|
||||
SymbolLookup::_FindImageByID(image_id id)
|
||||
{
|
||||
// iterate through the images
|
||||
for (const image_t *image = &Read(*Read(fDebugArea->loaded_images->head));
|
||||
image;
|
||||
image = &Read(*image->next)) {
|
||||
if (image->id == id)
|
||||
return image;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
|
||||
* Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@ -8,10 +8,12 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <image.h>
|
||||
#include <OS.h>
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
|
||||
//#define TRACE_DEBUG_SYMBOL_LOOKUP
|
||||
#ifdef TRACE_DEBUG_SYMBOL_LOOKUP
|
||||
# define TRACE(x) printf x
|
||||
@ -19,9 +21,11 @@
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
struct image_t;
|
||||
struct runtime_loader_debug_area;
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
// Exception
|
||||
@ -43,6 +47,7 @@ private:
|
||||
status_t fError;
|
||||
};
|
||||
|
||||
|
||||
// Area
|
||||
class Area : public DoublyLinkedListLinkImpl<Area> {
|
||||
public:
|
||||
@ -81,6 +86,7 @@ private:
|
||||
int32 fSize;
|
||||
};
|
||||
|
||||
|
||||
// RemoteMemoryAccessor
|
||||
class RemoteMemoryAccessor {
|
||||
public:
|
||||
@ -111,6 +117,16 @@ private:
|
||||
AreaList fAreas;
|
||||
};
|
||||
|
||||
|
||||
// SymbolIterator
|
||||
struct SymbolIterator {
|
||||
const image_t* image;
|
||||
int32 symbolCount;
|
||||
size_t textDelta;
|
||||
int32 currentIndex;
|
||||
};
|
||||
|
||||
|
||||
// SymbolLookup
|
||||
class SymbolLookup : private RemoteMemoryAccessor {
|
||||
public:
|
||||
@ -122,8 +138,13 @@ public:
|
||||
status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
|
||||
const char **_symbolName, const char **_imageName, bool *_exactMatch);
|
||||
|
||||
status_t InitSymbolIterator(image_id imageID, SymbolIterator& iterator);
|
||||
status_t NextSymbol(SymbolIterator& iterator, const char** _symbolName,
|
||||
addr_t* _symbolAddress, size_t* _symbolSize, int32* _symbolType);
|
||||
|
||||
private:
|
||||
const image_t *_FindImageAtAddress(addr_t address);
|
||||
const image_t *_FindImageByID(image_id id);
|
||||
|
||||
const runtime_loader_debug_area *fDebugArea;
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
|
||||
* Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@ -13,13 +13,19 @@
|
||||
#include "arch_debug_support.h"
|
||||
#include "SymbolLookup.h"
|
||||
|
||||
|
||||
using std::nothrow;
|
||||
|
||||
|
||||
struct debug_symbol_lookup_context {
|
||||
debug_context context;
|
||||
SymbolLookup *lookup;
|
||||
};
|
||||
|
||||
struct debug_symbol_iterator : BPrivate::SymbolIterator {
|
||||
debug_symbol_lookup_context* lookup_context;
|
||||
};
|
||||
|
||||
|
||||
// init_debug_context
|
||||
status_t
|
||||
@ -317,8 +323,8 @@ debug_lookup_symbol_address(debug_symbol_lookup_context *lookupContext,
|
||||
const char *_symbolName;
|
||||
const char *_imageName;
|
||||
try {
|
||||
status_t error = lookup->LookupSymbolAddress((addr_t)address, &_baseAddress,
|
||||
&_symbolName, &_imageName, exactMatch);
|
||||
status_t error = lookup->LookupSymbolAddress((addr_t)address,
|
||||
&_baseAddress, &_symbolName, &_imageName, exactMatch);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
} catch (BPrivate::Exception exception) {
|
||||
@ -351,3 +357,83 @@ debug_lookup_symbol_address(debug_symbol_lookup_context *lookupContext,
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
debug_create_image_symbol_iterator(debug_symbol_lookup_context* lookupContext,
|
||||
image_id imageID, debug_symbol_iterator** _iterator)
|
||||
{
|
||||
if (!lookupContext || !lookupContext->lookup)
|
||||
return B_BAD_VALUE;
|
||||
SymbolLookup *lookup = lookupContext->lookup;
|
||||
|
||||
debug_symbol_iterator* iterator = new(std::nothrow) debug_symbol_iterator;
|
||||
if (iterator == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error;
|
||||
try {
|
||||
error = lookup->InitSymbolIterator(imageID, *iterator);
|
||||
} catch (BPrivate::Exception exception) {
|
||||
error = exception.Error();
|
||||
}
|
||||
|
||||
if (error != B_OK) {
|
||||
delete iterator;
|
||||
return error;
|
||||
}
|
||||
|
||||
iterator->lookup_context = lookupContext;
|
||||
|
||||
*_iterator = iterator;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
debug_delete_image_symbol_iterator(debug_symbol_iterator* iterator)
|
||||
{
|
||||
delete iterator;
|
||||
}
|
||||
|
||||
|
||||
// debug_next_image_symbol
|
||||
status_t
|
||||
debug_next_image_symbol(debug_symbol_iterator* iterator, char* nameBuffer,
|
||||
size_t nameBufferLength, int32* _symbolType, void** _symbolLocation,
|
||||
size_t* _symbolSize)
|
||||
{
|
||||
if (iterator == NULL || iterator->lookup_context == NULL
|
||||
|| iterator->lookup_context->lookup == NULL) {
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
debug_symbol_lookup_context* lookupContext = iterator->lookup_context;
|
||||
|
||||
const char* symbolName;
|
||||
addr_t symbolLocation;
|
||||
|
||||
try {
|
||||
status_t error = lookupContext->lookup->NextSymbol(
|
||||
*iterator, &symbolName, &symbolLocation, _symbolSize, _symbolType);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
} catch (BPrivate::Exception exception) {
|
||||
return exception.Error();
|
||||
}
|
||||
|
||||
*_symbolLocation = (void*)symbolLocation;
|
||||
|
||||
// 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 != NULL) {
|
||||
ssize_t sizeRead = debug_read_string(&lookupContext->context,
|
||||
symbolName, nameBuffer, nameBufferLength);
|
||||
if (sizeRead < 0)
|
||||
return sizeRead;
|
||||
} else
|
||||
nameBuffer[0] = '\0';
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user