1ab3c00eeSIngo Weinhold/*
27483c98dSIngo Weinhold * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3d950dcd9SRene Gollent * Copyright 2013, Rene Gollent, rene@gollent.com.
4ab3c00eeSIngo Weinhold * Distributed under the terms of the MIT License.
5ab3c00eeSIngo Weinhold */
6ab3c00eeSIngo Weinhold
7ab3c00eeSIngo Weinhold
8ab3c00eeSIngo Weinhold#include "DwarfExpressionEvaluator.h"
9ab3c00eeSIngo Weinhold
10ab3c00eeSIngo Weinhold#include <stdio.h>
11ab3c00eeSIngo Weinhold#include <stdlib.h>
12ab3c00eeSIngo Weinhold
13ab3c00eeSIngo Weinhold#include <algorithm>
14ab3c00eeSIngo Weinhold#include <new>
15ab3c00eeSIngo Weinhold
16ca38af4cSIngo Weinhold#include <Variant.h>
17ca38af4cSIngo Weinhold
18ab3c00eeSIngo Weinhold#include "DataReader.h"
19ab3c00eeSIngo Weinhold#include "Dwarf.h"
20ca38af4cSIngo Weinhold#include "DwarfTargetInterface.h"
216e72ebfcSIngo Weinhold#include "Tracing.h"
22d315bfd5SIngo Weinhold#include "ValueLocation.h"
23ca38af4cSIngo Weinhold
24ab3c00eeSIngo Weinhold
25ca38af4cSIngo Weinhold// number of elements to increase the stack capacity when the stack is full
26ca38af4cSIngo Weinholdstatic const size_t kStackCapacityIncrement = 64;
27ab3c00eeSIngo Weinhold
28ca38af4cSIngo Weinhold// maximum number of elements we allow to be pushed on the stack
29ab3c00eeSIngo Weinholdstatic const size_t kMaxStackCapacity			= 1024;
30ab3c00eeSIngo Weinhold
31ca38af4cSIngo Weinhold// maximum number of operations we allow to be performed for a single expression
32ca38af4cSIngo Weinhold// (to avoid running infinite loops forever)
33ca38af4cSIngo Weinholdstatic const uint32 kMaxOperationCount			= 10000;
34ca38af4cSIngo Weinhold
35ab3c00eeSIngo Weinhold
36dec24704SIngo Weinhold// #pragma mark - DwarfExpressionEvaluationContext
37dec24704SIngo Weinhold
38dec24704SIngo Weinhold
39dec24704SIngo WeinholdDwarfExpressionEvaluationContext::DwarfExpressionEvaluationContext(
401a5bb78dSRene Gollent	const DwarfTargetInterface* targetInterface, uint8 addressSize,
411a5bb78dSRene Gollent	target_addr_t relocationDelta)
42dec24704SIngo Weinhold	:
43dec24704SIngo Weinhold	fTargetInterface(targetInterface),
441a5bb78dSRene Gollent	fAddressSize(addressSize),
451a5bb78dSRene Gollent	fRelocationDelta(relocationDelta)
46dec24704SIngo Weinhold{
47dec24704SIngo Weinhold}
48dec24704SIngo Weinhold
49dec24704SIngo Weinhold
50dec24704SIngo WeinholdDwarfExpressionEvaluationContext::~DwarfExpressionEvaluationContext()
51dec24704SIngo Weinhold{
52dec24704SIngo Weinhold}
53dec24704SIngo Weinhold
54dec24704SIngo Weinhold
55ab3c00eeSIngo Weinhold// #pragma mark - EvaluationException
56ab3c00eeSIngo Weinhold
57ab3c00eeSIngo Weinhold
58ab3c00eeSIngo Weinholdstruct DwarfExpressionEvaluator::EvaluationException {
59d315bfd5SIngo Weinhold	const char* message;
60d315bfd5SIngo Weinhold
61d315bfd5SIngo Weinhold	EvaluationException(const char* message)
62d315bfd5SIngo Weinhold		:
63d315bfd5SIngo Weinhold		message(message)
64d315bfd5SIngo Weinhold	{
65d315bfd5SIngo Weinhold	}
66ab3c00eeSIngo Weinhold};
67ab3c00eeSIngo Weinhold
68ab3c00eeSIngo Weinhold
69ab3c00eeSIngo Weinhold// #pragma mark - DwarfExpressionEvaluator
70ab3c00eeSIngo Weinhold
71ab3c00eeSIngo Weinhold
72ab3c00eeSIngo Weinholdvoid
73ab3c00eeSIngo WeinholdDwarfExpressionEvaluator::_AssertMinStackSize(size_t size) const
74ab3c00eeSIngo Weinhold{
75ab3c00eeSIngo Weinhold	if (fStackSize < size)
76d315bfd5SIngo Weinhold		throw EvaluationException("pop from empty stack");
77ab3c00eeSIngo Weinhold}
78ab3c00eeSIngo Weinhold
79ab3c00eeSIngo Weinhold
80ab3c00eeSIngo Weinholdvoid
81ab3c00eeSIngo WeinholdDwarfExpressionEvaluator::_Push(target_addr_t value)
82ab3c00eeSIngo Weinhold{
83ab3c00eeSIngo Weinhold	// resize the stack, if we hit the capacity
84ab3c00eeSIngo Weinhold	if (fStackSize == fStackCapacity) {
85ab3c00eeSIngo Weinhold		if (fStackCapacity >= kMaxStackCapacity)
86d315bfd5SIngo Weinhold			throw EvaluationException("stack overflow");
87ab3c00eeSIngo Weinhold
88ca38af4cSIngo Weinhold		size_t newCapacity = fStackCapacity + kStackCapacityIncrement;
89ab3c00eeSIngo Weinhold		target_addr_t* newStack = (target_addr_t*)realloc(fStack,
90ab3c00eeSIngo Weinhold			newCapacity * sizeof(target_addr_t));
91ab3c00eeSIngo Weinhold		if (newStack == NULL)
92ab3c00eeSIngo Weinhold			throw std::bad_alloc();
93ab3c00eeSIngo Weinhold
94ab3c00eeSIngo Weinhold		fStack = newStack;
95ab3c00eeSIngo Weinhold		fStackCapacity = newCapacity;
96ab3c00eeSIngo Weinhold	}
97ab3c00eeSIngo Weinhold
98ab3c00eeSIngo Weinhold	fStack[fStackSize++] = value;
99ab3c00eeSIngo Weinhold}
100ab3c00eeSIngo Weinhold
101ab3c00eeSIngo Weinhold
102ab3c00eeSIngo Weinholdtarget_addr_t
103ab3c00eeSIngo WeinholdDwarfExpressionEvaluator::_Pop()
104ab3c00eeSIngo Weinhold{
105ab3c00eeSIngo Weinhold	_AssertMinStackSize(1);
106ab3c00eeSIngo Weinhold	return fStack[--fStackSize];
107ab3c00eeSIngo Weinhold}
108ab3c00eeSIngo Weinhold
109ab3c00eeSIngo Weinhold
110ca38af4cSIngo WeinholdDwarfExpressionEvaluator::DwarfExpressionEvaluator(
111dec24704SIngo Weinhold	DwarfExpressionEvaluationContext* context)
112ab3c00eeSIngo Weinhold	:
113dec24704SIngo Weinhold	fContext(context),
114ab3c00eeSIngo Weinhold	fStack(NULL),
115ab3c00eeSIngo Weinhold	fStackSize(0),
116dec24704SIngo Weinhold	fStackCapacity(0)
117ab3c00eeSIngo Weinhold{
118ab3c00eeSIngo Weinhold}
119ab3c00eeSIngo Weinhold
120ab3c00eeSIngo Weinhold
121ab3c00eeSIngo WeinholdDwarfExpressionEvaluator::~DwarfExpressionEvaluator()
122ab3c00eeSIngo Weinhold{
123ab3c00eeSIngo Weinhold	free(fStack);
124ab3c00eeSIngo Weinhold}
125ab3c00eeSIngo Weinhold
126ab3c00eeSIngo Weinhold
127ab3c00eeSIngo Weinholdstatus_t
128d315bfd5SIngo WeinholdDwarfExpressionEvaluator::Push(target_addr_t value)
129d315bfd5SIngo Weinhold{
130d315bfd5SIngo Weinhold	try {
131d315bfd5SIngo Weinhold		_Push(value);
132d315bfd5SIngo Weinhold		return B_OK;
133d315bfd5SIngo Weinhold	} catch (const EvaluationException& exception) {
134d315bfd5SIngo Weinhold		return B_BAD_VALUE;
135d315bfd5SIngo Weinhold	} catch (const std::bad_alloc& exception) {
136d315bfd5SIngo Weinhold		return B_NO_MEMORY;
137d315bfd5SIngo Weinhold	}
138d315bfd5SIngo Weinhold}
139d315bfd5SIngo Weinhold
140d315bfd5SIngo Weinhold
141d315bfd5SIngo Weinholdstatus_t
142d315bfd5SIngo WeinholdDwarfExpressionEvaluator::Evaluate(const void* expression, size_t size,
143d315bfd5SIngo Weinhold	target_addr_t& _result)
144ab3c00eeSIngo Weinhold{
145dec24704SIngo Weinhold	fDataReader.SetTo(expression, size, fContext->AddressSize());
146ab3c00eeSIngo Weinhold
147ab3c00eeSIngo Weinhold	try {
148d315bfd5SIngo Weinhold		status_t error = _Evaluate(NULL);
149d315bfd5SIngo Weinhold		if (error != B_OK)
150d315bfd5SIngo Weinhold			return error;
151d315bfd5SIngo Weinhold		_result = _Pop();
152d315bfd5SIngo Weinhold		return B_OK;
153ab3c00eeSIngo Weinhold	} catch (const EvaluationException& exception) {
1546e72ebfcSIngo Weinhold		WARNING("DwarfExpressionEvaluator::Evaluate(): %s\n",
1556e72ebfcSIngo Weinhold			exception.message);
156ab3c00eeSIngo Weinhold		return B_BAD_VALUE;
157ab3c00eeSIngo Weinhold	} catch (const std::bad_alloc& exception) {
158ab3c00eeSIngo Weinhold		return B_NO_MEMORY;
159ab3c00eeSIngo Weinhold	}
160ab3c00eeSIngo Weinhold}
161ab3c00eeSIngo Weinhold
162ab3c00eeSIngo Weinhold
163ab3c00eeSIngo Weinholdstatus_t
164d315bfd5SIngo WeinholdDwarfExpressionEvaluator::EvaluateLocation(const void* expression, size_t size,
1651a5bb78dSRene Gollent	ValueLocation& _location)
1661a5bb78dSRene Gollent{
167d315bfd5SIngo Weinhold	_location.Clear();
168d315bfd5SIngo Weinhold
169d315bfd5SIngo Weinhold	// the empty expression is a valid one
170d315bfd5SIngo Weinhold	if (size == 0) {
171d315bfd5SIngo Weinhold		ValuePieceLocation piece;
172d315bfd5SIngo Weinhold		piece.SetToUnknown();
173d315bfd5SIngo Weinhold		piece.SetSize(0);
174d315bfd5SIngo Weinhold		return _location.AddPiece(piece) ? B_OK : B_NO_MEMORY;
175d315bfd5SIngo Weinhold	}
176d315bfd5SIngo Weinhold
177d315bfd5SIngo Weinhold	fDataReader.SetTo(expression, size, fContext->AddressSize());
178d315bfd5SIngo Weinhold
179d315bfd5SIngo Weinhold	// parse the first (and maybe only) expression
180d315bfd5SIngo Weinhold	try {
1816e72ebfcSIngo Weinhold		// push the object address, if any
1826e72ebfcSIngo Weinhold		target_addr_t objectAddress;
1836e72ebfcSIngo Weinhold		if (fContext->GetObjectAddress(objectAddress))
1846e72ebfcSIngo Weinhold			_Push(objectAddress);
1856e72ebfcSIngo Weinhold
186d315bfd5SIngo Weinhold		ValuePieceLocation piece;
1871a5bb78dSRene Gollent		status_t error = _Evaluate(&piece);
188d315bfd5SIngo Weinhold		if (error != B_OK)
189d315bfd5SIngo Weinhold			return error;
190d315bfd5SIngo Weinhold
191d315bfd5SIngo Weinhold		// if that's all, it's only a simple expression without composition
192d315bfd5SIngo Weinhold		if (fDataReader.BytesRemaining() == 0) {
193d315bfd5SIngo Weinhold			if (!piece.IsValid())
194d315bfd5SIngo Weinhold				piece.SetToMemory(_Pop());
195d315bfd5SIngo Weinhold			piece.SetSize(0);
196d315bfd5SIngo Weinhold			return _location.AddPiece(piece) ? B_OK : B_NO_MEMORY;
197d315bfd5SIngo Weinhold		}
198d315bfd5SIngo Weinhold
199d315bfd5SIngo Weinhold		// there's more, so it must be a composition operator
200d315bfd5SIngo Weinhold		uint8 opcode = fDataReader.Read<uint8>(0);
201d315bfd5SIngo Weinhold		if (opcode == DW_OP_piece) {
202d315bfd5SIngo Weinhold			piece.SetSize(fDataReader.ReadUnsignedLEB128(0));
203d315bfd5SIngo Weinhold		} else if (opcode == DW_OP_bit_piece) {
204d315bfd5SIngo Weinhold			uint64 bitSize = fDataReader.ReadUnsignedLEB128(0);
205d315bfd5SIngo Weinhold			piece.SetSize(bitSize, fDataReader.ReadUnsignedLEB128(0));
206d315bfd5SIngo Weinhold		} else
207d315bfd5SIngo Weinhold			return B_BAD_DATA;
208d315bfd5SIngo Weinhold
209d315bfd5SIngo Weinhold		// If there's a composition operator, there must be at least two
210d315bfd5SIngo Weinhold		// simple expressions, so this must not be the end.
211d315bfd5SIngo Weinhold		if (fDataReader.BytesRemaining() == 0)
212d315bfd5SIngo Weinhold			return B_BAD_DATA;
213d315bfd5SIngo Weinhold	} catch (const EvaluationException& exception) {
2146e72ebfcSIngo Weinhold		WARNING("DwarfExpressionEvaluator::EvaluateLocation(): %s\n",
2156e72ebfcSIngo Weinhold			exception.message);
216d315bfd5SIngo Weinhold		return B_BAD_VALUE;
217d315bfd5SIngo Weinhold	} catch (const std::bad_alloc& exception) {
218d315bfd5SIngo Weinhold		return B_NO_MEMORY;
219d315bfd5SIngo Weinhold	}
220d315bfd5SIngo Weinhold
221d315bfd5SIngo Weinhold	// parse subsequent expressions (at least one)
222d315bfd5SIngo Weinhold	while (fDataReader.BytesRemaining() > 0) {
223d315bfd5SIngo Weinhold		// Restrict the data reader to the remaining bytes to prevent jumping
224d315bfd5SIngo Weinhold		// back.
225d315bfd5SIngo Weinhold		fDataReader.SetTo(fDataReader.Data(), fDataReader.BytesRemaining(),
226d315bfd5SIngo Weinhold			fDataReader.AddressSize());
227d315bfd5SIngo Weinhold
228d315bfd5SIngo Weinhold		try {
2296e72ebfcSIngo Weinhold			// push the object address, if any
2306e72ebfcSIngo Weinhold			target_addr_t objectAddress;
2316e72ebfcSIngo Weinhold			if (fContext->GetObjectAddress(objectAddress))
2326e72ebfcSIngo Weinhold				_Push(objectAddress);
2336e72ebfcSIngo Weinhold
234d315bfd5SIngo Weinhold			ValuePieceLocation piece;
2351a5bb78dSRene Gollent			status_t error = _Evaluate(&piece);
236d315bfd5SIngo Weinhold			if (error != B_OK)
237d315bfd5SIngo Weinhold				return error;
238d315bfd5SIngo Weinhold
239d315bfd5SIngo Weinhold			if (!piece.IsValid())
240d315bfd5SIngo Weinhold				piece.SetToMemory(_Pop());
241d315bfd5SIngo Weinhold
242d315bfd5SIngo Weinhold			// each expression must be followed by a composition operator
243d315bfd5SIngo Weinhold			if (fDataReader.BytesRemaining() == 0)
244d315bfd5SIngo Weinhold				return B_BAD_DATA;
245d315bfd5SIngo Weinhold
246d315bfd5SIngo Weinhold			uint8 opcode = fDataReader.Read<uint8>(0);
247d315bfd5SIngo Weinhold			if (opcode == DW_OP_piece) {
248d315bfd5SIngo Weinhold				piece.SetSize(fDataReader.ReadUnsignedLEB128(0));
249d315bfd5SIngo Weinhold			} else if (opcode == DW_OP_bit_piece) {
250d315bfd5SIngo Weinhold				uint64 bitSize = fDataReader.ReadUnsignedLEB128(0);
251d315bfd5SIngo Weinhold				piece.SetSize(bitSize, fDataReader.ReadUnsignedLEB128(0));
252d315bfd5SIngo Weinhold			} else
253d315bfd5SIngo Weinhold				return B_BAD_DATA;
254d315bfd5SIngo Weinhold		} catch (const EvaluationException& exception) {
2556e72ebfcSIngo Weinhold			WARNING("DwarfExpressionEvaluator::EvaluateLocation(): %s\n",
2566e72ebfcSIngo Weinhold				exception.message);
257d315bfd5SIngo Weinhold			return B_BAD_VALUE;
258d315bfd5SIngo Weinhold		} catch (const std::bad_alloc& exception) {
259d315bfd5SIngo Weinhold			return B_NO_MEMORY;
260d315bfd5SIngo Weinhold		}
261d315bfd5SIngo Weinhold	}
262d315bfd5SIngo Weinhold
263d315bfd5SIngo Weinhold	return B_OK;
264d315bfd5SIngo Weinhold}
265d315bfd5SIngo Weinhold
266d315bfd5SIngo Weinhold
267d315bfd5SIngo Weinholdstatus_t
2681a5bb78dSRene GollentDwarfExpressionEvaluator::_Evaluate(ValuePieceLocation* _piece)
269d315bfd5SIngo Weinhold{
2706e72ebfcSIngo Weinhold	TRACE_EXPR_ONLY({
2717483c98dSIngo Weinhold		TRACE_EXPR("DwarfExpressionEvaluator::_Evaluate(%p, %" B_PRIdOFF ")\n",
2726e72ebfcSIngo Weinhold			fDataReader.Data(), fDataReader.BytesRemaining());
2736e72ebfcSIngo Weinhold		const uint8* data = (const uint8*)fDataReader.Data();
2746e72ebfcSIngo Weinhold		int32 count = fDataReader.BytesRemaining();
2756e72ebfcSIngo Weinhold		for (int32 i = 0; i < count; i++)
2766e72ebfcSIngo Weinhold			TRACE_EXPR(" %02x", data[i]);
2776e72ebfcSIngo Weinhold		TRACE_EXPR("\n");
2786e72ebfcSIngo Weinhold	})
2796e72ebfcSIngo Weinhold
280ca38af4cSIngo Weinhold	uint32 operationsExecuted = 0;
281ca38af4cSIngo Weinhold
282ab3c00eeSIngo Weinhold	while (fDataReader.BytesRemaining() > 0) {
283ab3c00eeSIngo Weinhold		uint8 opcode = fDataReader.Read<uint8>(0);
284ab3c00eeSIngo Weinhold
285ab3c00eeSIngo Weinhold		switch (opcode) {
286ab3c00eeSIngo Weinhold			case DW_OP_addr:
2876e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_addr\n");
2881a5bb78dSRene Gollent				_Push(fDataReader.ReadAddress(0) + fContext->RelocationDelta());
289ab3c00eeSIngo Weinhold				break;
290ab3c00eeSIngo Weinhold			case DW_OP_const1u:
2916e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_const1u\n");
292ab3c00eeSIngo Weinhold				_Push(fDataReader.Read<uint8>(0));
293ab3c00eeSIngo Weinhold				break;
294ab3c00eeSIngo Weinhold			case DW_OP_const1s:
2956e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_const1s\n");
296ab3c00eeSIngo Weinhold				_Push(fDataReader.Read<int8>(0));
297ab3c00eeSIngo Weinhold				break;
298ab3c00eeSIngo Weinhold			case DW_OP_const2u:
2996e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_const2u\n");
300ab3c00eeSIngo Weinhold				_Push(fDataReader.Read<uint16>(0));
301ab3c00eeSIngo Weinhold				break;
302ab3c00eeSIngo Weinhold			case DW_OP_const2s:
3036e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_const2s\n");
304ab3c00eeSIngo Weinhold				_Push(fDataReader.Read<int16>(0));
305ab3c00eeSIngo Weinhold				break;
306ab3c00eeSIngo Weinhold			case DW_OP_const4u:
3076e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_const4u\n");
308ab3c00eeSIngo Weinhold				_Push(fDataReader.Read<uint32>(0));
309ab3c00eeSIngo Weinhold				break;
310ab3c00eeSIngo Weinhold			case DW_OP_const4s:
3116e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_const4s\n");
312ab3c00eeSIngo Weinhold				_Push(fDataReader.Read<int32>(0));
313ab3c00eeSIngo Weinhold				break;
314ab3c00eeSIngo Weinhold			case DW_OP_const8u:
3156e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_const8u\n");
316ab3c00eeSIngo Weinhold				_Push(fDataReader.Read<uint64>(0));
317ab3c00eeSIngo Weinhold				break;
318ab3c00eeSIngo Weinhold			case DW_OP_const8s:
3196e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_const8s\n");
320ab3c00eeSIngo Weinhold				_Push(fDataReader.Read<int64>(0));
321ab3c00eeSIngo Weinhold				break;
322ab3c00eeSIngo Weinhold			case DW_OP_constu:
3236e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_constu\n");
324ab3c00eeSIngo Weinhold				_Push(fDataReader.ReadUnsignedLEB128(0));
325ab3c00eeSIngo Weinhold				break;
326ab3c00eeSIngo Weinhold			case DW_OP_consts:
3276e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_consts\n");
328ab3c00eeSIngo Weinhold				_Push(fDataReader.ReadSignedLEB128(0));
329ab3c00eeSIngo Weinhold				break;
330ab3c00eeSIngo Weinhold			case DW_OP_dup:
3316e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_dup\n");
332ab3c00eeSIngo Weinhold				_AssertMinStackSize(1);
333ab3c00eeSIngo Weinhold				_Push(fStack[fStackSize - 1]);
334ab3c00eeSIngo Weinhold				break;
335ab3c00eeSIngo Weinhold			case DW_OP_drop:
3366e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_drop\n");
337ab3c00eeSIngo Weinhold				_Pop();
338ab3c00eeSIngo Weinhold				break;
339ab3c00eeSIngo Weinhold			case DW_OP_over:
3406e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_over\n");
341ab3c00eeSIngo Weinhold				_AssertMinStackSize(1);
342ab3c00eeSIngo Weinhold				_Push(fStack[fStackSize - 2]);
343ab3c00eeSIngo Weinhold				break;
344ab3c00eeSIngo Weinhold			case DW_OP_pick:
345ab3c00eeSIngo Weinhold			{
3466e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_pick\n");
347ab3c00eeSIngo Weinhold				uint8 index = fDataReader.Read<uint8>(0);
348ab3c00eeSIngo Weinhold				_AssertMinStackSize(index + 1);
349ab3c00eeSIngo Weinhold				_Push(fStack[fStackSize - index - 1]);
350ab3c00eeSIngo Weinhold				break;
351ab3c00eeSIngo Weinhold			}
352ab3c00eeSIngo Weinhold			case DW_OP_swap:
353ab3c00eeSIngo Weinhold			{
3546e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_swap\n");
355ab3c00eeSIngo Weinhold				_AssertMinStackSize(2);
356ab3c00eeSIngo Weinhold				std::swap(fStack[fStackSize - 1], fStack[fStackSize - 2]);
357ab3c00eeSIngo Weinhold				break;
358ab3c00eeSIngo Weinhold			}
359ab3c00eeSIngo Weinhold			case DW_OP_rot:
360ab3c00eeSIngo Weinhold			{
3616e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_rot\n");
362ab3c00eeSIngo Weinhold				_AssertMinStackSize(3);
363ab3c00eeSIngo Weinhold				target_addr_t tmp = fStack[fStackSize - 1];
364ab3c00eeSIngo Weinhold				fStack[fStackSize - 1] = fStack[fStackSize - 2];
365ab3c00eeSIngo Weinhold				fStack[fStackSize - 2] = fStack[fStackSize - 3];
366ab3c00eeSIngo Weinhold				fStack[fStackSize - 3] = tmp;
367ab3c00eeSIngo Weinhold				break;
368ab3c00eeSIngo Weinhold			}
369ca38af4cSIngo Weinhold
370ab3c00eeSIngo Weinhold			case DW_OP_deref:
3716e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_deref\n");
372dec24704SIngo Weinhold				_DereferenceAddress(fContext->AddressSize());
373ca38af4cSIngo Weinhold				break;
374ca38af4cSIngo Weinhold			case DW_OP_deref_size:
3756e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_deref_size\n");
376ca38af4cSIngo Weinhold				_DereferenceAddress(fDataReader.Read<uint8>(0));
377ab3c00eeSIngo Weinhold				break;
378ab3c00eeSIngo Weinhold			case DW_OP_xderef:
3796e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_xderef\n");
380dec24704SIngo Weinhold				_DereferenceAddressSpaceAddress(fContext->AddressSize());
381ab3c00eeSIngo Weinhold				break;
382ca38af4cSIngo Weinhold			case DW_OP_xderef_size:
3836e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_xderef_size\n");
384ca38af4cSIngo Weinhold				_DereferenceAddressSpaceAddress(fDataReader.Read<uint8>(0));
385ca38af4cSIngo Weinhold				break;
386ca38af4cSIngo Weinhold
387ab3c00eeSIngo Weinhold			case DW_OP_abs:
388ca38af4cSIngo Weinhold			{
3896e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_abs\n");
390ca38af4cSIngo Weinhold				target_addr_t value = _Pop();
391dec24704SIngo Weinhold				if (fContext->AddressSize() == 4) {
392ca38af4cSIngo Weinhold					int32 signedValue = (int32)value;
393ca38af4cSIngo Weinhold					_Push(signedValue >= 0 ? signedValue : -signedValue);
394ca38af4cSIngo Weinhold				} else {
395ca38af4cSIngo Weinhold					int64 signedValue = (int64)value;
396ca38af4cSIngo Weinhold					_Push(signedValue >= 0 ? signedValue : -signedValue);
397ca38af4cSIngo Weinhold				}
398ca38af4cSIngo Weinhold				break;
399ca38af4cSIngo Weinhold			}
400ab3c00eeSIngo Weinhold			case DW_OP_and:
4016e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_and\n");
402ca38af4cSIngo Weinhold				_Push(_Pop() & _Pop());
403ca38af4cSIngo Weinhold				break;
404ab3c00eeSIngo Weinhold			case DW_OP_div:
405ca38af4cSIngo Weinhold			{
4066e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_div\n");
407ca38af4cSIngo Weinhold				int64 top = (int64)_Pop();
408ca38af4cSIngo Weinhold				int64 second = (int64)_Pop();
409ca38af4cSIngo Weinhold				_Push(top != 0 ? second / top : 0);
410ca38af4cSIngo Weinhold				break;
411ca38af4cSIngo Weinhold			}
412ab3c00eeSIngo Weinhold			case DW_OP_minus:
413ca38af4cSIngo Weinhold			{
4146e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_minus\n");
415ca38af4cSIngo Weinhold				target_addr_t top = _Pop();
416ca38af4cSIngo Weinhold				_Push(_Pop() - top);
417ca38af4cSIngo Weinhold				break;
418ca38af4cSIngo Weinhold			}
419ab3c00eeSIngo Weinhold			case DW_OP_mod:
420ca38af4cSIngo Weinhold			{
4216e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_mod\n");
422ca38af4cSIngo Weinhold				// While the specs explicitly speak of signed integer division
423ca38af4cSIngo Weinhold				// for "div", nothing is mentioned for "mod".
424ca38af4cSIngo Weinhold				target_addr_t top = _Pop();
425ca38af4cSIngo Weinhold				target_addr_t second = _Pop();
426ca38af4cSIngo Weinhold				_Push(top != 0 ? second % top : 0);
427ca38af4cSIngo Weinhold				break;
428ca38af4cSIngo Weinhold			}
429ab3c00eeSIngo Weinhold			case DW_OP_mul:
4306e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_mul\n");
431ca38af4cSIngo Weinhold				_Push(_Pop() * _Pop());
432ca38af4cSIngo Weinhold				break;
433ab3c00eeSIngo Weinhold			case DW_OP_neg:
434ca38af4cSIngo Weinhold			{
4356e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_neg\n");
436dec24704SIngo Weinhold				if (fContext->AddressSize() == 4)
437ca38af4cSIngo Weinhold					_Push(-(int32)_Pop());
438ca38af4cSIngo Weinhold				else
439ca38af4cSIngo Weinhold					_Push(-(int64)_Pop());
440ca38af4cSIngo Weinhold				break;
441ca38af4cSIngo Weinhold			}
442ab3c00eeSIngo Weinhold			case DW_OP_not:
4436e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_not\n");
444ca38af4cSIngo Weinhold				_Push(~_Pop());
445ca38af4cSIngo Weinhold				break;
446ab3c00eeSIngo Weinhold			case DW_OP_or:
4476e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_or\n");
448ca38af4cSIngo Weinhold				_Push(_Pop() | _Pop());
449ca38af4cSIngo Weinhold				break;
450ab3c00eeSIngo Weinhold			case DW_OP_plus:
4516e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_plus\n");
452ca38af4cSIngo Weinhold				_Push(_Pop() + _Pop());
453ca38af4cSIngo Weinhold				break;
454ab3c00eeSIngo Weinhold			case DW_OP_plus_uconst:
4556e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_plus_uconst\n");
456ca38af4cSIngo Weinhold				_Push(_Pop() + fDataReader.ReadUnsignedLEB128(0));
457ca38af4cSIngo Weinhold				break;
458ab3c00eeSIngo Weinhold			case DW_OP_shl:
459ca38af4cSIngo Weinhold			{
4606e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_shl\n");
461ca38af4cSIngo Weinhold				target_addr_t top = _Pop();
462ca38af4cSIngo Weinhold				_Push(_Pop() << top);
463ca38af4cSIngo Weinhold				break;
464ca38af4cSIngo Weinhold			}
465ab3c00eeSIngo Weinhold			case DW_OP_shr:
466ca38af4cSIngo Weinhold			{
4676e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_shr\n");
468ca38af4cSIngo Weinhold				target_addr_t top = _Pop();
469ca38af4cSIngo Weinhold				_Push(_Pop() >> top);
470ca38af4cSIngo Weinhold				break;
471ca38af4cSIngo Weinhold			}
472ab3c00eeSIngo Weinhold			case DW_OP_shra:
473ca38af4cSIngo Weinhold			{
4746e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_shra\n");
475ca38af4cSIngo Weinhold				target_addr_t top = _Pop();
476ca38af4cSIngo Weinhold				int64 second = (int64)_Pop();
477ca38af4cSIngo Weinhold				_Push(second >= 0 ? second >> top : -(-second >> top));
478ca38af4cSIngo Weinhold					// right shift on negative values is implementation defined
479ca38af4cSIngo Weinhold				break;
480ca38af4cSIngo Weinhold			}
481ab3c00eeSIngo Weinhold			case DW_OP_xor:
4826e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_xor\n");
483ca38af4cSIngo Weinhold				_Push(_Pop() ^ _Pop());
484ca38af4cSIngo Weinhold				break;
485ca38af4cSIngo Weinhold
486ab3c00eeSIngo Weinhold			case DW_OP_bra:
4876e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_bra\n");
488ca38af4cSIngo Weinhold				if (_Pop() == 0)
489ca38af4cSIngo Weinhold					break;
490ca38af4cSIngo Weinhold				// fall through
491ca38af4cSIngo Weinhold			case DW_OP_skip:
492ca38af4cSIngo Weinhold			{
4936e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_skip\n");
494ca38af4cSIngo Weinhold				int16 offset = fDataReader.Read<int16>(0);
495ca38af4cSIngo Weinhold				if (offset >= 0 ? offset > fDataReader.BytesRemaining()
496ca38af4cSIngo Weinhold						: -offset > fDataReader.Offset()) {
497d315bfd5SIngo Weinhold					throw EvaluationException("bra/skip: invalid offset");
498ca38af4cSIngo Weinhold				}
499ca38af4cSIngo Weinhold				fDataReader.SeekAbsolute(fDataReader.Offset() + offset);
500ca38af4cSIngo Weinhold				break;
501ca38af4cSIngo Weinhold			}
502ab3c00eeSIngo Weinhold
503ab3c00eeSIngo Weinhold			case DW_OP_eq:
5046e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_eq\n");
505ca38af4cSIngo Weinhold				_Push(_Pop() == _Pop() ? 1 : 0);
506ca38af4cSIngo Weinhold				break;
507ab3c00eeSIngo Weinhold			case DW_OP_ge:
508ca38af4cSIngo Weinhold			{
5096e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_ge\n");
510ca38af4cSIngo Weinhold				int64 top = (int64)_Pop();
511ca38af4cSIngo Weinhold				_Push((int64)_Pop() >= top ? 1 : 0);
512ca38af4cSIngo Weinhold				break;
513ca38af4cSIngo Weinhold			}
514ab3c00eeSIngo Weinhold			case DW_OP_gt:
515ca38af4cSIngo Weinhold			{
5166e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_gt\n");
517ca38af4cSIngo Weinhold				int64 top = (int64)_Pop();
518ca38af4cSIngo Weinhold				_Push((int64)_Pop() > top ? 1 : 0);
519ca38af4cSIngo Weinhold				break;
520ca38af4cSIngo Weinhold			}
521ab3c00eeSIngo Weinhold			case DW_OP_le:
522ca38af4cSIngo Weinhold			{
5236e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_le\n");
524ca38af4cSIngo Weinhold				int64 top = (int64)_Pop();
525ca38af4cSIngo Weinhold				_Push((int64)_Pop() <= top ? 1 : 0);
526ca38af4cSIngo Weinhold				break;
527ca38af4cSIngo Weinhold			}
528ab3c00eeSIngo Weinhold			case DW_OP_lt:
529ca38af4cSIngo Weinhold			{
5306e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_lt\n");
531ca38af4cSIngo Weinhold				int64 top = (int64)_Pop();
532ca38af4cSIngo Weinhold				_Push((int64)_Pop() < top ? 1 : 0);
533ca38af4cSIngo Weinhold				break;
534ca38af4cSIngo Weinhold			}
535ab3c00eeSIngo Weinhold			case DW_OP_ne:
5366e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_ne\n");
537ca38af4cSIngo Weinhold				_Push(_Pop() == _Pop() ? 1 : 0);
538ca38af4cSIngo Weinhold				break;
539ca38af4cSIngo Weinhold
540ca38af4cSIngo Weinhold			case DW_OP_push_object_address:
541dec24704SIngo Weinhold			{
5426e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_push_object_address\n");
543dec24704SIngo Weinhold				target_addr_t address;
544dec24704SIngo Weinhold				if (!fContext->GetObjectAddress(address))
545d315bfd5SIngo Weinhold					throw EvaluationException("failed to get object address");
546dec24704SIngo Weinhold				_Push(address);
547ca38af4cSIngo Weinhold				break;
548dec24704SIngo Weinhold			}
549ca38af4cSIngo Weinhold			case DW_OP_call_frame_cfa:
550dec24704SIngo Weinhold			{
5516e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_call_frame_cfa\n");
552dec24704SIngo Weinhold				target_addr_t address;
553dec24704SIngo Weinhold				if (!fContext->GetFrameAddress(address))
554d315bfd5SIngo Weinhold					throw EvaluationException("failed to get frame address");
555dec24704SIngo Weinhold				_Push(address);
556dec24704SIngo Weinhold				break;
557dec24704SIngo Weinhold			}
558dec24704SIngo Weinhold			case DW_OP_fbreg:
559dec24704SIngo Weinhold			{
56081ad27dfSIngo Weinhold				int64 offset = fDataReader.ReadSignedLEB128(0);
5617483c98dSIngo Weinhold				TRACE_EXPR("  DW_OP_fbreg(%" B_PRId64 ")\n", offset);
562dec24704SIngo Weinhold				target_addr_t address;
563d315bfd5SIngo Weinhold				if (!fContext->GetFrameBaseAddress(address)) {
564d315bfd5SIngo Weinhold					throw EvaluationException(
565d315bfd5SIngo Weinhold						"failed to get frame base address");
566d315bfd5SIngo Weinhold				}
56781ad27dfSIngo Weinhold				_Push(address + offset);
568dec24704SIngo Weinhold				break;
569dec24704SIngo Weinhold			}
570dec24704SIngo Weinhold			case DW_OP_form_tls_address:
571dec24704SIngo Weinhold			{
5726e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_form_tls_address\n");
573dec24704SIngo Weinhold				target_addr_t address;
574dec24704SIngo Weinhold				if (!fContext->GetTLSAddress(_Pop(), address))
575d315bfd5SIngo Weinhold					throw EvaluationException("failed to get tls address");
576dec24704SIngo Weinhold				_Push(address);
577ca38af4cSIngo Weinhold				break;
578dec24704SIngo Weinhold			}
579ab3c00eeSIngo Weinhold
580ab3c00eeSIngo Weinhold			case DW_OP_regx:
581d315bfd5SIngo Weinhold			{
5826e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_regx\n");
583d315bfd5SIngo Weinhold				if (_piece == NULL) {
584d315bfd5SIngo Weinhold					throw EvaluationException(
585d315bfd5SIngo Weinhold						"DW_OP_regx in non-location expression");
586d315bfd5SIngo Weinhold				}
587d315bfd5SIngo Weinhold				uint32 reg = fDataReader.ReadUnsignedLEB128(0);
588d315bfd5SIngo Weinhold				if (fDataReader.HasOverflow())
589d315bfd5SIngo Weinhold					throw EvaluationException("unexpected end of expression");
590d315bfd5SIngo Weinhold				_piece->SetToRegister(reg);
591d315bfd5SIngo Weinhold				return B_OK;
592d315bfd5SIngo Weinhold			}
593d315bfd5SIngo Weinhold
594ab3c00eeSIngo Weinhold			case DW_OP_bregx:
595ca38af4cSIngo Weinhold			{
5966e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_bregx\n");
597ca38af4cSIngo Weinhold				uint32 reg = fDataReader.ReadUnsignedLEB128(0);
598ca38af4cSIngo Weinhold				_PushRegister(reg, fDataReader.ReadSignedLEB128(0));
599ca38af4cSIngo Weinhold				break;
600ca38af4cSIngo Weinhold			}
601ca38af4cSIngo Weinhold
602ab3c00eeSIngo Weinhold			case DW_OP_call2:
6036e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_call2\n");
60471fec49eSRene Gollent				_Call(fDataReader.Read<uint16>(0), dwarf_reference_type_local);
605dec24704SIngo Weinhold				break;
606ab3c00eeSIngo Weinhold			case DW_OP_call4:
6076e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_call4\n");
60871fec49eSRene Gollent				_Call(fDataReader.Read<uint32>(0), dwarf_reference_type_local);
609dec24704SIngo Weinhold				break;
610ab3c00eeSIngo Weinhold			case DW_OP_call_ref:
6116e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_call_ref\n");
61271fec49eSRene Gollent				if (fContext->AddressSize() == 4) {
61371fec49eSRene Gollent					_Call(fDataReader.Read<uint32>(0),
61471fec49eSRene Gollent						dwarf_reference_type_global);
61571fec49eSRene Gollent				} else {
61671fec49eSRene Gollent					_Call(fDataReader.Read<uint64>(0),
61771fec49eSRene Gollent						dwarf_reference_type_global);
61871fec49eSRene Gollent				}
619ca38af4cSIngo Weinhold				break;
620ca38af4cSIngo Weinhold
621ca38af4cSIngo Weinhold			case DW_OP_piece:
622ab3c00eeSIngo Weinhold			case DW_OP_bit_piece:
623d315bfd5SIngo Weinhold				// are handled in EvaluateLocation()
624d315bfd5SIngo Weinhold				if (_piece == NULL)
625d315bfd5SIngo Weinhold					return B_BAD_DATA;
626d315bfd5SIngo Weinhold
627d315bfd5SIngo Weinhold				fDataReader.SeekAbsolute(fDataReader.Offset() - 1);
628d315bfd5SIngo Weinhold					// put back the operation
629d315bfd5SIngo Weinhold				return B_OK;
630ca38af4cSIngo Weinhold
631ca38af4cSIngo Weinhold			case DW_OP_nop:
6326e72ebfcSIngo Weinhold				TRACE_EXPR("  DW_OP_nop\n");
633ab3c00eeSIngo Weinhold				break;
634ab3c00eeSIngo Weinhold
635d950dcd9SRene Gollent			case DW_OP_implicit_value:
636d950dcd9SRene Gollent			{
637d950dcd9SRene Gollent				TRACE_EXPR("  DW_OP_implicit_value\n");
638d950dcd9SRene Gollent				if (_piece == NULL) {
639d950dcd9SRene Gollent					throw EvaluationException(
640d950dcd9SRene Gollent						"DW_OP_implicit_value in non-location expression");
641d950dcd9SRene Gollent				}
642d950dcd9SRene Gollent				uint32 length = fDataReader.ReadUnsignedLEB128(0);
643d950dcd9SRene Gollent				if (length == 0)
644d950dcd9SRene Gollent					return B_BAD_DATA;
645d950dcd9SRene Gollent
646d950dcd9SRene Gollent				if (fDataReader.BytesRemaining() < length)
647d950dcd9SRene Gollent					return B_BAD_DATA;
648d950dcd9SRene Gollent
649f1fb8046SRene Gollent				if (!_piece->SetToValue(fDataReader.Data(), length))
650f1fb8046SRene Gollent					return B_NO_MEMORY;
651f1fb8046SRene Gollent
652d950dcd9SRene Gollent				return B_OK;
653d950dcd9SRene Gollent			}
654d950dcd9SRene Gollent			case DW_OP_stack_value:
655d950dcd9SRene Gollent			{
656d950dcd9SRene Gollent				TRACE_EXPR("  DW_OP_stack_value\n");
657d950dcd9SRene Gollent				if (_piece == NULL) {
658d950dcd9SRene Gollent					throw EvaluationException(
659d950dcd9SRene Gollent						"DW_OP_stack_value in non-location expression");
660d950dcd9SRene Gollent				}
661d950dcd9SRene Gollent				if (fStackSize == 0)
662d950dcd9SRene Gollent					return B_BAD_DATA;
663d950dcd9SRene Gollent				target_addr_t value = _Pop();
664f1fb8046SRene Gollent				if (!_piece->SetToValue(&value, sizeof(target_addr_t)))
665f1fb8046SRene Gollent					return B_NO_MEMORY;
666f1fb8046SRene Gollent
667d950dcd9SRene Gollent				return B_OK;
668d950dcd9SRene Gollent			}
669ab3c00eeSIngo Weinhold			default:
670ab3c00eeSIngo Weinhold				if (opcode >= DW_OP_lit0 && opcode <= DW_OP_lit31) {
6716e72ebfcSIngo Weinhold					TRACE_EXPR("  DW_OP_lit%u\n", opcode - DW_OP_lit0);
672ab3c00eeSIngo Weinhold					_Push(opcode - DW_OP_lit0);
673ab3c00eeSIngo Weinhold				} else if (opcode >= DW_OP_reg0 && opcode <= DW_OP_reg31) {
6746e72ebfcSIngo Weinhold					TRACE_EXPR("  DW_OP_reg%u\n", opcode - DW_OP_reg0);
675d315bfd5SIngo Weinhold					if (_piece == NULL) {
6760b7f2d99SIngo Weinhold						// NOTE: Using these opcodes is actually only allowed in
6770b7f2d99SIngo Weinhold						// location expression, but gcc 2.95.3 does otherwise.
6780b7f2d99SIngo Weinhold						_PushRegister(opcode - DW_OP_reg0, 0);
6790b7f2d99SIngo Weinhold					} else {
6800b7f2d99SIngo Weinhold						_piece->SetToRegister(opcode - DW_OP_reg0);
6810b7f2d99SIngo Weinhold						return B_OK;
682d315bfd5SIngo Weinhold					}
683ab3c00eeSIngo Weinhold				} else if (opcode >= DW_OP_breg0 && opcode <= DW_OP_breg31) {
68481ad27dfSIngo Weinhold					int64 offset = fDataReader.ReadSignedLEB128(0);
6857483c98dSIngo Weinhold					TRACE_EXPR("  DW_OP_breg%u(%" B_PRId64 ")\n",
6867483c98dSIngo Weinhold						opcode - DW_OP_breg0, offset);
68781ad27dfSIngo Weinhold					_PushRegister(opcode - DW_OP_breg0, offset);
688ab3c00eeSIngo Weinhold				} else {
6896e72ebfcSIngo Weinhold					WARNING("DwarfExpressionEvaluator::_Evaluate(): "
6906e72ebfcSIngo Weinhold						"unsupported opcode: %u\n", opcode);
691ab3c00eeSIngo Weinhold					return B_BAD_DATA;
692ab3c00eeSIngo Weinhold				}
693ca38af4cSIngo Weinhold				break;
694ab3c00eeSIngo Weinhold		}
695ca38af4cSIngo Weinhold
696ca38af4cSIngo Weinhold		if (++operationsExecuted >= kMaxOperationCount)
697ca38af4cSIngo Weinhold			return B_BAD_DATA;
698ab3c00eeSIngo Weinhold	}
699ab3c00eeSIngo Weinhold
700ab3c00eeSIngo Weinhold	return fDataReader.HasOverflow() ? B_BAD_DATA : B_OK;
701ab3c00eeSIngo Weinhold}
702ca38af4cSIngo Weinhold
703ca38af4cSIngo Weinhold
704ca38af4cSIngo Weinholdvoid
705ca38af4cSIngo WeinholdDwarfExpressionEvaluator::_DereferenceAddress(uint8 addressSize)
706ca38af4cSIngo Weinhold{
707ca38af4cSIngo Weinhold	uint32 valueType;
708ca38af4cSIngo Weinhold	switch (addressSize) {
709ca38af4cSIngo Weinhold		case 1:
710ca38af4cSIngo Weinhold			valueType = B_UINT8_TYPE;
711ca38af4cSIngo Weinhold			break;
712ca38af4cSIngo Weinhold		case 2:
713ca38af4cSIngo Weinhold			valueType = B_UINT16_TYPE;
714ca38af4cSIngo Weinhold			break;
715ca38af4cSIngo Weinhold		case 4:
716ca38af4cSIngo Weinhold			valueType = B_UINT32_TYPE;
717ca38af4cSIngo Weinhold			break;
718ca38af4cSIngo Weinhold		case 8:
719dec24704SIngo Weinhold			if (fContext->AddressSize() == 8) {
720ca38af4cSIngo Weinhold				valueType = B_UINT64_TYPE;
721ca38af4cSIngo Weinhold				break;
722ca38af4cSIngo Weinhold			}
723ca38af4cSIngo Weinhold			// fall through
724ca38af4cSIngo Weinhold		default:
725d315bfd5SIngo Weinhold			throw EvaluationException("invalid dereference size");
726ca38af4cSIngo Weinhold	}
727ca38af4cSIngo Weinhold
728ca38af4cSIngo Weinhold	target_addr_t address = _Pop();
729ca38af4cSIngo Weinhold	BVariant value;
730dec24704SIngo Weinhold	if (!fContext->TargetInterface()->ReadValueFromMemory(address, valueType,
731dec24704SIngo Weinhold			value)) {
732d315bfd5SIngo Weinhold		throw EvaluationException("failed to read memory");
733ca38af4cSIngo Weinhold	}
734ca38af4cSIngo Weinhold
735ca38af4cSIngo Weinhold	_Push(value.ToUInt64());
736ca38af4cSIngo Weinhold}
737ca38af4cSIngo Weinhold
738ca38af4cSIngo Weinhold
739ca38af4cSIngo Weinholdvoid
740ca38af4cSIngo WeinholdDwarfExpressionEvaluator::_DereferenceAddressSpaceAddress(uint8 addressSize)
741ca38af4cSIngo Weinhold{
742ca38af4cSIngo Weinhold	uint32 valueType;
743ca38af4cSIngo Weinhold	switch (addressSize) {
744ca38af4cSIngo Weinhold		case 1:
745ca38af4cSIngo Weinhold			valueType = B_UINT8_TYPE;
746ca38af4cSIngo Weinhold			break;
747ca38af4cSIngo Weinhold		case 2:
748ca38af4cSIngo Weinhold			valueType = B_UINT16_TYPE;
749ca38af4cSIngo Weinhold			break;
750ca38af4cSIngo Weinhold		case 4:
751ca38af4cSIngo Weinhold			valueType = B_UINT32_TYPE;
752ca38af4cSIngo Weinhold			break;
753ca38af4cSIngo Weinhold		case 8:
754dec24704SIngo Weinhold			if (fContext->AddressSize() == 8) {
755ca38af4cSIngo Weinhold				valueType = B_UINT64_TYPE;
756ca38af4cSIngo Weinhold				break;
757ca38af4cSIngo Weinhold			}
758ca38af4cSIngo Weinhold			// fall through
759ca38af4cSIngo Weinhold		default:
760d315bfd5SIngo Weinhold			throw EvaluationException("invalid dereference size");
761ca38af4cSIngo Weinhold	}
762ca38af4cSIngo Weinhold
763ca38af4cSIngo Weinhold	target_addr_t address = _Pop();
764ca38af4cSIngo Weinhold	target_addr_t addressSpace = _Pop();
765ca38af4cSIngo Weinhold	BVariant value;
766dec24704SIngo Weinhold	if (!fContext->TargetInterface()->ReadValueFromMemory(addressSpace, address,
767dec24704SIngo Weinhold			valueType, value)) {
768d315bfd5SIngo Weinhold		throw EvaluationException("failed to read memory");
769ca38af4cSIngo Weinhold	}
770ca38af4cSIngo Weinhold
771ca38af4cSIngo Weinhold	_Push(value.ToUInt64());
772ca38af4cSIngo Weinhold}
773ca38af4cSIngo Weinhold
774ca38af4cSIngo Weinhold
775ca38af4cSIngo Weinholdvoid
776ca38af4cSIngo WeinholdDwarfExpressionEvaluator::_PushRegister(uint32 reg, target_addr_t offset)
777ca38af4cSIngo Weinhold{
778ca38af4cSIngo Weinhold	BVariant value;
779dec24704SIngo Weinhold	if (!fContext->TargetInterface()->GetRegisterValue(reg, value))
780d315bfd5SIngo Weinhold		throw EvaluationException("failed to get register");
781ca38af4cSIngo Weinhold
78281ad27dfSIngo Weinhold	_Push(value.ToUInt64() + offset);
783ca38af4cSIngo Weinhold}
784dec24704SIngo Weinhold
785dec24704SIngo Weinhold
786dec24704SIngo Weinholdvoid
78771fec49eSRene GollentDwarfExpressionEvaluator::_Call(uint64 offset, uint8 refType)
788dec24704SIngo Weinhold{
789dec24704SIngo Weinhold	if (fDataReader.HasOverflow())
790d315bfd5SIngo Weinhold		throw EvaluationException("unexpected end of expression");
791dec24704SIngo Weinhold
792dec24704SIngo Weinhold	// get the expression to "call"
793dec24704SIngo Weinhold	const void* block;
794dec24704SIngo Weinhold	off_t size;
79571fec49eSRene Gollent	if (fContext->GetCallTarget(offset, refType, block, size) != B_OK)
796d315bfd5SIngo Weinhold		throw EvaluationException("failed to get call target");
797dec24704SIngo Weinhold
798dec24704SIngo Weinhold	// no expression is OK, then this is just a no-op
799dec24704SIngo Weinhold	if (block == NULL)
800dec24704SIngo Weinhold		return;
801dec24704SIngo Weinhold
802dec24704SIngo Weinhold	// save the current data reader state
803dec24704SIngo Weinhold	DataReader savedReader = fDataReader;
804dec24704SIngo Weinhold
805dec24704SIngo Weinhold	// set the reader to the target expression
806dec24704SIngo Weinhold	fDataReader.SetTo(block, size, savedReader.AddressSize());
807dec24704SIngo Weinhold
808dec24704SIngo Weinhold	// and evaluate it
809dec24704SIngo Weinhold	try {
810d315bfd5SIngo Weinhold		if (_Evaluate(NULL) != B_OK)
811d315bfd5SIngo Weinhold			throw EvaluationException("call failed");
812dec24704SIngo Weinhold	} catch (...) {
813dec24704SIngo Weinhold		fDataReader = savedReader;
814dec24704SIngo Weinhold		throw;
815dec24704SIngo Weinhold	}
816dec24704SIngo Weinhold
817dec24704SIngo Weinhold	fDataReader = savedReader;
818dec24704SIngo Weinhold}
819