xref: /freebsd/contrib/llvm-project/lldb/source/Core/Address.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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-exception
6 //
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 
53 namespace lldb_private {
54 class CompileUnit;
55 }
56 namespace lldb_private {
57 class Function;
58 }
59 
60 using namespace lldb;
61 using namespace lldb_private;
62 
ReadBytes(ExecutionContextScope * exe_scope,const Address & address,void * dst,size_t dst_len)63 static 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 
GetByteOrderAndAddressSize(ExecutionContextScope * exe_scope,const Address & address,ByteOrder & byte_order,uint32_t & addr_size)78 static 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 
ReadUIntMax64(ExecutionContextScope * exe_scope,const Address & address,uint32_t byte_size,bool & success)103 static 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     } else
122       success = false;
123   }
124   return uval64;
125 }
126 
ReadAddress(ExecutionContextScope * exe_scope,const Address & address,uint32_t pointer_size,Address & deref_so_addr)127 static 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 the
139     // section load list
140     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 a
146       // module
147       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 were
155     // able to read the address, so we return a section offset address with no
156     // section and "deref_addr" as the offset (address).
157     deref_so_addr.SetRawAddress(deref_addr);
158     return true;
159   }
160   return false;
161 }
162 
DumpUInt(ExecutionContextScope * exe_scope,const Address & address,uint32_t byte_size,Stream * strm)163 static 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 characters
178                         buf.size(),           // Size of item
179                         1,                    // Items count
180                         UINT32_MAX,           // num per line
181                         LLDB_INVALID_ADDRESS, // base address
182                         0,                    // bitfield bit size
183                         0);                   // bitfield bit offset
184 
185       return true;
186     }
187   }
188   return false;
189 }
190 
ReadCStringFromMemory(ExecutionContextScope * exe_scope,const Address & address,Stream * strm)191 static 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 terminate
198 
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 characters
216                       1,                    // Size of item (1 byte for a char!)
217                       len,                  // How many bytes to print?
218                       UINT32_MAX,           // num per line
219                       LLDB_INVALID_ADDRESS, // base address
220                       0,                    // bitfield bit size
221 
222                       0); // bitfield bit offset
223 
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 
Address(lldb::addr_t abs_addr)234 Address::Address(lldb::addr_t abs_addr) : m_section_wp(), m_offset(abs_addr) {}
235 
Address(addr_t address,const SectionList * section_list)236 Address::Address(addr_t address, const SectionList *section_list)
237     : m_section_wp() {
238   ResolveAddressUsingFileSections(address, section_list);
239 }
240 
operator =(const Address & rhs)241 const 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 
ResolveAddressUsingFileSections(addr_t file_addr,const SectionList * section_list)249 bool 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 offset
259                    // address
260     }
261   }
262   m_offset = file_addr;
263   return false; // Failed to resolve this address to a section offset value
264 }
265 
ResolveFunctionScope(SymbolContext & sym_ctx)266 bool 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 
GetModule() const273 ModuleSP 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 
GetFileAddress() const281 addr_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 address
287       return LLDB_INVALID_ADDRESS;
288     }
289     // We have a valid file range, so we can return the file based address by
290     // adding the file base address to our offset
291     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't
294     // mean anything without the section
295     return LLDB_INVALID_ADDRESS;
296   }
297   // No section, we just return the offset since it is the value in this case
298   return m_offset;
299 }
300 
GetLoadAddress(Target * target) const301 addr_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 address
309         // by adding the file base address to our offset
310         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't
315     // mean anything without the section
316     return LLDB_INVALID_ADDRESS;
317   } else {
318     // We don't have a section so the offset is the load address
319     return m_offset;
320   }
321   // The section isn't resolved or an invalid target was passed in so we can't
322   // return a valid load address.
323   return LLDB_INVALID_ADDRESS;
324 }
325 
GetCallableLoadAddress(Target * target,bool is_indirect) const326 addr_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 
SetCallableLoadAddress(lldb::addr_t load_addr,Target * target)349 bool 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 
GetOpcodeLoadAddress(Target * target,AddressClass addr_class) const358 addr_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 
SetOpcodeLoadAddress(lldb::addr_t load_addr,Target * target,AddressClass addr_class,bool allow_section_end)369 bool 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 
GetDescription(Stream & s,Target & target,DescriptionLevel level) const383 bool 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 
Dump(Stream * s,ExecutionContextScope * exe_scope,DumpStyle style,DumpStyle fallback_style,uint32_t addr_size,bool all_ranges,std::optional<Stream::HighlightSettings> settings) const396 bool 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 we
401   // are trying to deref a pointer
402   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 byte
409   // size for the process or default to the size of addr_t
410   if (addr_size == UINT32_MAX) {
411     if (target)
412       addr_size = target->GetArchitecture().GetAddressByteSize();
413     else
414       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       else
443         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 microMIPS
464      * 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 it
522           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_OUTPUT
529             s->PutCString("(char *)");
530             so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
531                          DumpStyleFileAddress);
532             s->PutCString(": ");
533 #endif
534             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_OUTPUT
548                 s->PutCString("(objc_msgref *) -> { (func*)");
549                 so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
550                              DumpStyleFileAddress);
551 #else
552                 s->PutCString("{ ");
553 #endif
554                 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_OUTPUT
560                   s->PutCString("), (char *)");
561                   so_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
562                                DumpStyleFileAddress);
563                   s->PutCString(" (");
564 #else
565                   s->PutCString(", ");
566 #endif
567                   ReadCStringFromMemory(exe_scope, so_addr, s);
568                 }
569 #if VERBOSE_OUTPUT
570                 s->PutCString(") }");
571 #else
572                 s->PutCString(" }");
573 #endif
574               }
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_OUTPUT
586             s->PutCString("(CFString *) ");
587             cfstring_data_addr.Dump(s, exe_scope, DumpStyleLoadAddress,
588                                     DumpStyleFileAddress);
589             s->PutCString(" -> @");
590 #else
591             s->PutChar('@');
592 #endif
593             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 it
600           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 it
607           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 it
614           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 it
621           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 section
664               if (sc.symbol->ValueIsAddress()) {
665                 if (sc.symbol->GetAddressRef().GetSection() != GetSection()) {
666                   // don't show the module if the symbol is a trampoline symbol
667                   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 this
673               // 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 it
680               // isn't the symbol we should be showing, just show the section
681               // name + offset
682               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 as
705           // our address. If it isn't, then we might have just found the last
706           // symbol that came before the address that we are looking up that
707           // 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             else
737               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 
SectionWasDeleted() const800 bool Address::SectionWasDeleted() const {
801   if (GetSection())
802     return false;
803   return SectionWasDeletedPrivate();
804 }
805 
SectionWasDeletedPrivate() const806 bool 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) a
811   // reference to a valid shared pointer. This helps us know if we had a valid
812   // reference to a section which is now invalid because the module it was in
813   // was unloaded/deleted, or if the address doesn't have a valid reference to
814   // a section.
815   return empty_section_wp.owner_before(m_section_wp) ||
816          m_section_wp.owner_before(empty_section_wp);
817 }
818 
819 uint32_t
CalculateSymbolContext(SymbolContext * sc,SymbolContextItem resolve_scope) const820 Address::CalculateSymbolContext(SymbolContext *sc,
821                                 SymbolContextItem resolve_scope) const {
822   sc->Clear(false);
823   // Absolute addresses don't have enough information to reconstruct even their
824   // 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 
CalculateSymbolContextModule() const839 ModuleSP Address::CalculateSymbolContextModule() const {
840   SectionSP section_sp(GetSection());
841   if (section_sp)
842     return section_sp->GetModule();
843   return ModuleSP();
844 }
845 
CalculateSymbolContextCompileUnit() const846 CompileUnit *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 
CalculateSymbolContextFunction() const860 Function *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 
CalculateSymbolContextBlock() const874 Block *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 
CalculateSymbolContextSymbol() const888 Symbol *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 
CalculateSymbolContextLineEntry(LineEntry & line_entry) const902 bool 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 
CompareFileAddress(const Address & a,const Address & b)920 int 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 
CompareLoadAddress(const Address & a,const Address & b,Target * target)930 int 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 
CompareModulePointerAndOffset(const Address & a,const Address & b)942 int 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 be
952   // unique
953   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 
MemorySize() const962 size_t Address::MemorySize() const {
963   // Noting special for the memory size of a single Address object, it is just
964   // the size of itself.
965   return sizeof(Address);
966 }
967 
968 // NOTE: Be careful using this operator. It can correctly compare two
969 // addresses from the same Module correctly. It can't compare two addresses
970 // from different modules in any meaningful way, but it will compare the module
971 // pointers.
972 //
973 // To sum things up:
974 // - works great for addresses within the same module - it works for addresses
975 // across multiple modules, but don't expect the
976 //   address results to make much sense
977 //
978 // This basically lets Address objects be used in ordered collection classes.
979 
operator <(const Address & lhs,const Address & rhs)980 bool 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 addresses
987     return lhs.GetFileAddress() < rhs.GetFileAddress();
988   } else {
989     // The addresses are from different modules, just use the module pointer
990     // value to get consistent ordering
991     return lhs_module < rhs_module;
992   }
993 }
994 
operator >(const Address & lhs,const Address & rhs)995 bool 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 addresses
1002     return lhs.GetFileAddress() > rhs.GetFileAddress();
1003   } else {
1004     // The addresses are from different modules, just use the module pointer
1005     // value to get consistent ordering
1006     return lhs_module > rhs_module;
1007   }
1008 }
1009 
1010 // The operator == checks for exact equality only (same section, same offset)
operator ==(const Address & a,const Address & rhs)1011 bool 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, or
1016 // different offset)
operator !=(const Address & a,const Address & rhs)1017 bool lldb_private::operator!=(const Address &a, const Address &rhs) {
1018   return a.GetOffset() != rhs.GetOffset() || a.GetSection() != rhs.GetSection();
1019 }
1020 
GetAddressClass() const1021 AddressClass 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 list
1027       // and to the symtab.
1028       module_sp->GetSymtab();
1029       return obj_file->GetAddressClass(GetFileAddress());
1030     }
1031   }
1032   return AddressClass::eUnknown;
1033 }
1034 
SetLoadAddress(lldb::addr_t load_addr,Target * target,bool allow_section_end)1035 bool 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