1 //===-- Address.cpp ---------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Core/Address.h" 11 #include "lldb/Core/Module.h" 12 #include "lldb/Core/Section.h" 13 #include "lldb/Symbol/ObjectFile.h" 14 #include "lldb/Target/Process.h" 15 #include "lldb/Target/Target.h" 16 17 using namespace lldb; 18 using namespace lldb_private; 19 20 static size_t 21 ReadBytes (ExecutionContextScope *exe_scope, const Address &address, void *dst, size_t dst_len) 22 { 23 if (exe_scope == NULL) 24 return 0; 25 26 lldb::AddressType addr_type = eAddressTypeInvalid; 27 addr_t addr = LLDB_INVALID_ADDRESS; 28 29 Process *process = exe_scope->CalculateProcess(); 30 31 if (process && process->IsAlive()) 32 { 33 addr = address.GetLoadAddress(process); 34 if (addr != LLDB_INVALID_ADDRESS) 35 addr_type = eAddressTypeLoad; 36 } 37 38 if (addr == LLDB_INVALID_ADDRESS) 39 { 40 addr = address.GetFileAddress(); 41 if (addr != LLDB_INVALID_ADDRESS) 42 addr_type = eAddressTypeFile; 43 } 44 45 if (addr_type == eAddressTypeInvalid) 46 return false; 47 48 Target *target = exe_scope->CalculateTarget(); 49 if (target) 50 { 51 Error error; 52 return target->ReadMemory (addr_type, addr, dst, dst_len, error, NULL); 53 } 54 return 0; 55 } 56 57 static bool 58 GetByteOrderAndAddressSize (ExecutionContextScope *exe_scope, const Address &address, ByteOrder& byte_order, uint32_t& addr_size) 59 { 60 byte_order = eByteOrderInvalid; 61 addr_size = 0; 62 if (exe_scope == NULL) 63 return false; 64 65 Process *process = exe_scope->CalculateProcess(); 66 if (process) 67 { 68 byte_order = process->GetByteOrder(); 69 addr_size = process->GetAddressByteSize(); 70 } 71 72 if (byte_order == eByteOrderInvalid || addr_size == 0) 73 { 74 Module *module = address.GetModule(); 75 if (module) 76 { 77 byte_order = module->GetArchitecture().GetDefaultEndian(); 78 addr_size = module->GetArchitecture().GetAddressByteSize(); 79 } 80 } 81 return byte_order != eByteOrderInvalid && addr_size != 0; 82 } 83 84 static uint64_t 85 ReadUIntMax64 (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, bool &success) 86 { 87 uint64_t uval64 = 0; 88 if (exe_scope == NULL || byte_size > sizeof(uint64_t)) 89 { 90 success = false; 91 return 0; 92 } 93 uint64_t buf; 94 95 success = ReadBytes (exe_scope, address, &buf, byte_size) == byte_size; 96 if (success) 97 { 98 ByteOrder byte_order = eByteOrderInvalid; 99 uint32_t addr_size = 0; 100 if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size)) 101 { 102 DataExtractor data (&buf, sizeof(buf), byte_order, addr_size); 103 uint32_t offset = 0; 104 uval64 = data.GetU64(&offset); 105 } 106 else 107 success = false; 108 } 109 return uval64; 110 } 111 112 static bool 113 ReadAddress (ExecutionContextScope *exe_scope, const Address &address, uint32_t pointer_size, Address &deref_so_addr) 114 { 115 if (exe_scope == NULL) 116 return false; 117 118 119 bool success = false; 120 addr_t deref_addr = ReadUIntMax64 (exe_scope, address, pointer_size, success); 121 if (success) 122 { 123 Process *process = exe_scope->CalculateProcess(); 124 if (process && process->IsAlive()) 125 { 126 if (!process->ResolveLoadAddress (deref_addr, deref_so_addr)) 127 { 128 deref_so_addr.SetSection(NULL); 129 deref_so_addr.SetOffset(deref_addr); 130 } 131 } 132 else 133 { 134 Target *target = exe_scope->CalculateTarget(); 135 if (target == NULL) 136 return false; 137 138 if (!target->GetImages().ResolveFileAddress(deref_addr, deref_so_addr)) 139 { 140 deref_so_addr.SetSection(NULL); 141 deref_so_addr.SetOffset(deref_addr); 142 } 143 } 144 return true; 145 } 146 return false; 147 } 148 149 static bool 150 DumpUInt (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, Stream* strm) 151 { 152 if (exe_scope == NULL) 153 return 0; 154 std::vector<uint8_t> buf(byte_size, 0); 155 156 if (ReadBytes (exe_scope, address, &buf[0], buf.size()) == buf.size()) 157 { 158 ByteOrder byte_order = eByteOrderInvalid; 159 uint32_t addr_size = 0; 160 if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size)) 161 { 162 DataExtractor data (buf.data(), buf.size(), byte_order, addr_size); 163 164 data.Dump (strm, 165 0, // Start offset in "data" 166 eFormatHex, // Print as characters 167 buf.size(), // Size of item 168 1, // Items count 169 UINT32_MAX, // num per line 170 LLDB_INVALID_ADDRESS,// base address 171 0, // bitfield bit size 172 0); // bitfield bit offset 173 174 return true; 175 } 176 } 177 return false; 178 } 179 180 181 static size_t 182 ReadCStringFromMemory (ExecutionContextScope *exe_scope, const Address &address, Stream *strm) 183 { 184 if (exe_scope == NULL) 185 return 0; 186 const size_t k_buf_len = 256; 187 char buf[k_buf_len+1]; 188 buf[k_buf_len] = '\0'; // NULL terminate 189 190 // Byte order and adderss size don't matter for C string dumping.. 191 DataExtractor data (buf, sizeof(buf), eByteOrderHost, 4); 192 size_t total_len = 0; 193 size_t bytes_read; 194 Address curr_address(address); 195 strm->PutChar ('"'); 196 while ((bytes_read = ReadBytes (exe_scope, curr_address, buf, k_buf_len)) > 0) 197 { 198 size_t len = strlen(buf); 199 if (len == 0) 200 break; 201 if (len > bytes_read) 202 len = bytes_read; 203 204 data.Dump (strm, 205 0, // Start offset in "data" 206 eFormatChar, // Print as characters 207 1, // Size of item (1 byte for a char!) 208 len, // How many bytes to print? 209 UINT32_MAX, // num per line 210 LLDB_INVALID_ADDRESS,// base address 211 0, // bitfield bit size 212 213 0); // bitfield bit offset 214 215 total_len += bytes_read; 216 217 if (len < k_buf_len) 218 break; 219 curr_address.SetOffset (curr_address.GetOffset() + bytes_read); 220 } 221 strm->PutChar ('"'); 222 return total_len; 223 } 224 225 Address::Address () : 226 m_section (NULL), 227 m_offset (LLDB_INVALID_ADDRESS) 228 { 229 } 230 231 Address::Address (const Address& rhs) : 232 m_section (rhs.m_section), 233 m_offset (rhs.m_offset) 234 { 235 } 236 237 Address::Address (const Section* section, addr_t offset) : 238 m_section (section), 239 m_offset (offset) 240 { 241 } 242 243 Address::Address (addr_t address, const SectionList * sections) : 244 m_section (NULL), 245 m_offset (LLDB_INVALID_ADDRESS) 246 { 247 ResolveAddressUsingFileSections(address, sections); 248 } 249 250 Address::~Address () 251 { 252 } 253 254 255 const Address& 256 Address::operator= (const Address& rhs) 257 { 258 if (this != &rhs) 259 { 260 m_section = rhs.m_section; 261 m_offset = rhs.m_offset; 262 } 263 return *this; 264 } 265 266 bool 267 Address::IsValid() const 268 { 269 return m_offset != LLDB_INVALID_ADDRESS; 270 } 271 272 bool 273 Address::IsSectionOffset() const 274 { 275 return m_section != NULL && IsValid(); 276 } 277 278 bool 279 Address::ResolveAddressUsingFileSections (addr_t addr, const SectionList *sections) 280 { 281 if (sections) 282 m_section = sections->FindSectionContainingFileAddress(addr).get(); 283 else 284 m_section = NULL; 285 286 if (m_section != NULL) 287 { 288 assert( m_section->ContainsFileAddress(addr) ); 289 m_offset = addr - m_section->GetFileAddress(); 290 return true; // Successfully transformed addr into a section offset address 291 } 292 293 m_offset = addr; 294 return false; // Failed to resolve this address to a section offset value 295 } 296 297 //bool 298 //Address::ResolveAddressUsingLoadSections (addr_t addr, const SectionList *sections) 299 //{ 300 // if (sections) 301 // m_section = sections->FindSectionContainingLoadAddress(addr).get(); 302 // else 303 // m_section = NULL; 304 // 305 // if (m_section != NULL) 306 // { 307 // assert( m_section->ContainsLoadAddress(addr) ); 308 // m_offset = addr - m_section->GetLoadBaseAddress(); 309 // return true; // Successfully transformed addr into a section offset address 310 // } 311 // 312 // m_offset = addr; 313 // return false; // Failed to resolve this address to a section offset value 314 //} 315 // 316 Module * 317 Address::GetModule () const 318 { 319 if (m_section) 320 return m_section->GetModule(); 321 return NULL; 322 } 323 324 const Section* 325 Address::GetSection () const 326 { 327 return m_section; 328 } 329 330 331 //addr_t 332 //Address::Address() const 333 //{ 334 // addr_t addr = GetLoadAddress(); 335 // if (addr != LLDB_INVALID_ADDRESS) 336 // return addr; 337 // return GetFileAddress(); 338 //} 339 // 340 341 addr_t 342 Address::GetFileAddress () const 343 { 344 if (m_section != NULL) 345 { 346 addr_t sect_file_addr = m_section->GetFileAddress(); 347 if (sect_file_addr == LLDB_INVALID_ADDRESS) 348 { 349 // Section isn't resolved, we can't return a valid file address 350 return LLDB_INVALID_ADDRESS; 351 } 352 // We have a valid file range, so we can return the file based 353 // address by adding the file base address to our offset 354 return sect_file_addr + m_offset; 355 } 356 // No section, we just return the offset since it is the value in this case 357 return m_offset; 358 } 359 360 addr_t 361 Address::GetLoadAddress (Process *process) const 362 { 363 if (m_section != NULL) 364 { 365 if (process) 366 { 367 addr_t sect_load_addr = m_section->GetLoadBaseAddress (process); 368 369 if (sect_load_addr != LLDB_INVALID_ADDRESS) 370 { 371 // We have a valid file range, so we can return the file based 372 // address by adding the file base address to our offset 373 return sect_load_addr + m_offset; 374 } 375 } 376 // The section isn't resolved or no process was supplied so we can't 377 // return a valid file address. 378 return LLDB_INVALID_ADDRESS; 379 } 380 // No section, we just return the offset since it is the value in this case 381 return m_offset; 382 } 383 384 addr_t 385 Address::GetOffset () const 386 { 387 return m_offset; 388 } 389 390 bool 391 Address::SetOffset (addr_t offset) 392 { 393 bool changed = m_offset != offset; 394 m_offset = offset; 395 return changed; 396 } 397 398 void 399 Address::SetSection (const Section* section) 400 { 401 m_section = section; 402 } 403 404 void 405 Address::Clear() 406 { 407 m_section = NULL; 408 m_offset = LLDB_INVALID_ADDRESS; 409 } 410 411 412 bool 413 Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style) const 414 { 415 // If the section was NULL, only load address is going to work. 416 if (m_section == NULL) 417 style = DumpStyleLoadAddress; 418 419 Process *process = NULL; 420 if (exe_scope) 421 process = exe_scope->CalculateProcess(); 422 int addr_size = sizeof (addr_t); 423 if (process) 424 addr_size = process->GetAddressByteSize (); 425 426 lldb_private::Address so_addr; 427 428 switch (style) 429 { 430 case DumpStyleSectionNameOffset: 431 if (m_section != NULL) 432 { 433 m_section->DumpName(s); 434 s->Printf (" + %llu", m_offset); 435 } 436 else 437 { 438 s->Printf("0x%16.16llx", m_offset); 439 } 440 break; 441 442 case DumpStyleSectionPointerOffset: 443 s->Printf("(Section *)%.*p + 0x%16.16llx", (int)sizeof(void*) * 2, m_section, m_offset); 444 break; 445 446 case DumpStyleModuleWithFileAddress: 447 s->Printf("%s[", m_section->GetModule()->GetFileSpec().GetFilename().AsCString()); 448 // Fall through 449 case DumpStyleFileAddress: 450 { 451 addr_t file_addr = GetFileAddress(); 452 if (file_addr == LLDB_INVALID_ADDRESS) 453 { 454 if (fallback_style != DumpStyleInvalid) 455 return Dump (s, exe_scope, fallback_style); 456 return false; 457 } 458 s->Address (file_addr, addr_size); 459 if (style == DumpStyleModuleWithFileAddress) 460 s->PutChar(']'); 461 } 462 break; 463 464 case DumpStyleLoadAddress: 465 { 466 addr_t load_addr = GetLoadAddress (process); 467 if (load_addr == LLDB_INVALID_ADDRESS) 468 { 469 if (fallback_style != DumpStyleInvalid) 470 return Dump (s, exe_scope, fallback_style); 471 return false; 472 } 473 s->Address (load_addr, addr_size); 474 } 475 break; 476 477 case DumpStyleResolvedDescription: 478 if (IsSectionOffset()) 479 { 480 lldb::AddressType addr_type = eAddressTypeLoad; 481 addr_t addr = GetLoadAddress (process); 482 if (addr == LLDB_INVALID_ADDRESS) 483 { 484 addr = GetFileAddress(); 485 addr_type = eAddressTypeFile; 486 } 487 488 uint32_t pointer_size = 4; 489 lldb_private::Module *module = GetModule(); 490 if (process) 491 pointer_size = process->GetAddressByteSize(); 492 else if (module) 493 pointer_size = module->GetArchitecture().GetAddressByteSize(); 494 495 bool showed_info = false; 496 const Section *section = GetSection(); 497 if (section) 498 { 499 SectionType sect_type = section->GetSectionType(); 500 switch (sect_type) 501 { 502 case eSectionTypeDataCString: 503 // Read the C string from memory and display it 504 showed_info = true; 505 ReadCStringFromMemory (exe_scope, *this, s); 506 break; 507 508 case eSectionTypeDataCStringPointers: 509 { 510 if (ReadAddress (exe_scope, *this, pointer_size, so_addr)) 511 { 512 #if VERBOSE_OUTPUT 513 s->PutCString("(char *)"); 514 so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); 515 s->PutCString(": "); 516 #endif 517 showed_info = true; 518 ReadCStringFromMemory (exe_scope, so_addr, s); 519 } 520 } 521 break; 522 523 case eSectionTypeDataObjCMessageRefs: 524 { 525 if (ReadAddress (exe_scope, *this, pointer_size, so_addr)) 526 { 527 if (so_addr.IsSectionOffset()) 528 { 529 lldb_private::SymbolContext func_sc; 530 process->GetTarget().GetImages().ResolveSymbolContextForAddress (so_addr, 531 eSymbolContextEverything, 532 func_sc); 533 if (func_sc.function || func_sc.symbol) 534 { 535 showed_info = true; 536 #if VERBOSE_OUTPUT 537 s->PutCString ("(objc_msgref *) -> { (func*)"); 538 so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); 539 #else 540 s->PutCString ("{ "); 541 #endif 542 Address cstr_addr(*this); 543 cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size); 544 func_sc.DumpStopContext(s, process, so_addr, true); 545 if (ReadAddress (exe_scope, cstr_addr, pointer_size, so_addr)) 546 { 547 #if VERBOSE_OUTPUT 548 s->PutCString("), (char *)"); 549 so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); 550 s->PutCString(" ("); 551 #else 552 s->PutCString(", "); 553 #endif 554 ReadCStringFromMemory (exe_scope, so_addr, s); 555 } 556 #if VERBOSE_OUTPUT 557 s->PutCString(") }"); 558 #else 559 s->PutCString(" }"); 560 #endif 561 } 562 } 563 } 564 } 565 break; 566 567 case eSectionTypeDataObjCCFStrings: 568 { 569 Address cfstring_data_addr(*this); 570 cfstring_data_addr.SetOffset(cfstring_data_addr.GetOffset() + (2 * pointer_size)); 571 if (ReadAddress (exe_scope, cfstring_data_addr, pointer_size, so_addr)) 572 { 573 #if VERBOSE_OUTPUT 574 s->PutCString("(CFString *) "); 575 cfstring_data_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); 576 s->PutCString(" -> @"); 577 #else 578 s->PutChar('@'); 579 #endif 580 if (so_addr.Dump(s, exe_scope, DumpStyleResolvedDescription)) 581 showed_info = true; 582 } 583 } 584 break; 585 586 case eSectionTypeData4: 587 // Read the 4 byte data and display it 588 showed_info = true; 589 s->PutCString("(uint32_t) "); 590 DumpUInt (exe_scope, *this, 4, s); 591 break; 592 593 case eSectionTypeData8: 594 // Read the 8 byte data and display it 595 showed_info = true; 596 s->PutCString("(uint64_t) "); 597 DumpUInt (exe_scope, *this, 8, s); 598 break; 599 600 case eSectionTypeData16: 601 // Read the 16 byte data and display it 602 showed_info = true; 603 s->PutCString("(uint128_t) "); 604 DumpUInt (exe_scope, *this, 16, s); 605 break; 606 607 case eSectionTypeDataPointers: 608 // Read the pointer data and display it 609 { 610 if (ReadAddress (exe_scope, *this, pointer_size, so_addr)) 611 { 612 s->PutCString ("(void *)"); 613 so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); 614 615 showed_info = true; 616 if (so_addr.IsSectionOffset()) 617 { 618 lldb_private::SymbolContext pointer_sc; 619 process->GetTarget().GetImages().ResolveSymbolContextForAddress (so_addr, 620 eSymbolContextEverything, 621 pointer_sc); 622 if (pointer_sc.function || pointer_sc.symbol) 623 { 624 s->PutCString(": "); 625 pointer_sc.DumpStopContext(s, process, so_addr, false); 626 } 627 } 628 } 629 } 630 break; 631 } 632 } 633 634 if (!showed_info) 635 { 636 if (module) 637 { 638 lldb_private::SymbolContext sc; 639 module->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc); 640 if (sc.function || sc.symbol) 641 { 642 bool show_stop_context = true; 643 if (sc.function == NULL && sc.symbol != NULL) 644 { 645 // If we have just a symbol make sure it is in the right section 646 if (sc.symbol->GetAddressRangePtr()) 647 { 648 if (sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetSection() != GetSection()) 649 show_stop_context = false; 650 } 651 } 652 if (show_stop_context) 653 { 654 // We have a function or a symbol from the same 655 // sections as this address. 656 sc.DumpStopContext(s, process, *this, false); 657 } 658 else 659 { 660 // We found a symbol but it was in a different 661 // section so it isn't the symbol we should be 662 // showing, just show the section name + offset 663 Dump (s, exe_scope, DumpStyleSectionNameOffset); 664 } 665 } 666 } 667 } 668 } 669 else 670 { 671 if (fallback_style != DumpStyleInvalid) 672 return Dump (s, exe_scope, fallback_style); 673 return false; 674 } 675 break; 676 } 677 678 return true; 679 } 680 681 //Stream& operator << (Stream& s, const Address& so_addr) 682 //{ 683 // so_addr.Dump(&s, Address::DumpStyleSectionNameOffset); 684 // return s; 685 //} 686 // 687 void 688 Address::CalculateSymbolContext (SymbolContext *sc) 689 { 690 sc->Clear(); 691 // Absolute addresses don't have enough information to reconstruct even their target. 692 if (m_section == NULL) 693 return; 694 695 if (m_section->GetModule()) 696 { 697 sc->module_sp = m_section->GetModule()->GetSP(); 698 if (sc->module_sp) 699 sc->module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextEverything, *sc); 700 } 701 } 702 703 void 704 Address::DumpSymbolContext (Stream *s) 705 { 706 SymbolContext sc; 707 CalculateSymbolContext (&sc); 708 sc.Dump (s, NULL); 709 } 710 711 void 712 Address::DumpDebug(Stream *s) const 713 { 714 *s << (void *)this << ": " << "Address"; 715 if (m_section != NULL) 716 { 717 *s << ", section = " << (void *)m_section << " (" << m_section->GetName() << "), offset = " << m_offset; 718 } 719 else 720 { 721 *s << ", vm_addr = " << m_offset; 722 } 723 s->EOL(); 724 } 725 726 int 727 Address::CompareFileAddress (const Address& a, const Address& b) 728 { 729 addr_t a_file_addr = a.GetFileAddress(); 730 addr_t b_file_addr = b.GetFileAddress(); 731 if (a_file_addr < b_file_addr) 732 return -1; 733 if (a_file_addr > b_file_addr) 734 return +1; 735 return 0; 736 } 737 738 739 int 740 Address::CompareLoadAddress (const Address& a, const Address& b, Process *process) 741 { 742 assert (process != NULL); 743 addr_t a_load_addr = a.GetLoadAddress (process); 744 addr_t b_load_addr = b.GetLoadAddress (process); 745 if (a_load_addr < b_load_addr) 746 return -1; 747 if (a_load_addr > b_load_addr) 748 return +1; 749 return 0; 750 } 751 752 int 753 Address::CompareModulePointerAndOffset (const Address& a, const Address& b) 754 { 755 Module *a_module = a.GetModule (); 756 Module *b_module = b.GetModule (); 757 if (a_module < b_module) 758 return -1; 759 if (a_module > b_module) 760 return +1; 761 // Modules are the same, just compare the file address since they should 762 // be unique 763 addr_t a_file_addr = a.GetFileAddress(); 764 addr_t b_file_addr = b.GetFileAddress(); 765 if (a_file_addr < b_file_addr) 766 return -1; 767 if (a_file_addr > b_file_addr) 768 return +1; 769 return 0; 770 } 771 772 773 size_t 774 Address::MemorySize () const 775 { 776 // Noting special for the memory size of a single Address object, 777 // it is just the size of itself. 778 return sizeof(Address); 779 } 780 781 782 /// The only comparisons that make sense are the load addresses 783 //bool 784 //lldb::operator< (const Address& lhs, const Address& rhs) 785 //{ 786 // lldb::addr_t lhs_addr = lhs.GetLoadAddress(); 787 // lldb::addr_t rhs_addr = rhs.GetLoadAddress(); 788 // 789 // if (lhs_addr == rhs_addr) 790 // { 791 // lhs_addr = lhs.GetFileAddress(); 792 // rhs_addr = rhs.GetFileAddress(); 793 // } 794 // return lhs_addr < rhs_addr; 795 //} 796 // 797 //bool 798 //lldb::operator<= (const Address& lhs, const Address& rhs) 799 //{ 800 // lldb::addr_t lhs_addr = lhs.GetLoadAddress(); 801 // lldb::addr_t rhs_addr = rhs.GetLoadAddress(); 802 // 803 // if (lhs_addr == rhs_addr) 804 // { 805 // lhs_addr = lhs.GetFileAddress(); 806 // rhs_addr = rhs.GetFileAddress(); 807 // } 808 // return lhs_addr <= rhs_addr; 809 //} 810 // 811 //bool 812 //lldb::operator> (const Address& lhs, const Address& rhs) 813 //{ 814 // lldb::addr_t lhs_addr = lhs.GetLoadAddress(); 815 // lldb::addr_t rhs_addr = rhs.GetLoadAddress(); 816 // 817 // if (lhs_addr == rhs_addr) 818 // { 819 // lhs_addr = lhs.GetFileAddress(); 820 // rhs_addr = rhs.GetFileAddress(); 821 // } 822 // return lhs_addr > rhs_addr; 823 //} 824 // 825 //bool 826 //lldb::operator>= (const Address& lhs, const Address& rhs) 827 //{ 828 // lldb::addr_t lhs_addr = lhs.GetLoadAddress(); 829 // lldb::addr_t rhs_addr = rhs.GetLoadAddress(); 830 // 831 // if (lhs_addr == rhs_addr) 832 // { 833 // lhs_addr = lhs.GetFileAddress(); 834 // rhs_addr = rhs.GetFileAddress(); 835 // } 836 // return lhs_addr >= rhs_addr; 837 //} 838 // 839 840 // The operator == checks for exact equality only (same section, same offset) 841 bool 842 lldb_private::operator== (const Address& a, const Address& rhs) 843 { 844 return a.GetSection() == rhs.GetSection() && 845 a.GetOffset() == rhs.GetOffset(); 846 } 847 // The operator != checks for exact inequality only (differing section, or 848 // different offset) 849 bool 850 lldb_private::operator!= (const Address& a, const Address& rhs) 851 { 852 return a.GetSection() != rhs.GetSection() || 853 a.GetOffset() != rhs.GetOffset(); 854 } 855 856 bool 857 Address::IsLinkedAddress () const 858 { 859 return m_section && m_section->GetLinkedSection(); 860 } 861 862 863 void 864 Address::ResolveLinkedAddress () 865 { 866 if (m_section) 867 { 868 const Section *linked_section = m_section->GetLinkedSection(); 869 if (linked_section) 870 { 871 m_offset += m_section->GetLinkedOffset(); 872 m_section = linked_section; 873 } 874 } 875 } 876