Debugger: Call frame unwind optimizations.
- Pass address size to DwarfManager, and subsequently DwarfFile's Load()
method, as that information is needed in order to parse the frame
information correctly early on.
- When initially loading debug information, also do a quick pass through
.{debug,eh}_frame, and build a lookup table of offsets. This is then
used later when actual unwinding is requested in order to quickly find
the corresponding FDE/CIE. Should noticeably improve performance when
stepping through code, especially for larger/more complex executable images.
Implements #8613.
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "arch/Architecture.h"
|
||||||
#include "DebuggerInterface.h"
|
#include "DebuggerInterface.h"
|
||||||
#include "DwarfFile.h"
|
#include "DwarfFile.h"
|
||||||
#include "DwarfImageDebugInfo.h"
|
#include "DwarfImageDebugInfo.h"
|
||||||
@@ -47,7 +48,7 @@ DwarfTeamDebugInfo::~DwarfTeamDebugInfo()
|
|||||||
status_t
|
status_t
|
||||||
DwarfTeamDebugInfo::Init()
|
DwarfTeamDebugInfo::Init()
|
||||||
{
|
{
|
||||||
fManager = new(std::nothrow) DwarfManager;
|
fManager = new(std::nothrow) DwarfManager(fArchitecture->AddressSize());
|
||||||
if (fManager == NULL)
|
if (fManager == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
|||||||
@@ -442,6 +442,45 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - FDELookupInfo
|
||||||
|
|
||||||
|
|
||||||
|
struct DwarfFile::FDELookupInfo {
|
||||||
|
public:
|
||||||
|
FDELookupInfo(target_addr_t start, target_addr_t end,
|
||||||
|
uint64 fdeOffset, uint64 cieOffset, bool ehFrame)
|
||||||
|
:
|
||||||
|
start(start),
|
||||||
|
end(end),
|
||||||
|
fdeOffset(fdeOffset),
|
||||||
|
cieOffset(cieOffset),
|
||||||
|
ehFrame(ehFrame)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static int CompareFDEInfos(const FDELookupInfo* a, const FDELookupInfo* b)
|
||||||
|
{
|
||||||
|
if (a->start < b->start)
|
||||||
|
return -1;
|
||||||
|
else if (a->start > b->start)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ContainsAddress(target_addr_t address) const
|
||||||
|
{
|
||||||
|
return address >= start && address < end;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_addr_t start;
|
||||||
|
target_addr_t end;
|
||||||
|
uint64 fdeOffset;
|
||||||
|
uint64 cieOffset;
|
||||||
|
bool ehFrame;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DwarfFile
|
// #pragma mark - DwarfFile
|
||||||
|
|
||||||
|
|
||||||
@@ -462,8 +501,12 @@ DwarfFile::DwarfFile()
|
|||||||
fDebugPublicTypesSection(NULL),
|
fDebugPublicTypesSection(NULL),
|
||||||
fDebugTypesSection(NULL),
|
fDebugTypesSection(NULL),
|
||||||
fCompilationUnits(20, true),
|
fCompilationUnits(20, true),
|
||||||
|
fTypeUnits(),
|
||||||
|
fDebugFrameInfos(100, true),
|
||||||
|
fEHFrameInfos(100, true),
|
||||||
fTypesSectionRequired(false),
|
fTypesSectionRequired(false),
|
||||||
fFinished(false),
|
fFinished(false),
|
||||||
|
fItaniumEHFrameFormat(false),
|
||||||
fFinishError(B_OK)
|
fFinishError(B_OK)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -528,7 +571,7 @@ DwarfFile::StartLoading(const char* fileName, BString& _requiredExternalFile)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfFile::Load(const BString& externalInfoFilePath)
|
DwarfFile::Load(uint8 addressSize, const BString& externalInfoFilePath)
|
||||||
{
|
{
|
||||||
status_t error = B_OK;
|
status_t error = B_OK;
|
||||||
if (fDebugInfoSection == NULL) {
|
if (fDebugInfoSection == NULL) {
|
||||||
@@ -547,11 +590,27 @@ DwarfFile::Load(const BString& externalInfoFilePath)
|
|||||||
fDebugRangesSection = debugInfoFile->GetSection(".debug_ranges");
|
fDebugRangesSection = debugInfoFile->GetSection(".debug_ranges");
|
||||||
fDebugLineSection = debugInfoFile->GetSection(".debug_line");
|
fDebugLineSection = debugInfoFile->GetSection(".debug_line");
|
||||||
fDebugFrameSection = debugInfoFile->GetSection(".debug_frame");
|
fDebugFrameSection = debugInfoFile->GetSection(".debug_frame");
|
||||||
|
|
||||||
|
if (fDebugFrameSection != NULL) {
|
||||||
|
error = _ParseFrameSection(fDebugFrameSection, addressSize, false,
|
||||||
|
fDebugFrameInfos);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
// .eh_frame doesn't appear to get copied into separate debug
|
// .eh_frame doesn't appear to get copied into separate debug
|
||||||
// info files properly, therefore always use it off the main
|
// info files properly, therefore always use it off the main
|
||||||
// executable image
|
// executable image
|
||||||
if (fEHFrameSection == NULL)
|
if (fEHFrameSection == NULL)
|
||||||
fEHFrameSection = fElfFile->GetSection(".eh_frame");
|
fEHFrameSection = fElfFile->GetSection(".eh_frame");
|
||||||
|
|
||||||
|
if (fEHFrameSection != NULL) {
|
||||||
|
error = _ParseFrameSection(fEHFrameSection, addressSize, true,
|
||||||
|
fEHFrameInfos);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
fDebugLocationSection = debugInfoFile->GetSection(".debug_loc");
|
fDebugLocationSection = debugInfoFile->GetSection(".debug_loc");
|
||||||
fDebugPublicTypesSection = debugInfoFile->GetSection(".debug_pubtypes");
|
fDebugPublicTypesSection = debugInfoFile->GetSection(".debug_pubtypes");
|
||||||
|
|
||||||
@@ -699,22 +758,12 @@ DwarfFile::UnwindCallFrame(CompilationUnit* unit, uint8 addressSize,
|
|||||||
const DwarfTargetInterface* inputInterface,
|
const DwarfTargetInterface* inputInterface,
|
||||||
DwarfTargetInterface* outputInterface, target_addr_t& _framePointer)
|
DwarfTargetInterface* outputInterface, target_addr_t& _framePointer)
|
||||||
{
|
{
|
||||||
status_t result = B_ENTRY_NOT_FOUND;
|
FDELookupInfo* info = _GetContainingFDEInfo(location);
|
||||||
|
if (info == NULL)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
// first try to find the FDE in .debug_frame
|
return _UnwindCallFrame(unit, addressSize, subprogramEntry, location, info,
|
||||||
if (fDebugFrameSection != NULL) {
|
inputInterface, outputInterface, _framePointer);
|
||||||
result = _UnwindCallFrame(false, unit, addressSize, subprogramEntry,
|
|
||||||
location, inputInterface, outputInterface, _framePointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if .debug_frame isn't present, or if the FDE wasn't found there,
|
|
||||||
// try .eh_frame
|
|
||||||
if (result == B_ENTRY_NOT_FOUND && fEHFrameSection != NULL) {
|
|
||||||
result = _UnwindCallFrame(true, unit, addressSize, subprogramEntry,
|
|
||||||
location, inputInterface, outputInterface, _framePointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1080,6 +1129,116 @@ DwarfFile::_ParseTypesSection()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_ParseFrameSection(ElfSection* section, uint8 addressSize,
|
||||||
|
bool ehFrame, FDEInfoList& infos)
|
||||||
|
{
|
||||||
|
if (ehFrame) {
|
||||||
|
fItaniumEHFrameFormat = section->IsWritable();
|
||||||
|
// Crude heuristic for recognizing GCC 4 (Itanium ABI) style
|
||||||
|
// .eh_frame sections. The ones generated by GCC 2 are writable,
|
||||||
|
// the ones generated by GCC 4 aren't.
|
||||||
|
}
|
||||||
|
|
||||||
|
DataReader dataReader((uint8*)section->Data(),
|
||||||
|
section->Size(), addressSize);
|
||||||
|
|
||||||
|
while (dataReader.BytesRemaining() > 0) {
|
||||||
|
// length
|
||||||
|
bool dwarf64;
|
||||||
|
off_t entryOffset = dataReader.Offset();
|
||||||
|
uint64 length = dataReader.ReadInitialLength(dwarf64);
|
||||||
|
|
||||||
|
TRACE_CFI("DwarfFile::_ParseFrameSection(): offset: %" B_PRIdOFF
|
||||||
|
", length: %" B_PRId64 "\n", entryOffset, length);
|
||||||
|
|
||||||
|
if (length > (uint64)dataReader.BytesRemaining())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
off_t lengthOffset = dataReader.Offset();
|
||||||
|
|
||||||
|
// CIE ID/CIE pointer
|
||||||
|
uint64 cieID = dwarf64
|
||||||
|
? dataReader.Read<uint64>(0) : dataReader.Read<uint32>(0);
|
||||||
|
|
||||||
|
// In .debug_frame ~0 indicates a CIE, in .eh_frame 0 does.
|
||||||
|
if (ehFrame
|
||||||
|
? cieID == 0
|
||||||
|
: (dwarf64
|
||||||
|
? cieID == 0xffffffffffffffffULL
|
||||||
|
: cieID == 0xffffffff)) {
|
||||||
|
// this is a CIE -- skip it
|
||||||
|
} else {
|
||||||
|
// this is a FDE
|
||||||
|
uint64 initialLocationOffset = dataReader.Offset();
|
||||||
|
// In .eh_frame the CIE offset is a relative back offset.
|
||||||
|
if (ehFrame) {
|
||||||
|
if (cieID > (uint64)lengthOffset) {
|
||||||
|
TRACE_CFI("Invalid CIE offset: %" B_PRIu64 ", max "
|
||||||
|
"possible: %" B_PRIu64 "\n", cieID, lengthOffset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// convert to a section relative offset
|
||||||
|
cieID = lengthOffset - cieID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CfaContext context;
|
||||||
|
CIEAugmentation cieAugmentation;
|
||||||
|
// when using .eh_frame format, we need to parse the CIE's
|
||||||
|
// augmentation up front in order to know how the FDE's addresses
|
||||||
|
// will be represented
|
||||||
|
DataReader cieReader;
|
||||||
|
off_t cieRemaining;
|
||||||
|
status_t error = _ParseCIEHeader(section, ehFrame, NULL,
|
||||||
|
addressSize, context, cieID, cieAugmentation, cieReader,
|
||||||
|
cieRemaining);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
if (cieReader.HasOverflow())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
if (cieRemaining < 0)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
target_addr_t initialLocation = cieAugmentation.ReadEncodedAddress(
|
||||||
|
dataReader, fElfFile, section);
|
||||||
|
target_addr_t addressRange = cieAugmentation.ReadEncodedAddress(
|
||||||
|
dataReader, fElfFile, section, true);
|
||||||
|
|
||||||
|
if (dataReader.HasOverflow())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
if ((cieAugmentation.FDEAddressType()
|
||||||
|
& CFI_ADDRESS_TYPE_PC_RELATIVE) != 0) {
|
||||||
|
initialLocation += initialLocationOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for unknown reasons, the debug frame sections generated by gcc
|
||||||
|
// sometimes contain duplicates at different offsets within the
|
||||||
|
// section. In such a case, simply skip the duplicates.
|
||||||
|
FDELookupInfo* temp = _GetContainingFDEInfo(initialLocation,
|
||||||
|
infos);
|
||||||
|
if (temp == NULL) {
|
||||||
|
FDELookupInfo* info = new(std::nothrow)FDELookupInfo(
|
||||||
|
initialLocation, initialLocation + addressRange - 1,
|
||||||
|
entryOffset, cieID, ehFrame);
|
||||||
|
if (info == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
ObjectDeleter<FDELookupInfo> infoDeleter(info);
|
||||||
|
if (!infos.BinaryInsert(info, FDELookupInfo::CompareFDEInfos))
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
infoDeleter.Detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dataReader.SeekAbsolute(lengthOffset + length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
|
DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
|
||||||
{
|
{
|
||||||
@@ -1705,69 +1864,24 @@ DwarfFile::_ParseLineInfo(CompilationUnit* unit)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit,
|
DwarfFile::_UnwindCallFrame(CompilationUnit* unit, uint8 addressSize,
|
||||||
uint8 addressSize, DIESubprogram* subprogramEntry, target_addr_t location,
|
DIESubprogram* subprogramEntry, target_addr_t location,
|
||||||
const DwarfTargetInterface* inputInterface,
|
const FDELookupInfo* info, const DwarfTargetInterface* inputInterface,
|
||||||
DwarfTargetInterface* outputInterface, target_addr_t& _framePointer)
|
DwarfTargetInterface* outputInterface, target_addr_t& _framePointer)
|
||||||
{
|
{
|
||||||
ElfSection* currentFrameSection = (usingEHFrameSection)
|
ElfSection* currentFrameSection = (info->ehFrame)
|
||||||
? fEHFrameSection : fDebugFrameSection;
|
? fEHFrameSection : fDebugFrameSection;
|
||||||
|
|
||||||
if (currentFrameSection == NULL)
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
|
||||||
|
|
||||||
bool gcc4EHFrameSection = false;
|
|
||||||
if (usingEHFrameSection) {
|
|
||||||
gcc4EHFrameSection = !currentFrameSection->IsWritable();
|
|
||||||
// Crude heuristic for recognizing GCC 4 (Itanium ABI) style
|
|
||||||
// .eh_frame sections. The ones generated by GCC 2 are writable,
|
|
||||||
// the ones generated by GCC 4 aren't.
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE_CFI("DwarfFile::_UnwindCallFrame(%#" B_PRIx64 ")\n", location);
|
TRACE_CFI("DwarfFile::_UnwindCallFrame(%#" B_PRIx64 ")\n", location);
|
||||||
|
|
||||||
DataReader dataReader((uint8*)currentFrameSection->Data(),
|
DataReader dataReader((uint8*)currentFrameSection->Data(),
|
||||||
currentFrameSection->Size(), unit != NULL
|
currentFrameSection->Size(), unit != NULL
|
||||||
? unit->AddressSize() : addressSize);
|
? unit->AddressSize() : addressSize);
|
||||||
|
dataReader.SeekAbsolute(info->fdeOffset);
|
||||||
|
|
||||||
while (dataReader.BytesRemaining() > 0) {
|
|
||||||
// length
|
|
||||||
bool dwarf64;
|
bool dwarf64;
|
||||||
TRACE_CFI_ONLY(off_t entryOffset = dataReader.Offset();)
|
|
||||||
uint64 length = dataReader.ReadInitialLength(dwarf64);
|
uint64 length = dataReader.ReadInitialLength(dwarf64);
|
||||||
|
uint64 lengthOffset = dataReader.Offset();
|
||||||
TRACE_CFI("DwarfFile::_UnwindCallFrame(): offset: %" B_PRIdOFF
|
|
||||||
", length: %" B_PRId64 "\n", entryOffset, length);
|
|
||||||
|
|
||||||
if (length > (uint64)dataReader.BytesRemaining())
|
|
||||||
return B_BAD_DATA;
|
|
||||||
off_t lengthOffset = dataReader.Offset();
|
|
||||||
|
|
||||||
// CIE ID/CIE pointer
|
|
||||||
uint64 cieID = dwarf64
|
|
||||||
? dataReader.Read<uint64>(0) : dataReader.Read<uint32>(0);
|
|
||||||
|
|
||||||
// In .debug_frame ~0 indicates a CIE, in .eh_frame 0 does.
|
|
||||||
if (usingEHFrameSection
|
|
||||||
? cieID == 0
|
|
||||||
: (dwarf64
|
|
||||||
? cieID == 0xffffffffffffffffULL
|
|
||||||
: cieID == 0xffffffff)) {
|
|
||||||
// this is a CIE -- skip it
|
|
||||||
} else {
|
|
||||||
// this is a FDE
|
|
||||||
uint64 initialLocationOffset = dataReader.Offset();
|
|
||||||
// In .eh_frame the CIE offset is a relative back offset.
|
|
||||||
if (usingEHFrameSection) {
|
|
||||||
if (cieID > (uint64)lengthOffset) {
|
|
||||||
TRACE_CFI("Invalid CIE offset: %" B_PRIu64 ", max "
|
|
||||||
"possible: %" B_PRIu64 "\n", cieID, lengthOffset);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// convert to a section relative offset
|
|
||||||
cieID = lengthOffset - cieID;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CfaContext context;
|
CfaContext context;
|
||||||
CIEAugmentation cieAugmentation;
|
CIEAugmentation cieAugmentation;
|
||||||
@@ -1777,7 +1891,7 @@ DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit,
|
|||||||
DataReader cieReader;
|
DataReader cieReader;
|
||||||
off_t cieRemaining;
|
off_t cieRemaining;
|
||||||
status_t error = _ParseCIEHeader(currentFrameSection,
|
status_t error = _ParseCIEHeader(currentFrameSection,
|
||||||
usingEHFrameSection, unit, addressSize, context, cieID,
|
info->ehFrame, unit, addressSize, context, info->cieOffset,
|
||||||
cieAugmentation, cieReader, cieRemaining);
|
cieAugmentation, cieReader, cieRemaining);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
@@ -1786,44 +1900,24 @@ DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit,
|
|||||||
if (cieRemaining < 0)
|
if (cieRemaining < 0)
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|
||||||
target_addr_t initialLocation = cieAugmentation.ReadEncodedAddress(
|
uint64 remaining = lengthOffset + length - info->fdeOffset;
|
||||||
dataReader, fElfFile, currentFrameSection);
|
|
||||||
target_addr_t addressRange = cieAugmentation.ReadEncodedAddress(
|
|
||||||
dataReader, fElfFile, currentFrameSection, true);
|
|
||||||
|
|
||||||
if (dataReader.HasOverflow())
|
|
||||||
return B_BAD_DATA;
|
|
||||||
|
|
||||||
if ((cieAugmentation.FDEAddressType()
|
|
||||||
& CFI_ADDRESS_TYPE_PC_RELATIVE) != 0) {
|
|
||||||
initialLocation += initialLocationOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: For GCC 2 .eh_frame sections things work differently: The
|
|
||||||
// initial locations are relocated by the runtime loader and
|
|
||||||
// afterwards point to the absolute addresses. Fortunately the
|
|
||||||
// relocations that always seem to be used are R_386_RELATIVE, so
|
|
||||||
// that the value we read from the file is already absolute
|
|
||||||
// (assuming an unchanged segment load address).
|
|
||||||
|
|
||||||
TRACE_CFI("location: %" B_PRIx64 ", initial location: %" B_PRIx64
|
|
||||||
", address range: %" B_PRIx64 "\n", location, initialLocation,
|
|
||||||
addressRange);
|
|
||||||
|
|
||||||
if (location >= initialLocation
|
|
||||||
&& location < initialLocation + addressRange) {
|
|
||||||
// This is the FDE we're looking for.
|
|
||||||
off_t remaining = lengthOffset + length
|
|
||||||
- dataReader.Offset();
|
|
||||||
if (remaining < 0)
|
if (remaining < 0)
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
// skip CIE ID, initial offset and range, since we already know those
|
||||||
|
// from FDELookupInfo.
|
||||||
|
dwarf64 ? dataReader.Read<uint64>(0) : dataReader.Read<uint32>(0);
|
||||||
|
cieAugmentation.ReadEncodedAddress(dataReader, fElfFile,
|
||||||
|
currentFrameSection);
|
||||||
|
cieAugmentation.ReadEncodedAddress(dataReader, fElfFile,
|
||||||
|
currentFrameSection, true);
|
||||||
|
|
||||||
TRACE_CFI(" found fde: length: %" B_PRIu64 " (%" B_PRIdOFF
|
TRACE_CFI(" found fde: length: %" B_PRIu64 " (%" B_PRIdOFF
|
||||||
"), CIE offset: %#" B_PRIx64 ", location: %#" B_PRIx64 ", "
|
"), CIE offset: %#" B_PRIx64 ", location: %#" B_PRIx64 ", "
|
||||||
"range: %#" B_PRIx64 "\n", length, remaining, cieID,
|
"range: %#" B_PRIx64 "\n", length, dataReader.BytesRemaining(),
|
||||||
initialLocation, addressRange);
|
info->cieOffset, info->start, info->end - info->start);
|
||||||
|
|
||||||
context.SetLocation(location, initialLocation);
|
context.SetLocation(location, info->start);
|
||||||
uint32 registerCount = outputInterface->CountRegisters();
|
uint32 registerCount = outputInterface->CountRegisters();
|
||||||
error = context.Init(registerCount);
|
error = context.Init(registerCount);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
@@ -1848,10 +1942,6 @@ DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit,
|
|||||||
TRACE_CFI(" failed to read FDE augmentation data!\n");
|
TRACE_CFI(" failed to read FDE augmentation data!\n");
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
// adjust remaining byte count to take augmentation bytes
|
|
||||||
// (if any) into account.
|
|
||||||
remaining = lengthOffset + length
|
|
||||||
- dataReader.Offset();
|
|
||||||
|
|
||||||
error = context.SaveInitialRuleSet();
|
error = context.SaveInitialRuleSet();
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
@@ -1996,14 +2086,8 @@ DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_framePointer = frameAddress;
|
_framePointer = frameAddress;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dataReader.SeekAbsolute(lengthOffset + length);
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2842,3 +2926,40 @@ DwarfFile::_GetContainingCompilationUnit(off_t refAddr) const
|
|||||||
CompilationUnit* unit = fCompilationUnits.ItemAt(lower);
|
CompilationUnit* unit = fCompilationUnits.ItemAt(lower);
|
||||||
return unit->ContainsAbsoluteOffset(refAddr) ? unit : NULL;
|
return unit->ContainsAbsoluteOffset(refAddr) ? unit : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DwarfFile::FDELookupInfo*
|
||||||
|
DwarfFile::_GetContainingFDEInfo(target_addr_t offset) const
|
||||||
|
{
|
||||||
|
FDELookupInfo* info = NULL;
|
||||||
|
if (fDebugFrameSection != NULL) {
|
||||||
|
info = _GetContainingFDEInfo(offset, fDebugFrameInfos);
|
||||||
|
if (info != NULL)
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _GetContainingFDEInfo(offset, fEHFrameInfos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DwarfFile::FDELookupInfo*
|
||||||
|
DwarfFile::_GetContainingFDEInfo(target_addr_t offset,
|
||||||
|
const FDEInfoList& infoList) const
|
||||||
|
{
|
||||||
|
// binary search
|
||||||
|
int lower = 0;
|
||||||
|
int upper = infoList.CountItems() - 1;
|
||||||
|
if (upper < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (lower < upper) {
|
||||||
|
int mid = (lower + upper + 1) / 2;
|
||||||
|
if (offset < infoList.ItemAt(mid)->start)
|
||||||
|
upper = mid - 1;
|
||||||
|
else
|
||||||
|
lower = mid;
|
||||||
|
}
|
||||||
|
|
||||||
|
FDELookupInfo* info = infoList.ItemAt(lower);
|
||||||
|
return info->ContainsAddress(offset) ? info : NULL;
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ public:
|
|||||||
|
|
||||||
status_t StartLoading(const char* fileName,
|
status_t StartLoading(const char* fileName,
|
||||||
BString& _requiredExternalFile);
|
BString& _requiredExternalFile);
|
||||||
status_t Load(const BString& externalFilePath);
|
status_t Load(uint8 addressSize,
|
||||||
|
const BString& externalFilePath);
|
||||||
status_t FinishLoading();
|
status_t FinishLoading();
|
||||||
|
|
||||||
const char* Name() const { return fName; }
|
const char* Name() const { return fName; }
|
||||||
@@ -108,14 +109,19 @@ private:
|
|||||||
struct ExpressionEvaluationContext;
|
struct ExpressionEvaluationContext;
|
||||||
struct FDEAugmentation;
|
struct FDEAugmentation;
|
||||||
struct CIEAugmentation;
|
struct CIEAugmentation;
|
||||||
|
struct FDELookupInfo;
|
||||||
|
|
||||||
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
|
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
|
||||||
typedef BObjectList<CompilationUnit> CompilationUnitList;
|
typedef BObjectList<CompilationUnit> CompilationUnitList;
|
||||||
typedef BOpenHashTable<TypeUnitTableHashDefinition> TypeUnitTable;
|
typedef BOpenHashTable<TypeUnitTableHashDefinition> TypeUnitTable;
|
||||||
|
typedef BObjectList<FDELookupInfo> FDEInfoList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _ParseDebugInfoSection();
|
status_t _ParseDebugInfoSection();
|
||||||
status_t _ParseTypesSection();
|
status_t _ParseTypesSection();
|
||||||
|
status_t _ParseFrameSection(ElfSection* section,
|
||||||
|
uint8 addressSize, bool ehFrame,
|
||||||
|
FDEInfoList& infos);
|
||||||
status_t _ParseCompilationUnit(CompilationUnit* unit);
|
status_t _ParseCompilationUnit(CompilationUnit* unit);
|
||||||
status_t _ParseTypeUnit(TypeUnit* unit);
|
status_t _ParseTypeUnit(TypeUnit* unit);
|
||||||
status_t _ParseDebugInfoEntry(DataReader& dataReader,
|
status_t _ParseDebugInfoEntry(DataReader& dataReader,
|
||||||
@@ -131,11 +137,11 @@ private:
|
|||||||
|
|
||||||
status_t _ParseLineInfo(CompilationUnit* unit);
|
status_t _ParseLineInfo(CompilationUnit* unit);
|
||||||
|
|
||||||
status_t _UnwindCallFrame(bool usingEHFrameSection,
|
status_t _UnwindCallFrame(CompilationUnit* unit,
|
||||||
CompilationUnit* unit,
|
|
||||||
uint8 addressSize,
|
uint8 addressSize,
|
||||||
DIESubprogram* subprogramEntry,
|
DIESubprogram* subprogramEntry,
|
||||||
target_addr_t location,
|
target_addr_t location,
|
||||||
|
const FDELookupInfo* info,
|
||||||
const DwarfTargetInterface* inputInterface,
|
const DwarfTargetInterface* inputInterface,
|
||||||
DwarfTargetInterface* outputInterface,
|
DwarfTargetInterface* outputInterface,
|
||||||
target_addr_t& _framePointer);
|
target_addr_t& _framePointer);
|
||||||
@@ -185,6 +191,13 @@ private:
|
|||||||
CompilationUnit* _GetContainingCompilationUnit(
|
CompilationUnit* _GetContainingCompilationUnit(
|
||||||
off_t refAddr) const;
|
off_t refAddr) const;
|
||||||
|
|
||||||
|
FDELookupInfo* _GetContainingFDEInfo(
|
||||||
|
target_addr_t offset) const;
|
||||||
|
|
||||||
|
FDELookupInfo* _GetContainingFDEInfo(
|
||||||
|
target_addr_t offset,
|
||||||
|
const FDEInfoList& infoList) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class DwarfFile::ExpressionEvaluationContext;
|
friend class DwarfFile::ExpressionEvaluationContext;
|
||||||
|
|
||||||
@@ -207,8 +220,11 @@ private:
|
|||||||
DebugInfoEntryFactory fDebugInfoFactory;
|
DebugInfoEntryFactory fDebugInfoFactory;
|
||||||
CompilationUnitList fCompilationUnits;
|
CompilationUnitList fCompilationUnits;
|
||||||
TypeUnitTable fTypeUnits;
|
TypeUnitTable fTypeUnits;
|
||||||
|
FDEInfoList fDebugFrameInfos;
|
||||||
|
FDEInfoList fEHFrameInfos;
|
||||||
bool fTypesSectionRequired;
|
bool fTypesSectionRequired;
|
||||||
bool fFinished;
|
bool fFinished;
|
||||||
|
bool fItaniumEHFrameFormat;
|
||||||
status_t fFinishError;
|
status_t fFinishError;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,9 @@
|
|||||||
#include "DwarfFileLoadingState.h"
|
#include "DwarfFileLoadingState.h"
|
||||||
|
|
||||||
|
|
||||||
DwarfManager::DwarfManager()
|
DwarfManager::DwarfManager(uint8 addressSize)
|
||||||
:
|
:
|
||||||
|
fAddressSize(addressSize),
|
||||||
fLock("dwarf manager")
|
fLock("dwarf manager")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -65,7 +66,7 @@ DwarfManager::LoadFile(const char* fileName, DwarfFileLoadingState& _state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error = file->Load(_state.locatedExternalInfoPath);
|
error = file->Load(fAddressSize, _state.locatedExternalInfoPath);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
_state.state = DWARF_FILE_LOADING_STATE_FAILED;
|
_state.state = DWARF_FILE_LOADING_STATE_FAILED;
|
||||||
return error;
|
return error;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ struct DwarfFileLoadingState;
|
|||||||
|
|
||||||
class DwarfManager {
|
class DwarfManager {
|
||||||
public:
|
public:
|
||||||
DwarfManager();
|
DwarfManager(uint8 addressSize);
|
||||||
~DwarfManager();
|
~DwarfManager();
|
||||||
|
|
||||||
status_t Init();
|
status_t Init();
|
||||||
@@ -36,6 +36,7 @@ private:
|
|||||||
typedef DoublyLinkedList<DwarfFile> FileList;
|
typedef DoublyLinkedList<DwarfFile> FileList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uint8 fAddressSize;
|
||||||
BLocker fLock;
|
BLocker fLock;
|
||||||
FileList fFiles;
|
FileList fFiles;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user