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
DwarfExpressionEvaluationContext(const DwarfTargetInterface * targetInterface,uint8 addressSize,bool isBigEndian,target_addr_t relocationDelta)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
~DwarfExpressionEvaluationContext()51 DwarfExpressionEvaluationContext::~DwarfExpressionEvaluationContext()
52 {
53 }
54
55
56 // #pragma mark - EvaluationException
57
58
59 struct DwarfExpressionEvaluator::EvaluationException {
60 const char* message;
61
EvaluationExceptionDwarfExpressionEvaluator::EvaluationException62 EvaluationException(const char* message)
63 :
64 message(message)
65 {
66 }
67 };
68
69
70 // #pragma mark - DwarfExpressionEvaluator
71
72
73 void
_AssertMinStackSize(size_t size) const74 DwarfExpressionEvaluator::_AssertMinStackSize(size_t size) const
75 {
76 if (fStackSize < size)
77 throw EvaluationException("pop from empty stack");
78 }
79
80
81 void
_Push(target_addr_t value)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
_Pop()104 DwarfExpressionEvaluator::_Pop()
105 {
106 _AssertMinStackSize(1);
107 return fStack[--fStackSize];
108 }
109
110
DwarfExpressionEvaluator(DwarfExpressionEvaluationContext * context)111 DwarfExpressionEvaluator::DwarfExpressionEvaluator(
112 DwarfExpressionEvaluationContext* context)
113 :
114 fContext(context),
115 fStack(NULL),
116 fStackSize(0),
117 fStackCapacity(0)
118 {
119 }
120
121
~DwarfExpressionEvaluator()122 DwarfExpressionEvaluator::~DwarfExpressionEvaluator()
123 {
124 free(fStack);
125 }
126
127
128 status_t
Push(target_addr_t value)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
Evaluate(const void * expression,size_t size,target_addr_t & _result)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
EvaluateLocation(const void * expression,size_t size,ValueLocation & _location)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
_Evaluate(ValuePieceLocation * _piece)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
_DereferenceAddress(uint8 addressSize)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
_DereferenceAddressSpaceAddress(uint8 addressSize)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
_PushRegister(uint32 reg,target_addr_t offset)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
_Call(uint64 offset,uint8 refType)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