Also get the local variables for a stack frame. Apparently gcc doesn't add a

DW_AT_start_scope attribute to any variable entries, so the variables already
appear at the beginning of the block. I suppose we'll have to guess from the
source location when the variables become active.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31649 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-07-20 01:12:52 +00:00
parent 905860f5b4
commit 8fad39df43
4 changed files with 273 additions and 58 deletions
@@ -147,6 +147,22 @@ private:
};
// #pragma mark - EntryListWrapper
/*! Wraps a DebugInfoEntryList, which is a typedef and thus cannot appear in
the header, since our policy disallows us to include DWARF headers there.
*/
struct DwarfImageDebugInfo::EntryListWrapper {
const DebugInfoEntryList& list;
EntryListWrapper(const DebugInfoEntryList& list)
:
list(list)
{
}
};
// #pragma mark - DwarfImageDebugInfo
@@ -313,6 +329,7 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
functionInstance->GetFunctionDebugInfo());
if (function == NULL)
return B_BAD_VALUE;
printf("DwarfImageDebugInfo::CreateFrame(): subprogram DIE: %p\n", function->SubprogramEntry());
int32 registerCount = fArchitecture->CountRegisters();
const Register* registers = fArchitecture->Registers();
@@ -344,9 +361,9 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
target_addr_t instructionPointer
= cpuState->InstructionPointer() - fRelocationDelta;
target_addr_t framePointer;
error = fFile->UnwindCallFrame(function->GetCompilationUnit(),
function->SubprogramEntry(), instructionPointer, &inputInterface,
&outputInterface, framePointer);
CompilationUnit* unit = function->GetCompilationUnit();
error = fFile->UnwindCallFrame(unit, function->SubprogramEntry(),
instructionPointer, &inputInterface, &outputInterface, framePointer);
if (error != B_OK)
return B_UNSUPPORTED;
@@ -382,9 +399,8 @@ if (previousCpuState->GetRegisterValue(reg, value)) {
// create function parameter objects
DIESubprogram* subprogramEntry = function->SubprogramEntry();
DwarfInterfaceFactory factory(fFile, function->GetCompilationUnit(),
subprogramEntry, instructionPointer, framePointer, &inputInterface,
fromDwarfMap);
DwarfInterfaceFactory factory(fFile, unit, subprogramEntry,
instructionPointer, framePointer, &inputInterface, fromDwarfMap);
error = factory.Init();
if (error != B_OK)
return error;
@@ -403,13 +419,17 @@ if (previousCpuState->GetRegisterValue(reg, value)) {
!= B_OK) {
continue;
}
Reference<Variable> parameterReference(parameter, true);
if (!frame->AddParameter(parameter)) {
parameter->ReleaseReference();
if (!frame->AddParameter(parameter))
return B_NO_MEMORY;
}
}
// create objects for the local variables
_CreateLocalVariables(unit, frame, functionID, factory, instructionPointer,
functionInstance->Address() - fRelocationDelta,
subprogramEntry->Variables(), subprogramEntry->Blocks());
_previousFrame = frameReference.Detach();
_previousCpuState = previousCpuStateReference.Detach();
@@ -723,3 +743,75 @@ DwarfImageDebugInfo::_GetSourceFileIndex(CompilationUnit* unit,
return -1;
}
status_t
DwarfImageDebugInfo::_CreateLocalVariables(CompilationUnit* unit,
StackFrame* frame, FunctionID* functionID, DwarfInterfaceFactory& factory,
target_addr_t instructionPointer, target_addr_t lowPC,
const EntryListWrapper& variableEntries,
const EntryListWrapper& blockEntries)
{
printf("DwarfImageDebugInfo::_CreateLocalVariables(): ip: %#llx, low PC: %#llx\n",
instructionPointer, lowPC);
// iterate through the variables and add the ones in scope
for (DebugInfoEntryList::ConstIterator it
= variableEntries.list.GetIterator();
DIEVariable* variableEntry = dynamic_cast<DIEVariable*>(it.Next());) {
printf(" variableEntry %p, scope start: %llu\n", variableEntry, variableEntry->StartScope());
// check the variable's scope
if (instructionPointer < lowPC + variableEntry->StartScope())
continue;
// add the variable
Variable* variable;
if (factory.CreateLocalVariable(functionID, variableEntry, variable)
!= B_OK) {
continue;
}
Reference<Variable> variableReference(variable, true);
if (!frame->AddLocalVariable(variable))
return B_NO_MEMORY;
}
// iterate through the blocks and find the one we're currently in (if any)
for (DebugInfoEntryList::ConstIterator it = blockEntries.list.GetIterator();
DIELexicalBlock* block = dynamic_cast<DIELexicalBlock*>(it.Next());) {
printf(" lexical block: %p\n", block);
// check whether the block has low/high PC attributes
if (block->LowPC() != 0) {
printf(" has lowPC\n");
// yep, compare with the instruction pointer
if (instructionPointer < block->LowPC()
|| instructionPointer >= block->HighPC()) {
continue;
}
} else {
printf(" no lowPC\n");
// check the address ranges instead
TargetAddressRangeList* rangeList = fFile->ResolveRangeList(unit,
block->AddressRangesOffset());
if (rangeList == NULL)
{
printf(" failed to get ranges\n");
continue;
}
Reference<TargetAddressRangeList> rangeListReference(rangeList,
true);
if (!rangeList->Contains(instructionPointer))
{
printf(" ranges don't contain IP\n");
continue;
}
}
// found a block -- recurse
return _CreateLocalVariables(unit, frame, functionID, factory,
instructionPointer, lowPC, block->Variables(), block->Blocks());
}
return B_OK;
}
@@ -17,10 +17,12 @@
class Architecture;
class CompilationUnit;
class DwarfInterfaceFactory;
class DwarfFile;
class ElfSegment;
class FileManager;
class FileSourceCode;
class FunctionID;
class LocatableFile;
class SourceCode;
class TeamMemory;
@@ -65,6 +67,7 @@ public:
private:
struct UnwindTargetInterface;
struct EntryListWrapper;
private:
status_t _AddSourceCodeInfo(CompilationUnit* unit,
@@ -73,6 +76,14 @@ private:
int32 _GetSourceFileIndex(CompilationUnit* unit,
LocatableFile* sourceFile) const;
status_t _CreateLocalVariables(CompilationUnit* unit,
StackFrame* frame, FunctionID* functionID,
DwarfInterfaceFactory& factory,
target_addr_t instructionPointer,
target_addr_t lowPC,
const EntryListWrapper& variableEntries,
const EntryListWrapper& blockEntries);
private:
BLocker fLock;
ImageInfo fImageInfo;
@@ -17,6 +17,7 @@
#include "DwarfUtils.h"
#include "FunctionID.h"
#include "FunctionParameterID.h"
#include "LocalVariableID.h"
#include "RegisterMap.h"
#include "StringUtils.h"
#include "ValueLocation.h"
@@ -63,6 +64,54 @@ private:
};
// #pragma mark - DwarfLocalVariableID
struct DwarfInterfaceFactory::DwarfLocalVariableID : public LocalVariableID {
DwarfLocalVariableID(FunctionID* functionID, const BString& name,
int32 line, int32 column)
:
fFunctionID(functionID),
fName(name),
fLine(line),
fColumn(column)
{
fFunctionID->AcquireReference();
}
virtual ~DwarfLocalVariableID()
{
fFunctionID->ReleaseReference();
}
virtual bool operator==(const ObjectID& other) const
{
const DwarfLocalVariableID* otherID
= dynamic_cast<const DwarfLocalVariableID*>(&other);
return otherID != NULL && *fFunctionID == *otherID->fFunctionID
&& fName == otherID->fName && fLine == otherID->fLine
&& fColumn == otherID->fColumn;
}
protected:
virtual uint32 ComputeHashValue() const
{
uint32 hash = fFunctionID->HashValue();
hash = hash * 19 + StringUtils::HashValue(fName);
hash = hash * 19 + fLine;
hash = hash * 19 + fColumn;
return hash;
}
private:
FunctionID* fFunctionID;
const BString fName;
int32 fLine;
int32 fColumn;
};
// #pragma mark - DwarfType
@@ -521,61 +570,43 @@ parameterEntry, name.String());
return B_NO_MEMORY;
Reference<DwarfFunctionParameterID> idReference(id, true);
// get the type entry
DIEFormalParameter* typeOwnerEntry = parameterEntry;
DIEType* typeEntry = typeOwnerEntry->GetType();
if (typeEntry == NULL) {
if (DIEFormalParameter* abstractOrigin
= dynamic_cast<DIEFormalParameter*>(
typeOwnerEntry->AbstractOrigin())) {
typeOwnerEntry = abstractOrigin;
typeEntry = typeOwnerEntry->GetType();
}
}
// create the variable
return _CreateVariable(id, name, _GetDIEType(parameterEntry),
parameterEntry->GetLocationDescription(), _parameter);
}
if (typeEntry == NULL) {
if (DIEFormalParameter* specification
= dynamic_cast<DIEFormalParameter*>(
typeOwnerEntry->Specification())) {
typeOwnerEntry = specification;
typeEntry = typeOwnerEntry->GetType();
}
}
if (typeEntry == NULL)
return B_BAD_VALUE;
status_t
DwarfInterfaceFactory::CreateLocalVariable(FunctionID* functionID,
DIEVariable* variableEntry, Variable*& _variable)
{
// get the name
BString name;
DwarfUtils::GetDIEName(variableEntry, name);
printf("DwarfInterfaceFactory::CreateLocalVariable(DIE: %p): name: \"%s\"\n",
variableEntry, name.String());
// get the location, if possible
ValueLocation* location = new(std::nothrow) ValueLocation;
if (location == NULL)
// get the declaration location
int32 line = -1;
int32 column = -1;
const char* file;
const char* directory;
DwarfUtils::GetDeclarationLocation(fFile, variableEntry, directory, file,
line, column);
// TODO: If the declaration location is unavailable, we should probably
// add a component to the ID to make it unique nonetheless (the name
// might not suffice).
// create the ID
DwarfLocalVariableID* id = new(std::nothrow) DwarfLocalVariableID(
functionID, name, line, column);
if (id == NULL)
return B_NO_MEMORY;
Reference<ValueLocation> locationReference(location, true);
LocationDescription* locationDescription
= parameterEntry->GetLocationDescription();
if (locationDescription->IsValid()) {
fFile->ResolveLocation(fCompilationUnit,
fSubprogramEntry, locationDescription, fTargetInterface,
fInstructionPointer, 0, fFramePointer, *location);
location->Dump();
}
// create the type
DwarfType* type;
status_t error = _CreateType(typeEntry, type);
if (error != B_OK)
return error;
Reference<DwarfType> typeReference(type, true);
_FixLocation(location, type);
Reference<DwarfLocalVariableID> idReference(id, true);
// create the variable
Variable* variable = new(std::nothrow) Variable(id, name, type, location);
if (variable == NULL)
return B_NO_MEMORY;
_parameter = variable;
return B_OK;
return _CreateVariable(id, name, _GetDIEType(variableEntry),
variableEntry->GetLocationDescription(), _variable);
}
@@ -1049,6 +1080,46 @@ DwarfInterfaceFactory::_CreateArrayType(const BString& name,
}
status_t
DwarfInterfaceFactory::_CreateVariable(ObjectID* id, const BString& name,
DIEType* typeEntry, LocationDescription* locationDescription,
Variable*& _variable)
{
if (typeEntry == NULL)
return B_BAD_VALUE;
// get the location, if possible
ValueLocation* location = new(std::nothrow) ValueLocation;
if (location == NULL)
return B_NO_MEMORY;
Reference<ValueLocation> locationReference(location, true);
if (locationDescription->IsValid()) {
fFile->ResolveLocation(fCompilationUnit,
fSubprogramEntry, locationDescription, fTargetInterface,
fInstructionPointer, 0, fFramePointer, *location);
location->Dump();
}
// create the type
DwarfType* type;
status_t error = _CreateType(typeEntry, type);
if (error != B_OK)
return error;
Reference<DwarfType> typeReference(type, true);
_FixLocation(location, type);
// create the variable
Variable* variable = new(std::nothrow) Variable(id, name, type, location);
if (variable == NULL)
return B_NO_MEMORY;
_variable = variable;
return B_OK;
}
status_t
DwarfInterfaceFactory::_ResolveTypedef(DIETypedef* entry,
DIEType*& _baseTypeEntry)
@@ -1204,3 +1275,28 @@ printf(" set single piece size to %llu\n", type->ByteSize());
}
}
}
template<typename EntryType>
/*static*/ DIEType*
DwarfInterfaceFactory::_GetDIEType(EntryType* entry)
{
if (DIEType* typeEntry = entry->GetType())
return typeEntry;
if (EntryType* abstractOrigin = dynamic_cast<EntryType*>(
entry->AbstractOrigin())) {
entry = abstractOrigin;
if (DIEType* typeEntry = entry->GetType())
return typeEntry;
}
if (EntryType* specification = dynamic_cast<EntryType*>(
entry->Specification())) {
entry = specification;
if (DIEType* typeEntry = entry->GetType())
return typeEntry;
}
return NULL;
}
@@ -23,9 +23,12 @@ class DIEModifiedType;
class DIESubprogram;
class DIEType;
class DIETypedef;
class DIEVariable;
class DwarfFile;
class DwarfTargetInterface;
class FunctionID;
class LocationDescription;
class ObjectID;
class RegisterMap;
class Type;
class ValueLocation;
@@ -51,9 +54,14 @@ public:
DIEFormalParameter* parameterEntry,
Variable*& _parameter);
// returns reference
status_t CreateLocalVariable(FunctionID* functionID,
DIEVariable* variableEntry,
Variable*& _variable);
// returns reference
private:
struct DwarfFunctionParameterID;
struct DwarfLocalVariableID;
struct DwarfType;
struct DwarfDataMember;
struct DwarfPrimitiveType;
@@ -91,6 +99,11 @@ private:
DIEArrayType* typeEntry,
DwarfType*& _type);
status_t _CreateVariable(ObjectID* id,
const BString& name, DIEType* typeEntry,
LocationDescription* locationDescription,
Variable*& _variable);
status_t _ResolveTypedef(DIETypedef* entry,
DIEType*& _baseTypeEntry);
status_t _ResolveTypeByteSize(DIEType* typeEntry,
@@ -99,6 +112,9 @@ private:
void _FixLocation(ValueLocation* location,
DwarfType* type);
template<typename EntryType>
static DIEType* _GetDIEType(EntryType* entry);
private:
DwarfFile* fFile;
CompilationUnit* fCompilationUnit;