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