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