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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user