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