* Added class ValueLocation to represent a location of a value on the target
machine.
* DWARF:
- Various additions to the DIE classes.
- DwarfExpressionEvaluationContext:
- Added support for location expressions and thus the missing DW_OP_piece
and DW_OP_bit_piece operations.
- Fixed some deviations from the specs.
- Added debug output.
- DwarfFile:
- Added missing evaluation of CFA expression rules.
- Added service methods to evaluate expressions, location expressions,
and constant and dynamic values.
* Added model classes for representing types and variables. Particularly the
types part is not finished yet.
* StackFrame does now contain parameters and local variables.
* Added DwarfInterfaceFactory, which creates implementation objects for the
types, as well as variables objects. It's even less finished.
* DwarfImageDebugInfo::CreateFrame(): Resolve function parameters and add them
to the stack frame. No local variables yet.
* Added the beginnings of a variables view. Only lists the names of parameters
and local variables (of understood types) ATM.
* Renamed RegisterView to RegistersView.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31614 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -29,6 +29,7 @@ SourceHdrs
|
|||||||
DwarfFunctionDebugInfo.cpp
|
DwarfFunctionDebugInfo.cpp
|
||||||
DwarfImageDebugInfo.cpp
|
DwarfImageDebugInfo.cpp
|
||||||
DwarfTeamDebugInfo.cpp
|
DwarfTeamDebugInfo.cpp
|
||||||
|
DwarfInterfaceFactory.cpp
|
||||||
: [ FDirName $(SUBDIR) dwarf ]
|
: [ FDirName $(SUBDIR) dwarf ]
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -58,6 +59,7 @@ Application Debugger :
|
|||||||
DwarfFunctionDebugInfo.cpp
|
DwarfFunctionDebugInfo.cpp
|
||||||
DwarfImageDebugInfo.cpp
|
DwarfImageDebugInfo.cpp
|
||||||
DwarfTeamDebugInfo.cpp
|
DwarfTeamDebugInfo.cpp
|
||||||
|
DwarfInterfaceFactory.cpp
|
||||||
Function.cpp
|
Function.cpp
|
||||||
FunctionDebugInfo.cpp
|
FunctionDebugInfo.cpp
|
||||||
FunctionInstance.cpp
|
FunctionInstance.cpp
|
||||||
@@ -84,11 +86,12 @@ Application Debugger :
|
|||||||
# gui/team_window
|
# gui/team_window
|
||||||
ImageFunctionsView.cpp
|
ImageFunctionsView.cpp
|
||||||
ImageListView.cpp
|
ImageListView.cpp
|
||||||
RegisterView.cpp
|
RegistersView.cpp
|
||||||
SourceView.cpp
|
SourceView.cpp
|
||||||
StackTraceView.cpp
|
StackTraceView.cpp
|
||||||
TeamWindow.cpp
|
TeamWindow.cpp
|
||||||
ThreadListView.cpp
|
ThreadListView.cpp
|
||||||
|
VariablesView.cpp
|
||||||
|
|
||||||
# model
|
# model
|
||||||
Breakpoint.cpp
|
Breakpoint.cpp
|
||||||
@@ -107,6 +110,8 @@ Application Debugger :
|
|||||||
TeamMemory.cpp
|
TeamMemory.cpp
|
||||||
Thread.cpp
|
Thread.cpp
|
||||||
ThreadInfo.cpp
|
ThreadInfo.cpp
|
||||||
|
Type.cpp
|
||||||
|
Variable.cpp
|
||||||
|
|
||||||
# source_language
|
# source_language
|
||||||
CLanguage.cpp
|
CLanguage.cpp
|
||||||
@@ -119,6 +124,7 @@ Application Debugger :
|
|||||||
|
|
||||||
# types
|
# types
|
||||||
TargetAddressRangeList.cpp
|
TargetAddressRangeList.cpp
|
||||||
|
ValueLocation.cpp
|
||||||
|
|
||||||
# util
|
# util
|
||||||
StringUtils.cpp
|
StringUtils.cpp
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ DwarfFunctionDebugInfo::DwarfFunctionDebugInfo(
|
|||||||
:
|
:
|
||||||
fImageDebugInfo(imageDebugInfo),
|
fImageDebugInfo(imageDebugInfo),
|
||||||
fCompilationUnit(compilationUnit),
|
fCompilationUnit(compilationUnit),
|
||||||
|
fSubprogramEntry(subprogramEntry),
|
||||||
fAddressRanges(addressRanges),
|
fAddressRanges(addressRanges),
|
||||||
fName(name),
|
fName(name),
|
||||||
fSourceFile(sourceFile),
|
fSourceFile(sourceFile),
|
||||||
|
|||||||
@@ -41,10 +41,13 @@ public:
|
|||||||
|
|
||||||
CompilationUnit* GetCompilationUnit() const
|
CompilationUnit* GetCompilationUnit() const
|
||||||
{ return fCompilationUnit; }
|
{ return fCompilationUnit; }
|
||||||
|
DIESubprogram* SubprogramEntry() const
|
||||||
|
{ return fSubprogramEntry; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DwarfImageDebugInfo* fImageDebugInfo;
|
DwarfImageDebugInfo* fImageDebugInfo;
|
||||||
CompilationUnit* fCompilationUnit;
|
CompilationUnit* fCompilationUnit;
|
||||||
|
DIESubprogram* fSubprogramEntry;
|
||||||
TargetAddressRangeList* fAddressRanges;
|
TargetAddressRangeList* fAddressRanges;
|
||||||
BString fName;
|
BString fName;
|
||||||
LocatableFile* fSourceFile;
|
LocatableFile* fSourceFile;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "Dwarf.h"
|
#include "Dwarf.h"
|
||||||
#include "DwarfFile.h"
|
#include "DwarfFile.h"
|
||||||
#include "DwarfFunctionDebugInfo.h"
|
#include "DwarfFunctionDebugInfo.h"
|
||||||
|
#include "DwarfInterfaceFactory.h"
|
||||||
#include "DwarfTargetInterface.h"
|
#include "DwarfTargetInterface.h"
|
||||||
#include "DwarfUtils.h"
|
#include "DwarfUtils.h"
|
||||||
#include "ElfFile.h"
|
#include "ElfFile.h"
|
||||||
@@ -40,6 +41,8 @@
|
|||||||
#include "TargetAddressRangeList.h"
|
#include "TargetAddressRangeList.h"
|
||||||
#include "TeamMemory.h"
|
#include "TeamMemory.h"
|
||||||
#include "UnsupportedLanguage.h"
|
#include "UnsupportedLanguage.h"
|
||||||
|
#include "ValueLocation.h"
|
||||||
|
#include "Variable.h"
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - UnwindTargetInterface
|
// #pragma mark - UnwindTargetInterface
|
||||||
@@ -336,10 +339,12 @@ DwarfImageDebugInfo::CreateFrame(Image* image, FunctionDebugInfo* _function,
|
|||||||
fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, fTeamMemory);
|
fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, fTeamMemory);
|
||||||
|
|
||||||
// do the unwinding
|
// do the unwinding
|
||||||
|
target_addr_t instructionPointer
|
||||||
|
= cpuState->InstructionPointer() - fRelocationDelta;
|
||||||
target_addr_t framePointer;
|
target_addr_t framePointer;
|
||||||
error = fFile->UnwindCallFrame(function->GetCompilationUnit(),
|
error = fFile->UnwindCallFrame(function->GetCompilationUnit(),
|
||||||
cpuState->InstructionPointer() - fRelocationDelta,
|
function->SubprogramEntry(), instructionPointer, &inputInterface,
|
||||||
&inputInterface, &outputInterface, framePointer);
|
&outputInterface, framePointer);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
|
|
||||||
@@ -358,12 +363,40 @@ if (previousCpuState->GetRegisterValue(reg, value)) {
|
|||||||
cpuState, framePointer, cpuState->InstructionPointer());
|
cpuState, framePointer, cpuState->InstructionPointer());
|
||||||
if (frame == NULL)
|
if (frame == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
Reference<StackFrame> frameReference(frame, true);
|
||||||
|
|
||||||
frame->SetReturnAddress(previousCpuState->InstructionPointer());
|
frame->SetReturnAddress(previousCpuState->InstructionPointer());
|
||||||
// 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.
|
||||||
|
|
||||||
_previousFrame = frame;
|
// create function parameter objects
|
||||||
|
DIESubprogram* subprogramEntry = function->SubprogramEntry();
|
||||||
|
DwarfInterfaceFactory factory(fFile, function->GetCompilationUnit(),
|
||||||
|
subprogramEntry, instructionPointer, framePointer, &inputInterface);
|
||||||
|
error = factory.Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
for (DebugInfoEntryList::ConstIterator it = subprogramEntry->Parameters()
|
||||||
|
.GetIterator(); DebugInfoEntry* entry = it.Next();) {
|
||||||
|
BString parameterName;
|
||||||
|
DwarfUtils::GetDIEName(entry, parameterName);
|
||||||
|
if (entry->Tag() != DW_TAG_formal_parameter)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
DIEFormalParameter* parameterEntry
|
||||||
|
= dynamic_cast<DIEFormalParameter*>(entry);
|
||||||
|
Variable* parameter;
|
||||||
|
if (factory.CreateParameter(parameterEntry, parameter) != B_OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!frame->AddParameter(parameter)) {
|
||||||
|
parameter->ReleaseReference();
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_previousFrame = frameReference.Detach();
|
||||||
_previousCpuState = previousCpuStateReference.Detach();
|
_previousCpuState = previousCpuStateReference.Detach();
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "ImageInfo.h"
|
#include "ImageInfo.h"
|
||||||
#include "SpecificImageDebugInfo.h"
|
#include "SpecificImageDebugInfo.h"
|
||||||
|
#include "Type.h"
|
||||||
|
|
||||||
|
|
||||||
class Architecture;
|
class Architecture;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef DWARF_INTERFACE_FACTORY_H
|
||||||
|
#define DWARF_INTERFACE_FACTORY_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
|
#include "Type.h"
|
||||||
|
|
||||||
|
|
||||||
|
class CompilationUnit;
|
||||||
|
class DIEAddressingType;
|
||||||
|
class DIEArrayType;
|
||||||
|
class DIEBaseType;
|
||||||
|
class DIECompoundType;
|
||||||
|
class DIEFormalParameter;
|
||||||
|
class DIEModifiedType;
|
||||||
|
class DIESubprogram;
|
||||||
|
class DIEType;
|
||||||
|
class DIETypedef;
|
||||||
|
class DwarfFile;
|
||||||
|
class DwarfTargetInterface;
|
||||||
|
class Type;
|
||||||
|
class Variable;
|
||||||
|
|
||||||
|
|
||||||
|
class DwarfInterfaceFactory {
|
||||||
|
public:
|
||||||
|
DwarfInterfaceFactory(DwarfFile* file,
|
||||||
|
CompilationUnit* compilationUnit,
|
||||||
|
DIESubprogram* subprogramEntry,
|
||||||
|
target_addr_t instructionPointer,
|
||||||
|
target_addr_t framePointer,
|
||||||
|
DwarfTargetInterface* targetInterface);
|
||||||
|
~DwarfInterfaceFactory();
|
||||||
|
|
||||||
|
status_t Init();
|
||||||
|
|
||||||
|
status_t CreateType(DIEType* typeEntry, Type*& _type);
|
||||||
|
// returns reference
|
||||||
|
status_t CreateParameter(
|
||||||
|
DIEFormalParameter* parameterEntry,
|
||||||
|
Variable*& _parameter);
|
||||||
|
// returns reference
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct DwarfType;
|
||||||
|
struct DwarfDataMember;
|
||||||
|
struct DwarfPrimitiveType;
|
||||||
|
struct DwarfCompoundType;
|
||||||
|
struct DwarfModifiedType;
|
||||||
|
struct DwarfTypedefType;
|
||||||
|
struct DwarfAddressType;
|
||||||
|
struct DwarfArrayType;
|
||||||
|
struct DwarfTypeHashDefinition;
|
||||||
|
|
||||||
|
typedef OpenHashTable<DwarfTypeHashDefinition> TypeTable;
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _CreateType(DIEType* typeEntry,
|
||||||
|
DwarfType*& _type);
|
||||||
|
status_t _CreateTypeInternal(DIEType* typeEntry,
|
||||||
|
DwarfType*& _type);
|
||||||
|
|
||||||
|
status_t _CreateCompoundType(const BString& name,
|
||||||
|
DIECompoundType* typeEntry,
|
||||||
|
DwarfType*& _type);
|
||||||
|
status_t _CreatePrimitiveType(const BString& name,
|
||||||
|
DIEBaseType* typeEntry,
|
||||||
|
DwarfType*& _type);
|
||||||
|
status_t _CreateAddressType(const BString& name,
|
||||||
|
DIEAddressingType* typeEntry,
|
||||||
|
address_type_kind addressKind,
|
||||||
|
DwarfType*& _type);
|
||||||
|
status_t _CreateModifiedType(const BString& name,
|
||||||
|
DIEModifiedType* typeEntry,
|
||||||
|
uint32 modifiers, DwarfType*& _type);
|
||||||
|
status_t _CreateTypedefType(const BString& name,
|
||||||
|
DIETypedef* typeEntry, DwarfType*& _type);
|
||||||
|
status_t _CreateArrayType(const BString& name,
|
||||||
|
DIEArrayType* typeEntry,
|
||||||
|
DwarfType*& _type);
|
||||||
|
|
||||||
|
status_t _ResolveTypedef(DIETypedef* entry,
|
||||||
|
DIEType*& _baseTypeEntry);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DwarfFile* fFile;
|
||||||
|
CompilationUnit* fCompilationUnit;
|
||||||
|
DIESubprogram* fSubprogramEntry;
|
||||||
|
target_addr_t fInstructionPointer;
|
||||||
|
target_addr_t fFramePointer;
|
||||||
|
DwarfTargetInterface* fTargetInterface;
|
||||||
|
TypeTable* fTypes;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DWARF_INTERFACE_FACTORY_H
|
||||||
@@ -135,11 +135,16 @@ struct DynamicAttributeValue {
|
|||||||
|
|
||||||
DynamicAttributeValue()
|
DynamicAttributeValue()
|
||||||
:
|
:
|
||||||
attributeClass(ATTRIBUTE_CLASS_CONSTANT)
|
attributeClass(ATTRIBUTE_CLASS_UNKNOWN)
|
||||||
{
|
{
|
||||||
this->constant = 0;
|
this->constant = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsValid() const
|
||||||
|
{
|
||||||
|
return attributeClass != ATTRIBUTE_CLASS_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
void SetTo(uint64 constant)
|
void SetTo(uint64 constant)
|
||||||
{
|
{
|
||||||
this->constant = constant;
|
this->constant = constant;
|
||||||
@@ -174,9 +179,13 @@ struct ConstantAttributeValue {
|
|||||||
|
|
||||||
ConstantAttributeValue()
|
ConstantAttributeValue()
|
||||||
:
|
:
|
||||||
attributeClass(ATTRIBUTE_CLASS_CONSTANT)
|
attributeClass(ATTRIBUTE_CLASS_UNKNOWN)
|
||||||
{
|
{
|
||||||
this->constant = 0;
|
}
|
||||||
|
|
||||||
|
bool IsValid() const
|
||||||
|
{
|
||||||
|
return attributeClass != ATTRIBUTE_CLASS_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetTo(uint64 constant)
|
void SetTo(uint64 constant)
|
||||||
|
|||||||
@@ -437,7 +437,7 @@ DIEClassBaseType::AddChild(DebugInfoEntry* child)
|
|||||||
{
|
{
|
||||||
switch (child->Tag()) {
|
switch (child->Tag()) {
|
||||||
case DW_TAG_inheritance:
|
case DW_TAG_inheritance:
|
||||||
fDataMembers.Add(child);
|
fBaseTypes.Add(child);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
case DW_TAG_friend:
|
case DW_TAG_friend:
|
||||||
fFriends.Add(child);
|
fFriends.Add(child);
|
||||||
@@ -777,6 +777,9 @@ DIEEnumerationType::AddAttribute_specification(uint16 attributeName,
|
|||||||
|
|
||||||
|
|
||||||
DIEFormalParameter::DIEFormalParameter()
|
DIEFormalParameter::DIEFormalParameter()
|
||||||
|
:
|
||||||
|
fAbstractOrigin(NULL),
|
||||||
|
fType(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -788,6 +791,13 @@ DIEFormalParameter::Tag() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DebugInfoEntry*
|
||||||
|
DIEFormalParameter::AbstractOrigin() const
|
||||||
|
{
|
||||||
|
return fAbstractOrigin;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LocationDescription*
|
LocationDescription*
|
||||||
DIEFormalParameter::GetLocationDescription()
|
DIEFormalParameter::GetLocationDescription()
|
||||||
{
|
{
|
||||||
@@ -795,6 +805,32 @@ DIEFormalParameter::GetLocationDescription()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEFormalParameter::AddAttribute_abstract_origin(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
fAbstractOrigin = value.reference;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEFormalParameter::AddAttribute_const_value(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
return SetConstantAttributeValue(fValue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEFormalParameter::AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
fType = dynamic_cast<DIEType*>(value.reference);
|
||||||
|
return fType != NULL ? B_OK : B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DIEImportedDeclaration
|
// #pragma mark - DIEImportedDeclaration
|
||||||
|
|
||||||
|
|
||||||
@@ -844,6 +880,8 @@ DIELexicalBlock::Tag() const
|
|||||||
|
|
||||||
|
|
||||||
DIEMember::DIEMember()
|
DIEMember::DIEMember()
|
||||||
|
:
|
||||||
|
fType(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -855,6 +893,15 @@ DIEMember::Tag() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEMember::AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
fType = dynamic_cast<DIEType*>(value.reference);
|
||||||
|
return fType != NULL ? B_OK : B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DIEPointerType
|
// #pragma mark - DIEPointerType
|
||||||
|
|
||||||
|
|
||||||
@@ -1118,6 +1165,8 @@ DIECommonInclusion::Tag() const
|
|||||||
|
|
||||||
|
|
||||||
DIEInheritance::DIEInheritance()
|
DIEInheritance::DIEInheritance()
|
||||||
|
:
|
||||||
|
fType(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1129,6 +1178,15 @@ DIEInheritance::Tag() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEInheritance::AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
fType = dynamic_cast<DIEType*>(value.reference);
|
||||||
|
return fType != NULL ? B_OK : B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DIEInlinedSubroutine
|
// #pragma mark - DIEInlinedSubroutine
|
||||||
|
|
||||||
|
|
||||||
@@ -1297,6 +1355,8 @@ DIESubrangeType::AddAttribute_threads_scaled(uint16 attributeName,
|
|||||||
|
|
||||||
|
|
||||||
DIEWithStatement::DIEWithStatement()
|
DIEWithStatement::DIEWithStatement()
|
||||||
|
:
|
||||||
|
fType(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1315,6 +1375,15 @@ DIEWithStatement::GetLocationDescription()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEWithStatement::AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
fType = dynamic_cast<DIEType*>(value.reference);
|
||||||
|
return fType != NULL ? B_OK : B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DIEAccessDeclaration
|
// #pragma mark - DIEAccessDeclaration
|
||||||
|
|
||||||
|
|
||||||
@@ -1424,6 +1493,8 @@ DIEConstType::Tag() const
|
|||||||
|
|
||||||
|
|
||||||
DIEConstant::DIEConstant()
|
DIEConstant::DIEConstant()
|
||||||
|
:
|
||||||
|
fType(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1435,6 +1506,23 @@ DIEConstant::Tag() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEConstant::AddAttribute_const_value(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
return SetConstantAttributeValue(fValue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEConstant::AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
fType = dynamic_cast<DIEType*>(value.reference);
|
||||||
|
return fType != NULL ? B_OK : B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DIEEnumerator
|
// #pragma mark - DIEEnumerator
|
||||||
|
|
||||||
|
|
||||||
@@ -1586,6 +1674,20 @@ DIESubprogram::AbstractOrigin() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIESubprogram::AddChild(DebugInfoEntry* child)
|
||||||
|
{
|
||||||
|
switch (child->Tag()) {
|
||||||
|
case DW_TAG_formal_parameter:
|
||||||
|
case DW_TAG_unspecified_parameters:
|
||||||
|
fParameters.Add(child);
|
||||||
|
return B_OK;
|
||||||
|
default:
|
||||||
|
return DIEDeclaredNamedBase::AddChild(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DIESubprogram::AddAttribute_low_pc(uint16 attributeName,
|
DIESubprogram::AddAttribute_low_pc(uint16 attributeName,
|
||||||
const AttributeValue& value)
|
const AttributeValue& value)
|
||||||
@@ -1669,10 +1771,30 @@ DIESubprogram::AddAttribute_abstract_origin(uint16 attributeName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIESubprogram::AddAttribute_frame_base(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
if (value.attributeClass == ATTRIBUTE_CLASS_LOCLISTPTR) {
|
||||||
|
fFrameBase.SetToLocationList(value.pointer);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.attributeClass == ATTRIBUTE_CLASS_BLOCK) {
|
||||||
|
fFrameBase.SetToExpression(value.block.data, value.block.length);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DIETemplateTypeParameter
|
// #pragma mark - DIETemplateTypeParameter
|
||||||
|
|
||||||
|
|
||||||
DIETemplateTypeParameter::DIETemplateTypeParameter()
|
DIETemplateTypeParameter::DIETemplateTypeParameter()
|
||||||
|
:
|
||||||
|
fType(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1684,10 +1806,21 @@ DIETemplateTypeParameter::Tag() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIETemplateTypeParameter::AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
fType = dynamic_cast<DIEType*>(value.reference);
|
||||||
|
return fType != NULL ? B_OK : B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DIETemplateValueParameter
|
// #pragma mark - DIETemplateValueParameter
|
||||||
|
|
||||||
|
|
||||||
DIETemplateValueParameter::DIETemplateValueParameter()
|
DIETemplateValueParameter::DIETemplateValueParameter()
|
||||||
|
:
|
||||||
|
fType(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1699,10 +1832,29 @@ DIETemplateValueParameter::Tag() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIETemplateValueParameter::AddAttribute_const_value(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
return SetConstantAttributeValue(fValue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIETemplateValueParameter::AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
fType = dynamic_cast<DIEType*>(value.reference);
|
||||||
|
return fType != NULL ? B_OK : B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DIEThrownType
|
// #pragma mark - DIEThrownType
|
||||||
|
|
||||||
|
|
||||||
DIEThrownType::DIEThrownType()
|
DIEThrownType::DIEThrownType()
|
||||||
|
:
|
||||||
|
fType(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1714,6 +1866,15 @@ DIEThrownType::Tag() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEThrownType::AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
fType = dynamic_cast<DIEType*>(value.reference);
|
||||||
|
return fType != NULL ? B_OK : B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DIETryBlock
|
// #pragma mark - DIETryBlock
|
||||||
|
|
||||||
|
|
||||||
@@ -1733,6 +1894,8 @@ DIETryBlock::Tag() const
|
|||||||
|
|
||||||
|
|
||||||
DIEVariantPart::DIEVariantPart()
|
DIEVariantPart::DIEVariantPart()
|
||||||
|
:
|
||||||
|
fType(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1744,10 +1907,21 @@ DIEVariantPart::Tag() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEVariantPart::AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
fType = dynamic_cast<DIEType*>(value.reference);
|
||||||
|
return fType != NULL ? B_OK : B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DIEVariable
|
// #pragma mark - DIEVariable
|
||||||
|
|
||||||
|
|
||||||
DIEVariable::DIEVariable()
|
DIEVariable::DIEVariable()
|
||||||
|
:
|
||||||
|
fType(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1766,6 +1940,23 @@ DIEVariable::GetLocationDescription()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEVariable::AddAttribute_const_value(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
return SetConstantAttributeValue(fValue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DIEVariable::AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value)
|
||||||
|
{
|
||||||
|
fType = dynamic_cast<DIEType*>(value.reference);
|
||||||
|
return fType != NULL ? B_OK : B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - DIEVolatileType
|
// #pragma mark - DIEVolatileType
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -241,6 +241,8 @@ class DIEModifiedType : public DIEType {
|
|||||||
public:
|
public:
|
||||||
DIEModifiedType();
|
DIEModifiedType();
|
||||||
|
|
||||||
|
DIEType* GetType() const { return fType; }
|
||||||
|
|
||||||
virtual status_t AddAttribute_type(uint16 attributeName,
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
const AttributeValue& value);
|
const AttributeValue& value);
|
||||||
|
|
||||||
@@ -301,6 +303,8 @@ class DIEDerivedType : public DIEDeclaredType {
|
|||||||
public:
|
public:
|
||||||
DIEDerivedType();
|
DIEDerivedType();
|
||||||
|
|
||||||
|
DIEType* GetType() const { return fType; }
|
||||||
|
|
||||||
virtual status_t AddAttribute_type(uint16 attributeName,
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
const AttributeValue& value);
|
const AttributeValue& value);
|
||||||
|
|
||||||
@@ -317,6 +321,9 @@ public:
|
|||||||
|
|
||||||
virtual DebugInfoEntry* Specification() const;
|
virtual DebugInfoEntry* Specification() const;
|
||||||
|
|
||||||
|
const DebugInfoEntryList& DataMembers() const
|
||||||
|
{ return fDataMembers; }
|
||||||
|
|
||||||
virtual status_t AddChild(DebugInfoEntry* child);
|
virtual status_t AddChild(DebugInfoEntry* child);
|
||||||
|
|
||||||
virtual status_t AddAttribute_byte_size(uint16 attributeName,
|
virtual status_t AddAttribute_byte_size(uint16 attributeName,
|
||||||
@@ -453,6 +460,8 @@ public:
|
|||||||
|
|
||||||
class DIEEntryPoint : public DebugInfoEntry {
|
class DIEEntryPoint : public DebugInfoEntry {
|
||||||
public:
|
public:
|
||||||
|
// TODO: Maybe introduce a common base class for DIEEntryPoint and
|
||||||
|
// DIESubprogram.
|
||||||
DIEEntryPoint();
|
DIEEntryPoint();
|
||||||
|
|
||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
@@ -504,21 +513,35 @@ public:
|
|||||||
|
|
||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
|
|
||||||
|
virtual DebugInfoEntry* AbstractOrigin() const;
|
||||||
virtual LocationDescription* GetLocationDescription();
|
virtual LocationDescription* GetLocationDescription();
|
||||||
|
|
||||||
|
DIEType* GetType() const { return fType; }
|
||||||
|
|
||||||
|
const ConstantAttributeValue* ConstValue() const
|
||||||
|
{ return &fValue; }
|
||||||
|
|
||||||
|
virtual status_t AddAttribute_abstract_origin(
|
||||||
|
uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
virtual status_t AddAttribute_const_value(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// DW_AT_abstract_origin
|
|
||||||
// DW_AT_artificial
|
// DW_AT_artificial
|
||||||
// DW_AT_const_value
|
|
||||||
// DW_AT_default_value
|
// DW_AT_default_value
|
||||||
// DW_AT_endianity
|
// DW_AT_endianity
|
||||||
// DW_AT_is_optional
|
// DW_AT_is_optional
|
||||||
// DW_AT_segment
|
// DW_AT_segment
|
||||||
// DW_AT_type
|
|
||||||
// DW_AT_variable_parameter
|
// DW_AT_variable_parameter
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LocationDescription fLocationDescription;
|
LocationDescription fLocationDescription;
|
||||||
|
DebugInfoEntry* fAbstractOrigin;
|
||||||
|
DIEType* fType;
|
||||||
|
ConstantAttributeValue fValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -569,14 +592,20 @@ public:
|
|||||||
|
|
||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
|
|
||||||
|
DIEType* GetType() const { return fType; }
|
||||||
|
|
||||||
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// DW_AT_bit_offset
|
// DW_AT_bit_offset
|
||||||
// DW_AT_bit_size
|
// DW_AT_bit_size
|
||||||
// DW_AT_byte_size
|
// DW_AT_byte_size
|
||||||
// DW_AT_data_member_location
|
// DW_AT_data_member_location
|
||||||
// DW_AT_mutable
|
// DW_AT_mutable
|
||||||
// DW_AT_type
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
DIEType* fType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -738,11 +767,18 @@ public:
|
|||||||
|
|
||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
|
|
||||||
|
DIEType* GetType() const { return fType; }
|
||||||
|
|
||||||
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// DW_AT_accessibility
|
// DW_AT_accessibility
|
||||||
// DW_AT_data_member_location
|
// DW_AT_data_member_location
|
||||||
// DW_AT_type
|
|
||||||
// DW_AT_virtuality
|
// DW_AT_virtuality
|
||||||
|
|
||||||
|
private:
|
||||||
|
DIEType* fType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -857,8 +893,13 @@ public:
|
|||||||
|
|
||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
|
|
||||||
|
DIEType* GetType() const { return fType; }
|
||||||
|
|
||||||
virtual LocationDescription* GetLocationDescription();
|
virtual LocationDescription* GetLocationDescription();
|
||||||
|
|
||||||
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// DW_AT_accessibility
|
// DW_AT_accessibility
|
||||||
// DW_AT_address_class
|
// DW_AT_address_class
|
||||||
@@ -867,10 +908,10 @@ public:
|
|||||||
// DW_AT_low_pc
|
// DW_AT_low_pc
|
||||||
// DW_AT_ranges
|
// DW_AT_ranges
|
||||||
// DW_AT_segment
|
// DW_AT_segment
|
||||||
// DW_AT_type
|
|
||||||
// DW_AT_visibility
|
// DW_AT_visibility
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
DIEType* fType;
|
||||||
LocationDescription fLocationDescription;
|
LocationDescription fLocationDescription;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -889,6 +930,15 @@ public:
|
|||||||
|
|
||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
|
|
||||||
|
const DynamicAttributeValue* ByteSize() const
|
||||||
|
{ return &fByteSize; }
|
||||||
|
const DynamicAttributeValue* BitOffset() const
|
||||||
|
{ return &fBitOffset; }
|
||||||
|
const DynamicAttributeValue* BitSize() const
|
||||||
|
{ return &fBitSize; }
|
||||||
|
uint8 Encoding() const { return fEncoding; }
|
||||||
|
uint8 Endianity() const { return fEndianity; }
|
||||||
|
|
||||||
virtual status_t AddAttribute_encoding(uint16 attributeName,
|
virtual status_t AddAttribute_encoding(uint16 attributeName,
|
||||||
const AttributeValue& value);
|
const AttributeValue& value);
|
||||||
virtual status_t AddAttribute_byte_size(uint16 attributeName,
|
virtual status_t AddAttribute_byte_size(uint16 attributeName,
|
||||||
@@ -947,12 +997,24 @@ public:
|
|||||||
|
|
||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
|
|
||||||
|
DIEType* GetType() const { return fType; }
|
||||||
|
|
||||||
|
const ConstantAttributeValue* ConstValue() const
|
||||||
|
{ return &fValue; }
|
||||||
|
|
||||||
|
virtual status_t AddAttribute_const_value(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// DW_AT_const_value
|
|
||||||
// DW_AT_endianity
|
// DW_AT_endianity
|
||||||
// DW_AT_external
|
// DW_AT_external
|
||||||
// DW_AT_start_scope
|
// DW_AT_start_scope
|
||||||
// DW_AT_type
|
|
||||||
|
private:
|
||||||
|
DIEType* fType;
|
||||||
|
ConstantAttributeValue fValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -962,6 +1024,9 @@ public:
|
|||||||
|
|
||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
|
|
||||||
|
const ConstantAttributeValue* ConstValue() const
|
||||||
|
{ return &fValue; }
|
||||||
|
|
||||||
virtual status_t AddAttribute_const_value(uint16 attributeName,
|
virtual status_t AddAttribute_const_value(uint16 attributeName,
|
||||||
const AttributeValue& value);
|
const AttributeValue& value);
|
||||||
|
|
||||||
@@ -1042,9 +1107,15 @@ public:
|
|||||||
target_addr_t LowPC() const { return fLowPC; }
|
target_addr_t LowPC() const { return fLowPC; }
|
||||||
target_addr_t HighPC() const { return fHighPC; }
|
target_addr_t HighPC() const { return fHighPC; }
|
||||||
|
|
||||||
|
const LocationDescription* FrameBase() const { return &fFrameBase; }
|
||||||
|
|
||||||
|
const DebugInfoEntryList Parameters() const { return fParameters; }
|
||||||
|
|
||||||
bool IsPrototyped() const { return fPrototyped; }
|
bool IsPrototyped() const { return fPrototyped; }
|
||||||
uint8 Inline() const { return fInline; }
|
uint8 Inline() const { return fInline; }
|
||||||
|
|
||||||
|
virtual status_t AddChild(DebugInfoEntry* child);
|
||||||
|
|
||||||
virtual status_t AddAttribute_low_pc(uint16 attributeName,
|
virtual status_t AddAttribute_low_pc(uint16 attributeName,
|
||||||
const AttributeValue& value);
|
const AttributeValue& value);
|
||||||
virtual status_t AddAttribute_high_pc(uint16 attributeName,
|
virtual status_t AddAttribute_high_pc(uint16 attributeName,
|
||||||
@@ -1064,33 +1135,35 @@ public:
|
|||||||
virtual status_t AddAttribute_abstract_origin(
|
virtual status_t AddAttribute_abstract_origin(
|
||||||
uint16 attributeName,
|
uint16 attributeName,
|
||||||
const AttributeValue& value);
|
const AttributeValue& value);
|
||||||
|
virtual status_t AddAttribute_frame_base(
|
||||||
|
uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
DebugInfoEntryList fParameters;
|
||||||
target_addr_t fLowPC;
|
target_addr_t fLowPC;
|
||||||
target_addr_t fHighPC;
|
target_addr_t fHighPC;
|
||||||
off_t fAddressRangesOffset;
|
off_t fAddressRangesOffset;
|
||||||
DIESubprogram* fSpecification;
|
DIESubprogram* fSpecification;
|
||||||
DIESubprogram* fAbstractOrigin;
|
DIESubprogram* fAbstractOrigin;
|
||||||
DIEType* fReturnType;
|
DIEType* fReturnType;
|
||||||
|
LocationDescription fFrameBase;
|
||||||
uint8 fAddressClass;
|
uint8 fAddressClass;
|
||||||
bool fPrototyped;
|
bool fPrototyped;
|
||||||
uint8 fInline;
|
uint8 fInline;
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// DW_AT_abstract_origin
|
|
||||||
// DW_AT_artificial
|
// DW_AT_artificial
|
||||||
// DW_AT_calling_convention
|
// DW_AT_calling_convention
|
||||||
// DW_AT_elemental
|
// DW_AT_elemental
|
||||||
// DW_AT_entry_pc
|
// DW_AT_entry_pc
|
||||||
// DW_AT_explicit
|
// DW_AT_explicit
|
||||||
// DW_AT_external
|
// DW_AT_external
|
||||||
// DW_AT_frame_base
|
|
||||||
// DW_AT_object_pointer
|
// DW_AT_object_pointer
|
||||||
// DW_AT_pure
|
// DW_AT_pure
|
||||||
// DW_AT_recursive
|
// DW_AT_recursive
|
||||||
// DW_AT_return_addr
|
// DW_AT_return_addr
|
||||||
// DW_AT_segment
|
// DW_AT_segment
|
||||||
// DW_AT_specification
|
|
||||||
// DW_AT_start_scope
|
// DW_AT_start_scope
|
||||||
// DW_AT_static_link
|
// DW_AT_static_link
|
||||||
// DW_AT_trampoline
|
// DW_AT_trampoline
|
||||||
@@ -1105,8 +1178,13 @@ public:
|
|||||||
|
|
||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
|
|
||||||
// TODO:
|
DIEType* GetType() const { return fType; }
|
||||||
// DW_AT_type
|
|
||||||
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DIEType* fType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1116,9 +1194,19 @@ public:
|
|||||||
|
|
||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
|
|
||||||
// TODO:
|
DIEType* GetType() const { return fType; }
|
||||||
// DW_AT_const_value
|
|
||||||
// DW_AT_type
|
const ConstantAttributeValue* ConstValue() const
|
||||||
|
{ return &fValue; }
|
||||||
|
|
||||||
|
virtual status_t AddAttribute_const_value(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DIEType* fType;
|
||||||
|
ConstantAttributeValue fValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1128,11 +1216,18 @@ public:
|
|||||||
|
|
||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
|
|
||||||
|
DIEType* GetType() const { return fType; }
|
||||||
|
|
||||||
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// DW_AT_allocated
|
// DW_AT_allocated
|
||||||
// DW_AT_associated
|
// DW_AT_associated
|
||||||
// DW_AT_data_location
|
// DW_AT_data_location
|
||||||
// DW_AT_type
|
|
||||||
|
private:
|
||||||
|
DIEType* fType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1157,12 +1252,19 @@ public:
|
|||||||
|
|
||||||
virtual uint16 Tag() const;
|
virtual uint16 Tag() const;
|
||||||
|
|
||||||
|
DIEType* GetType() const { return fType; }
|
||||||
|
|
||||||
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// DW_AT_abstract_origin
|
// DW_AT_abstract_origin
|
||||||
// DW_AT_accessibility
|
// DW_AT_accessibility
|
||||||
// DW_AT_declaration
|
// DW_AT_declaration
|
||||||
// DW_AT_discr
|
// DW_AT_discr
|
||||||
// DW_AT_type
|
|
||||||
|
private:
|
||||||
|
DIEType* fType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -1174,18 +1276,28 @@ public:
|
|||||||
|
|
||||||
virtual LocationDescription* GetLocationDescription();
|
virtual LocationDescription* GetLocationDescription();
|
||||||
|
|
||||||
|
DIEType* GetType() const { return fType; }
|
||||||
|
|
||||||
|
const ConstantAttributeValue* ConstValue() const
|
||||||
|
{ return &fValue; }
|
||||||
|
|
||||||
|
virtual status_t AddAttribute_const_value(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
virtual status_t AddAttribute_type(uint16 attributeName,
|
||||||
|
const AttributeValue& value);
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// DW_AT_abstract_origin
|
// DW_AT_abstract_origin
|
||||||
// DW_AT_const_value
|
|
||||||
// DW_AT_endianity
|
// DW_AT_endianity
|
||||||
// DW_AT_external
|
// DW_AT_external
|
||||||
// DW_AT_segment
|
// DW_AT_segment
|
||||||
// DW_AT_specification
|
// DW_AT_specification
|
||||||
// DW_AT_start_scope
|
// DW_AT_start_scope
|
||||||
// DW_AT_type
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LocationDescription fLocationDescription;
|
LocationDescription fLocationDescription;
|
||||||
|
ConstantAttributeValue fValue;
|
||||||
|
DIEType* fType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -202,7 +202,6 @@ DebugInfoEntry::AddAttribute_location(uint16 attributeName,
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ATTRIBUTE_NOT_HANDLED;
|
return ATTRIBUTE_NOT_HANDLED;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "DataReader.h"
|
#include "DataReader.h"
|
||||||
#include "Dwarf.h"
|
#include "Dwarf.h"
|
||||||
#include "DwarfTargetInterface.h"
|
#include "DwarfTargetInterface.h"
|
||||||
|
#include "ValueLocation.h"
|
||||||
|
|
||||||
|
|
||||||
// number of elements to increase the stack capacity when the stack is full
|
// number of elements to increase the stack capacity when the stack is full
|
||||||
@@ -34,7 +35,7 @@ static const uint32 kMaxOperationCount = 10000;
|
|||||||
|
|
||||||
|
|
||||||
DwarfExpressionEvaluationContext::DwarfExpressionEvaluationContext(
|
DwarfExpressionEvaluationContext::DwarfExpressionEvaluationContext(
|
||||||
DwarfTargetInterface* targetInterface, uint8 addressSize)
|
const DwarfTargetInterface* targetInterface, uint8 addressSize)
|
||||||
:
|
:
|
||||||
fTargetInterface(targetInterface),
|
fTargetInterface(targetInterface),
|
||||||
fAddressSize(addressSize)
|
fAddressSize(addressSize)
|
||||||
@@ -51,6 +52,13 @@ DwarfExpressionEvaluationContext::~DwarfExpressionEvaluationContext()
|
|||||||
|
|
||||||
|
|
||||||
struct DwarfExpressionEvaluator::EvaluationException {
|
struct DwarfExpressionEvaluator::EvaluationException {
|
||||||
|
const char* message;
|
||||||
|
|
||||||
|
EvaluationException(const char* message)
|
||||||
|
:
|
||||||
|
message(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -61,7 +69,7 @@ void
|
|||||||
DwarfExpressionEvaluator::_AssertMinStackSize(size_t size) const
|
DwarfExpressionEvaluator::_AssertMinStackSize(size_t size) const
|
||||||
{
|
{
|
||||||
if (fStackSize < size)
|
if (fStackSize < size)
|
||||||
throw EvaluationException();
|
throw EvaluationException("pop from empty stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -71,7 +79,7 @@ DwarfExpressionEvaluator::_Push(target_addr_t value)
|
|||||||
// resize the stack, if we hit the capacity
|
// resize the stack, if we hit the capacity
|
||||||
if (fStackSize == fStackCapacity) {
|
if (fStackSize == fStackCapacity) {
|
||||||
if (fStackCapacity >= kMaxStackCapacity)
|
if (fStackCapacity >= kMaxStackCapacity)
|
||||||
throw EvaluationException();
|
throw EvaluationException("stack overflow");
|
||||||
|
|
||||||
size_t newCapacity = fStackCapacity + kStackCapacityIncrement;
|
size_t newCapacity = fStackCapacity + kStackCapacityIncrement;
|
||||||
target_addr_t* newStack = (target_addr_t*)realloc(fStack,
|
target_addr_t* newStack = (target_addr_t*)realloc(fStack,
|
||||||
@@ -113,12 +121,11 @@ DwarfExpressionEvaluator::~DwarfExpressionEvaluator()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfExpressionEvaluator::Evaluate(const void* expression, size_t size)
|
DwarfExpressionEvaluator::Push(target_addr_t value)
|
||||||
{
|
{
|
||||||
fDataReader.SetTo(expression, size, fContext->AddressSize());
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return _Evaluate();
|
_Push(value);
|
||||||
|
return B_OK;
|
||||||
} catch (const EvaluationException& exception) {
|
} catch (const EvaluationException& exception) {
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
} catch (const std::bad_alloc& exception) {
|
} catch (const std::bad_alloc& exception) {
|
||||||
@@ -128,8 +135,122 @@ DwarfExpressionEvaluator::Evaluate(const void* expression, size_t size)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfExpressionEvaluator::_Evaluate()
|
DwarfExpressionEvaluator::Evaluate(const void* expression, size_t size,
|
||||||
|
target_addr_t& _result)
|
||||||
{
|
{
|
||||||
|
fDataReader.SetTo(expression, size, fContext->AddressSize());
|
||||||
|
|
||||||
|
try {
|
||||||
|
status_t error = _Evaluate(NULL);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
_result = _Pop();
|
||||||
|
return B_OK;
|
||||||
|
} catch (const EvaluationException& exception) {
|
||||||
|
printf("DwarfExpressionEvaluator::Evaluate(): %s\n", exception.message);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
} catch (const std::bad_alloc& exception) {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfExpressionEvaluator::EvaluateLocation(const void* expression, size_t size,
|
||||||
|
ValueLocation& _location)
|
||||||
|
{
|
||||||
|
_location.Clear();
|
||||||
|
|
||||||
|
// the empty expression is a valid one
|
||||||
|
if (size == 0) {
|
||||||
|
ValuePieceLocation piece;
|
||||||
|
piece.SetToUnknown();
|
||||||
|
piece.SetSize(0);
|
||||||
|
return _location.AddPiece(piece) ? B_OK : B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
fDataReader.SetTo(expression, size, fContext->AddressSize());
|
||||||
|
|
||||||
|
// parse the first (and maybe only) expression
|
||||||
|
try {
|
||||||
|
ValuePieceLocation piece;
|
||||||
|
status_t error = _Evaluate(&piece);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// if that's all, it's only a simple expression without composition
|
||||||
|
if (fDataReader.BytesRemaining() == 0) {
|
||||||
|
if (!piece.IsValid())
|
||||||
|
piece.SetToMemory(_Pop());
|
||||||
|
piece.SetSize(0);
|
||||||
|
return _location.AddPiece(piece) ? B_OK : B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// there's more, so it must be a composition operator
|
||||||
|
uint8 opcode = fDataReader.Read<uint8>(0);
|
||||||
|
if (opcode == DW_OP_piece) {
|
||||||
|
piece.SetSize(fDataReader.ReadUnsignedLEB128(0));
|
||||||
|
} else if (opcode == DW_OP_bit_piece) {
|
||||||
|
uint64 bitSize = fDataReader.ReadUnsignedLEB128(0);
|
||||||
|
piece.SetSize(bitSize, fDataReader.ReadUnsignedLEB128(0));
|
||||||
|
} else
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
// If there's a composition operator, there must be at least two
|
||||||
|
// simple expressions, so this must not be the end.
|
||||||
|
if (fDataReader.BytesRemaining() == 0)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
} catch (const EvaluationException& exception) {
|
||||||
|
printf("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
} catch (const std::bad_alloc& exception) {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse subsequent expressions (at least one)
|
||||||
|
while (fDataReader.BytesRemaining() > 0) {
|
||||||
|
// Restrict the data reader to the remaining bytes to prevent jumping
|
||||||
|
// back.
|
||||||
|
fDataReader.SetTo(fDataReader.Data(), fDataReader.BytesRemaining(),
|
||||||
|
fDataReader.AddressSize());
|
||||||
|
|
||||||
|
try {
|
||||||
|
ValuePieceLocation piece;
|
||||||
|
status_t error = _Evaluate(&piece);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (!piece.IsValid())
|
||||||
|
piece.SetToMemory(_Pop());
|
||||||
|
|
||||||
|
// each expression must be followed by a composition operator
|
||||||
|
if (fDataReader.BytesRemaining() == 0)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
uint8 opcode = fDataReader.Read<uint8>(0);
|
||||||
|
if (opcode == DW_OP_piece) {
|
||||||
|
piece.SetSize(fDataReader.ReadUnsignedLEB128(0));
|
||||||
|
} else if (opcode == DW_OP_bit_piece) {
|
||||||
|
uint64 bitSize = fDataReader.ReadUnsignedLEB128(0);
|
||||||
|
piece.SetSize(bitSize, fDataReader.ReadUnsignedLEB128(0));
|
||||||
|
} else
|
||||||
|
return B_BAD_DATA;
|
||||||
|
} catch (const EvaluationException& exception) {
|
||||||
|
printf("DwarfExpressionEvaluator::EvaluateLocation(): %s\n", exception.message);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
} catch (const std::bad_alloc& exception) {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfExpressionEvaluator::_Evaluate(ValuePieceLocation* _piece)
|
||||||
|
{
|
||||||
|
printf("DwarfExpressionEvaluator::_Evaluate()\n");
|
||||||
uint32 operationsExecuted = 0;
|
uint32 operationsExecuted = 0;
|
||||||
|
|
||||||
while (fDataReader.BytesRemaining() > 0) {
|
while (fDataReader.BytesRemaining() > 0) {
|
||||||
@@ -137,51 +258,66 @@ DwarfExpressionEvaluator::_Evaluate()
|
|||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case DW_OP_addr:
|
case DW_OP_addr:
|
||||||
|
printf(" DW_OP_addr\n");
|
||||||
_Push(fDataReader.ReadAddress(0));
|
_Push(fDataReader.ReadAddress(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const1u:
|
case DW_OP_const1u:
|
||||||
|
printf(" DW_OP_const1u\n");
|
||||||
_Push(fDataReader.Read<uint8>(0));
|
_Push(fDataReader.Read<uint8>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const1s:
|
case DW_OP_const1s:
|
||||||
|
printf(" DW_OP_const1s\n");
|
||||||
_Push(fDataReader.Read<int8>(0));
|
_Push(fDataReader.Read<int8>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const2u:
|
case DW_OP_const2u:
|
||||||
|
printf(" DW_OP_const2u\n");
|
||||||
_Push(fDataReader.Read<uint16>(0));
|
_Push(fDataReader.Read<uint16>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const2s:
|
case DW_OP_const2s:
|
||||||
|
printf(" DW_OP_const2s\n");
|
||||||
_Push(fDataReader.Read<int16>(0));
|
_Push(fDataReader.Read<int16>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const4u:
|
case DW_OP_const4u:
|
||||||
|
printf(" DW_OP_const4u\n");
|
||||||
_Push(fDataReader.Read<uint32>(0));
|
_Push(fDataReader.Read<uint32>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const4s:
|
case DW_OP_const4s:
|
||||||
|
printf(" DW_OP_const4s\n");
|
||||||
_Push(fDataReader.Read<int32>(0));
|
_Push(fDataReader.Read<int32>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const8u:
|
case DW_OP_const8u:
|
||||||
|
printf(" DW_OP_const8u\n");
|
||||||
_Push(fDataReader.Read<uint64>(0));
|
_Push(fDataReader.Read<uint64>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_const8s:
|
case DW_OP_const8s:
|
||||||
|
printf(" DW_OP_const8s\n");
|
||||||
_Push(fDataReader.Read<int64>(0));
|
_Push(fDataReader.Read<int64>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_constu:
|
case DW_OP_constu:
|
||||||
|
printf(" DW_OP_constu\n");
|
||||||
_Push(fDataReader.ReadUnsignedLEB128(0));
|
_Push(fDataReader.ReadUnsignedLEB128(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_consts:
|
case DW_OP_consts:
|
||||||
|
printf(" DW_OP_consts\n");
|
||||||
_Push(fDataReader.ReadSignedLEB128(0));
|
_Push(fDataReader.ReadSignedLEB128(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_dup:
|
case DW_OP_dup:
|
||||||
|
printf(" DW_OP_dup\n");
|
||||||
_AssertMinStackSize(1);
|
_AssertMinStackSize(1);
|
||||||
_Push(fStack[fStackSize - 1]);
|
_Push(fStack[fStackSize - 1]);
|
||||||
break;
|
break;
|
||||||
case DW_OP_drop:
|
case DW_OP_drop:
|
||||||
|
printf(" DW_OP_drop\n");
|
||||||
_Pop();
|
_Pop();
|
||||||
break;
|
break;
|
||||||
case DW_OP_over:
|
case DW_OP_over:
|
||||||
|
printf(" DW_OP_over\n");
|
||||||
_AssertMinStackSize(1);
|
_AssertMinStackSize(1);
|
||||||
_Push(fStack[fStackSize - 2]);
|
_Push(fStack[fStackSize - 2]);
|
||||||
break;
|
break;
|
||||||
case DW_OP_pick:
|
case DW_OP_pick:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_pick\n");
|
||||||
uint8 index = fDataReader.Read<uint8>(0);
|
uint8 index = fDataReader.Read<uint8>(0);
|
||||||
_AssertMinStackSize(index + 1);
|
_AssertMinStackSize(index + 1);
|
||||||
_Push(fStack[fStackSize - index - 1]);
|
_Push(fStack[fStackSize - index - 1]);
|
||||||
@@ -189,12 +325,14 @@ DwarfExpressionEvaluator::_Evaluate()
|
|||||||
}
|
}
|
||||||
case DW_OP_swap:
|
case DW_OP_swap:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_swap\n");
|
||||||
_AssertMinStackSize(2);
|
_AssertMinStackSize(2);
|
||||||
std::swap(fStack[fStackSize - 1], fStack[fStackSize - 2]);
|
std::swap(fStack[fStackSize - 1], fStack[fStackSize - 2]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_rot:
|
case DW_OP_rot:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_rot\n");
|
||||||
_AssertMinStackSize(3);
|
_AssertMinStackSize(3);
|
||||||
target_addr_t tmp = fStack[fStackSize - 1];
|
target_addr_t tmp = fStack[fStackSize - 1];
|
||||||
fStack[fStackSize - 1] = fStack[fStackSize - 2];
|
fStack[fStackSize - 1] = fStack[fStackSize - 2];
|
||||||
@@ -204,20 +342,25 @@ DwarfExpressionEvaluator::_Evaluate()
|
|||||||
}
|
}
|
||||||
|
|
||||||
case DW_OP_deref:
|
case DW_OP_deref:
|
||||||
|
printf(" DW_OP_deref\n");
|
||||||
_DereferenceAddress(fContext->AddressSize());
|
_DereferenceAddress(fContext->AddressSize());
|
||||||
break;
|
break;
|
||||||
case DW_OP_deref_size:
|
case DW_OP_deref_size:
|
||||||
|
printf(" DW_OP_deref_size\n");
|
||||||
_DereferenceAddress(fDataReader.Read<uint8>(0));
|
_DereferenceAddress(fDataReader.Read<uint8>(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_xderef:
|
case DW_OP_xderef:
|
||||||
|
printf(" DW_OP_xderef\n");
|
||||||
_DereferenceAddressSpaceAddress(fContext->AddressSize());
|
_DereferenceAddressSpaceAddress(fContext->AddressSize());
|
||||||
break;
|
break;
|
||||||
case DW_OP_xderef_size:
|
case DW_OP_xderef_size:
|
||||||
|
printf(" DW_OP_xderef_size\n");
|
||||||
_DereferenceAddressSpaceAddress(fDataReader.Read<uint8>(0));
|
_DereferenceAddressSpaceAddress(fDataReader.Read<uint8>(0));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_OP_abs:
|
case DW_OP_abs:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_abs\n");
|
||||||
target_addr_t value = _Pop();
|
target_addr_t value = _Pop();
|
||||||
if (fContext->AddressSize() == 4) {
|
if (fContext->AddressSize() == 4) {
|
||||||
int32 signedValue = (int32)value;
|
int32 signedValue = (int32)value;
|
||||||
@@ -229,10 +372,12 @@ DwarfExpressionEvaluator::_Evaluate()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_and:
|
case DW_OP_and:
|
||||||
|
printf(" DW_OP_and\n");
|
||||||
_Push(_Pop() & _Pop());
|
_Push(_Pop() & _Pop());
|
||||||
break;
|
break;
|
||||||
case DW_OP_div:
|
case DW_OP_div:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_div\n");
|
||||||
int64 top = (int64)_Pop();
|
int64 top = (int64)_Pop();
|
||||||
int64 second = (int64)_Pop();
|
int64 second = (int64)_Pop();
|
||||||
_Push(top != 0 ? second / top : 0);
|
_Push(top != 0 ? second / top : 0);
|
||||||
@@ -240,12 +385,14 @@ DwarfExpressionEvaluator::_Evaluate()
|
|||||||
}
|
}
|
||||||
case DW_OP_minus:
|
case DW_OP_minus:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_minus\n");
|
||||||
target_addr_t top = _Pop();
|
target_addr_t top = _Pop();
|
||||||
_Push(_Pop() - top);
|
_Push(_Pop() - top);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_mod:
|
case DW_OP_mod:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_mod\n");
|
||||||
// While the specs explicitly speak of signed integer division
|
// While the specs explicitly speak of signed integer division
|
||||||
// for "div", nothing is mentioned for "mod".
|
// for "div", nothing is mentioned for "mod".
|
||||||
target_addr_t top = _Pop();
|
target_addr_t top = _Pop();
|
||||||
@@ -254,10 +401,12 @@ DwarfExpressionEvaluator::_Evaluate()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_mul:
|
case DW_OP_mul:
|
||||||
|
printf(" DW_OP_mul\n");
|
||||||
_Push(_Pop() * _Pop());
|
_Push(_Pop() * _Pop());
|
||||||
break;
|
break;
|
||||||
case DW_OP_neg:
|
case DW_OP_neg:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_neg\n");
|
||||||
if (fContext->AddressSize() == 4)
|
if (fContext->AddressSize() == 4)
|
||||||
_Push(-(int32)_Pop());
|
_Push(-(int32)_Pop());
|
||||||
else
|
else
|
||||||
@@ -265,31 +414,38 @@ DwarfExpressionEvaluator::_Evaluate()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_not:
|
case DW_OP_not:
|
||||||
|
printf(" DW_OP_not\n");
|
||||||
_Push(~_Pop());
|
_Push(~_Pop());
|
||||||
break;
|
break;
|
||||||
case DW_OP_or:
|
case DW_OP_or:
|
||||||
|
printf(" DW_OP_or\n");
|
||||||
_Push(_Pop() | _Pop());
|
_Push(_Pop() | _Pop());
|
||||||
break;
|
break;
|
||||||
case DW_OP_plus:
|
case DW_OP_plus:
|
||||||
|
printf(" DW_OP_plus\n");
|
||||||
_Push(_Pop() + _Pop());
|
_Push(_Pop() + _Pop());
|
||||||
break;
|
break;
|
||||||
case DW_OP_plus_uconst:
|
case DW_OP_plus_uconst:
|
||||||
|
printf(" DW_OP_plus_uconst\n");
|
||||||
_Push(_Pop() + fDataReader.ReadUnsignedLEB128(0));
|
_Push(_Pop() + fDataReader.ReadUnsignedLEB128(0));
|
||||||
break;
|
break;
|
||||||
case DW_OP_shl:
|
case DW_OP_shl:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_shl\n");
|
||||||
target_addr_t top = _Pop();
|
target_addr_t top = _Pop();
|
||||||
_Push(_Pop() << top);
|
_Push(_Pop() << top);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_shr:
|
case DW_OP_shr:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_shr\n");
|
||||||
target_addr_t top = _Pop();
|
target_addr_t top = _Pop();
|
||||||
_Push(_Pop() >> top);
|
_Push(_Pop() >> top);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_shra:
|
case DW_OP_shra:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_shra\n");
|
||||||
target_addr_t top = _Pop();
|
target_addr_t top = _Pop();
|
||||||
int64 second = (int64)_Pop();
|
int64 second = (int64)_Pop();
|
||||||
_Push(second >= 0 ? second >> top : -(-second >> top));
|
_Push(second >= 0 ? second >> top : -(-second >> top));
|
||||||
@@ -297,105 +453,135 @@ DwarfExpressionEvaluator::_Evaluate()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_xor:
|
case DW_OP_xor:
|
||||||
|
printf(" DW_OP_xor\n");
|
||||||
_Push(_Pop() ^ _Pop());
|
_Push(_Pop() ^ _Pop());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_OP_bra:
|
case DW_OP_bra:
|
||||||
|
printf(" DW_OP_bra\n");
|
||||||
if (_Pop() == 0)
|
if (_Pop() == 0)
|
||||||
break;
|
break;
|
||||||
// fall through
|
// fall through
|
||||||
case DW_OP_skip:
|
case DW_OP_skip:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_skip\n");
|
||||||
int16 offset = fDataReader.Read<int16>(0);
|
int16 offset = fDataReader.Read<int16>(0);
|
||||||
if (offset >= 0 ? offset > fDataReader.BytesRemaining()
|
if (offset >= 0 ? offset > fDataReader.BytesRemaining()
|
||||||
: -offset > fDataReader.Offset()) {
|
: -offset > fDataReader.Offset()) {
|
||||||
throw EvaluationException();
|
throw EvaluationException("bra/skip: invalid offset");
|
||||||
}
|
}
|
||||||
fDataReader.SeekAbsolute(fDataReader.Offset() + offset);
|
fDataReader.SeekAbsolute(fDataReader.Offset() + offset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DW_OP_eq:
|
case DW_OP_eq:
|
||||||
|
printf(" DW_OP_eq\n");
|
||||||
_Push(_Pop() == _Pop() ? 1 : 0);
|
_Push(_Pop() == _Pop() ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
case DW_OP_ge:
|
case DW_OP_ge:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_ge\n");
|
||||||
int64 top = (int64)_Pop();
|
int64 top = (int64)_Pop();
|
||||||
_Push((int64)_Pop() >= top ? 1 : 0);
|
_Push((int64)_Pop() >= top ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_gt:
|
case DW_OP_gt:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_gt\n");
|
||||||
int64 top = (int64)_Pop();
|
int64 top = (int64)_Pop();
|
||||||
_Push((int64)_Pop() > top ? 1 : 0);
|
_Push((int64)_Pop() > top ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_le:
|
case DW_OP_le:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_le\n");
|
||||||
int64 top = (int64)_Pop();
|
int64 top = (int64)_Pop();
|
||||||
_Push((int64)_Pop() <= top ? 1 : 0);
|
_Push((int64)_Pop() <= top ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_lt:
|
case DW_OP_lt:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_lt\n");
|
||||||
int64 top = (int64)_Pop();
|
int64 top = (int64)_Pop();
|
||||||
_Push((int64)_Pop() < top ? 1 : 0);
|
_Push((int64)_Pop() < top ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_ne:
|
case DW_OP_ne:
|
||||||
|
printf(" DW_OP_ne\n");
|
||||||
_Push(_Pop() == _Pop() ? 1 : 0);
|
_Push(_Pop() == _Pop() ? 1 : 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DW_OP_push_object_address:
|
case DW_OP_push_object_address:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_push_object_address\n");
|
||||||
target_addr_t address;
|
target_addr_t address;
|
||||||
if (!fContext->GetObjectAddress(address))
|
if (!fContext->GetObjectAddress(address))
|
||||||
throw EvaluationException();
|
throw EvaluationException("failed to get object address");
|
||||||
_Push(address);
|
_Push(address);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_call_frame_cfa:
|
case DW_OP_call_frame_cfa:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_call_frame_cfa\n");
|
||||||
target_addr_t address;
|
target_addr_t address;
|
||||||
if (!fContext->GetFrameAddress(address))
|
if (!fContext->GetFrameAddress(address))
|
||||||
throw EvaluationException();
|
throw EvaluationException("failed to get frame address");
|
||||||
_Push(address);
|
_Push(address);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_fbreg:
|
case DW_OP_fbreg:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_fbreg\n");
|
||||||
target_addr_t address;
|
target_addr_t address;
|
||||||
if (!fContext->GetFrameBaseAddress(address))
|
if (!fContext->GetFrameBaseAddress(address)) {
|
||||||
throw EvaluationException();
|
throw EvaluationException(
|
||||||
|
"failed to get frame base address");
|
||||||
|
}
|
||||||
_Push(address + fDataReader.ReadSignedLEB128(0));
|
_Push(address + fDataReader.ReadSignedLEB128(0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DW_OP_form_tls_address:
|
case DW_OP_form_tls_address:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_form_tls_address\n");
|
||||||
target_addr_t address;
|
target_addr_t address;
|
||||||
if (!fContext->GetTLSAddress(_Pop(), address))
|
if (!fContext->GetTLSAddress(_Pop(), address))
|
||||||
throw EvaluationException();
|
throw EvaluationException("failed to get tls address");
|
||||||
_Push(address);
|
_Push(address);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DW_OP_regx:
|
case DW_OP_regx:
|
||||||
_PushRegister(fDataReader.ReadUnsignedLEB128(0), 0);
|
{
|
||||||
break;
|
printf(" DW_OP_regx\n");
|
||||||
|
if (_piece == NULL) {
|
||||||
|
throw EvaluationException(
|
||||||
|
"DW_OP_regx in non-location expression");
|
||||||
|
}
|
||||||
|
uint32 reg = fDataReader.ReadUnsignedLEB128(0);
|
||||||
|
if (fDataReader.HasOverflow())
|
||||||
|
throw EvaluationException("unexpected end of expression");
|
||||||
|
_piece->SetToRegister(reg);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
case DW_OP_bregx:
|
case DW_OP_bregx:
|
||||||
{
|
{
|
||||||
|
printf(" DW_OP_bregx\n");
|
||||||
uint32 reg = fDataReader.ReadUnsignedLEB128(0);
|
uint32 reg = fDataReader.ReadUnsignedLEB128(0);
|
||||||
_PushRegister(reg, fDataReader.ReadSignedLEB128(0));
|
_PushRegister(reg, fDataReader.ReadSignedLEB128(0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DW_OP_call2:
|
case DW_OP_call2:
|
||||||
|
printf(" DW_OP_call2\n");
|
||||||
_Call(fDataReader.Read<uint16>(0), true);
|
_Call(fDataReader.Read<uint16>(0), true);
|
||||||
break;
|
break;
|
||||||
case DW_OP_call4:
|
case DW_OP_call4:
|
||||||
|
printf(" DW_OP_call4\n");
|
||||||
_Call(fDataReader.Read<uint32>(0), true);
|
_Call(fDataReader.Read<uint32>(0), true);
|
||||||
break;
|
break;
|
||||||
case DW_OP_call_ref:
|
case DW_OP_call_ref:
|
||||||
|
printf(" DW_OP_call_ref\n");
|
||||||
if (fContext->AddressSize() == 4)
|
if (fContext->AddressSize() == 4)
|
||||||
_Call(fDataReader.Read<uint32>(0), false);
|
_Call(fDataReader.Read<uint32>(0), false);
|
||||||
else
|
else
|
||||||
@@ -404,19 +590,33 @@ DwarfExpressionEvaluator::_Evaluate()
|
|||||||
|
|
||||||
case DW_OP_piece:
|
case DW_OP_piece:
|
||||||
case DW_OP_bit_piece:
|
case DW_OP_bit_piece:
|
||||||
// TODO:...
|
// are handled in EvaluateLocation()
|
||||||
break;
|
if (_piece == NULL)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
fDataReader.SeekAbsolute(fDataReader.Offset() - 1);
|
||||||
|
// put back the operation
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
case DW_OP_nop:
|
case DW_OP_nop:
|
||||||
|
printf(" DW_OP_nop\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (opcode >= DW_OP_lit0 && opcode <= DW_OP_lit31) {
|
if (opcode >= DW_OP_lit0 && opcode <= DW_OP_lit31) {
|
||||||
|
printf(" DW_OP_lit%u\n", opcode - DW_OP_lit0);
|
||||||
_Push(opcode - DW_OP_lit0);
|
_Push(opcode - DW_OP_lit0);
|
||||||
} else if (opcode >= DW_OP_reg0 && opcode <= DW_OP_reg31) {
|
} else if (opcode >= DW_OP_reg0 && opcode <= DW_OP_reg31) {
|
||||||
_PushRegister(opcode - DW_OP_reg0, 0);
|
printf(" DW_OP_reg%u\n", opcode - DW_OP_reg0);
|
||||||
|
if (_piece == NULL) {
|
||||||
|
throw EvaluationException(
|
||||||
|
"DW_OP_reg* in non-location expression");
|
||||||
|
}
|
||||||
|
_piece->SetToRegister(opcode - DW_OP_reg0);
|
||||||
|
return B_OK;
|
||||||
} else if (opcode >= DW_OP_breg0 && opcode <= DW_OP_breg31) {
|
} else if (opcode >= DW_OP_breg0 && opcode <= DW_OP_breg31) {
|
||||||
_PushRegister(opcode - DW_OP_reg0,
|
printf(" DW_OP_breg%u\n", opcode - DW_OP_breg0);
|
||||||
|
_PushRegister(opcode - DW_OP_breg0,
|
||||||
fDataReader.ReadSignedLEB128(0));
|
fDataReader.ReadSignedLEB128(0));
|
||||||
} else {
|
} else {
|
||||||
printf("DwarfExpressionEvaluator::_Evaluate(): unsupported "
|
printf("DwarfExpressionEvaluator::_Evaluate(): unsupported "
|
||||||
@@ -455,14 +655,14 @@ DwarfExpressionEvaluator::_DereferenceAddress(uint8 addressSize)
|
|||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
default:
|
default:
|
||||||
throw EvaluationException();
|
throw EvaluationException("invalid dereference size");
|
||||||
}
|
}
|
||||||
|
|
||||||
target_addr_t address = _Pop();
|
target_addr_t address = _Pop();
|
||||||
BVariant value;
|
BVariant value;
|
||||||
if (!fContext->TargetInterface()->ReadValueFromMemory(address, valueType,
|
if (!fContext->TargetInterface()->ReadValueFromMemory(address, valueType,
|
||||||
value)) {
|
value)) {
|
||||||
throw EvaluationException();
|
throw EvaluationException("failed to read memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
_Push(value.ToUInt64());
|
_Push(value.ToUInt64());
|
||||||
@@ -490,7 +690,7 @@ DwarfExpressionEvaluator::_DereferenceAddressSpaceAddress(uint8 addressSize)
|
|||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
default:
|
default:
|
||||||
throw EvaluationException();
|
throw EvaluationException("invalid dereference size");
|
||||||
}
|
}
|
||||||
|
|
||||||
target_addr_t address = _Pop();
|
target_addr_t address = _Pop();
|
||||||
@@ -498,7 +698,7 @@ DwarfExpressionEvaluator::_DereferenceAddressSpaceAddress(uint8 addressSize)
|
|||||||
BVariant value;
|
BVariant value;
|
||||||
if (!fContext->TargetInterface()->ReadValueFromMemory(addressSpace, address,
|
if (!fContext->TargetInterface()->ReadValueFromMemory(addressSpace, address,
|
||||||
valueType, value)) {
|
valueType, value)) {
|
||||||
throw EvaluationException();
|
throw EvaluationException("failed to read memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
_Push(value.ToUInt64());
|
_Push(value.ToUInt64());
|
||||||
@@ -510,7 +710,7 @@ DwarfExpressionEvaluator::_PushRegister(uint32 reg, target_addr_t offset)
|
|||||||
{
|
{
|
||||||
BVariant value;
|
BVariant value;
|
||||||
if (!fContext->TargetInterface()->GetRegisterValue(reg, value))
|
if (!fContext->TargetInterface()->GetRegisterValue(reg, value))
|
||||||
throw EvaluationException();
|
throw EvaluationException("failed to get register");
|
||||||
|
|
||||||
_Push(value.ToUInt64());
|
_Push(value.ToUInt64());
|
||||||
}
|
}
|
||||||
@@ -520,13 +720,13 @@ void
|
|||||||
DwarfExpressionEvaluator::_Call(uint64 offset, bool local)
|
DwarfExpressionEvaluator::_Call(uint64 offset, bool local)
|
||||||
{
|
{
|
||||||
if (fDataReader.HasOverflow())
|
if (fDataReader.HasOverflow())
|
||||||
throw EvaluationException();
|
throw EvaluationException("unexpected end of expression");
|
||||||
|
|
||||||
// get the expression to "call"
|
// get the expression to "call"
|
||||||
const void* block;
|
const void* block;
|
||||||
off_t size;
|
off_t size;
|
||||||
if (fContext->GetCallTarget(offset, local, block, size) != B_OK)
|
if (fContext->GetCallTarget(offset, local, block, size) != B_OK)
|
||||||
throw EvaluationException();
|
throw EvaluationException("failed to get call target");
|
||||||
|
|
||||||
// no expression is OK, then this is just a no-op
|
// no expression is OK, then this is just a no-op
|
||||||
if (block == NULL)
|
if (block == NULL)
|
||||||
@@ -540,7 +740,8 @@ DwarfExpressionEvaluator::_Call(uint64 offset, bool local)
|
|||||||
|
|
||||||
// and evaluate it
|
// and evaluate it
|
||||||
try {
|
try {
|
||||||
_Evaluate();
|
if (_Evaluate(NULL) != B_OK)
|
||||||
|
throw EvaluationException("call failed");
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
fDataReader = savedReader;
|
fDataReader = savedReader;
|
||||||
throw;
|
throw;
|
||||||
|
|||||||
@@ -11,16 +11,18 @@
|
|||||||
|
|
||||||
|
|
||||||
class DwarfTargetInterface;
|
class DwarfTargetInterface;
|
||||||
|
class ValueLocation;
|
||||||
|
struct ValuePieceLocation;
|
||||||
|
|
||||||
|
|
||||||
class DwarfExpressionEvaluationContext {
|
class DwarfExpressionEvaluationContext {
|
||||||
public:
|
public:
|
||||||
DwarfExpressionEvaluationContext(
|
DwarfExpressionEvaluationContext(
|
||||||
DwarfTargetInterface* targetInterface,
|
const DwarfTargetInterface* targetInterface,
|
||||||
uint8 addressSize);
|
uint8 addressSize);
|
||||||
virtual ~DwarfExpressionEvaluationContext();
|
virtual ~DwarfExpressionEvaluationContext();
|
||||||
|
|
||||||
DwarfTargetInterface* TargetInterface() const
|
const DwarfTargetInterface* TargetInterface() const
|
||||||
{ return fTargetInterface; }
|
{ return fTargetInterface; }
|
||||||
uint8 AddressSize() const { return fAddressSize; }
|
uint8 AddressSize() const { return fAddressSize; }
|
||||||
|
|
||||||
@@ -38,8 +40,8 @@ public:
|
|||||||
// block, when the entry doesn't have a
|
// block, when the entry doesn't have a
|
||||||
// location attribute
|
// location attribute
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
DwarfTargetInterface* fTargetInterface;
|
const DwarfTargetInterface* fTargetInterface;
|
||||||
uint8 fAddressSize;
|
uint8 fAddressSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,10 +52,12 @@ public:
|
|||||||
DwarfExpressionEvaluationContext* context);
|
DwarfExpressionEvaluationContext* context);
|
||||||
~DwarfExpressionEvaluator();
|
~DwarfExpressionEvaluator();
|
||||||
|
|
||||||
void SetObjectAddress(target_addr_t address);
|
status_t Push(target_addr_t value);
|
||||||
void SetFrameAddress(target_addr_t address);
|
|
||||||
|
|
||||||
status_t Evaluate(const void* expression, size_t size);
|
status_t Evaluate(const void* expression, size_t size,
|
||||||
|
target_addr_t& _result);
|
||||||
|
status_t EvaluateLocation(const void* expression,
|
||||||
|
size_t size, ValueLocation& _location);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct EvaluationException;
|
struct EvaluationException;
|
||||||
@@ -64,7 +68,7 @@ private:
|
|||||||
inline void _Push(target_addr_t value);
|
inline void _Push(target_addr_t value);
|
||||||
inline target_addr_t _Pop();
|
inline target_addr_t _Pop();
|
||||||
|
|
||||||
status_t _Evaluate();
|
status_t _Evaluate(ValuePieceLocation* _piece);
|
||||||
void _DereferenceAddress(uint8 addressSize);
|
void _DereferenceAddress(uint8 addressSize);
|
||||||
void _DereferenceAddressSpaceAddress(
|
void _DereferenceAddressSpaceAddress(
|
||||||
uint8 addressSize);
|
uint8 addressSize);
|
||||||
|
|||||||
@@ -17,10 +17,12 @@
|
|||||||
#include "CfaContext.h"
|
#include "CfaContext.h"
|
||||||
#include "CompilationUnit.h"
|
#include "CompilationUnit.h"
|
||||||
#include "DataReader.h"
|
#include "DataReader.h"
|
||||||
|
#include "DwarfExpressionEvaluator.h"
|
||||||
#include "DwarfTargetInterface.h"
|
#include "DwarfTargetInterface.h"
|
||||||
#include "ElfFile.h"
|
#include "ElfFile.h"
|
||||||
#include "TagNames.h"
|
#include "TagNames.h"
|
||||||
#include "TargetAddressRangeList.h"
|
#include "TargetAddressRangeList.h"
|
||||||
|
#include "Variant.h"
|
||||||
|
|
||||||
|
|
||||||
DwarfFile::DwarfFile()
|
DwarfFile::DwarfFile()
|
||||||
@@ -33,6 +35,7 @@ DwarfFile::DwarfFile()
|
|||||||
fDebugRangesSection(NULL),
|
fDebugRangesSection(NULL),
|
||||||
fDebugLineSection(NULL),
|
fDebugLineSection(NULL),
|
||||||
fDebugFrameSection(NULL),
|
fDebugFrameSection(NULL),
|
||||||
|
fDebugLocationSection(NULL),
|
||||||
fCompilationUnits(20, true),
|
fCompilationUnits(20, true),
|
||||||
fCurrentCompilationUnit(NULL),
|
fCurrentCompilationUnit(NULL),
|
||||||
fFinished(false),
|
fFinished(false),
|
||||||
@@ -53,6 +56,7 @@ DwarfFile::~DwarfFile()
|
|||||||
fElfFile->PutSection(fDebugRangesSection);
|
fElfFile->PutSection(fDebugRangesSection);
|
||||||
fElfFile->PutSection(fDebugLineSection);
|
fElfFile->PutSection(fDebugLineSection);
|
||||||
fElfFile->PutSection(fDebugFrameSection);
|
fElfFile->PutSection(fDebugFrameSection);
|
||||||
|
fElfFile->PutSection(fDebugLocationSection);
|
||||||
delete fElfFile;
|
delete fElfFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,6 +95,7 @@ DwarfFile::Load(const char* fileName)
|
|||||||
fDebugRangesSection = fElfFile->GetSection(".debug_ranges");
|
fDebugRangesSection = fElfFile->GetSection(".debug_ranges");
|
||||||
fDebugLineSection = fElfFile->GetSection(".debug_line");
|
fDebugLineSection = fElfFile->GetSection(".debug_line");
|
||||||
fDebugFrameSection = fElfFile->GetSection(".debug_frame");
|
fDebugFrameSection = fElfFile->GetSection(".debug_frame");
|
||||||
|
fDebugLocationSection = fElfFile->GetSection(".debug_loc");
|
||||||
|
|
||||||
// iterate through the debug info section
|
// iterate through the debug info section
|
||||||
DataReader dataReader(fDebugInfoSection->Data(),
|
DataReader dataReader(fDebugInfoSection->Data(),
|
||||||
@@ -270,7 +275,8 @@ DwarfFile::ResolveRangeList(CompilationUnit* unit, uint64 offset) const
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfFile::UnwindCallFrame(CompilationUnit* unit, target_addr_t location,
|
DwarfFile::UnwindCallFrame(CompilationUnit* unit,
|
||||||
|
DIESubprogram* subprogramEntry, target_addr_t location,
|
||||||
const DwarfTargetInterface* inputInterface,
|
const DwarfTargetInterface* inputInterface,
|
||||||
DwarfTargetInterface* outputInterface, target_addr_t& _framePointer)
|
DwarfTargetInterface* outputInterface, target_addr_t& _framePointer)
|
||||||
{
|
{
|
||||||
@@ -365,8 +371,16 @@ printf(" found row!\n");
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CFA_CFA_RULE_EXPRESSION:
|
case CFA_CFA_RULE_EXPRESSION:
|
||||||
// TODO: Implement!
|
{
|
||||||
return B_UNSUPPORTED;
|
error = EvaluateExpression(unit, subprogramEntry,
|
||||||
|
cfaCfaRule->Expression().block,
|
||||||
|
cfaCfaRule->Expression().size,
|
||||||
|
inputInterface, location, 0, 0, false,
|
||||||
|
frameAddress);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case CFA_CFA_RULE_UNDEFINED:
|
case CFA_CFA_RULE_UNDEFINED:
|
||||||
default:
|
default:
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -421,13 +435,35 @@ printf(" -> CFA_RULE_REGISTER\n");
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CFA_RULE_LOCATION_EXPRESSION:
|
case CFA_RULE_LOCATION_EXPRESSION:
|
||||||
|
{
|
||||||
printf(" -> CFA_RULE_LOCATION_EXPRESSION\n");
|
printf(" -> CFA_RULE_LOCATION_EXPRESSION\n");
|
||||||
// TODO:...
|
target_addr_t address;
|
||||||
|
error = EvaluateExpression(unit, subprogramEntry,
|
||||||
|
rule->Expression().block,
|
||||||
|
rule->Expression().size,
|
||||||
|
inputInterface, location, frameAddress,
|
||||||
|
frameAddress, true, address);
|
||||||
|
BVariant value;
|
||||||
|
if (error == B_OK
|
||||||
|
&& inputInterface->ReadValueFromMemory(address,
|
||||||
|
valueType, value)) {
|
||||||
|
outputInterface->SetRegisterValue(i, value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CFA_RULE_VALUE_EXPRESSION:
|
case CFA_RULE_VALUE_EXPRESSION:
|
||||||
|
{
|
||||||
printf(" -> CFA_RULE_VALUE_EXPRESSION\n");
|
printf(" -> CFA_RULE_VALUE_EXPRESSION\n");
|
||||||
// TODO:...
|
target_addr_t value;
|
||||||
|
error = EvaluateExpression(unit, subprogramEntry,
|
||||||
|
rule->Expression().block,
|
||||||
|
rule->Expression().size,
|
||||||
|
inputInterface, location, frameAddress,
|
||||||
|
frameAddress, true, value);
|
||||||
|
if (error == B_OK)
|
||||||
|
outputInterface->SetRegisterValue(i, value);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case CFA_RULE_UNDEFINED:
|
case CFA_RULE_UNDEFINED:
|
||||||
printf(" -> CFA_RULE_UNDEFINED\n");
|
printf(" -> CFA_RULE_UNDEFINED\n");
|
||||||
default:
|
default:
|
||||||
@@ -447,6 +483,275 @@ printf(" -> CFA_RULE_UNDEFINED\n");
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct DwarfFile::ExpressionEvaluationContext
|
||||||
|
: DwarfExpressionEvaluationContext {
|
||||||
|
public:
|
||||||
|
ExpressionEvaluationContext(DwarfFile* file, CompilationUnit* unit,
|
||||||
|
DIESubprogram* subprogramEntry,
|
||||||
|
const DwarfTargetInterface* targetInterface,
|
||||||
|
target_addr_t instructionPointer, target_addr_t objectPointer,
|
||||||
|
target_addr_t framePointer)
|
||||||
|
:
|
||||||
|
DwarfExpressionEvaluationContext(targetInterface, unit->AddressSize()),
|
||||||
|
fFile(file),
|
||||||
|
fUnit(unit),
|
||||||
|
fSubprogramEntry(subprogramEntry),
|
||||||
|
fInstructionPointer(instructionPointer),
|
||||||
|
fObjectPointer(objectPointer),
|
||||||
|
fFramePointer(framePointer),
|
||||||
|
fFrameBasePointer(0),
|
||||||
|
fFrameBaseEvaluated(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool GetObjectAddress(target_addr_t& _address)
|
||||||
|
{
|
||||||
|
if (fObjectPointer == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_address = fObjectPointer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool GetFrameAddress(target_addr_t& _address)
|
||||||
|
{
|
||||||
|
_address = fFramePointer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool GetFrameBaseAddress(target_addr_t& _address)
|
||||||
|
{
|
||||||
|
if (fFrameBaseEvaluated) {
|
||||||
|
if (fFrameBasePointer == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_address = fFrameBasePointer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set flag already to prevent recursion for a buggy expression
|
||||||
|
fFrameBaseEvaluated = true;
|
||||||
|
|
||||||
|
// get the subprogram's frame base location
|
||||||
|
const LocationDescription* location = fSubprogramEntry->FrameBase();
|
||||||
|
if (!location->IsValid())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// get the expression
|
||||||
|
const void* expression;
|
||||||
|
off_t expressionLength;
|
||||||
|
status_t error = fFile->_GetLocationExpression(fUnit, location,
|
||||||
|
fInstructionPointer, expression, expressionLength);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// evaluate the expression
|
||||||
|
DwarfExpressionEvaluator evaluator(this);
|
||||||
|
error = evaluator.Evaluate(expression, expressionLength,
|
||||||
|
fFrameBasePointer);
|
||||||
|
if (error != B_OK)
|
||||||
|
return false;
|
||||||
|
printf(" -> frame base: %llx\n", fFrameBasePointer);
|
||||||
|
_address = fFrameBasePointer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool GetTLSAddress(target_addr_t localAddress,
|
||||||
|
target_addr_t& _address)
|
||||||
|
{
|
||||||
|
// TODO:...
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual status_t GetCallTarget(uint64 offset, bool local,
|
||||||
|
const void*& _block, off_t& _size)
|
||||||
|
{
|
||||||
|
// resolve the entry
|
||||||
|
DebugInfoEntry* entry = fFile->_ResolveReference(fUnit, offset, local);
|
||||||
|
if (entry == NULL)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
// get the location description
|
||||||
|
LocationDescription* location = entry->GetLocationDescription();
|
||||||
|
if (location == NULL || !location->IsValid()) {
|
||||||
|
_block = NULL;
|
||||||
|
_size = 0;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the expression
|
||||||
|
return fFile->_GetLocationExpression(fUnit, location,
|
||||||
|
fInstructionPointer, _block, _size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DwarfFile* fFile;
|
||||||
|
CompilationUnit* fUnit;
|
||||||
|
DIESubprogram* fSubprogramEntry;
|
||||||
|
target_addr_t fInstructionPointer;
|
||||||
|
target_addr_t fObjectPointer;
|
||||||
|
target_addr_t fFramePointer;
|
||||||
|
target_addr_t fFrameBasePointer;
|
||||||
|
bool fFrameBaseEvaluated;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::EvaluateExpression(CompilationUnit* unit,
|
||||||
|
DIESubprogram* subprogramEntry, const void* expression,
|
||||||
|
off_t expressionLength, const DwarfTargetInterface* targetInterface,
|
||||||
|
target_addr_t instructionPointer, target_addr_t framePointer,
|
||||||
|
target_addr_t valueToPush, bool pushValue, target_addr_t& _result)
|
||||||
|
{
|
||||||
|
ExpressionEvaluationContext context(this, unit, subprogramEntry,
|
||||||
|
targetInterface, instructionPointer, 0, framePointer);
|
||||||
|
DwarfExpressionEvaluator evaluator(&context);
|
||||||
|
|
||||||
|
if (pushValue && evaluator.Push(valueToPush) != B_OK)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
return evaluator.Evaluate(expression, expressionLength, _result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::ResolveLocation(CompilationUnit* unit,
|
||||||
|
DIESubprogram* subprogramEntry, const LocationDescription* location,
|
||||||
|
const DwarfTargetInterface* targetInterface,
|
||||||
|
target_addr_t instructionPointer, target_addr_t objectPointer,
|
||||||
|
target_addr_t framePointer, ValueLocation& _result)
|
||||||
|
{
|
||||||
|
// get the expression
|
||||||
|
const void* expression;
|
||||||
|
off_t expressionLength;
|
||||||
|
status_t error = _GetLocationExpression(unit, location, instructionPointer,
|
||||||
|
expression, expressionLength);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// evaluate it
|
||||||
|
ExpressionEvaluationContext context(this, unit, subprogramEntry,
|
||||||
|
targetInterface, instructionPointer, objectPointer, framePointer);
|
||||||
|
DwarfExpressionEvaluator evaluator(&context);
|
||||||
|
return evaluator.EvaluateLocation(expression, expressionLength, _result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::EvaluateConstantValue(CompilationUnit* unit,
|
||||||
|
DIESubprogram* subprogramEntry, const ConstantAttributeValue* value,
|
||||||
|
const DwarfTargetInterface* targetInterface,
|
||||||
|
target_addr_t instructionPointer, target_addr_t framePointer,
|
||||||
|
BVariant& _result)
|
||||||
|
{
|
||||||
|
if (!value->IsValid())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
switch (value->attributeClass) {
|
||||||
|
case ATTRIBUTE_CLASS_CONSTANT:
|
||||||
|
_result.SetTo(value->constant);
|
||||||
|
return B_OK;
|
||||||
|
case ATTRIBUTE_CLASS_STRING:
|
||||||
|
_result.SetTo(value->string);
|
||||||
|
return B_OK;
|
||||||
|
case ATTRIBUTE_CLASS_BLOCK:
|
||||||
|
{
|
||||||
|
target_addr_t result;
|
||||||
|
status_t error = EvaluateExpression(unit, subprogramEntry,
|
||||||
|
value->block.data, value->block.length, targetInterface,
|
||||||
|
instructionPointer, framePointer, 0, false, result);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
_result.SetTo(result);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::EvaluateDynamicValue(CompilationUnit* unit,
|
||||||
|
DIESubprogram* subprogramEntry, const DynamicAttributeValue* value,
|
||||||
|
const DwarfTargetInterface* targetInterface,
|
||||||
|
target_addr_t instructionPointer, target_addr_t framePointer,
|
||||||
|
BVariant& _result)
|
||||||
|
{
|
||||||
|
if (!value->IsValid())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
switch (value->attributeClass) {
|
||||||
|
case ATTRIBUTE_CLASS_CONSTANT:
|
||||||
|
_result.SetTo(value->constant);
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
case ATTRIBUTE_CLASS_REFERENCE:
|
||||||
|
{
|
||||||
|
// TODO: The specs are a bit fuzzy on this one: "the value is a
|
||||||
|
// reference to another entity whose value is the value of the
|
||||||
|
// attribute". Supposedly that also means e.g. if the referenced
|
||||||
|
// entity is a variable, we should read the value of that variable.
|
||||||
|
// ATM we only check for the types that can have a DW_AT_const_value
|
||||||
|
// attribute and evaluate it, if present.
|
||||||
|
DebugInfoEntry* entry = value->reference;
|
||||||
|
if (entry == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
const ConstantAttributeValue* constantValue = NULL;
|
||||||
|
|
||||||
|
switch (entry->Tag()) {
|
||||||
|
case DW_TAG_constant:
|
||||||
|
constantValue = dynamic_cast<DIEConstant*>(entry)
|
||||||
|
->ConstValue();
|
||||||
|
break;
|
||||||
|
case DW_TAG_enumerator:
|
||||||
|
constantValue = dynamic_cast<DIEEnumerator*>(entry)
|
||||||
|
->ConstValue();
|
||||||
|
break;
|
||||||
|
case DW_TAG_formal_parameter:
|
||||||
|
constantValue = dynamic_cast<DIEFormalParameter*>(entry)
|
||||||
|
->ConstValue();
|
||||||
|
break;
|
||||||
|
case DW_TAG_template_value_parameter:
|
||||||
|
constantValue = dynamic_cast<DIETemplateValueParameter*>(
|
||||||
|
entry)->ConstValue();
|
||||||
|
break;
|
||||||
|
case DW_TAG_variable:
|
||||||
|
constantValue = dynamic_cast<DIEVariable*>(entry)
|
||||||
|
->ConstValue();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constantValue == NULL || !constantValue->IsValid())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
return EvaluateConstantValue(unit, subprogramEntry, constantValue,
|
||||||
|
targetInterface, instructionPointer, framePointer, _result);
|
||||||
|
}
|
||||||
|
|
||||||
|
case ATTRIBUTE_CLASS_BLOCK:
|
||||||
|
{
|
||||||
|
target_addr_t result;
|
||||||
|
status_t error = EvaluateExpression(unit, subprogramEntry,
|
||||||
|
value->block.data, value->block.length, targetInterface,
|
||||||
|
instructionPointer, framePointer, 0, false, result);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
_result.SetTo(result);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
|
DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
|
||||||
{
|
{
|
||||||
@@ -800,8 +1105,8 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
|
|||||||
break;
|
break;
|
||||||
case ATTRIBUTE_CLASS_REFERENCE:
|
case ATTRIBUTE_CLASS_REFERENCE:
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
attributeValue.SetToReference(_ResolveReference(value,
|
attributeValue.SetToReference(_ResolveReference(
|
||||||
localReference));
|
fCurrentCompilationUnit, value, localReference));
|
||||||
if (attributeValue.reference == NULL) {
|
if (attributeValue.reference == NULL) {
|
||||||
// gcc 2 apparently somtimes produces DW_AT_sibling
|
// gcc 2 apparently somtimes produces DW_AT_sibling
|
||||||
// attributes pointing to the end of the sibling list.
|
// attributes pointing to the end of the sibling list.
|
||||||
@@ -1372,11 +1677,84 @@ DwarfFile::_GetAbbreviationTable(off_t offset, AbbreviationTable*& _table)
|
|||||||
|
|
||||||
|
|
||||||
DebugInfoEntry*
|
DebugInfoEntry*
|
||||||
DwarfFile::_ResolveReference(uint64 offset, bool localReference) const
|
DwarfFile::_ResolveReference(CompilationUnit* unit, uint64 offset,
|
||||||
|
bool localReference) const
|
||||||
{
|
{
|
||||||
if (localReference)
|
if (localReference)
|
||||||
return fCurrentCompilationUnit->EntryForOffset(offset);
|
return unit->EntryForOffset(offset);
|
||||||
|
|
||||||
// TODO: Implement program-global references!
|
// TODO: Implement program-global references!
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_GetLocationExpression(CompilationUnit* unit,
|
||||||
|
const LocationDescription* location, target_addr_t instructionPointer,
|
||||||
|
const void*& _expression, off_t& _length) const
|
||||||
|
{
|
||||||
|
if (!location->IsValid())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (location->IsExpression()) {
|
||||||
|
_expression = location->expression.data;
|
||||||
|
_length = location->expression.length;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (location->IsLocationList()) {
|
||||||
|
return _FindLocationExpression(unit, location->listOffset,
|
||||||
|
instructionPointer, _expression, _length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DwarfFile::_FindLocationExpression(CompilationUnit* unit, uint64 offset,
|
||||||
|
target_addr_t address, const void*& _expression, off_t& _length) const
|
||||||
|
{
|
||||||
|
if (unit == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (fDebugLocationSection == NULL)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
if (offset < 0 || offset >= (uint64)fDebugLocationSection->Size())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
target_addr_t baseAddress = unit->AddressRangeBase();
|
||||||
|
target_addr_t maxAddress = unit->MaxAddress();
|
||||||
|
|
||||||
|
DataReader dataReader((uint8*)fDebugLocationSection->Data() + offset,
|
||||||
|
fDebugLocationSection->Size() - offset, unit->AddressSize());
|
||||||
|
while (true) {
|
||||||
|
target_addr_t start = dataReader.ReadAddress(0);
|
||||||
|
target_addr_t end = dataReader.ReadAddress(0);
|
||||||
|
if (dataReader.HasOverflow())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
if (start == 0 && end == 0)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
if (start == maxAddress) {
|
||||||
|
baseAddress = end;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 expressionLength = dataReader.Read<uint16>(0);
|
||||||
|
const void* expression = dataReader.Data();
|
||||||
|
if (!dataReader.Skip(expressionLength))
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
if (start == end)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (address >= start && address < end) {
|
||||||
|
_expression = expression;
|
||||||
|
_length = expressionLength;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
class AbbreviationEntry;
|
class AbbreviationEntry;
|
||||||
class AbbreviationTable;
|
class AbbreviationTable;
|
||||||
|
class BVariant;
|
||||||
class CfaContext;
|
class CfaContext;
|
||||||
class CompilationUnit;
|
class CompilationUnit;
|
||||||
class DataReader;
|
class DataReader;
|
||||||
@@ -21,6 +22,7 @@ class DwarfTargetInterface;
|
|||||||
class ElfFile;
|
class ElfFile;
|
||||||
class ElfSection;
|
class ElfSection;
|
||||||
class TargetAddressRangeList;
|
class TargetAddressRangeList;
|
||||||
|
class ValueLocation;
|
||||||
|
|
||||||
|
|
||||||
class DwarfFile : public DoublyLinkedListLinkImpl<DwarfFile> {
|
class DwarfFile : public DoublyLinkedListLinkImpl<DwarfFile> {
|
||||||
@@ -43,12 +45,48 @@ public:
|
|||||||
uint64 offset) const;
|
uint64 offset) const;
|
||||||
|
|
||||||
status_t UnwindCallFrame(CompilationUnit* unit,
|
status_t UnwindCallFrame(CompilationUnit* unit,
|
||||||
|
DIESubprogram* subprogramEntry,
|
||||||
target_addr_t location,
|
target_addr_t location,
|
||||||
const DwarfTargetInterface* inputInterface,
|
const DwarfTargetInterface* inputInterface,
|
||||||
DwarfTargetInterface* outputInterface,
|
DwarfTargetInterface* outputInterface,
|
||||||
target_addr_t& _framePointer);
|
target_addr_t& _framePointer);
|
||||||
|
|
||||||
|
status_t EvaluateExpression(CompilationUnit* unit,
|
||||||
|
DIESubprogram* subprogramEntry,
|
||||||
|
const void* expression,
|
||||||
|
off_t expressionLength,
|
||||||
|
const DwarfTargetInterface* targetInterface,
|
||||||
|
target_addr_t instructionPointer,
|
||||||
|
target_addr_t framePointer,
|
||||||
|
target_addr_t valueToPush, bool pushValue,
|
||||||
|
target_addr_t& _result);
|
||||||
|
status_t ResolveLocation(CompilationUnit* unit,
|
||||||
|
DIESubprogram* subprogramEntry,
|
||||||
|
const LocationDescription* location,
|
||||||
|
const DwarfTargetInterface* targetInterface,
|
||||||
|
target_addr_t instructionPointer,
|
||||||
|
target_addr_t objectPointer,
|
||||||
|
target_addr_t framePointer,
|
||||||
|
ValueLocation& _result);
|
||||||
|
|
||||||
|
status_t EvaluateConstantValue(CompilationUnit* unit,
|
||||||
|
DIESubprogram* subprogramEntry,
|
||||||
|
const ConstantAttributeValue* value,
|
||||||
|
const DwarfTargetInterface* targetInterface,
|
||||||
|
target_addr_t instructionPointer,
|
||||||
|
target_addr_t framePointer,
|
||||||
|
BVariant& _result);
|
||||||
|
status_t EvaluateDynamicValue(CompilationUnit* unit,
|
||||||
|
DIESubprogram* subprogramEntry,
|
||||||
|
const DynamicAttributeValue* value,
|
||||||
|
const DwarfTargetInterface* targetInterface,
|
||||||
|
target_addr_t instructionPointer,
|
||||||
|
target_addr_t framePointer,
|
||||||
|
BVariant& _result);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct ExpressionEvaluationContext;
|
||||||
|
|
||||||
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
|
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
|
||||||
typedef BObjectList<CompilationUnit> CompilationUnitList;
|
typedef BObjectList<CompilationUnit> CompilationUnitList;
|
||||||
|
|
||||||
@@ -75,10 +113,18 @@ private:
|
|||||||
status_t _GetAbbreviationTable(off_t offset,
|
status_t _GetAbbreviationTable(off_t offset,
|
||||||
AbbreviationTable*& _table);
|
AbbreviationTable*& _table);
|
||||||
|
|
||||||
DebugInfoEntry* _ResolveReference(uint64 offset,
|
DebugInfoEntry* _ResolveReference(CompilationUnit* unit,
|
||||||
bool localReference) const;
|
uint64 offset, bool localReference) const;
|
||||||
TargetAddressRangeList* _ResolveRangeList(uint64 offset);
|
|
||||||
// returns reference
|
status_t _GetLocationExpression(CompilationUnit* unit,
|
||||||
|
const LocationDescription* location,
|
||||||
|
target_addr_t instructionPointer,
|
||||||
|
const void*& _expression,
|
||||||
|
off_t& _length) const;
|
||||||
|
status_t _FindLocationExpression(CompilationUnit* unit,
|
||||||
|
uint64 offset, target_addr_t address,
|
||||||
|
const void*& _expression,
|
||||||
|
off_t& _length) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* fName;
|
char* fName;
|
||||||
@@ -89,6 +135,7 @@ private:
|
|||||||
ElfSection* fDebugRangesSection;
|
ElfSection* fDebugRangesSection;
|
||||||
ElfSection* fDebugLineSection;
|
ElfSection* fDebugLineSection;
|
||||||
ElfSection* fDebugFrameSection;
|
ElfSection* fDebugFrameSection;
|
||||||
|
ElfSection* fDebugLocationSection;
|
||||||
AbbreviationTableList fAbbreviationTables;
|
AbbreviationTableList fAbbreviationTables;
|
||||||
DebugInfoEntryFactory fDebugInfoFactory;
|
DebugInfoEntryFactory fDebugInfoFactory;
|
||||||
CompilationUnitList fCompilationUnits;
|
CompilationUnitList fCompilationUnits;
|
||||||
|
|||||||
+13
-12
@@ -3,7 +3,7 @@
|
|||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "RegisterView.h"
|
#include "RegistersView.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
// #pragma mark - RegisterValueColumn
|
// #pragma mark - RegisterValueColumn
|
||||||
|
|
||||||
|
|
||||||
class RegisterView::RegisterValueColumn : public StringTableColumn {
|
class RegistersView::RegisterValueColumn : public StringTableColumn {
|
||||||
public:
|
public:
|
||||||
RegisterValueColumn(int32 modelIndex, const char* title, float width,
|
RegisterValueColumn(int32 modelIndex, const char* title, float width,
|
||||||
float minWidth, float maxWidth, uint32 truncate = B_TRUNCATE_MIDDLE,
|
float minWidth, float maxWidth, uint32 truncate = B_TRUNCATE_MIDDLE,
|
||||||
@@ -109,7 +109,7 @@ private:
|
|||||||
// #pragma mark - RegisterTableModel
|
// #pragma mark - RegisterTableModel
|
||||||
|
|
||||||
|
|
||||||
class RegisterView::RegisterTableModel : public TableModel {
|
class RegistersView::RegisterTableModel : public TableModel {
|
||||||
public:
|
public:
|
||||||
RegisterTableModel(Architecture* architecture)
|
RegisterTableModel(Architecture* architecture)
|
||||||
:
|
:
|
||||||
@@ -167,13 +167,14 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - RegisterView
|
// #pragma mark - RegistersView
|
||||||
|
|
||||||
|
|
||||||
RegisterView::RegisterView(Architecture* architecture)
|
RegistersView::RegistersView(Architecture* architecture)
|
||||||
:
|
:
|
||||||
BGroupView(B_VERTICAL),
|
BGroupView(B_VERTICAL),
|
||||||
fArchitecture(architecture),
|
fArchitecture(architecture),
|
||||||
|
fCpuState(NULL),
|
||||||
fRegisterTable(NULL),
|
fRegisterTable(NULL),
|
||||||
fRegisterTableModel(NULL)
|
fRegisterTableModel(NULL)
|
||||||
{
|
{
|
||||||
@@ -181,7 +182,7 @@ RegisterView::RegisterView(Architecture* architecture)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RegisterView::~RegisterView()
|
RegistersView::~RegistersView()
|
||||||
{
|
{
|
||||||
SetCpuState(NULL);
|
SetCpuState(NULL);
|
||||||
fRegisterTable->SetTableModel(NULL);
|
fRegisterTable->SetTableModel(NULL);
|
||||||
@@ -189,10 +190,10 @@ RegisterView::~RegisterView()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ RegisterView*
|
/*static*/ RegistersView*
|
||||||
RegisterView::Create(Architecture* architecture)
|
RegistersView::Create(Architecture* architecture)
|
||||||
{
|
{
|
||||||
RegisterView* self = new RegisterView(architecture);
|
RegistersView* self = new RegistersView(architecture);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
self->_Init();
|
self->_Init();
|
||||||
@@ -206,7 +207,7 @@ RegisterView::Create(Architecture* architecture)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
RegisterView::SetCpuState(CpuState* cpuState)
|
RegistersView::SetCpuState(CpuState* cpuState)
|
||||||
{
|
{
|
||||||
if (cpuState == fCpuState)
|
if (cpuState == fCpuState)
|
||||||
return;
|
return;
|
||||||
@@ -224,13 +225,13 @@ RegisterView::SetCpuState(CpuState* cpuState)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
RegisterView::TableRowInvoked(Table* table, int32 rowIndex)
|
RegistersView::TableRowInvoked(Table* table, int32 rowIndex)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
RegisterView::_Init()
|
RegistersView::_Init()
|
||||||
{
|
{
|
||||||
fRegisterTable = new Table("register list", 0, B_FANCY_BORDER);
|
fRegisterTable = new Table("register list", 0, B_FANCY_BORDER);
|
||||||
AddChild(fRegisterTable->ToView());
|
AddChild(fRegisterTable->ToView());
|
||||||
+7
-7
@@ -2,8 +2,8 @@
|
|||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef REGISTER_VIEW_H
|
#ifndef REGISTERS_VIEW_H
|
||||||
#define REGISTER_VIEW_H
|
#define REGISTERS_VIEW_H
|
||||||
|
|
||||||
#include <GroupView.h>
|
#include <GroupView.h>
|
||||||
|
|
||||||
@@ -14,12 +14,12 @@
|
|||||||
class Architecture;
|
class Architecture;
|
||||||
|
|
||||||
|
|
||||||
class RegisterView : public BGroupView, private TableListener {
|
class RegistersView : public BGroupView, private TableListener {
|
||||||
public:
|
public:
|
||||||
RegisterView(Architecture* architecture);
|
RegistersView(Architecture* architecture);
|
||||||
~RegisterView();
|
~RegistersView();
|
||||||
|
|
||||||
static RegisterView* Create(Architecture* architecture);
|
static RegistersView* Create(Architecture* architecture);
|
||||||
// throws
|
// throws
|
||||||
|
|
||||||
void SetCpuState(CpuState* cpuState);
|
void SetCpuState(CpuState* cpuState);
|
||||||
@@ -42,4 +42,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // REGISTER_VIEW_H
|
#endif // REGISTERS_VIEW_H
|
||||||
@@ -26,9 +26,10 @@
|
|||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
#include "ImageDebugInfo.h"
|
#include "ImageDebugInfo.h"
|
||||||
#include "MessageCodes.h"
|
#include "MessageCodes.h"
|
||||||
#include "RegisterView.h"
|
#include "RegistersView.h"
|
||||||
#include "StackTrace.h"
|
#include "StackTrace.h"
|
||||||
#include "StackTraceView.h"
|
#include "StackTraceView.h"
|
||||||
|
#include "VariablesView.h"
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -57,7 +58,8 @@ TeamWindow::TeamWindow(TeamDebugModel* debugModel, Listener* listener)
|
|||||||
fThreadListView(NULL),
|
fThreadListView(NULL),
|
||||||
fImageListView(NULL),
|
fImageListView(NULL),
|
||||||
fImageFunctionsView(NULL),
|
fImageFunctionsView(NULL),
|
||||||
fRegisterView(NULL),
|
fVariablesView(NULL),
|
||||||
|
fRegistersView(NULL),
|
||||||
fStackTraceView(NULL),
|
fStackTraceView(NULL),
|
||||||
fSourceView(NULL),
|
fSourceView(NULL),
|
||||||
fRunButton(NULL),
|
fRunButton(NULL),
|
||||||
@@ -386,11 +388,12 @@ TeamWindow::_Init()
|
|||||||
.Add(fImageFunctionsView = ImageFunctionsView::Create(this));
|
.Add(fImageFunctionsView = ImageFunctionsView::Create(this));
|
||||||
|
|
||||||
// add local variables tab
|
// add local variables tab
|
||||||
BView* tab = new BTextView("Variables");
|
BView* tab = fVariablesView = VariablesView::Create();
|
||||||
fLocalsTabView->AddTab(tab);
|
fLocalsTabView->AddTab(tab);
|
||||||
|
|
||||||
// add registers tab
|
// add registers tab
|
||||||
tab = fRegisterView = RegisterView::Create(fDebugModel->GetArchitecture());
|
tab = fRegistersView = RegistersView::Create(
|
||||||
|
fDebugModel->GetArchitecture());
|
||||||
fLocalsTabView->AddTab(tab);
|
fLocalsTabView->AddTab(tab);
|
||||||
|
|
||||||
fRunButton->SetMessage(new BMessage(MSG_THREAD_RUN));
|
fRunButton->SetMessage(new BMessage(MSG_THREAD_RUN));
|
||||||
@@ -529,6 +532,7 @@ TeamWindow::_SetActiveStackFrame(StackFrame* frame)
|
|||||||
_UpdateCpuState();
|
_UpdateCpuState();
|
||||||
|
|
||||||
fStackTraceView->SetStackFrame(fActiveStackFrame);
|
fStackTraceView->SetStackFrame(fActiveStackFrame);
|
||||||
|
fVariablesView->SetStackFrame(fActiveStackFrame);
|
||||||
fSourceView->SetStackFrame(fActiveStackFrame);
|
fSourceView->SetStackFrame(fActiveStackFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,7 +631,7 @@ TeamWindow::_UpdateCpuState()
|
|||||||
cpuState = fActiveStackFrame->GetCpuState();
|
cpuState = fActiveStackFrame->GetCpuState();
|
||||||
}
|
}
|
||||||
|
|
||||||
fRegisterView->SetCpuState(cpuState);
|
fRegistersView->SetCpuState(cpuState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,10 @@ class BButton;
|
|||||||
class BMenuBar;
|
class BMenuBar;
|
||||||
class BTabView;
|
class BTabView;
|
||||||
class Image;
|
class Image;
|
||||||
class RegisterView;
|
class RegistersView;
|
||||||
class SourceCode;
|
class SourceCode;
|
||||||
class StackFrame;
|
class StackFrame;
|
||||||
|
class VariablesView;
|
||||||
|
|
||||||
|
|
||||||
class TeamWindow : public BWindow, ThreadListView::Listener,
|
class TeamWindow : public BWindow, ThreadListView::Listener,
|
||||||
@@ -119,7 +120,8 @@ private:
|
|||||||
ThreadListView* fThreadListView;
|
ThreadListView* fThreadListView;
|
||||||
ImageListView* fImageListView;
|
ImageListView* fImageListView;
|
||||||
ImageFunctionsView* fImageFunctionsView;
|
ImageFunctionsView* fImageFunctionsView;
|
||||||
RegisterView* fRegisterView;
|
VariablesView* fVariablesView;
|
||||||
|
RegistersView* fRegistersView;
|
||||||
StackTraceView* fStackTraceView;
|
StackTraceView* fStackTraceView;
|
||||||
SourceView* fSourceView;
|
SourceView* fSourceView;
|
||||||
BButton* fRunButton;
|
BButton* fRunButton;
|
||||||
|
|||||||
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "VariablesView.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include "table/TableColumns.h"
|
||||||
|
|
||||||
|
#include "Architecture.h"
|
||||||
|
#include "StackFrame.h"
|
||||||
|
#include "Variable.h"
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - VariableTableModel
|
||||||
|
|
||||||
|
|
||||||
|
class VariablesView::VariableTableModel : public TableModel {
|
||||||
|
public:
|
||||||
|
VariableTableModel()
|
||||||
|
:
|
||||||
|
fStackFrame(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~VariableTableModel()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetStackFrame(StackFrame* stackFrame)
|
||||||
|
{
|
||||||
|
if (fStackFrame != NULL) {
|
||||||
|
int32 rowCount = CountRows();
|
||||||
|
fStackFrame = NULL;
|
||||||
|
NotifyRowsRemoved(0, rowCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
fStackFrame = stackFrame;
|
||||||
|
|
||||||
|
if (fStackFrame != NULL)
|
||||||
|
NotifyRowsAdded(0, CountRows());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int32 CountColumns() const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int32 CountRows() const
|
||||||
|
{
|
||||||
|
return fStackFrame != NULL
|
||||||
|
? fStackFrame->CountParameters()
|
||||||
|
+ fStackFrame->CountLocalVariables()
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool GetValueAt(int32 rowIndex, int32 columnIndex, BVariant& value)
|
||||||
|
{
|
||||||
|
if (fStackFrame == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int32 parameterCount = fStackFrame->CountParameters();
|
||||||
|
const Variable* variable = rowIndex < parameterCount
|
||||||
|
? fStackFrame->ParameterAt(rowIndex)
|
||||||
|
: fStackFrame->LocalVariableAt(rowIndex - parameterCount);
|
||||||
|
if (variable == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (columnIndex) {
|
||||||
|
case 0:
|
||||||
|
value.SetTo(variable->Name(), B_VARIANT_DONT_COPY_DATA);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
StackFrame* fStackFrame;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - VariablesView
|
||||||
|
|
||||||
|
|
||||||
|
VariablesView::VariablesView()
|
||||||
|
:
|
||||||
|
BGroupView(B_VERTICAL),
|
||||||
|
fStackFrame(NULL),
|
||||||
|
fVariableTable(NULL),
|
||||||
|
fVariableTableModel(NULL)
|
||||||
|
{
|
||||||
|
SetName("Variables");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VariablesView::~VariablesView()
|
||||||
|
{
|
||||||
|
SetStackFrame(NULL);
|
||||||
|
fVariableTable->SetTableModel(NULL);
|
||||||
|
delete fVariableTableModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ VariablesView*
|
||||||
|
VariablesView::Create()
|
||||||
|
{
|
||||||
|
VariablesView* self = new VariablesView;
|
||||||
|
|
||||||
|
try {
|
||||||
|
self->_Init();
|
||||||
|
} catch (...) {
|
||||||
|
delete self;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
VariablesView::SetStackFrame(StackFrame* stackFrame)
|
||||||
|
{
|
||||||
|
if (stackFrame == fStackFrame)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fStackFrame != NULL)
|
||||||
|
fStackFrame->RemoveReference();
|
||||||
|
|
||||||
|
fStackFrame = stackFrame;
|
||||||
|
|
||||||
|
if (fStackFrame != NULL)
|
||||||
|
fStackFrame->AddReference();
|
||||||
|
|
||||||
|
fVariableTableModel->SetStackFrame(fStackFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
VariablesView::_Init()
|
||||||
|
{
|
||||||
|
fVariableTable = new Table("variable list", 0, B_FANCY_BORDER);
|
||||||
|
AddChild(fVariableTable->ToView());
|
||||||
|
|
||||||
|
// columns
|
||||||
|
fVariableTable->AddColumn(new StringTableColumn(0, "Variable", 80, 40, 1000,
|
||||||
|
B_TRUNCATE_END, B_ALIGN_LEFT));
|
||||||
|
// fVariableTable->AddColumn(new VariableValueColumn(1, "Value", 80, 40, 1000,
|
||||||
|
// B_TRUNCATE_END, B_ALIGN_RIGHT));
|
||||||
|
|
||||||
|
fVariableTableModel = new VariableTableModel;
|
||||||
|
fVariableTable->SetTableModel(fVariableTableModel);
|
||||||
|
|
||||||
|
fVariableTable->AddTableListener(this);
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef VARIABLES_VIEW_H
|
||||||
|
#define VARIABLES_VIEW_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <GroupView.h>
|
||||||
|
|
||||||
|
#include "table/Table.h"
|
||||||
|
|
||||||
|
|
||||||
|
class StackFrame;
|
||||||
|
class Variable;
|
||||||
|
|
||||||
|
|
||||||
|
class VariablesView : public BGroupView, private TableListener {
|
||||||
|
public:
|
||||||
|
VariablesView();
|
||||||
|
~VariablesView();
|
||||||
|
|
||||||
|
static VariablesView* Create();
|
||||||
|
// throws
|
||||||
|
|
||||||
|
void SetStackFrame(StackFrame* stackFrame);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class VariableTableModel;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _Init();
|
||||||
|
|
||||||
|
private:
|
||||||
|
StackFrame* fStackFrame;
|
||||||
|
Table* fVariableTable;
|
||||||
|
VariableTableModel* fVariableTableModel;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VARIABLES_VIEW_H
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "CpuState.h"
|
#include "CpuState.h"
|
||||||
#include "FunctionInstance.h"
|
#include "FunctionInstance.h"
|
||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
|
#include "Variable.h"
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - StackFrame
|
// #pragma mark - StackFrame
|
||||||
@@ -24,15 +25,21 @@ StackFrame::StackFrame(stack_frame_type type, CpuState* cpuState,
|
|||||||
fImage(NULL),
|
fImage(NULL),
|
||||||
fFunction(NULL)
|
fFunction(NULL)
|
||||||
{
|
{
|
||||||
fCpuState->AddReference();
|
fCpuState->AcquireReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StackFrame::~StackFrame()
|
StackFrame::~StackFrame()
|
||||||
{
|
{
|
||||||
|
for (int32 i = 0; Variable* variable = fParameters.ItemAt(i); i++)
|
||||||
|
variable->ReleaseReference();
|
||||||
|
|
||||||
|
for (int32 i = 0; Variable* variable = fLocalVariables.ItemAt(i); i++)
|
||||||
|
variable->ReleaseReference();
|
||||||
|
|
||||||
SetImage(NULL);
|
SetImage(NULL);
|
||||||
SetFunction(NULL);
|
SetFunction(NULL);
|
||||||
fCpuState->RemoveReference();
|
fCpuState->ReleaseReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -47,12 +54,12 @@ void
|
|||||||
StackFrame::SetImage(Image* image)
|
StackFrame::SetImage(Image* image)
|
||||||
{
|
{
|
||||||
if (fImage != NULL)
|
if (fImage != NULL)
|
||||||
fImage->RemoveReference();
|
fImage->ReleaseReference();
|
||||||
|
|
||||||
fImage = image;
|
fImage = image;
|
||||||
|
|
||||||
if (fImage != NULL)
|
if (fImage != NULL)
|
||||||
fImage->AddReference();
|
fImage->AcquireReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -60,10 +67,60 @@ void
|
|||||||
StackFrame::SetFunction(FunctionInstance* function)
|
StackFrame::SetFunction(FunctionInstance* function)
|
||||||
{
|
{
|
||||||
if (fFunction != NULL)
|
if (fFunction != NULL)
|
||||||
fFunction->RemoveReference();
|
fFunction->ReleaseReference();
|
||||||
|
|
||||||
fFunction = function;
|
fFunction = function;
|
||||||
|
|
||||||
if (fFunction != NULL)
|
if (fFunction != NULL)
|
||||||
fFunction->AddReference();
|
fFunction->AcquireReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
StackFrame::CountParameters() const
|
||||||
|
{
|
||||||
|
return fParameters.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Variable*
|
||||||
|
StackFrame::ParameterAt(int32 index) const
|
||||||
|
{
|
||||||
|
return fParameters.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
StackFrame::AddParameter(Variable* parameter)
|
||||||
|
{
|
||||||
|
if (!fParameters.AddItem(parameter))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
parameter->AcquireReference();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
StackFrame::CountLocalVariables() const
|
||||||
|
{
|
||||||
|
return fLocalVariables.CountItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Variable*
|
||||||
|
StackFrame::LocalVariableAt(int32 index) const
|
||||||
|
{
|
||||||
|
return fLocalVariables.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
StackFrame::AddLocalVariable(Variable* variable)
|
||||||
|
{
|
||||||
|
if (!fLocalVariables.AddItem(variable))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
variable->AcquireReference();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include <ObjectList.h>
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
@@ -23,6 +24,7 @@ enum stack_frame_type {
|
|||||||
class CpuState;
|
class CpuState;
|
||||||
class Image;
|
class Image;
|
||||||
class FunctionInstance;
|
class FunctionInstance;
|
||||||
|
class Variable;
|
||||||
|
|
||||||
|
|
||||||
class StackFrame : public Referenceable {
|
class StackFrame : public Referenceable {
|
||||||
@@ -49,6 +51,17 @@ public:
|
|||||||
FunctionInstance* Function() const { return fFunction; }
|
FunctionInstance* Function() const { return fFunction; }
|
||||||
void SetFunction(FunctionInstance* function);
|
void SetFunction(FunctionInstance* function);
|
||||||
|
|
||||||
|
int32 CountParameters() const;
|
||||||
|
Variable* ParameterAt(int32 index) const;
|
||||||
|
bool AddParameter(Variable* parameter);
|
||||||
|
|
||||||
|
int32 CountLocalVariables() const;
|
||||||
|
Variable* LocalVariableAt(int32 index) const;
|
||||||
|
bool AddLocalVariable(Variable* variable);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef BObjectList<Variable> VariableList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
stack_frame_type fType;
|
stack_frame_type fType;
|
||||||
CpuState* fCpuState;
|
CpuState* fCpuState;
|
||||||
@@ -57,6 +70,8 @@ private:
|
|||||||
target_addr_t fReturnAddress;
|
target_addr_t fReturnAddress;
|
||||||
Image* fImage;
|
Image* fImage;
|
||||||
FunctionInstance* fFunction;
|
FunctionInstance* fFunction;
|
||||||
|
VariableList fParameters;
|
||||||
|
VariableList fLocalVariables;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Type.h"
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - DataMember
|
||||||
|
|
||||||
|
|
||||||
|
DataMember::~DataMember()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Type
|
||||||
|
|
||||||
|
|
||||||
|
Type::~Type()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PrimitiveType
|
||||||
|
|
||||||
|
|
||||||
|
PrimitiveType::~PrimitiveType()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type_kind
|
||||||
|
PrimitiveType::Kind() const
|
||||||
|
{
|
||||||
|
return TYPE_PRIMITIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - CompoundType
|
||||||
|
|
||||||
|
|
||||||
|
CompoundType::~CompoundType()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type_kind
|
||||||
|
CompoundType::Kind() const
|
||||||
|
{
|
||||||
|
return TYPE_COMPOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - ModifiedType
|
||||||
|
|
||||||
|
|
||||||
|
ModifiedType::~ModifiedType()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type_kind
|
||||||
|
ModifiedType::Kind() const
|
||||||
|
{
|
||||||
|
return TYPE_MODIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - TypedefType
|
||||||
|
|
||||||
|
|
||||||
|
TypedefType::~TypedefType()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type_kind
|
||||||
|
TypedefType::Kind() const
|
||||||
|
{
|
||||||
|
return TYPE_TYPEDEF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - AddressType
|
||||||
|
|
||||||
|
|
||||||
|
AddressType::~AddressType()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type_kind
|
||||||
|
AddressType::Kind() const
|
||||||
|
{
|
||||||
|
return TYPE_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - ArrayType
|
||||||
|
|
||||||
|
|
||||||
|
ArrayType::~ArrayType()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type_kind
|
||||||
|
ArrayType::Kind() const
|
||||||
|
{
|
||||||
|
return TYPE_ARRAY;
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef TYPE_H
|
||||||
|
#define TYPE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
|
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum type_kind {
|
||||||
|
TYPE_PRIMITIVE,
|
||||||
|
TYPE_COMPOUND,
|
||||||
|
TYPE_MODIFIED,
|
||||||
|
TYPE_TYPEDEF,
|
||||||
|
TYPE_ADDRESS,
|
||||||
|
TYPE_ARRAY
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum address_type_kind {
|
||||||
|
DERIVED_TYPE_POINTER,
|
||||||
|
DERIVED_TYPE_REFERENCE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TYPE_MODIFIER_CONST = 0x01,
|
||||||
|
TYPE_MODIFIER_VOLATILE = 0x02,
|
||||||
|
TYPE_MODIFIER_RESTRICT = 0x04,
|
||||||
|
TYPE_MODIFIER_PACKED = 0x08,
|
||||||
|
TYPE_MODIFIER_SHARED = 0x10
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type;
|
||||||
|
|
||||||
|
|
||||||
|
class DataMember : public Referenceable {
|
||||||
|
public:
|
||||||
|
virtual ~DataMember();
|
||||||
|
|
||||||
|
virtual const char* Name() const = 0;
|
||||||
|
virtual Type* GetType() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type : public Referenceable {
|
||||||
|
public:
|
||||||
|
virtual ~Type();
|
||||||
|
|
||||||
|
virtual const char* Name() const = 0;
|
||||||
|
virtual type_kind Kind() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PrimitiveType : public virtual Type {
|
||||||
|
public:
|
||||||
|
virtual ~PrimitiveType();
|
||||||
|
|
||||||
|
virtual type_kind Kind() const;
|
||||||
|
|
||||||
|
virtual uint32 TypeConstant() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CompoundType : public virtual Type {
|
||||||
|
public:
|
||||||
|
virtual ~CompoundType();
|
||||||
|
|
||||||
|
virtual type_kind Kind() const;
|
||||||
|
|
||||||
|
virtual int32 CountDataMembers() const = 0;
|
||||||
|
virtual DataMember* DataMemberAt(int32 index) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModifiedType : public virtual Type {
|
||||||
|
public:
|
||||||
|
virtual ~ModifiedType();
|
||||||
|
|
||||||
|
virtual type_kind Kind() const;
|
||||||
|
|
||||||
|
virtual uint32 Modifiers() const = 0;
|
||||||
|
virtual Type* BaseType() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class TypedefType : public virtual Type {
|
||||||
|
public:
|
||||||
|
virtual ~TypedefType();
|
||||||
|
|
||||||
|
virtual type_kind Kind() const;
|
||||||
|
|
||||||
|
virtual Type* BaseType() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class AddressType : public virtual Type {
|
||||||
|
public:
|
||||||
|
virtual ~AddressType();
|
||||||
|
|
||||||
|
virtual type_kind Kind() const;
|
||||||
|
|
||||||
|
virtual address_type_kind AddressKind() const = 0;
|
||||||
|
virtual Type* BaseType() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ArrayType : public virtual Type {
|
||||||
|
public:
|
||||||
|
virtual ~ArrayType();
|
||||||
|
|
||||||
|
virtual type_kind Kind() const;
|
||||||
|
|
||||||
|
virtual Type* BaseType() const = 0;
|
||||||
|
virtual target_size_t CountElements() const = 0;
|
||||||
|
// TODO: That doesn't work. We need a list of dimensions which in turn
|
||||||
|
// are enumeration or subrange types.
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // TYPE_H
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Variable.h"
|
||||||
|
|
||||||
|
#include "Type.h"
|
||||||
|
#include "ValueLocation.h"
|
||||||
|
|
||||||
|
|
||||||
|
Variable::Variable(const BString& name, Type* type, ValueLocation* location)
|
||||||
|
:
|
||||||
|
fName(name),
|
||||||
|
fType(type),
|
||||||
|
fLocation(location)
|
||||||
|
{
|
||||||
|
fType->AcquireReference();
|
||||||
|
fLocation->AcquireReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Variable::~Variable()
|
||||||
|
{
|
||||||
|
fType->ReleaseReference();
|
||||||
|
fLocation->ReleaseReference();
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef VARIABLE_H
|
||||||
|
#define VARIABLE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
|
|
||||||
|
|
||||||
|
class Type;
|
||||||
|
class ValueLocation;
|
||||||
|
|
||||||
|
|
||||||
|
class Variable : public Referenceable {
|
||||||
|
public:
|
||||||
|
Variable(const BString& name, Type* type,
|
||||||
|
ValueLocation* location);
|
||||||
|
~Variable();
|
||||||
|
|
||||||
|
const BString& Name() const { return fName; }
|
||||||
|
Type* GetType() const { return fType; }
|
||||||
|
ValueLocation* Location() const { return fLocation; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
BString fName;
|
||||||
|
Type* fType;
|
||||||
|
ValueLocation* fLocation;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VARIABLE_H
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ValueLocation.h"
|
||||||
|
|
||||||
|
|
||||||
|
ValueLocation::ValueLocation()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ValueLocation::ValueLocation(const ValuePieceLocation& piece)
|
||||||
|
{
|
||||||
|
AddPiece(piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ValueLocation::ValueLocation(const ValueLocation& other)
|
||||||
|
:
|
||||||
|
fPieces(other.fPieces)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ValueLocation::Clear()
|
||||||
|
{
|
||||||
|
fPieces.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
ValueLocation::AddPiece(const ValuePieceLocation& piece)
|
||||||
|
{
|
||||||
|
return fPieces.Add(piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
ValueLocation::CountPieces() const
|
||||||
|
{
|
||||||
|
return fPieces.Size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ValuePieceLocation
|
||||||
|
ValueLocation::PieceAt(int32 index) const
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= fPieces.Size())
|
||||||
|
return ValuePieceLocation();
|
||||||
|
|
||||||
|
return fPieces.ElementAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ValueLocation&
|
||||||
|
ValueLocation::operator=(const ValueLocation& other)
|
||||||
|
{
|
||||||
|
fPieces = other.fPieces;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef VALUE_LOCATION_H
|
||||||
|
#define VALUE_LOCATION_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
|
|
||||||
|
#include "Array.h"
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
|
||||||
|
enum value_piece_location_type {
|
||||||
|
VALUE_PIECE_LOCATION_INVALID, // structure is invalid
|
||||||
|
VALUE_PIECE_LOCATION_UNKNOWN, // location unknown, but size is valid
|
||||||
|
VALUE_PIECE_LOCATION_MEMORY, // piece is in memory
|
||||||
|
VALUE_PIECE_LOCATION_REGISTER // piece is in a register
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ValuePieceLocation {
|
||||||
|
union {
|
||||||
|
target_addr_t address; // memory address
|
||||||
|
uint32 reg; // register number
|
||||||
|
};
|
||||||
|
target_size_t size; // size in bytes (complete ones)
|
||||||
|
uint8 bitSize; // totalBitSize = size * 8 + bitSize
|
||||||
|
uint8 bitOffset; // offset in bits
|
||||||
|
value_piece_location_type type;
|
||||||
|
|
||||||
|
ValuePieceLocation()
|
||||||
|
:
|
||||||
|
type(VALUE_PIECE_LOCATION_INVALID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValid() const
|
||||||
|
{
|
||||||
|
return type != VALUE_PIECE_LOCATION_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetToUnknown()
|
||||||
|
{
|
||||||
|
type = VALUE_PIECE_LOCATION_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetToMemory(target_addr_t address)
|
||||||
|
{
|
||||||
|
type = VALUE_PIECE_LOCATION_MEMORY;
|
||||||
|
this->address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetToRegister(uint32 reg)
|
||||||
|
{
|
||||||
|
type = VALUE_PIECE_LOCATION_REGISTER;
|
||||||
|
this->reg = reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSize(target_size_t size)
|
||||||
|
{
|
||||||
|
this->size = size;
|
||||||
|
this->bitSize = 0;
|
||||||
|
this->bitOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSize(uint64 bitSize, uint8 bitOffset)
|
||||||
|
{
|
||||||
|
this->size = bitSize / 8;
|
||||||
|
this->bitSize = bitSize % 8;
|
||||||
|
this->bitOffset = bitOffset;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ValueLocation : public Referenceable {
|
||||||
|
public:
|
||||||
|
ValueLocation();
|
||||||
|
ValueLocation(const ValuePieceLocation& piece);
|
||||||
|
ValueLocation(const ValueLocation& other);
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
bool AddPiece(const ValuePieceLocation& piece);
|
||||||
|
|
||||||
|
int32 CountPieces() const;
|
||||||
|
ValuePieceLocation PieceAt(int32 index) const;
|
||||||
|
|
||||||
|
ValueLocation& operator=(const ValueLocation& other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef Array<ValuePieceLocation> PieceArray;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PieceArray fPieces;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VALUE_LOCATION_H
|
||||||
Reference in New Issue
Block a user