* Moved the outer dependencies for the expression evaluation into new class

DwarfExpressionEvaluationContext.
* Implemented the remaining operations save DW_OP_piece and DW_OP_bit_piece.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31590 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-07-15 16:21:33 +00:00
parent 137ded7516
commit dec24704e1
2 changed files with 134 additions and 52 deletions

View File

@ -30,6 +30,23 @@ static const size_t kMaxStackCapacity = 1024;
static const uint32 kMaxOperationCount = 10000; static const uint32 kMaxOperationCount = 10000;
// #pragma mark - DwarfExpressionEvaluationContext
DwarfExpressionEvaluationContext::DwarfExpressionEvaluationContext(
DwarfTargetInterface* targetInterface, uint8 addressSize)
:
fTargetInterface(targetInterface),
fAddressSize(addressSize)
{
}
DwarfExpressionEvaluationContext::~DwarfExpressionEvaluationContext()
{
}
// #pragma mark - EvaluationException // #pragma mark - EvaluationException
@ -79,17 +96,12 @@ DwarfExpressionEvaluator::_Pop()
DwarfExpressionEvaluator::DwarfExpressionEvaluator( DwarfExpressionEvaluator::DwarfExpressionEvaluator(
DwarfTargetInterface* targetInterface, uint8 addressSize) DwarfExpressionEvaluationContext* context)
: :
fTargetInterface(targetInterface), fContext(context),
fStack(NULL), fStack(NULL),
fStackSize(0), fStackSize(0),
fStackCapacity(0), fStackCapacity(0)
fObjectAddress(0),
fFrameAddress(0),
fAddressSize(addressSize),
fObjectAddressValid(false),
fFrameAddressValid(false)
{ {
} }
@ -100,26 +112,10 @@ DwarfExpressionEvaluator::~DwarfExpressionEvaluator()
} }
void
DwarfExpressionEvaluator::SetObjectAddress(target_addr_t address)
{
fObjectAddress = address;
fObjectAddressValid = true;
}
void
DwarfExpressionEvaluator::SetFrameAddress(target_addr_t address)
{
fFrameAddress = address;
fFrameAddressValid = true;
}
status_t status_t
DwarfExpressionEvaluator::Evaluate(const void* expression, size_t size) DwarfExpressionEvaluator::Evaluate(const void* expression, size_t size)
{ {
fDataReader.SetTo(expression, size, fAddressSize); fDataReader.SetTo(expression, size, fContext->AddressSize());
try { try {
return _Evaluate(); return _Evaluate();
@ -208,13 +204,13 @@ DwarfExpressionEvaluator::_Evaluate()
} }
case DW_OP_deref: case DW_OP_deref:
_DereferenceAddress(fAddressSize); _DereferenceAddress(fContext->AddressSize());
break; break;
case DW_OP_deref_size: case DW_OP_deref_size:
_DereferenceAddress(fDataReader.Read<uint8>(0)); _DereferenceAddress(fDataReader.Read<uint8>(0));
break; break;
case DW_OP_xderef: case DW_OP_xderef:
_DereferenceAddressSpaceAddress(fAddressSize); _DereferenceAddressSpaceAddress(fContext->AddressSize());
break; break;
case DW_OP_xderef_size: case DW_OP_xderef_size:
_DereferenceAddressSpaceAddress(fDataReader.Read<uint8>(0)); _DereferenceAddressSpaceAddress(fDataReader.Read<uint8>(0));
@ -223,7 +219,7 @@ DwarfExpressionEvaluator::_Evaluate()
case DW_OP_abs: case DW_OP_abs:
{ {
target_addr_t value = _Pop(); target_addr_t value = _Pop();
if (fAddressSize == 4) { if (fContext->AddressSize() == 4) {
int32 signedValue = (int32)value; int32 signedValue = (int32)value;
_Push(signedValue >= 0 ? signedValue : -signedValue); _Push(signedValue >= 0 ? signedValue : -signedValue);
} else { } else {
@ -262,7 +258,7 @@ DwarfExpressionEvaluator::_Evaluate()
break; break;
case DW_OP_neg: case DW_OP_neg:
{ {
if (fAddressSize == 4) if (fContext->AddressSize() == 4)
_Push(-(int32)_Pop()); _Push(-(int32)_Pop());
else else
_Push(-(int64)_Pop()); _Push(-(int64)_Pop());
@ -351,15 +347,37 @@ DwarfExpressionEvaluator::_Evaluate()
break; break;
case DW_OP_push_object_address: case DW_OP_push_object_address:
if (!fObjectAddressValid) {
target_addr_t address;
if (!fContext->GetObjectAddress(address))
throw EvaluationException(); throw EvaluationException();
_Push(fObjectAddress); _Push(address);
break; break;
}
case DW_OP_call_frame_cfa: case DW_OP_call_frame_cfa:
if (!fFrameAddressValid) {
target_addr_t address;
if (!fContext->GetFrameAddress(address))
throw EvaluationException(); throw EvaluationException();
_Push(fFrameAddress); _Push(address);
break; break;
}
case DW_OP_fbreg:
{
target_addr_t address;
if (!fContext->GetFrameBaseAddress(address))
throw EvaluationException();
_Push(address + fDataReader.ReadSignedLEB128(0));
break;
}
case DW_OP_form_tls_address:
{
target_addr_t address;
if (!fContext->GetTLSAddress(_Pop(), address))
throw EvaluationException();
_Push(address);
break;
}
case DW_OP_regx: case DW_OP_regx:
_PushRegister(fDataReader.ReadUnsignedLEB128(0), 0); _PushRegister(fDataReader.ReadUnsignedLEB128(0), 0);
@ -371,18 +389,17 @@ DwarfExpressionEvaluator::_Evaluate()
break; break;
} }
case DW_OP_form_tls_address:
// TODO:...
break;
case DW_OP_fbreg:
// TODO:...
break;
case DW_OP_call2: case DW_OP_call2:
_Call(fDataReader.Read<uint16>(0), true);
break;
case DW_OP_call4: case DW_OP_call4:
_Call(fDataReader.Read<uint32>(0), true);
break;
case DW_OP_call_ref: case DW_OP_call_ref:
// TODO:... if (fContext->AddressSize() == 4)
_Call(fDataReader.Read<uint32>(0), false);
else
_Call(fDataReader.Read<uint64>(0), false);
break; break;
case DW_OP_piece: case DW_OP_piece:
@ -432,7 +449,7 @@ DwarfExpressionEvaluator::_DereferenceAddress(uint8 addressSize)
valueType = B_UINT32_TYPE; valueType = B_UINT32_TYPE;
break; break;
case 8: case 8:
if (fAddressSize == 8) { if (fContext->AddressSize() == 8) {
valueType = B_UINT64_TYPE; valueType = B_UINT64_TYPE;
break; break;
} }
@ -443,7 +460,8 @@ DwarfExpressionEvaluator::_DereferenceAddress(uint8 addressSize)
target_addr_t address = _Pop(); target_addr_t address = _Pop();
BVariant value; BVariant value;
if (!fTargetInterface->ReadValueFromMemory(address, valueType, value)) { if (!fContext->TargetInterface()->ReadValueFromMemory(address, valueType,
value)) {
throw EvaluationException(); throw EvaluationException();
} }
@ -466,7 +484,7 @@ DwarfExpressionEvaluator::_DereferenceAddressSpaceAddress(uint8 addressSize)
valueType = B_UINT32_TYPE; valueType = B_UINT32_TYPE;
break; break;
case 8: case 8:
if (fAddressSize == 8) { if (fContext->AddressSize() == 8) {
valueType = B_UINT64_TYPE; valueType = B_UINT64_TYPE;
break; break;
} }
@ -478,8 +496,8 @@ DwarfExpressionEvaluator::_DereferenceAddressSpaceAddress(uint8 addressSize)
target_addr_t address = _Pop(); target_addr_t address = _Pop();
target_addr_t addressSpace = _Pop(); target_addr_t addressSpace = _Pop();
BVariant value; BVariant value;
if (!fTargetInterface->ReadValueFromMemory(addressSpace, address, valueType, if (!fContext->TargetInterface()->ReadValueFromMemory(addressSpace, address,
value)) { valueType, value)) {
throw EvaluationException(); throw EvaluationException();
} }
@ -491,8 +509,42 @@ void
DwarfExpressionEvaluator::_PushRegister(uint32 reg, target_addr_t offset) DwarfExpressionEvaluator::_PushRegister(uint32 reg, target_addr_t offset)
{ {
BVariant value; BVariant value;
if (!fTargetInterface->GetRegisterValue(reg, value)) if (!fContext->TargetInterface()->GetRegisterValue(reg, value))
throw EvaluationException(); throw EvaluationException();
_Push(value.ToUInt64()); _Push(value.ToUInt64());
} }
void
DwarfExpressionEvaluator::_Call(uint64 offset, bool local)
{
if (fDataReader.HasOverflow())
throw EvaluationException();
// get the expression to "call"
const void* block;
off_t size;
if (fContext->GetCallTarget(offset, local, block, size) != B_OK)
throw EvaluationException();
// no expression is OK, then this is just a no-op
if (block == NULL)
return;
// save the current data reader state
DataReader savedReader = fDataReader;
// set the reader to the target expression
fDataReader.SetTo(block, size, savedReader.AddressSize());
// and evaluate it
try {
_Evaluate();
} catch (...) {
fDataReader = savedReader;
throw;
}
fDataReader = savedReader;
}

View File

@ -13,11 +13,41 @@
class DwarfTargetInterface; class DwarfTargetInterface;
class DwarfExpressionEvaluationContext {
public:
DwarfExpressionEvaluationContext(
DwarfTargetInterface* targetInterface,
uint8 addressSize);
virtual ~DwarfExpressionEvaluationContext();
DwarfTargetInterface* TargetInterface() const
{ return fTargetInterface; }
uint8 AddressSize() const { return fAddressSize; }
virtual bool GetObjectAddress(target_addr_t& _address) = 0;
virtual bool GetFrameAddress(target_addr_t& _address) = 0;
virtual bool GetFrameBaseAddress(target_addr_t& _address)
= 0;
virtual bool GetTLSAddress(target_addr_t localAddress,
target_addr_t& _address) = 0;
virtual status_t GetCallTarget(uint64 offset, bool local,
const void*& _block, off_t& _size) = 0;
// returns error, when an error resolving
// the entry occurs; returns B_OK and a NULL
// block, when the entry doesn't have a
// location attribute
private:
DwarfTargetInterface* fTargetInterface;
uint8 fAddressSize;
};
class DwarfExpressionEvaluator { class DwarfExpressionEvaluator {
public: public:
DwarfExpressionEvaluator( DwarfExpressionEvaluator(
DwarfTargetInterface* targetInterface, DwarfExpressionEvaluationContext* context);
uint8 addressSize);
~DwarfExpressionEvaluator(); ~DwarfExpressionEvaluator();
void SetObjectAddress(target_addr_t address); void SetObjectAddress(target_addr_t address);
@ -39,16 +69,16 @@ private:
void _DereferenceAddressSpaceAddress( void _DereferenceAddressSpaceAddress(
uint8 addressSize); uint8 addressSize);
void _PushRegister(uint32 reg, target_addr_t offset); void _PushRegister(uint32 reg, target_addr_t offset);
void _Call(uint64 offset, bool local);
private: private:
DwarfTargetInterface* fTargetInterface; DwarfExpressionEvaluationContext* fContext;
target_addr_t* fStack; target_addr_t* fStack;
size_t fStackSize; size_t fStackSize;
size_t fStackCapacity; size_t fStackCapacity;
DataReader fDataReader; DataReader fDataReader;
target_addr_t fObjectAddress; target_addr_t fObjectAddress;
target_addr_t fFrameAddress; target_addr_t fFrameAddress;
uint8 fAddressSize;
bool fObjectAddressValid; bool fObjectAddressValid;
bool fFrameAddressValid; bool fFrameAddressValid;
}; };