* SymbolLookup: Implemented loading the symbol tables from the shared

object files. Thus static functions will be found, too.
* debug_lookup_symbol_address() and debug_next_image_symbol() no longer
  need to read the symbol name via the debugger API, since the
  respective SymbolLookup methods compute the length of the symbol name
  that can safely be accessed locally, now.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27628 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2008-09-18 22:17:11 +00:00
parent 6126236e8a
commit abb2df34ee
3 changed files with 524 additions and 115 deletions
+410 -39
View File
@@ -5,15 +5,31 @@
#include "SymbolLookup.h" #include "SymbolLookup.h"
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <new> #include <new>
#include <string.h>
#include <runtime_loader.h> #include <runtime_loader.h>
#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 std::nothrow;
using namespace BPrivate; using namespace BPrivate;
// PrepareAddress // PrepareAddress
const void * const void *
Area::PrepareAddress(const void *address) Area::PrepareAddress(const void *address)
@@ -89,7 +105,8 @@ RemoteMemoryAccessor::Init()
// PrepareAddress // PrepareAddress
const void * const void *
RemoteMemoryAccessor::PrepareAddress(const void *remoteAddress, int32 size) RemoteMemoryAccessor::PrepareAddress(const void *remoteAddress,
int32 size) const
{ {
TRACE(("RemoteMemoryAccessor::PrepareAddress(%p, %ld)\n", remoteAddress, TRACE(("RemoteMemoryAccessor::PrepareAddress(%p, %ld)\n", remoteAddress,
size)); size));
@@ -102,13 +119,46 @@ RemoteMemoryAccessor::PrepareAddress(const void *remoteAddress, int32 size)
return _FindArea(remoteAddress, size).PrepareAddress(remoteAddress); 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 // _FindArea
Area & Area &
RemoteMemoryAccessor::_FindArea(const void *address, int32 size) RemoteMemoryAccessor::_FindArea(const void *address, int32 size) const
{ {
TRACE(("RemoteMemoryAccessor::_FindArea(%p, %ld)\n", address, size)); 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(); Area *area = it.Next();
if (area->ContainsAddress(address, size)) if (area->ContainsAddress(address, size))
return *area; 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 - // #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 // constructor
SymbolLookup::SymbolLookup(team_id team) SymbolLookup::SymbolLookup(team_id team)
: RemoteMemoryAccessor(team), :
fDebugArea(NULL) RemoteMemoryAccessor(team),
fDebugArea(NULL),
fImageFiles()
{ {
} }
// destructor // destructor
SymbolLookup::~SymbolLookup() SymbolLookup::~SymbolLookup()
{ {
while (ImageFile* imageFile = fImageFiles.RemoveHead())
delete imageFile;
} }
// Init // Init
status_t status_t
SymbolLookup::Init() SymbolLookup::Init()
@@ -170,29 +454,47 @@ SymbolLookup::Init()
TRACE(("SymbolLookup::Init(): translated debug area is at: %p, " TRACE(("SymbolLookup::Init(): translated debug area is at: %p, "
"loaded_images: %p\n", fDebugArea, fDebugArea->loaded_images)); "loaded_images: %p\n", fDebugArea, fDebugArea->loaded_images));
} catch (Exception exception) { } catch (Exception exception) {
return exception.Error(); 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; return B_OK;
} }
// LookupSymbolAddress // LookupSymbolAddress
status_t status_t
SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress, 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)); 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 // get the image for the address
const image_t *image = _FindImageAtAddress(address); const image_t *image = _FindImageAtAddress(address);
if (!image) if (!image)
@@ -206,19 +508,13 @@ SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
const struct Elf32_Sym *symbolFound = NULL; const struct Elf32_Sym *symbolFound = NULL;
addr_t deltaFound = INT_MAX; addr_t deltaFound = INT_MAX;
bool exactMatch = false; bool exactMatch = false;
const char *symbolName = NULL; // remote const char *symbolName = NULL;
int32 hashTabSize = Read(image->symhash[0]); int32 symbolCount = Read(image->symhash[1]);
const uint32 *hashBuckets = image->symhash + 2; // remote
const uint32 *hashChains = image->symhash + 2 + hashTabSize; // remote
const elf_region_t *textRegion = image->regions; // local const elf_region_t *textRegion = image->regions; // local
for (int32 i = 0; i < hashTabSize; i++) { for (int32 i = 0; i < symbolCount; i++) {
for (int32 j = Read(hashBuckets[i]); const struct Elf32_Sym *symbol = &Read(image->syms[i]);
j != STN_UNDEF;
j = Read(hashChains[j])) {
const struct Elf32_Sym *symbol = &Read(image->syms[j]);
// The symbol table contains not only symbols referring to functions // The symbol table contains not only symbols referring to functions
// and data symbols within the shared object, but also referenced // and data symbols within the shared object, but also referenced
@@ -243,9 +539,13 @@ SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
addr_t symbolDelta = address - symbolAddress; addr_t symbolDelta = address - symbolAddress;
if (!symbolFound || symbolDelta < deltaFound) { if (!symbolFound || symbolDelta < deltaFound) {
symbolName = (const char*)PrepareAddressNoThrow(SYMNAME(image,
symbol), 1);
if (symbolName == NULL)
continue;
deltaFound = symbolDelta; deltaFound = symbolDelta;
symbolFound = symbol; symbolFound = symbol;
symbolName = SYMNAME(image, symbol);
if (symbolDelta >= 0 && symbolDelta < symbol->st_size) { if (symbolDelta >= 0 && symbolDelta < symbol->st_size) {
// exact match // exact match
@@ -254,7 +554,6 @@ SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
} }
} }
} }
}
TRACE(("SymbolLookup::LookupSymbolAddress(): done: symbol: %p, image name: " TRACE(("SymbolLookup::LookupSymbolAddress(): done: symbol: %p, image name: "
"%s, exact match: %d\n", symbolFound, image->name, exactMatch)); "%s, exact match: %d\n", symbolFound, image->name, exactMatch));
@@ -275,26 +574,37 @@ SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
if (_exactMatch) if (_exactMatch)
*_exactMatch = exactMatch; *_exactMatch = exactMatch;
if (_symbolNameLen != NULL)
*_symbolNameLen = _SymbolNameLen(symbolName);
return B_OK; return B_OK;
} }
// InitSymbolIterator // InitSymbolIterator
status_t 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)); TRACE(("SymbolLookup::InitSymbolIterator(): image ID: %ld\n", imageID));
// find the image // 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); const image_t* image = _FindImageByID(imageID);
if (image == NULL) { if (image == NULL) {
TRACE(("SymbolLookup::InitSymbolIterator() done: image not found\n")); TRACE(("SymbolLookup::InitSymbolIterator() done: image not "
"found\n"));
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
} }
iterator.image = image; iterator.image = image;
iterator.symbolCount = Read(image->symhash[1]); iterator.symbolCount = Read(image->symhash[1]);
iterator.textDelta = image->regions->delta; iterator.textDelta = image->regions->delta;
}
iterator.currentIndex = -1; iterator.currentIndex = -1;
return B_OK; return B_OK;
@@ -304,22 +614,28 @@ SymbolLookup::InitSymbolIterator(image_id imageID, SymbolIterator& iterator)
// InitSymbolIterator // InitSymbolIterator
status_t status_t
SymbolLookup::InitSymbolIteratorByAddress(addr_t address, SymbolLookup::InitSymbolIteratorByAddress(addr_t address,
SymbolIterator& iterator) SymbolIterator& iterator) const
{ {
TRACE(("SymbolLookup::InitSymbolIteratorByAddress(): base address: %#lx\n", TRACE(("SymbolLookup::InitSymbolIteratorByAddress(): base address: %#lx\n",
address)); address));
// find the image // 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); const image_t *image = _FindImageAtAddress(address);
if (image == NULL) { if (image == NULL) {
TRACE(("SymbolLookup::InitSymbolIteratorByAddress() done: image not " TRACE(("SymbolLookup::InitSymbolIteratorByAddress() done: image "
"found\n")); "not found\n"));
return B_ENTRY_NOT_FOUND; return B_ENTRY_NOT_FOUND;
} }
iterator.image = image; iterator.image = image;
iterator.symbolCount = Read(image->symhash[1]); iterator.symbolCount = Read(image->symhash[1]);
iterator.textDelta = image->regions->delta; iterator.textDelta = image->regions->delta;
}
iterator.currentIndex = -1; iterator.currentIndex = -1;
return B_OK; return B_OK;
@@ -329,8 +645,17 @@ SymbolLookup::InitSymbolIteratorByAddress(addr_t address,
// NextSymbol // NextSymbol
status_t status_t
SymbolLookup::NextSymbol(SymbolIterator& iterator, const char** _symbolName, 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; const image_t* image = iterator.image;
while (true) { while (true) {
@@ -345,7 +670,9 @@ SymbolLookup::NextSymbol(SymbolIterator& iterator, const char** _symbolName,
continue; continue;
} }
*_symbolName = SYMNAME(image, symbol); *_symbolName = (const char*)PrepareAddressNoThrow(SYMNAME(image,
symbol), 1);
*_symbolNameLen = _SymbolNameLen(*_symbolName);
*_symbolAddress = symbol->st_value + iterator.textDelta; *_symbolAddress = symbol->st_value + iterator.textDelta;
*_symbolSize = symbol->st_size; *_symbolSize = symbol->st_size;
*_symbolType = ELF32_ST_TYPE(symbol->st_info) == STT_FUNC *_symbolType = ELF32_ST_TYPE(symbol->st_info) == STT_FUNC
@@ -358,7 +685,7 @@ SymbolLookup::NextSymbol(SymbolIterator& iterator, const char** _symbolName,
// _FindImageAtAddress // _FindImageAtAddress
const image_t * const image_t *
SymbolLookup::_FindImageAtAddress(addr_t address) SymbolLookup::_FindImageAtAddress(addr_t address) const
{ {
TRACE(("SymbolLookup::_FindImageAtAddress(%p)\n", (void*)address)); TRACE(("SymbolLookup::_FindImageAtAddress(%p)\n", (void*)address));
@@ -378,7 +705,7 @@ SymbolLookup::_FindImageAtAddress(addr_t address)
// _FindImageByID // _FindImageByID
const image_t* const image_t*
SymbolLookup::_FindImageByID(image_id id) SymbolLookup::_FindImageByID(image_id id) const
{ {
// iterate through the images // iterate through the images
for (const image_t *image = &Read(*Read(fDebugArea->loaded_images->head)); for (const image_t *image = &Read(*Read(fDebugArea->loaded_images->head));
@@ -390,3 +717,47 @@ SymbolLookup::_FindImageByID(image_id id)
return NULL; return NULL;
} }
// _FindImageFileAtAddress
ImageFile*
SymbolLookup::_FindImageFileAtAddress(addr_t address) const
{
DoublyLinkedList<ImageFile>::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<ImageFile>::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);
}
+63 -17
View File
@@ -14,16 +14,9 @@
#include <util/DoublyLinkedList.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 image_t;
struct runtime_loader_debug_area; struct runtime_loader_debug_area;
struct Elf32_Sym;
namespace BPrivate { namespace BPrivate {
@@ -76,6 +69,12 @@ public:
&& (addr_t)address + size <= (addr_t)fRemoteAddress + fSize); && (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); const void *PrepareAddress(const void *address);
private: private:
@@ -95,9 +94,12 @@ public:
status_t Init(); 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<typename Type> inline const Type &Read(const Type &remoteData) template<typename Type> inline const Type &Read(
const Type &remoteData) const
{ {
const void *remoteAddress = &remoteData; const void *remoteAddress = &remoteData;
const void *localAddress = PrepareAddress(remoteAddress, const void *localAddress = PrepareAddress(remoteAddress,
@@ -105,8 +107,11 @@ public:
return *(const Type*)localAddress; return *(const Type*)localAddress;
} }
Area* AreaForLocalAddress(const void* address) const;
private: 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<Area> AreaList; typedef DoublyLinkedList<Area> AreaList;
@@ -118,9 +123,42 @@ private:
}; };
// ImageFile
class ImageFile : public DoublyLinkedListLinkImpl<ImageFile> {
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 // SymbolIterator
struct SymbolIterator { struct SymbolIterator {
const image_t* image; const image_t* image;
const ImageFile* imageFile;
int32 symbolCount; int32 symbolCount;
size_t textDelta; size_t textDelta;
int32 currentIndex; int32 currentIndex;
@@ -136,19 +174,27 @@ public:
status_t Init(); status_t Init();
status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress, 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, status_t InitSymbolIteratorByAddress(addr_t address,
SymbolIterator& iterator); SymbolIterator& iterator) const;
status_t NextSymbol(SymbolIterator& iterator, const char** _symbolName, 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: private:
const image_t *_FindImageAtAddress(addr_t address); const image_t *_FindImageAtAddress(addr_t address) const;
const image_t *_FindImageByID(image_id id); 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; const runtime_loader_debug_area *fDebugArea;
DoublyLinkedList<ImageFile> fImageFiles;
}; };
} // namespace BPrivate } // namespace BPrivate
+13 -21
View File
@@ -321,10 +321,12 @@ debug_lookup_symbol_address(debug_symbol_lookup_context *lookupContext,
// find the symbol // find the symbol
addr_t _baseAddress; addr_t _baseAddress;
const char *_symbolName; const char *_symbolName;
size_t _symbolNameLen;
const char *_imageName; const char *_imageName;
try { try {
status_t error = lookup->LookupSymbolAddress((addr_t)address, status_t error = lookup->LookupSymbolAddress((addr_t)address,
&_baseAddress, &_symbolName, &_imageName, exactMatch); &_baseAddress, &_symbolName, &_symbolNameLen, &_imageName,
exactMatch);
if (error != B_OK) if (error != B_OK)
return error; return error;
} catch (BPrivate::Exception exception) { } catch (BPrivate::Exception exception) {
@@ -336,15 +338,9 @@ debug_lookup_symbol_address(debug_symbol_lookup_context *lookupContext,
*baseAddress = (void*)_baseAddress; *baseAddress = (void*)_baseAddress;
if (symbolName && symbolNameSize > 0) { if (symbolName && symbolNameSize > 0) {
// _symbolName is a remote address: We read the string from the if (_symbolName && _symbolNameLen > 0) {
// remote memory. The reason for not using the cloned area is that strlcpy(symbolName, _symbolName,
// we don't trust that the data therein is valid (i.e. null-terminated) min_c((size_t)symbolNameSize, _symbolNameLen + 1));
// 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 } else
symbolName[0] = '\0'; 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; debug_symbol_lookup_context* lookupContext = iterator->lookup_context;
const char* symbolName; const char* symbolName;
size_t symbolNameLen;
addr_t symbolLocation; addr_t symbolLocation;
try { try {
status_t error = lookupContext->lookup->NextSymbol( status_t error = lookupContext->lookup->NextSymbol(*iterator,
*iterator, &symbolName, &symbolLocation, _symbolSize, _symbolType); &symbolName, &symbolNameLen, &symbolLocation, _symbolSize,
_symbolType);
if (error != B_OK) if (error != B_OK)
return error; return error;
} catch (BPrivate::Exception exception) { } catch (BPrivate::Exception exception) {
@@ -443,15 +441,9 @@ debug_next_image_symbol(debug_symbol_iterator* iterator, char* nameBuffer,
*_symbolLocation = (void*)symbolLocation; *_symbolLocation = (void*)symbolLocation;
// symbolName is a remote address: We read the string from the if (symbolName != NULL && symbolNameLen > 0) {
// remote memory. The reason for not using the cloned area is that strlcpy(nameBuffer, symbolName,
// we don't trust that the data therein is valid (i.e. null-terminated) min_c(nameBufferLength, symbolNameLen + 1));
// 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 } else
nameBuffer[0] = '\0'; nameBuffer[0] = '\0';