1045 lines · cpp
1//===-- Address.cpp -------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Core/Address.h"10#include "lldb/Core/Debugger.h"11#include "lldb/Core/Declaration.h"12#include "lldb/Core/DumpDataExtractor.h"13#include "lldb/Core/Module.h"14#include "lldb/Core/ModuleList.h"15#include "lldb/Core/Section.h"16#include "lldb/Symbol/Block.h"17#include "lldb/Symbol/LineEntry.h"18#include "lldb/Symbol/ObjectFile.h"19#include "lldb/Symbol/Symbol.h"20#include "lldb/Symbol/SymbolContext.h"21#include "lldb/Symbol/SymbolVendor.h"22#include "lldb/Symbol/Symtab.h"23#include "lldb/Symbol/Type.h"24#include "lldb/Symbol/Variable.h"25#include "lldb/Symbol/VariableList.h"26#include "lldb/Target/ABI.h"27#include "lldb/Target/ExecutionContext.h"28#include "lldb/Target/ExecutionContextScope.h"29#include "lldb/Target/Process.h"30#include "lldb/Target/SectionLoadList.h"31#include "lldb/Target/Target.h"32#include "lldb/Utility/AnsiTerminal.h"33#include "lldb/Utility/ConstString.h"34#include "lldb/Utility/DataExtractor.h"35#include "lldb/Utility/Endian.h"36#include "lldb/Utility/FileSpec.h"37#include "lldb/Utility/Status.h"38#include "lldb/Utility/Stream.h"39#include "lldb/Utility/StreamString.h"40 41#include "llvm/ADT/StringRef.h"42#include "llvm/Support/Compiler.h"43#include "llvm/TargetParser/Triple.h"44 45#include <cstdint>46#include <memory>47#include <vector>48 49#include <cassert>50#include <cinttypes>51#include <cstring>52 53namespace lldb_private {54class CompileUnit;55}56namespace lldb_private {57class Function;58}59 60using namespace lldb;61using namespace lldb_private;62 63static size_t ReadBytes(ExecutionContextScope *exe_scope,64 const Address &address, void *dst, size_t dst_len) {65 if (exe_scope == nullptr)66 return 0;67 68 TargetSP target_sp(exe_scope->CalculateTarget());69 if (target_sp) {70 Status error;71 bool force_live_memory = true;72 return target_sp->ReadMemory(address, dst, dst_len, error,73 force_live_memory);74 }75 return 0;76}77 78static bool GetByteOrderAndAddressSize(ExecutionContextScope *exe_scope,79 const Address &address,80 ByteOrder &byte_order,81 uint32_t &addr_size) {82 byte_order = eByteOrderInvalid;83 addr_size = 0;84 if (exe_scope == nullptr)85 return false;86 87 TargetSP target_sp(exe_scope->CalculateTarget());88 if (target_sp) {89 byte_order = target_sp->GetArchitecture().GetByteOrder();90 addr_size = target_sp->GetArchitecture().GetAddressByteSize();91 }92 93 if (byte_order == eByteOrderInvalid || addr_size == 0) {94 ModuleSP module_sp(address.GetModule());95 if (module_sp) {96 byte_order = module_sp->GetArchitecture().GetByteOrder();97 addr_size = module_sp->GetArchitecture().GetAddressByteSize();98 }99 }100 return byte_order != eByteOrderInvalid && addr_size != 0;101}102 103static uint64_t ReadUIntMax64(ExecutionContextScope *exe_scope,104 const Address &address, uint32_t byte_size,105 bool &success) {106 uint64_t uval64 = 0;107 if (exe_scope == nullptr || byte_size > sizeof(uint64_t)) {108 success = false;109 return 0;110 }111 uint64_t buf = 0;112 113 success = ReadBytes(exe_scope, address, &buf, byte_size) == byte_size;114 if (success) {115 ByteOrder byte_order = eByteOrderInvalid;116 uint32_t addr_size = 0;117 if (GetByteOrderAndAddressSize(exe_scope, address, byte_order, addr_size)) {118 DataExtractor data(&buf, sizeof(buf), byte_order, addr_size);119 lldb::offset_t offset = 0;120 uval64 = data.GetU64(&offset);121 } else122 success = false;123 }124 return uval64;125}126 127static bool ReadAddress(ExecutionContextScope *exe_scope,128 const Address &address, uint32_t pointer_size,129 Address &deref_so_addr) {130 if (exe_scope == nullptr)131 return false;132 133 bool success = false;134 addr_t deref_addr = ReadUIntMax64(exe_scope, address, pointer_size, success);135 if (success) {136 ExecutionContext exe_ctx;137 exe_scope->CalculateExecutionContext(exe_ctx);138 // If we have any sections that are loaded, try and resolve using the139 // section load list140 Target *target = exe_ctx.GetTargetPtr();141 if (target && target->HasLoadedSections()) {142 if (target->ResolveLoadAddress(deref_addr, deref_so_addr))143 return true;144 } else {145 // If we were not running, yet able to read an integer, we must have a146 // module147 ModuleSP module_sp(address.GetModule());148 149 assert(module_sp);150 if (module_sp->ResolveFileAddress(deref_addr, deref_so_addr))151 return true;152 }153 154 // We couldn't make "deref_addr" into a section offset value, but we were155 // able to read the address, so we return a section offset address with no156 // section and "deref_addr" as the offset (address).157 deref_so_addr.SetRawAddress(deref_addr);158 return true;159 }160 return false;161}162 163static bool DumpUInt(ExecutionContextScope *exe_scope, const Address &address,164 uint32_t byte_size, Stream *strm) {165 if (exe_scope == nullptr || byte_size == 0)166 return false;167 std::vector<uint8_t> buf(byte_size, 0);168 169 if (ReadBytes(exe_scope, address, &buf[0], buf.size()) == buf.size()) {170 ByteOrder byte_order = eByteOrderInvalid;171 uint32_t addr_size = 0;172 if (GetByteOrderAndAddressSize(exe_scope, address, byte_order, addr_size)) {173 DataExtractor data(&buf.front(), buf.size(), byte_order, addr_size);174 175 DumpDataExtractor(data, strm,176 0, // Start offset in "data"177 eFormatHex, // Print as characters178 buf.size(), // Size of item179 1, // Items count180 UINT32_MAX, // num per line181 LLDB_INVALID_ADDRESS, // base address182 0, // bitfield bit size183 0); // bitfield bit offset184 185 return true;186 }187 }188 return false;189}190 191static size_t ReadCStringFromMemory(ExecutionContextScope *exe_scope,192 const Address &address, Stream *strm) {193 if (exe_scope == nullptr)194 return 0;195 const size_t k_buf_len = 256;196 char buf[k_buf_len + 1];197 buf[k_buf_len] = '\0'; // NULL terminate198 199 // Byte order and address size don't matter for C string dumping..200 DataExtractor data(buf, sizeof(buf), endian::InlHostByteOrder(), 4);201 size_t total_len = 0;202 size_t bytes_read;203 Address curr_address(address);204 strm->PutChar('"');205 while ((bytes_read = ReadBytes(exe_scope, curr_address, buf, k_buf_len)) >206 0) {207 size_t len = strlen(buf);208 if (len == 0)209 break;210 if (len > bytes_read)211 len = bytes_read;212 213 DumpDataExtractor(data, strm,214 0, // Start offset in "data"215 eFormatChar, // Print as characters216 1, // Size of item (1 byte for a char!)217 len, // How many bytes to print?218 UINT32_MAX, // num per line219 LLDB_INVALID_ADDRESS, // base address220 0, // bitfield bit size221 222 0); // bitfield bit offset223 224 total_len += bytes_read;225 226 if (len < k_buf_len)227 break;228 curr_address.SetOffset(curr_address.GetOffset() + bytes_read);229 }230 strm->PutChar('"');231 return total_len;232}233 234Address::Address(lldb::addr_t abs_addr) : m_section_wp(), m_offset(abs_addr) {}235 236Address::Address(addr_t address, const SectionList *section_list)237 : m_section_wp() {238 ResolveAddressUsingFileSections(address, section_list);239}240 241const Address &Address::operator=(const Address &rhs) {242 if (this != &rhs) {243 m_section_wp = rhs.m_section_wp;244 m_offset = rhs.m_offset;245 }246 return *this;247}248 249bool Address::ResolveAddressUsingFileSections(addr_t file_addr,250 const SectionList *section_list) {251 if (section_list) {252 SectionSP section_sp(253 section_list->FindSectionContainingFileAddress(file_addr));254 m_section_wp = section_sp;255 if (section_sp) {256 assert(section_sp->ContainsFileAddress(file_addr));257 m_offset = file_addr - section_sp->GetFileAddress();258 return true; // Successfully transformed addr into a section offset259 // address260 }261 }262 m_offset = file_addr;263 return false; // Failed to resolve this address to a section offset value264}265 266bool Address::ResolveFunctionScope(SymbolContext &sym_ctx) {267 constexpr SymbolContextItem resolve_scope =268 eSymbolContextFunction | eSymbolContextSymbol;269 270 return CalculateSymbolContext(&sym_ctx, resolve_scope) & resolve_scope;271}272 273ModuleSP Address::GetModule() const {274 lldb::ModuleSP module_sp;275 SectionSP section_sp(GetSection());276 if (section_sp)277 module_sp = section_sp->GetModule();278 return module_sp;279}280 281addr_t Address::GetFileAddress() const {282 SectionSP section_sp(GetSection());283 if (section_sp) {284 addr_t sect_file_addr = section_sp->GetFileAddress();285 if (sect_file_addr == LLDB_INVALID_ADDRESS) {286 // Section isn't resolved, we can't return a valid file address287 return LLDB_INVALID_ADDRESS;288 }289 // We have a valid file range, so we can return the file based address by290 // adding the file base address to our offset291 return sect_file_addr + m_offset;292 } else if (SectionWasDeletedPrivate()) {293 // Used to have a valid section but it got deleted so the offset doesn't294 // mean anything without the section295 return LLDB_INVALID_ADDRESS;296 }297 // No section, we just return the offset since it is the value in this case298 return m_offset;299}300 301addr_t Address::GetLoadAddress(Target *target) const {302 SectionSP section_sp(GetSection());303 if (section_sp) {304 if (target) {305 addr_t sect_load_addr = section_sp->GetLoadBaseAddress(target);306 307 if (sect_load_addr != LLDB_INVALID_ADDRESS) {308 // We have a valid file range, so we can return the file based address309 // by adding the file base address to our offset310 return sect_load_addr + m_offset;311 }312 }313 } else if (SectionWasDeletedPrivate()) {314 // Used to have a valid section but it got deleted so the offset doesn't315 // mean anything without the section316 return LLDB_INVALID_ADDRESS;317 } else {318 // We don't have a section so the offset is the load address319 return m_offset;320 }321 // The section isn't resolved or an invalid target was passed in so we can't322 // return a valid load address.323 return LLDB_INVALID_ADDRESS;324}325 326addr_t Address::GetCallableLoadAddress(Target *target, bool is_indirect) const {327 addr_t code_addr = LLDB_INVALID_ADDRESS;328 329 if (is_indirect && target) {330 ProcessSP processSP = target->GetProcessSP();331 Status error;332 if (processSP) {333 code_addr = processSP->ResolveIndirectFunction(this, error);334 if (!error.Success())335 code_addr = LLDB_INVALID_ADDRESS;336 }337 } else {338 code_addr = GetLoadAddress(target);339 }340 341 if (code_addr == LLDB_INVALID_ADDRESS)342 return code_addr;343 344 if (target)345 return target->GetCallableLoadAddress(code_addr, GetAddressClass());346 return code_addr;347}348 349bool Address::SetCallableLoadAddress(lldb::addr_t load_addr, Target *target) {350 if (SetLoadAddress(load_addr, target)) {351 if (target)352 m_offset = target->GetCallableLoadAddress(m_offset, GetAddressClass());353 return true;354 }355 return false;356}357 358addr_t Address::GetOpcodeLoadAddress(Target *target,359 AddressClass addr_class) const {360 addr_t code_addr = GetLoadAddress(target);361 if (code_addr != LLDB_INVALID_ADDRESS) {362 if (addr_class == AddressClass::eInvalid)363 addr_class = GetAddressClass();364 code_addr = target->GetOpcodeLoadAddress(code_addr, addr_class);365 }366 return code_addr;367}368 369bool Address::SetOpcodeLoadAddress(lldb::addr_t load_addr, Target *target,370 AddressClass addr_class,371 bool allow_section_end) {372 if (SetLoadAddress(load_addr, target, allow_section_end)) {373 if (target) {374 if (addr_class == AddressClass::eInvalid)375 addr_class = GetAddressClass();376 m_offset = target->GetOpcodeLoadAddress(m_offset, addr_class);377 }378 return true;379 }380 return false;381}382 383bool Address::GetDescription(Stream &s, Target &target,384 DescriptionLevel level) const {385 assert(level == eDescriptionLevelBrief &&386 "Non-brief descriptions not implemented");387 LineEntry line_entry;388 if (CalculateSymbolContextLineEntry(line_entry)) {389 s.Printf(" (%s:%u:%u)", line_entry.GetFile().GetFilename().GetCString(),390 line_entry.line, line_entry.column);391 return true;392 }393 return false;394}395 396bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,397 DumpStyle fallback_style, uint32_t addr_size,398 bool all_ranges,399 std::optional<Stream::HighlightSettings> settings) const {400 // If the section was nullptr, only load address is going to work unless we401 // are trying to deref a pointer402 SectionSP section_sp(GetSection());403 if (!section_sp && style != DumpStyleResolvedPointerDescription)404 style = DumpStyleLoadAddress;405 406 ExecutionContext exe_ctx(exe_scope);407 Target *target = exe_ctx.GetTargetPtr();408 // If addr_byte_size is UINT32_MAX, then determine the correct address byte409 // size for the process or default to the size of addr_t410 if (addr_size == UINT32_MAX) {411 if (target)412 addr_size = target->GetArchitecture().GetAddressByteSize();413 else414 addr_size = sizeof(addr_t);415 }416 417 Address so_addr;418 switch (style) {419 case DumpStyleInvalid:420 return false;421 422 case DumpStyleSectionNameOffset:423 if (section_sp) {424 section_sp->DumpName(s->AsRawOstream());425 s->Printf(" + %" PRIu64, m_offset);426 } else {427 DumpAddress(s->AsRawOstream(), m_offset, addr_size);428 }429 break;430 431 case DumpStyleSectionPointerOffset:432 s->Printf("(Section *)%p + ", static_cast<void *>(section_sp.get()));433 DumpAddress(s->AsRawOstream(), m_offset, addr_size);434 break;435 436 case DumpStyleModuleWithFileAddress:437 if (section_sp) {438 ModuleSP module_sp = section_sp->GetModule();439 if (module_sp)440 s->Printf("%s[", module_sp->GetFileSpec().GetFilename().AsCString(441 "<Unknown>"));442 else443 s->Printf("%s[", "<Unknown>");444 }445 [[fallthrough]];446 case DumpStyleFileAddress: {447 addr_t file_addr = GetFileAddress();448 if (file_addr == LLDB_INVALID_ADDRESS) {449 if (fallback_style != DumpStyleInvalid)450 return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);451 return false;452 }453 DumpAddress(s->AsRawOstream(), file_addr, addr_size);454 if (style == DumpStyleModuleWithFileAddress && section_sp)455 s->PutChar(']');456 } break;457 458 case DumpStyleLoadAddress: {459 addr_t load_addr = GetLoadAddress(target);460 461 /*462 * MIPS:463 * Display address in compressed form for MIPS16 or microMIPS464 * if the address belongs to AddressClass::eCodeAlternateISA.465 */466 if (target) {467 const llvm::Triple::ArchType llvm_arch =468 target->GetArchitecture().GetMachine();469 if (llvm_arch == llvm::Triple::mips ||470 llvm_arch == llvm::Triple::mipsel ||471 llvm_arch == llvm::Triple::mips64 ||472 llvm_arch == llvm::Triple::mips64el)473 load_addr = GetCallableLoadAddress(target);474 }475 476 if (load_addr == LLDB_INVALID_ADDRESS) {477 if (fallback_style != DumpStyleInvalid)478 return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);479 return false;480 }481 DumpAddress(s->AsRawOstream(), load_addr, addr_size);482 } break;483 484 case DumpStyleResolvedDescription:485 case DumpStyleResolvedDescriptionNoModule:486 case DumpStyleResolvedDescriptionNoFunctionArguments:487 case DumpStyleNoFunctionName:488 if (IsSectionOffset()) {489 uint32_t pointer_size = 4;490 ModuleSP module_sp(GetModule());491 if (target)492 pointer_size = target->GetArchitecture().GetAddressByteSize();493 else if (module_sp)494 pointer_size = module_sp->GetArchitecture().GetAddressByteSize();495 bool showed_info = false;496 if (section_sp) {497 SectionType sect_type = section_sp->GetType();498 switch (sect_type) {499 case eSectionTypeData:500 if (module_sp) {501 if (Symtab *symtab = module_sp->GetSymtab()) {502 const addr_t file_Addr = GetFileAddress();503 Symbol *symbol =504 symtab->FindSymbolContainingFileAddress(file_Addr);505 if (symbol) {506 const char *symbol_name = symbol->GetName().AsCString();507 if (symbol_name) {508 s->PutCStringColorHighlighted(symbol_name, settings);509 addr_t delta =510 file_Addr - symbol->GetAddressRef().GetFileAddress();511 if (delta)512 s->Printf(" + %" PRIu64, delta);513 showed_info = true;514 }515 }516 }517 }518 break;519 520 case eSectionTypeDataCString:521 // Read the C string from memory and display it522 showed_info = true;523 ReadCStringFromMemory(exe_scope, *this, s);524 break;525 526 case eSectionTypeDataCStringPointers:527 if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) {528#if VERBOSE_OUTPUT529 s->PutCString("(char *)");530 so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,531 DumpStyleFileAddress);532 s->PutCString(": ");533#endif534 showed_info = true;535 ReadCStringFromMemory(exe_scope, so_addr, s);536 }537 break;538 539 case eSectionTypeDataObjCMessageRefs:540 if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) {541 if (target && so_addr.IsSectionOffset()) {542 SymbolContext func_sc;543 target->GetImages().ResolveSymbolContextForAddress(544 so_addr, eSymbolContextEverything, func_sc);545 if (func_sc.function != nullptr || func_sc.symbol != nullptr) {546 showed_info = true;547#if VERBOSE_OUTPUT548 s->PutCString("(objc_msgref *) -> { (func*)");549 so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,550 DumpStyleFileAddress);551#else552 s->PutCString("{ ");553#endif554 Address cstr_addr(*this);555 cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size);556 func_sc.DumpStopContext(s, exe_scope, so_addr, true, true,557 false, true, true);558 if (ReadAddress(exe_scope, cstr_addr, pointer_size, so_addr)) {559#if VERBOSE_OUTPUT560 s->PutCString("), (char *)");561 so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,562 DumpStyleFileAddress);563 s->PutCString(" (");564#else565 s->PutCString(", ");566#endif567 ReadCStringFromMemory(exe_scope, so_addr, s);568 }569#if VERBOSE_OUTPUT570 s->PutCString(") }");571#else572 s->PutCString(" }");573#endif574 }575 }576 }577 break;578 579 case eSectionTypeDataObjCCFStrings: {580 Address cfstring_data_addr(*this);581 cfstring_data_addr.SetOffset(cfstring_data_addr.GetOffset() +582 (2 * pointer_size));583 if (ReadAddress(exe_scope, cfstring_data_addr, pointer_size,584 so_addr)) {585#if VERBOSE_OUTPUT586 s->PutCString("(CFString *) ");587 cfstring_data_addr.Dump(s, exe_scope, DumpStyleLoadAddress,588 DumpStyleFileAddress);589 s->PutCString(" -> @");590#else591 s->PutChar('@');592#endif593 if (so_addr.Dump(s, exe_scope, DumpStyleResolvedDescription))594 showed_info = true;595 }596 } break;597 598 case eSectionTypeData4:599 // Read the 4 byte data and display it600 showed_info = true;601 s->PutCString("(uint32_t) ");602 DumpUInt(exe_scope, *this, 4, s);603 break;604 605 case eSectionTypeData8:606 // Read the 8 byte data and display it607 showed_info = true;608 s->PutCString("(uint64_t) ");609 DumpUInt(exe_scope, *this, 8, s);610 break;611 612 case eSectionTypeData16:613 // Read the 16 byte data and display it614 showed_info = true;615 s->PutCString("(uint128_t) ");616 DumpUInt(exe_scope, *this, 16, s);617 break;618 619 case eSectionTypeDataPointers:620 // Read the pointer data and display it621 if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) {622 s->PutCString("(void *)");623 so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,624 DumpStyleFileAddress);625 626 showed_info = true;627 if (so_addr.IsSectionOffset()) {628 SymbolContext pointer_sc;629 if (target) {630 target->GetImages().ResolveSymbolContextForAddress(631 so_addr, eSymbolContextEverything, pointer_sc);632 if (pointer_sc.function != nullptr ||633 pointer_sc.symbol != nullptr) {634 s->PutCString(": ");635 pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false,636 false, true, true, false,637 settings);638 }639 }640 }641 }642 break;643 644 default:645 break;646 }647 }648 649 if (!showed_info) {650 if (module_sp) {651 SymbolContext sc;652 module_sp->ResolveSymbolContextForAddress(653 *this, eSymbolContextEverything, sc);654 if (sc.function || sc.symbol) {655 bool show_stop_context = true;656 const bool show_module = (style == DumpStyleResolvedDescription);657 const bool show_fullpaths = false;658 const bool show_inlined_frames = true;659 const bool show_function_arguments =660 (style != DumpStyleResolvedDescriptionNoFunctionArguments);661 const bool show_function_name = (style != DumpStyleNoFunctionName);662 if (sc.function == nullptr && sc.symbol != nullptr) {663 // If we have just a symbol make sure it is in the right section664 if (sc.symbol->ValueIsAddress()) {665 if (sc.symbol->GetAddressRef().GetSection() != GetSection()) {666 // don't show the module if the symbol is a trampoline symbol667 show_stop_context = false;668 }669 }670 }671 if (show_stop_context) {672 // We have a function or a symbol from the same sections as this673 // address.674 sc.DumpStopContext(s, exe_scope, *this, show_fullpaths,675 show_module, show_inlined_frames,676 show_function_arguments, show_function_name,677 false, settings);678 } else {679 // We found a symbol but it was in a different section so it680 // isn't the symbol we should be showing, just show the section681 // name + offset682 Dump(s, exe_scope, DumpStyleSectionNameOffset, DumpStyleInvalid,683 UINT32_MAX, false, settings);684 }685 }686 }687 }688 } else {689 if (fallback_style != DumpStyleInvalid)690 return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size,691 false, settings);692 return false;693 }694 break;695 696 case DumpStyleDetailedSymbolContext:697 if (IsSectionOffset()) {698 ModuleSP module_sp(GetModule());699 if (module_sp) {700 SymbolContext sc;701 module_sp->ResolveSymbolContextForAddress(702 *this, eSymbolContextEverything | eSymbolContextVariable, sc);703 if (sc.symbol) {704 // If we have just a symbol make sure it is in the same section as705 // our address. If it isn't, then we might have just found the last706 // symbol that came before the address that we are looking up that707 // has nothing to do with our address lookup.708 if (sc.symbol->ValueIsAddress() &&709 sc.symbol->GetAddressRef().GetSection() != GetSection())710 sc.symbol = nullptr;711 }712 sc.GetDescription(s, eDescriptionLevelBrief, target, settings);713 714 if (sc.block) {715 bool can_create = true;716 bool get_parent_variables = true;717 bool stop_if_block_is_inlined_function = false;718 VariableList variable_list;719 addr_t file_addr = GetFileAddress();720 sc.block->AppendVariables(721 can_create, get_parent_variables,722 stop_if_block_is_inlined_function,723 [&](Variable *var) {724 return var && var->LocationIsValidForAddress(*this);725 },726 &variable_list);727 ABISP abi =728 ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());729 for (const VariableSP &var_sp : variable_list) {730 s->Indent();731 s->Printf(" Variable: id = {0x%8.8" PRIx64 "}, name = \"%s\"",732 var_sp->GetID(), var_sp->GetName().GetCString());733 Type *type = var_sp->GetType();734 if (type)735 s->Printf(", type = \"%s\"", type->GetName().GetCString());736 else737 s->PutCString(", type = <unknown>");738 s->PutCString(", valid ranges = ");739 if (var_sp->GetScopeRange().IsEmpty())740 s->PutCString("<block>");741 else if (all_ranges) {742 for (auto range : var_sp->GetScopeRange())743 DumpAddressRange(s->AsRawOstream(), range.GetRangeBase(),744 range.GetRangeEnd(), addr_size);745 } else if (auto *range =746 var_sp->GetScopeRange().FindEntryThatContains(747 file_addr))748 DumpAddressRange(s->AsRawOstream(), range->GetRangeBase(),749 range->GetRangeEnd(), addr_size);750 s->PutCString(", location = ");751 var_sp->DumpLocations(s, all_ranges ? LLDB_INVALID_ADDRESS : *this);752 s->PutCString(", decl = ");753 var_sp->GetDeclaration().DumpStopContext(s, false);754 s->EOL();755 }756 }757 }758 } else {759 if (fallback_style != DumpStyleInvalid)760 return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size,761 false, settings);762 return false;763 }764 break;765 766 case DumpStyleResolvedPointerDescription: {767 Process *process = exe_ctx.GetProcessPtr();768 if (process) {769 addr_t load_addr = GetLoadAddress(target);770 if (load_addr != LLDB_INVALID_ADDRESS) {771 Status memory_error;772 addr_t dereferenced_load_addr =773 process->ReadPointerFromMemory(load_addr, memory_error);774 if (dereferenced_load_addr != LLDB_INVALID_ADDRESS) {775 Address dereferenced_addr;776 if (dereferenced_addr.SetLoadAddress(dereferenced_load_addr,777 target)) {778 StreamString strm;779 if (dereferenced_addr.Dump(&strm, exe_scope,780 DumpStyleResolvedDescription,781 DumpStyleInvalid, addr_size)) {782 DumpAddress(s->AsRawOstream(), dereferenced_load_addr, addr_size,783 " -> ", " ");784 s->Write(strm.GetString().data(), strm.GetSize());785 return true;786 }787 }788 }789 }790 }791 if (fallback_style != DumpStyleInvalid)792 return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);793 return false;794 } break;795 }796 797 return true;798}799 800bool Address::SectionWasDeleted() const {801 if (GetSection())802 return false;803 return SectionWasDeletedPrivate();804}805 806bool Address::SectionWasDeletedPrivate() const {807 lldb::SectionWP empty_section_wp;808 809 // If either call to "std::weak_ptr::owner_before(...) value returns true,810 // this indicates that m_section_wp once contained (possibly still does) a811 // reference to a valid shared pointer. This helps us know if we had a valid812 // reference to a section which is now invalid because the module it was in813 // was unloaded/deleted, or if the address doesn't have a valid reference to814 // a section.815 return empty_section_wp.owner_before(m_section_wp) ||816 m_section_wp.owner_before(empty_section_wp);817}818 819uint32_t820Address::CalculateSymbolContext(SymbolContext *sc,821 SymbolContextItem resolve_scope) const {822 sc->Clear(false);823 // Absolute addresses don't have enough information to reconstruct even their824 // target.825 826 SectionSP section_sp(GetSection());827 if (section_sp) {828 ModuleSP module_sp(section_sp->GetModule());829 if (module_sp) {830 sc->module_sp = module_sp;831 if (sc->module_sp)832 return sc->module_sp->ResolveSymbolContextForAddress(833 *this, resolve_scope, *sc);834 }835 }836 return 0;837}838 839ModuleSP Address::CalculateSymbolContextModule() const {840 SectionSP section_sp(GetSection());841 if (section_sp)842 return section_sp->GetModule();843 return ModuleSP();844}845 846CompileUnit *Address::CalculateSymbolContextCompileUnit() const {847 SectionSP section_sp(GetSection());848 if (section_sp) {849 SymbolContext sc;850 sc.module_sp = section_sp->GetModule();851 if (sc.module_sp) {852 sc.module_sp->ResolveSymbolContextForAddress(*this,853 eSymbolContextCompUnit, sc);854 return sc.comp_unit;855 }856 }857 return nullptr;858}859 860Function *Address::CalculateSymbolContextFunction() const {861 SectionSP section_sp(GetSection());862 if (section_sp) {863 SymbolContext sc;864 sc.module_sp = section_sp->GetModule();865 if (sc.module_sp) {866 sc.module_sp->ResolveSymbolContextForAddress(*this,867 eSymbolContextFunction, sc);868 return sc.function;869 }870 }871 return nullptr;872}873 874Block *Address::CalculateSymbolContextBlock() const {875 SectionSP section_sp(GetSection());876 if (section_sp) {877 SymbolContext sc;878 sc.module_sp = section_sp->GetModule();879 if (sc.module_sp) {880 sc.module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextBlock,881 sc);882 return sc.block;883 }884 }885 return nullptr;886}887 888Symbol *Address::CalculateSymbolContextSymbol() const {889 SectionSP section_sp(GetSection());890 if (section_sp) {891 SymbolContext sc;892 sc.module_sp = section_sp->GetModule();893 if (sc.module_sp) {894 sc.module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextSymbol,895 sc);896 return sc.symbol;897 }898 }899 return nullptr;900}901 902bool Address::CalculateSymbolContextLineEntry(LineEntry &line_entry) const {903 SectionSP section_sp(GetSection());904 if (section_sp) {905 SymbolContext sc;906 sc.module_sp = section_sp->GetModule();907 if (sc.module_sp) {908 sc.module_sp->ResolveSymbolContextForAddress(*this,909 eSymbolContextLineEntry, sc);910 if (sc.line_entry.IsValid()) {911 line_entry = sc.line_entry;912 return true;913 }914 }915 }916 line_entry.Clear();917 return false;918}919 920int Address::CompareFileAddress(const Address &a, const Address &b) {921 addr_t a_file_addr = a.GetFileAddress();922 addr_t b_file_addr = b.GetFileAddress();923 if (a_file_addr < b_file_addr)924 return -1;925 if (a_file_addr > b_file_addr)926 return +1;927 return 0;928}929 930int Address::CompareLoadAddress(const Address &a, const Address &b,931 Target *target) {932 assert(target != nullptr);933 addr_t a_load_addr = a.GetLoadAddress(target);934 addr_t b_load_addr = b.GetLoadAddress(target);935 if (a_load_addr < b_load_addr)936 return -1;937 if (a_load_addr > b_load_addr)938 return +1;939 return 0;940}941 942int Address::CompareModulePointerAndOffset(const Address &a, const Address &b) {943 ModuleSP a_module_sp(a.GetModule());944 ModuleSP b_module_sp(b.GetModule());945 Module *a_module = a_module_sp.get();946 Module *b_module = b_module_sp.get();947 if (a_module < b_module)948 return -1;949 if (a_module > b_module)950 return +1;951 // Modules are the same, just compare the file address since they should be952 // unique953 addr_t a_file_addr = a.GetFileAddress();954 addr_t b_file_addr = b.GetFileAddress();955 if (a_file_addr < b_file_addr)956 return -1;957 if (a_file_addr > b_file_addr)958 return +1;959 return 0;960}961 962size_t Address::MemorySize() const {963 // Noting special for the memory size of a single Address object, it is just964 // the size of itself.965 return sizeof(Address);966}967 968// NOTE: Be careful using this operator. It can correctly compare two969// addresses from the same Module correctly. It can't compare two addresses970// from different modules in any meaningful way, but it will compare the module971// pointers.972//973// To sum things up:974// - works great for addresses within the same module - it works for addresses975// across multiple modules, but don't expect the976// address results to make much sense977//978// This basically lets Address objects be used in ordered collection classes.979 980bool lldb_private::operator<(const Address &lhs, const Address &rhs) {981 ModuleSP lhs_module_sp(lhs.GetModule());982 ModuleSP rhs_module_sp(rhs.GetModule());983 Module *lhs_module = lhs_module_sp.get();984 Module *rhs_module = rhs_module_sp.get();985 if (lhs_module == rhs_module) {986 // Addresses are in the same module, just compare the file addresses987 return lhs.GetFileAddress() < rhs.GetFileAddress();988 } else {989 // The addresses are from different modules, just use the module pointer990 // value to get consistent ordering991 return lhs_module < rhs_module;992 }993}994 995bool lldb_private::operator>(const Address &lhs, const Address &rhs) {996 ModuleSP lhs_module_sp(lhs.GetModule());997 ModuleSP rhs_module_sp(rhs.GetModule());998 Module *lhs_module = lhs_module_sp.get();999 Module *rhs_module = rhs_module_sp.get();1000 if (lhs_module == rhs_module) {1001 // Addresses are in the same module, just compare the file addresses1002 return lhs.GetFileAddress() > rhs.GetFileAddress();1003 } else {1004 // The addresses are from different modules, just use the module pointer1005 // value to get consistent ordering1006 return lhs_module > rhs_module;1007 }1008}1009 1010// The operator == checks for exact equality only (same section, same offset)1011bool lldb_private::operator==(const Address &a, const Address &rhs) {1012 return a.GetOffset() == rhs.GetOffset() && a.GetSection() == rhs.GetSection();1013}1014 1015// The operator != checks for exact inequality only (differing section, or1016// different offset)1017bool lldb_private::operator!=(const Address &a, const Address &rhs) {1018 return a.GetOffset() != rhs.GetOffset() || a.GetSection() != rhs.GetSection();1019}1020 1021AddressClass Address::GetAddressClass() const {1022 ModuleSP module_sp(GetModule());1023 if (module_sp) {1024 ObjectFile *obj_file = module_sp->GetObjectFile();1025 if (obj_file) {1026 // Give the symbol file a chance to add to the unified section list1027 // and to the symtab.1028 module_sp->GetSymtab();1029 return obj_file->GetAddressClass(GetFileAddress());1030 }1031 }1032 return AddressClass::eUnknown;1033}1034 1035bool Address::SetLoadAddress(lldb::addr_t load_addr, Target *target,1036 bool allow_section_end) {1037 if (target && target->ResolveLoadAddress(load_addr, *this,1038 SectionLoadHistory::eStopIDNow,1039 allow_section_end))1040 return true;1041 m_section_wp.reset();1042 m_offset = load_addr;1043 return false;1044}1045