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