Debugger: CoreFileDebuggerInterface: Finish symbol support

If available, symbols are read from the respectice core file symbols
note. Otherwise, if available read symbols from ELF file. Finally fall
back to the dynamic symbol table from the core file image. Reusable
functionality is implemented in DebuggerInterface (GetElfSymbols()).
This commit is contained in:
Ingo Weinhold 2016-05-22 22:08:00 +02:00
parent e07597abd9
commit 6c06458f8a
4 changed files with 170 additions and 15 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2009-2016, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2010-2016, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
@ -7,6 +7,61 @@
#include "DebuggerInterface.h"
#include <algorithm>
#include <AutoDeleter.h>
#include "ElfSymbolLookup.h"
// #pragma mark - SymbolTableLookupSource
struct DebuggerInterface::SymbolTableLookupSource : ElfSymbolLookupSource {
public:
SymbolTableLookupSource(const void* symbolTable, size_t symbolTableSize,
const char* stringTable, size_t stringTableSize)
:
fSymbolTable((const uint8*)symbolTable),
fStringTable(stringTable),
fSymbolTableSize(symbolTableSize),
fStringTableEnd(symbolTableSize + stringTableSize)
{
}
virtual ssize_t Read(uint64 address, void* buffer, size_t size)
{
ssize_t copied = 0;
if (address > fStringTableEnd)
return B_BAD_VALUE;
if (address < fSymbolTableSize) {
size_t toCopy = std::min(size, size_t(fSymbolTableSize - address));
memcpy(buffer, fSymbolTable + address, toCopy);
address -= toCopy;
size -= toCopy;
copied += toCopy;
}
if (address < fStringTableEnd) {
size_t toCopy = std::min(size, size_t(fStringTableEnd - address));
memcpy(buffer, fStringTable + address - fSymbolTableSize, toCopy);
address -= toCopy;
size -= toCopy;
copied += toCopy;
}
return copied;
}
private:
const uint8* fSymbolTable;
const char* fStringTable;
size_t fSymbolTableSize;
size_t fStringTableEnd;
};
// #pragma mark - DebuggerInterface
@ -22,3 +77,71 @@ DebuggerInterface::IsPostMortem() const
// only true for core file interfaces
return false;
}
status_t
DebuggerInterface::GetElfSymbols(const char* filePath, int64 textDelta,
BObjectList<SymbolInfo>& infos)
{
// open the ELF file
ElfFile elfFile;
status_t error = elfFile.Init(filePath);
if (error != B_OK)
return error;
// create the symbol lookup
ElfSymbolLookup* symbolLookup;
error = elfFile.CreateSymbolLookup(textDelta, symbolLookup);
if (error != B_OK)
return error;
ObjectDeleter<ElfSymbolLookup> symbolLookupDeleter(symbolLookup);
// get the symbols
return GetElfSymbols(symbolLookup, infos);
}
status_t
DebuggerInterface::GetElfSymbols(const void* symbolTable, uint32 symbolCount,
uint32 symbolTableEntrySize, const char* stringTable,
uint32 stringTableSize, bool is64Bit, bool swappedByteOrder,
int64 textDelta, BObjectList<SymbolInfo>& infos)
{
size_t symbolTableSize = symbolCount * symbolTableEntrySize;
SymbolTableLookupSource* source = new(std::nothrow) SymbolTableLookupSource(
symbolTable, symbolTableSize, stringTable, stringTableSize);
if (source == NULL)
return B_NO_MEMORY;
BReference<SymbolTableLookupSource> sourceReference(source, true);
ElfSymbolLookup* symbolLookup;
status_t error = ElfSymbolLookup::Create(
source, 0, 0, symbolTableSize, symbolCount, symbolTableEntrySize,
textDelta, is64Bit, swappedByteOrder, false, symbolLookup);
if (error != B_OK)
return error;
ObjectDeleter<ElfSymbolLookup> symbolLookupDeleter(symbolLookup);
// get the symbols
return GetElfSymbols(symbolLookup, infos);
}
status_t
DebuggerInterface::GetElfSymbols(ElfSymbolLookup* symbolLookup,
BObjectList<SymbolInfo>& infos)
{
SymbolInfo symbolInfo;
uint32 index = 0;
while (symbolLookup->NextSymbolInfo(index, symbolInfo) == B_OK) {
SymbolInfo* info = new(std::nothrow) SymbolInfo(symbolInfo);
if (info == NULL || !infos.AddItem(info)) {
delete info;
return B_NO_MEMORY;
}
}
return B_OK;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2009-2016, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2010-2015, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License.
*/
@ -15,9 +15,10 @@
class Architecture;
class AreaInfo;
class CpuState;
class DebugEvent;
class AreaInfo;
class ElfSymbolLookup;
class ImageInfo;
class SemaphoreInfo;
class SymbolInfo;
@ -99,6 +100,24 @@ public:
size_t size) = 0;
virtual ssize_t WriteMemory(target_addr_t address,
void* buffer, size_t size) = 0;
protected:
status_t GetElfSymbols(const char* filePath,
int64 textDelta,
BObjectList<SymbolInfo>& infos);
status_t GetElfSymbols(const void* symbolTable,
uint32 symbolCount,
uint32 symbolTableEntrySize,
const char* stringTable,
uint32 stringTableSize, bool is64Bit,
bool swappedByteOrder, int64 textDelta,
BObjectList<SymbolInfo>& infos);
status_t GetElfSymbols(ElfSymbolLookup* symbolLookup,
BObjectList<SymbolInfo>& infos);
private:
struct SymbolTableLookupSource;
};
#endif // DEBUGGER_INTERFACE_H

View File

@ -236,30 +236,38 @@ status_t
CoreFileDebuggerInterface::GetSymbolInfos(team_id team, image_id image,
BObjectList<SymbolInfo>& infos)
{
// get the image info
const CoreFileImageInfo* imageInfo = fCoreFile->ImageInfoForId(image);
if (imageInfo == NULL)
return B_BAD_IMAGE_ID;
if (const CoreFileSymbolsInfo* symbolsInfo = imageInfo->SymbolsInfo()) {
return GetElfSymbols(symbolsInfo->SymbolTable(),
symbolsInfo->SymbolCount(), symbolsInfo->SymbolTableEntrySize(),
symbolsInfo->StringTable(), symbolsInfo->StringTableSize(),
fCoreFile->GetElfFile().Is64Bit(),
fCoreFile->GetElfFile().IsByteOrderSwapped(),
imageInfo->TextDelta(), infos);
}
// get the symbols from the ELF file, if possible
status_t error = GetElfSymbols(imageInfo->Name(), imageInfo->TextDelta(),
infos);
if (error == B_OK)
return error;
// get the symbols from the core file, if possible
ElfSymbolLookup* symbolLookup;
status_t error = fCoreFile->CreateSymbolLookup(imageInfo, symbolLookup);
error = fCoreFile->CreateSymbolLookup(imageInfo, symbolLookup);
if (error != B_OK) {
WARNING("Failed to create symbol lookup for image (%" B_PRId32
"): %s\n", image, strerror(error));
return error;
}
ObjectDeleter<ElfSymbolLookup> symbolLookupDeleter(symbolLookup);
SymbolInfo symbolInfo;
uint32 index = 0;
while (symbolLookup->NextSymbolInfo(index, symbolInfo) == B_OK) {
SymbolInfo* info = new(std::nothrow) SymbolInfo(symbolInfo);
if (info == NULL || !infos.AddItem(info)) {
delete info;
return B_NO_MEMORY;
}
}
return B_OK;
return GetElfSymbols(symbolLookup, infos);
}

View File

@ -12,6 +12,8 @@
class CoreFile;
struct CoreFileThreadInfo;
class ElfSection;
class ElfSymbolLookup;
class CoreFileDebuggerInterface : public DebuggerInterface {
@ -83,6 +85,9 @@ private:
void _GetThreadInfo(
const CoreFileThreadInfo& coreInfo,
ThreadInfo& info);
status_t _CreateSharedObjectFileSymbolLookup(
const char* path,
ElfSymbolLookup*& _lookup);
private:
CoreFile* fCoreFile;