* Added class ValueLocation to represent a location of a value on the target
machine.
* DWARF:
- Various additions to the DIE classes.
- DwarfExpressionEvaluationContext:
- Added support for location expressions and thus the missing DW_OP_piece
and DW_OP_bit_piece operations.
- Fixed some deviations from the specs.
- Added debug output.
- DwarfFile:
- Added missing evaluation of CFA expression rules.
- Added service methods to evaluate expressions, location expressions,
and constant and dynamic values.
* Added model classes for representing types and variables. Particularly the
types part is not finished yet.
* StackFrame does now contain parameters and local variables.
* Added DwarfInterfaceFactory, which creates implementation objects for the
types, as well as variables objects. It's even less finished.
* DwarfImageDebugInfo::CreateFrame(): Resolve function parameters and add them
to the stack frame. No local variables yet.
* Added the beginnings of a variables view. Only lists the names of parameters
and local variables (of understood types) ATM.
* Renamed RegisterView to RegistersView.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31614 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -29,6 +29,7 @@ SourceHdrs
|
||||
DwarfFunctionDebugInfo.cpp
|
||||
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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
+13
-12
@@ -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());
|
||||
+7
-7
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Type.h"
|
||||
|
||||
|
||||
// #pragma mark - DataMember
|
||||
|
||||
|
||||
DataMember::~DataMember()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Type
|
||||
|
||||
|
||||
Type::~Type()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - PrimitiveType
|
||||
|
||||
|
||||
PrimitiveType::~PrimitiveType()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
type_kind
|
||||
PrimitiveType::Kind() const
|
||||
{
|
||||
return TYPE_PRIMITIVE;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - CompoundType
|
||||
|
||||
|
||||
CompoundType::~CompoundType()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
type_kind
|
||||
CompoundType::Kind() const
|
||||
{
|
||||
return TYPE_COMPOUND;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ModifiedType
|
||||
|
||||
|
||||
ModifiedType::~ModifiedType()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
type_kind
|
||||
ModifiedType::Kind() const
|
||||
{
|
||||
return TYPE_MODIFIED;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - TypedefType
|
||||
|
||||
|
||||
TypedefType::~TypedefType()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
type_kind
|
||||
TypedefType::Kind() const
|
||||
{
|
||||
return TYPE_TYPEDEF;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - AddressType
|
||||
|
||||
|
||||
AddressType::~AddressType()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
type_kind
|
||||
AddressType::Kind() const
|
||||
{
|
||||
return TYPE_ADDRESS;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ArrayType
|
||||
|
||||
|
||||
ArrayType::~ArrayType()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
type_kind
|
||||
ArrayType::Kind() const
|
||||
{
|
||||
return TYPE_ARRAY;
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TYPE_H
|
||||
#define TYPE_H
|
||||
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
enum type_kind {
|
||||
TYPE_PRIMITIVE,
|
||||
TYPE_COMPOUND,
|
||||
TYPE_MODIFIED,
|
||||
TYPE_TYPEDEF,
|
||||
TYPE_ADDRESS,
|
||||
TYPE_ARRAY
|
||||
};
|
||||
|
||||
|
||||
enum address_type_kind {
|
||||
DERIVED_TYPE_POINTER,
|
||||
DERIVED_TYPE_REFERENCE
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
TYPE_MODIFIER_CONST = 0x01,
|
||||
TYPE_MODIFIER_VOLATILE = 0x02,
|
||||
TYPE_MODIFIER_RESTRICT = 0x04,
|
||||
TYPE_MODIFIER_PACKED = 0x08,
|
||||
TYPE_MODIFIER_SHARED = 0x10
|
||||
};
|
||||
|
||||
|
||||
class Type;
|
||||
|
||||
|
||||
class DataMember : public Referenceable {
|
||||
public:
|
||||
virtual ~DataMember();
|
||||
|
||||
virtual const char* Name() const = 0;
|
||||
virtual Type* GetType() const = 0;
|
||||
};
|
||||
|
||||
|
||||
class Type : public Referenceable {
|
||||
public:
|
||||
virtual ~Type();
|
||||
|
||||
virtual const char* Name() const = 0;
|
||||
virtual type_kind Kind() const = 0;
|
||||
};
|
||||
|
||||
|
||||
class PrimitiveType : public virtual Type {
|
||||
public:
|
||||
virtual ~PrimitiveType();
|
||||
|
||||
virtual type_kind Kind() const;
|
||||
|
||||
virtual uint32 TypeConstant() const = 0;
|
||||
};
|
||||
|
||||
|
||||
class CompoundType : public virtual Type {
|
||||
public:
|
||||
virtual ~CompoundType();
|
||||
|
||||
virtual type_kind Kind() const;
|
||||
|
||||
virtual int32 CountDataMembers() const = 0;
|
||||
virtual DataMember* DataMemberAt(int32 index) const = 0;
|
||||
};
|
||||
|
||||
|
||||
class ModifiedType : public virtual Type {
|
||||
public:
|
||||
virtual ~ModifiedType();
|
||||
|
||||
virtual type_kind Kind() const;
|
||||
|
||||
virtual uint32 Modifiers() const = 0;
|
||||
virtual Type* BaseType() const = 0;
|
||||
};
|
||||
|
||||
|
||||
class TypedefType : public virtual Type {
|
||||
public:
|
||||
virtual ~TypedefType();
|
||||
|
||||
virtual type_kind Kind() const;
|
||||
|
||||
virtual Type* BaseType() const = 0;
|
||||
};
|
||||
|
||||
|
||||
class AddressType : public virtual Type {
|
||||
public:
|
||||
virtual ~AddressType();
|
||||
|
||||
virtual type_kind Kind() const;
|
||||
|
||||
virtual address_type_kind AddressKind() const = 0;
|
||||
virtual Type* BaseType() const = 0;
|
||||
};
|
||||
|
||||
|
||||
class ArrayType : public virtual Type {
|
||||
public:
|
||||
virtual ~ArrayType();
|
||||
|
||||
virtual type_kind Kind() const;
|
||||
|
||||
virtual Type* BaseType() const = 0;
|
||||
virtual target_size_t CountElements() const = 0;
|
||||
// TODO: That doesn't work. We need a list of dimensions which in turn
|
||||
// are enumeration or subrange types.
|
||||
};
|
||||
|
||||
|
||||
#endif // TYPE_H
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Variable.h"
|
||||
|
||||
#include "Type.h"
|
||||
#include "ValueLocation.h"
|
||||
|
||||
|
||||
Variable::Variable(const BString& name, Type* type, ValueLocation* location)
|
||||
:
|
||||
fName(name),
|
||||
fType(type),
|
||||
fLocation(location)
|
||||
{
|
||||
fType->AcquireReference();
|
||||
fLocation->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
Variable::~Variable()
|
||||
{
|
||||
fType->ReleaseReference();
|
||||
fLocation->ReleaseReference();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VARIABLE_H
|
||||
#define VARIABLE_H
|
||||
|
||||
|
||||
#include <String.h>
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
|
||||
class Type;
|
||||
class ValueLocation;
|
||||
|
||||
|
||||
class Variable : public Referenceable {
|
||||
public:
|
||||
Variable(const BString& name, Type* type,
|
||||
ValueLocation* location);
|
||||
~Variable();
|
||||
|
||||
const BString& Name() const { return fName; }
|
||||
Type* GetType() const { return fType; }
|
||||
ValueLocation* Location() const { return fLocation; }
|
||||
|
||||
private:
|
||||
BString fName;
|
||||
Type* fType;
|
||||
ValueLocation* fLocation;
|
||||
};
|
||||
|
||||
|
||||
#endif // VARIABLE_H
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ValueLocation.h"
|
||||
|
||||
|
||||
ValueLocation::ValueLocation()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ValueLocation::ValueLocation(const ValuePieceLocation& piece)
|
||||
{
|
||||
AddPiece(piece);
|
||||
}
|
||||
|
||||
|
||||
ValueLocation::ValueLocation(const ValueLocation& other)
|
||||
:
|
||||
fPieces(other.fPieces)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueLocation::Clear()
|
||||
{
|
||||
fPieces.Clear();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ValueLocation::AddPiece(const ValuePieceLocation& piece)
|
||||
{
|
||||
return fPieces.Add(piece);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
ValueLocation::CountPieces() const
|
||||
{
|
||||
return fPieces.Size();
|
||||
}
|
||||
|
||||
|
||||
ValuePieceLocation
|
||||
ValueLocation::PieceAt(int32 index) const
|
||||
{
|
||||
if (index < 0 || index >= fPieces.Size())
|
||||
return ValuePieceLocation();
|
||||
|
||||
return fPieces.ElementAt(index);
|
||||
}
|
||||
|
||||
|
||||
ValueLocation&
|
||||
ValueLocation::operator=(const ValueLocation& other)
|
||||
{
|
||||
fPieces = other.fPieces;
|
||||
return *this;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VALUE_LOCATION_H
|
||||
#define VALUE_LOCATION_H
|
||||
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "Array.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
enum value_piece_location_type {
|
||||
VALUE_PIECE_LOCATION_INVALID, // structure is invalid
|
||||
VALUE_PIECE_LOCATION_UNKNOWN, // location unknown, but size is valid
|
||||
VALUE_PIECE_LOCATION_MEMORY, // piece is in memory
|
||||
VALUE_PIECE_LOCATION_REGISTER // piece is in a register
|
||||
};
|
||||
|
||||
|
||||
struct ValuePieceLocation {
|
||||
union {
|
||||
target_addr_t address; // memory address
|
||||
uint32 reg; // register number
|
||||
};
|
||||
target_size_t size; // size in bytes (complete ones)
|
||||
uint8 bitSize; // totalBitSize = size * 8 + bitSize
|
||||
uint8 bitOffset; // offset in bits
|
||||
value_piece_location_type type;
|
||||
|
||||
ValuePieceLocation()
|
||||
:
|
||||
type(VALUE_PIECE_LOCATION_INVALID)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return type != VALUE_PIECE_LOCATION_INVALID;
|
||||
}
|
||||
|
||||
void SetToUnknown()
|
||||
{
|
||||
type = VALUE_PIECE_LOCATION_UNKNOWN;
|
||||
}
|
||||
|
||||
void SetToMemory(target_addr_t address)
|
||||
{
|
||||
type = VALUE_PIECE_LOCATION_MEMORY;
|
||||
this->address = address;
|
||||
}
|
||||
|
||||
void SetToRegister(uint32 reg)
|
||||
{
|
||||
type = VALUE_PIECE_LOCATION_REGISTER;
|
||||
this->reg = reg;
|
||||
}
|
||||
|
||||
void SetSize(target_size_t size)
|
||||
{
|
||||
this->size = size;
|
||||
this->bitSize = 0;
|
||||
this->bitOffset = 0;
|
||||
}
|
||||
|
||||
void SetSize(uint64 bitSize, uint8 bitOffset)
|
||||
{
|
||||
this->size = bitSize / 8;
|
||||
this->bitSize = bitSize % 8;
|
||||
this->bitOffset = bitOffset;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ValueLocation : public Referenceable {
|
||||
public:
|
||||
ValueLocation();
|
||||
ValueLocation(const ValuePieceLocation& piece);
|
||||
ValueLocation(const ValueLocation& other);
|
||||
|
||||
void Clear();
|
||||
bool AddPiece(const ValuePieceLocation& piece);
|
||||
|
||||
int32 CountPieces() const;
|
||||
ValuePieceLocation PieceAt(int32 index) const;
|
||||
|
||||
ValueLocation& operator=(const ValueLocation& other);
|
||||
|
||||
private:
|
||||
typedef Array<ValuePieceLocation> PieceArray;
|
||||
|
||||
private:
|
||||
PieceArray fPieces;
|
||||
};
|
||||
|
||||
|
||||
#endif // VALUE_LOCATION_H
|
||||
Reference in New Issue
Block a user