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