From 68e6763b074c48a3e3302b2162031c71110abe51 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 15 Sep 2008 12:47:59 +0000 Subject: [PATCH] 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 --- headers/private/debug/debug_support.h | 9 +++ src/kits/debug/SymbolLookup.cpp | 66 ++++++++++++++++++- src/kits/debug/SymbolLookup.h | 23 ++++++- src/kits/debug/debug_support.cpp | 92 ++++++++++++++++++++++++++- 4 files changed, 185 insertions(+), 5 deletions(-) diff --git a/headers/private/debug/debug_support.h b/headers/private/debug/debug_support.h index 05c8e81b93..629c2b3201 100644 --- a/headers/private/debug/debug_support.h +++ b/headers/private/debug/debug_support.h @@ -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" diff --git a/src/kits/debug/SymbolLookup.cpp b/src/kits/debug/SymbolLookup.cpp index c3b0b7a468..816f1a19d9 100644 --- a/src/kits/debug/SymbolLookup.cpp +++ b/src/kits/debug/SymbolLookup.cpp @@ -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; +} diff --git a/src/kits/debug/SymbolLookup.h b/src/kits/debug/SymbolLookup.h index f64a35b9c2..7a7a394d47 100644 --- a/src/kits/debug/SymbolLookup.h +++ b/src/kits/debug/SymbolLookup.h @@ -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 +#include #include #include + //#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 { 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; }; diff --git a/src/kits/debug/debug_support.cpp b/src/kits/debug/debug_support.cpp index a2130e1c2b..3ee453cb82 100644 --- a/src/kits/debug/debug_support.cpp +++ b/src/kits/debug/debug_support.cpp @@ -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; +}