1dda28197Spatrick //===-- Address.cpp -------------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Core/Address.h"
10be691f3bSpatrick #include "lldb/Core/Declaration.h"
11061da546Spatrick #include "lldb/Core/DumpDataExtractor.h"
12061da546Spatrick #include "lldb/Core/Module.h"
13061da546Spatrick #include "lldb/Core/ModuleList.h"
14061da546Spatrick #include "lldb/Core/Section.h"
15061da546Spatrick #include "lldb/Symbol/Block.h"
16061da546Spatrick #include "lldb/Symbol/LineEntry.h"
17061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
18061da546Spatrick #include "lldb/Symbol/Symbol.h"
19061da546Spatrick #include "lldb/Symbol/SymbolContext.h"
20061da546Spatrick #include "lldb/Symbol/SymbolVendor.h"
21061da546Spatrick #include "lldb/Symbol/Symtab.h"
22061da546Spatrick #include "lldb/Symbol/Type.h"
23061da546Spatrick #include "lldb/Symbol/Variable.h"
24061da546Spatrick #include "lldb/Symbol/VariableList.h"
25*f6aab3d8Srobert #include "lldb/Target/ABI.h"
26061da546Spatrick #include "lldb/Target/ExecutionContext.h"
27061da546Spatrick #include "lldb/Target/ExecutionContextScope.h"
28061da546Spatrick #include "lldb/Target/Process.h"
29061da546Spatrick #include "lldb/Target/SectionLoadList.h"
30061da546Spatrick #include "lldb/Target/Target.h"
31061da546Spatrick #include "lldb/Utility/ConstString.h"
32061da546Spatrick #include "lldb/Utility/DataExtractor.h"
33061da546Spatrick #include "lldb/Utility/Endian.h"
34061da546Spatrick #include "lldb/Utility/FileSpec.h"
35061da546Spatrick #include "lldb/Utility/Status.h"
36061da546Spatrick #include "lldb/Utility/Stream.h"
37061da546Spatrick #include "lldb/Utility/StreamString.h"
38061da546Spatrick
39061da546Spatrick #include "llvm/ADT/StringRef.h"
40061da546Spatrick #include "llvm/ADT/Triple.h"
41061da546Spatrick #include "llvm/Support/Compiler.h"
42061da546Spatrick
43061da546Spatrick #include <cstdint>
44061da546Spatrick #include <memory>
45061da546Spatrick #include <vector>
46061da546Spatrick
47be691f3bSpatrick #include <cassert>
48be691f3bSpatrick #include <cinttypes>
49be691f3bSpatrick #include <cstring>
50061da546Spatrick
51061da546Spatrick namespace lldb_private {
52061da546Spatrick class CompileUnit;
53061da546Spatrick }
54061da546Spatrick namespace lldb_private {
55061da546Spatrick class Function;
56061da546Spatrick }
57061da546Spatrick
58061da546Spatrick using namespace lldb;
59061da546Spatrick using namespace lldb_private;
60061da546Spatrick
ReadBytes(ExecutionContextScope * exe_scope,const Address & address,void * dst,size_t dst_len)61061da546Spatrick static size_t ReadBytes(ExecutionContextScope *exe_scope,
62061da546Spatrick const Address &address, void *dst, size_t dst_len) {
63061da546Spatrick if (exe_scope == nullptr)
64061da546Spatrick return 0;
65061da546Spatrick
66061da546Spatrick TargetSP target_sp(exe_scope->CalculateTarget());
67061da546Spatrick if (target_sp) {
68061da546Spatrick Status error;
69be691f3bSpatrick bool force_live_memory = true;
70be691f3bSpatrick return target_sp->ReadMemory(address, dst, dst_len, error,
71be691f3bSpatrick force_live_memory);
72061da546Spatrick }
73061da546Spatrick return 0;
74061da546Spatrick }
75061da546Spatrick
GetByteOrderAndAddressSize(ExecutionContextScope * exe_scope,const Address & address,ByteOrder & byte_order,uint32_t & addr_size)76061da546Spatrick static bool GetByteOrderAndAddressSize(ExecutionContextScope *exe_scope,
77061da546Spatrick const Address &address,
78061da546Spatrick ByteOrder &byte_order,
79061da546Spatrick uint32_t &addr_size) {
80061da546Spatrick byte_order = eByteOrderInvalid;
81061da546Spatrick addr_size = 0;
82061da546Spatrick if (exe_scope == nullptr)
83061da546Spatrick return false;
84061da546Spatrick
85061da546Spatrick TargetSP target_sp(exe_scope->CalculateTarget());
86061da546Spatrick if (target_sp) {
87061da546Spatrick byte_order = target_sp->GetArchitecture().GetByteOrder();
88061da546Spatrick addr_size = target_sp->GetArchitecture().GetAddressByteSize();
89061da546Spatrick }
90061da546Spatrick
91061da546Spatrick if (byte_order == eByteOrderInvalid || addr_size == 0) {
92061da546Spatrick ModuleSP module_sp(address.GetModule());
93061da546Spatrick if (module_sp) {
94061da546Spatrick byte_order = module_sp->GetArchitecture().GetByteOrder();
95061da546Spatrick addr_size = module_sp->GetArchitecture().GetAddressByteSize();
96061da546Spatrick }
97061da546Spatrick }
98061da546Spatrick return byte_order != eByteOrderInvalid && addr_size != 0;
99061da546Spatrick }
100061da546Spatrick
ReadUIntMax64(ExecutionContextScope * exe_scope,const Address & address,uint32_t byte_size,bool & success)101061da546Spatrick static uint64_t ReadUIntMax64(ExecutionContextScope *exe_scope,
102061da546Spatrick const Address &address, uint32_t byte_size,
103061da546Spatrick bool &success) {
104061da546Spatrick uint64_t uval64 = 0;
105061da546Spatrick if (exe_scope == nullptr || byte_size > sizeof(uint64_t)) {
106061da546Spatrick success = false;
107061da546Spatrick return 0;
108061da546Spatrick }
109061da546Spatrick uint64_t buf = 0;
110061da546Spatrick
111061da546Spatrick success = ReadBytes(exe_scope, address, &buf, byte_size) == byte_size;
112061da546Spatrick if (success) {
113061da546Spatrick ByteOrder byte_order = eByteOrderInvalid;
114061da546Spatrick uint32_t addr_size = 0;
115061da546Spatrick if (GetByteOrderAndAddressSize(exe_scope, address, byte_order, addr_size)) {
116061da546Spatrick DataExtractor data(&buf, sizeof(buf), byte_order, addr_size);
117061da546Spatrick lldb::offset_t offset = 0;
118061da546Spatrick uval64 = data.GetU64(&offset);
119061da546Spatrick } else
120061da546Spatrick success = false;
121061da546Spatrick }
122061da546Spatrick return uval64;
123061da546Spatrick }
124061da546Spatrick
ReadAddress(ExecutionContextScope * exe_scope,const Address & address,uint32_t pointer_size,Address & deref_so_addr)125061da546Spatrick static bool ReadAddress(ExecutionContextScope *exe_scope,
126061da546Spatrick const Address &address, uint32_t pointer_size,
127061da546Spatrick Address &deref_so_addr) {
128061da546Spatrick if (exe_scope == nullptr)
129061da546Spatrick return false;
130061da546Spatrick
131061da546Spatrick bool success = false;
132061da546Spatrick addr_t deref_addr = ReadUIntMax64(exe_scope, address, pointer_size, success);
133061da546Spatrick if (success) {
134061da546Spatrick ExecutionContext exe_ctx;
135061da546Spatrick exe_scope->CalculateExecutionContext(exe_ctx);
136061da546Spatrick // If we have any sections that are loaded, try and resolve using the
137061da546Spatrick // section load list
138061da546Spatrick Target *target = exe_ctx.GetTargetPtr();
139061da546Spatrick if (target && !target->GetSectionLoadList().IsEmpty()) {
140061da546Spatrick if (target->GetSectionLoadList().ResolveLoadAddress(deref_addr,
141061da546Spatrick deref_so_addr))
142061da546Spatrick return true;
143061da546Spatrick } else {
144061da546Spatrick // If we were not running, yet able to read an integer, we must have a
145061da546Spatrick // module
146061da546Spatrick ModuleSP module_sp(address.GetModule());
147061da546Spatrick
148061da546Spatrick assert(module_sp);
149061da546Spatrick if (module_sp->ResolveFileAddress(deref_addr, deref_so_addr))
150061da546Spatrick return true;
151061da546Spatrick }
152061da546Spatrick
153061da546Spatrick // We couldn't make "deref_addr" into a section offset value, but we were
154061da546Spatrick // able to read the address, so we return a section offset address with no
155061da546Spatrick // section and "deref_addr" as the offset (address).
156061da546Spatrick deref_so_addr.SetRawAddress(deref_addr);
157061da546Spatrick return true;
158061da546Spatrick }
159061da546Spatrick return false;
160061da546Spatrick }
161061da546Spatrick
DumpUInt(ExecutionContextScope * exe_scope,const Address & address,uint32_t byte_size,Stream * strm)162061da546Spatrick static bool DumpUInt(ExecutionContextScope *exe_scope, const Address &address,
163061da546Spatrick uint32_t byte_size, Stream *strm) {
164061da546Spatrick if (exe_scope == nullptr || byte_size == 0)
165061da546Spatrick return false;
166061da546Spatrick std::vector<uint8_t> buf(byte_size, 0);
167061da546Spatrick
168061da546Spatrick if (ReadBytes(exe_scope, address, &buf[0], buf.size()) == buf.size()) {
169061da546Spatrick ByteOrder byte_order = eByteOrderInvalid;
170061da546Spatrick uint32_t addr_size = 0;
171061da546Spatrick if (GetByteOrderAndAddressSize(exe_scope, address, byte_order, addr_size)) {
172061da546Spatrick DataExtractor data(&buf.front(), buf.size(), byte_order, addr_size);
173061da546Spatrick
174061da546Spatrick DumpDataExtractor(data, strm,
175061da546Spatrick 0, // Start offset in "data"
176061da546Spatrick eFormatHex, // Print as characters
177061da546Spatrick buf.size(), // Size of item
178061da546Spatrick 1, // Items count
179061da546Spatrick UINT32_MAX, // num per line
180061da546Spatrick LLDB_INVALID_ADDRESS, // base address
181061da546Spatrick 0, // bitfield bit size
182061da546Spatrick 0); // bitfield bit offset
183061da546Spatrick
184061da546Spatrick return true;
185061da546Spatrick }
186061da546Spatrick }
187061da546Spatrick return false;
188061da546Spatrick }
189061da546Spatrick
ReadCStringFromMemory(ExecutionContextScope * exe_scope,const Address & address,Stream * strm)190061da546Spatrick static size_t ReadCStringFromMemory(ExecutionContextScope *exe_scope,
191061da546Spatrick const Address &address, Stream *strm) {
192061da546Spatrick if (exe_scope == nullptr)
193061da546Spatrick return 0;
194061da546Spatrick const size_t k_buf_len = 256;
195061da546Spatrick char buf[k_buf_len + 1];
196061da546Spatrick buf[k_buf_len] = '\0'; // NULL terminate
197061da546Spatrick
198061da546Spatrick // Byte order and address size don't matter for C string dumping..
199061da546Spatrick DataExtractor data(buf, sizeof(buf), endian::InlHostByteOrder(), 4);
200061da546Spatrick size_t total_len = 0;
201061da546Spatrick size_t bytes_read;
202061da546Spatrick Address curr_address(address);
203061da546Spatrick strm->PutChar('"');
204061da546Spatrick while ((bytes_read = ReadBytes(exe_scope, curr_address, buf, k_buf_len)) >
205061da546Spatrick 0) {
206061da546Spatrick size_t len = strlen(buf);
207061da546Spatrick if (len == 0)
208061da546Spatrick break;
209061da546Spatrick if (len > bytes_read)
210061da546Spatrick len = bytes_read;
211061da546Spatrick
212061da546Spatrick DumpDataExtractor(data, strm,
213061da546Spatrick 0, // Start offset in "data"
214061da546Spatrick eFormatChar, // Print as characters
215061da546Spatrick 1, // Size of item (1 byte for a char!)
216061da546Spatrick len, // How many bytes to print?
217061da546Spatrick UINT32_MAX, // num per line
218061da546Spatrick LLDB_INVALID_ADDRESS, // base address
219061da546Spatrick 0, // bitfield bit size
220061da546Spatrick
221061da546Spatrick 0); // bitfield bit offset
222061da546Spatrick
223061da546Spatrick total_len += bytes_read;
224061da546Spatrick
225061da546Spatrick if (len < k_buf_len)
226061da546Spatrick break;
227061da546Spatrick curr_address.SetOffset(curr_address.GetOffset() + bytes_read);
228061da546Spatrick }
229061da546Spatrick strm->PutChar('"');
230061da546Spatrick return total_len;
231061da546Spatrick }
232061da546Spatrick
Address(lldb::addr_t abs_addr)233061da546Spatrick Address::Address(lldb::addr_t abs_addr) : m_section_wp(), m_offset(abs_addr) {}
234061da546Spatrick
Address(addr_t address,const SectionList * section_list)235061da546Spatrick Address::Address(addr_t address, const SectionList *section_list)
236*f6aab3d8Srobert : m_section_wp() {
237061da546Spatrick ResolveAddressUsingFileSections(address, section_list);
238061da546Spatrick }
239061da546Spatrick
operator =(const Address & rhs)240061da546Spatrick const Address &Address::operator=(const Address &rhs) {
241061da546Spatrick if (this != &rhs) {
242061da546Spatrick m_section_wp = rhs.m_section_wp;
243061da546Spatrick m_offset = rhs.m_offset;
244061da546Spatrick }
245061da546Spatrick return *this;
246061da546Spatrick }
247061da546Spatrick
ResolveAddressUsingFileSections(addr_t file_addr,const SectionList * section_list)248061da546Spatrick bool Address::ResolveAddressUsingFileSections(addr_t file_addr,
249061da546Spatrick const SectionList *section_list) {
250061da546Spatrick if (section_list) {
251061da546Spatrick SectionSP section_sp(
252061da546Spatrick section_list->FindSectionContainingFileAddress(file_addr));
253061da546Spatrick m_section_wp = section_sp;
254061da546Spatrick if (section_sp) {
255061da546Spatrick assert(section_sp->ContainsFileAddress(file_addr));
256061da546Spatrick m_offset = file_addr - section_sp->GetFileAddress();
257061da546Spatrick return true; // Successfully transformed addr into a section offset
258061da546Spatrick // address
259061da546Spatrick }
260061da546Spatrick }
261061da546Spatrick m_offset = file_addr;
262061da546Spatrick return false; // Failed to resolve this address to a section offset value
263061da546Spatrick }
264061da546Spatrick
265061da546Spatrick /// if "addr_range_ptr" is not NULL, then fill in with the address range of the function.
ResolveFunctionScope(SymbolContext & sym_ctx,AddressRange * addr_range_ptr)266061da546Spatrick bool Address::ResolveFunctionScope(SymbolContext &sym_ctx,
267061da546Spatrick AddressRange *addr_range_ptr) {
268061da546Spatrick constexpr SymbolContextItem resolve_scope =
269061da546Spatrick eSymbolContextFunction | eSymbolContextSymbol;
270061da546Spatrick
271061da546Spatrick if (!(CalculateSymbolContext(&sym_ctx, resolve_scope) & resolve_scope)) {
272061da546Spatrick if (addr_range_ptr)
273061da546Spatrick addr_range_ptr->Clear();
274061da546Spatrick return false;
275061da546Spatrick }
276061da546Spatrick
277061da546Spatrick if (!addr_range_ptr)
278061da546Spatrick return true;
279061da546Spatrick
280061da546Spatrick return sym_ctx.GetAddressRange(resolve_scope, 0, false, *addr_range_ptr);
281061da546Spatrick }
282061da546Spatrick
GetModule() const283061da546Spatrick ModuleSP Address::GetModule() const {
284061da546Spatrick lldb::ModuleSP module_sp;
285061da546Spatrick SectionSP section_sp(GetSection());
286061da546Spatrick if (section_sp)
287061da546Spatrick module_sp = section_sp->GetModule();
288061da546Spatrick return module_sp;
289061da546Spatrick }
290061da546Spatrick
GetFileAddress() const291061da546Spatrick addr_t Address::GetFileAddress() const {
292061da546Spatrick SectionSP section_sp(GetSection());
293061da546Spatrick if (section_sp) {
294061da546Spatrick addr_t sect_file_addr = section_sp->GetFileAddress();
295061da546Spatrick if (sect_file_addr == LLDB_INVALID_ADDRESS) {
296061da546Spatrick // Section isn't resolved, we can't return a valid file address
297061da546Spatrick return LLDB_INVALID_ADDRESS;
298061da546Spatrick }
299061da546Spatrick // We have a valid file range, so we can return the file based address by
300061da546Spatrick // adding the file base address to our offset
301061da546Spatrick return sect_file_addr + m_offset;
302061da546Spatrick } else if (SectionWasDeletedPrivate()) {
303061da546Spatrick // Used to have a valid section but it got deleted so the offset doesn't
304061da546Spatrick // mean anything without the section
305061da546Spatrick return LLDB_INVALID_ADDRESS;
306061da546Spatrick }
307061da546Spatrick // No section, we just return the offset since it is the value in this case
308061da546Spatrick return m_offset;
309061da546Spatrick }
310061da546Spatrick
GetLoadAddress(Target * target) const311061da546Spatrick addr_t Address::GetLoadAddress(Target *target) const {
312061da546Spatrick SectionSP section_sp(GetSection());
313061da546Spatrick if (section_sp) {
314061da546Spatrick if (target) {
315061da546Spatrick addr_t sect_load_addr = section_sp->GetLoadBaseAddress(target);
316061da546Spatrick
317061da546Spatrick if (sect_load_addr != LLDB_INVALID_ADDRESS) {
318061da546Spatrick // We have a valid file range, so we can return the file based address
319061da546Spatrick // by adding the file base address to our offset
320061da546Spatrick return sect_load_addr + m_offset;
321061da546Spatrick }
322061da546Spatrick }
323061da546Spatrick } else if (SectionWasDeletedPrivate()) {
324061da546Spatrick // Used to have a valid section but it got deleted so the offset doesn't
325061da546Spatrick // mean anything without the section
326061da546Spatrick return LLDB_INVALID_ADDRESS;
327061da546Spatrick } else {
328061da546Spatrick // We don't have a section so the offset is the load address
329061da546Spatrick return m_offset;
330061da546Spatrick }
331061da546Spatrick // The section isn't resolved or an invalid target was passed in so we can't
332061da546Spatrick // return a valid load address.
333061da546Spatrick return LLDB_INVALID_ADDRESS;
334061da546Spatrick }
335061da546Spatrick
GetCallableLoadAddress(Target * target,bool is_indirect) const336061da546Spatrick addr_t Address::GetCallableLoadAddress(Target *target, bool is_indirect) const {
337061da546Spatrick addr_t code_addr = LLDB_INVALID_ADDRESS;
338061da546Spatrick
339061da546Spatrick if (is_indirect && target) {
340061da546Spatrick ProcessSP processSP = target->GetProcessSP();
341061da546Spatrick Status error;
342061da546Spatrick if (processSP) {
343061da546Spatrick code_addr = processSP->ResolveIndirectFunction(this, error);
344061da546Spatrick if (!error.Success())
345061da546Spatrick code_addr = LLDB_INVALID_ADDRESS;
346061da546Spatrick }
347061da546Spatrick } else {
348061da546Spatrick code_addr = GetLoadAddress(target);
349061da546Spatrick }
350061da546Spatrick
351061da546Spatrick if (code_addr == LLDB_INVALID_ADDRESS)
352061da546Spatrick return code_addr;
353061da546Spatrick
354061da546Spatrick if (target)
355061da546Spatrick return target->GetCallableLoadAddress(code_addr, GetAddressClass());
356061da546Spatrick return code_addr;
357061da546Spatrick }
358061da546Spatrick
SetCallableLoadAddress(lldb::addr_t load_addr,Target * target)359061da546Spatrick bool Address::SetCallableLoadAddress(lldb::addr_t load_addr, Target *target) {
360061da546Spatrick if (SetLoadAddress(load_addr, target)) {
361061da546Spatrick if (target)
362061da546Spatrick m_offset = target->GetCallableLoadAddress(m_offset, GetAddressClass());
363061da546Spatrick return true;
364061da546Spatrick }
365061da546Spatrick return false;
366061da546Spatrick }
367061da546Spatrick
GetOpcodeLoadAddress(Target * target,AddressClass addr_class) const368061da546Spatrick addr_t Address::GetOpcodeLoadAddress(Target *target,
369061da546Spatrick AddressClass addr_class) const {
370061da546Spatrick addr_t code_addr = GetLoadAddress(target);
371061da546Spatrick if (code_addr != LLDB_INVALID_ADDRESS) {
372061da546Spatrick if (addr_class == AddressClass::eInvalid)
373061da546Spatrick addr_class = GetAddressClass();
374061da546Spatrick code_addr = target->GetOpcodeLoadAddress(code_addr, addr_class);
375061da546Spatrick }
376061da546Spatrick return code_addr;
377061da546Spatrick }
378061da546Spatrick
SetOpcodeLoadAddress(lldb::addr_t load_addr,Target * target,AddressClass addr_class,bool allow_section_end)379061da546Spatrick bool Address::SetOpcodeLoadAddress(lldb::addr_t load_addr, Target *target,
380061da546Spatrick AddressClass addr_class,
381061da546Spatrick bool allow_section_end) {
382061da546Spatrick if (SetLoadAddress(load_addr, target, allow_section_end)) {
383061da546Spatrick if (target) {
384061da546Spatrick if (addr_class == AddressClass::eInvalid)
385061da546Spatrick addr_class = GetAddressClass();
386061da546Spatrick m_offset = target->GetOpcodeLoadAddress(m_offset, addr_class);
387061da546Spatrick }
388061da546Spatrick return true;
389061da546Spatrick }
390061da546Spatrick return false;
391061da546Spatrick }
392061da546Spatrick
GetDescription(Stream & s,Target & target,DescriptionLevel level) const393*f6aab3d8Srobert bool Address::GetDescription(Stream &s, Target &target,
394*f6aab3d8Srobert DescriptionLevel level) const {
395*f6aab3d8Srobert assert(level == eDescriptionLevelBrief &&
396*f6aab3d8Srobert "Non-brief descriptions not implemented");
397*f6aab3d8Srobert LineEntry line_entry;
398*f6aab3d8Srobert if (CalculateSymbolContextLineEntry(line_entry)) {
399*f6aab3d8Srobert s.Printf(" (%s:%u:%u)", line_entry.file.GetFilename().GetCString(),
400*f6aab3d8Srobert line_entry.line, line_entry.column);
401*f6aab3d8Srobert return true;
402*f6aab3d8Srobert }
403*f6aab3d8Srobert return false;
404*f6aab3d8Srobert }
405*f6aab3d8Srobert
Dump(Stream * s,ExecutionContextScope * exe_scope,DumpStyle style,DumpStyle fallback_style,uint32_t addr_size,bool all_ranges) const406061da546Spatrick bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
407*f6aab3d8Srobert DumpStyle fallback_style, uint32_t addr_size,
408*f6aab3d8Srobert bool all_ranges) const {
409061da546Spatrick // If the section was nullptr, only load address is going to work unless we
410061da546Spatrick // are trying to deref a pointer
411061da546Spatrick SectionSP section_sp(GetSection());
412061da546Spatrick if (!section_sp && style != DumpStyleResolvedPointerDescription)
413061da546Spatrick style = DumpStyleLoadAddress;
414061da546Spatrick
415061da546Spatrick ExecutionContext exe_ctx(exe_scope);
416061da546Spatrick Target *target = exe_ctx.GetTargetPtr();
417061da546Spatrick // If addr_byte_size is UINT32_MAX, then determine the correct address byte
418061da546Spatrick // size for the process or default to the size of addr_t
419061da546Spatrick if (addr_size == UINT32_MAX) {
420061da546Spatrick if (target)
421061da546Spatrick addr_size = target->GetArchitecture().GetAddressByteSize();
422061da546Spatrick else
423061da546Spatrick addr_size = sizeof(addr_t);
424061da546Spatrick }
425061da546Spatrick
426061da546Spatrick Address so_addr;
427061da546Spatrick switch (style) {
428061da546Spatrick case DumpStyleInvalid:
429061da546Spatrick return false;
430061da546Spatrick
431061da546Spatrick case DumpStyleSectionNameOffset:
432061da546Spatrick if (section_sp) {
433dda28197Spatrick section_sp->DumpName(s->AsRawOstream());
434061da546Spatrick s->Printf(" + %" PRIu64, m_offset);
435061da546Spatrick } else {
436061da546Spatrick DumpAddress(s->AsRawOstream(), m_offset, addr_size);
437061da546Spatrick }
438061da546Spatrick break;
439061da546Spatrick
440061da546Spatrick case DumpStyleSectionPointerOffset:
441061da546Spatrick s->Printf("(Section *)%p + ", static_cast<void *>(section_sp.get()));
442061da546Spatrick DumpAddress(s->AsRawOstream(), m_offset, addr_size);
443061da546Spatrick break;
444061da546Spatrick
445061da546Spatrick case DumpStyleModuleWithFileAddress:
446061da546Spatrick if (section_sp) {
447061da546Spatrick ModuleSP module_sp = section_sp->GetModule();
448061da546Spatrick if (module_sp)
449061da546Spatrick s->Printf("%s[", module_sp->GetFileSpec().GetFilename().AsCString(
450061da546Spatrick "<Unknown>"));
451061da546Spatrick else
452061da546Spatrick s->Printf("%s[", "<Unknown>");
453061da546Spatrick }
454*f6aab3d8Srobert [[fallthrough]];
455061da546Spatrick case DumpStyleFileAddress: {
456061da546Spatrick addr_t file_addr = GetFileAddress();
457061da546Spatrick if (file_addr == LLDB_INVALID_ADDRESS) {
458061da546Spatrick if (fallback_style != DumpStyleInvalid)
459061da546Spatrick return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
460061da546Spatrick return false;
461061da546Spatrick }
462061da546Spatrick DumpAddress(s->AsRawOstream(), file_addr, addr_size);
463061da546Spatrick if (style == DumpStyleModuleWithFileAddress && section_sp)
464061da546Spatrick s->PutChar(']');
465061da546Spatrick } break;
466061da546Spatrick
467061da546Spatrick case DumpStyleLoadAddress: {
468061da546Spatrick addr_t load_addr = GetLoadAddress(target);
469061da546Spatrick
470061da546Spatrick /*
471061da546Spatrick * MIPS:
472061da546Spatrick * Display address in compressed form for MIPS16 or microMIPS
473061da546Spatrick * if the address belongs to AddressClass::eCodeAlternateISA.
474061da546Spatrick */
475061da546Spatrick if (target) {
476061da546Spatrick const llvm::Triple::ArchType llvm_arch =
477061da546Spatrick target->GetArchitecture().GetMachine();
478061da546Spatrick if (llvm_arch == llvm::Triple::mips ||
479061da546Spatrick llvm_arch == llvm::Triple::mipsel ||
480061da546Spatrick llvm_arch == llvm::Triple::mips64 ||
481061da546Spatrick llvm_arch == llvm::Triple::mips64el)
482061da546Spatrick load_addr = GetCallableLoadAddress(target);
483061da546Spatrick }
484061da546Spatrick
485061da546Spatrick if (load_addr == LLDB_INVALID_ADDRESS) {
486061da546Spatrick if (fallback_style != DumpStyleInvalid)
487061da546Spatrick return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
488061da546Spatrick return false;
489061da546Spatrick }
490061da546Spatrick DumpAddress(s->AsRawOstream(), load_addr, addr_size);
491061da546Spatrick } break;
492061da546Spatrick
493061da546Spatrick case DumpStyleResolvedDescription:
494061da546Spatrick case DumpStyleResolvedDescriptionNoModule:
495061da546Spatrick case DumpStyleResolvedDescriptionNoFunctionArguments:
496061da546Spatrick case DumpStyleNoFunctionName:
497061da546Spatrick if (IsSectionOffset()) {
498061da546Spatrick uint32_t pointer_size = 4;
499061da546Spatrick ModuleSP module_sp(GetModule());
500061da546Spatrick if (target)
501061da546Spatrick pointer_size = target->GetArchitecture().GetAddressByteSize();
502061da546Spatrick else if (module_sp)
503061da546Spatrick pointer_size = module_sp->GetArchitecture().GetAddressByteSize();
504061da546Spatrick
505061da546Spatrick bool showed_info = false;
506061da546Spatrick if (section_sp) {
507061da546Spatrick SectionType sect_type = section_sp->GetType();
508061da546Spatrick switch (sect_type) {
509061da546Spatrick case eSectionTypeData:
510061da546Spatrick if (module_sp) {
511061da546Spatrick if (Symtab *symtab = module_sp->GetSymtab()) {
512061da546Spatrick const addr_t file_Addr = GetFileAddress();
513061da546Spatrick Symbol *symbol =
514061da546Spatrick symtab->FindSymbolContainingFileAddress(file_Addr);
515061da546Spatrick if (symbol) {
516061da546Spatrick const char *symbol_name = symbol->GetName().AsCString();
517061da546Spatrick if (symbol_name) {
518061da546Spatrick s->PutCString(symbol_name);
519061da546Spatrick addr_t delta =
520061da546Spatrick file_Addr - symbol->GetAddressRef().GetFileAddress();
521061da546Spatrick if (delta)
522061da546Spatrick s->Printf(" + %" PRIu64, delta);
523061da546Spatrick showed_info = true;
524061da546Spatrick }
525061da546Spatrick }
526061da546Spatrick }
527061da546Spatrick }
528061da546Spatrick break;
529061da546Spatrick
530061da546Spatrick case eSectionTypeDataCString:
531061da546Spatrick // Read the C string from memory and display it
532061da546Spatrick showed_info = true;
533061da546Spatrick ReadCStringFromMemory(exe_scope, *this, s);
534061da546Spatrick break;
535061da546Spatrick
536061da546Spatrick case eSectionTypeDataCStringPointers:
537061da546Spatrick if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) {
538061da546Spatrick #if VERBOSE_OUTPUT
539061da546Spatrick s->PutCString("(char *)");
540061da546Spatrick so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
541061da546Spatrick DumpStyleFileAddress);
542061da546Spatrick s->PutCString(": ");
543061da546Spatrick #endif
544061da546Spatrick showed_info = true;
545061da546Spatrick ReadCStringFromMemory(exe_scope, so_addr, s);
546061da546Spatrick }
547061da546Spatrick break;
548061da546Spatrick
549061da546Spatrick case eSectionTypeDataObjCMessageRefs:
550061da546Spatrick if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) {
551061da546Spatrick if (target && so_addr.IsSectionOffset()) {
552061da546Spatrick SymbolContext func_sc;
553061da546Spatrick target->GetImages().ResolveSymbolContextForAddress(
554061da546Spatrick so_addr, eSymbolContextEverything, func_sc);
555061da546Spatrick if (func_sc.function != nullptr || func_sc.symbol != nullptr) {
556061da546Spatrick showed_info = true;
557061da546Spatrick #if VERBOSE_OUTPUT
558061da546Spatrick s->PutCString("(objc_msgref *) -> { (func*)");
559061da546Spatrick so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
560061da546Spatrick DumpStyleFileAddress);
561061da546Spatrick #else
562061da546Spatrick s->PutCString("{ ");
563061da546Spatrick #endif
564061da546Spatrick Address cstr_addr(*this);
565061da546Spatrick cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size);
566061da546Spatrick func_sc.DumpStopContext(s, exe_scope, so_addr, true, true,
567061da546Spatrick false, true, true);
568061da546Spatrick if (ReadAddress(exe_scope, cstr_addr, pointer_size, so_addr)) {
569061da546Spatrick #if VERBOSE_OUTPUT
570061da546Spatrick s->PutCString("), (char *)");
571061da546Spatrick so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
572061da546Spatrick DumpStyleFileAddress);
573061da546Spatrick s->PutCString(" (");
574061da546Spatrick #else
575061da546Spatrick s->PutCString(", ");
576061da546Spatrick #endif
577061da546Spatrick ReadCStringFromMemory(exe_scope, so_addr, s);
578061da546Spatrick }
579061da546Spatrick #if VERBOSE_OUTPUT
580061da546Spatrick s->PutCString(") }");
581061da546Spatrick #else
582061da546Spatrick s->PutCString(" }");
583061da546Spatrick #endif
584061da546Spatrick }
585061da546Spatrick }
586061da546Spatrick }
587061da546Spatrick break;
588061da546Spatrick
589061da546Spatrick case eSectionTypeDataObjCCFStrings: {
590061da546Spatrick Address cfstring_data_addr(*this);
591061da546Spatrick cfstring_data_addr.SetOffset(cfstring_data_addr.GetOffset() +
592061da546Spatrick (2 * pointer_size));
593061da546Spatrick if (ReadAddress(exe_scope, cfstring_data_addr, pointer_size,
594061da546Spatrick so_addr)) {
595061da546Spatrick #if VERBOSE_OUTPUT
596061da546Spatrick s->PutCString("(CFString *) ");
597061da546Spatrick cfstring_data_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
598061da546Spatrick DumpStyleFileAddress);
599061da546Spatrick s->PutCString(" -> @");
600061da546Spatrick #else
601061da546Spatrick s->PutChar('@');
602061da546Spatrick #endif
603061da546Spatrick if (so_addr.Dump(s, exe_scope, DumpStyleResolvedDescription))
604061da546Spatrick showed_info = true;
605061da546Spatrick }
606061da546Spatrick } break;
607061da546Spatrick
608061da546Spatrick case eSectionTypeData4:
609061da546Spatrick // Read the 4 byte data and display it
610061da546Spatrick showed_info = true;
611061da546Spatrick s->PutCString("(uint32_t) ");
612061da546Spatrick DumpUInt(exe_scope, *this, 4, s);
613061da546Spatrick break;
614061da546Spatrick
615061da546Spatrick case eSectionTypeData8:
616061da546Spatrick // Read the 8 byte data and display it
617061da546Spatrick showed_info = true;
618061da546Spatrick s->PutCString("(uint64_t) ");
619061da546Spatrick DumpUInt(exe_scope, *this, 8, s);
620061da546Spatrick break;
621061da546Spatrick
622061da546Spatrick case eSectionTypeData16:
623061da546Spatrick // Read the 16 byte data and display it
624061da546Spatrick showed_info = true;
625061da546Spatrick s->PutCString("(uint128_t) ");
626061da546Spatrick DumpUInt(exe_scope, *this, 16, s);
627061da546Spatrick break;
628061da546Spatrick
629061da546Spatrick case eSectionTypeDataPointers:
630061da546Spatrick // Read the pointer data and display it
631061da546Spatrick if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) {
632061da546Spatrick s->PutCString("(void *)");
633061da546Spatrick so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
634061da546Spatrick DumpStyleFileAddress);
635061da546Spatrick
636061da546Spatrick showed_info = true;
637061da546Spatrick if (so_addr.IsSectionOffset()) {
638061da546Spatrick SymbolContext pointer_sc;
639061da546Spatrick if (target) {
640061da546Spatrick target->GetImages().ResolveSymbolContextForAddress(
641061da546Spatrick so_addr, eSymbolContextEverything, pointer_sc);
642061da546Spatrick if (pointer_sc.function != nullptr ||
643061da546Spatrick pointer_sc.symbol != nullptr) {
644061da546Spatrick s->PutCString(": ");
645061da546Spatrick pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false,
646061da546Spatrick false, true, true);
647061da546Spatrick }
648061da546Spatrick }
649061da546Spatrick }
650061da546Spatrick }
651061da546Spatrick break;
652061da546Spatrick
653061da546Spatrick default:
654061da546Spatrick break;
655061da546Spatrick }
656061da546Spatrick }
657061da546Spatrick
658061da546Spatrick if (!showed_info) {
659061da546Spatrick if (module_sp) {
660061da546Spatrick SymbolContext sc;
661061da546Spatrick module_sp->ResolveSymbolContextForAddress(
662061da546Spatrick *this, eSymbolContextEverything, sc);
663061da546Spatrick if (sc.function || sc.symbol) {
664061da546Spatrick bool show_stop_context = true;
665061da546Spatrick const bool show_module = (style == DumpStyleResolvedDescription);
666061da546Spatrick const bool show_fullpaths = false;
667061da546Spatrick const bool show_inlined_frames = true;
668061da546Spatrick const bool show_function_arguments =
669061da546Spatrick (style != DumpStyleResolvedDescriptionNoFunctionArguments);
670061da546Spatrick const bool show_function_name = (style != DumpStyleNoFunctionName);
671061da546Spatrick if (sc.function == nullptr && sc.symbol != nullptr) {
672061da546Spatrick // If we have just a symbol make sure it is in the right section
673061da546Spatrick if (sc.symbol->ValueIsAddress()) {
674061da546Spatrick if (sc.symbol->GetAddressRef().GetSection() != GetSection()) {
675061da546Spatrick // don't show the module if the symbol is a trampoline symbol
676061da546Spatrick show_stop_context = false;
677061da546Spatrick }
678061da546Spatrick }
679061da546Spatrick }
680061da546Spatrick if (show_stop_context) {
681061da546Spatrick // We have a function or a symbol from the same sections as this
682061da546Spatrick // address.
683061da546Spatrick sc.DumpStopContext(s, exe_scope, *this, show_fullpaths,
684061da546Spatrick show_module, show_inlined_frames,
685061da546Spatrick show_function_arguments, show_function_name);
686061da546Spatrick } else {
687061da546Spatrick // We found a symbol but it was in a different section so it
688061da546Spatrick // isn't the symbol we should be showing, just show the section
689061da546Spatrick // name + offset
690061da546Spatrick Dump(s, exe_scope, DumpStyleSectionNameOffset);
691061da546Spatrick }
692061da546Spatrick }
693061da546Spatrick }
694061da546Spatrick }
695061da546Spatrick } else {
696061da546Spatrick if (fallback_style != DumpStyleInvalid)
697061da546Spatrick return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
698061da546Spatrick return false;
699061da546Spatrick }
700061da546Spatrick break;
701061da546Spatrick
702061da546Spatrick case DumpStyleDetailedSymbolContext:
703061da546Spatrick if (IsSectionOffset()) {
704061da546Spatrick ModuleSP module_sp(GetModule());
705061da546Spatrick if (module_sp) {
706061da546Spatrick SymbolContext sc;
707061da546Spatrick module_sp->ResolveSymbolContextForAddress(
708061da546Spatrick *this, eSymbolContextEverything | eSymbolContextVariable, sc);
709061da546Spatrick if (sc.symbol) {
710061da546Spatrick // If we have just a symbol make sure it is in the same section as
711061da546Spatrick // our address. If it isn't, then we might have just found the last
712061da546Spatrick // symbol that came before the address that we are looking up that
713061da546Spatrick // has nothing to do with our address lookup.
714061da546Spatrick if (sc.symbol->ValueIsAddress() &&
715061da546Spatrick sc.symbol->GetAddressRef().GetSection() != GetSection())
716061da546Spatrick sc.symbol = nullptr;
717061da546Spatrick }
718061da546Spatrick sc.GetDescription(s, eDescriptionLevelBrief, target);
719061da546Spatrick
720061da546Spatrick if (sc.block) {
721061da546Spatrick bool can_create = true;
722061da546Spatrick bool get_parent_variables = true;
723061da546Spatrick bool stop_if_block_is_inlined_function = false;
724061da546Spatrick VariableList variable_list;
725*f6aab3d8Srobert addr_t file_addr = GetFileAddress();
726*f6aab3d8Srobert sc.block->AppendVariables(
727*f6aab3d8Srobert can_create, get_parent_variables,
728061da546Spatrick stop_if_block_is_inlined_function,
729*f6aab3d8Srobert [&](Variable *var) {
730*f6aab3d8Srobert return var && var->LocationIsValidForAddress(*this);
731*f6aab3d8Srobert },
732061da546Spatrick &variable_list);
733*f6aab3d8Srobert ABISP abi =
734*f6aab3d8Srobert ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());
735061da546Spatrick for (const VariableSP &var_sp : variable_list) {
736061da546Spatrick s->Indent();
737061da546Spatrick s->Printf(" Variable: id = {0x%8.8" PRIx64 "}, name = \"%s\"",
738061da546Spatrick var_sp->GetID(), var_sp->GetName().GetCString());
739061da546Spatrick Type *type = var_sp->GetType();
740061da546Spatrick if (type)
741061da546Spatrick s->Printf(", type = \"%s\"", type->GetName().GetCString());
742061da546Spatrick else
743061da546Spatrick s->PutCString(", type = <unknown>");
744*f6aab3d8Srobert s->PutCString(", valid ranges = ");
745*f6aab3d8Srobert if (var_sp->GetScopeRange().IsEmpty())
746*f6aab3d8Srobert s->PutCString("<block>");
747*f6aab3d8Srobert else if (all_ranges) {
748*f6aab3d8Srobert for (auto range : var_sp->GetScopeRange())
749*f6aab3d8Srobert DumpAddressRange(s->AsRawOstream(), range.GetRangeBase(),
750*f6aab3d8Srobert range.GetRangeEnd(), addr_size);
751*f6aab3d8Srobert } else if (auto *range =
752*f6aab3d8Srobert var_sp->GetScopeRange().FindEntryThatContains(
753*f6aab3d8Srobert file_addr))
754*f6aab3d8Srobert DumpAddressRange(s->AsRawOstream(), range->GetRangeBase(),
755*f6aab3d8Srobert range->GetRangeEnd(), addr_size);
756061da546Spatrick s->PutCString(", location = ");
757*f6aab3d8Srobert var_sp->DumpLocations(s, all_ranges ? LLDB_INVALID_ADDRESS : *this);
758061da546Spatrick s->PutCString(", decl = ");
759061da546Spatrick var_sp->GetDeclaration().DumpStopContext(s, false);
760061da546Spatrick s->EOL();
761061da546Spatrick }
762061da546Spatrick }
763061da546Spatrick }
764061da546Spatrick } else {
765061da546Spatrick if (fallback_style != DumpStyleInvalid)
766061da546Spatrick return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
767061da546Spatrick return false;
768061da546Spatrick }
769061da546Spatrick break;
770061da546Spatrick
771061da546Spatrick case DumpStyleResolvedPointerDescription: {
772061da546Spatrick Process *process = exe_ctx.GetProcessPtr();
773061da546Spatrick if (process) {
774061da546Spatrick addr_t load_addr = GetLoadAddress(target);
775061da546Spatrick if (load_addr != LLDB_INVALID_ADDRESS) {
776061da546Spatrick Status memory_error;
777061da546Spatrick addr_t dereferenced_load_addr =
778061da546Spatrick process->ReadPointerFromMemory(load_addr, memory_error);
779061da546Spatrick if (dereferenced_load_addr != LLDB_INVALID_ADDRESS) {
780061da546Spatrick Address dereferenced_addr;
781061da546Spatrick if (dereferenced_addr.SetLoadAddress(dereferenced_load_addr,
782061da546Spatrick target)) {
783061da546Spatrick StreamString strm;
784061da546Spatrick if (dereferenced_addr.Dump(&strm, exe_scope,
785061da546Spatrick DumpStyleResolvedDescription,
786061da546Spatrick DumpStyleInvalid, addr_size)) {
787061da546Spatrick DumpAddress(s->AsRawOstream(), dereferenced_load_addr, addr_size,
788061da546Spatrick " -> ", " ");
789061da546Spatrick s->Write(strm.GetString().data(), strm.GetSize());
790061da546Spatrick return true;
791061da546Spatrick }
792061da546Spatrick }
793061da546Spatrick }
794061da546Spatrick }
795061da546Spatrick }
796061da546Spatrick if (fallback_style != DumpStyleInvalid)
797061da546Spatrick return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
798061da546Spatrick return false;
799061da546Spatrick } break;
800061da546Spatrick }
801061da546Spatrick
802061da546Spatrick return true;
803061da546Spatrick }
804061da546Spatrick
SectionWasDeleted() const805061da546Spatrick bool Address::SectionWasDeleted() const {
806061da546Spatrick if (GetSection())
807061da546Spatrick return false;
808061da546Spatrick return SectionWasDeletedPrivate();
809061da546Spatrick }
810061da546Spatrick
SectionWasDeletedPrivate() const811061da546Spatrick bool Address::SectionWasDeletedPrivate() const {
812061da546Spatrick lldb::SectionWP empty_section_wp;
813061da546Spatrick
814061da546Spatrick // If either call to "std::weak_ptr::owner_before(...) value returns true,
815061da546Spatrick // this indicates that m_section_wp once contained (possibly still does) a
816061da546Spatrick // reference to a valid shared pointer. This helps us know if we had a valid
817061da546Spatrick // reference to a section which is now invalid because the module it was in
818061da546Spatrick // was unloaded/deleted, or if the address doesn't have a valid reference to
819061da546Spatrick // a section.
820061da546Spatrick return empty_section_wp.owner_before(m_section_wp) ||
821061da546Spatrick m_section_wp.owner_before(empty_section_wp);
822061da546Spatrick }
823061da546Spatrick
824061da546Spatrick uint32_t
CalculateSymbolContext(SymbolContext * sc,SymbolContextItem resolve_scope) const825061da546Spatrick Address::CalculateSymbolContext(SymbolContext *sc,
826061da546Spatrick SymbolContextItem resolve_scope) const {
827061da546Spatrick sc->Clear(false);
828061da546Spatrick // Absolute addresses don't have enough information to reconstruct even their
829061da546Spatrick // target.
830061da546Spatrick
831061da546Spatrick SectionSP section_sp(GetSection());
832061da546Spatrick if (section_sp) {
833061da546Spatrick ModuleSP module_sp(section_sp->GetModule());
834061da546Spatrick if (module_sp) {
835061da546Spatrick sc->module_sp = module_sp;
836061da546Spatrick if (sc->module_sp)
837061da546Spatrick return sc->module_sp->ResolveSymbolContextForAddress(
838061da546Spatrick *this, resolve_scope, *sc);
839061da546Spatrick }
840061da546Spatrick }
841061da546Spatrick return 0;
842061da546Spatrick }
843061da546Spatrick
CalculateSymbolContextModule() const844061da546Spatrick ModuleSP Address::CalculateSymbolContextModule() const {
845061da546Spatrick SectionSP section_sp(GetSection());
846061da546Spatrick if (section_sp)
847061da546Spatrick return section_sp->GetModule();
848061da546Spatrick return ModuleSP();
849061da546Spatrick }
850061da546Spatrick
CalculateSymbolContextCompileUnit() const851061da546Spatrick CompileUnit *Address::CalculateSymbolContextCompileUnit() const {
852061da546Spatrick SectionSP section_sp(GetSection());
853061da546Spatrick if (section_sp) {
854061da546Spatrick SymbolContext sc;
855061da546Spatrick sc.module_sp = section_sp->GetModule();
856061da546Spatrick if (sc.module_sp) {
857061da546Spatrick sc.module_sp->ResolveSymbolContextForAddress(*this,
858061da546Spatrick eSymbolContextCompUnit, sc);
859061da546Spatrick return sc.comp_unit;
860061da546Spatrick }
861061da546Spatrick }
862061da546Spatrick return nullptr;
863061da546Spatrick }
864061da546Spatrick
CalculateSymbolContextFunction() const865061da546Spatrick Function *Address::CalculateSymbolContextFunction() const {
866061da546Spatrick SectionSP section_sp(GetSection());
867061da546Spatrick if (section_sp) {
868061da546Spatrick SymbolContext sc;
869061da546Spatrick sc.module_sp = section_sp->GetModule();
870061da546Spatrick if (sc.module_sp) {
871061da546Spatrick sc.module_sp->ResolveSymbolContextForAddress(*this,
872061da546Spatrick eSymbolContextFunction, sc);
873061da546Spatrick return sc.function;
874061da546Spatrick }
875061da546Spatrick }
876061da546Spatrick return nullptr;
877061da546Spatrick }
878061da546Spatrick
CalculateSymbolContextBlock() const879061da546Spatrick Block *Address::CalculateSymbolContextBlock() const {
880061da546Spatrick SectionSP section_sp(GetSection());
881061da546Spatrick if (section_sp) {
882061da546Spatrick SymbolContext sc;
883061da546Spatrick sc.module_sp = section_sp->GetModule();
884061da546Spatrick if (sc.module_sp) {
885061da546Spatrick sc.module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextBlock,
886061da546Spatrick sc);
887061da546Spatrick return sc.block;
888061da546Spatrick }
889061da546Spatrick }
890061da546Spatrick return nullptr;
891061da546Spatrick }
892061da546Spatrick
CalculateSymbolContextSymbol() const893061da546Spatrick Symbol *Address::CalculateSymbolContextSymbol() const {
894061da546Spatrick SectionSP section_sp(GetSection());
895061da546Spatrick if (section_sp) {
896061da546Spatrick SymbolContext sc;
897061da546Spatrick sc.module_sp = section_sp->GetModule();
898061da546Spatrick if (sc.module_sp) {
899061da546Spatrick sc.module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextSymbol,
900061da546Spatrick sc);
901061da546Spatrick return sc.symbol;
902061da546Spatrick }
903061da546Spatrick }
904061da546Spatrick return nullptr;
905061da546Spatrick }
906061da546Spatrick
CalculateSymbolContextLineEntry(LineEntry & line_entry) const907061da546Spatrick bool Address::CalculateSymbolContextLineEntry(LineEntry &line_entry) const {
908061da546Spatrick SectionSP section_sp(GetSection());
909061da546Spatrick if (section_sp) {
910061da546Spatrick SymbolContext sc;
911061da546Spatrick sc.module_sp = section_sp->GetModule();
912061da546Spatrick if (sc.module_sp) {
913061da546Spatrick sc.module_sp->ResolveSymbolContextForAddress(*this,
914061da546Spatrick eSymbolContextLineEntry, sc);
915061da546Spatrick if (sc.line_entry.IsValid()) {
916061da546Spatrick line_entry = sc.line_entry;
917061da546Spatrick return true;
918061da546Spatrick }
919061da546Spatrick }
920061da546Spatrick }
921061da546Spatrick line_entry.Clear();
922061da546Spatrick return false;
923061da546Spatrick }
924061da546Spatrick
CompareFileAddress(const Address & a,const Address & b)925061da546Spatrick int Address::CompareFileAddress(const Address &a, const Address &b) {
926061da546Spatrick addr_t a_file_addr = a.GetFileAddress();
927061da546Spatrick addr_t b_file_addr = b.GetFileAddress();
928061da546Spatrick if (a_file_addr < b_file_addr)
929061da546Spatrick return -1;
930061da546Spatrick if (a_file_addr > b_file_addr)
931061da546Spatrick return +1;
932061da546Spatrick return 0;
933061da546Spatrick }
934061da546Spatrick
CompareLoadAddress(const Address & a,const Address & b,Target * target)935061da546Spatrick int Address::CompareLoadAddress(const Address &a, const Address &b,
936061da546Spatrick Target *target) {
937061da546Spatrick assert(target != nullptr);
938061da546Spatrick addr_t a_load_addr = a.GetLoadAddress(target);
939061da546Spatrick addr_t b_load_addr = b.GetLoadAddress(target);
940061da546Spatrick if (a_load_addr < b_load_addr)
941061da546Spatrick return -1;
942061da546Spatrick if (a_load_addr > b_load_addr)
943061da546Spatrick return +1;
944061da546Spatrick return 0;
945061da546Spatrick }
946061da546Spatrick
CompareModulePointerAndOffset(const Address & a,const Address & b)947061da546Spatrick int Address::CompareModulePointerAndOffset(const Address &a, const Address &b) {
948061da546Spatrick ModuleSP a_module_sp(a.GetModule());
949061da546Spatrick ModuleSP b_module_sp(b.GetModule());
950061da546Spatrick Module *a_module = a_module_sp.get();
951061da546Spatrick Module *b_module = b_module_sp.get();
952061da546Spatrick if (a_module < b_module)
953061da546Spatrick return -1;
954061da546Spatrick if (a_module > b_module)
955061da546Spatrick return +1;
956061da546Spatrick // Modules are the same, just compare the file address since they should be
957061da546Spatrick // unique
958061da546Spatrick addr_t a_file_addr = a.GetFileAddress();
959061da546Spatrick addr_t b_file_addr = b.GetFileAddress();
960061da546Spatrick if (a_file_addr < b_file_addr)
961061da546Spatrick return -1;
962061da546Spatrick if (a_file_addr > b_file_addr)
963061da546Spatrick return +1;
964061da546Spatrick return 0;
965061da546Spatrick }
966061da546Spatrick
MemorySize() const967061da546Spatrick size_t Address::MemorySize() const {
968061da546Spatrick // Noting special for the memory size of a single Address object, it is just
969061da546Spatrick // the size of itself.
970061da546Spatrick return sizeof(Address);
971061da546Spatrick }
972061da546Spatrick
973061da546Spatrick // NOTE: Be careful using this operator. It can correctly compare two
974061da546Spatrick // addresses from the same Module correctly. It can't compare two addresses
975061da546Spatrick // from different modules in any meaningful way, but it will compare the module
976061da546Spatrick // pointers.
977061da546Spatrick //
978061da546Spatrick // To sum things up:
979061da546Spatrick // - works great for addresses within the same module - it works for addresses
980061da546Spatrick // across multiple modules, but don't expect the
981061da546Spatrick // address results to make much sense
982061da546Spatrick //
983061da546Spatrick // This basically lets Address objects be used in ordered collection classes.
984061da546Spatrick
operator <(const Address & lhs,const Address & rhs)985061da546Spatrick bool lldb_private::operator<(const Address &lhs, const Address &rhs) {
986061da546Spatrick ModuleSP lhs_module_sp(lhs.GetModule());
987061da546Spatrick ModuleSP rhs_module_sp(rhs.GetModule());
988061da546Spatrick Module *lhs_module = lhs_module_sp.get();
989061da546Spatrick Module *rhs_module = rhs_module_sp.get();
990061da546Spatrick if (lhs_module == rhs_module) {
991061da546Spatrick // Addresses are in the same module, just compare the file addresses
992061da546Spatrick return lhs.GetFileAddress() < rhs.GetFileAddress();
993061da546Spatrick } else {
994061da546Spatrick // The addresses are from different modules, just use the module pointer
995061da546Spatrick // value to get consistent ordering
996061da546Spatrick return lhs_module < rhs_module;
997061da546Spatrick }
998061da546Spatrick }
999061da546Spatrick
operator >(const Address & lhs,const Address & rhs)1000061da546Spatrick bool lldb_private::operator>(const Address &lhs, const Address &rhs) {
1001061da546Spatrick ModuleSP lhs_module_sp(lhs.GetModule());
1002061da546Spatrick ModuleSP rhs_module_sp(rhs.GetModule());
1003061da546Spatrick Module *lhs_module = lhs_module_sp.get();
1004061da546Spatrick Module *rhs_module = rhs_module_sp.get();
1005061da546Spatrick if (lhs_module == rhs_module) {
1006061da546Spatrick // Addresses are in the same module, just compare the file addresses
1007061da546Spatrick return lhs.GetFileAddress() > rhs.GetFileAddress();
1008061da546Spatrick } else {
1009061da546Spatrick // The addresses are from different modules, just use the module pointer
1010061da546Spatrick // value to get consistent ordering
1011061da546Spatrick return lhs_module > rhs_module;
1012061da546Spatrick }
1013061da546Spatrick }
1014061da546Spatrick
1015061da546Spatrick // The operator == checks for exact equality only (same section, same offset)
operator ==(const Address & a,const Address & rhs)1016061da546Spatrick bool lldb_private::operator==(const Address &a, const Address &rhs) {
1017061da546Spatrick return a.GetOffset() == rhs.GetOffset() && a.GetSection() == rhs.GetSection();
1018061da546Spatrick }
1019061da546Spatrick
1020061da546Spatrick // The operator != checks for exact inequality only (differing section, or
1021061da546Spatrick // different offset)
operator !=(const Address & a,const Address & rhs)1022061da546Spatrick bool lldb_private::operator!=(const Address &a, const Address &rhs) {
1023061da546Spatrick return a.GetOffset() != rhs.GetOffset() || a.GetSection() != rhs.GetSection();
1024061da546Spatrick }
1025061da546Spatrick
GetAddressClass() const1026061da546Spatrick AddressClass Address::GetAddressClass() const {
1027061da546Spatrick ModuleSP module_sp(GetModule());
1028061da546Spatrick if (module_sp) {
1029061da546Spatrick ObjectFile *obj_file = module_sp->GetObjectFile();
1030061da546Spatrick if (obj_file) {
1031061da546Spatrick // Give the symbol file a chance to add to the unified section list
1032061da546Spatrick // and to the symtab.
1033061da546Spatrick module_sp->GetSymtab();
1034061da546Spatrick return obj_file->GetAddressClass(GetFileAddress());
1035061da546Spatrick }
1036061da546Spatrick }
1037061da546Spatrick return AddressClass::eUnknown;
1038061da546Spatrick }
1039061da546Spatrick
SetLoadAddress(lldb::addr_t load_addr,Target * target,bool allow_section_end)1040061da546Spatrick bool Address::SetLoadAddress(lldb::addr_t load_addr, Target *target,
1041061da546Spatrick bool allow_section_end) {
1042061da546Spatrick if (target && target->GetSectionLoadList().ResolveLoadAddress(
1043061da546Spatrick load_addr, *this, allow_section_end))
1044061da546Spatrick return true;
1045061da546Spatrick m_section_wp.reset();
1046061da546Spatrick m_offset = load_addr;
1047061da546Spatrick return false;
1048061da546Spatrick }
1049