* ValueLocation:

- Changed the bit{Offset,Size} semantics. It's now more or less
    aligned with the semantics of the respective DWARF DIE attributes.
    DwarfStackFrameDebugInfo does now correctly translate the ValueLocations
    returned by the DWARF layer (the bit piece location expression semantics is
    different for some reason).
  - ValueLocation is now aware of the target's endianess. The SetTo() method
    needs that information to correctly meddle with the pieces.
  - Support normalizing the pieces.
* Fixed retrieving the values of bit fields in various places. We still don't
  handle the bit offset/size attributes of types correctly, but I haven't seen
  those in actual debug info yet.
* Added support for enumerations. The variable view shows the enumerator names,
  when available.
* Added partial support for subrange types. C++ doesn't have those -- we only
  need them for array dimensions.
* Started adding support for array types. Still work in progress.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33314 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-09-27 04:52:43 +00:00
parent 7d82c6dd73
commit e82b494112
15 changed files with 1240 additions and 337 deletions
+83 -38
View File
@@ -519,10 +519,13 @@ GetStackFrameValueJob::_GetValue()
// find out the type of the data we want to read
type_code valueType = 0;
bool shortValueIsFine = false;
while (valueType == 0) {
switch (type->Kind()) {
case TYPE_PRIMITIVE:
valueType = dynamic_cast<PrimitiveType*>(type)->TypeConstant();
shortValueIsFine = BVariant::TypeIsInteger(valueType)
|| valueType == B_BOOL_TYPE;
TRACE_LOCALS(" TYPE_PRIMITIVE: '%c%c%c%c'\n",
int(valueType >> 24), int(valueType >> 16),
@@ -560,6 +563,38 @@ GetStackFrameValueJob::_GetValue()
// recursion work smoothly, we have to set the type and
// location at least.
return _SetValue(BVariant(), actualType, location);
case TYPE_ENUMERATION:
{
TRACE_LOCALS(" TYPE_ENUMERATION\n");
// If a base type is known, use that.
EnumerationType* enumType
= dynamic_cast<EnumerationType*>(type);
if (enumType->BaseType() != NULL) {
type = enumType->BaseType();
break;
}
// get the value type constant
// TODO: This is C source language specific!
switch (enumType->ByteSize()) {
case 1:
valueType = B_INT8_TYPE;
break;
case 2:
valueType = B_INT16_TYPE;
break;
case 4:
default:
valueType = B_INT32_TYPE;
break;
case 8:
valueType = B_INT64_TYPE;
break;
}
shortValueIsFine = true;
break;
}
default:
TRACE_LOCALS(" default -> unsupported\n");
return B_UNSUPPORTED;
@@ -578,7 +613,7 @@ GetStackFrameValueJob::_GetValue()
// check whether we know the complete location
int32 count = location->CountPieces();
TRACE_LOCALS(" location: %p, %ld pieces\n", location, count);
TRACE_LOCALS_ONLY(location->Dump();)
if (count == 0) {
TRACE_LOCALS(" -> no location\n");
@@ -592,7 +627,7 @@ GetStackFrameValueJob::_GetValue()
if (piece.type == VALUE_PIECE_LOCATION_MEMORY) {
ValueLocation* dataLocation;
error = fStackFrame->DebugInfo()->ResolveObjectDataLocation(
fStackFrame, type, piece.address, dataLocation);
fStackFrame, type, *location, dataLocation);
if (error != B_OK)
return error;
@@ -601,7 +636,7 @@ GetStackFrameValueJob::_GetValue()
}
}
target_size_t totalSize = 0;
static const size_t kMaxPieceSize = 16;
uint64 totalBitSize = 0;
for (int32 i = 0; i < count; i++) {
ValuePieceLocation piece = location->PieceAt(i);
@@ -614,48 +649,51 @@ GetStackFrameValueJob::_GetValue()
break;
}
totalSize += piece.size;
if (piece.size > kMaxPieceSize) {
TRACE_LOCALS(" -> overly long piece size (%llu bytes)\n",
piece.size);
return B_UNSUPPORTED;
}
totalBitSize += piece.bitSize;
}
TRACE_LOCALS(" -> totalSize: %llu, totalBitSize: %llu\n", totalSize,
totalBitSize);
TRACE_LOCALS(" -> totalBitSize: %llu\n", totalBitSize);
if (totalSize == 0 && totalBitSize == 0) {
if (totalBitSize == 0) {
TRACE_LOCALS(" -> no size\n");
return B_ENTRY_NOT_FOUND;
}
if (totalSize > 8 || totalSize + (totalBitSize + 7) / 8 > 8) {
TRACE_LOCALS(" -> longer than 8 bytes: unsupported\n");
if (totalBitSize > 64) {
TRACE_LOCALS(" -> longer than 64 bits: unsupported\n");
return B_UNSUPPORTED;
}
if (totalSize + (totalBitSize + 7) / 8 < BVariant::SizeOfType(valueType)) {
TRACE_LOCALS(" -> too short for value type (%llu vs. %lu)\n",
totalSize + (totalBitSize + 7) / 8,
BVariant::SizeOfType(valueType));
uint64 valueBitSize = BVariant::SizeOfType(valueType) * 8;
if (!shortValueIsFine && totalBitSize < valueBitSize) {
TRACE_LOCALS(" -> too short for value type (%llu vs. %llu bits)\n",
totalBitSize, valueBitSize);
return B_BAD_VALUE;
}
// load the data
// Load the data. Since the BitBuffer class we're using only supports big
// endian bit semantics, we convert all data to big endian before pushing
// them to the buffer. For later conversion to BVariant we need to make sure
// the final buffer has the size of the value type, so we pad the most
// significant bits with zeros.
BitBuffer valueBuffer;
if (totalBitSize < valueBitSize)
valueBuffer.AddZeroBits(valueBitSize - totalBitSize);
// If the total bit size is not byte aligned, push the respective number of
// 0 bits on a big endian architecture to get an immediately usable value.
// On a little endian architecture we'll play with the last read byte
// instead.
if (fArchitecture->IsBigEndian() && totalBitSize % 8 != 0) {
const uint8 zero = 0;
valueBuffer.AddBits(&zero, 8 - totalBitSize % 8, 0);
}
bool bigEndian = fArchitecture->IsBigEndian();
const Register* registers = fArchitecture->Registers();
for (int32 i = 0; i < count; i++) {
ValuePieceLocation piece = location->PieceAt(i);
ValuePieceLocation piece = location->PieceAt(
bigEndian ? i : count - i - 1);
uint32 bytesToRead = piece.size;
uint32 bitSize = piece.bitSize;
uint8 bitOffset = piece.bitOffset;
uint32 bitSize = piece.size * 8 + piece.bitSize;
uint32 bytesToRead = (bitSize + 7) / 8;
switch (piece.type) {
case VALUE_PIECE_LOCATION_INVALID:
@@ -663,13 +701,12 @@ GetStackFrameValueJob::_GetValue()
return B_ENTRY_NOT_FOUND;
case VALUE_PIECE_LOCATION_MEMORY:
{
target_addr_t address = piece.address + bitOffset / 8;
target_addr_t address = piece.address;
TRACE_LOCALS(" piece %ld: memory address: %#llx, bits: %lu\n",
i, address, bitSize);
bitOffset %= 8;
uint8 pieceBuffer[8];
uint8 pieceBuffer[kMaxPieceSize];
ssize_t bytesRead = fDebuggerInterface->ReadMemory(address,
pieceBuffer, bytesToRead);
if (bytesRead < 0)
@@ -684,6 +721,14 @@ GetStackFrameValueJob::_GetValue()
TRACE_LOCALS("\n");
)
// convert to big endian
if (!bigEndian) {
for (int32 k = bytesRead / 2 - 1; k >= 0; k--) {
std::swap(pieceBuffer[k],
pieceBuffer[bytesRead - k - 1]);
}
}
valueBuffer.AddBits(pieceBuffer, bitSize, bitOffset);
break;
}
@@ -700,7 +745,7 @@ GetStackFrameValueJob::_GetValue()
if (registerValue.Size() < bytesToRead)
return B_ENTRY_NOT_FOUND;
if (!fArchitecture->IsHostEndian())
if (!bigEndian)
registerValue.SwapEndianess();
valueBuffer.AddBits(registerValue.Bytes(), bitSize, bitOffset);
break;
@@ -708,12 +753,9 @@ GetStackFrameValueJob::_GetValue()
}
}
// If the total bit size is not byte aligned, shift the last byte by the
// respective number of bits on a little endian architecture to get a usable
// value.
if (!fArchitecture->IsBigEndian() && totalBitSize % 8 != 0)
valueBuffer.Bytes()[totalBitSize / 8] >>= 8 - totalBitSize % 8;
// TODO: Verify that this is the way to handle it!
// If we don't have enough bits in the buffer apparently adding some failed.
if (valueBuffer.BitSize() < valueBitSize)
return B_NO_MEMORY;
// convert the bits into something we can work with
BVariant value;
@@ -723,8 +765,10 @@ GetStackFrameValueJob::_GetValue()
return error;
}
if (!fArchitecture->IsHostEndian())
// convert to host endianess
#if B_HOST_IS_LENDIAN
value.SwapEndianess();
#endif
return _SetValue(value, actualType, location);
}
@@ -788,9 +832,10 @@ GetStackFrameValueJob::_ResolveTypeAndLocation(Type*& _type,
TypeComponent component = fPath->ComponentAt(componentCount - 1);
switch (component.typeKind) {
case TYPE_PRIMITIVE:
case TYPE_ENUMERATION:
// cannot happen
TRACE_LOCALS("GetStackFrameValueJob::_ResolveTypeAndLocation(): "
"TYPE_PRIMITIVE subcomponent!\n");
"TYPE_PRIMITIVE/TYPE_ENUMERATION subcomponent!\n");
return B_BAD_VALUE;
case TYPE_COMPOUND:
{
@@ -322,7 +322,7 @@ ArchitectureX86::CreateStackFrame(Image* image, FunctionDebugInfo* function,
// create the stack frame
StackFrameDebugInfo* stackFrameDebugInfo
= new(std::nothrow) NoOpStackFrameDebugInfo;
= new(std::nothrow) NoOpStackFrameDebugInfo(this);
if (stackFrameDebugInfo == NULL)
return B_NO_MEMORY;
Reference<StackFrameDebugInfo> stackFrameDebugInfoReference(
@@ -44,7 +44,6 @@
#include "TeamMemory.h"
#include "Tracing.h"
#include "UnsupportedLanguage.h"
#include "ValueLocation.h"
#include "Variable.h"
@@ -397,7 +396,7 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
// create the stack frame debug info
DIESubprogram* subprogramEntry = function->SubprogramEntry();
DwarfStackFrameDebugInfo* stackFrameDebugInfo
= new(std::nothrow) DwarfStackFrameDebugInfo(fFile, unit,
= new(std::nothrow) DwarfStackFrameDebugInfo(fArchitecture, fFile, unit,
subprogramEntry, instructionPointer, framePointer, inputInterface,
fromDwarfMap);
if (stackFrameDebugInfo == NULL)
File diff suppressed because it is too large Load Diff
@@ -19,9 +19,11 @@ class DIEAddressingType;
class DIEArrayType;
class DIEBaseType;
class DIECompoundType;
class DIEEnumerationType;
class DIEFormalParameter;
class DIEModifiedType;
class DIESubprogram;
class DIESubrangeType;
class DIEType;
class DIETypedef;
class DIEVariable;
@@ -37,7 +39,8 @@ class Variable;
class DwarfStackFrameDebugInfo : public StackFrameDebugInfo {
public:
DwarfStackFrameDebugInfo(DwarfFile* file,
DwarfStackFrameDebugInfo(
Architecture* architecture, DwarfFile* file,
CompilationUnit* compilationUnit,
DIESubprogram* subprogramEntry,
target_addr_t instructionPointer,
@@ -50,7 +53,7 @@ public:
virtual status_t ResolveObjectDataLocation(
StackFrame* stackFrame, Type* type,
target_addr_t objectAddress,
const ValueLocation& objectLocation,
ValueLocation*& _location);
virtual status_t ResolveBaseTypeLocation(
StackFrame* stackFrame, Type* type,
@@ -80,11 +83,15 @@ private:
struct DwarfType;
struct DwarfInheritance;
struct DwarfDataMember;
struct DwarfEnumerationValue;
struct DwarfArrayDimension;
struct DwarfPrimitiveType;
struct DwarfCompoundType;
struct DwarfModifiedType;
struct DwarfTypedefType;
struct DwarfAddressType;
struct DwarfEnumerationType;
struct DwarfSubrangeType;
struct DwarfArrayType;
struct DwarfTypeHashDefinition;
@@ -123,6 +130,12 @@ private:
status_t _CreateArrayType(const BString& name,
DIEArrayType* typeEntry,
DwarfType*& _type);
status_t _CreateEnumerationType(const BString& name,
DIEEnumerationType* typeEntry,
DwarfType*& _type);
status_t _CreateSubrangeType(const BString& name,
DIESubrangeType* typeEntry,
DwarfType*& _type);
status_t _CreateVariable(ObjectID* id,
const BString& name, DIEType* typeEntry,
@@ -134,8 +147,10 @@ private:
status_t _ResolveTypeByteSize(DIEType* typeEntry,
uint64& _size);
void _FixLocation(ValueLocation* location,
DwarfType* type);
status_t _ResolveLocation(
const LocationDescription* description,
target_addr_t objectAddress, Type* type,
ValueLocation& _location);
template<typename EntryType>
static DIEType* _GetDIEType(EntryType* entry);
@@ -7,7 +7,9 @@
#include "NoOpStackFrameDebugInfo.h"
NoOpStackFrameDebugInfo::NoOpStackFrameDebugInfo()
NoOpStackFrameDebugInfo::NoOpStackFrameDebugInfo(Architecture* architecture)
:
StackFrameDebugInfo(architecture)
{
}
@@ -19,7 +21,7 @@ NoOpStackFrameDebugInfo::~NoOpStackFrameDebugInfo()
status_t
NoOpStackFrameDebugInfo::ResolveObjectDataLocation(StackFrame* stackFrame,
Type* type, target_addr_t objectAddress, ValueLocation*& _location)
Type* type, const ValueLocation& objectLocation, ValueLocation*& _location)
{
return B_UNSUPPORTED;
}
@@ -11,12 +11,13 @@
class NoOpStackFrameDebugInfo : public StackFrameDebugInfo {
public:
NoOpStackFrameDebugInfo();
NoOpStackFrameDebugInfo(
Architecture* architecture);
virtual ~NoOpStackFrameDebugInfo();
virtual status_t ResolveObjectDataLocation(
StackFrame* stackFrame, Type* type,
target_addr_t objectAddress,
const ValueLocation& objectLocation,
ValueLocation*& _location);
virtual status_t ResolveBaseTypeLocation(
StackFrame* stackFrame, Type* type,
@@ -6,12 +6,39 @@
#include "StackFrameDebugInfo.h"
#include "Architecture.h"
#include "ValueLocation.h"
StackFrameDebugInfo::StackFrameDebugInfo()
StackFrameDebugInfo::StackFrameDebugInfo(Architecture* architecture)
:
fArchitecture(architecture)
{
fArchitecture->AcquireReference();
}
StackFrameDebugInfo::~StackFrameDebugInfo()
{
fArchitecture->ReleaseReference();
}
status_t
StackFrameDebugInfo::ResolveObjectDataLocation(StackFrame* stackFrame,
Type* type, target_addr_t objectAddress, ValueLocation*& _location)
{
ValuePieceLocation piece;
piece.SetToMemory(objectAddress);
piece.SetSize(0);
// We set the piece size to 0 as an indicator that the size has to be
// set.
// TODO: We could set the byte size from type, but that may not be
// accurate. We may want to add bit offset and size to Type.
ValueLocation location(fArchitecture->IsBigEndian());
if (!location.AddPiece(piece))
return B_NO_MEMORY;
return ResolveObjectDataLocation(stackFrame, type, location, _location);
}
@@ -11,6 +11,7 @@
#include "Types.h"
class Architecture;
class BaseType;
class DataMember;
class StackFrame;
@@ -20,14 +21,19 @@ class ValueLocation;
class StackFrameDebugInfo : public Referenceable {
public:
StackFrameDebugInfo();
StackFrameDebugInfo(Architecture* architecture);
virtual ~StackFrameDebugInfo();
virtual status_t ResolveObjectDataLocation(
StackFrame* stackFrame, Type* type,
target_addr_t objectAddress,
const ValueLocation& objectLocation,
ValueLocation*& _location) = 0;
// returns a reference
status_t ResolveObjectDataLocation(
StackFrame* stackFrame, Type* type,
target_addr_t objectAddress,
ValueLocation*& _location);
// returns a reference
virtual status_t ResolveBaseTypeLocation(
StackFrame* stackFrame, Type* type,
BaseType* baseType,
@@ -40,6 +46,9 @@ public:
const ValueLocation& parentLocation,
ValueLocation*& _location) = 0;
// returns a reference
protected:
Architecture* fArchitecture;
};
@@ -24,7 +24,12 @@
#include "Variable.h"
class VariablesView::ValueNode : Referenceable {
enum {
VALUE_NODE_TYPE = 'valn'
};
class VariablesView::ValueNode : public Referenceable {
public:
ValueNode(ValueNode* parent, Variable* variable, TypeComponentPath* path,
const BString& name, Type* type)
@@ -34,11 +39,13 @@ public:
fPath(path),
fName(name),
fType(type),
fRawType(type->ResolveRawType()),
fChildrenAdded(false)
{
fVariable->AcquireReference();
fPath->AcquireReference();
fType->AcquireReference();
fRawType->AcquireReference();
}
~ValueNode()
@@ -49,6 +56,7 @@ public:
fVariable->ReleaseReference();
fPath->ReleaseReference();
fType->ReleaseReference();
fRawType->ReleaseReference();
}
ValueNode* Parent() const
@@ -76,6 +84,11 @@ public:
return fType;
}
Type* RawType() const
{
return fRawType;
}
const BVariant& Value() const
{
return fValue;
@@ -129,6 +142,7 @@ private:
TypeComponentPath* fPath;
BString fName;
Type* fType;
Type* fRawType;
BVariant fValue;
ChildList fChildren;
bool fChildrenAdded;
@@ -150,16 +164,21 @@ public:
}
protected:
virtual BField* PrepareField(const BVariant& value) const
virtual BField* PrepareField(const BVariant& _value) const
{
BVariant value = _ResolveValue(_value);
char buffer[64];
return StringTableColumn::PrepareField(
BVariant(_ToString(value, buffer, sizeof(buffer)),
B_VARIANT_DONT_COPY_DATA));
}
virtual int CompareValues(const BVariant& a, const BVariant& b)
virtual int CompareValues(const BVariant& _a, const BVariant& _b)
{
BVariant a = _ResolveValue(_a);
BVariant b = _ResolveValue(_b);
// If neither value is a number, compare the strings. If only one value
// is a number, it is considered to be greater.
if (!a.IsNumber()) {
@@ -190,6 +209,26 @@ protected:
}
private:
BVariant _ResolveValue(const BVariant& nodeValue) const
{
BVariant value;
if (nodeValue.Type() != VALUE_NODE_TYPE)
return BVariant();
ValueNode* node = dynamic_cast<ValueNode*>(nodeValue.ToReferenceable());
// replace enumerations values with their names
if (node->RawType()->Kind() == TYPE_ENUMERATION) {
EnumerationValue* enumValue
= dynamic_cast<EnumerationType*>(node->RawType())
->ValueFor(node->Value());
if (enumValue != NULL)
return enumValue->Name();
}
return node->Value();
}
const char* _ToString(const BVariant& value, char* buffer,
size_t bufferSize) const
{
@@ -329,7 +368,7 @@ public:
if (node->Value().Type() == 0)
return false;
_value = node->Value();
_value.SetTo(node, VALUE_NODE_TYPE);
return true;
default:
return false;
@@ -484,6 +523,10 @@ private:
TRACE_LOCALS("TYPE_ARRAY\n");
// TODO:...
return;
case TYPE_ENUMERATION:
TRACE_LOCALS("TYPE_ENUMERATION\n");
done = true;
return;
default:
TRACE_LOCALS("unknown\n");
return;
+105
View File
@@ -23,6 +23,47 @@ DataMember::~DataMember()
}
// #pragma mark - EnumerationValue
EnumerationValue::~EnumerationValue()
{
}
// #pragma mark - ArrayDimension
ArrayDimension::~ArrayDimension()
{
}
uint64
ArrayDimension::CountElements() const
{
Type* type = GetType();
if (type->Kind() == TYPE_ENUMERATION)
return dynamic_cast<EnumerationType*>(type)->CountValues();
if (type->Kind() == TYPE_SUBRANGE) {
SubrangeType* subrangeType = dynamic_cast<SubrangeType*>(type);
BVariant lower = subrangeType->LowerBound();
BVariant upper = subrangeType->LowerBound();
bool isSigned;
if (!lower.IsInteger(&isSigned) || !upper.IsInteger())
return 0;
return isSigned
? upper.ToInt64() - lower.ToInt64()
: upper.ToUInt64() - lower.ToUInt64();
}
return 0;
}
// #pragma mark - Type
@@ -31,6 +72,13 @@ Type::~Type()
}
Type*
Type::ResolveRawType() const
{
return const_cast<Type*>(this);
}
// #pragma mark - PrimitiveType
@@ -76,6 +124,13 @@ ModifiedType::Kind() const
}
Type*
ModifiedType::ResolveRawType() const
{
return BaseType();
}
// #pragma mark - TypedefType
@@ -91,6 +146,13 @@ TypedefType::Kind() const
}
Type*
TypedefType::ResolveRawType() const
{
return BaseType();
}
// #pragma mark - AddressType
@@ -106,6 +168,49 @@ AddressType::Kind() const
}
// #pragma mark - EnumerationType
EnumerationType::~EnumerationType()
{
}
type_kind
EnumerationType::Kind() const
{
return TYPE_ENUMERATION;
}
EnumerationValue*
EnumerationType::ValueFor(const BVariant& value) const
{
// TODO: Optimize?
for (int32 i = 0; EnumerationValue* enumValue = ValueAt(i); i++) {
if (enumValue->Value() == value)
return enumValue;
}
return NULL;
}
// #pragma mark - SubrangeType
SubrangeType::~SubrangeType()
{
}
type_kind
SubrangeType::Kind() const
{
return TYPE_SUBRANGE;
}
// #pragma mark - ArrayType
+58 -3
View File
@@ -7,6 +7,7 @@
#include <Referenceable.h>
#include <Variant.h>
#include "Types.h"
@@ -17,6 +18,8 @@ enum type_kind {
TYPE_MODIFIED,
TYPE_TYPEDEF,
TYPE_ADDRESS,
TYPE_ENUMERATION,
TYPE_SUBRANGE,
TYPE_ARRAY
};
@@ -56,6 +59,26 @@ public:
};
class EnumerationValue : public Referenceable {
public:
virtual ~EnumerationValue();
virtual const char* Name() const = 0;
virtual BVariant Value() const = 0;
};
class ArrayDimension : public Referenceable {
public:
virtual ~ArrayDimension();
virtual Type* GetType() const = 0;
// subrange or enumeration
virtual uint64 CountElements() const;
// returns 0, if unknown
};
class Type : public Referenceable {
public:
virtual ~Type();
@@ -63,6 +86,8 @@ public:
virtual const char* Name() const = 0;
virtual type_kind Kind() const = 0;
virtual target_size_t ByteSize() const = 0;
virtual Type* ResolveRawType() const;
// strips modifiers and typedefs
};
@@ -98,6 +123,7 @@ public:
virtual uint32 Modifiers() const = 0;
virtual Type* BaseType() const = 0;
virtual Type* ResolveRawType() const;
};
@@ -108,6 +134,7 @@ public:
virtual type_kind Kind() const;
virtual Type* BaseType() const = 0;
virtual Type* ResolveRawType() const;
};
@@ -122,6 +149,34 @@ public:
};
class EnumerationType : public virtual Type {
public:
virtual ~EnumerationType();
virtual type_kind Kind() const;
virtual Type* BaseType() const = 0;
// may return NULL
virtual int32 CountValues() const = 0;
virtual EnumerationValue* ValueAt(int32 index) const = 0;
virtual EnumerationValue* ValueFor(const BVariant& value) const;
};
class SubrangeType : public virtual Type {
public:
virtual ~SubrangeType();
virtual type_kind Kind() const;
virtual Type* BaseType() const = 0;
virtual BVariant LowerBound() const = 0;
virtual BVariant UpperBound() const = 0;
};
class ArrayType : public virtual Type {
public:
virtual ~ArrayType();
@@ -129,9 +184,9 @@ public:
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.
virtual int32 CountDimensions() const = 0;
virtual ArrayDimension* DimensionAt(int32 index) const = 0;
};
@@ -43,6 +43,12 @@ TypeComponent::Dump() const
case TYPE_ADDRESS:
printf("address");
break;
case TYPE_ENUMERATION:
printf("enum");
break;
case TYPE_SUBRANGE:
printf("subrange");
break;
case TYPE_ARRAY:
printf("array");
break;
+145 -48
View File
@@ -7,12 +7,59 @@
#include "ValueLocation.h"
// #pragma mark - ValuePieceLocation
ValuePieceLocation&
ValuePieceLocation::Normalize(bool bigEndian)
{
uint64 excessMSBs = bitOffset / 8;
uint64 excessLSBs = size - (bitOffset + bitSize + 7) / 8;
if (excessMSBs > 0 || excessLSBs > 0) {
switch (type) {
case VALUE_PIECE_LOCATION_MEMORY:
if (bigEndian)
address += excessMSBs;
else
address += excessLSBs;
bitOffset -= excessMSBs * 8;
size -= excessMSBs + excessLSBs;
break;
case VALUE_PIECE_LOCATION_UNKNOWN:
bitOffset -= excessMSBs * 8;
size -= excessMSBs + excessLSBs;
break;
case VALUE_PIECE_LOCATION_REGISTER:
default:
break;
}
}
return *this;
}
// #pragma mark - ValueLocation
ValueLocation::ValueLocation()
:
fBigEndian(false)
{
}
ValueLocation::ValueLocation(const ValuePieceLocation& piece)
ValueLocation::ValueLocation(bool bigEndian)
:
fBigEndian(bigEndian)
{
}
ValueLocation::ValueLocation(bool bigEndian, const ValuePieceLocation& piece)
:
fBigEndian(bigEndian)
{
AddPiece(piece);
}
@@ -20,7 +67,8 @@ ValueLocation::ValueLocation(const ValuePieceLocation& piece)
ValueLocation::ValueLocation(const ValueLocation& other)
:
fPieces(other.fPieces)
fPieces(other.fPieces),
fBigEndian(other.fBigEndian)
{
}
@@ -31,60 +79,105 @@ ValueLocation::SetTo(const ValueLocation& other, uint64 bitOffset,
{
Clear();
// skip pieces before the offset
fBigEndian = other.fBigEndian;
// compute the total bit size
int32 count = other.CountPieces();
int32 i;
ValuePieceLocation piece;
for (i = 0; i < count; i++) {
piece = other.PieceAt(i);
if (piece.size * 8 + piece.bitSize > bitOffset)
break;
bitOffset -= piece.size * 8 + piece.bitSize;
uint64 totalBitSize = 0;
for (int32 i = 0; i < count; i++) {
ValuePieceLocation piece = other.PieceAt(i);
totalBitSize += piece.bitSize;
}
if (i >= count)
return true;
// adjust requested bit offset/size to something reasonable, if necessary
if (bitOffset + bitSize > totalBitSize) {
if (bitOffset >= totalBitSize)
return true;
bitSize = totalBitSize - bitOffset;
}
// handle partial piece
if (bitOffset > 0) {
uint64 remainingBits = piece.size * 8 + piece.bitSize - bitOffset;
piece.size = remainingBits / 8;
piece.bitSize = remainingBits % 8;
if (fBigEndian) {
// Big endian: Skip the superfluous most significant bits, copy the
// pieces we need (cutting the first and the last one as needed) and
// ignore the remaining pieces.
switch (piece.type) {
case VALUE_PIECE_LOCATION_MEMORY:
piece.address += (bitOffset + piece.bitOffset) / 8;
piece.bitOffset = (bitOffset + piece.bitOffset) % 8;
break;
case VALUE_PIECE_LOCATION_UNKNOWN:
piece.bitOffset = 0;
break;
case VALUE_PIECE_LOCATION_REGISTER:
piece.bitOffset += bitOffset;
break;
default:
// skip pieces for the most significant bits we don't need anymore
uint64 bitsToSkip = bitOffset;
int32 i;
ValuePieceLocation piece;
for (i = 0; i < count; i++) {
piece = other.PieceAt(i);
if (piece.bitSize > bitsToSkip)
break;
bitsToSkip -= piece.bitSize;
}
}
// handle remaining pieces
while (bitSize > 0) {
target_addr_t pieceSize = piece.size * 8 + piece.bitSize;
if (pieceSize > bitSize) {
// the piece is bigger than the remaining size -- cut it
piece.size = bitSize / 8;
piece.bitSize = bitSize % 8;
bitSize = 0;
} else
bitSize -= pieceSize;
// handle partial piece
if (bitsToSkip > 0) {
piece.bitOffset += bitsToSkip;
piece.bitSize -= bitsToSkip;
piece.Normalize(fBigEndian);
}
if (!AddPiece(piece))
return false;
// handle remaining pieces
while (bitSize > 0) {
if (piece.bitSize > bitSize) {
// the piece is bigger than the remaining size -- cut it
piece.bitSize = bitSize;
piece.Normalize(fBigEndian);
bitSize = 0;
} else
bitSize -= piece.bitSize;
if (++i >= count)
break;
if (!AddPiece(piece))
return false;
piece = other.PieceAt(i);
if (++i >= count)
break;
piece = other.PieceAt(i);
}
} else {
// Little endian: Skip the superfluous least significant bits, copy the
// pieces we need (cutting the first and the last one as needed) and
// ignore the remaining pieces.
// skip pieces for the least significant bits we don't need anymore
uint64 bitsToSkip = totalBitSize - bitOffset - bitSize;
int32 i;
ValuePieceLocation piece;
for (i = 0; i < count; i++) {
piece = other.PieceAt(i);
if (piece.bitSize > bitsToSkip)
break;
bitsToSkip -= piece.bitSize;
}
// handle partial piece
if (bitsToSkip > 0) {
piece.bitSize -= bitsToSkip;
piece.Normalize(fBigEndian);
}
// handle remaining pieces
while (bitSize > 0) {
if (piece.bitSize > bitSize) {
// the piece is bigger than the remaining size -- cut it
piece.bitOffset += piece.bitSize - bitSize;
piece.bitSize = bitSize;
piece.Normalize(fBigEndian);
bitSize = 0;
} else
bitSize -= piece.bitSize;
if (!AddPiece(piece))
return false;
if (++i >= count)
break;
piece = other.PieceAt(i);
}
}
return true;
@@ -101,6 +194,8 @@ ValueLocation::Clear()
bool
ValueLocation::AddPiece(const ValuePieceLocation& piece)
{
// Just add, don't normalize. This allows for using the class with different
// semantics (e.g. in the DWARF code).
return fPieces.Add(piece);
}
@@ -136,6 +231,7 @@ ValueLocation&
ValueLocation::operator=(const ValueLocation& other)
{
fPieces = other.fPieces;
fBigEndian = other.fBigEndian;
return *this;
}
@@ -144,7 +240,8 @@ void
ValueLocation::Dump() const
{
int32 count = fPieces.Size();
printf("ValueLocation: %ld pieces:\n", count);
printf("ValueLocation: %s endian, %ld pieces:\n",
fBigEndian ? "big" : "little", count);
for (int32 i = 0; i < count; i++) {
const ValuePieceLocation& piece = fPieces[i];
@@ -163,7 +260,7 @@ ValueLocation::Dump() const
break;
}
printf(" size: %llu+%u, offset: %u\n", piece.size, piece.bitSize,
piece.bitOffset);
printf(" size: %llu (%llu bits), offset: %llu bits\n", piece.size,
piece.bitSize, piece.bitOffset);
}
}
+18 -8
View File
@@ -25,9 +25,11 @@ struct ValuePieceLocation {
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
target_size_t size; // size in bytes (including
// incomplete ones)
uint64 bitSize; // total size in bits
uint64 bitOffset; // bit offset (to the most
// significant bit)
value_piece_location_type type;
ValuePieceLocation()
@@ -61,29 +63,36 @@ struct ValuePieceLocation {
void SetSize(target_size_t size)
{
this->size = size;
this->bitSize = 0;
this->bitSize = size * 8;
this->bitOffset = 0;
}
void SetSize(uint64 bitSize, uint8 bitOffset)
void SetSize(uint64 bitSize, uint64 bitOffset)
{
this->size = bitSize / 8;
this->bitSize = bitSize % 8;
this->size = (bitOffset + bitSize + 7) / 8;
this->bitSize = bitSize;
this->bitOffset = bitOffset;
}
ValuePieceLocation& Normalize(bool bigEndian);
};
class ValueLocation : public Referenceable {
public:
ValueLocation();
ValueLocation(const ValuePieceLocation& piece);
ValueLocation(bool bigEndian);
ValueLocation(bool bigEndian,
const ValuePieceLocation& piece);
ValueLocation(const ValueLocation& other);
bool SetTo(const ValueLocation& other,
uint64 bitOffset, uint64 bitSize);
void Clear();
bool IsBigEndian() const { return fBigEndian; }
bool AddPiece(const ValuePieceLocation& piece);
int32 CountPieces() const;
@@ -100,6 +109,7 @@ private:
private:
PieceArray fPieces;
bool fBigEndian;
};