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 // ObjectFile *objfile = NULL; 53 // if (address.GetModule()) 54 // objfile = address.GetModule()->GetObjectFile(); 55 // return target->ReadMemory (addr_type, addr, dst, dst_len, error, objfile); 56 // } 57 // return 0; 58 //} 59 60 static size_t 61 ReadBytes (ExecutionContextScope *exe_scope, const Address &address, void *dst, size_t dst_len) 62 { 63 if (exe_scope == NULL) 64 return 0; 65 66 Target *target = exe_scope->CalculateTarget(); 67 if (target) 68 { 69 Error error; 70 return target->ReadMemory (address, dst, dst_len, error); 71 } 72 return 0; 73 } 74 75 static bool 76 GetByteOrderAndAddressSize (ExecutionContextScope *exe_scope, const Address &address, ByteOrder& byte_order, uint32_t& addr_size) 77 { 78 byte_order = eByteOrderInvalid; 79 addr_size = 0; 80 if (exe_scope == NULL) 81 return false; 82 83 Process *process = exe_scope->CalculateProcess(); 84 if (process) 85 { 86 byte_order = process->GetByteOrder(); 87 addr_size = process->GetAddressByteSize(); 88 } 89 90 if (byte_order == eByteOrderInvalid || addr_size == 0) 91 { 92 Module *module = address.GetModule(); 93 if (module) 94 { 95 byte_order = module->GetArchitecture().GetDefaultEndian(); 96 addr_size = module->GetArchitecture().GetAddressByteSize(); 97 } 98 } 99 return byte_order != eByteOrderInvalid && addr_size != 0; 100 } 101 102 static uint64_t 103 ReadUIntMax64 (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, bool &success) 104 { 105 uint64_t uval64 = 0; 106 if (exe_scope == NULL || byte_size > sizeof(uint64_t)) 107 { 108 success = false; 109 return 0; 110 } 111 uint64_t buf; 112 113 success = ReadBytes (exe_scope, address, &buf, byte_size) == byte_size; 114 if (success) 115 { 116 ByteOrder byte_order = eByteOrderInvalid; 117 uint32_t addr_size = 0; 118 if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size)) 119 { 120 DataExtractor data (&buf, sizeof(buf), byte_order, addr_size); 121 uint32_t offset = 0; 122 uval64 = data.GetU64(&offset); 123 } 124 else 125 success = false; 126 } 127 return uval64; 128 } 129 130 static bool 131 ReadAddress (ExecutionContextScope *exe_scope, const Address &address, uint32_t pointer_size, Address &deref_so_addr) 132 { 133 if (exe_scope == NULL) 134 return false; 135 136 137 bool success = false; 138 addr_t deref_addr = ReadUIntMax64 (exe_scope, address, pointer_size, success); 139 if (success) 140 { 141 Process *process = exe_scope->CalculateProcess(); 142 if (process && process->IsAlive()) 143 { 144 if (!process->ResolveLoadAddress (deref_addr, deref_so_addr)) 145 { 146 deref_so_addr.SetSection(NULL); 147 deref_so_addr.SetOffset(deref_addr); 148 } 149 } 150 else 151 { 152 Target *target = exe_scope->CalculateTarget(); 153 if (target == NULL) 154 return false; 155 156 if (!target->GetImages().ResolveFileAddress(deref_addr, deref_so_addr)) 157 { 158 deref_so_addr.SetSection(NULL); 159 deref_so_addr.SetOffset(deref_addr); 160 } 161 } 162 return true; 163 } 164 return false; 165 } 166 167 static bool 168 DumpUInt (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, Stream* strm) 169 { 170 if (exe_scope == NULL) 171 return 0; 172 std::vector<uint8_t> buf(byte_size, 0); 173 174 if (ReadBytes (exe_scope, address, &buf[0], buf.size()) == buf.size()) 175 { 176 ByteOrder byte_order = eByteOrderInvalid; 177 uint32_t addr_size = 0; 178 if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size)) 179 { 180 DataExtractor data (buf.data(), buf.size(), byte_order, addr_size); 181 182 data.Dump (strm, 183 0, // Start offset in "data" 184 eFormatHex, // Print as characters 185 buf.size(), // Size of item 186 1, // Items count 187 UINT32_MAX, // num per line 188 LLDB_INVALID_ADDRESS,// base address 189 0, // bitfield bit size 190 0); // bitfield bit offset 191 192 return true; 193 } 194 } 195 return false; 196 } 197 198 199 static size_t 200 ReadCStringFromMemory (ExecutionContextScope *exe_scope, const Address &address, Stream *strm) 201 { 202 if (exe_scope == NULL) 203 return 0; 204 const size_t k_buf_len = 256; 205 char buf[k_buf_len+1]; 206 buf[k_buf_len] = '\0'; // NULL terminate 207 208 // Byte order and adderss size don't matter for C string dumping.. 209 DataExtractor data (buf, sizeof(buf), eByteOrderHost, 4); 210 size_t total_len = 0; 211 size_t bytes_read; 212 Address curr_address(address); 213 strm->PutChar ('"'); 214 while ((bytes_read = ReadBytes (exe_scope, curr_address, buf, k_buf_len)) > 0) 215 { 216 size_t len = strlen(buf); 217 if (len == 0) 218 break; 219 if (len > bytes_read) 220 len = bytes_read; 221 222 data.Dump (strm, 223 0, // Start offset in "data" 224 eFormatChar, // Print as characters 225 1, // Size of item (1 byte for a char!) 226 len, // How many bytes to print? 227 UINT32_MAX, // num per line 228 LLDB_INVALID_ADDRESS,// base address 229 0, // bitfield bit size 230 231 0); // bitfield bit offset 232 233 total_len += bytes_read; 234 235 if (len < k_buf_len) 236 break; 237 curr_address.SetOffset (curr_address.GetOffset() + bytes_read); 238 } 239 strm->PutChar ('"'); 240 return total_len; 241 } 242 243 Address::Address () : 244 m_section (NULL), 245 m_offset (LLDB_INVALID_ADDRESS) 246 { 247 } 248 249 Address::Address (const Address& rhs) : 250 m_section (rhs.m_section), 251 m_offset (rhs.m_offset) 252 { 253 } 254 255 Address::Address (const Section* section, addr_t offset) : 256 m_section (section), 257 m_offset (offset) 258 { 259 } 260 261 Address::Address (addr_t address, const SectionList * sections) : 262 m_section (NULL), 263 m_offset (LLDB_INVALID_ADDRESS) 264 { 265 ResolveAddressUsingFileSections(address, sections); 266 } 267 268 const Address& 269 Address::operator= (const Address& rhs) 270 { 271 if (this != &rhs) 272 { 273 m_section = rhs.m_section; 274 m_offset = rhs.m_offset; 275 } 276 return *this; 277 } 278 279 bool 280 Address::IsValid() const 281 { 282 return m_offset != LLDB_INVALID_ADDRESS; 283 } 284 285 bool 286 Address::IsSectionOffset() const 287 { 288 return m_section != NULL && IsValid(); 289 } 290 291 bool 292 Address::ResolveAddressUsingFileSections (addr_t addr, const SectionList *sections) 293 { 294 if (sections) 295 m_section = sections->FindSectionContainingFileAddress(addr).get(); 296 else 297 m_section = NULL; 298 299 if (m_section != NULL) 300 { 301 assert( m_section->ContainsFileAddress(addr) ); 302 m_offset = addr - m_section->GetFileAddress(); 303 return true; // Successfully transformed addr into a section offset address 304 } 305 306 m_offset = addr; 307 return false; // Failed to resolve this address to a section offset value 308 } 309 310 //bool 311 //Address::ResolveAddressUsingLoadSections (addr_t addr, const SectionList *sections) 312 //{ 313 // if (sections) 314 // m_section = sections->FindSectionContainingLoadAddress(addr).get(); 315 // else 316 // m_section = NULL; 317 // 318 // if (m_section != NULL) 319 // { 320 // assert( m_section->ContainsLoadAddress(addr) ); 321 // m_offset = addr - m_section->GetLoadBaseAddress(); 322 // return true; // Successfully transformed addr into a section offset address 323 // } 324 // 325 // m_offset = addr; 326 // return false; // Failed to resolve this address to a section offset value 327 //} 328 // 329 Module * 330 Address::GetModule () const 331 { 332 if (m_section) 333 return m_section->GetModule(); 334 return NULL; 335 } 336 337 //addr_t 338 //Address::Address() const 339 //{ 340 // addr_t addr = GetLoadAddress(); 341 // if (addr != LLDB_INVALID_ADDRESS) 342 // return addr; 343 // return GetFileAddress(); 344 //} 345 // 346 347 addr_t 348 Address::GetFileAddress () const 349 { 350 if (m_section != NULL) 351 { 352 addr_t sect_file_addr = m_section->GetFileAddress(); 353 if (sect_file_addr == LLDB_INVALID_ADDRESS) 354 { 355 // Section isn't resolved, we can't return a valid file address 356 return LLDB_INVALID_ADDRESS; 357 } 358 // We have a valid file range, so we can return the file based 359 // address by adding the file base address to our offset 360 return sect_file_addr + m_offset; 361 } 362 // No section, we just return the offset since it is the value in this case 363 return m_offset; 364 } 365 366 addr_t 367 Address::GetLoadAddress (Process *process) const 368 { 369 if (m_section != NULL) 370 { 371 if (process) 372 { 373 addr_t sect_load_addr = m_section->GetLoadBaseAddress (process); 374 375 if (sect_load_addr != LLDB_INVALID_ADDRESS) 376 { 377 // We have a valid file range, so we can return the file based 378 // address by adding the file base address to our offset 379 return sect_load_addr + m_offset; 380 } 381 } 382 // The section isn't resolved or no process was supplied so we can't 383 // return a valid file address. 384 return LLDB_INVALID_ADDRESS; 385 } 386 // No section, we just return the offset since it is the value in this case 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::Clear() 400 { 401 m_section = NULL; 402 m_offset = LLDB_INVALID_ADDRESS; 403 } 404 405 406 bool 407 Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style, uint32_t addr_size) const 408 { 409 // If the section was NULL, only load address is going to work. 410 if (m_section == NULL) 411 style = DumpStyleLoadAddress; 412 413 Process *process = NULL; 414 if (exe_scope) 415 process = exe_scope->CalculateProcess(); 416 // If addr_byte_size is UINT32_MAX, then determine the correct address 417 // byte size for the process or default to the size of addr_t 418 if (addr_size == UINT32_MAX) 419 { 420 if (process) 421 addr_size = process->GetAddressByteSize (); 422 else 423 addr_size = sizeof(addr_t); 424 } 425 426 lldb_private::Address so_addr; 427 switch (style) 428 { 429 case DumpStyleSectionNameOffset: 430 if (m_section != NULL) 431 { 432 m_section->DumpName(s); 433 s->Printf (" + %llu", m_offset); 434 } 435 else 436 { 437 s->Address(m_offset, addr_size); 438 } 439 break; 440 441 case DumpStyleSectionPointerOffset: 442 s->Printf("(Section *)%.*p + ", (int)sizeof(void*) * 2, m_section); 443 s->Address(m_offset, addr_size); 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, DumpStyleInvalid, addr_size); 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, DumpStyleInvalid, addr_size); 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 Target *target = exe_scope->CalculateTarget(); 620 if (target) 621 { 622 target->GetImages().ResolveSymbolContextForAddress (so_addr, 623 eSymbolContextEverything, 624 pointer_sc); 625 if (pointer_sc.function || pointer_sc.symbol) 626 { 627 s->PutCString(": "); 628 pointer_sc.DumpStopContext(s, process, so_addr, false); 629 } 630 } 631 } 632 } 633 } 634 break; 635 } 636 } 637 638 if (!showed_info) 639 { 640 if (module) 641 { 642 lldb_private::SymbolContext sc; 643 module->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc); 644 if (sc.function || sc.symbol) 645 { 646 bool show_stop_context = true; 647 if (sc.function == NULL && sc.symbol != NULL) 648 { 649 // If we have just a symbol make sure it is in the right section 650 if (sc.symbol->GetAddressRangePtr()) 651 { 652 if (sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetSection() != GetSection()) 653 show_stop_context = false; 654 } 655 } 656 if (show_stop_context) 657 { 658 // We have a function or a symbol from the same 659 // sections as this address. 660 sc.DumpStopContext(s, process, *this, true); 661 } 662 else 663 { 664 // We found a symbol but it was in a different 665 // section so it isn't the symbol we should be 666 // showing, just show the section name + offset 667 Dump (s, exe_scope, DumpStyleSectionNameOffset); 668 } 669 } 670 } 671 } 672 } 673 else 674 { 675 if (fallback_style != DumpStyleInvalid) 676 return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); 677 return false; 678 } 679 break; 680 681 case DumpStyleDetailedSymbolContext: 682 if (IsSectionOffset()) 683 { 684 lldb::AddressType addr_type = eAddressTypeLoad; 685 addr_t addr = GetLoadAddress (process); 686 if (addr == LLDB_INVALID_ADDRESS) 687 { 688 addr = GetFileAddress(); 689 addr_type = eAddressTypeFile; 690 } 691 692 lldb_private::Module *module = GetModule(); 693 if (module) 694 { 695 lldb_private::SymbolContext sc; 696 module->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc); 697 if (sc.function || sc.symbol) 698 { 699 if (sc.function == NULL && sc.symbol != NULL) 700 { 701 // If we have just a symbol make sure it is in the right section 702 if (sc.symbol->GetAddressRangePtr() && sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetSection() == GetSection()) 703 { 704 sc.GetDescription(s, eDescriptionLevelBrief, process); 705 break; 706 } 707 } 708 } 709 } 710 } 711 if (fallback_style != DumpStyleInvalid) 712 return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); 713 return false; 714 break; 715 } 716 717 return true; 718 } 719 720 //Stream& operator << (Stream& s, const Address& so_addr) 721 //{ 722 // so_addr.Dump(&s, Address::DumpStyleSectionNameOffset); 723 // return s; 724 //} 725 // 726 void 727 Address::CalculateSymbolContext (SymbolContext *sc) 728 { 729 sc->Clear(); 730 // Absolute addresses don't have enough information to reconstruct even their target. 731 if (m_section == NULL) 732 return; 733 734 if (m_section->GetModule()) 735 { 736 sc->module_sp = m_section->GetModule()->GetSP(); 737 if (sc->module_sp) 738 sc->module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextEverything, *sc); 739 } 740 } 741 742 void 743 Address::DumpSymbolContext (Stream *s) 744 { 745 SymbolContext sc; 746 CalculateSymbolContext (&sc); 747 sc.Dump (s, NULL); 748 } 749 750 void 751 Address::DumpDebug(Stream *s) const 752 { 753 *s << (void *)this << ": " << "Address"; 754 if (m_section != NULL) 755 { 756 *s << ", section = " << (void *)m_section << " (" << m_section->GetName() << "), offset = " << m_offset; 757 } 758 else 759 { 760 *s << ", vm_addr = " << m_offset; 761 } 762 s->EOL(); 763 } 764 765 int 766 Address::CompareFileAddress (const Address& a, const Address& b) 767 { 768 addr_t a_file_addr = a.GetFileAddress(); 769 addr_t b_file_addr = b.GetFileAddress(); 770 if (a_file_addr < b_file_addr) 771 return -1; 772 if (a_file_addr > b_file_addr) 773 return +1; 774 return 0; 775 } 776 777 778 int 779 Address::CompareLoadAddress (const Address& a, const Address& b, Process *process) 780 { 781 assert (process != NULL); 782 addr_t a_load_addr = a.GetLoadAddress (process); 783 addr_t b_load_addr = b.GetLoadAddress (process); 784 if (a_load_addr < b_load_addr) 785 return -1; 786 if (a_load_addr > b_load_addr) 787 return +1; 788 return 0; 789 } 790 791 int 792 Address::CompareModulePointerAndOffset (const Address& a, const Address& b) 793 { 794 Module *a_module = a.GetModule (); 795 Module *b_module = b.GetModule (); 796 if (a_module < b_module) 797 return -1; 798 if (a_module > b_module) 799 return +1; 800 // Modules are the same, just compare the file address since they should 801 // be unique 802 addr_t a_file_addr = a.GetFileAddress(); 803 addr_t b_file_addr = b.GetFileAddress(); 804 if (a_file_addr < b_file_addr) 805 return -1; 806 if (a_file_addr > b_file_addr) 807 return +1; 808 return 0; 809 } 810 811 812 size_t 813 Address::MemorySize () const 814 { 815 // Noting special for the memory size of a single Address object, 816 // it is just the size of itself. 817 return sizeof(Address); 818 } 819 820 821 /// The only comparisons that make sense are the load addresses 822 //bool 823 //lldb::operator< (const Address& lhs, const Address& rhs) 824 //{ 825 // lldb::addr_t lhs_addr = lhs.GetLoadAddress(); 826 // lldb::addr_t rhs_addr = rhs.GetLoadAddress(); 827 // 828 // if (lhs_addr == rhs_addr) 829 // { 830 // lhs_addr = lhs.GetFileAddress(); 831 // rhs_addr = rhs.GetFileAddress(); 832 // } 833 // return lhs_addr < rhs_addr; 834 //} 835 // 836 //bool 837 //lldb::operator<= (const Address& lhs, const Address& rhs) 838 //{ 839 // lldb::addr_t lhs_addr = lhs.GetLoadAddress(); 840 // lldb::addr_t rhs_addr = rhs.GetLoadAddress(); 841 // 842 // if (lhs_addr == rhs_addr) 843 // { 844 // lhs_addr = lhs.GetFileAddress(); 845 // rhs_addr = rhs.GetFileAddress(); 846 // } 847 // return lhs_addr <= rhs_addr; 848 //} 849 // 850 //bool 851 //lldb::operator> (const Address& lhs, const Address& rhs) 852 //{ 853 // lldb::addr_t lhs_addr = lhs.GetLoadAddress(); 854 // lldb::addr_t rhs_addr = rhs.GetLoadAddress(); 855 // 856 // if (lhs_addr == rhs_addr) 857 // { 858 // lhs_addr = lhs.GetFileAddress(); 859 // rhs_addr = rhs.GetFileAddress(); 860 // } 861 // return lhs_addr > rhs_addr; 862 //} 863 // 864 //bool 865 //lldb::operator>= (const Address& lhs, const Address& rhs) 866 //{ 867 // lldb::addr_t lhs_addr = lhs.GetLoadAddress(); 868 // lldb::addr_t rhs_addr = rhs.GetLoadAddress(); 869 // 870 // if (lhs_addr == rhs_addr) 871 // { 872 // lhs_addr = lhs.GetFileAddress(); 873 // rhs_addr = rhs.GetFileAddress(); 874 // } 875 // return lhs_addr >= rhs_addr; 876 //} 877 // 878 879 // The operator == checks for exact equality only (same section, same offset) 880 bool 881 lldb_private::operator== (const Address& a, const Address& rhs) 882 { 883 return a.GetSection() == rhs.GetSection() && 884 a.GetOffset() == rhs.GetOffset(); 885 } 886 // The operator != checks for exact inequality only (differing section, or 887 // different offset) 888 bool 889 lldb_private::operator!= (const Address& a, const Address& rhs) 890 { 891 return a.GetSection() != rhs.GetSection() || 892 a.GetOffset() != rhs.GetOffset(); 893 } 894 895 bool 896 Address::IsLinkedAddress () const 897 { 898 return m_section && m_section->GetLinkedSection(); 899 } 900 901 902 void 903 Address::ResolveLinkedAddress () 904 { 905 if (m_section) 906 { 907 const Section *linked_section = m_section->GetLinkedSection(); 908 if (linked_section) 909 { 910 m_offset += m_section->GetLinkedOffset(); 911 m_section = linked_section; 912 } 913 } 914 } 915