* 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
DwarfImageDebugInfo.cpp
DwarfTeamDebugInfo.cpp
DwarfInterfaceFactory.cpp
: [ FDirName $(SUBDIR) dwarf ]
;
@@ -58,6 +59,7 @@ Application Debugger :
DwarfFunctionDebugInfo.cpp
DwarfImageDebugInfo.cpp
DwarfTeamDebugInfo.cpp
DwarfInterfaceFactory.cpp
Function.cpp
FunctionDebugInfo.cpp
FunctionInstance.cpp
@@ -84,11 +86,12 @@ Application Debugger :
# gui/team_window
ImageFunctionsView.cpp
ImageListView.cpp
RegisterView.cpp
RegistersView.cpp
SourceView.cpp
StackTraceView.cpp
TeamWindow.cpp
ThreadListView.cpp
VariablesView.cpp
# model
Breakpoint.cpp
@@ -107,6 +110,8 @@ Application Debugger :
TeamMemory.cpp
Thread.cpp
ThreadInfo.cpp
Type.cpp
Variable.cpp
# source_language
CLanguage.cpp
@@ -119,6 +124,7 @@ Application Debugger :
# types
TargetAddressRangeList.cpp
ValueLocation.cpp
# util
StringUtils.cpp
@@ -19,6 +19,7 @@ DwarfFunctionDebugInfo::DwarfFunctionDebugInfo(
:
fImageDebugInfo(imageDebugInfo),
fCompilationUnit(compilationUnit),
fSubprogramEntry(subprogramEntry),
fAddressRanges(addressRanges),
fName(name),
fSourceFile(sourceFile),
@@ -41,10 +41,13 @@ public:
CompilationUnit* GetCompilationUnit() const
{ return fCompilationUnit; }
DIESubprogram* SubprogramEntry() const
{ return fSubprogramEntry; }
private:
DwarfImageDebugInfo* fImageDebugInfo;
CompilationUnit* fCompilationUnit;
DIESubprogram* fSubprogramEntry;
TargetAddressRangeList* fAddressRanges;
BString fName;
LocatableFile* fSourceFile;
@@ -25,6 +25,7 @@
#include "Dwarf.h"
#include "DwarfFile.h"
#include "DwarfFunctionDebugInfo.h"
#include "DwarfInterfaceFactory.h"
#include "DwarfTargetInterface.h"
#include "DwarfUtils.h"
#include "ElfFile.h"
@@ -40,6 +41,8 @@
#include "TargetAddressRangeList.h"
#include "TeamMemory.h"
#include "UnsupportedLanguage.h"
#include "ValueLocation.h"
#include "Variable.h"
// #pragma mark - UnwindTargetInterface
@@ -336,10 +339,12 @@ DwarfImageDebugInfo::CreateFrame(Image* image, FunctionDebugInfo* _function,
fromDwarfMap, toDwarfMap, previousCpuState, fArchitecture, fTeamMemory);
// do the unwinding
target_addr_t instructionPointer
= cpuState->InstructionPointer() - fRelocationDelta;
target_addr_t framePointer;
error = fFile->UnwindCallFrame(function->GetCompilationUnit(),
cpuState->InstructionPointer() - fRelocationDelta,
&inputInterface, &outputInterface, framePointer);
function->SubprogramEntry(), instructionPointer, &inputInterface,
&outputInterface, framePointer);
if (error != B_OK)
return B_UNSUPPORTED;
@@ -358,12 +363,40 @@ if (previousCpuState->GetRegisterValue(reg, value)) {
cpuState, framePointer, cpuState->InstructionPointer());
if (frame == NULL)
return B_NO_MEMORY;
Reference<StackFrame> frameReference(frame, true);
frame->SetReturnAddress(previousCpuState->InstructionPointer());
// Note, this is correct, since we actually retrieved the return
// 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();
return B_OK;
@@ -12,6 +12,7 @@
#include "ImageInfo.h"
#include "SpecificImageDebugInfo.h"
#include "Type.h"
class Architecture;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,103 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* 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()
:
attributeClass(ATTRIBUTE_CLASS_CONSTANT)
attributeClass(ATTRIBUTE_CLASS_UNKNOWN)
{
this->constant = 0;
}
bool IsValid() const
{
return attributeClass != ATTRIBUTE_CLASS_UNKNOWN;
}
void SetTo(uint64 constant)
{
this->constant = constant;
@@ -174,9 +179,13 @@ struct 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)
+192 -1
View File
@@ -437,7 +437,7 @@ DIEClassBaseType::AddChild(DebugInfoEntry* child)
{
switch (child->Tag()) {
case DW_TAG_inheritance:
fDataMembers.Add(child);
fBaseTypes.Add(child);
return B_OK;
case DW_TAG_friend:
fFriends.Add(child);
@@ -777,6 +777,9 @@ DIEEnumerationType::AddAttribute_specification(uint16 attributeName,
DIEFormalParameter::DIEFormalParameter()
:
fAbstractOrigin(NULL),
fType(NULL)
{
}
@@ -788,6 +791,13 @@ DIEFormalParameter::Tag() const
}
DebugInfoEntry*
DIEFormalParameter::AbstractOrigin() const
{
return fAbstractOrigin;
}
LocationDescription*
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
@@ -844,6 +880,8 @@ DIELexicalBlock::Tag() const
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
@@ -1118,6 +1165,8 @@ DIECommonInclusion::Tag() const
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
@@ -1297,6 +1355,8 @@ DIESubrangeType::AddAttribute_threads_scaled(uint16 attributeName,
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
@@ -1424,6 +1493,8 @@ DIEConstType::Tag() const
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
@@ -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
DIESubprogram::AddAttribute_low_pc(uint16 attributeName,
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
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
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
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
@@ -1733,6 +1894,8 @@ DIETryBlock::Tag() const
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
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
+132 -20
View File
@@ -241,6 +241,8 @@ class DIEModifiedType : public DIEType {
public:
DIEModifiedType();
DIEType* GetType() const { return fType; }
virtual status_t AddAttribute_type(uint16 attributeName,
const AttributeValue& value);
@@ -301,6 +303,8 @@ class DIEDerivedType : public DIEDeclaredType {
public:
DIEDerivedType();
DIEType* GetType() const { return fType; }
virtual status_t AddAttribute_type(uint16 attributeName,
const AttributeValue& value);
@@ -317,6 +321,9 @@ public:
virtual DebugInfoEntry* Specification() const;
const DebugInfoEntryList& DataMembers() const
{ return fDataMembers; }
virtual status_t AddChild(DebugInfoEntry* child);
virtual status_t AddAttribute_byte_size(uint16 attributeName,
@@ -453,6 +460,8 @@ public:
class DIEEntryPoint : public DebugInfoEntry {
public:
// TODO: Maybe introduce a common base class for DIEEntryPoint and
// DIESubprogram.
DIEEntryPoint();
virtual uint16 Tag() const;
@@ -504,21 +513,35 @@ public:
virtual uint16 Tag() const;
virtual DebugInfoEntry* AbstractOrigin() const;
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:
// DW_AT_abstract_origin
// DW_AT_artificial
// DW_AT_const_value
// DW_AT_default_value
// DW_AT_endianity
// DW_AT_is_optional
// DW_AT_segment
// DW_AT_type
// DW_AT_variable_parameter
private:
LocationDescription fLocationDescription;
DebugInfoEntry* fAbstractOrigin;
DIEType* fType;
ConstantAttributeValue fValue;
};
@@ -569,14 +592,20 @@ public:
virtual uint16 Tag() const;
DIEType* GetType() const { return fType; }
virtual status_t AddAttribute_type(uint16 attributeName,
const AttributeValue& value);
// TODO:
// DW_AT_bit_offset
// DW_AT_bit_size
// DW_AT_byte_size
// DW_AT_data_member_location
// DW_AT_mutable
// DW_AT_type
private:
DIEType* fType;
};
@@ -738,11 +767,18 @@ public:
virtual uint16 Tag() const;
DIEType* GetType() const { return fType; }
virtual status_t AddAttribute_type(uint16 attributeName,
const AttributeValue& value);
// TODO:
// DW_AT_accessibility
// DW_AT_data_member_location
// DW_AT_type
// DW_AT_virtuality
private:
DIEType* fType;
};
@@ -857,8 +893,13 @@ public:
virtual uint16 Tag() const;
DIEType* GetType() const { return fType; }
virtual LocationDescription* GetLocationDescription();
virtual status_t AddAttribute_type(uint16 attributeName,
const AttributeValue& value);
// TODO:
// DW_AT_accessibility
// DW_AT_address_class
@@ -867,10 +908,10 @@ public:
// DW_AT_low_pc
// DW_AT_ranges
// DW_AT_segment
// DW_AT_type
// DW_AT_visibility
private:
DIEType* fType;
LocationDescription fLocationDescription;
};
@@ -889,6 +930,15 @@ public:
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,
const AttributeValue& value);
virtual status_t AddAttribute_byte_size(uint16 attributeName,
@@ -947,12 +997,24 @@ public:
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:
// DW_AT_const_value
// DW_AT_endianity
// DW_AT_external
// DW_AT_start_scope
// DW_AT_type
private:
DIEType* fType;
ConstantAttributeValue fValue;
};
@@ -962,6 +1024,9 @@ public:
virtual uint16 Tag() const;
const ConstantAttributeValue* ConstValue() const
{ return &fValue; }
virtual status_t AddAttribute_const_value(uint16 attributeName,
const AttributeValue& value);
@@ -1042,9 +1107,15 @@ public:
target_addr_t LowPC() const { return fLowPC; }
target_addr_t HighPC() const { return fHighPC; }
const LocationDescription* FrameBase() const { return &fFrameBase; }
const DebugInfoEntryList Parameters() const { return fParameters; }
bool IsPrototyped() const { return fPrototyped; }
uint8 Inline() const { return fInline; }
virtual status_t AddChild(DebugInfoEntry* child);
virtual status_t AddAttribute_low_pc(uint16 attributeName,
const AttributeValue& value);
virtual status_t AddAttribute_high_pc(uint16 attributeName,
@@ -1064,33 +1135,35 @@ public:
virtual status_t AddAttribute_abstract_origin(
uint16 attributeName,
const AttributeValue& value);
virtual status_t AddAttribute_frame_base(
uint16 attributeName,
const AttributeValue& value);
protected:
DebugInfoEntryList fParameters;
target_addr_t fLowPC;
target_addr_t fHighPC;
off_t fAddressRangesOffset;
DIESubprogram* fSpecification;
DIESubprogram* fAbstractOrigin;
DIEType* fReturnType;
LocationDescription fFrameBase;
uint8 fAddressClass;
bool fPrototyped;
uint8 fInline;
// TODO:
// DW_AT_abstract_origin
// DW_AT_artificial
// DW_AT_calling_convention
// DW_AT_elemental
// DW_AT_entry_pc
// DW_AT_explicit
// DW_AT_external
// DW_AT_frame_base
// DW_AT_object_pointer
// DW_AT_pure
// DW_AT_recursive
// DW_AT_return_addr
// DW_AT_segment
// DW_AT_specification
// DW_AT_start_scope
// DW_AT_static_link
// DW_AT_trampoline
@@ -1105,8 +1178,13 @@ public:
virtual uint16 Tag() const;
// TODO:
// DW_AT_type
DIEType* GetType() const { return fType; }
virtual status_t AddAttribute_type(uint16 attributeName,
const AttributeValue& value);
private:
DIEType* fType;
};
@@ -1116,9 +1194,19 @@ public:
virtual uint16 Tag() const;
// TODO:
// DW_AT_const_value
// DW_AT_type
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);
private:
DIEType* fType;
ConstantAttributeValue fValue;
};
@@ -1128,11 +1216,18 @@ public:
virtual uint16 Tag() const;
DIEType* GetType() const { return fType; }
virtual status_t AddAttribute_type(uint16 attributeName,
const AttributeValue& value);
// TODO:
// DW_AT_allocated
// DW_AT_associated
// DW_AT_data_location
// DW_AT_type
private:
DIEType* fType;
};
@@ -1157,12 +1252,19 @@ public:
virtual uint16 Tag() const;
DIEType* GetType() const { return fType; }
virtual status_t AddAttribute_type(uint16 attributeName,
const AttributeValue& value);
// TODO:
// DW_AT_abstract_origin
// DW_AT_accessibility
// DW_AT_declaration
// DW_AT_discr
// DW_AT_type
private:
DIEType* fType;
};
@@ -1174,18 +1276,28 @@ public:
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:
// DW_AT_abstract_origin
// DW_AT_const_value
// DW_AT_endianity
// DW_AT_external
// DW_AT_segment
// DW_AT_specification
// DW_AT_start_scope
// DW_AT_type
private:
LocationDescription fLocationDescription;
ConstantAttributeValue fValue;
DIEType* fType;
};
@@ -202,7 +202,6 @@ DebugInfoEntry::AddAttribute_location(uint16 attributeName,
return B_OK;
}
return B_BAD_DATA;
}
return ATTRIBUTE_NOT_HANDLED;
@@ -17,6 +17,7 @@
#include "DataReader.h"
#include "Dwarf.h"
#include "DwarfTargetInterface.h"
#include "ValueLocation.h"
// number of elements to increase the stack capacity when the stack is full
@@ -34,7 +35,7 @@ static const uint32 kMaxOperationCount = 10000;
DwarfExpressionEvaluationContext::DwarfExpressionEvaluationContext(
DwarfTargetInterface* targetInterface, uint8 addressSize)
const DwarfTargetInterface* targetInterface, uint8 addressSize)
:
fTargetInterface(targetInterface),
fAddressSize(addressSize)
@@ -51,6 +52,13 @@ DwarfExpressionEvaluationContext::~DwarfExpressionEvaluationContext()
struct DwarfExpressionEvaluator::EvaluationException {
const char* message;
EvaluationException(const char* message)
:
message(message)
{
}
};
@@ -61,7 +69,7 @@ void
DwarfExpressionEvaluator::_AssertMinStackSize(size_t size) const
{
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
if (fStackSize == fStackCapacity) {
if (fStackCapacity >= kMaxStackCapacity)
throw EvaluationException();
throw EvaluationException("stack overflow");
size_t newCapacity = fStackCapacity + kStackCapacityIncrement;
target_addr_t* newStack = (target_addr_t*)realloc(fStack,
@@ -113,12 +121,11 @@ DwarfExpressionEvaluator::~DwarfExpressionEvaluator()
status_t
DwarfExpressionEvaluator::Evaluate(const void* expression, size_t size)
DwarfExpressionEvaluator::Push(target_addr_t value)
{
fDataReader.SetTo(expression, size, fContext->AddressSize());
try {
return _Evaluate();
_Push(value);
return B_OK;
} catch (const EvaluationException& exception) {
return B_BAD_VALUE;
} catch (const std::bad_alloc& exception) {
@@ -128,8 +135,122 @@ DwarfExpressionEvaluator::Evaluate(const void* expression, size_t size)
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;
while (fDataReader.BytesRemaining() > 0) {
@@ -137,51 +258,66 @@ DwarfExpressionEvaluator::_Evaluate()
switch (opcode) {
case DW_OP_addr:
printf(" DW_OP_addr\n");
_Push(fDataReader.ReadAddress(0));
break;
case DW_OP_const1u:
printf(" DW_OP_const1u\n");
_Push(fDataReader.Read<uint8>(0));
break;
case DW_OP_const1s:
printf(" DW_OP_const1s\n");
_Push(fDataReader.Read<int8>(0));
break;
case DW_OP_const2u:
printf(" DW_OP_const2u\n");
_Push(fDataReader.Read<uint16>(0));
break;
case DW_OP_const2s:
printf(" DW_OP_const2s\n");
_Push(fDataReader.Read<int16>(0));
break;
case DW_OP_const4u:
printf(" DW_OP_const4u\n");
_Push(fDataReader.Read<uint32>(0));
break;
case DW_OP_const4s:
printf(" DW_OP_const4s\n");
_Push(fDataReader.Read<int32>(0));
break;
case DW_OP_const8u:
printf(" DW_OP_const8u\n");
_Push(fDataReader.Read<uint64>(0));
break;
case DW_OP_const8s:
printf(" DW_OP_const8s\n");
_Push(fDataReader.Read<int64>(0));
break;
case DW_OP_constu:
printf(" DW_OP_constu\n");
_Push(fDataReader.ReadUnsignedLEB128(0));
break;
case DW_OP_consts:
printf(" DW_OP_consts\n");
_Push(fDataReader.ReadSignedLEB128(0));
break;
case DW_OP_dup:
printf(" DW_OP_dup\n");
_AssertMinStackSize(1);
_Push(fStack[fStackSize - 1]);
break;
case DW_OP_drop:
printf(" DW_OP_drop\n");
_Pop();
break;
case DW_OP_over:
printf(" DW_OP_over\n");
_AssertMinStackSize(1);
_Push(fStack[fStackSize - 2]);
break;
case DW_OP_pick:
{
printf(" DW_OP_pick\n");
uint8 index = fDataReader.Read<uint8>(0);
_AssertMinStackSize(index + 1);
_Push(fStack[fStackSize - index - 1]);
@@ -189,12 +325,14 @@ DwarfExpressionEvaluator::_Evaluate()
}
case DW_OP_swap:
{
printf(" DW_OP_swap\n");
_AssertMinStackSize(2);
std::swap(fStack[fStackSize - 1], fStack[fStackSize - 2]);
break;
}
case DW_OP_rot:
{
printf(" DW_OP_rot\n");
_AssertMinStackSize(3);
target_addr_t tmp = fStack[fStackSize - 1];
fStack[fStackSize - 1] = fStack[fStackSize - 2];
@@ -204,20 +342,25 @@ DwarfExpressionEvaluator::_Evaluate()
}
case DW_OP_deref:
printf(" DW_OP_deref\n");
_DereferenceAddress(fContext->AddressSize());
break;
case DW_OP_deref_size:
printf(" DW_OP_deref_size\n");
_DereferenceAddress(fDataReader.Read<uint8>(0));
break;
case DW_OP_xderef:
printf(" DW_OP_xderef\n");
_DereferenceAddressSpaceAddress(fContext->AddressSize());
break;
case DW_OP_xderef_size:
printf(" DW_OP_xderef_size\n");
_DereferenceAddressSpaceAddress(fDataReader.Read<uint8>(0));
break;
case DW_OP_abs:
{
printf(" DW_OP_abs\n");
target_addr_t value = _Pop();
if (fContext->AddressSize() == 4) {
int32 signedValue = (int32)value;
@@ -229,10 +372,12 @@ DwarfExpressionEvaluator::_Evaluate()
break;
}
case DW_OP_and:
printf(" DW_OP_and\n");
_Push(_Pop() & _Pop());
break;
case DW_OP_div:
{
printf(" DW_OP_div\n");
int64 top = (int64)_Pop();
int64 second = (int64)_Pop();
_Push(top != 0 ? second / top : 0);
@@ -240,12 +385,14 @@ DwarfExpressionEvaluator::_Evaluate()
}
case DW_OP_minus:
{
printf(" DW_OP_minus\n");
target_addr_t top = _Pop();
_Push(_Pop() - top);
break;
}
case DW_OP_mod:
{
printf(" DW_OP_mod\n");
// While the specs explicitly speak of signed integer division
// for "div", nothing is mentioned for "mod".
target_addr_t top = _Pop();
@@ -254,10 +401,12 @@ DwarfExpressionEvaluator::_Evaluate()
break;
}
case DW_OP_mul:
printf(" DW_OP_mul\n");
_Push(_Pop() * _Pop());
break;
case DW_OP_neg:
{
printf(" DW_OP_neg\n");
if (fContext->AddressSize() == 4)
_Push(-(int32)_Pop());
else
@@ -265,31 +414,38 @@ DwarfExpressionEvaluator::_Evaluate()
break;
}
case DW_OP_not:
printf(" DW_OP_not\n");
_Push(~_Pop());
break;
case DW_OP_or:
printf(" DW_OP_or\n");
_Push(_Pop() | _Pop());
break;
case DW_OP_plus:
printf(" DW_OP_plus\n");
_Push(_Pop() + _Pop());
break;
case DW_OP_plus_uconst:
printf(" DW_OP_plus_uconst\n");
_Push(_Pop() + fDataReader.ReadUnsignedLEB128(0));
break;
case DW_OP_shl:
{
printf(" DW_OP_shl\n");
target_addr_t top = _Pop();
_Push(_Pop() << top);
break;
}
case DW_OP_shr:
{
printf(" DW_OP_shr\n");
target_addr_t top = _Pop();
_Push(_Pop() >> top);
break;
}
case DW_OP_shra:
{
printf(" DW_OP_shra\n");
target_addr_t top = _Pop();
int64 second = (int64)_Pop();
_Push(second >= 0 ? second >> top : -(-second >> top));
@@ -297,105 +453,135 @@ DwarfExpressionEvaluator::_Evaluate()
break;
}
case DW_OP_xor:
printf(" DW_OP_xor\n");
_Push(_Pop() ^ _Pop());
break;
case DW_OP_bra:
printf(" DW_OP_bra\n");
if (_Pop() == 0)
break;
// fall through
case DW_OP_skip:
{
printf(" DW_OP_skip\n");
int16 offset = fDataReader.Read<int16>(0);
if (offset >= 0 ? offset > fDataReader.BytesRemaining()
: -offset > fDataReader.Offset()) {
throw EvaluationException();
throw EvaluationException("bra/skip: invalid offset");
}
fDataReader.SeekAbsolute(fDataReader.Offset() + offset);
break;
}
case DW_OP_eq:
printf(" DW_OP_eq\n");
_Push(_Pop() == _Pop() ? 1 : 0);
break;
case DW_OP_ge:
{
printf(" DW_OP_ge\n");
int64 top = (int64)_Pop();
_Push((int64)_Pop() >= top ? 1 : 0);
break;
}
case DW_OP_gt:
{
printf(" DW_OP_gt\n");
int64 top = (int64)_Pop();
_Push((int64)_Pop() > top ? 1 : 0);
break;
}
case DW_OP_le:
{
printf(" DW_OP_le\n");
int64 top = (int64)_Pop();
_Push((int64)_Pop() <= top ? 1 : 0);
break;
}
case DW_OP_lt:
{
printf(" DW_OP_lt\n");
int64 top = (int64)_Pop();
_Push((int64)_Pop() < top ? 1 : 0);
break;
}
case DW_OP_ne:
printf(" DW_OP_ne\n");
_Push(_Pop() == _Pop() ? 1 : 0);
break;
case DW_OP_push_object_address:
{
printf(" DW_OP_push_object_address\n");
target_addr_t address;
if (!fContext->GetObjectAddress(address))
throw EvaluationException();
throw EvaluationException("failed to get object address");
_Push(address);
break;
}
case DW_OP_call_frame_cfa:
{
printf(" DW_OP_call_frame_cfa\n");
target_addr_t address;
if (!fContext->GetFrameAddress(address))
throw EvaluationException();
throw EvaluationException("failed to get frame address");
_Push(address);
break;
}
case DW_OP_fbreg:
{
printf(" DW_OP_fbreg\n");
target_addr_t address;
if (!fContext->GetFrameBaseAddress(address))
throw EvaluationException();
if (!fContext->GetFrameBaseAddress(address)) {
throw EvaluationException(
"failed to get frame base address");
}
_Push(address + fDataReader.ReadSignedLEB128(0));
break;
}
case DW_OP_form_tls_address:
{
printf(" DW_OP_form_tls_address\n");
target_addr_t address;
if (!fContext->GetTLSAddress(_Pop(), address))
throw EvaluationException();
throw EvaluationException("failed to get tls address");
_Push(address);
break;
}
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:
{
printf(" DW_OP_bregx\n");
uint32 reg = fDataReader.ReadUnsignedLEB128(0);
_PushRegister(reg, fDataReader.ReadSignedLEB128(0));
break;
}
case DW_OP_call2:
printf(" DW_OP_call2\n");
_Call(fDataReader.Read<uint16>(0), true);
break;
case DW_OP_call4:
printf(" DW_OP_call4\n");
_Call(fDataReader.Read<uint32>(0), true);
break;
case DW_OP_call_ref:
printf(" DW_OP_call_ref\n");
if (fContext->AddressSize() == 4)
_Call(fDataReader.Read<uint32>(0), false);
else
@@ -404,19 +590,33 @@ DwarfExpressionEvaluator::_Evaluate()
case DW_OP_piece:
case DW_OP_bit_piece:
// TODO:...
break;
// are handled in EvaluateLocation()
if (_piece == NULL)
return B_BAD_DATA;
fDataReader.SeekAbsolute(fDataReader.Offset() - 1);
// put back the operation
return B_OK;
case DW_OP_nop:
printf(" DW_OP_nop\n");
break;
default:
if (opcode >= DW_OP_lit0 && opcode <= DW_OP_lit31) {
printf(" DW_OP_lit%u\n", opcode - DW_OP_lit0);
_Push(opcode - DW_OP_lit0);
} 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) {
_PushRegister(opcode - DW_OP_reg0,
printf(" DW_OP_breg%u\n", opcode - DW_OP_breg0);
_PushRegister(opcode - DW_OP_breg0,
fDataReader.ReadSignedLEB128(0));
} else {
printf("DwarfExpressionEvaluator::_Evaluate(): unsupported "
@@ -455,14 +655,14 @@ DwarfExpressionEvaluator::_DereferenceAddress(uint8 addressSize)
}
// fall through
default:
throw EvaluationException();
throw EvaluationException("invalid dereference size");
}
target_addr_t address = _Pop();
BVariant value;
if (!fContext->TargetInterface()->ReadValueFromMemory(address, valueType,
value)) {
throw EvaluationException();
throw EvaluationException("failed to read memory");
}
_Push(value.ToUInt64());
@@ -490,7 +690,7 @@ DwarfExpressionEvaluator::_DereferenceAddressSpaceAddress(uint8 addressSize)
}
// fall through
default:
throw EvaluationException();
throw EvaluationException("invalid dereference size");
}
target_addr_t address = _Pop();
@@ -498,7 +698,7 @@ DwarfExpressionEvaluator::_DereferenceAddressSpaceAddress(uint8 addressSize)
BVariant value;
if (!fContext->TargetInterface()->ReadValueFromMemory(addressSpace, address,
valueType, value)) {
throw EvaluationException();
throw EvaluationException("failed to read memory");
}
_Push(value.ToUInt64());
@@ -510,7 +710,7 @@ DwarfExpressionEvaluator::_PushRegister(uint32 reg, target_addr_t offset)
{
BVariant value;
if (!fContext->TargetInterface()->GetRegisterValue(reg, value))
throw EvaluationException();
throw EvaluationException("failed to get register");
_Push(value.ToUInt64());
}
@@ -520,13 +720,13 @@ void
DwarfExpressionEvaluator::_Call(uint64 offset, bool local)
{
if (fDataReader.HasOverflow())
throw EvaluationException();
throw EvaluationException("unexpected end of expression");
// get the expression to "call"
const void* block;
off_t size;
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
if (block == NULL)
@@ -540,7 +740,8 @@ DwarfExpressionEvaluator::_Call(uint64 offset, bool local)
// and evaluate it
try {
_Evaluate();
if (_Evaluate(NULL) != B_OK)
throw EvaluationException("call failed");
} catch (...) {
fDataReader = savedReader;
throw;
@@ -11,16 +11,18 @@
class DwarfTargetInterface;
class ValueLocation;
struct ValuePieceLocation;
class DwarfExpressionEvaluationContext {
public:
DwarfExpressionEvaluationContext(
DwarfTargetInterface* targetInterface,
const DwarfTargetInterface* targetInterface,
uint8 addressSize);
virtual ~DwarfExpressionEvaluationContext();
DwarfTargetInterface* TargetInterface() const
const DwarfTargetInterface* TargetInterface() const
{ return fTargetInterface; }
uint8 AddressSize() const { return fAddressSize; }
@@ -38,8 +40,8 @@ public:
// block, when the entry doesn't have a
// location attribute
private:
DwarfTargetInterface* fTargetInterface;
protected:
const DwarfTargetInterface* fTargetInterface;
uint8 fAddressSize;
};
@@ -50,10 +52,12 @@ public:
DwarfExpressionEvaluationContext* context);
~DwarfExpressionEvaluator();
void SetObjectAddress(target_addr_t address);
void SetFrameAddress(target_addr_t address);
status_t Push(target_addr_t value);
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:
struct EvaluationException;
@@ -64,7 +68,7 @@ private:
inline void _Push(target_addr_t value);
inline target_addr_t _Pop();
status_t _Evaluate();
status_t _Evaluate(ValuePieceLocation* _piece);
void _DereferenceAddress(uint8 addressSize);
void _DereferenceAddressSpaceAddress(
uint8 addressSize);
+387 -9
View File
@@ -17,10 +17,12 @@
#include "CfaContext.h"
#include "CompilationUnit.h"
#include "DataReader.h"
#include "DwarfExpressionEvaluator.h"
#include "DwarfTargetInterface.h"
#include "ElfFile.h"
#include "TagNames.h"
#include "TargetAddressRangeList.h"
#include "Variant.h"
DwarfFile::DwarfFile()
@@ -33,6 +35,7 @@ DwarfFile::DwarfFile()
fDebugRangesSection(NULL),
fDebugLineSection(NULL),
fDebugFrameSection(NULL),
fDebugLocationSection(NULL),
fCompilationUnits(20, true),
fCurrentCompilationUnit(NULL),
fFinished(false),
@@ -53,6 +56,7 @@ DwarfFile::~DwarfFile()
fElfFile->PutSection(fDebugRangesSection);
fElfFile->PutSection(fDebugLineSection);
fElfFile->PutSection(fDebugFrameSection);
fElfFile->PutSection(fDebugLocationSection);
delete fElfFile;
}
@@ -91,6 +95,7 @@ DwarfFile::Load(const char* fileName)
fDebugRangesSection = fElfFile->GetSection(".debug_ranges");
fDebugLineSection = fElfFile->GetSection(".debug_line");
fDebugFrameSection = fElfFile->GetSection(".debug_frame");
fDebugLocationSection = fElfFile->GetSection(".debug_loc");
// iterate through the debug info section
DataReader dataReader(fDebugInfoSection->Data(),
@@ -270,7 +275,8 @@ DwarfFile::ResolveRangeList(CompilationUnit* unit, uint64 offset) const
status_t
DwarfFile::UnwindCallFrame(CompilationUnit* unit, target_addr_t location,
DwarfFile::UnwindCallFrame(CompilationUnit* unit,
DIESubprogram* subprogramEntry, target_addr_t location,
const DwarfTargetInterface* inputInterface,
DwarfTargetInterface* outputInterface, target_addr_t& _framePointer)
{
@@ -365,8 +371,16 @@ printf(" found row!\n");
break;
}
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:
default:
return B_BAD_VALUE;
@@ -421,13 +435,35 @@ printf(" -> CFA_RULE_REGISTER\n");
break;
}
case CFA_RULE_LOCATION_EXPRESSION:
{
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;
}
case CFA_RULE_VALUE_EXPRESSION:
{
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;
}
case CFA_RULE_UNDEFINED:
printf(" -> CFA_RULE_UNDEFINED\n");
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
DwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
{
@@ -800,8 +1105,8 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
break;
case ATTRIBUTE_CLASS_REFERENCE:
if (entry != NULL) {
attributeValue.SetToReference(_ResolveReference(value,
localReference));
attributeValue.SetToReference(_ResolveReference(
fCurrentCompilationUnit, value, localReference));
if (attributeValue.reference == NULL) {
// gcc 2 apparently somtimes produces DW_AT_sibling
// attributes pointing to the end of the sibling list.
@@ -1372,11 +1677,84 @@ DwarfFile::_GetAbbreviationTable(off_t offset, AbbreviationTable*& _table)
DebugInfoEntry*
DwarfFile::_ResolveReference(uint64 offset, bool localReference) const
DwarfFile::_ResolveReference(CompilationUnit* unit, uint64 offset,
bool localReference) const
{
if (localReference)
return fCurrentCompilationUnit->EntryForOffset(offset);
return unit->EntryForOffset(offset);
// TODO: Implement program-global references!
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 AbbreviationTable;
class BVariant;
class CfaContext;
class CompilationUnit;
class DataReader;
@@ -21,6 +22,7 @@ class DwarfTargetInterface;
class ElfFile;
class ElfSection;
class TargetAddressRangeList;
class ValueLocation;
class DwarfFile : public DoublyLinkedListLinkImpl<DwarfFile> {
@@ -43,12 +45,48 @@ public:
uint64 offset) const;
status_t UnwindCallFrame(CompilationUnit* unit,
DIESubprogram* subprogramEntry,
target_addr_t location,
const DwarfTargetInterface* inputInterface,
DwarfTargetInterface* outputInterface,
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:
struct ExpressionEvaluationContext;
typedef DoublyLinkedList<AbbreviationTable> AbbreviationTableList;
typedef BObjectList<CompilationUnit> CompilationUnitList;
@@ -75,10 +113,18 @@ private:
status_t _GetAbbreviationTable(off_t offset,
AbbreviationTable*& _table);
DebugInfoEntry* _ResolveReference(uint64 offset,
bool localReference) const;
TargetAddressRangeList* _ResolveRangeList(uint64 offset);
// returns reference
DebugInfoEntry* _ResolveReference(CompilationUnit* unit,
uint64 offset, bool localReference) const;
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:
char* fName;
@@ -89,6 +135,7 @@ private:
ElfSection* fDebugRangesSection;
ElfSection* fDebugLineSection;
ElfSection* fDebugFrameSection;
ElfSection* fDebugLocationSection;
AbbreviationTableList fAbbreviationTables;
DebugInfoEntryFactory fDebugInfoFactory;
CompilationUnitList fCompilationUnits;
@@ -3,7 +3,7 @@
* Distributed under the terms of the MIT License.
*/
#include "RegisterView.h"
#include "RegistersView.h"
#include <stdio.h>
@@ -19,7 +19,7 @@
// #pragma mark - RegisterValueColumn
class RegisterView::RegisterValueColumn : public StringTableColumn {
class RegistersView::RegisterValueColumn : public StringTableColumn {
public:
RegisterValueColumn(int32 modelIndex, const char* title, float width,
float minWidth, float maxWidth, uint32 truncate = B_TRUNCATE_MIDDLE,
@@ -109,7 +109,7 @@ private:
// #pragma mark - RegisterTableModel
class RegisterView::RegisterTableModel : public TableModel {
class RegistersView::RegisterTableModel : public TableModel {
public:
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),
fArchitecture(architecture),
fCpuState(NULL),
fRegisterTable(NULL),
fRegisterTableModel(NULL)
{
@@ -181,7 +182,7 @@ RegisterView::RegisterView(Architecture* architecture)
}
RegisterView::~RegisterView()
RegistersView::~RegistersView()
{
SetCpuState(NULL);
fRegisterTable->SetTableModel(NULL);
@@ -189,10 +190,10 @@ RegisterView::~RegisterView()
}
/*static*/ RegisterView*
RegisterView::Create(Architecture* architecture)
/*static*/ RegistersView*
RegistersView::Create(Architecture* architecture)
{
RegisterView* self = new RegisterView(architecture);
RegistersView* self = new RegistersView(architecture);
try {
self->_Init();
@@ -206,7 +207,7 @@ RegisterView::Create(Architecture* architecture)
void
RegisterView::SetCpuState(CpuState* cpuState)
RegistersView::SetCpuState(CpuState* cpuState)
{
if (cpuState == fCpuState)
return;
@@ -224,13 +225,13 @@ RegisterView::SetCpuState(CpuState* cpuState)
void
RegisterView::TableRowInvoked(Table* table, int32 rowIndex)
RegistersView::TableRowInvoked(Table* table, int32 rowIndex)
{
}
void
RegisterView::_Init()
RegistersView::_Init()
{
fRegisterTable = new Table("register list", 0, B_FANCY_BORDER);
AddChild(fRegisterTable->ToView());
@@ -2,8 +2,8 @@
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef REGISTER_VIEW_H
#define REGISTER_VIEW_H
#ifndef REGISTERS_VIEW_H
#define REGISTERS_VIEW_H
#include <GroupView.h>
@@ -14,12 +14,12 @@
class Architecture;
class RegisterView : public BGroupView, private TableListener {
class RegistersView : public BGroupView, private TableListener {
public:
RegisterView(Architecture* architecture);
~RegisterView();
RegistersView(Architecture* architecture);
~RegistersView();
static RegisterView* Create(Architecture* architecture);
static RegistersView* Create(Architecture* architecture);
// throws
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 "ImageDebugInfo.h"
#include "MessageCodes.h"
#include "RegisterView.h"
#include "RegistersView.h"
#include "StackTrace.h"
#include "StackTraceView.h"
#include "VariablesView.h"
enum {
@@ -57,7 +58,8 @@ TeamWindow::TeamWindow(TeamDebugModel* debugModel, Listener* listener)
fThreadListView(NULL),
fImageListView(NULL),
fImageFunctionsView(NULL),
fRegisterView(NULL),
fVariablesView(NULL),
fRegistersView(NULL),
fStackTraceView(NULL),
fSourceView(NULL),
fRunButton(NULL),
@@ -386,11 +388,12 @@ TeamWindow::_Init()
.Add(fImageFunctionsView = ImageFunctionsView::Create(this));
// add local variables tab
BView* tab = new BTextView("Variables");
BView* tab = fVariablesView = VariablesView::Create();
fLocalsTabView->AddTab(tab);
// add registers tab
tab = fRegisterView = RegisterView::Create(fDebugModel->GetArchitecture());
tab = fRegistersView = RegistersView::Create(
fDebugModel->GetArchitecture());
fLocalsTabView->AddTab(tab);
fRunButton->SetMessage(new BMessage(MSG_THREAD_RUN));
@@ -529,6 +532,7 @@ TeamWindow::_SetActiveStackFrame(StackFrame* frame)
_UpdateCpuState();
fStackTraceView->SetStackFrame(fActiveStackFrame);
fVariablesView->SetStackFrame(fActiveStackFrame);
fSourceView->SetStackFrame(fActiveStackFrame);
}
@@ -627,7 +631,7 @@ TeamWindow::_UpdateCpuState()
cpuState = fActiveStackFrame->GetCpuState();
}
fRegisterView->SetCpuState(cpuState);
fRegistersView->SetCpuState(cpuState);
}
@@ -22,9 +22,10 @@ class BButton;
class BMenuBar;
class BTabView;
class Image;
class RegisterView;
class RegistersView;
class SourceCode;
class StackFrame;
class VariablesView;
class TeamWindow : public BWindow, ThreadListView::Listener,
@@ -119,7 +120,8 @@ private:
ThreadListView* fThreadListView;
ImageListView* fImageListView;
ImageFunctionsView* fImageFunctionsView;
RegisterView* fRegisterView;
VariablesView* fVariablesView;
RegistersView* fRegistersView;
StackTraceView* fStackTraceView;
SourceView* fSourceView;
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 "FunctionInstance.h"
#include "Image.h"
#include "Variable.h"
// #pragma mark - StackFrame
@@ -24,15 +25,21 @@ StackFrame::StackFrame(stack_frame_type type, CpuState* cpuState,
fImage(NULL),
fFunction(NULL)
{
fCpuState->AddReference();
fCpuState->AcquireReference();
}
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);
SetFunction(NULL);
fCpuState->RemoveReference();
fCpuState->ReleaseReference();
}
@@ -47,12 +54,12 @@ void
StackFrame::SetImage(Image* image)
{
if (fImage != NULL)
fImage->RemoveReference();
fImage->ReleaseReference();
fImage = image;
if (fImage != NULL)
fImage->AddReference();
fImage->AcquireReference();
}
@@ -60,10 +67,60 @@ void
StackFrame::SetFunction(FunctionInstance* function)
{
if (fFunction != NULL)
fFunction->RemoveReference();
fFunction->ReleaseReference();
fFunction = function;
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 <ObjectList.h>
#include <Referenceable.h>
#include "Types.h"
@@ -23,6 +24,7 @@ enum stack_frame_type {
class CpuState;
class Image;
class FunctionInstance;
class Variable;
class StackFrame : public Referenceable {
@@ -49,6 +51,17 @@ public:
FunctionInstance* Function() const { return fFunction; }
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:
stack_frame_type fType;
CpuState* fCpuState;
@@ -57,6 +70,8 @@ private:
target_addr_t fReturnAddress;
Image* fImage;
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