* Some refactoring: There are three ways to access the symbols of an image.

Formerly two were implemented in ImageFile (from file, via syscalls) and one
  in SymbolLookup (via the debugger interface). Now there's a base class Image
  and respective derived classes implementing those methods.
* Simplified SymbolIterator.
* Moved the classes into sub-namespace BPrivate::Debug.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30142 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-04-12 23:57:35 +00:00
parent db9ff5bfb8
commit 73677f785a
6 changed files with 788 additions and 512 deletions
+333
View File
@@ -0,0 +1,333 @@
/*
* Copyright 2005-2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "Image.h"
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <new>
#include <runtime_loader.h>
#include <syscalls.h>
using namespace BPrivate::Debug;
// #pragma mark - Image
Image::Image()
{
}
Image::~Image()
{
}
// #pragma mark - SymbolTableBasedImage
SymbolTableBasedImage::SymbolTableBasedImage()
:
fInfo(),
fLoadDelta(0),
fSymbolTable(NULL),
fStringTable(NULL),
fSymbolCount(0),
fStringTableSize(0)
{
}
SymbolTableBasedImage::~SymbolTableBasedImage()
{
}
image_id
SymbolTableBasedImage::ID() const
{
return fInfo.id;
}
const char*
SymbolTableBasedImage::Name() const
{
return fInfo.name;
}
addr_t
SymbolTableBasedImage::TextAddress() const
{
return (addr_t)fInfo.text;
}
size_t
SymbolTableBasedImage::TextSize() const
{
return fInfo.text_size;
}
const Elf32_Sym*
SymbolTableBasedImage::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
SymbolTableBasedImage::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
SymbolTableBasedImage::_SymbolNameLen(const char* symbolName) const
{
if (symbolName == NULL || (addr_t)symbolName < (addr_t)fStringTable
|| (addr_t)symbolName >= (addr_t)fStringTable + fStringTableSize) {
return 0;
}
return strnlen(symbolName,
(addr_t)fStringTable + fStringTableSize - (addr_t)symbolName);
}
// #pragma mark - ImageFile
ImageFile::ImageFile()
:
fFD(-1),
fFileSize(0),
fMappedFile((uint8*)MAP_FAILED)
{
}
ImageFile::~ImageFile()
{
if (fMappedFile != MAP_FAILED)
munmap(fMappedFile, fFileSize);
if (fFD >= 0)
close(fFD);
}
status_t
ImageFile::Init(const image_info& info)
{
fInfo = info;
// 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_PRIVATE, 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 = (Elf32_Sym*)(fMappedFile + sectionHeader->sh_offset);
fStringTable = (char*)(fMappedFile + stringHeader.sh_offset);
fSymbolCount = sectionHeader->sh_size / sizeof(Elf32_Sym);
fStringTableSize = stringHeader.sh_size;
return B_OK;
}
}
return B_BAD_DATA;
}
// #pragma mark - KernelImage
KernelImage::KernelImage()
{
}
KernelImage::~KernelImage()
{
delete[] fSymbolTable;
delete[] fStringTable;
}
status_t
KernelImage::Init(const image_info& info)
{
fInfo = info;
// get the table sizes
fSymbolCount = 0;
fStringTableSize = 0;
status_t error = _kern_read_kernel_image_symbols(fInfo.id,
NULL, &fSymbolCount, NULL, &fStringTableSize, NULL);
if (error != B_OK)
return error;
// allocate the tables
fSymbolTable = new(std::nothrow) Elf32_Sym[fSymbolCount];
fStringTable = new(std::nothrow) char[fStringTableSize];
if (fSymbolTable == NULL || fStringTable == NULL)
return B_NO_MEMORY;
// get the info
return _kern_read_kernel_image_symbols(fInfo.id,
fSymbolTable, &fSymbolCount, fStringTable, &fStringTableSize,
&fLoadDelta);
}
+112
View File
@@ -0,0 +1,112 @@
/*
* Copyright 2005-2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef IMAGE_H
#define IMAGE_H
#include <stdio.h>
#include <image.h>
#include <OS.h>
#include <util/DoublyLinkedList.h>
struct image_t;
struct runtime_loader_debug_area;
struct Elf32_Sym;
namespace BPrivate {
namespace Debug {
class Image : public DoublyLinkedListLinkImpl<Image> {
public:
Image();
virtual ~Image();
virtual image_id ID() const = 0;
virtual const char* Name() const = 0;
virtual addr_t TextAddress() const = 0;
virtual size_t TextSize() const = 0;
virtual const Elf32_Sym* LookupSymbol(addr_t address,
addr_t* _baseAddress,
const char** _symbolName,
size_t *_symbolNameLen,
bool *_exactMatch) const = 0;
virtual status_t NextSymbol(int32& iterator,
const char** _symbolName,
size_t* _symbolNameLen,
addr_t* _symbolAddress, size_t* _symbolSize,
int32* _symbolType) const = 0;
};
class SymbolTableBasedImage : public Image {
public:
SymbolTableBasedImage();
virtual ~SymbolTableBasedImage();
virtual image_id ID() const ;
virtual const char* Name() const;
virtual addr_t TextAddress() const;
virtual size_t TextSize() const;
virtual const Elf32_Sym* LookupSymbol(addr_t address,
addr_t* _baseAddress,
const char** _symbolName,
size_t *_symbolNameLen,
bool *_exactMatch) const;
virtual status_t NextSymbol(int32& iterator,
const char** _symbolName,
size_t* _symbolNameLen,
addr_t* _symbolAddress, size_t* _symbolSize,
int32* _symbolType) const;
protected:
size_t _SymbolNameLen(const char* symbolName) const;
protected:
image_info fInfo;
addr_t fLoadDelta;
Elf32_Sym* fSymbolTable;
char* fStringTable;
int32 fSymbolCount;
size_t fStringTableSize;
};
class ImageFile : public SymbolTableBasedImage {
public:
ImageFile();
virtual ~ImageFile();
status_t Init(const image_info& info);
private:
int fFD;
off_t fFileSize;
uint8* fMappedFile;
};
class KernelImage : public SymbolTableBasedImage {
public:
KernelImage();
virtual ~KernelImage();
status_t Init(const image_info& info);
};
} // namespace Debug
} // namespace BPrivate
using BPrivate::Debug::ImageFile;
#endif // IMAGE_H
+1
View File
@@ -12,6 +12,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) arch $(TARGET_ARCH) ] ;
SharedLibrary libdebug.so :
debug_support.cpp
Image.cpp
SymbolLookup.cpp
# architecture specific
+317 -459
View File
@@ -1,15 +1,12 @@
/*
* Copyright 2005-2008, Ingo Weinhold, [email protected].
* Copyright 2005-2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "SymbolLookup.h"
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <new>
@@ -17,6 +14,8 @@
#include <runtime_loader.h>
#include <syscalls.h>
#include "Image.h"
#undef TRACE
//#define TRACE_DEBUG_SYMBOL_LOOKUP
@@ -27,8 +26,7 @@
#endif
using std::nothrow;
using namespace BPrivate;
using namespace BPrivate::Debug;
// PrepareAddress
@@ -94,7 +92,7 @@ RemoteMemoryAccessor::Init()
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,
Area *area = new(std::nothrow) Area(areaInfo.area, areaInfo.address,
areaInfo.size);
if (!area)
return B_NO_MEMORY;
@@ -192,243 +190,34 @@ RemoteMemoryAccessor::_FindAreaNoThrow(const void *address, int32 size) const
// #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),
fStringTableSize(0)
{
}
class SymbolLookup::LoadedImage : public Image {
public:
LoadedImage(SymbolLookup* symbolLookup,
const image_t* image, int32 symbolCount);
virtual ~LoadedImage();
virtual image_id ID() const;
virtual const char* Name() const;
virtual addr_t TextAddress() const;
virtual size_t TextSize() const;
ImageFile::~ImageFile()
{
if (fMappedFile != MAP_FAILED) {
munmap(fMappedFile, fFileSize);
} else {
delete[] fSymbolTable;
delete[] fStringTable;
}
virtual const Elf32_Sym* LookupSymbol(addr_t address,
addr_t* _baseAddress,
const char** _symbolName,
size_t *_symbolNameLen,
bool *_exactMatch) const;
virtual status_t NextSymbol(int32& iterator,
const char** _symbolName,
size_t* _symbolNameLen,
addr_t* _symbolAddress, size_t* _symbolSize,
int32* _symbolType) const;
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_PRIVATE, 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 = (Elf32_Sym*)(fMappedFile + sectionHeader->sh_offset);
fStringTable = (char*)(fMappedFile + stringHeader.sh_offset);
fSymbolCount = sectionHeader->sh_size / sizeof(Elf32_Sym);
fStringTableSize = stringHeader.sh_size;
return B_OK;
}
}
return B_BAD_DATA;
}
status_t
ImageFile::LoadKernel()
{
// get the table sizes
fSymbolCount = 0;
fStringTableSize = 0;
status_t error = _kern_read_kernel_image_symbols(fInfo.id,
NULL, &fSymbolCount, NULL, &fStringTableSize, NULL);
if (error != B_OK)
return error;
// allocate the tables
fSymbolTable = new(std::nothrow) Elf32_Sym[fSymbolCount];
fStringTable = new(std::nothrow) char[fStringTableSize];
if (fSymbolTable == NULL || fStringTable == NULL)
return B_NO_MEMORY;
// get the info
return _kern_read_kernel_image_symbols(fInfo.id,
fSymbolTable, &fSymbolCount, fStringTable, &fStringTableSize,
&fLoadDelta);
}
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)fStringTable + fStringTableSize) {
return 0;
}
return strnlen(symbolName,
(addr_t)fStringTable + fStringTableSize - (addr_t)symbolName);
}
private:
SymbolLookup* fSymbolLookup;
const image_t* fImage;
int32 fSymbolCount;
size_t fTextDelta;
};
// #pragma mark -
@@ -439,7 +228,7 @@ SymbolLookup::SymbolLookup(team_id team)
:
RemoteMemoryAccessor(team),
fDebugArea(NULL),
fImageFiles()
fImages()
{
}
@@ -447,8 +236,8 @@ SymbolLookup::SymbolLookup(team_id team)
// destructor
SymbolLookup::~SymbolLookup()
{
while (ImageFile* imageFile = fImageFiles.RemoveHead())
delete imageFile;
while (Image* image = fImages.RemoveHead())
delete image;
}
@@ -500,18 +289,41 @@ SymbolLookup::Init()
image_info imageInfo;
int32 cookie = 0;
while (get_next_image_info(fTeam, &cookie, &imageInfo) == B_OK) {
ImageFile* imageFile = new(std::nothrow) ImageFile(imageInfo);
if (imageFile == NULL)
break;
Image* image;
error = fTeam == B_SYSTEM_TEAM
? imageFile->LoadKernel() : imageFile->Load();
if (error != B_OK) {
delete imageFile;
continue;
if (fTeam == B_SYSTEM_TEAM) {
// kernel image
KernelImage* kernelImage = new(std::nothrow) KernelImage;
if (kernelImage == NULL)
return B_NO_MEMORY;
error = kernelImage->Init(imageInfo);
image = kernelImage;
} else {
// userland image -- try to load an image file
ImageFile* imageFile = new(std::nothrow) ImageFile;
if (imageFile == NULL)
return B_NO_MEMORY;
error = imageFile->Init(imageInfo);
image = imageFile;
}
fImageFiles.Add(imageFile);
if (error != B_OK) {
// initialization error -- fall back to the loaded image
delete image;
const image_t* loadedImage = _FindLoadedImageByID(imageInfo.id);
if (loadedImage == NULL)
continue;
image = new(std::nothrow) LoadedImage(this, loadedImage,
Read(loadedImage->symhash[1]));
if (image == NULL)
return B_NO_MEMORY;
}
fImages.Add(image);
}
return B_OK;
@@ -526,25 +338,237 @@ SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
{
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);
Image* 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));
if (_imageName != NULL)
*_imageName = image->Name();
const Elf32_Sym* symbolFound = image->LookupSymbol(address, _baseAddress,
_symbolName, _symbolNameLen, _exactMatch);
TRACE(("SymbolLookup::LookupSymbolAddress(): done: symbol: %p, image name: "
"%s, exact match: %d\n", symbolFound, image->name, exactMatch));
if (symbolFound != NULL)
return B_OK;
// symbol not found -- return the image itself
if (_baseAddress)
*_baseAddress = image->TextAddress();
if (_imageName)
*_imageName = image->Name();
if (_symbolName)
*_symbolName = NULL;
if (_exactMatch)
*_exactMatch = false;
if (_symbolNameLen != NULL)
*_symbolNameLen = 0;
return B_OK;
}
// InitSymbolIterator
status_t
SymbolLookup::InitSymbolIterator(image_id imageID,
SymbolIterator& iterator) const
{
TRACE(("SymbolLookup::InitSymbolIterator(): image ID: %ld\n", imageID));
// find the image
iterator.image = _FindImageByID(imageID);
// If that didn't work, find the loaded image.
if (iterator.image == NULL) {
TRACE(("SymbolLookup::InitSymbolIterator() done: image not "
"found\n"));
return B_ENTRY_NOT_FOUND;
}
iterator.currentIndex = -1;
return B_OK;
}
// InitSymbolIterator
status_t
SymbolLookup::InitSymbolIteratorByAddress(addr_t address,
SymbolIterator& iterator) const
{
TRACE(("SymbolLookup::InitSymbolIteratorByAddress(): base address: %#lx\n",
address));
// find the image
iterator.image = _FindImageAtAddress(address);
if (iterator.image == NULL) {
TRACE(("SymbolLookup::InitSymbolIteratorByAddress() done: image "
"not found\n"));
return B_ENTRY_NOT_FOUND;
}
iterator.currentIndex = -1;
return B_OK;
}
// NextSymbol
status_t
SymbolLookup::NextSymbol(SymbolIterator& iterator, const char** _symbolName,
size_t* _symbolNameLen, addr_t* _symbolAddress, size_t* _symbolSize,
int32* _symbolType) const
{
return iterator.image->NextSymbol(iterator.currentIndex, _symbolName,
_symbolNameLen, _symbolAddress, _symbolSize, _symbolType);
}
// _FindLoadedImageAtAddress
const image_t *
SymbolLookup::_FindLoadedImageAtAddress(addr_t address) const
{
TRACE(("SymbolLookup::_FindLoadedImageAtAddress(%p)\n", (void*)address));
if (fDebugArea == NULL)
return NULL;
// iterate through the loaded 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;
}
// _FindLoadedImageByID
const image_t*
SymbolLookup::_FindLoadedImageByID(image_id id) const
{
if (fDebugArea == NULL)
return NULL;
// 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;
}
// _FindImageAtAddress
Image*
SymbolLookup::_FindImageAtAddress(addr_t address) const
{
DoublyLinkedList<Image>::ConstIterator it = fImages.GetIterator();
while (Image* image = it.Next()) {
addr_t textAddress = image->TextAddress();
if (address >= textAddress && address < textAddress + image->TextSize())
return image;
}
return NULL;
}
// _FindImageByID
Image*
SymbolLookup::_FindImageByID(image_id id) const
{
DoublyLinkedList<Image>::ConstIterator it = fImages.GetIterator();
while (Image* image = it.Next()) {
if (image->ID() == id)
return image;
}
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);
}
// #pragma mark - LoadedImage
SymbolLookup::LoadedImage::LoadedImage(SymbolLookup* symbolLookup,
const image_t* image, int32 symbolCount)
:
fSymbolLookup(symbolLookup),
fImage(image),
fSymbolCount(symbolCount),
fTextDelta(image->regions[0].delta)
{
}
SymbolLookup::LoadedImage::~LoadedImage()
{
}
image_id
SymbolLookup::LoadedImage::ID() const
{
return fImage->id;
}
const char*
SymbolLookup::LoadedImage::Name() const
{
return fImage->path;
}
addr_t
SymbolLookup::LoadedImage::TextAddress() const
{
return fImage->regions[0].vmstart;
}
size_t
SymbolLookup::LoadedImage::TextSize() const
{
return fImage->regions[0].vmsize;
}
const Elf32_Sym*
SymbolLookup::LoadedImage::LookupSymbol(addr_t address, addr_t* _baseAddress,
const char** _symbolName, size_t *_symbolNameLen, bool *_exactMatch) const
{
TRACE(("LoadedImage::LookupSymbol(): found image: ID: %ld, text: "
"address: %p, size: %ld\n", fImage->id,
(void*)fImage->regions[0].vmstart, fImage->regions[0].size));
// search the image for the symbol
const struct Elf32_Sym *symbolFound = NULL;
@@ -552,11 +576,11 @@ SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
bool exactMatch = false;
const char *symbolName = NULL;
int32 symbolCount = Read(image->symhash[1]);
const elf_region_t *textRegion = image->regions; // local
int32 symbolCount = fSymbolLookup->Read(fImage->symhash[1]);
const elf_region_t *textRegion = fImage->regions; // local
for (int32 i = 0; i < symbolCount; i++) {
const struct Elf32_Sym *symbol = &Read(image->syms[i]);
const struct Elf32_Sym *symbol = &fSymbolLookup->Read(fImage->syms[i]);
// The symbol table contains not only symbols referring to functions
// and data symbols within the shared object, but also referenced
@@ -581,8 +605,8 @@ SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
addr_t symbolDelta = address - symbolAddress;
if (!symbolFound || symbolDelta < deltaFound) {
symbolName = (const char*)PrepareAddressNoThrow(SYMNAME(image,
symbol), 1);
symbolName = (const char*)fSymbolLookup->PrepareAddressNoThrow(
SYMNAME(fImage, symbol), 1);
if (symbolName == NULL)
continue;
@@ -597,125 +621,45 @@ SymbolLookup::LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
}
}
TRACE(("SymbolLookup::LookupSymbolAddress(): done: symbol: %p, image name: "
"%s, exact match: %d\n", symbolFound, image->name, exactMatch));
TRACE(("LoadedImage::LookupSymbol(): done: symbol: %p, image name: "
"%s, exact match: %d\n", symbolFound, fImage->name, exactMatch));
if (_baseAddress) {
if (symbolFound)
if (symbolFound != NULL) {
if (_baseAddress)
*_baseAddress = symbolFound->st_value + textRegion->delta;
else
*_baseAddress = textRegion->vmstart;
if (_symbolName)
*_symbolName = symbolName;
if (_exactMatch)
*_exactMatch = exactMatch;
if (_symbolNameLen != NULL)
*_symbolNameLen = fSymbolLookup->_SymbolNameLen(symbolName);
}
if (_imageName)
*_imageName = image->name;
if (_symbolName)
*_symbolName = symbolName; // remote address
if (_exactMatch)
*_exactMatch = exactMatch;
if (_symbolNameLen != NULL)
*_symbolNameLen = _SymbolNameLen(symbolName);
return B_OK;
return symbolFound;
}
// InitSymbolIterator
status_t
SymbolLookup::InitSymbolIterator(image_id imageID,
SymbolIterator& iterator) const
{
TRACE(("SymbolLookup::InitSymbolIterator(): image ID: %ld\n", imageID));
// 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.currentIndex = -1;
return B_OK;
}
// InitSymbolIterator
status_t
SymbolLookup::InitSymbolIteratorByAddress(addr_t address,
SymbolIterator& iterator) const
{
TRACE(("SymbolLookup::InitSymbolIteratorByAddress(): base address: %#lx\n",
address));
// 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.currentIndex = -1;
return B_OK;
}
// NextSymbol
status_t
SymbolLookup::NextSymbol(SymbolIterator& iterator, const char** _symbolName,
SymbolLookup::LoadedImage::NextSymbol(int32& iterator, const char** _symbolName,
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) {
if (++iterator.currentIndex >= iterator.symbolCount)
if (++iterator >= fSymbolCount)
return B_ENTRY_NOT_FOUND;
const struct Elf32_Sym* symbol = &Read(image->syms[
iterator.currentIndex]);
const struct Elf32_Sym* symbol
= &fSymbolLookup->Read(fImage->syms[iterator]);
if ((ELF32_ST_TYPE(symbol->st_info) != STT_FUNC
&& ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT)
|| symbol->st_value == 0) {
continue;
}
*_symbolName = (const char*)PrepareAddressNoThrow(SYMNAME(image,
symbol), 1);
*_symbolNameLen = _SymbolNameLen(*_symbolName);
*_symbolAddress = symbol->st_value + iterator.textDelta;
*_symbolName = (const char*)fSymbolLookup->PrepareAddressNoThrow(
SYMNAME(fImage, symbol), 1);
*_symbolNameLen = fSymbolLookup->_SymbolNameLen(*_symbolName);
*_symbolAddress = symbol->st_value + fTextDelta;
*_symbolSize = symbol->st_size;
*_symbolType = ELF32_ST_TYPE(symbol->st_info) == STT_FUNC
? B_SYMBOL_TYPE_TEXT : B_SYMBOL_TYPE_DATA;
@@ -723,89 +667,3 @@ SymbolLookup::NextSymbol(SymbolIterator& iterator, const char** _symbolName,
return B_OK;
}
}
// _FindImageAtAddress
const image_t *
SymbolLookup::_FindImageAtAddress(addr_t address) const
{
TRACE(("SymbolLookup::_FindImageAtAddress(%p)\n", (void*)address));
if (fDebugArea == NULL)
return NULL;
// 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;
}
// _FindImageByID
const image_t*
SymbolLookup::_FindImageByID(image_id id) const
{
if (fDebugArea == NULL)
return NULL;
// 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;
}
// _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);
}
+20 -48
View File
@@ -1,10 +1,10 @@
/*
* Copyright 2005-2008, Ingo Weinhold, [email protected].
* Copyright 2005-2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef _SYMBOL_LOOKUP_H
#define _SYMBOL_LOOKUP_H
#ifndef SYMBOL_LOOKUP_H
#define SYMBOL_LOOKUP_H
#include <stdio.h>
@@ -20,6 +20,10 @@ struct Elf32_Sym;
namespace BPrivate {
namespace Debug {
class Image;
// Exception
class Exception {
@@ -123,46 +127,9 @@ private:
};
// ImageFile
class ImageFile : public DoublyLinkedListLinkImpl<ImageFile> {
public:
ImageFile(const image_info& info);
~ImageFile();
const image_info& Info() const { return fInfo; }
status_t Load();
status_t LoadKernel();
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;
Elf32_Sym* fSymbolTable;
char* fStringTable;
int32 fSymbolCount;
size_t fStringTableSize;
};
// SymbolIterator
struct SymbolIterator {
const image_t* image;
const ImageFile* imageFile;
int32 symbolCount;
size_t textDelta;
const Image* image;
int32 currentIndex;
};
@@ -188,19 +155,24 @@ public:
int32* _symbolType) const;
private:
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;
class LoadedImage;
friend class LoadedImage;
private:
const image_t* _FindLoadedImageAtAddress(addr_t address) const;
const image_t* _FindLoadedImageByID(image_id id) const;
Image* _FindImageAtAddress(addr_t address) const;
Image* _FindImageByID(image_id id) const;
size_t _SymbolNameLen(const char* address) const;
private:
const runtime_loader_debug_area *fDebugArea;
DoublyLinkedList<ImageFile> fImageFiles;
DoublyLinkedList<Image> fImages;
};
} // namespace Debug
} // namespace BPrivate
using BPrivate::SymbolLookup;
using BPrivate::Debug::SymbolLookup;
#endif // _SYMBOL_LOOKUP_H
#endif // SYMBOL_LOOKUP_H
+5 -5
View File
@@ -21,7 +21,7 @@ struct debug_symbol_lookup_context {
SymbolLookup* lookup;
};
struct debug_symbol_iterator : BPrivate::SymbolIterator {
struct debug_symbol_iterator : BPrivate::Debug::SymbolIterator {
debug_symbol_lookup_context* lookup_context;
};
@@ -327,7 +327,7 @@ debug_lookup_symbol_address(debug_symbol_lookup_context *lookupContext,
exactMatch);
if (error != B_OK)
return error;
} catch (BPrivate::Exception exception) {
} catch (BPrivate::Debug::Exception exception) {
return exception.Error();
}
@@ -368,7 +368,7 @@ debug_create_image_symbol_iterator(debug_symbol_lookup_context* lookupContext,
status_t error;
try {
error = lookup->InitSymbolIterator(imageID, *iterator);
} catch (BPrivate::Exception exception) {
} catch (BPrivate::Debug::Exception exception) {
error = exception.Error();
}
@@ -386,7 +386,7 @@ debug_create_image_symbol_iterator(debug_symbol_lookup_context* lookupContext,
try {
error = lookup->InitSymbolIteratorByAddress(
(addr_t)imageInfo.text, *iterator);
} catch (BPrivate::Exception exception) {
} catch (BPrivate::Debug::Exception exception) {
error = exception.Error();
}
}
@@ -433,7 +433,7 @@ debug_next_image_symbol(debug_symbol_iterator* iterator, char* nameBuffer,
_symbolType);
if (error != B_OK)
return error;
} catch (BPrivate::Exception exception) {
} catch (BPrivate::Debug::Exception exception) {
return exception.Error();
}