- When attempting to unwind the call frame, we now search for the appropriate
  FDE in both .debug_frame and .eh_frame. This mirrors gdb's behavior and
  works around the ever-changing whims of the gcc developers as to which
  section the requisite FDE/CIE resides in.
This commit is contained in:
Rene Gollent
2012-07-11 19:12:59 -04:00
parent 2218c029a5
commit dfa21dfeab
3 changed files with 68 additions and 46 deletions
@@ -1,5 +1,6 @@
/* /*
* Copyright 2009, Ingo Weinhold, [email protected]. * Copyright 2009, Ingo Weinhold, [email protected].
* Copyright 2012, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -554,8 +555,22 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
= cpuState->InstructionPointer() - fRelocationDelta; = cpuState->InstructionPointer() - fRelocationDelta;
target_addr_t framePointer; target_addr_t framePointer;
CompilationUnit* unit = function->GetCompilationUnit(); CompilationUnit* unit = function->GetCompilationUnit();
error = fFile->UnwindCallFrame(unit, function->SubprogramEntry(), // first try .debug_frame
instructionPointer, inputInterface, outputInterface, framePointer); if (fFile->HasDebugFrameSection()) {
error = fFile->UnwindCallFrame(false, unit,
function->SubprogramEntry(), instructionPointer, inputInterface,
outputInterface, framePointer);
} else
error = B_ENTRY_NOT_FOUND;
// if that section isn't present, or we couldn't find a match,
// try .eh_frame if possible.
if (error == B_ENTRY_NOT_FOUND && fFile->HasEHFrameSection()) {
error = fFile->UnwindCallFrame(true, unit,
function->SubprogramEntry(), instructionPointer, inputInterface,
outputInterface, framePointer);
}
if (error != B_OK) { if (error != B_OK) {
TRACE_CFI("Failed to unwind call frame: %s\n", strerror(error)); TRACE_CFI("Failed to unwind call frame: %s\n", strerror(error));
return B_UNSUPPORTED; return B_UNSUPPORTED;
+37 -40
View File
@@ -1,5 +1,6 @@
/* /*
* Copyright 2009-2010, Ingo Weinhold, [email protected]. * Copyright 2009-2010, Ingo Weinhold, [email protected].
* Copyright 2012, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -287,12 +288,11 @@ DwarfFile::DwarfFile()
fDebugRangesSection(NULL), fDebugRangesSection(NULL),
fDebugLineSection(NULL), fDebugLineSection(NULL),
fDebugFrameSection(NULL), fDebugFrameSection(NULL),
fEHFrameSection(NULL),
fDebugLocationSection(NULL), fDebugLocationSection(NULL),
fDebugPublicTypesSection(NULL), fDebugPublicTypesSection(NULL),
fCompilationUnits(20, true), fCompilationUnits(20, true),
fCurrentCompilationUnit(NULL), fCurrentCompilationUnit(NULL),
fUsingEHFrameSection(false),
fGCC4EHFrameSection(false),
fFinished(false), fFinished(false),
fFinishError(B_OK) fFinishError(B_OK)
{ {
@@ -311,6 +311,7 @@ DwarfFile::~DwarfFile()
fElfFile->PutSection(fDebugRangesSection); fElfFile->PutSection(fDebugRangesSection);
fElfFile->PutSection(fDebugLineSection); fElfFile->PutSection(fDebugLineSection);
fElfFile->PutSection(fDebugFrameSection); fElfFile->PutSection(fDebugFrameSection);
fElfFile->PutSection(fEHFrameSection);
fElfFile->PutSection(fDebugLocationSection); fElfFile->PutSection(fDebugLocationSection);
fElfFile->PutSection(fDebugPublicTypesSection); fElfFile->PutSection(fDebugPublicTypesSection);
delete fElfFile; delete fElfFile;
@@ -350,26 +351,7 @@ DwarfFile::Load(const char* fileName)
fDebugRangesSection = fElfFile->GetSection(".debug_ranges"); fDebugRangesSection = fElfFile->GetSection(".debug_ranges");
fDebugLineSection = fElfFile->GetSection(".debug_line"); fDebugLineSection = fElfFile->GetSection(".debug_line");
fDebugFrameSection = fElfFile->GetSection(".debug_frame"); fDebugFrameSection = fElfFile->GetSection(".debug_frame");
ElfSection* ehFrameSection = fElfFile->GetSection(".eh_frame"); fEHFrameSection = fElfFile->GetSection(".eh_frame");
if (fDebugFrameSection != NULL && ehFrameSection != NULL) {
if (ehFrameSection->Size() > fDebugFrameSection->Size()) {
fElfFile->PutSection(fDebugFrameSection);
fDebugFrameSection = ehFrameSection;
fUsingEHFrameSection = true;
} else
fElfFile->PutSection(ehFrameSection);
} else if (ehFrameSection != NULL) {
fDebugFrameSection = ehFrameSection;
fUsingEHFrameSection = true;
}
if (fUsingEHFrameSection) {
fGCC4EHFrameSection = !fDebugFrameSection->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.
}
fDebugLocationSection = fElfFile->GetSection(".debug_loc"); fDebugLocationSection = fElfFile->GetSection(".debug_loc");
fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubtypes"); fDebugPublicTypesSection = fElfFile->GetSection(".debug_pubtypes");
@@ -553,18 +535,31 @@ DwarfFile::ResolveRangeList(CompilationUnit* unit, uint64 offset) const
status_t status_t
DwarfFile::UnwindCallFrame(CompilationUnit* unit, DwarfFile::UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit,
DIESubprogram* subprogramEntry, target_addr_t location, DIESubprogram* subprogramEntry, target_addr_t location,
const DwarfTargetInterface* inputInterface, const DwarfTargetInterface* inputInterface,
DwarfTargetInterface* outputInterface, target_addr_t& _framePointer) DwarfTargetInterface* outputInterface, target_addr_t& _framePointer)
{ {
if (fDebugFrameSection == NULL) ElfSection* currentFrameSection = (usingEHFrameSection)
? fEHFrameSection : fDebugFrameSection;
if (currentFrameSection == NULL)
return B_ENTRY_NOT_FOUND; 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(%#llx)\n", location); TRACE_CFI("DwarfFile::UnwindCallFrame(%#llx)\n", location);
DataReader dataReader((uint8*)fDebugFrameSection->Data(), DataReader dataReader((uint8*)currentFrameSection->Data(),
fDebugFrameSection->Size(), unit->AddressSize()); currentFrameSection->Size(), unit->AddressSize());
while (dataReader.BytesRemaining() > 0) { while (dataReader.BytesRemaining() > 0) {
// length // length
@@ -584,7 +579,7 @@ DwarfFile::UnwindCallFrame(CompilationUnit* unit,
? dataReader.Read<uint64>(0) : dataReader.Read<uint32>(0); ? dataReader.Read<uint64>(0) : dataReader.Read<uint32>(0);
// In .debug_frame ~0 indicates a CIE, in .eh_frame 0 does. // In .debug_frame ~0 indicates a CIE, in .eh_frame 0 does.
if (fUsingEHFrameSection if (usingEHFrameSection
? cieID == 0 ? cieID == 0
: (dwarf64 : (dwarf64
? cieID == 0xffffffffffffffffULL ? cieID == 0xffffffffffffffffULL
@@ -601,16 +596,16 @@ DwarfFile::UnwindCallFrame(CompilationUnit* unit,
// In the GCC 4 .eh_frame initialLocation is relative to the offset // In the GCC 4 .eh_frame initialLocation is relative to the offset
// of the address. // of the address.
if (fUsingEHFrameSection && fGCC4EHFrameSection) { if (usingEHFrameSection && gcc4EHFrameSection) {
// Note: We need to cast to the exact address width, since the // Note: We need to cast to the exact address width, since the
// initialLocation value can be (and likely is) negative. // initialLocation value can be (and likely is) negative.
if (dwarf64) { if (dwarf64) {
initialLocation = (uint64)fDebugFrameSection->LoadAddress() initialLocation = (uint64)currentFrameSection
+ (uint64)initialLocationOffset ->LoadAddress() + (uint64)initialLocationOffset
+ (uint64)initialLocation; + (uint64)initialLocation;
} else { } else {
initialLocation = (uint32)fDebugFrameSection->LoadAddress() initialLocation = (uint32)currentFrameSection
+ (uint32)initialLocationOffset ->LoadAddress() + (uint32)initialLocationOffset
+ (uint32)initialLocation; + (uint32)initialLocation;
} }
} }
@@ -634,7 +629,7 @@ DwarfFile::UnwindCallFrame(CompilationUnit* unit,
return B_BAD_DATA; return B_BAD_DATA;
// In .eh_frame the CIE offset is a relative back offset. // In .eh_frame the CIE offset is a relative back offset.
if (fUsingEHFrameSection) { if (usingEHFrameSection) {
if (cieID > (uint64)lengthOffset) { if (cieID > (uint64)lengthOffset) {
TRACE_CFI("Invalid CIE offset: %" B_PRIu64 ", max " TRACE_CFI("Invalid CIE offset: %" B_PRIu64 ", max "
"possible: %" B_PRIu64 "\n", cieID, lengthOffset); "possible: %" B_PRIu64 "\n", cieID, lengthOffset);
@@ -660,7 +655,8 @@ DwarfFile::UnwindCallFrame(CompilationUnit* unit,
// process the CIE // process the CIE
CIEAugmentation cieAugmentation; CIEAugmentation cieAugmentation;
error = _ParseCIE(unit, context, cieID, cieAugmentation); error = _ParseCIE(currentFrameSection, usingEHFrameSection,
unit, context, cieID, cieAugmentation);
if (error != B_OK) if (error != B_OK)
return error; return error;
@@ -1554,14 +1550,15 @@ DwarfFile::_ParseLineInfo(CompilationUnit* unit)
status_t status_t
DwarfFile::_ParseCIE(CompilationUnit* unit, CfaContext& context, DwarfFile::_ParseCIE(ElfSection* debugFrameSection, bool usingEHFrameSection,
off_t cieOffset, CIEAugmentation& cieAugmentation) CompilationUnit* unit, CfaContext& context, off_t cieOffset,
CIEAugmentation& cieAugmentation)
{ {
if (cieOffset < 0 || cieOffset >= fDebugFrameSection->Size()) if (cieOffset < 0 || cieOffset >= debugFrameSection->Size())
return B_BAD_DATA; return B_BAD_DATA;
DataReader dataReader((uint8*)fDebugFrameSection->Data() + cieOffset, DataReader dataReader((uint8*)debugFrameSection->Data() + cieOffset,
fDebugFrameSection->Size() - cieOffset, unit->AddressSize()); debugFrameSection->Size() - cieOffset, unit->AddressSize());
// length // length
bool dwarf64; bool dwarf64;
@@ -1573,7 +1570,7 @@ DwarfFile::_ParseCIE(CompilationUnit* unit, CfaContext& context,
// CIE ID/CIE pointer // CIE ID/CIE pointer
uint64 cieID = dwarf64 uint64 cieID = dwarf64
? dataReader.Read<uint64>(0) : dataReader.Read<uint32>(0); ? dataReader.Read<uint64>(0) : dataReader.Read<uint32>(0);
if (fUsingEHFrameSection) { if (usingEHFrameSection) {
if (cieID != 0) if (cieID != 0)
return B_BAD_DATA; return B_BAD_DATA;
} else { } else {
+14 -4
View File
@@ -1,5 +1,6 @@
/* /*
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2012, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef DWARF_FILE_H #ifndef DWARF_FILE_H
@@ -38,6 +39,13 @@ public:
const char* Name() const { return fName; } const char* Name() const { return fName; }
ElfFile* GetElfFile() const { return fElfFile; } ElfFile* GetElfFile() const { return fElfFile; }
bool HasDebugFrameSection() const {
return fDebugFrameSection != NULL;
}
bool HasEHFrameSection() const {
return fEHFrameSection != NULL;
}
int32 CountCompilationUnits() const; int32 CountCompilationUnits() const;
CompilationUnit* CompilationUnitAt(int32 index) const; CompilationUnit* CompilationUnitAt(int32 index) const;
CompilationUnit* CompilationUnitForDIE( CompilationUnit* CompilationUnitForDIE(
@@ -46,7 +54,8 @@ public:
TargetAddressRangeList* ResolveRangeList(CompilationUnit* unit, TargetAddressRangeList* ResolveRangeList(CompilationUnit* unit,
uint64 offset) const; uint64 offset) const;
status_t UnwindCallFrame(CompilationUnit* unit, status_t UnwindCallFrame(bool usingEHFrameSection,
CompilationUnit* unit,
DIESubprogram* subprogramEntry, DIESubprogram* subprogramEntry,
target_addr_t location, target_addr_t location,
const DwarfTargetInterface* inputInterface, const DwarfTargetInterface* inputInterface,
@@ -112,7 +121,9 @@ private:
status_t _ParseLineInfo(CompilationUnit* unit); status_t _ParseLineInfo(CompilationUnit* unit);
status_t _ParseCIE(CompilationUnit* unit, status_t _ParseCIE(ElfSection* debugFrameSection,
bool usingEHFrameSection,
CompilationUnit* unit,
CfaContext& context, off_t cieOffset, CfaContext& context, off_t cieOffset,
CIEAugmentation& cieAugmentation); CIEAugmentation& cieAugmentation);
status_t _ParseFrameInfoInstructions( status_t _ParseFrameInfoInstructions(
@@ -151,14 +162,13 @@ private:
ElfSection* fDebugRangesSection; ElfSection* fDebugRangesSection;
ElfSection* fDebugLineSection; ElfSection* fDebugLineSection;
ElfSection* fDebugFrameSection; ElfSection* fDebugFrameSection;
ElfSection* fEHFrameSection;
ElfSection* fDebugLocationSection; ElfSection* fDebugLocationSection;
ElfSection* fDebugPublicTypesSection; ElfSection* fDebugPublicTypesSection;
AbbreviationTableList fAbbreviationTables; AbbreviationTableList fAbbreviationTables;
DebugInfoEntryFactory fDebugInfoFactory; DebugInfoEntryFactory fDebugInfoFactory;
CompilationUnitList fCompilationUnits; CompilationUnitList fCompilationUnits;
CompilationUnit* fCurrentCompilationUnit; CompilationUnit* fCurrentCompilationUnit;
bool fUsingEHFrameSection;
bool fGCC4EHFrameSection;
bool fFinished; bool fFinished;
status_t fFinishError; status_t fFinishError;
}; };