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