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:
parent
dc95dfe60b
commit
5bda396ef4
@ -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);
|
|
||||||
}
|
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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(
|
||||||
|
Loading…
Reference in New Issue
Block a user