Path: blob/main/contrib/llvm-project/lldb/source/Core/Address.cpp
39587 views
//===-- Address.cpp -------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Core/Address.h"9#include "lldb/Core/Debugger.h"10#include "lldb/Core/Declaration.h"11#include "lldb/Core/DumpDataExtractor.h"12#include "lldb/Core/Module.h"13#include "lldb/Core/ModuleList.h"14#include "lldb/Core/Section.h"15#include "lldb/Symbol/Block.h"16#include "lldb/Symbol/LineEntry.h"17#include "lldb/Symbol/ObjectFile.h"18#include "lldb/Symbol/Symbol.h"19#include "lldb/Symbol/SymbolContext.h"20#include "lldb/Symbol/SymbolVendor.h"21#include "lldb/Symbol/Symtab.h"22#include "lldb/Symbol/Type.h"23#include "lldb/Symbol/Variable.h"24#include "lldb/Symbol/VariableList.h"25#include "lldb/Target/ABI.h"26#include "lldb/Target/ExecutionContext.h"27#include "lldb/Target/ExecutionContextScope.h"28#include "lldb/Target/Process.h"29#include "lldb/Target/SectionLoadList.h"30#include "lldb/Target/Target.h"31#include "lldb/Utility/AnsiTerminal.h"32#include "lldb/Utility/ConstString.h"33#include "lldb/Utility/DataExtractor.h"34#include "lldb/Utility/Endian.h"35#include "lldb/Utility/FileSpec.h"36#include "lldb/Utility/Status.h"37#include "lldb/Utility/Stream.h"38#include "lldb/Utility/StreamString.h"3940#include "llvm/ADT/StringRef.h"41#include "llvm/Support/Compiler.h"42#include "llvm/TargetParser/Triple.h"4344#include <cstdint>45#include <memory>46#include <vector>4748#include <cassert>49#include <cinttypes>50#include <cstring>5152namespace lldb_private {53class CompileUnit;54}55namespace lldb_private {56class Function;57}5859using namespace lldb;60using namespace lldb_private;6162static size_t ReadBytes(ExecutionContextScope *exe_scope,63const Address &address, void *dst, size_t dst_len) {64if (exe_scope == nullptr)65return 0;6667TargetSP target_sp(exe_scope->CalculateTarget());68if (target_sp) {69Status error;70bool force_live_memory = true;71return target_sp->ReadMemory(address, dst, dst_len, error,72force_live_memory);73}74return 0;75}7677static bool GetByteOrderAndAddressSize(ExecutionContextScope *exe_scope,78const Address &address,79ByteOrder &byte_order,80uint32_t &addr_size) {81byte_order = eByteOrderInvalid;82addr_size = 0;83if (exe_scope == nullptr)84return false;8586TargetSP target_sp(exe_scope->CalculateTarget());87if (target_sp) {88byte_order = target_sp->GetArchitecture().GetByteOrder();89addr_size = target_sp->GetArchitecture().GetAddressByteSize();90}9192if (byte_order == eByteOrderInvalid || addr_size == 0) {93ModuleSP module_sp(address.GetModule());94if (module_sp) {95byte_order = module_sp->GetArchitecture().GetByteOrder();96addr_size = module_sp->GetArchitecture().GetAddressByteSize();97}98}99return byte_order != eByteOrderInvalid && addr_size != 0;100}101102static uint64_t ReadUIntMax64(ExecutionContextScope *exe_scope,103const Address &address, uint32_t byte_size,104bool &success) {105uint64_t uval64 = 0;106if (exe_scope == nullptr || byte_size > sizeof(uint64_t)) {107success = false;108return 0;109}110uint64_t buf = 0;111112success = ReadBytes(exe_scope, address, &buf, byte_size) == byte_size;113if (success) {114ByteOrder byte_order = eByteOrderInvalid;115uint32_t addr_size = 0;116if (GetByteOrderAndAddressSize(exe_scope, address, byte_order, addr_size)) {117DataExtractor data(&buf, sizeof(buf), byte_order, addr_size);118lldb::offset_t offset = 0;119uval64 = data.GetU64(&offset);120} else121success = false;122}123return uval64;124}125126static bool ReadAddress(ExecutionContextScope *exe_scope,127const Address &address, uint32_t pointer_size,128Address &deref_so_addr) {129if (exe_scope == nullptr)130return false;131132bool success = false;133addr_t deref_addr = ReadUIntMax64(exe_scope, address, pointer_size, success);134if (success) {135ExecutionContext exe_ctx;136exe_scope->CalculateExecutionContext(exe_ctx);137// If we have any sections that are loaded, try and resolve using the138// section load list139Target *target = exe_ctx.GetTargetPtr();140if (target && !target->GetSectionLoadList().IsEmpty()) {141if (target->GetSectionLoadList().ResolveLoadAddress(deref_addr,142deref_so_addr))143return true;144} else {145// If we were not running, yet able to read an integer, we must have a146// module147ModuleSP module_sp(address.GetModule());148149assert(module_sp);150if (module_sp->ResolveFileAddress(deref_addr, deref_so_addr))151return true;152}153154// 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).157deref_so_addr.SetRawAddress(deref_addr);158return true;159}160return false;161}162163static bool DumpUInt(ExecutionContextScope *exe_scope, const Address &address,164uint32_t byte_size, Stream *strm) {165if (exe_scope == nullptr || byte_size == 0)166return false;167std::vector<uint8_t> buf(byte_size, 0);168169if (ReadBytes(exe_scope, address, &buf[0], buf.size()) == buf.size()) {170ByteOrder byte_order = eByteOrderInvalid;171uint32_t addr_size = 0;172if (GetByteOrderAndAddressSize(exe_scope, address, byte_order, addr_size)) {173DataExtractor data(&buf.front(), buf.size(), byte_order, addr_size);174175DumpDataExtractor(data, strm,1760, // Start offset in "data"177eFormatHex, // Print as characters178buf.size(), // Size of item1791, // Items count180UINT32_MAX, // num per line181LLDB_INVALID_ADDRESS, // base address1820, // bitfield bit size1830); // bitfield bit offset184185return true;186}187}188return false;189}190191static size_t ReadCStringFromMemory(ExecutionContextScope *exe_scope,192const Address &address, Stream *strm) {193if (exe_scope == nullptr)194return 0;195const size_t k_buf_len = 256;196char buf[k_buf_len + 1];197buf[k_buf_len] = '\0'; // NULL terminate198199// Byte order and address size don't matter for C string dumping..200DataExtractor data(buf, sizeof(buf), endian::InlHostByteOrder(), 4);201size_t total_len = 0;202size_t bytes_read;203Address curr_address(address);204strm->PutChar('"');205while ((bytes_read = ReadBytes(exe_scope, curr_address, buf, k_buf_len)) >2060) {207size_t len = strlen(buf);208if (len == 0)209break;210if (len > bytes_read)211len = bytes_read;212213DumpDataExtractor(data, strm,2140, // Start offset in "data"215eFormatChar, // Print as characters2161, // Size of item (1 byte for a char!)217len, // How many bytes to print?218UINT32_MAX, // num per line219LLDB_INVALID_ADDRESS, // base address2200, // bitfield bit size2212220); // bitfield bit offset223224total_len += bytes_read;225226if (len < k_buf_len)227break;228curr_address.SetOffset(curr_address.GetOffset() + bytes_read);229}230strm->PutChar('"');231return total_len;232}233234Address::Address(lldb::addr_t abs_addr) : m_section_wp(), m_offset(abs_addr) {}235236Address::Address(addr_t address, const SectionList *section_list)237: m_section_wp() {238ResolveAddressUsingFileSections(address, section_list);239}240241const Address &Address::operator=(const Address &rhs) {242if (this != &rhs) {243m_section_wp = rhs.m_section_wp;244m_offset = rhs.m_offset;245}246return *this;247}248249bool Address::ResolveAddressUsingFileSections(addr_t file_addr,250const SectionList *section_list) {251if (section_list) {252SectionSP section_sp(253section_list->FindSectionContainingFileAddress(file_addr));254m_section_wp = section_sp;255if (section_sp) {256assert(section_sp->ContainsFileAddress(file_addr));257m_offset = file_addr - section_sp->GetFileAddress();258return true; // Successfully transformed addr into a section offset259// address260}261}262m_offset = file_addr;263return false; // Failed to resolve this address to a section offset value264}265266/// if "addr_range_ptr" is not NULL, then fill in with the address range of the function.267bool Address::ResolveFunctionScope(SymbolContext &sym_ctx,268AddressRange *addr_range_ptr) {269constexpr SymbolContextItem resolve_scope =270eSymbolContextFunction | eSymbolContextSymbol;271272if (!(CalculateSymbolContext(&sym_ctx, resolve_scope) & resolve_scope)) {273if (addr_range_ptr)274addr_range_ptr->Clear();275return false;276}277278if (!addr_range_ptr)279return true;280281return sym_ctx.GetAddressRange(resolve_scope, 0, false, *addr_range_ptr);282}283284ModuleSP Address::GetModule() const {285lldb::ModuleSP module_sp;286SectionSP section_sp(GetSection());287if (section_sp)288module_sp = section_sp->GetModule();289return module_sp;290}291292addr_t Address::GetFileAddress() const {293SectionSP section_sp(GetSection());294if (section_sp) {295addr_t sect_file_addr = section_sp->GetFileAddress();296if (sect_file_addr == LLDB_INVALID_ADDRESS) {297// Section isn't resolved, we can't return a valid file address298return LLDB_INVALID_ADDRESS;299}300// We have a valid file range, so we can return the file based address by301// adding the file base address to our offset302return sect_file_addr + m_offset;303} else if (SectionWasDeletedPrivate()) {304// Used to have a valid section but it got deleted so the offset doesn't305// mean anything without the section306return LLDB_INVALID_ADDRESS;307}308// No section, we just return the offset since it is the value in this case309return m_offset;310}311312addr_t Address::GetLoadAddress(Target *target) const {313SectionSP section_sp(GetSection());314if (section_sp) {315if (target) {316addr_t sect_load_addr = section_sp->GetLoadBaseAddress(target);317318if (sect_load_addr != LLDB_INVALID_ADDRESS) {319// We have a valid file range, so we can return the file based address320// by adding the file base address to our offset321return sect_load_addr + m_offset;322}323}324} else if (SectionWasDeletedPrivate()) {325// Used to have a valid section but it got deleted so the offset doesn't326// mean anything without the section327return LLDB_INVALID_ADDRESS;328} else {329// We don't have a section so the offset is the load address330return m_offset;331}332// The section isn't resolved or an invalid target was passed in so we can't333// return a valid load address.334return LLDB_INVALID_ADDRESS;335}336337addr_t Address::GetCallableLoadAddress(Target *target, bool is_indirect) const {338addr_t code_addr = LLDB_INVALID_ADDRESS;339340if (is_indirect && target) {341ProcessSP processSP = target->GetProcessSP();342Status error;343if (processSP) {344code_addr = processSP->ResolveIndirectFunction(this, error);345if (!error.Success())346code_addr = LLDB_INVALID_ADDRESS;347}348} else {349code_addr = GetLoadAddress(target);350}351352if (code_addr == LLDB_INVALID_ADDRESS)353return code_addr;354355if (target)356return target->GetCallableLoadAddress(code_addr, GetAddressClass());357return code_addr;358}359360bool Address::SetCallableLoadAddress(lldb::addr_t load_addr, Target *target) {361if (SetLoadAddress(load_addr, target)) {362if (target)363m_offset = target->GetCallableLoadAddress(m_offset, GetAddressClass());364return true;365}366return false;367}368369addr_t Address::GetOpcodeLoadAddress(Target *target,370AddressClass addr_class) const {371addr_t code_addr = GetLoadAddress(target);372if (code_addr != LLDB_INVALID_ADDRESS) {373if (addr_class == AddressClass::eInvalid)374addr_class = GetAddressClass();375code_addr = target->GetOpcodeLoadAddress(code_addr, addr_class);376}377return code_addr;378}379380bool Address::SetOpcodeLoadAddress(lldb::addr_t load_addr, Target *target,381AddressClass addr_class,382bool allow_section_end) {383if (SetLoadAddress(load_addr, target, allow_section_end)) {384if (target) {385if (addr_class == AddressClass::eInvalid)386addr_class = GetAddressClass();387m_offset = target->GetOpcodeLoadAddress(m_offset, addr_class);388}389return true;390}391return false;392}393394bool Address::GetDescription(Stream &s, Target &target,395DescriptionLevel level) const {396assert(level == eDescriptionLevelBrief &&397"Non-brief descriptions not implemented");398LineEntry line_entry;399if (CalculateSymbolContextLineEntry(line_entry)) {400s.Printf(" (%s:%u:%u)", line_entry.GetFile().GetFilename().GetCString(),401line_entry.line, line_entry.column);402return true;403}404return false;405}406407bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,408DumpStyle fallback_style, uint32_t addr_size,409bool all_ranges,410std::optional<Stream::HighlightSettings> settings) const {411// If the section was nullptr, only load address is going to work unless we412// are trying to deref a pointer413SectionSP section_sp(GetSection());414if (!section_sp && style != DumpStyleResolvedPointerDescription)415style = DumpStyleLoadAddress;416417ExecutionContext exe_ctx(exe_scope);418Target *target = exe_ctx.GetTargetPtr();419// If addr_byte_size is UINT32_MAX, then determine the correct address byte420// size for the process or default to the size of addr_t421if (addr_size == UINT32_MAX) {422if (target)423addr_size = target->GetArchitecture().GetAddressByteSize();424else425addr_size = sizeof(addr_t);426}427428Address so_addr;429switch (style) {430case DumpStyleInvalid:431return false;432433case DumpStyleSectionNameOffset:434if (section_sp) {435section_sp->DumpName(s->AsRawOstream());436s->Printf(" + %" PRIu64, m_offset);437} else {438DumpAddress(s->AsRawOstream(), m_offset, addr_size);439}440break;441442case DumpStyleSectionPointerOffset:443s->Printf("(Section *)%p + ", static_cast<void *>(section_sp.get()));444DumpAddress(s->AsRawOstream(), m_offset, addr_size);445break;446447case DumpStyleModuleWithFileAddress:448if (section_sp) {449ModuleSP module_sp = section_sp->GetModule();450if (module_sp)451s->Printf("%s[", module_sp->GetFileSpec().GetFilename().AsCString(452"<Unknown>"));453else454s->Printf("%s[", "<Unknown>");455}456[[fallthrough]];457case DumpStyleFileAddress: {458addr_t file_addr = GetFileAddress();459if (file_addr == LLDB_INVALID_ADDRESS) {460if (fallback_style != DumpStyleInvalid)461return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);462return false;463}464DumpAddress(s->AsRawOstream(), file_addr, addr_size);465if (style == DumpStyleModuleWithFileAddress && section_sp)466s->PutChar(']');467} break;468469case DumpStyleLoadAddress: {470addr_t load_addr = GetLoadAddress(target);471472/*473* MIPS:474* Display address in compressed form for MIPS16 or microMIPS475* if the address belongs to AddressClass::eCodeAlternateISA.476*/477if (target) {478const llvm::Triple::ArchType llvm_arch =479target->GetArchitecture().GetMachine();480if (llvm_arch == llvm::Triple::mips ||481llvm_arch == llvm::Triple::mipsel ||482llvm_arch == llvm::Triple::mips64 ||483llvm_arch == llvm::Triple::mips64el)484load_addr = GetCallableLoadAddress(target);485}486487if (load_addr == LLDB_INVALID_ADDRESS) {488if (fallback_style != DumpStyleInvalid)489return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);490return false;491}492DumpAddress(s->AsRawOstream(), load_addr, addr_size);493} break;494495case DumpStyleResolvedDescription:496case DumpStyleResolvedDescriptionNoModule:497case DumpStyleResolvedDescriptionNoFunctionArguments:498case DumpStyleNoFunctionName:499if (IsSectionOffset()) {500uint32_t pointer_size = 4;501ModuleSP module_sp(GetModule());502if (target)503pointer_size = target->GetArchitecture().GetAddressByteSize();504else if (module_sp)505pointer_size = module_sp->GetArchitecture().GetAddressByteSize();506bool showed_info = false;507if (section_sp) {508SectionType sect_type = section_sp->GetType();509switch (sect_type) {510case eSectionTypeData:511if (module_sp) {512if (Symtab *symtab = module_sp->GetSymtab()) {513const addr_t file_Addr = GetFileAddress();514Symbol *symbol =515symtab->FindSymbolContainingFileAddress(file_Addr);516if (symbol) {517const char *symbol_name = symbol->GetName().AsCString();518if (symbol_name) {519s->PutCStringColorHighlighted(symbol_name, settings);520addr_t delta =521file_Addr - symbol->GetAddressRef().GetFileAddress();522if (delta)523s->Printf(" + %" PRIu64, delta);524showed_info = true;525}526}527}528}529break;530531case eSectionTypeDataCString:532// Read the C string from memory and display it533showed_info = true;534ReadCStringFromMemory(exe_scope, *this, s);535break;536537case eSectionTypeDataCStringPointers:538if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) {539#if VERBOSE_OUTPUT540s->PutCString("(char *)");541so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,542DumpStyleFileAddress);543s->PutCString(": ");544#endif545showed_info = true;546ReadCStringFromMemory(exe_scope, so_addr, s);547}548break;549550case eSectionTypeDataObjCMessageRefs:551if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) {552if (target && so_addr.IsSectionOffset()) {553SymbolContext func_sc;554target->GetImages().ResolveSymbolContextForAddress(555so_addr, eSymbolContextEverything, func_sc);556if (func_sc.function != nullptr || func_sc.symbol != nullptr) {557showed_info = true;558#if VERBOSE_OUTPUT559s->PutCString("(objc_msgref *) -> { (func*)");560so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,561DumpStyleFileAddress);562#else563s->PutCString("{ ");564#endif565Address cstr_addr(*this);566cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size);567func_sc.DumpStopContext(s, exe_scope, so_addr, true, true,568false, true, true);569if (ReadAddress(exe_scope, cstr_addr, pointer_size, so_addr)) {570#if VERBOSE_OUTPUT571s->PutCString("), (char *)");572so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,573DumpStyleFileAddress);574s->PutCString(" (");575#else576s->PutCString(", ");577#endif578ReadCStringFromMemory(exe_scope, so_addr, s);579}580#if VERBOSE_OUTPUT581s->PutCString(") }");582#else583s->PutCString(" }");584#endif585}586}587}588break;589590case eSectionTypeDataObjCCFStrings: {591Address cfstring_data_addr(*this);592cfstring_data_addr.SetOffset(cfstring_data_addr.GetOffset() +593(2 * pointer_size));594if (ReadAddress(exe_scope, cfstring_data_addr, pointer_size,595so_addr)) {596#if VERBOSE_OUTPUT597s->PutCString("(CFString *) ");598cfstring_data_addr.Dump(s, exe_scope, DumpStyleLoadAddress,599DumpStyleFileAddress);600s->PutCString(" -> @");601#else602s->PutChar('@');603#endif604if (so_addr.Dump(s, exe_scope, DumpStyleResolvedDescription))605showed_info = true;606}607} break;608609case eSectionTypeData4:610// Read the 4 byte data and display it611showed_info = true;612s->PutCString("(uint32_t) ");613DumpUInt(exe_scope, *this, 4, s);614break;615616case eSectionTypeData8:617// Read the 8 byte data and display it618showed_info = true;619s->PutCString("(uint64_t) ");620DumpUInt(exe_scope, *this, 8, s);621break;622623case eSectionTypeData16:624// Read the 16 byte data and display it625showed_info = true;626s->PutCString("(uint128_t) ");627DumpUInt(exe_scope, *this, 16, s);628break;629630case eSectionTypeDataPointers:631// Read the pointer data and display it632if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) {633s->PutCString("(void *)");634so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,635DumpStyleFileAddress);636637showed_info = true;638if (so_addr.IsSectionOffset()) {639SymbolContext pointer_sc;640if (target) {641target->GetImages().ResolveSymbolContextForAddress(642so_addr, eSymbolContextEverything, pointer_sc);643if (pointer_sc.function != nullptr ||644pointer_sc.symbol != nullptr) {645s->PutCString(": ");646pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false,647false, true, true, false,648settings);649}650}651}652}653break;654655default:656break;657}658}659660if (!showed_info) {661if (module_sp) {662SymbolContext sc;663module_sp->ResolveSymbolContextForAddress(664*this, eSymbolContextEverything, sc);665if (sc.function || sc.symbol) {666bool show_stop_context = true;667const bool show_module = (style == DumpStyleResolvedDescription);668const bool show_fullpaths = false;669const bool show_inlined_frames = true;670const bool show_function_arguments =671(style != DumpStyleResolvedDescriptionNoFunctionArguments);672const bool show_function_name = (style != DumpStyleNoFunctionName);673if (sc.function == nullptr && sc.symbol != nullptr) {674// If we have just a symbol make sure it is in the right section675if (sc.symbol->ValueIsAddress()) {676if (sc.symbol->GetAddressRef().GetSection() != GetSection()) {677// don't show the module if the symbol is a trampoline symbol678show_stop_context = false;679}680}681}682if (show_stop_context) {683// We have a function or a symbol from the same sections as this684// address.685sc.DumpStopContext(s, exe_scope, *this, show_fullpaths,686show_module, show_inlined_frames,687show_function_arguments, show_function_name,688false, settings);689} else {690// We found a symbol but it was in a different section so it691// isn't the symbol we should be showing, just show the section692// name + offset693Dump(s, exe_scope, DumpStyleSectionNameOffset, DumpStyleInvalid,694UINT32_MAX, false, settings);695}696}697}698}699} else {700if (fallback_style != DumpStyleInvalid)701return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size,702false, settings);703return false;704}705break;706707case DumpStyleDetailedSymbolContext:708if (IsSectionOffset()) {709ModuleSP module_sp(GetModule());710if (module_sp) {711SymbolContext sc;712module_sp->ResolveSymbolContextForAddress(713*this, eSymbolContextEverything | eSymbolContextVariable, sc);714if (sc.symbol) {715// If we have just a symbol make sure it is in the same section as716// our address. If it isn't, then we might have just found the last717// symbol that came before the address that we are looking up that718// has nothing to do with our address lookup.719if (sc.symbol->ValueIsAddress() &&720sc.symbol->GetAddressRef().GetSection() != GetSection())721sc.symbol = nullptr;722}723sc.GetDescription(s, eDescriptionLevelBrief, target, settings);724725if (sc.block) {726bool can_create = true;727bool get_parent_variables = true;728bool stop_if_block_is_inlined_function = false;729VariableList variable_list;730addr_t file_addr = GetFileAddress();731sc.block->AppendVariables(732can_create, get_parent_variables,733stop_if_block_is_inlined_function,734[&](Variable *var) {735return var && var->LocationIsValidForAddress(*this);736},737&variable_list);738ABISP abi =739ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());740for (const VariableSP &var_sp : variable_list) {741s->Indent();742s->Printf(" Variable: id = {0x%8.8" PRIx64 "}, name = \"%s\"",743var_sp->GetID(), var_sp->GetName().GetCString());744Type *type = var_sp->GetType();745if (type)746s->Printf(", type = \"%s\"", type->GetName().GetCString());747else748s->PutCString(", type = <unknown>");749s->PutCString(", valid ranges = ");750if (var_sp->GetScopeRange().IsEmpty())751s->PutCString("<block>");752else if (all_ranges) {753for (auto range : var_sp->GetScopeRange())754DumpAddressRange(s->AsRawOstream(), range.GetRangeBase(),755range.GetRangeEnd(), addr_size);756} else if (auto *range =757var_sp->GetScopeRange().FindEntryThatContains(758file_addr))759DumpAddressRange(s->AsRawOstream(), range->GetRangeBase(),760range->GetRangeEnd(), addr_size);761s->PutCString(", location = ");762var_sp->DumpLocations(s, all_ranges ? LLDB_INVALID_ADDRESS : *this);763s->PutCString(", decl = ");764var_sp->GetDeclaration().DumpStopContext(s, false);765s->EOL();766}767}768}769} else {770if (fallback_style != DumpStyleInvalid)771return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size,772false, settings);773return false;774}775break;776777case DumpStyleResolvedPointerDescription: {778Process *process = exe_ctx.GetProcessPtr();779if (process) {780addr_t load_addr = GetLoadAddress(target);781if (load_addr != LLDB_INVALID_ADDRESS) {782Status memory_error;783addr_t dereferenced_load_addr =784process->ReadPointerFromMemory(load_addr, memory_error);785if (dereferenced_load_addr != LLDB_INVALID_ADDRESS) {786Address dereferenced_addr;787if (dereferenced_addr.SetLoadAddress(dereferenced_load_addr,788target)) {789StreamString strm;790if (dereferenced_addr.Dump(&strm, exe_scope,791DumpStyleResolvedDescription,792DumpStyleInvalid, addr_size)) {793DumpAddress(s->AsRawOstream(), dereferenced_load_addr, addr_size,794" -> ", " ");795s->Write(strm.GetString().data(), strm.GetSize());796return true;797}798}799}800}801}802if (fallback_style != DumpStyleInvalid)803return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);804return false;805} break;806}807808return true;809}810811bool Address::SectionWasDeleted() const {812if (GetSection())813return false;814return SectionWasDeletedPrivate();815}816817bool Address::SectionWasDeletedPrivate() const {818lldb::SectionWP empty_section_wp;819820// If either call to "std::weak_ptr::owner_before(...) value returns true,821// this indicates that m_section_wp once contained (possibly still does) a822// reference to a valid shared pointer. This helps us know if we had a valid823// reference to a section which is now invalid because the module it was in824// was unloaded/deleted, or if the address doesn't have a valid reference to825// a section.826return empty_section_wp.owner_before(m_section_wp) ||827m_section_wp.owner_before(empty_section_wp);828}829830uint32_t831Address::CalculateSymbolContext(SymbolContext *sc,832SymbolContextItem resolve_scope) const {833sc->Clear(false);834// Absolute addresses don't have enough information to reconstruct even their835// target.836837SectionSP section_sp(GetSection());838if (section_sp) {839ModuleSP module_sp(section_sp->GetModule());840if (module_sp) {841sc->module_sp = module_sp;842if (sc->module_sp)843return sc->module_sp->ResolveSymbolContextForAddress(844*this, resolve_scope, *sc);845}846}847return 0;848}849850ModuleSP Address::CalculateSymbolContextModule() const {851SectionSP section_sp(GetSection());852if (section_sp)853return section_sp->GetModule();854return ModuleSP();855}856857CompileUnit *Address::CalculateSymbolContextCompileUnit() const {858SectionSP section_sp(GetSection());859if (section_sp) {860SymbolContext sc;861sc.module_sp = section_sp->GetModule();862if (sc.module_sp) {863sc.module_sp->ResolveSymbolContextForAddress(*this,864eSymbolContextCompUnit, sc);865return sc.comp_unit;866}867}868return nullptr;869}870871Function *Address::CalculateSymbolContextFunction() const {872SectionSP section_sp(GetSection());873if (section_sp) {874SymbolContext sc;875sc.module_sp = section_sp->GetModule();876if (sc.module_sp) {877sc.module_sp->ResolveSymbolContextForAddress(*this,878eSymbolContextFunction, sc);879return sc.function;880}881}882return nullptr;883}884885Block *Address::CalculateSymbolContextBlock() const {886SectionSP section_sp(GetSection());887if (section_sp) {888SymbolContext sc;889sc.module_sp = section_sp->GetModule();890if (sc.module_sp) {891sc.module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextBlock,892sc);893return sc.block;894}895}896return nullptr;897}898899Symbol *Address::CalculateSymbolContextSymbol() const {900SectionSP section_sp(GetSection());901if (section_sp) {902SymbolContext sc;903sc.module_sp = section_sp->GetModule();904if (sc.module_sp) {905sc.module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextSymbol,906sc);907return sc.symbol;908}909}910return nullptr;911}912913bool Address::CalculateSymbolContextLineEntry(LineEntry &line_entry) const {914SectionSP section_sp(GetSection());915if (section_sp) {916SymbolContext sc;917sc.module_sp = section_sp->GetModule();918if (sc.module_sp) {919sc.module_sp->ResolveSymbolContextForAddress(*this,920eSymbolContextLineEntry, sc);921if (sc.line_entry.IsValid()) {922line_entry = sc.line_entry;923return true;924}925}926}927line_entry.Clear();928return false;929}930931int Address::CompareFileAddress(const Address &a, const Address &b) {932addr_t a_file_addr = a.GetFileAddress();933addr_t b_file_addr = b.GetFileAddress();934if (a_file_addr < b_file_addr)935return -1;936if (a_file_addr > b_file_addr)937return +1;938return 0;939}940941int Address::CompareLoadAddress(const Address &a, const Address &b,942Target *target) {943assert(target != nullptr);944addr_t a_load_addr = a.GetLoadAddress(target);945addr_t b_load_addr = b.GetLoadAddress(target);946if (a_load_addr < b_load_addr)947return -1;948if (a_load_addr > b_load_addr)949return +1;950return 0;951}952953int Address::CompareModulePointerAndOffset(const Address &a, const Address &b) {954ModuleSP a_module_sp(a.GetModule());955ModuleSP b_module_sp(b.GetModule());956Module *a_module = a_module_sp.get();957Module *b_module = b_module_sp.get();958if (a_module < b_module)959return -1;960if (a_module > b_module)961return +1;962// Modules are the same, just compare the file address since they should be963// unique964addr_t a_file_addr = a.GetFileAddress();965addr_t b_file_addr = b.GetFileAddress();966if (a_file_addr < b_file_addr)967return -1;968if (a_file_addr > b_file_addr)969return +1;970return 0;971}972973size_t Address::MemorySize() const {974// Noting special for the memory size of a single Address object, it is just975// the size of itself.976return sizeof(Address);977}978979// NOTE: Be careful using this operator. It can correctly compare two980// addresses from the same Module correctly. It can't compare two addresses981// from different modules in any meaningful way, but it will compare the module982// pointers.983//984// To sum things up:985// - works great for addresses within the same module - it works for addresses986// across multiple modules, but don't expect the987// address results to make much sense988//989// This basically lets Address objects be used in ordered collection classes.990991bool lldb_private::operator<(const Address &lhs, const Address &rhs) {992ModuleSP lhs_module_sp(lhs.GetModule());993ModuleSP rhs_module_sp(rhs.GetModule());994Module *lhs_module = lhs_module_sp.get();995Module *rhs_module = rhs_module_sp.get();996if (lhs_module == rhs_module) {997// Addresses are in the same module, just compare the file addresses998return lhs.GetFileAddress() < rhs.GetFileAddress();999} else {1000// The addresses are from different modules, just use the module pointer1001// value to get consistent ordering1002return lhs_module < rhs_module;1003}1004}10051006bool lldb_private::operator>(const Address &lhs, const Address &rhs) {1007ModuleSP lhs_module_sp(lhs.GetModule());1008ModuleSP rhs_module_sp(rhs.GetModule());1009Module *lhs_module = lhs_module_sp.get();1010Module *rhs_module = rhs_module_sp.get();1011if (lhs_module == rhs_module) {1012// Addresses are in the same module, just compare the file addresses1013return lhs.GetFileAddress() > rhs.GetFileAddress();1014} else {1015// The addresses are from different modules, just use the module pointer1016// value to get consistent ordering1017return lhs_module > rhs_module;1018}1019}10201021// The operator == checks for exact equality only (same section, same offset)1022bool lldb_private::operator==(const Address &a, const Address &rhs) {1023return a.GetOffset() == rhs.GetOffset() && a.GetSection() == rhs.GetSection();1024}10251026// The operator != checks for exact inequality only (differing section, or1027// different offset)1028bool lldb_private::operator!=(const Address &a, const Address &rhs) {1029return a.GetOffset() != rhs.GetOffset() || a.GetSection() != rhs.GetSection();1030}10311032AddressClass Address::GetAddressClass() const {1033ModuleSP module_sp(GetModule());1034if (module_sp) {1035ObjectFile *obj_file = module_sp->GetObjectFile();1036if (obj_file) {1037// Give the symbol file a chance to add to the unified section list1038// and to the symtab.1039module_sp->GetSymtab();1040return obj_file->GetAddressClass(GetFileAddress());1041}1042}1043return AddressClass::eUnknown;1044}10451046bool Address::SetLoadAddress(lldb::addr_t load_addr, Target *target,1047bool allow_section_end) {1048if (target && target->GetSectionLoadList().ResolveLoadAddress(1049load_addr, *this, allow_section_end))1050return true;1051m_section_wp.reset();1052m_offset = load_addr;1053return false;1054}105510561057