* 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:
Ingo Weinhold
2009-07-17 01:54:43 +00:00
parent ce79a21bd0
commit d315bfd510
29 changed files with 2956 additions and 110 deletions
+7 -1
View File
@@ -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
+12 -3
View File
@@ -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)
+192 -1
View File
@@ -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
+132 -20
View File
@@ -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);
+387 -9
View File
@@ -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;
}
}
}
+51 -4
View File
@@ -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;
@@ -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());
@@ -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
+63 -6
View File
@@ -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;
} }
+15
View File
@@ -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;
}; };
+113
View File
@@ -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;
}
+126
View File
@@ -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
+28
View File
@@ -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();
}
+35
View File
@@ -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
+64
View File
@@ -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;
}
+99
View File
@@ -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