Refactor Dwarf*DebugInfo to be able to work with limited info.

- DwarfImageDebugInfo and DwarfFile will now allow us to construct
  DWARF debug info objects even if the only section available for
  use is .eh_frame. This essentially allows us to use CFI-based
  unwinding even for release executables (assuming C++ is involved),
  which means we can properly unwind the stack even for binaries
  compiled with fomit-frame-pointer. This becomes more important
  for x86-64, since omit is the ABI default there.

- Pull a GetFunctionsFromSymbols() out of DebuggerImageDebugInfo. This
  is shared between DebuggerImageDebugInfo and DwarfImageDebugInfo for
  creating debug information entries in the absence of debugging
  information.
This commit is contained in:
Rene Gollent 2012-12-16 10:59:12 -05:00
parent dc95dfe60b
commit 5bda396ef4
10 changed files with 174 additions and 107 deletions

View File

@ -44,39 +44,8 @@ DebuggerImageDebugInfo::Init()
status_t status_t
DebuggerImageDebugInfo::GetFunctions(BObjectList<FunctionDebugInfo>& functions) DebuggerImageDebugInfo::GetFunctions(BObjectList<FunctionDebugInfo>& functions)
{ {
BObjectList<SymbolInfo> symbols(20, true); return SpecificImageDebugInfo::GetFunctionsFromSymbols(functions,
status_t error = fDebuggerInterface->GetSymbolInfos(fImageInfo.TeamID(), fDebuggerInterface, fImageInfo, this);
fImageInfo.ImageID(), symbols);
if (error != B_OK)
return error;
// sort the symbols -- not necessary, but a courtesy to ImageDebugInfo which
// will peform better when inserting functions at the end of a list
symbols.SortItems(&_CompareSymbols);
// create the function infos
int32 functionsAdded = 0;
for (int32 i = 0; SymbolInfo* symbol = symbols.ItemAt(i); i++) {
if (symbol->Type() != B_SYMBOL_TYPE_TEXT)
continue;
FunctionDebugInfo* function = new(std::nothrow) BasicFunctionDebugInfo(
this, symbol->Address(), symbol->Size(), symbol->Name(),
Demangler::Demangle(symbol->Name()));
if (function == NULL || !functions.AddItem(function)) {
delete function;
int32 index = functions.CountItems() - 1;
for (; functionsAdded >= 0; functionsAdded--, index--) {
function = functions.RemoveItemAt(index);
delete function;
}
return B_NO_MEMORY;
}
functionsAdded++;
}
return B_OK;
} }
@ -144,12 +113,3 @@ DebuggerImageDebugInfo::AddSourceCodeInfo(LocatableFile* file,
{ {
return B_UNSUPPORTED; return B_UNSUPPORTED;
} }
/*static*/ int
DebuggerImageDebugInfo::_CompareSymbols(const SymbolInfo* a,
const SymbolInfo* b)
{
return a->Address() < b->Address()
? -1 : (a->Address() == b->Address() ? 0 : 1);
}

View File

@ -54,10 +54,6 @@ public:
virtual status_t AddSourceCodeInfo(LocatableFile* file, virtual status_t AddSourceCodeInfo(LocatableFile* file,
FileSourceCode* sourceCode); FileSourceCode* sourceCode);
private:
static int _CompareSymbols(const SymbolInfo* a,
const SymbolInfo* b);
private: private:
ImageInfo fImageInfo; ImageInfo fImageInfo;
DebuggerInterface* fDebuggerInterface; DebuggerInterface* fDebuggerInterface;

View File

@ -18,11 +18,14 @@
#include <AutoLocker.h> #include <AutoLocker.h>
#include "Architecture.h" #include "Architecture.h"
#include "BasicFunctionDebugInfo.h"
#include "CLanguage.h" #include "CLanguage.h"
#include "CompilationUnit.h" #include "CompilationUnit.h"
#include "CppLanguage.h" #include "CppLanguage.h"
#include "CpuState.h" #include "CpuState.h"
#include "DebuggerInterface.h"
#include "DebugInfoEntries.h" #include "DebugInfoEntries.h"
#include "Demangler.h"
#include "Dwarf.h" #include "Dwarf.h"
#include "DwarfFile.h" #include "DwarfFile.h"
#include "DwarfFunctionDebugInfo.h" #include "DwarfFunctionDebugInfo.h"
@ -44,6 +47,7 @@
#include "StackFrame.h" #include "StackFrame.h"
#include "Statement.h" #include "Statement.h"
#include "StringUtils.h" #include "StringUtils.h"
#include "SymbolInfo.h"
#include "TargetAddressRangeList.h" #include "TargetAddressRangeList.h"
#include "TeamMemory.h" #include "TeamMemory.h"
#include "Tracing.h" #include "Tracing.h"
@ -226,14 +230,14 @@ struct DwarfImageDebugInfo::EntryListWrapper {
DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo, DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
Architecture* architecture, TeamMemory* teamMemory, DebuggerInterface* interface, Architecture* architecture,
FileManager* fileManager, GlobalTypeLookup* typeLookup, FileManager* fileManager, GlobalTypeLookup* typeLookup,
GlobalTypeCache* typeCache, DwarfFile* file) GlobalTypeCache* typeCache, DwarfFile* file)
: :
fLock("dwarf image debug info"), fLock("dwarf image debug info"),
fImageInfo(imageInfo), fImageInfo(imageInfo),
fDebuggerInterface(interface),
fArchitecture(architecture), fArchitecture(architecture),
fTeamMemory(teamMemory),
fFileManager(fileManager), fFileManager(fileManager),
fTypeLookup(typeLookup), fTypeLookup(typeLookup),
fTypeCache(typeCache), fTypeCache(typeCache),
@ -245,6 +249,7 @@ DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
fPLTSectionStart(0), fPLTSectionStart(0),
fPLTSectionEnd(0) fPLTSectionEnd(0)
{ {
fDebuggerInterface->AcquireReference();
fFile->AcquireReference(); fFile->AcquireReference();
fTypeCache->AcquireReference(); fTypeCache->AcquireReference();
} }
@ -252,6 +257,7 @@ DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
DwarfImageDebugInfo::~DwarfImageDebugInfo() DwarfImageDebugInfo::~DwarfImageDebugInfo()
{ {
fDebuggerInterface->ReleaseReference();
fFile->ReleaseReference(); fFile->ReleaseReference();
fTypeCache->ReleaseReference(); fTypeCache->ReleaseReference();
} }
@ -397,7 +403,13 @@ DwarfImageDebugInfo::GetFunctions(BObjectList<FunctionDebugInfo>& functions)
} }
} }
return B_OK; if (fFile->CountCompilationUnits() != 0)
return B_OK;
// if we had no compilation units, fall back to providing basic
// debug infos with DWARF-supported call frame unwinding
return SpecificImageDebugInfo::GetFunctionsFromSymbols(functions,
fDebuggerInterface, fImageInfo, this);
} }
@ -419,7 +431,7 @@ DwarfImageDebugInfo::GetType(GlobalTypeCache* cache,
// create the target interface // create the target interface
BasicTargetInterface *inputInterface BasicTargetInterface *inputInterface
= new(std::nothrow) BasicTargetInterface(registers, registerCount, = new(std::nothrow) BasicTargetInterface(registers, registerCount,
fromDwarfMap, fArchitecture, fTeamMemory); fromDwarfMap, fArchitecture, fDebuggerInterface);
if (inputInterface == NULL) if (inputInterface == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@ -508,16 +520,17 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
{ {
DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>( DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>(
functionInstance->GetFunctionDebugInfo()); functionInstance->GetFunctionDebugInfo());
if (function == NULL)
return B_BAD_VALUE;
FunctionID* functionID = functionInstance->GetFunctionID(); FunctionID* functionID = functionInstance->GetFunctionID();
if (functionID == NULL) BReference<FunctionID> functionIDReference;
return B_NO_MEMORY; if (functionID != NULL)
BReference<FunctionID> functionIDReference(functionID, true); functionIDReference.SetTo(functionID, true);
DIESubprogram* entry = function != NULL
? function->SubprogramEntry() : NULL;
TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p, " TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p, "
"function: %s\n", function->SubprogramEntry(), "function: %s\n", entry,
functionID->FunctionName().String()); functionID->FunctionName().String());
int32 registerCount = fArchitecture->CountRegisters(); int32 registerCount = fArchitecture->CountRegisters();
@ -543,7 +556,8 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
// create the target interfaces // create the target interfaces
UnwindTargetInterface* inputInterface UnwindTargetInterface* inputInterface
= new(std::nothrow) UnwindTargetInterface(registers, registerCount, = new(std::nothrow) UnwindTargetInterface(registers, registerCount,
fromDwarfMap, toDwarfMap, cpuState, fArchitecture, fTeamMemory); fromDwarfMap, toDwarfMap, cpuState, fArchitecture,
fDebuggerInterface);
if (inputInterface == NULL) if (inputInterface == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
BReference<UnwindTargetInterface> inputInterfaceReference(inputInterface, BReference<UnwindTargetInterface> inputInterfaceReference(inputInterface,
@ -552,7 +566,7 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
UnwindTargetInterface* outputInterface UnwindTargetInterface* outputInterface
= new(std::nothrow) UnwindTargetInterface(registers, registerCount, = new(std::nothrow) UnwindTargetInterface(registers, registerCount,
fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture,
fTeamMemory); fDebuggerInterface);
if (outputInterface == NULL) if (outputInterface == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
BReference<UnwindTargetInterface> outputInterfaceReference(outputInterface, BReference<UnwindTargetInterface> outputInterfaceReference(outputInterface,
@ -562,8 +576,9 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
target_addr_t instructionPointer target_addr_t instructionPointer
= cpuState->InstructionPointer() - fRelocationDelta; = cpuState->InstructionPointer() - fRelocationDelta;
target_addr_t framePointer; target_addr_t framePointer;
CompilationUnit* unit = function->GetCompilationUnit(); CompilationUnit* unit = function != NULL ? function->GetCompilationUnit()
error = fFile->UnwindCallFrame(unit, function->SubprogramEntry(), : NULL;
error = fFile->UnwindCallFrame(unit, fArchitecture->AddressSize(), entry,
instructionPointer, inputInterface, outputInterface, framePointer); instructionPointer, inputInterface, outputInterface, framePointer);
if (error != B_OK) { if (error != B_OK) {
@ -585,7 +600,8 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
) )
// create the stack frame debug info // create the stack frame debug info
DIESubprogram* subprogramEntry = function->SubprogramEntry(); DIESubprogram* subprogramEntry = function != NULL ?
function->SubprogramEntry() : NULL;
DwarfStackFrameDebugInfo* stackFrameDebugInfo DwarfStackFrameDebugInfo* stackFrameDebugInfo
= new(std::nothrow) DwarfStackFrameDebugInfo(fArchitecture, = new(std::nothrow) DwarfStackFrameDebugInfo(fArchitecture,
fImageInfo.ImageID(), fFile, unit, subprogramEntry, fTypeLookup, fImageInfo.ImageID(), fFile, unit, subprogramEntry, fTypeLookup,
@ -616,35 +632,41 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
// Note, this is correct, since we actually retrieved the return // Note, this is correct, since we actually retrieved the return
// address. Our caller will fix the IP for us. // address. Our caller will fix the IP for us.
// create function parameter objects // The subprogram entry may not be available since this may be a case
for (DebugInfoEntryList::ConstIterator it = subprogramEntry->Parameters() // where .eh_frame was used to unwind the stack without other DWARF
.GetIterator(); DebugInfoEntry* entry = it.Next();) { // info being available.
if (entry->Tag() != DW_TAG_formal_parameter) if (subprogramEntry != NULL) {
continue; // create function parameter objects
for (DebugInfoEntryList::ConstIterator it
= subprogramEntry->Parameters().GetIterator();
DebugInfoEntry* entry = it.Next();) {
if (entry->Tag() != DW_TAG_formal_parameter)
continue;
BString parameterName; BString parameterName;
DwarfUtils::GetDIEName(entry, parameterName); DwarfUtils::GetDIEName(entry, parameterName);
if (parameterName.Length() == 0) if (parameterName.Length() == 0)
continue; continue;
DIEFormalParameter* parameterEntry DIEFormalParameter* parameterEntry
= dynamic_cast<DIEFormalParameter*>(entry); = dynamic_cast<DIEFormalParameter*>(entry);
Variable* parameter; Variable* parameter;
if (stackFrameDebugInfo->CreateParameter(functionID, parameterEntry, if (stackFrameDebugInfo->CreateParameter(functionID,
parameter) != B_OK) { parameterEntry, parameter) != B_OK) {
continue; continue;
}
BReference<Variable> parameterReference(parameter, true);
if (!frame->AddParameter(parameter))
return B_NO_MEMORY;
} }
BReference<Variable> parameterReference(parameter, true);
if (!frame->AddParameter(parameter)) // create objects for the local variables
return B_NO_MEMORY; _CreateLocalVariables(unit, frame, functionID, *stackFrameDebugInfo,
instructionPointer, functionInstance->Address() - fRelocationDelta,
subprogramEntry->Variables(), subprogramEntry->Blocks());
} }
// create objects for the local variables
_CreateLocalVariables(unit, frame, functionID, *stackFrameDebugInfo,
instructionPointer, functionInstance->Address() - fRelocationDelta,
subprogramEntry->Variables(), subprogramEntry->Blocks());
_frame = frameReference.Detach(); _frame = frameReference.Detach();
_previousCpuState = previousCpuStateReference.Detach(); _previousCpuState = previousCpuStateReference.Detach();

View File

@ -1,6 +1,6 @@
/* /*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2010, Rene Gollent, rene@gollent.com. * Copyright 2010-2012, Rene Gollent, rene@gollent.com.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef DWARF_IMAGE_DEBUG_INFO_H #ifndef DWARF_IMAGE_DEBUG_INFO_H
@ -19,6 +19,7 @@
class Architecture; class Architecture;
class CompilationUnit; class CompilationUnit;
class DebuggerInterface;
class DIEType; class DIEType;
class DwarfStackFrameDebugInfo; class DwarfStackFrameDebugInfo;
class DwarfFile; class DwarfFile;
@ -30,14 +31,13 @@ class GlobalTypeCache;
class GlobalTypeLookup; class GlobalTypeLookup;
class LocatableFile; class LocatableFile;
class SourceCode; class SourceCode;
class TeamMemory;
class DwarfImageDebugInfo : public SpecificImageDebugInfo { class DwarfImageDebugInfo : public SpecificImageDebugInfo {
public: public:
DwarfImageDebugInfo(const ImageInfo& imageInfo, DwarfImageDebugInfo(const ImageInfo& imageInfo,
DebuggerInterface* interface,
Architecture* architecture, Architecture* architecture,
TeamMemory* teamMemory,
FileManager* fileManager, FileManager* fileManager,
GlobalTypeLookup* typeLookup, GlobalTypeLookup* typeLookup,
GlobalTypeCache* typeCache, GlobalTypeCache* typeCache,
@ -106,8 +106,8 @@ private:
private: private:
BLocker fLock; BLocker fLock;
ImageInfo fImageInfo; ImageInfo fImageInfo;
DebuggerInterface* fDebuggerInterface;
Architecture* fArchitecture; Architecture* fArchitecture;
TeamMemory* fTeamMemory;
FileManager* fFileManager; FileManager* fFileManager;
GlobalTypeLookup* fTypeLookup; GlobalTypeLookup* fTypeLookup;
GlobalTypeCache* fTypeCache; GlobalTypeCache* fTypeCache;

View File

@ -9,6 +9,7 @@
#include <string.h> #include <string.h>
#include "DebuggerInterface.h"
#include "DwarfFile.h" #include "DwarfFile.h"
#include "DwarfImageDebugInfo.h" #include "DwarfImageDebugInfo.h"
#include "DwarfManager.h" #include "DwarfManager.h"
@ -17,22 +18,24 @@
DwarfTeamDebugInfo::DwarfTeamDebugInfo(Architecture* architecture, DwarfTeamDebugInfo::DwarfTeamDebugInfo(Architecture* architecture,
TeamMemory* teamMemory, FileManager* fileManager, DebuggerInterface* interface, FileManager* fileManager,
GlobalTypeLookup* typeLookup, GlobalTypeCache* typeCache) GlobalTypeLookup* typeLookup, GlobalTypeCache* typeCache)
: :
fArchitecture(architecture), fArchitecture(architecture),
fTeamMemory(teamMemory), fDebuggerInterface(interface),
fFileManager(fileManager), fFileManager(fileManager),
fManager(NULL), fManager(NULL),
fTypeLookup(typeLookup), fTypeLookup(typeLookup),
fTypeCache(typeCache) fTypeCache(typeCache)
{ {
fDebuggerInterface->AcquireReference();
fTypeCache->AcquireReference(); fTypeCache->AcquireReference();
} }
DwarfTeamDebugInfo::~DwarfTeamDebugInfo() DwarfTeamDebugInfo::~DwarfTeamDebugInfo()
{ {
fDebuggerInterface->ReleaseReference();
fTypeCache->ReleaseReference(); fTypeCache->ReleaseReference();
delete fManager; delete fManager;
} }
@ -75,8 +78,8 @@ DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo,
// create the image debug info // create the image debug info
DwarfImageDebugInfo* debugInfo = new(std::nothrow) DwarfImageDebugInfo( DwarfImageDebugInfo* debugInfo = new(std::nothrow) DwarfImageDebugInfo(
imageInfo, fArchitecture, fTeamMemory, fFileManager, fTypeLookup, imageInfo, fDebuggerInterface, fArchitecture, fFileManager,
fTypeCache, file); fTypeLookup, fTypeCache, file);
if (debugInfo == NULL) if (debugInfo == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;

View File

@ -9,6 +9,7 @@
class Architecture; class Architecture;
class DebuggerInterface;
class DwarfManager; class DwarfManager;
class FileManager; class FileManager;
class ImageInfo; class ImageInfo;
@ -20,7 +21,7 @@ class TeamMemory;
class DwarfTeamDebugInfo : public SpecificTeamDebugInfo { class DwarfTeamDebugInfo : public SpecificTeamDebugInfo {
public: public:
DwarfTeamDebugInfo(Architecture* architecture, DwarfTeamDebugInfo(Architecture* architecture,
TeamMemory* teamMemory, DebuggerInterface* interface,
FileManager* fileManager, FileManager* fileManager,
GlobalTypeLookup* typeLookup, GlobalTypeLookup* typeLookup,
GlobalTypeCache* typeCache); GlobalTypeCache* typeCache);
@ -34,7 +35,7 @@ public:
private: private:
Architecture* fArchitecture; Architecture* fArchitecture;
TeamMemory* fTeamMemory; DebuggerInterface* fDebuggerInterface;
FileManager* fFileManager; FileManager* fFileManager;
DwarfManager* fManager; DwarfManager* fManager;
GlobalTypeLookup* fTypeLookup; GlobalTypeLookup* fTypeLookup;

View File

@ -5,7 +5,62 @@
#include "SpecificImageDebugInfo.h" #include "SpecificImageDebugInfo.h"
#include "BasicFunctionDebugInfo.h"
#include "DebuggerInterface.h"
#include "Demangler.h"
#include "ImageInfo.h"
#include "SymbolInfo.h"
SpecificImageDebugInfo::~SpecificImageDebugInfo() SpecificImageDebugInfo::~SpecificImageDebugInfo()
{ {
} }
/*static*/ status_t
SpecificImageDebugInfo::GetFunctionsFromSymbols(
BObjectList<FunctionDebugInfo>& functions, DebuggerInterface* interface,
const ImageInfo& imageInfo, SpecificImageDebugInfo* info)
{
BObjectList<SymbolInfo> symbols(20, true);
status_t error = interface->GetSymbolInfos(imageInfo.TeamID(),
imageInfo.ImageID(), symbols);
if (error != B_OK)
return error;
// sort the symbols -- not necessary, but a courtesy to ImageDebugInfo which
// will peform better when inserting functions at the end of a list
symbols.SortItems(&_CompareSymbols);
// create the function infos
int32 functionsAdded = 0;
for (int32 i = 0; SymbolInfo* symbol = symbols.ItemAt(i); i++) {
if (symbol->Type() != B_SYMBOL_TYPE_TEXT)
continue;
FunctionDebugInfo* function = new(std::nothrow) BasicFunctionDebugInfo(
info, symbol->Address(), symbol->Size(), symbol->Name(),
Demangler::Demangle(symbol->Name()));
if (function == NULL || !functions.AddItem(function)) {
delete function;
int32 index = functions.CountItems() - 1;
for (; functionsAdded >= 0; functionsAdded--, index--) {
function = functions.RemoveItemAt(index);
delete function;
}
return B_NO_MEMORY;
}
functionsAdded++;
}
return B_OK;
}
/*static*/ int
SpecificImageDebugInfo::_CompareSymbols(const SymbolInfo* a,
const SymbolInfo* b)
{
return a->Address() < b->Address()
? -1 : (a->Address() == b->Address() ? 0 : 1);
}

View File

@ -23,11 +23,13 @@ class FunctionDebugInfo;
class FunctionInstance; class FunctionInstance;
class GlobalTypeCache; class GlobalTypeCache;
class Image; class Image;
class ImageInfo;
class LocatableFile; class LocatableFile;
class SourceLanguage; class SourceLanguage;
class SourceLocation; class SourceLocation;
class StackFrame; class StackFrame;
class Statement; class Statement;
class SymbolInfo;
class Type; class Type;
class TypeLookupConstraints; class TypeLookupConstraints;
class ValueLocation; class ValueLocation;
@ -76,6 +78,17 @@ public:
virtual status_t AddSourceCodeInfo(LocatableFile* file, virtual status_t AddSourceCodeInfo(LocatableFile* file,
FileSourceCode* sourceCode) = 0; FileSourceCode* sourceCode) = 0;
protected:
static status_t GetFunctionsFromSymbols(
BObjectList<FunctionDebugInfo>& functions,
DebuggerInterface* interface,
const ImageInfo& imageInfo,
SpecificImageDebugInfo* info);
private:
static int _CompareSymbols(const SymbolInfo* a,
const SymbolInfo* b);
}; };

View File

@ -386,10 +386,16 @@ DwarfFile::Load(const char* fileName)
// .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
fEHFrameSection = fElfFile->GetSection(".eh_frame"); if (fEHFrameSection == NULL)
fEHFrameSection = fElfFile->GetSection(".eh_frame");
fDebugLocationSection = debugInfoFile->GetSection(".debug_loc"); fDebugLocationSection = debugInfoFile->GetSection(".debug_loc");
fDebugPublicTypesSection = debugInfoFile->GetSection(".debug_pubtypes"); fDebugPublicTypesSection = debugInfoFile->GetSection(".debug_pubtypes");
if (fDebugInfoSection == NULL) {
fFinished = true;
return B_OK;
}
// iterate through the debug info section // iterate through the debug info section
DataReader dataReader(fDebugInfoSection->Data(), DataReader dataReader(fDebugInfoSection->Data(),
fDebugInfoSection->Size(), 4); fDebugInfoSection->Size(), 4);
@ -570,7 +576,7 @@ DwarfFile::ResolveRangeList(CompilationUnit* unit, uint64 offset) const
status_t status_t
DwarfFile::UnwindCallFrame(CompilationUnit* unit, DwarfFile::UnwindCallFrame(CompilationUnit* unit, uint8 addressSize,
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)
@ -579,15 +585,15 @@ DwarfFile::UnwindCallFrame(CompilationUnit* unit,
// first try to find the FDE in .debug_frame // first try to find the FDE in .debug_frame
if (fDebugFrameSection != NULL) { if (fDebugFrameSection != NULL) {
result = _UnwindCallFrame(false, unit, subprogramEntry, location, result = _UnwindCallFrame(false, unit, addressSize, subprogramEntry,
inputInterface, outputInterface, _framePointer); location, inputInterface, outputInterface, _framePointer);
} }
// if .debug_frame isn't present, or if the FDE wasn't found there, // if .debug_frame isn't present, or if the FDE wasn't found there,
// try .eh_frame // try .eh_frame
if (result == B_ENTRY_NOT_FOUND && fEHFrameSection != NULL) { if (result == B_ENTRY_NOT_FOUND && fEHFrameSection != NULL) {
result = _UnwindCallFrame(true, unit, subprogramEntry, location, result = _UnwindCallFrame(true, unit, addressSize, subprogramEntry,
inputInterface, outputInterface, _framePointer); location, inputInterface, outputInterface, _framePointer);
} }
return result; return result;
@ -1329,7 +1335,7 @@ DwarfFile::_ParseLineInfo(CompilationUnit* unit)
status_t status_t
DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit, DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit,
DIESubprogram* subprogramEntry, target_addr_t location, uint8 addressSize, DIESubprogram* subprogramEntry, target_addr_t location,
const DwarfTargetInterface* inputInterface, const DwarfTargetInterface* inputInterface,
DwarfTargetInterface* outputInterface, target_addr_t& _framePointer) DwarfTargetInterface* outputInterface, target_addr_t& _framePointer)
{ {
@ -1350,7 +1356,8 @@ DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit,
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->AddressSize()); currentFrameSection->Size(), unit != NULL
? unit->AddressSize() : addressSize);
while (dataReader.BytesRemaining() > 0) { while (dataReader.BytesRemaining() > 0) {
// length // length
@ -1448,7 +1455,7 @@ DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit,
// process the CIE // process the CIE
CIEAugmentation cieAugmentation; CIEAugmentation cieAugmentation;
error = _ParseCIE(currentFrameSection, usingEHFrameSection, error = _ParseCIE(currentFrameSection, usingEHFrameSection,
unit, context, cieID, cieAugmentation); unit, addressSize, context, cieID, cieAugmentation);
if (error != B_OK) if (error != B_OK)
return error; return error;
@ -1618,20 +1625,22 @@ DwarfFile::_UnwindCallFrame(bool usingEHFrameSection, CompilationUnit* unit,
status_t status_t
DwarfFile::_ParseCIE(ElfSection* debugFrameSection, bool usingEHFrameSection, DwarfFile::_ParseCIE(ElfSection* debugFrameSection, bool usingEHFrameSection,
CompilationUnit* unit, CfaContext& context, off_t cieOffset, CompilationUnit* unit, uint8 addressSize, CfaContext& context,
CIEAugmentation& cieAugmentation) off_t cieOffset, CIEAugmentation& cieAugmentation)
{ {
if (cieOffset < 0 || cieOffset >= debugFrameSection->Size()) if (cieOffset < 0 || cieOffset >= debugFrameSection->Size())
return B_BAD_DATA; return B_BAD_DATA;
DataReader dataReader((uint8*)debugFrameSection->Data() + cieOffset, DataReader dataReader((uint8*)debugFrameSection->Data() + cieOffset,
debugFrameSection->Size() - cieOffset, unit->AddressSize()); debugFrameSection->Size() - cieOffset, unit != NULL
? unit->AddressSize() : addressSize);
// length // length
bool dwarf64; bool dwarf64;
uint64 length = dataReader.ReadInitialLength(dwarf64); uint64 length = dataReader.ReadInitialLength(dwarf64);
if (length > (uint64)dataReader.BytesRemaining()) if (length > (uint64)dataReader.BytesRemaining())
return B_BAD_DATA; return B_BAD_DATA;
off_t lengthOffset = dataReader.Offset(); off_t lengthOffset = dataReader.Offset();
// CIE ID/CIE pointer // CIE ID/CIE pointer
@ -2328,7 +2337,12 @@ DwarfFile::_LocateDebugInfo()
if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL) { if (fDebugInfoSection == NULL || fDebugAbbrevSection == NULL) {
WARNING("DwarfManager::File::Load(\"%s\"): no " WARNING("DwarfManager::File::Load(\"%s\"): no "
".debug_info or .debug_abbrev.\n", fName); ".debug_info or .debug_abbrev.\n", fName);
return B_ERROR;
// if we at least have an EH frame, use that for stack unwinding
// if nothing else.
fEHFrameSection = fElfFile->GetSection(".eh_frame");
if (fEHFrameSection == NULL)
return B_ERROR;
} }
return B_OK; return B_OK;

View File

@ -48,6 +48,7 @@ public:
uint64 offset) const; uint64 offset) const;
status_t UnwindCallFrame(CompilationUnit* unit, status_t UnwindCallFrame(CompilationUnit* unit,
uint8 addressSize,
DIESubprogram* subprogramEntry, DIESubprogram* subprogramEntry,
target_addr_t location, target_addr_t location,
const DwarfTargetInterface* inputInterface, const DwarfTargetInterface* inputInterface,
@ -115,6 +116,7 @@ private:
status_t _UnwindCallFrame(bool usingEHFrameSection, status_t _UnwindCallFrame(bool usingEHFrameSection,
CompilationUnit* unit, CompilationUnit* unit,
uint8 addressSize,
DIESubprogram* subprogramEntry, DIESubprogram* subprogramEntry,
target_addr_t location, target_addr_t location,
const DwarfTargetInterface* inputInterface, const DwarfTargetInterface* inputInterface,
@ -124,6 +126,7 @@ private:
status_t _ParseCIE(ElfSection* debugFrameSection, status_t _ParseCIE(ElfSection* debugFrameSection,
bool usingEHFrameSection, bool usingEHFrameSection,
CompilationUnit* unit, CompilationUnit* unit,
uint8 addressSize,
CfaContext& context, off_t cieOffset, CfaContext& context, off_t cieOffset,
CIEAugmentation& cieAugmentation); CIEAugmentation& cieAugmentation);
status_t _ParseFrameInfoInstructions( status_t _ParseFrameInfoInstructions(