* 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:
+83
-38
@@ -519,10 +519,13 @@ GetStackFrameValueJob::_GetValue()
|
|||||||
|
|
||||||
// find out the type of the data we want to read
|
// find out the type of the data we want to read
|
||||||
type_code valueType = 0;
|
type_code valueType = 0;
|
||||||
|
bool shortValueIsFine = false;
|
||||||
while (valueType == 0) {
|
while (valueType == 0) {
|
||||||
switch (type->Kind()) {
|
switch (type->Kind()) {
|
||||||
case TYPE_PRIMITIVE:
|
case TYPE_PRIMITIVE:
|
||||||
valueType = dynamic_cast<PrimitiveType*>(type)->TypeConstant();
|
valueType = dynamic_cast<PrimitiveType*>(type)->TypeConstant();
|
||||||
|
shortValueIsFine = BVariant::TypeIsInteger(valueType)
|
||||||
|
|| valueType == B_BOOL_TYPE;
|
||||||
|
|
||||||
TRACE_LOCALS(" TYPE_PRIMITIVE: '%c%c%c%c'\n",
|
TRACE_LOCALS(" TYPE_PRIMITIVE: '%c%c%c%c'\n",
|
||||||
int(valueType >> 24), int(valueType >> 16),
|
int(valueType >> 24), int(valueType >> 16),
|
||||||
@@ -560,6 +563,38 @@ GetStackFrameValueJob::_GetValue()
|
|||||||
// recursion work smoothly, we have to set the type and
|
// recursion work smoothly, we have to set the type and
|
||||||
// location at least.
|
// location at least.
|
||||||
return _SetValue(BVariant(), actualType, location);
|
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:
|
default:
|
||||||
TRACE_LOCALS(" default -> unsupported\n");
|
TRACE_LOCALS(" default -> unsupported\n");
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
@@ -578,7 +613,7 @@ GetStackFrameValueJob::_GetValue()
|
|||||||
// check whether we know the complete location
|
// check whether we know the complete location
|
||||||
int32 count = location->CountPieces();
|
int32 count = location->CountPieces();
|
||||||
|
|
||||||
TRACE_LOCALS(" location: %p, %ld pieces\n", location, count);
|
TRACE_LOCALS_ONLY(location->Dump();)
|
||||||
|
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
TRACE_LOCALS(" -> no location\n");
|
TRACE_LOCALS(" -> no location\n");
|
||||||
@@ -592,7 +627,7 @@ GetStackFrameValueJob::_GetValue()
|
|||||||
if (piece.type == VALUE_PIECE_LOCATION_MEMORY) {
|
if (piece.type == VALUE_PIECE_LOCATION_MEMORY) {
|
||||||
ValueLocation* dataLocation;
|
ValueLocation* dataLocation;
|
||||||
error = fStackFrame->DebugInfo()->ResolveObjectDataLocation(
|
error = fStackFrame->DebugInfo()->ResolveObjectDataLocation(
|
||||||
fStackFrame, type, piece.address, dataLocation);
|
fStackFrame, type, *location, dataLocation);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -601,7 +636,7 @@ GetStackFrameValueJob::_GetValue()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target_size_t totalSize = 0;
|
static const size_t kMaxPieceSize = 16;
|
||||||
uint64 totalBitSize = 0;
|
uint64 totalBitSize = 0;
|
||||||
for (int32 i = 0; i < count; i++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
ValuePieceLocation piece = location->PieceAt(i);
|
ValuePieceLocation piece = location->PieceAt(i);
|
||||||
@@ -614,48 +649,51 @@ GetStackFrameValueJob::_GetValue()
|
|||||||
break;
|
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;
|
totalBitSize += piece.bitSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE_LOCALS(" -> totalSize: %llu, totalBitSize: %llu\n", totalSize,
|
TRACE_LOCALS(" -> totalBitSize: %llu\n", totalBitSize);
|
||||||
totalBitSize);
|
|
||||||
|
|
||||||
if (totalSize == 0 && totalBitSize == 0) {
|
if (totalBitSize == 0) {
|
||||||
TRACE_LOCALS(" -> no size\n");
|
TRACE_LOCALS(" -> no size\n");
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalSize > 8 || totalSize + (totalBitSize + 7) / 8 > 8) {
|
if (totalBitSize > 64) {
|
||||||
TRACE_LOCALS(" -> longer than 8 bytes: unsupported\n");
|
TRACE_LOCALS(" -> longer than 64 bits: unsupported\n");
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalSize + (totalBitSize + 7) / 8 < BVariant::SizeOfType(valueType)) {
|
uint64 valueBitSize = BVariant::SizeOfType(valueType) * 8;
|
||||||
TRACE_LOCALS(" -> too short for value type (%llu vs. %lu)\n",
|
if (!shortValueIsFine && totalBitSize < valueBitSize) {
|
||||||
totalSize + (totalBitSize + 7) / 8,
|
TRACE_LOCALS(" -> too short for value type (%llu vs. %llu bits)\n",
|
||||||
BVariant::SizeOfType(valueType));
|
totalBitSize, valueBitSize);
|
||||||
return B_BAD_VALUE;
|
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;
|
BitBuffer valueBuffer;
|
||||||
|
if (totalBitSize < valueBitSize)
|
||||||
|
valueBuffer.AddZeroBits(valueBitSize - totalBitSize);
|
||||||
|
|
||||||
// If the total bit size is not byte aligned, push the respective number of
|
bool bigEndian = fArchitecture->IsBigEndian();
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Register* registers = fArchitecture->Registers();
|
const Register* registers = fArchitecture->Registers();
|
||||||
for (int32 i = 0; i < count; i++) {
|
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;
|
uint8 bitOffset = piece.bitOffset;
|
||||||
uint32 bitSize = piece.size * 8 + piece.bitSize;
|
|
||||||
uint32 bytesToRead = (bitSize + 7) / 8;
|
|
||||||
|
|
||||||
switch (piece.type) {
|
switch (piece.type) {
|
||||||
case VALUE_PIECE_LOCATION_INVALID:
|
case VALUE_PIECE_LOCATION_INVALID:
|
||||||
@@ -663,13 +701,12 @@ GetStackFrameValueJob::_GetValue()
|
|||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
case VALUE_PIECE_LOCATION_MEMORY:
|
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",
|
TRACE_LOCALS(" piece %ld: memory address: %#llx, bits: %lu\n",
|
||||||
i, address, bitSize);
|
i, address, bitSize);
|
||||||
|
|
||||||
bitOffset %= 8;
|
uint8 pieceBuffer[kMaxPieceSize];
|
||||||
uint8 pieceBuffer[8];
|
|
||||||
ssize_t bytesRead = fDebuggerInterface->ReadMemory(address,
|
ssize_t bytesRead = fDebuggerInterface->ReadMemory(address,
|
||||||
pieceBuffer, bytesToRead);
|
pieceBuffer, bytesToRead);
|
||||||
if (bytesRead < 0)
|
if (bytesRead < 0)
|
||||||
@@ -684,6 +721,14 @@ GetStackFrameValueJob::_GetValue()
|
|||||||
TRACE_LOCALS("\n");
|
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);
|
valueBuffer.AddBits(pieceBuffer, bitSize, bitOffset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -700,7 +745,7 @@ GetStackFrameValueJob::_GetValue()
|
|||||||
if (registerValue.Size() < bytesToRead)
|
if (registerValue.Size() < bytesToRead)
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
if (!fArchitecture->IsHostEndian())
|
if (!bigEndian)
|
||||||
registerValue.SwapEndianess();
|
registerValue.SwapEndianess();
|
||||||
valueBuffer.AddBits(registerValue.Bytes(), bitSize, bitOffset);
|
valueBuffer.AddBits(registerValue.Bytes(), bitSize, bitOffset);
|
||||||
break;
|
break;
|
||||||
@@ -708,12 +753,9 @@ GetStackFrameValueJob::_GetValue()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the total bit size is not byte aligned, shift the last byte by the
|
// If we don't have enough bits in the buffer apparently adding some failed.
|
||||||
// respective number of bits on a little endian architecture to get a usable
|
if (valueBuffer.BitSize() < valueBitSize)
|
||||||
// value.
|
return B_NO_MEMORY;
|
||||||
if (!fArchitecture->IsBigEndian() && totalBitSize % 8 != 0)
|
|
||||||
valueBuffer.Bytes()[totalBitSize / 8] >>= 8 - totalBitSize % 8;
|
|
||||||
// TODO: Verify that this is the way to handle it!
|
|
||||||
|
|
||||||
// convert the bits into something we can work with
|
// convert the bits into something we can work with
|
||||||
BVariant value;
|
BVariant value;
|
||||||
@@ -723,8 +765,10 @@ GetStackFrameValueJob::_GetValue()
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fArchitecture->IsHostEndian())
|
// convert to host endianess
|
||||||
|
#if B_HOST_IS_LENDIAN
|
||||||
value.SwapEndianess();
|
value.SwapEndianess();
|
||||||
|
#endif
|
||||||
|
|
||||||
return _SetValue(value, actualType, location);
|
return _SetValue(value, actualType, location);
|
||||||
}
|
}
|
||||||
@@ -788,9 +832,10 @@ GetStackFrameValueJob::_ResolveTypeAndLocation(Type*& _type,
|
|||||||
TypeComponent component = fPath->ComponentAt(componentCount - 1);
|
TypeComponent component = fPath->ComponentAt(componentCount - 1);
|
||||||
switch (component.typeKind) {
|
switch (component.typeKind) {
|
||||||
case TYPE_PRIMITIVE:
|
case TYPE_PRIMITIVE:
|
||||||
|
case TYPE_ENUMERATION:
|
||||||
// cannot happen
|
// cannot happen
|
||||||
TRACE_LOCALS("GetStackFrameValueJob::_ResolveTypeAndLocation(): "
|
TRACE_LOCALS("GetStackFrameValueJob::_ResolveTypeAndLocation(): "
|
||||||
"TYPE_PRIMITIVE subcomponent!\n");
|
"TYPE_PRIMITIVE/TYPE_ENUMERATION subcomponent!\n");
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
case TYPE_COMPOUND:
|
case TYPE_COMPOUND:
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -322,7 +322,7 @@ ArchitectureX86::CreateStackFrame(Image* image, FunctionDebugInfo* function,
|
|||||||
|
|
||||||
// create the stack frame
|
// create the stack frame
|
||||||
StackFrameDebugInfo* stackFrameDebugInfo
|
StackFrameDebugInfo* stackFrameDebugInfo
|
||||||
= new(std::nothrow) NoOpStackFrameDebugInfo;
|
= new(std::nothrow) NoOpStackFrameDebugInfo(this);
|
||||||
if (stackFrameDebugInfo == NULL)
|
if (stackFrameDebugInfo == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
Reference<StackFrameDebugInfo> stackFrameDebugInfoReference(
|
Reference<StackFrameDebugInfo> stackFrameDebugInfoReference(
|
||||||
|
|||||||
@@ -44,7 +44,6 @@
|
|||||||
#include "TeamMemory.h"
|
#include "TeamMemory.h"
|
||||||
#include "Tracing.h"
|
#include "Tracing.h"
|
||||||
#include "UnsupportedLanguage.h"
|
#include "UnsupportedLanguage.h"
|
||||||
#include "ValueLocation.h"
|
|
||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -397,7 +396,7 @@ DwarfImageDebugInfo::CreateFrame(Image* image,
|
|||||||
// create the stack frame debug info
|
// create the stack frame debug info
|
||||||
DIESubprogram* subprogramEntry = function->SubprogramEntry();
|
DIESubprogram* subprogramEntry = function->SubprogramEntry();
|
||||||
DwarfStackFrameDebugInfo* stackFrameDebugInfo
|
DwarfStackFrameDebugInfo* stackFrameDebugInfo
|
||||||
= new(std::nothrow) DwarfStackFrameDebugInfo(fFile, unit,
|
= new(std::nothrow) DwarfStackFrameDebugInfo(fArchitecture, fFile, unit,
|
||||||
subprogramEntry, instructionPointer, framePointer, inputInterface,
|
subprogramEntry, instructionPointer, framePointer, inputInterface,
|
||||||
fromDwarfMap);
|
fromDwarfMap);
|
||||||
if (stackFrameDebugInfo == NULL)
|
if (stackFrameDebugInfo == NULL)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -19,9 +19,11 @@ class DIEAddressingType;
|
|||||||
class DIEArrayType;
|
class DIEArrayType;
|
||||||
class DIEBaseType;
|
class DIEBaseType;
|
||||||
class DIECompoundType;
|
class DIECompoundType;
|
||||||
|
class DIEEnumerationType;
|
||||||
class DIEFormalParameter;
|
class DIEFormalParameter;
|
||||||
class DIEModifiedType;
|
class DIEModifiedType;
|
||||||
class DIESubprogram;
|
class DIESubprogram;
|
||||||
|
class DIESubrangeType;
|
||||||
class DIEType;
|
class DIEType;
|
||||||
class DIETypedef;
|
class DIETypedef;
|
||||||
class DIEVariable;
|
class DIEVariable;
|
||||||
@@ -37,7 +39,8 @@ class Variable;
|
|||||||
|
|
||||||
class DwarfStackFrameDebugInfo : public StackFrameDebugInfo {
|
class DwarfStackFrameDebugInfo : public StackFrameDebugInfo {
|
||||||
public:
|
public:
|
||||||
DwarfStackFrameDebugInfo(DwarfFile* file,
|
DwarfStackFrameDebugInfo(
|
||||||
|
Architecture* architecture, DwarfFile* file,
|
||||||
CompilationUnit* compilationUnit,
|
CompilationUnit* compilationUnit,
|
||||||
DIESubprogram* subprogramEntry,
|
DIESubprogram* subprogramEntry,
|
||||||
target_addr_t instructionPointer,
|
target_addr_t instructionPointer,
|
||||||
@@ -50,7 +53,7 @@ public:
|
|||||||
|
|
||||||
virtual status_t ResolveObjectDataLocation(
|
virtual status_t ResolveObjectDataLocation(
|
||||||
StackFrame* stackFrame, Type* type,
|
StackFrame* stackFrame, Type* type,
|
||||||
target_addr_t objectAddress,
|
const ValueLocation& objectLocation,
|
||||||
ValueLocation*& _location);
|
ValueLocation*& _location);
|
||||||
virtual status_t ResolveBaseTypeLocation(
|
virtual status_t ResolveBaseTypeLocation(
|
||||||
StackFrame* stackFrame, Type* type,
|
StackFrame* stackFrame, Type* type,
|
||||||
@@ -80,11 +83,15 @@ private:
|
|||||||
struct DwarfType;
|
struct DwarfType;
|
||||||
struct DwarfInheritance;
|
struct DwarfInheritance;
|
||||||
struct DwarfDataMember;
|
struct DwarfDataMember;
|
||||||
|
struct DwarfEnumerationValue;
|
||||||
|
struct DwarfArrayDimension;
|
||||||
struct DwarfPrimitiveType;
|
struct DwarfPrimitiveType;
|
||||||
struct DwarfCompoundType;
|
struct DwarfCompoundType;
|
||||||
struct DwarfModifiedType;
|
struct DwarfModifiedType;
|
||||||
struct DwarfTypedefType;
|
struct DwarfTypedefType;
|
||||||
struct DwarfAddressType;
|
struct DwarfAddressType;
|
||||||
|
struct DwarfEnumerationType;
|
||||||
|
struct DwarfSubrangeType;
|
||||||
struct DwarfArrayType;
|
struct DwarfArrayType;
|
||||||
struct DwarfTypeHashDefinition;
|
struct DwarfTypeHashDefinition;
|
||||||
|
|
||||||
@@ -123,6 +130,12 @@ private:
|
|||||||
status_t _CreateArrayType(const BString& name,
|
status_t _CreateArrayType(const BString& name,
|
||||||
DIEArrayType* typeEntry,
|
DIEArrayType* typeEntry,
|
||||||
DwarfType*& _type);
|
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,
|
status_t _CreateVariable(ObjectID* id,
|
||||||
const BString& name, DIEType* typeEntry,
|
const BString& name, DIEType* typeEntry,
|
||||||
@@ -134,8 +147,10 @@ private:
|
|||||||
status_t _ResolveTypeByteSize(DIEType* typeEntry,
|
status_t _ResolveTypeByteSize(DIEType* typeEntry,
|
||||||
uint64& _size);
|
uint64& _size);
|
||||||
|
|
||||||
void _FixLocation(ValueLocation* location,
|
status_t _ResolveLocation(
|
||||||
DwarfType* type);
|
const LocationDescription* description,
|
||||||
|
target_addr_t objectAddress, Type* type,
|
||||||
|
ValueLocation& _location);
|
||||||
|
|
||||||
template<typename EntryType>
|
template<typename EntryType>
|
||||||
static DIEType* _GetDIEType(EntryType* entry);
|
static DIEType* _GetDIEType(EntryType* entry);
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
#include "NoOpStackFrameDebugInfo.h"
|
#include "NoOpStackFrameDebugInfo.h"
|
||||||
|
|
||||||
|
|
||||||
NoOpStackFrameDebugInfo::NoOpStackFrameDebugInfo()
|
NoOpStackFrameDebugInfo::NoOpStackFrameDebugInfo(Architecture* architecture)
|
||||||
|
:
|
||||||
|
StackFrameDebugInfo(architecture)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +21,7 @@ NoOpStackFrameDebugInfo::~NoOpStackFrameDebugInfo()
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
NoOpStackFrameDebugInfo::ResolveObjectDataLocation(StackFrame* stackFrame,
|
NoOpStackFrameDebugInfo::ResolveObjectDataLocation(StackFrame* stackFrame,
|
||||||
Type* type, target_addr_t objectAddress, ValueLocation*& _location)
|
Type* type, const ValueLocation& objectLocation, ValueLocation*& _location)
|
||||||
{
|
{
|
||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,13 @@
|
|||||||
|
|
||||||
class NoOpStackFrameDebugInfo : public StackFrameDebugInfo {
|
class NoOpStackFrameDebugInfo : public StackFrameDebugInfo {
|
||||||
public:
|
public:
|
||||||
NoOpStackFrameDebugInfo();
|
NoOpStackFrameDebugInfo(
|
||||||
|
Architecture* architecture);
|
||||||
virtual ~NoOpStackFrameDebugInfo();
|
virtual ~NoOpStackFrameDebugInfo();
|
||||||
|
|
||||||
virtual status_t ResolveObjectDataLocation(
|
virtual status_t ResolveObjectDataLocation(
|
||||||
StackFrame* stackFrame, Type* type,
|
StackFrame* stackFrame, Type* type,
|
||||||
target_addr_t objectAddress,
|
const ValueLocation& objectLocation,
|
||||||
ValueLocation*& _location);
|
ValueLocation*& _location);
|
||||||
virtual status_t ResolveBaseTypeLocation(
|
virtual status_t ResolveBaseTypeLocation(
|
||||||
StackFrame* stackFrame, Type* type,
|
StackFrame* stackFrame, Type* type,
|
||||||
|
|||||||
@@ -6,12 +6,39 @@
|
|||||||
|
|
||||||
#include "StackFrameDebugInfo.h"
|
#include "StackFrameDebugInfo.h"
|
||||||
|
|
||||||
|
#include "Architecture.h"
|
||||||
|
#include "ValueLocation.h"
|
||||||
|
|
||||||
StackFrameDebugInfo::StackFrameDebugInfo()
|
|
||||||
|
StackFrameDebugInfo::StackFrameDebugInfo(Architecture* architecture)
|
||||||
|
:
|
||||||
|
fArchitecture(architecture)
|
||||||
{
|
{
|
||||||
|
fArchitecture->AcquireReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StackFrameDebugInfo::~StackFrameDebugInfo()
|
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"
|
#include "Types.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Architecture;
|
||||||
class BaseType;
|
class BaseType;
|
||||||
class DataMember;
|
class DataMember;
|
||||||
class StackFrame;
|
class StackFrame;
|
||||||
@@ -20,14 +21,19 @@ class ValueLocation;
|
|||||||
|
|
||||||
class StackFrameDebugInfo : public Referenceable {
|
class StackFrameDebugInfo : public Referenceable {
|
||||||
public:
|
public:
|
||||||
StackFrameDebugInfo();
|
StackFrameDebugInfo(Architecture* architecture);
|
||||||
virtual ~StackFrameDebugInfo();
|
virtual ~StackFrameDebugInfo();
|
||||||
|
|
||||||
virtual status_t ResolveObjectDataLocation(
|
virtual status_t ResolveObjectDataLocation(
|
||||||
StackFrame* stackFrame, Type* type,
|
StackFrame* stackFrame, Type* type,
|
||||||
target_addr_t objectAddress,
|
const ValueLocation& objectLocation,
|
||||||
ValueLocation*& _location) = 0;
|
ValueLocation*& _location) = 0;
|
||||||
// returns a reference
|
// returns a reference
|
||||||
|
status_t ResolveObjectDataLocation(
|
||||||
|
StackFrame* stackFrame, Type* type,
|
||||||
|
target_addr_t objectAddress,
|
||||||
|
ValueLocation*& _location);
|
||||||
|
// returns a reference
|
||||||
virtual status_t ResolveBaseTypeLocation(
|
virtual status_t ResolveBaseTypeLocation(
|
||||||
StackFrame* stackFrame, Type* type,
|
StackFrame* stackFrame, Type* type,
|
||||||
BaseType* baseType,
|
BaseType* baseType,
|
||||||
@@ -40,6 +46,9 @@ public:
|
|||||||
const ValueLocation& parentLocation,
|
const ValueLocation& parentLocation,
|
||||||
ValueLocation*& _location) = 0;
|
ValueLocation*& _location) = 0;
|
||||||
// returns a reference
|
// returns a reference
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Architecture* fArchitecture;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,12 @@
|
|||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
|
|
||||||
|
|
||||||
class VariablesView::ValueNode : Referenceable {
|
enum {
|
||||||
|
VALUE_NODE_TYPE = 'valn'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class VariablesView::ValueNode : public Referenceable {
|
||||||
public:
|
public:
|
||||||
ValueNode(ValueNode* parent, Variable* variable, TypeComponentPath* path,
|
ValueNode(ValueNode* parent, Variable* variable, TypeComponentPath* path,
|
||||||
const BString& name, Type* type)
|
const BString& name, Type* type)
|
||||||
@@ -34,11 +39,13 @@ public:
|
|||||||
fPath(path),
|
fPath(path),
|
||||||
fName(name),
|
fName(name),
|
||||||
fType(type),
|
fType(type),
|
||||||
|
fRawType(type->ResolveRawType()),
|
||||||
fChildrenAdded(false)
|
fChildrenAdded(false)
|
||||||
{
|
{
|
||||||
fVariable->AcquireReference();
|
fVariable->AcquireReference();
|
||||||
fPath->AcquireReference();
|
fPath->AcquireReference();
|
||||||
fType->AcquireReference();
|
fType->AcquireReference();
|
||||||
|
fRawType->AcquireReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
~ValueNode()
|
~ValueNode()
|
||||||
@@ -49,6 +56,7 @@ public:
|
|||||||
fVariable->ReleaseReference();
|
fVariable->ReleaseReference();
|
||||||
fPath->ReleaseReference();
|
fPath->ReleaseReference();
|
||||||
fType->ReleaseReference();
|
fType->ReleaseReference();
|
||||||
|
fRawType->ReleaseReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueNode* Parent() const
|
ValueNode* Parent() const
|
||||||
@@ -76,6 +84,11 @@ public:
|
|||||||
return fType;
|
return fType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type* RawType() const
|
||||||
|
{
|
||||||
|
return fRawType;
|
||||||
|
}
|
||||||
|
|
||||||
const BVariant& Value() const
|
const BVariant& Value() const
|
||||||
{
|
{
|
||||||
return fValue;
|
return fValue;
|
||||||
@@ -129,6 +142,7 @@ private:
|
|||||||
TypeComponentPath* fPath;
|
TypeComponentPath* fPath;
|
||||||
BString fName;
|
BString fName;
|
||||||
Type* fType;
|
Type* fType;
|
||||||
|
Type* fRawType;
|
||||||
BVariant fValue;
|
BVariant fValue;
|
||||||
ChildList fChildren;
|
ChildList fChildren;
|
||||||
bool fChildrenAdded;
|
bool fChildrenAdded;
|
||||||
@@ -150,16 +164,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual BField* PrepareField(const BVariant& value) const
|
virtual BField* PrepareField(const BVariant& _value) const
|
||||||
{
|
{
|
||||||
|
BVariant value = _ResolveValue(_value);
|
||||||
|
|
||||||
char buffer[64];
|
char buffer[64];
|
||||||
return StringTableColumn::PrepareField(
|
return StringTableColumn::PrepareField(
|
||||||
BVariant(_ToString(value, buffer, sizeof(buffer)),
|
BVariant(_ToString(value, buffer, sizeof(buffer)),
|
||||||
B_VARIANT_DONT_COPY_DATA));
|
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
|
// If neither value is a number, compare the strings. If only one value
|
||||||
// is a number, it is considered to be greater.
|
// is a number, it is considered to be greater.
|
||||||
if (!a.IsNumber()) {
|
if (!a.IsNumber()) {
|
||||||
@@ -190,6 +209,26 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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,
|
const char* _ToString(const BVariant& value, char* buffer,
|
||||||
size_t bufferSize) const
|
size_t bufferSize) const
|
||||||
{
|
{
|
||||||
@@ -329,7 +368,7 @@ public:
|
|||||||
if (node->Value().Type() == 0)
|
if (node->Value().Type() == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_value = node->Value();
|
_value.SetTo(node, VALUE_NODE_TYPE);
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -484,6 +523,10 @@ private:
|
|||||||
TRACE_LOCALS("TYPE_ARRAY\n");
|
TRACE_LOCALS("TYPE_ARRAY\n");
|
||||||
// TODO:...
|
// TODO:...
|
||||||
return;
|
return;
|
||||||
|
case TYPE_ENUMERATION:
|
||||||
|
TRACE_LOCALS("TYPE_ENUMERATION\n");
|
||||||
|
done = true;
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
TRACE_LOCALS("unknown\n");
|
TRACE_LOCALS("unknown\n");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -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
|
// #pragma mark - Type
|
||||||
|
|
||||||
|
|
||||||
@@ -31,6 +72,13 @@ Type::~Type()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Type*
|
||||||
|
Type::ResolveRawType() const
|
||||||
|
{
|
||||||
|
return const_cast<Type*>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - PrimitiveType
|
// #pragma mark - PrimitiveType
|
||||||
|
|
||||||
|
|
||||||
@@ -76,6 +124,13 @@ ModifiedType::Kind() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Type*
|
||||||
|
ModifiedType::ResolveRawType() const
|
||||||
|
{
|
||||||
|
return BaseType();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - TypedefType
|
// #pragma mark - TypedefType
|
||||||
|
|
||||||
|
|
||||||
@@ -91,6 +146,13 @@ TypedefType::Kind() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Type*
|
||||||
|
TypedefType::ResolveRawType() const
|
||||||
|
{
|
||||||
|
return BaseType();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - AddressType
|
// #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
|
// #pragma mark - ArrayType
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
#include <Variant.h>
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
@@ -17,6 +18,8 @@ enum type_kind {
|
|||||||
TYPE_MODIFIED,
|
TYPE_MODIFIED,
|
||||||
TYPE_TYPEDEF,
|
TYPE_TYPEDEF,
|
||||||
TYPE_ADDRESS,
|
TYPE_ADDRESS,
|
||||||
|
TYPE_ENUMERATION,
|
||||||
|
TYPE_SUBRANGE,
|
||||||
TYPE_ARRAY
|
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 {
|
class Type : public Referenceable {
|
||||||
public:
|
public:
|
||||||
virtual ~Type();
|
virtual ~Type();
|
||||||
@@ -63,6 +86,8 @@ public:
|
|||||||
virtual const char* Name() const = 0;
|
virtual const char* Name() const = 0;
|
||||||
virtual type_kind Kind() const = 0;
|
virtual type_kind Kind() const = 0;
|
||||||
virtual target_size_t ByteSize() 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 uint32 Modifiers() const = 0;
|
||||||
virtual Type* BaseType() const = 0;
|
virtual Type* BaseType() const = 0;
|
||||||
|
virtual Type* ResolveRawType() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -108,6 +134,7 @@ public:
|
|||||||
virtual type_kind Kind() const;
|
virtual type_kind Kind() const;
|
||||||
|
|
||||||
virtual Type* BaseType() const = 0;
|
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 {
|
class ArrayType : public virtual Type {
|
||||||
public:
|
public:
|
||||||
virtual ~ArrayType();
|
virtual ~ArrayType();
|
||||||
@@ -129,9 +184,9 @@ public:
|
|||||||
virtual type_kind Kind() const;
|
virtual type_kind Kind() const;
|
||||||
|
|
||||||
virtual Type* BaseType() const = 0;
|
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
|
virtual int32 CountDimensions() const = 0;
|
||||||
// are enumeration or subrange types.
|
virtual ArrayDimension* DimensionAt(int32 index) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,12 @@ TypeComponent::Dump() const
|
|||||||
case TYPE_ADDRESS:
|
case TYPE_ADDRESS:
|
||||||
printf("address");
|
printf("address");
|
||||||
break;
|
break;
|
||||||
|
case TYPE_ENUMERATION:
|
||||||
|
printf("enum");
|
||||||
|
break;
|
||||||
|
case TYPE_SUBRANGE:
|
||||||
|
printf("subrange");
|
||||||
|
break;
|
||||||
case TYPE_ARRAY:
|
case TYPE_ARRAY:
|
||||||
printf("array");
|
printf("array");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -7,12 +7,59 @@
|
|||||||
#include "ValueLocation.h"
|
#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()
|
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);
|
AddPiece(piece);
|
||||||
}
|
}
|
||||||
@@ -20,7 +67,8 @@ ValueLocation::ValueLocation(const ValuePieceLocation& piece)
|
|||||||
|
|
||||||
ValueLocation::ValueLocation(const ValueLocation& other)
|
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();
|
Clear();
|
||||||
|
|
||||||
// skip pieces before the offset
|
fBigEndian = other.fBigEndian;
|
||||||
|
|
||||||
|
// compute the total bit size
|
||||||
int32 count = other.CountPieces();
|
int32 count = other.CountPieces();
|
||||||
int32 i;
|
uint64 totalBitSize = 0;
|
||||||
ValuePieceLocation piece;
|
for (int32 i = 0; i < count; i++) {
|
||||||
for (i = 0; i < count; i++) {
|
ValuePieceLocation piece = other.PieceAt(i);
|
||||||
piece = other.PieceAt(i);
|
totalBitSize += piece.bitSize;
|
||||||
if (piece.size * 8 + piece.bitSize > bitOffset)
|
|
||||||
break;
|
|
||||||
bitOffset -= piece.size * 8 + piece.bitSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i >= count)
|
// adjust requested bit offset/size to something reasonable, if necessary
|
||||||
return true;
|
if (bitOffset + bitSize > totalBitSize) {
|
||||||
|
if (bitOffset >= totalBitSize)
|
||||||
|
return true;
|
||||||
|
bitSize = totalBitSize - bitOffset;
|
||||||
|
}
|
||||||
|
|
||||||
// handle partial piece
|
if (fBigEndian) {
|
||||||
if (bitOffset > 0) {
|
// Big endian: Skip the superfluous most significant bits, copy the
|
||||||
uint64 remainingBits = piece.size * 8 + piece.bitSize - bitOffset;
|
// pieces we need (cutting the first and the last one as needed) and
|
||||||
piece.size = remainingBits / 8;
|
// ignore the remaining pieces.
|
||||||
piece.bitSize = remainingBits % 8;
|
|
||||||
|
|
||||||
switch (piece.type) {
|
// skip pieces for the most significant bits we don't need anymore
|
||||||
case VALUE_PIECE_LOCATION_MEMORY:
|
uint64 bitsToSkip = bitOffset;
|
||||||
piece.address += (bitOffset + piece.bitOffset) / 8;
|
int32 i;
|
||||||
piece.bitOffset = (bitOffset + piece.bitOffset) % 8;
|
ValuePieceLocation piece;
|
||||||
break;
|
for (i = 0; i < count; i++) {
|
||||||
case VALUE_PIECE_LOCATION_UNKNOWN:
|
piece = other.PieceAt(i);
|
||||||
piece.bitOffset = 0;
|
if (piece.bitSize > bitsToSkip)
|
||||||
break;
|
|
||||||
case VALUE_PIECE_LOCATION_REGISTER:
|
|
||||||
piece.bitOffset += bitOffset;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
break;
|
||||||
|
bitsToSkip -= piece.bitSize;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// handle remaining pieces
|
// handle partial piece
|
||||||
while (bitSize > 0) {
|
if (bitsToSkip > 0) {
|
||||||
target_addr_t pieceSize = piece.size * 8 + piece.bitSize;
|
piece.bitOffset += bitsToSkip;
|
||||||
if (pieceSize > bitSize) {
|
piece.bitSize -= bitsToSkip;
|
||||||
// the piece is bigger than the remaining size -- cut it
|
piece.Normalize(fBigEndian);
|
||||||
piece.size = bitSize / 8;
|
}
|
||||||
piece.bitSize = bitSize % 8;
|
|
||||||
bitSize = 0;
|
|
||||||
} else
|
|
||||||
bitSize -= pieceSize;
|
|
||||||
|
|
||||||
if (!AddPiece(piece))
|
// handle remaining pieces
|
||||||
return false;
|
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)
|
if (!AddPiece(piece))
|
||||||
break;
|
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;
|
return true;
|
||||||
@@ -101,6 +194,8 @@ ValueLocation::Clear()
|
|||||||
bool
|
bool
|
||||||
ValueLocation::AddPiece(const ValuePieceLocation& piece)
|
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);
|
return fPieces.Add(piece);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,6 +231,7 @@ ValueLocation&
|
|||||||
ValueLocation::operator=(const ValueLocation& other)
|
ValueLocation::operator=(const ValueLocation& other)
|
||||||
{
|
{
|
||||||
fPieces = other.fPieces;
|
fPieces = other.fPieces;
|
||||||
|
fBigEndian = other.fBigEndian;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +240,8 @@ void
|
|||||||
ValueLocation::Dump() const
|
ValueLocation::Dump() const
|
||||||
{
|
{
|
||||||
int32 count = fPieces.Size();
|
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++) {
|
for (int32 i = 0; i < count; i++) {
|
||||||
const ValuePieceLocation& piece = fPieces[i];
|
const ValuePieceLocation& piece = fPieces[i];
|
||||||
@@ -163,7 +260,7 @@ ValueLocation::Dump() const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" size: %llu+%u, offset: %u\n", piece.size, piece.bitSize,
|
printf(" size: %llu (%llu bits), offset: %llu bits\n", piece.size,
|
||||||
piece.bitOffset);
|
piece.bitSize, piece.bitOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,11 @@ struct ValuePieceLocation {
|
|||||||
target_addr_t address; // memory address
|
target_addr_t address; // memory address
|
||||||
uint32 reg; // register number
|
uint32 reg; // register number
|
||||||
};
|
};
|
||||||
target_size_t size; // size in bytes (complete ones)
|
target_size_t size; // size in bytes (including
|
||||||
uint8 bitSize; // totalBitSize = size * 8 + bitSize
|
// incomplete ones)
|
||||||
uint8 bitOffset; // offset in bits
|
uint64 bitSize; // total size in bits
|
||||||
|
uint64 bitOffset; // bit offset (to the most
|
||||||
|
// significant bit)
|
||||||
value_piece_location_type type;
|
value_piece_location_type type;
|
||||||
|
|
||||||
ValuePieceLocation()
|
ValuePieceLocation()
|
||||||
@@ -61,29 +63,36 @@ struct ValuePieceLocation {
|
|||||||
void SetSize(target_size_t size)
|
void SetSize(target_size_t size)
|
||||||
{
|
{
|
||||||
this->size = size;
|
this->size = size;
|
||||||
this->bitSize = 0;
|
this->bitSize = size * 8;
|
||||||
this->bitOffset = 0;
|
this->bitOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSize(uint64 bitSize, uint8 bitOffset)
|
void SetSize(uint64 bitSize, uint64 bitOffset)
|
||||||
{
|
{
|
||||||
this->size = bitSize / 8;
|
this->size = (bitOffset + bitSize + 7) / 8;
|
||||||
this->bitSize = bitSize % 8;
|
this->bitSize = bitSize;
|
||||||
this->bitOffset = bitOffset;
|
this->bitOffset = bitOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValuePieceLocation& Normalize(bool bigEndian);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ValueLocation : public Referenceable {
|
class ValueLocation : public Referenceable {
|
||||||
public:
|
public:
|
||||||
ValueLocation();
|
ValueLocation();
|
||||||
ValueLocation(const ValuePieceLocation& piece);
|
ValueLocation(bool bigEndian);
|
||||||
|
ValueLocation(bool bigEndian,
|
||||||
|
const ValuePieceLocation& piece);
|
||||||
ValueLocation(const ValueLocation& other);
|
ValueLocation(const ValueLocation& other);
|
||||||
|
|
||||||
bool SetTo(const ValueLocation& other,
|
bool SetTo(const ValueLocation& other,
|
||||||
uint64 bitOffset, uint64 bitSize);
|
uint64 bitOffset, uint64 bitSize);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
bool IsBigEndian() const { return fBigEndian; }
|
||||||
|
|
||||||
bool AddPiece(const ValuePieceLocation& piece);
|
bool AddPiece(const ValuePieceLocation& piece);
|
||||||
|
|
||||||
int32 CountPieces() const;
|
int32 CountPieces() const;
|
||||||
@@ -100,6 +109,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
PieceArray fPieces;
|
PieceArray fPieces;
|
||||||
|
bool fBigEndian;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user