diff --git a/src/kits/debug/SymbolLookup.cpp b/src/kits/debug/SymbolLookup.cpp index 16ad71efbd..4256a898ba 100644 --- a/src/kits/debug/SymbolLookup.cpp +++ b/src/kits/debug/SymbolLookup.cpp @@ -5,15 +5,31 @@ #include "SymbolLookup.h" +#include +#include +#include +#include +#include +#include + #include -#include #include +#undef TRACE +//#define TRACE_DEBUG_SYMBOL_LOOKUP +#ifdef TRACE_DEBUG_SYMBOL_LOOKUP +# define TRACE(x) printf x +#else +# define TRACE(x) ; +#endif + + using std::nothrow; using namespace BPrivate; + // PrepareAddress const void * Area::PrepareAddress(const void *address) @@ -89,7 +105,8 @@ RemoteMemoryAccessor::Init() // PrepareAddress const void * -RemoteMemoryAccessor::PrepareAddress(const void *remoteAddress, int32 size) +RemoteMemoryAccessor::PrepareAddress(const void *remoteAddress, + int32 size) const { TRACE(("RemoteMemoryAccessor::PrepareAddress(%p, %ld)\n", remoteAddress, size)); @@ -102,13 +119,46 @@ RemoteMemoryAccessor::PrepareAddress(const void *remoteAddress, int32 size) return _FindArea(remoteAddress, size).PrepareAddress(remoteAddress); } + +const void * +RemoteMemoryAccessor::PrepareAddressNoThrow(const void *remoteAddress, + int32 size) const +{ + if (remoteAddress == NULL) + return NULL; + + Area* area = _FindAreaNoThrow(remoteAddress, size); + if (area == NULL) + return NULL; + + return area->PrepareAddress(remoteAddress); +} + + +// AreaForLocalAddress +Area* +RemoteMemoryAccessor::AreaForLocalAddress(const void* address) const +{ + if (address == NULL) + return NULL; + + for (AreaList::ConstIterator it = fAreas.GetIterator(); it.HasNext();) { + Area* area = it.Next(); + if (area->ContainsLocalAddress(address)) + return area; + } + + return NULL; +} + + // _FindArea Area & -RemoteMemoryAccessor::_FindArea(const void *address, int32 size) +RemoteMemoryAccessor::_FindArea(const void *address, int32 size) const { TRACE(("RemoteMemoryAccessor::_FindArea(%p, %ld)\n", address, size)); - for (AreaList::Iterator it = fAreas.GetIterator(); it.HasNext();) { + for (AreaList::ConstIterator it = fAreas.GetIterator(); it.HasNext();) { Area *area = it.Next(); if (area->ContainsAddress(address, size)) return *area; @@ -120,20 +170,254 @@ RemoteMemoryAccessor::_FindArea(const void *address, int32 size) } +// _FindAreaNoThrow +Area* +RemoteMemoryAccessor::_FindAreaNoThrow(const void *address, int32 size) const +{ + for (AreaList::ConstIterator it = fAreas.GetIterator(); it.HasNext();) { + Area *area = it.Next(); + if (area->ContainsAddress(address, size)) + return area; + } + + return NULL; +} + + // #pragma mark - + +ImageFile::ImageFile(const image_info& info) + : + fInfo(info), + fFD(-1), + fFileSize(0), + fMappedFile((uint8*)MAP_FAILED), + fLoadDelta(0), + fSymbolTable(NULL), + fStringTable(NULL), + fSymbolCount(0) +{ +} + + +ImageFile::~ImageFile() +{ + if (fMappedFile != MAP_FAILED) + munmap(fMappedFile, fFileSize); + + if (fFD >= 0) + close(fFD); +} + + +status_t +ImageFile::Load() +{ + // open and stat() the file + fFD = open(fInfo.name, O_RDONLY); + if (fFD < 0) + return errno; + + struct stat st; + if (fstat(fFD, &st) < 0) + return errno; + + fFileSize = st.st_size; + if (fFileSize < sizeof(Elf32_Ehdr)) + return B_NOT_AN_EXECUTABLE; + + // map it + fMappedFile = (uint8*)mmap(NULL, fFileSize, PROT_READ, MAP_SHARED, fFD, 0); + if (fMappedFile == MAP_FAILED) + return errno; + + // examine the elf header + Elf32_Ehdr* elfHeader = (Elf32_Ehdr*)fMappedFile; + if (memcmp(elfHeader->e_ident, ELF_MAGIC, 4) != 0) + return B_NOT_AN_EXECUTABLE; + + if (elfHeader->e_ident[4] != ELFCLASS32) + return B_NOT_AN_EXECUTABLE; + + // verify the location of the program headers + int32 programHeaderCount = elfHeader->e_phnum; + if (elfHeader->e_phoff < sizeof(Elf32_Ehdr) + || elfHeader->e_phentsize < sizeof(Elf32_Phdr) + || elfHeader->e_phoff + programHeaderCount * elfHeader->e_phentsize + > fFileSize) { + return B_NOT_AN_EXECUTABLE; + } + + Elf32_Phdr* programHeaders + = (Elf32_Phdr*)(fMappedFile + elfHeader->e_phoff); + + // verify the location of the section headers + int32 sectionCount = elfHeader->e_shnum; + if (elfHeader->e_shoff < sizeof(Elf32_Ehdr) + || elfHeader->e_shentsize < sizeof(Elf32_Shdr) + || elfHeader->e_shoff + sectionCount * elfHeader->e_shentsize + > fFileSize) { + return B_NOT_AN_EXECUTABLE; + } + + Elf32_Shdr* sectionHeaders + = (Elf32_Shdr*)(fMappedFile + elfHeader->e_shoff); + + // find the first segment -- we need its relative offset + for (int32 i = 0; i < programHeaderCount; i++) { + Elf32_Phdr* header = (Elf32_Phdr*) + ((uint8*)programHeaders + i * elfHeader->e_phentsize); + if (header->p_type == PT_LOAD) { + fLoadDelta = (addr_t)fInfo.text - header->p_vaddr; + break; + } + } + + // find the symbol table + for (int32 i = 0; i < elfHeader->e_shnum; i++) { + Elf32_Shdr* sectionHeader = (Elf32_Shdr*) + ((uint8*)sectionHeaders + i * elfHeader->e_shentsize); + + if (sectionHeader->sh_type == SHT_SYMTAB) { + Elf32_Shdr& stringHeader = *(Elf32_Shdr*) + ((uint8*)sectionHeaders + + sectionHeader->sh_link * elfHeader->e_shentsize); + + if (stringHeader.sh_type != SHT_STRTAB) + return B_BAD_DATA; + + if (sectionHeader->sh_offset + sectionHeader->sh_size > fFileSize + || stringHeader.sh_offset + stringHeader.sh_size > fFileSize) { + return B_BAD_DATA; + } + + fSymbolTable + = (const Elf32_Sym*)(fMappedFile + sectionHeader->sh_offset); + fStringTable = (const char*)(fMappedFile + stringHeader.sh_offset); + fSymbolCount = sectionHeader->sh_size / sizeof(Elf32_Sym); + + return B_OK; + } + } + + return B_BAD_DATA; +} + + +const Elf32_Sym* +ImageFile::LookupSymbol(addr_t address, addr_t* _baseAddress, + const char** _symbolName, size_t *_symbolNameLen, bool *_exactMatch) const +{ + const Elf32_Sym* symbolFound = NULL; + const char* symbolName = NULL; + bool exactMatch = false; + addr_t deltaFound = ~(addr_t)0; + + for (int32 i = 0; i < fSymbolCount; i++) { + const Elf32_Sym* symbol = &fSymbolTable[i]; + + if (symbol->st_value == 0 + || symbol->st_size >= (size_t)fInfo.text_size + fInfo.data_size) { + continue; + } + + addr_t symbolAddress = symbol->st_value + fLoadDelta; + if (symbolAddress > address) + continue; + + addr_t symbolDelta = address - symbolAddress; + if (symbolDelta >= 0 && symbolDelta < symbol->st_size) + exactMatch = true; + + if (exactMatch || symbolDelta < deltaFound) { + deltaFound = symbolDelta; + symbolFound = symbol; + symbolName = fStringTable + symbol->st_name; + + if (exactMatch) + break; + } + } + + if (symbolFound != NULL) { + if (_baseAddress != NULL) + *_baseAddress = symbolFound->st_value + fLoadDelta; + if (_symbolName != NULL) + *_symbolName = symbolName; + if (_exactMatch != NULL) + *_exactMatch = exactMatch; + if (_symbolNameLen != NULL) + *_symbolNameLen = _SymbolNameLen(symbolName); + } + + return symbolFound; +} + + +status_t +ImageFile::NextSymbol(int32& iterator, const char** _symbolName, + size_t* _symbolNameLen, addr_t* _symbolAddress, size_t* _symbolSize, + int32* _symbolType) const +{ + while (true) { + if (++iterator >= fSymbolCount) + return B_ENTRY_NOT_FOUND; + + const Elf32_Sym* symbol = &fSymbolTable[iterator]; + + if ((ELF32_ST_TYPE(symbol->st_info) != STT_FUNC + && ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT) + || symbol->st_value == 0) { + continue; + } + + *_symbolName = fStringTable + symbol->st_name; + *_symbolNameLen = _SymbolNameLen(*_symbolName); + *_symbolAddress = symbol->st_value + fLoadDelta; + *_symbolSize = symbol->st_size; + *_symbolType = ELF32_ST_TYPE(symbol->st_info) == STT_FUNC + ? B_SYMBOL_TYPE_TEXT : B_SYMBOL_TYPE_DATA; + + return B_OK; + } +} + + +size_t +ImageFile::_SymbolNameLen(const char* symbolName) const +{ + if (symbolName == NULL || (addr_t)symbolName < (addr_t)fStringTable + || (addr_t)symbolName >= (addr_t)fMappedFile + fFileSize) { + return 0; + } + + return strnlen(symbolName, + (addr_t)fMappedFile + fFileSize - (addr_t)symbolName); +} + + +// #pragma mark - + + // constructor SymbolLookup::SymbolLookup(team_id team) - : RemoteMemoryAccessor(team), - fDebugArea(NULL) + : + RemoteMemoryAccessor(team), + fDebugArea(NULL), + fImageFiles() { } + // destructor SymbolLookup::~SymbolLookup() { + while (ImageFile* imageFile = fImageFiles.RemoveHead()) + delete imageFile; } + // Init status_t SymbolLookup::Init() @@ -170,29 +454,47 @@ SymbolLookup::Init() TRACE(("SymbolLookup::Init(): translated debug area is at: %p, " "loaded_images: %p\n", fDebugArea, fDebugArea->loaded_images)); - } catch (Exception exception) { return exception.Error(); } + // create a list of the team's images + image_info imageInfo; + cookie = 0; + while (get_next_image_info(fTeam, &cookie, &imageInfo) == B_OK) { + ImageFile* imageFile = new(std::nothrow) ImageFile(imageInfo); + if (imageFile == NULL) + break; + + if (imageFile->Load() != B_OK) + delete imageFile; + + fImageFiles.Add(imageFile); + } + return B_OK; } + // LookupSymbolAddress status_t SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress, - const char **_symbolName, const char **_imageName, bool *_exactMatch) + const char **_symbolName, size_t *_symbolNameLen, const char **_imageName, + bool *_exactMatch) const { - // Note, that this function doesn't find all symbols that we would like - // to find. E.g. static functions do not appear in the symbol table - // as function symbols, but as sections without name and size. The .symtab - // section together with the .strtab section, which apparently differ from - // the tables referred to by the .dynamic section, also contain proper names - // and sizes for those symbols. Therefore, to get completely satisfying - // results, we would need to read those tables from the shared object. - TRACE(("SymbolLookup::LookupSymbolAddress(%p)\n", (void*)address)); + // Try the loaded image file first -- it also contains static symbols. + ImageFile* imageFile = _FindImageFileAtAddress(address); + if (imageFile != NULL) { + if (_imageName != NULL) + *_imageName = imageFile->Info().name; + const Elf32_Sym* symbol = imageFile->LookupSymbol(address, _baseAddress, + _symbolName, _symbolNameLen, _exactMatch); + if (symbol != NULL) + return B_OK; + } + // get the image for the address const image_t *image = _FindImageAtAddress(address); if (!image) @@ -206,52 +508,49 @@ SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress, const struct Elf32_Sym *symbolFound = NULL; addr_t deltaFound = INT_MAX; bool exactMatch = false; - const char *symbolName = NULL; // remote + const char *symbolName = NULL; - int32 hashTabSize = Read(image->symhash[0]); - const uint32 *hashBuckets = image->symhash + 2; // remote - const uint32 *hashChains = image->symhash + 2 + hashTabSize; // remote + int32 symbolCount = Read(image->symhash[1]); 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])) { + for (int32 i = 0; i < symbolCount; i++) { + const struct Elf32_Sym *symbol = &Read(image->syms[i]); - const struct Elf32_Sym *symbol = &Read(image->syms[j]); + // The symbol table contains not only symbols referring to functions + // and data symbols within the shared object, but also referenced + // symbols of other shared objects, as well as section and file + // references. We ignore everything but function and data symbols + // that have an st_value != 0 (0 seems to be an indication for a + // symbol defined elsewhere -- couldn't verify that in the specs + // though). + if ((ELF32_ST_TYPE(symbol->st_info) != STT_FUNC + && ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT) + || symbol->st_value == 0 + || symbol->st_value + symbol->st_size + textRegion->delta + > textRegion->vmstart + textRegion->size) { + continue; + } - // The symbol table contains not only symbols referring to functions - // and data symbols within the shared object, but also referenced - // symbols of other shared objects, as well as section and file - // references. We ignore everything but function and data symbols - // that have an st_value != 0 (0 seems to be an indication for a - // symbol defined elsewhere -- couldn't verify that in the specs - // though). - if ((ELF32_ST_TYPE(symbol->st_info) != STT_FUNC - && ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT) - || symbol->st_value == 0 - || symbol->st_value + symbol->st_size + textRegion->delta - > textRegion->vmstart + textRegion->size) { + // 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) { + symbolName = (const char*)PrepareAddressNoThrow(SYMNAME(image, + symbol), 1); + if (symbolName == NULL) continue; - } - // skip symbols starting after the given address - addr_t symbolAddress = symbol->st_value + textRegion->delta; + deltaFound = symbolDelta; + symbolFound = symbol; - 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; - } + if (symbolDelta >= 0 && symbolDelta < symbol->st_size) { + // exact match + exactMatch = true; + break; } } } @@ -275,26 +574,37 @@ SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress, if (_exactMatch) *_exactMatch = exactMatch; + if (_symbolNameLen != NULL) + *_symbolNameLen = _SymbolNameLen(symbolName); + return B_OK; } // InitSymbolIterator status_t -SymbolLookup::InitSymbolIterator(image_id imageID, SymbolIterator& iterator) +SymbolLookup::InitSymbolIterator(image_id imageID, + SymbolIterator& iterator) const { TRACE(("SymbolLookup::InitSymbolIterator(): image ID: %ld\n", imageID)); - // find the image - const image_t* image = _FindImageByID(imageID); - if (image == NULL) { - TRACE(("SymbolLookup::InitSymbolIterator() done: image not found\n")); - return B_ENTRY_NOT_FOUND; + // find the image file + iterator.imageFile = _FindImageFileByID(imageID); + + // If that didn't work, find the image. + if (iterator.imageFile == NULL) { + const image_t* image = _FindImageByID(imageID); + if (image == NULL) { + TRACE(("SymbolLookup::InitSymbolIterator() done: image not " + "found\n")); + return B_ENTRY_NOT_FOUND; + } + + iterator.image = image; + iterator.symbolCount = Read(image->symhash[1]); + iterator.textDelta = image->regions->delta; } - iterator.image = image; - iterator.symbolCount = Read(image->symhash[1]); - iterator.textDelta = image->regions->delta; iterator.currentIndex = -1; return B_OK; @@ -304,22 +614,28 @@ SymbolLookup::InitSymbolIterator(image_id imageID, SymbolIterator& iterator) // InitSymbolIterator status_t SymbolLookup::InitSymbolIteratorByAddress(addr_t address, - SymbolIterator& iterator) + SymbolIterator& iterator) const { TRACE(("SymbolLookup::InitSymbolIteratorByAddress(): base address: %#lx\n", address)); - // find the image - const image_t *image = _FindImageAtAddress(address); - if (image == NULL) { - TRACE(("SymbolLookup::InitSymbolIteratorByAddress() done: image not " - "found\n")); - return B_ENTRY_NOT_FOUND; + // find the image file + iterator.imageFile = _FindImageFileAtAddress(address); + + // If that didn't work, find the image. + if (iterator.imageFile == NULL) { + const image_t *image = _FindImageAtAddress(address); + if (image == NULL) { + TRACE(("SymbolLookup::InitSymbolIteratorByAddress() done: image " + "not found\n")); + return B_ENTRY_NOT_FOUND; + } + + iterator.image = image; + iterator.symbolCount = Read(image->symhash[1]); + iterator.textDelta = image->regions->delta; } - iterator.image = image; - iterator.symbolCount = Read(image->symhash[1]); - iterator.textDelta = image->regions->delta; iterator.currentIndex = -1; return B_OK; @@ -329,8 +645,17 @@ SymbolLookup::InitSymbolIteratorByAddress(addr_t address, // NextSymbol status_t SymbolLookup::NextSymbol(SymbolIterator& iterator, const char** _symbolName, - addr_t* _symbolAddress, size_t* _symbolSize, int32* _symbolType) + size_t* _symbolNameLen, addr_t* _symbolAddress, size_t* _symbolSize, + int32* _symbolType) const { + // If we have an image file, get the next symbol from it. + const ImageFile* imageFile = iterator.imageFile; + if (imageFile != NULL) { + return imageFile->NextSymbol(iterator.currentIndex, _symbolName, + _symbolNameLen, _symbolAddress, _symbolSize, _symbolType); + } + + // Otherwise we've to fall be to iterating through the image. const image_t* image = iterator.image; while (true) { @@ -345,7 +670,9 @@ SymbolLookup::NextSymbol(SymbolIterator& iterator, const char** _symbolName, continue; } - *_symbolName = SYMNAME(image, symbol); + *_symbolName = (const char*)PrepareAddressNoThrow(SYMNAME(image, + symbol), 1); + *_symbolNameLen = _SymbolNameLen(*_symbolName); *_symbolAddress = symbol->st_value + iterator.textDelta; *_symbolSize = symbol->st_size; *_symbolType = ELF32_ST_TYPE(symbol->st_info) == STT_FUNC @@ -358,7 +685,7 @@ SymbolLookup::NextSymbol(SymbolIterator& iterator, const char** _symbolName, // _FindImageAtAddress const image_t * -SymbolLookup::_FindImageAtAddress(addr_t address) +SymbolLookup::_FindImageAtAddress(addr_t address) const { TRACE(("SymbolLookup::_FindImageAtAddress(%p)\n", (void*)address)); @@ -378,7 +705,7 @@ SymbolLookup::_FindImageAtAddress(addr_t address) // _FindImageByID const image_t* -SymbolLookup::_FindImageByID(image_id id) +SymbolLookup::_FindImageByID(image_id id) const { // iterate through the images for (const image_t *image = &Read(*Read(fDebugArea->loaded_images->head)); @@ -390,3 +717,47 @@ SymbolLookup::_FindImageByID(image_id id) return NULL; } + + +// _FindImageFileAtAddress +ImageFile* +SymbolLookup::_FindImageFileAtAddress(addr_t address) const +{ + DoublyLinkedList::ConstIterator it = fImageFiles.GetIterator(); + while (ImageFile* imageFile = it.Next()) { + const image_info& info = imageFile->Info(); + if (address >= (addr_t)info.text + && address < (addr_t)info.text + info.text_size) { + return imageFile; + } + } + + return NULL; +} + + +// _FindImageFileByID +ImageFile* +SymbolLookup::_FindImageFileByID(image_id id) const +{ + DoublyLinkedList::ConstIterator it = fImageFiles.GetIterator(); + while (ImageFile* imageFile = it.Next()) { + if (imageFile->Info().id == id) + return imageFile; + } + + return NULL; +} + + +// _SymbolNameLen +size_t +SymbolLookup::_SymbolNameLen(const char* address) const +{ + Area* area = AreaForLocalAddress(address); + if (area == NULL) + return 0; + + return strnlen(address, (addr_t)area->LocalAddress() + area->Size() + - (addr_t)address); +} diff --git a/src/kits/debug/SymbolLookup.h b/src/kits/debug/SymbolLookup.h index 89606842fb..ebe1e07d54 100644 --- a/src/kits/debug/SymbolLookup.h +++ b/src/kits/debug/SymbolLookup.h @@ -14,16 +14,9 @@ #include -//#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; +struct Elf32_Sym; namespace BPrivate { @@ -76,6 +69,12 @@ public: && (addr_t)address + size <= (addr_t)fRemoteAddress + fSize); } + bool ContainsLocalAddress(const void* address) const + { + return (addr_t)address >= (addr_t)fLocalAddress + && (addr_t)address < (addr_t)fLocalAddress + fSize; + } + const void *PrepareAddress(const void *address); private: @@ -95,9 +94,12 @@ public: status_t Init(); - const void *PrepareAddress(const void *remoteAddress, int32 size); + const void *PrepareAddress(const void *remoteAddress, int32 size) const; + const void *PrepareAddressNoThrow(const void *remoteAddress, + int32 size) const; - template inline const Type &Read(const Type &remoteData) + template inline const Type &Read( + const Type &remoteData) const { const void *remoteAddress = &remoteData; const void *localAddress = PrepareAddress(remoteAddress, @@ -105,8 +107,11 @@ public: return *(const Type*)localAddress; } + Area* AreaForLocalAddress(const void* address) const; + private: - Area &_FindArea(const void *address, int32 size); + Area &_FindArea(const void *address, int32 size) const; + Area* _FindAreaNoThrow(const void *address, int32 size) const; typedef DoublyLinkedList AreaList; @@ -118,9 +123,42 @@ private: }; +// ImageFile +class ImageFile : public DoublyLinkedListLinkImpl { +public: + ImageFile(const image_info& info); + ~ImageFile(); + + const image_info& Info() const { return fInfo; } + + status_t Load(); + + const Elf32_Sym* LookupSymbol(addr_t address, addr_t* _baseAddress, + const char** _symbolName, size_t *_symbolNameLen, + bool *_exactMatch) const; + status_t NextSymbol(int32& iterator, const char** _symbolName, + size_t* _symbolNameLen, addr_t* _symbolAddress, size_t* _symbolSize, + int32* _symbolType) const; + +private: + size_t _SymbolNameLen(const char* symbolName) const; + +private: + image_info fInfo; + int fFD; + off_t fFileSize; + uint8* fMappedFile; + addr_t fLoadDelta; + const Elf32_Sym* fSymbolTable; + const char* fStringTable; + int32 fSymbolCount; +}; + + // SymbolIterator struct SymbolIterator { const image_t* image; + const ImageFile* imageFile; int32 symbolCount; size_t textDelta; int32 currentIndex; @@ -136,19 +174,27 @@ public: status_t Init(); status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress, - const char **_symbolName, const char **_imageName, bool *_exactMatch); + const char **_symbolName, size_t *_symbolNameLen, + const char **_imageName, bool *_exactMatch) const; - status_t InitSymbolIterator(image_id imageID, SymbolIterator& iterator); + status_t InitSymbolIterator(image_id imageID, + SymbolIterator& iterator) const; status_t InitSymbolIteratorByAddress(addr_t address, - SymbolIterator& iterator); + SymbolIterator& iterator) const; status_t NextSymbol(SymbolIterator& iterator, const char** _symbolName, - addr_t* _symbolAddress, size_t* _symbolSize, int32* _symbolType); + size_t* _symbolNameLen, addr_t* _symbolAddress, size_t* _symbolSize, + int32* _symbolType) const; private: - const image_t *_FindImageAtAddress(addr_t address); - const image_t *_FindImageByID(image_id id); + const image_t *_FindImageAtAddress(addr_t address) const; + const image_t *_FindImageByID(image_id id) const; + ImageFile* _FindImageFileAtAddress(addr_t address) const; + ImageFile* _FindImageFileByID(image_id id) const; + size_t _SymbolNameLen(const char* address) const; +private: const runtime_loader_debug_area *fDebugArea; + DoublyLinkedList fImageFiles; }; } // namespace BPrivate diff --git a/src/kits/debug/debug_support.cpp b/src/kits/debug/debug_support.cpp index 68ec20e936..f7a212ca24 100644 --- a/src/kits/debug/debug_support.cpp +++ b/src/kits/debug/debug_support.cpp @@ -321,10 +321,12 @@ debug_lookup_symbol_address(debug_symbol_lookup_context *lookupContext, // find the symbol addr_t _baseAddress; const char *_symbolName; + size_t _symbolNameLen; const char *_imageName; try { status_t error = lookup->LookupSymbolAddress((addr_t)address, - &_baseAddress, &_symbolName, &_imageName, exactMatch); + &_baseAddress, &_symbolName, &_symbolNameLen, &_imageName, + exactMatch); if (error != B_OK) return error; } catch (BPrivate::Exception exception) { @@ -336,15 +338,9 @@ debug_lookup_symbol_address(debug_symbol_lookup_context *lookupContext, *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; + if (_symbolName && _symbolNameLen > 0) { + strlcpy(symbolName, _symbolName, + min_c((size_t)symbolNameSize, _symbolNameLen + 1)); } else symbolName[0] = '\0'; } @@ -430,11 +426,13 @@ debug_next_image_symbol(debug_symbol_iterator* iterator, char* nameBuffer, debug_symbol_lookup_context* lookupContext = iterator->lookup_context; const char* symbolName; + size_t symbolNameLen; addr_t symbolLocation; try { - status_t error = lookupContext->lookup->NextSymbol( - *iterator, &symbolName, &symbolLocation, _symbolSize, _symbolType); + status_t error = lookupContext->lookup->NextSymbol(*iterator, + &symbolName, &symbolNameLen, &symbolLocation, _symbolSize, + _symbolType); if (error != B_OK) return error; } catch (BPrivate::Exception exception) { @@ -443,15 +441,9 @@ debug_next_image_symbol(debug_symbol_iterator* iterator, char* nameBuffer, *_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; + if (symbolName != NULL && symbolNameLen > 0) { + strlcpy(nameBuffer, symbolName, + min_c(nameBufferLength, symbolNameLen + 1)); } else nameBuffer[0] = '\0';