Skip to content

Commit

Permalink
Refactor Dwarf*DebugInfo to be able to work with limited info.
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
anevilyak committed Dec 16, 2012
1 parent dc95dfe commit 5bda396
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 107 deletions.
44 changes: 2 additions & 42 deletions src/apps/debugger/debug_info/DebuggerImageDebugInfo.cpp
Expand Up @@ -44,39 +44,8 @@ DebuggerImageDebugInfo::Init()
status_t
DebuggerImageDebugInfo::GetFunctions(BObjectList<FunctionDebugInfo>& functions)
{
BObjectList<SymbolInfo> symbols(20, true);
status_t error = fDebuggerInterface->GetSymbolInfos(fImageInfo.TeamID(),
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;
return SpecificImageDebugInfo::GetFunctionsFromSymbols(functions,
fDebuggerInterface, fImageInfo, this);
}


Expand Down Expand Up @@ -144,12 +113,3 @@ DebuggerImageDebugInfo::AddSourceCodeInfo(LocatableFile* file,
{
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);
}
4 changes: 0 additions & 4 deletions src/apps/debugger/debug_info/DebuggerImageDebugInfo.h
Expand Up @@ -54,10 +54,6 @@ class DebuggerImageDebugInfo : public SpecificImageDebugInfo {
virtual status_t AddSourceCodeInfo(LocatableFile* file,
FileSourceCode* sourceCode);

private:
static int _CompareSymbols(const SymbolInfo* a,
const SymbolInfo* b);

private:
ImageInfo fImageInfo;
DebuggerInterface* fDebuggerInterface;
Expand Down
98 changes: 60 additions & 38 deletions src/apps/debugger/debug_info/DwarfImageDebugInfo.cpp
Expand Up @@ -18,11 +18,14 @@
#include <AutoLocker.h>

#include "Architecture.h"
#include "BasicFunctionDebugInfo.h"
#include "CLanguage.h"
#include "CompilationUnit.h"
#include "CppLanguage.h"
#include "CpuState.h"
#include "DebuggerInterface.h"
#include "DebugInfoEntries.h"
#include "Demangler.h"
#include "Dwarf.h"
#include "DwarfFile.h"
#include "DwarfFunctionDebugInfo.h"
Expand All @@ -44,6 +47,7 @@
#include "StackFrame.h"
#include "Statement.h"
#include "StringUtils.h"
#include "SymbolInfo.h"
#include "TargetAddressRangeList.h"
#include "TeamMemory.h"
#include "Tracing.h"
Expand Down Expand Up @@ -226,14 +230,14 @@ struct DwarfImageDebugInfo::EntryListWrapper {


DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
Architecture* architecture, TeamMemory* teamMemory,
DebuggerInterface* interface, Architecture* architecture,
FileManager* fileManager, GlobalTypeLookup* typeLookup,
GlobalTypeCache* typeCache, DwarfFile* file)
:
fLock("dwarf image debug info"),
fImageInfo(imageInfo),
fDebuggerInterface(interface),
fArchitecture(architecture),
fTeamMemory(teamMemory),
fFileManager(fileManager),
fTypeLookup(typeLookup),
fTypeCache(typeCache),
Expand All @@ -245,13 +249,15 @@ DwarfImageDebugInfo::DwarfImageDebugInfo(const ImageInfo& imageInfo,
fPLTSectionStart(0),
fPLTSectionEnd(0)
{
fDebuggerInterface->AcquireReference();
fFile->AcquireReference();
fTypeCache->AcquireReference();
}


DwarfImageDebugInfo::~DwarfImageDebugInfo()
{
fDebuggerInterface->ReleaseReference();
fFile->ReleaseReference();
fTypeCache->ReleaseReference();
}
Expand Down Expand Up @@ -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);
}


Expand All @@ -419,7 +431,7 @@ DwarfImageDebugInfo::GetType(GlobalTypeCache* cache,
// create the target interface
BasicTargetInterface *inputInterface
= new(std::nothrow) BasicTargetInterface(registers, registerCount,
fromDwarfMap, fArchitecture, fTeamMemory);
fromDwarfMap, fArchitecture, fDebuggerInterface);

if (inputInterface == NULL)
return B_NO_MEMORY;
Expand Down Expand Up @@ -508,16 +520,17 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
{
DwarfFunctionDebugInfo* function = dynamic_cast<DwarfFunctionDebugInfo*>(
functionInstance->GetFunctionDebugInfo());
if (function == NULL)
return B_BAD_VALUE;

FunctionID* functionID = functionInstance->GetFunctionID();
if (functionID == NULL)
return B_NO_MEMORY;
BReference<FunctionID> functionIDReference(functionID, true);
BReference<FunctionID> functionIDReference;
if (functionID != NULL)
functionIDReference.SetTo(functionID, true);

DIESubprogram* entry = function != NULL
? function->SubprogramEntry() : NULL;

TRACE_CFI("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p, "
"function: %s\n", function->SubprogramEntry(),
"function: %s\n", entry,
functionID->FunctionName().String());

int32 registerCount = fArchitecture->CountRegisters();
Expand All @@ -543,7 +556,8 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
// create the target interfaces
UnwindTargetInterface* inputInterface
= new(std::nothrow) UnwindTargetInterface(registers, registerCount,
fromDwarfMap, toDwarfMap, cpuState, fArchitecture, fTeamMemory);
fromDwarfMap, toDwarfMap, cpuState, fArchitecture,
fDebuggerInterface);
if (inputInterface == NULL)
return B_NO_MEMORY;
BReference<UnwindTargetInterface> inputInterfaceReference(inputInterface,
Expand All @@ -552,7 +566,7 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
UnwindTargetInterface* outputInterface
= new(std::nothrow) UnwindTargetInterface(registers, registerCount,
fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture,
fTeamMemory);
fDebuggerInterface);
if (outputInterface == NULL)
return B_NO_MEMORY;
BReference<UnwindTargetInterface> outputInterfaceReference(outputInterface,
Expand All @@ -562,8 +576,9 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
target_addr_t instructionPointer
= cpuState->InstructionPointer() - fRelocationDelta;
target_addr_t framePointer;
CompilationUnit* unit = function->GetCompilationUnit();
error = fFile->UnwindCallFrame(unit, function->SubprogramEntry(),
CompilationUnit* unit = function != NULL ? function->GetCompilationUnit()
: NULL;
error = fFile->UnwindCallFrame(unit, fArchitecture->AddressSize(), entry,
instructionPointer, inputInterface, outputInterface, framePointer);

if (error != B_OK) {
Expand All @@ -585,7 +600,8 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
)

// create the stack frame debug info
DIESubprogram* subprogramEntry = function->SubprogramEntry();
DIESubprogram* subprogramEntry = function != NULL ?
function->SubprogramEntry() : NULL;
DwarfStackFrameDebugInfo* stackFrameDebugInfo
= new(std::nothrow) DwarfStackFrameDebugInfo(fArchitecture,
fImageInfo.ImageID(), fFile, unit, subprogramEntry, fTypeLookup,
Expand Down Expand Up @@ -616,35 +632,41 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
// Note, this is correct, since we actually retrieved the return
// address. Our caller will fix the IP for us.

// create function parameter objects
for (DebugInfoEntryList::ConstIterator it = subprogramEntry->Parameters()
.GetIterator(); DebugInfoEntry* entry = it.Next();) {
if (entry->Tag() != DW_TAG_formal_parameter)
continue;
// The subprogram entry may not be available since this may be a case
// where .eh_frame was used to unwind the stack without other DWARF
// info being available.
if (subprogramEntry != NULL) {
// 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;
DwarfUtils::GetDIEName(entry, parameterName);
if (parameterName.Length() == 0)
continue;
BString parameterName;
DwarfUtils::GetDIEName(entry, parameterName);
if (parameterName.Length() == 0)
continue;

DIEFormalParameter* parameterEntry
= dynamic_cast<DIEFormalParameter*>(entry);
Variable* parameter;
if (stackFrameDebugInfo->CreateParameter(functionID, parameterEntry,
parameter) != B_OK) {
continue;
DIEFormalParameter* parameterEntry
= dynamic_cast<DIEFormalParameter*>(entry);
Variable* parameter;
if (stackFrameDebugInfo->CreateParameter(functionID,
parameterEntry, parameter) != B_OK) {
continue;
}
BReference<Variable> parameterReference(parameter, true);

if (!frame->AddParameter(parameter))
return B_NO_MEMORY;
}
BReference<Variable> parameterReference(parameter, true);

if (!frame->AddParameter(parameter))
return B_NO_MEMORY;
// create objects for the local variables
_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();
_previousCpuState = previousCpuStateReference.Detach();

Expand Down
8 changes: 4 additions & 4 deletions src/apps/debugger/debug_info/DwarfImageDebugInfo.h
@@ -1,6 +1,6 @@
/*
* 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.
*/
#ifndef DWARF_IMAGE_DEBUG_INFO_H
Expand All @@ -19,6 +19,7 @@

class Architecture;
class CompilationUnit;
class DebuggerInterface;
class DIEType;
class DwarfStackFrameDebugInfo;
class DwarfFile;
Expand All @@ -30,14 +31,13 @@ class GlobalTypeCache;
class GlobalTypeLookup;
class LocatableFile;
class SourceCode;
class TeamMemory;


class DwarfImageDebugInfo : public SpecificImageDebugInfo {
public:
DwarfImageDebugInfo(const ImageInfo& imageInfo,
DebuggerInterface* interface,
Architecture* architecture,
TeamMemory* teamMemory,
FileManager* fileManager,
GlobalTypeLookup* typeLookup,
GlobalTypeCache* typeCache,
Expand Down Expand Up @@ -106,8 +106,8 @@ class DwarfImageDebugInfo : public SpecificImageDebugInfo {
private:
BLocker fLock;
ImageInfo fImageInfo;
DebuggerInterface* fDebuggerInterface;
Architecture* fArchitecture;
TeamMemory* fTeamMemory;
FileManager* fFileManager;
GlobalTypeLookup* fTypeLookup;
GlobalTypeCache* fTypeCache;
Expand Down
11 changes: 7 additions & 4 deletions src/apps/debugger/debug_info/DwarfTeamDebugInfo.cpp
Expand Up @@ -9,6 +9,7 @@

#include <string.h>

#include "DebuggerInterface.h"
#include "DwarfFile.h"
#include "DwarfImageDebugInfo.h"
#include "DwarfManager.h"
Expand All @@ -17,22 +18,24 @@


DwarfTeamDebugInfo::DwarfTeamDebugInfo(Architecture* architecture,
TeamMemory* teamMemory, FileManager* fileManager,
DebuggerInterface* interface, FileManager* fileManager,
GlobalTypeLookup* typeLookup, GlobalTypeCache* typeCache)
:
fArchitecture(architecture),
fTeamMemory(teamMemory),
fDebuggerInterface(interface),
fFileManager(fileManager),
fManager(NULL),
fTypeLookup(typeLookup),
fTypeCache(typeCache)
{
fDebuggerInterface->AcquireReference();
fTypeCache->AcquireReference();
}


DwarfTeamDebugInfo::~DwarfTeamDebugInfo()
{
fDebuggerInterface->ReleaseReference();
fTypeCache->ReleaseReference();
delete fManager;
}
Expand Down Expand Up @@ -75,8 +78,8 @@ DwarfTeamDebugInfo::CreateImageDebugInfo(const ImageInfo& imageInfo,

// create the image debug info
DwarfImageDebugInfo* debugInfo = new(std::nothrow) DwarfImageDebugInfo(
imageInfo, fArchitecture, fTeamMemory, fFileManager, fTypeLookup,
fTypeCache, file);
imageInfo, fDebuggerInterface, fArchitecture, fFileManager,
fTypeLookup, fTypeCache, file);
if (debugInfo == NULL)
return B_NO_MEMORY;

Expand Down
5 changes: 3 additions & 2 deletions src/apps/debugger/debug_info/DwarfTeamDebugInfo.h
Expand Up @@ -9,6 +9,7 @@


class Architecture;
class DebuggerInterface;
class DwarfManager;
class FileManager;
class ImageInfo;
Expand All @@ -20,7 +21,7 @@ class TeamMemory;
class DwarfTeamDebugInfo : public SpecificTeamDebugInfo {
public:
DwarfTeamDebugInfo(Architecture* architecture,
TeamMemory* teamMemory,
DebuggerInterface* interface,
FileManager* fileManager,
GlobalTypeLookup* typeLookup,
GlobalTypeCache* typeCache);
Expand All @@ -34,7 +35,7 @@ class DwarfTeamDebugInfo : public SpecificTeamDebugInfo {

private:
Architecture* fArchitecture;
TeamMemory* fTeamMemory;
DebuggerInterface* fDebuggerInterface;
FileManager* fFileManager;
DwarfManager* fManager;
GlobalTypeLookup* fTypeLookup;
Expand Down

0 comments on commit 5bda396

Please sign in to comment.