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