The beginnings of a DWARF expression evaluator.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31548 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-07-13 23:54:32 +00:00
parent e355492924
commit ab3c00eef3
3 changed files with 279 additions and 0 deletions
@@ -0,0 +1,238 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "DwarfExpressionEvaluator.h"
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <new>
#include "DataReader.h"
#include "Dwarf.h"
static const size_t kMaxStackCapacityIncrement = 64;
static const size_t kMaxStackCapacity = 1024;
// #pragma mark - EvaluationException
struct DwarfExpressionEvaluator::EvaluationException {
};
// #pragma mark - DwarfExpressionEvaluator
void
DwarfExpressionEvaluator::_AssertMinStackSize(size_t size) const
{
if (fStackSize < size)
throw EvaluationException();
}
void
DwarfExpressionEvaluator::_Push(target_addr_t value)
{
// resize the stack, if we hit the capacity
if (fStackSize == fStackCapacity) {
if (fStackCapacity >= kMaxStackCapacity)
throw EvaluationException();
size_t newCapacity = fStackCapacity + kMaxStackCapacityIncrement;
target_addr_t* newStack = (target_addr_t*)realloc(fStack,
newCapacity * sizeof(target_addr_t));
if (newStack == NULL)
throw std::bad_alloc();
fStack = newStack;
fStackCapacity = newCapacity;
}
fStack[fStackSize++] = value;
}
target_addr_t
DwarfExpressionEvaluator::_Pop()
{
_AssertMinStackSize(1);
return fStack[--fStackSize];
}
DwarfExpressionEvaluator::DwarfExpressionEvaluator(uint8 addressSize)
:
fStack(NULL),
fStackSize(0),
fStackCapacity(0),
fAddressSize(addressSize)
{
}
DwarfExpressionEvaluator::~DwarfExpressionEvaluator()
{
free(fStack);
}
status_t
DwarfExpressionEvaluator::Evaluate(const void* expression, size_t size)
{
fDataReader.SetTo(expression, size, fAddressSize);
try {
return _Evaluate();
} catch (const EvaluationException& exception) {
return B_BAD_VALUE;
} catch (const std::bad_alloc& exception) {
return B_NO_MEMORY;
}
}
status_t
DwarfExpressionEvaluator::_Evaluate()
{
while (fDataReader.BytesRemaining() > 0) {
uint8 opcode = fDataReader.Read<uint8>(0);
switch (opcode) {
case DW_OP_addr:
_Push(fDataReader.ReadAddress(0));
break;
case DW_OP_const1u:
_Push(fDataReader.Read<uint8>(0));
break;
case DW_OP_const1s:
_Push(fDataReader.Read<int8>(0));
break;
case DW_OP_const2u:
_Push(fDataReader.Read<uint16>(0));
break;
case DW_OP_const2s:
_Push(fDataReader.Read<int16>(0));
break;
case DW_OP_const4u:
_Push(fDataReader.Read<uint32>(0));
break;
case DW_OP_const4s:
_Push(fDataReader.Read<int32>(0));
break;
case DW_OP_const8u:
_Push(fDataReader.Read<uint64>(0));
break;
case DW_OP_const8s:
_Push(fDataReader.Read<int64>(0));
break;
case DW_OP_constu:
_Push(fDataReader.ReadUnsignedLEB128(0));
break;
case DW_OP_consts:
_Push(fDataReader.ReadSignedLEB128(0));
break;
case DW_OP_dup:
_AssertMinStackSize(1);
_Push(fStack[fStackSize - 1]);
break;
case DW_OP_drop:
_Pop();
break;
case DW_OP_over:
_AssertMinStackSize(1);
_Push(fStack[fStackSize - 2]);
break;
case DW_OP_pick:
{
uint8 index = fDataReader.Read<uint8>(0);
_AssertMinStackSize(index + 1);
_Push(fStack[fStackSize - index - 1]);
break;
}
case DW_OP_swap:
{
_AssertMinStackSize(2);
std::swap(fStack[fStackSize - 1], fStack[fStackSize - 2]);
break;
}
case DW_OP_rot:
{
_AssertMinStackSize(3);
target_addr_t tmp = fStack[fStackSize - 1];
fStack[fStackSize - 1] = fStack[fStackSize - 2];
fStack[fStackSize - 2] = fStack[fStackSize - 3];
fStack[fStackSize - 3] = tmp;
break;
}
case DW_OP_deref:
// TODO:...
break;
case DW_OP_xderef:
// TODO:...
break;
case DW_OP_abs:
case DW_OP_and:
case DW_OP_div:
case DW_OP_minus:
case DW_OP_mod:
case DW_OP_mul:
case DW_OP_neg:
case DW_OP_not:
case DW_OP_or:
case DW_OP_plus:
case DW_OP_plus_uconst:
case DW_OP_shl:
case DW_OP_shr:
case DW_OP_shra:
case DW_OP_xor:
case DW_OP_skip:
case DW_OP_bra:
case DW_OP_eq:
case DW_OP_ge:
case DW_OP_gt:
case DW_OP_le:
case DW_OP_lt:
case DW_OP_ne:
case DW_OP_regx:
case DW_OP_fbreg:
case DW_OP_bregx:
case DW_OP_piece:
case DW_OP_deref_size:
case DW_OP_xderef_size:
case DW_OP_nop:
case DW_OP_push_object_address:
case DW_OP_call2:
case DW_OP_call4:
case DW_OP_call_ref:
case DW_OP_form_tls_address:
case DW_OP_call_frame_cfa:
case DW_OP_bit_piece:
break;
default:
if (opcode >= DW_OP_lit0 && opcode <= DW_OP_lit31) {
_Push(opcode - DW_OP_lit0);
} else if (opcode >= DW_OP_reg0 && opcode <= DW_OP_reg31) {
// TODO:...
} else if (opcode >= DW_OP_breg0 && opcode <= DW_OP_breg31) {
// TODO:...
} else {
printf("DwarfExpressionEvaluator::_Evaluate(): unsupported "
"opcode: %u\n", opcode);
return B_BAD_DATA;
}
}
}
return fDataReader.HasOverflow() ? B_BAD_DATA : B_OK;
}
@@ -0,0 +1,40 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef DWARF_EXPRESSION_EVALUATOR_H
#define DWARF_EXPRESSION_EVALUATOR_H
#include "DataReader.h"
#include "Types.h"
class DwarfExpressionEvaluator {
public:
DwarfExpressionEvaluator(uint8 addressSize);
~DwarfExpressionEvaluator();
status_t Evaluate(const void* expression, size_t size);
private:
struct EvaluationException;
private:
inline void _AssertMinStackSize(size_t size) const;
inline void _Push(target_addr_t value);
inline target_addr_t _Pop();
status_t _Evaluate();
private:
target_addr_t* fStack;
size_t fStackSize;
size_t fStackCapacity;
DataReader fDataReader;
uint8 fAddressSize;
};
#endif // DWARF_EXPRESSION_EVALUATOR_H
+1
View File
@@ -22,6 +22,7 @@ MergeObject Debugger_dwarf.o
CompilationUnit.cpp
DebugInfoEntries.cpp
DebugInfoEntry.cpp
DwarfExpressionEvaluator.cpp
DwarfFile.cpp
DwarfManager.cpp
DwarfTargetInterface.cpp