1 //===-- SymbolFileDWARFDebugMap.cpp ---------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "SymbolFileDWARFDebugMap.h"
10 #include "DWARFCompileUnit.h"
11 #include "DWARFDebugAranges.h"
12 #include "DWARFDebugInfo.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/ModuleList.h"
16 #include "lldb/Core/PluginManager.h"
17 #include "lldb/Core/Section.h"
18 #include "lldb/Host/FileSystem.h"
19 #include "lldb/Utility/RangeMap.h"
20 #include "lldb/Utility/RegularExpression.h"
21 #include "lldb/Utility/StreamString.h"
22 #include "lldb/Utility/StructuredData.h"
23 #include "lldb/Utility/Timer.h"
25 //#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT
27 #include "lldb/Symbol/CompileUnit.h"
28 #include "lldb/Symbol/LineTable.h"
29 #include "lldb/Symbol/ObjectFile.h"
30 #include "lldb/Symbol/SymbolVendor.h"
31 #include "lldb/Symbol/TypeMap.h"
32 #include "lldb/Symbol/VariableList.h"
33 #include "llvm/ADT/STLExtras.h"
34 #include "llvm/Support/ScopedPrinter.h"
36 #include "lldb/Target/StackFrame.h"
38 #include "LogChannelDWARF.h"
39 #include "SymbolFileDWARF.h"
40 #include "lldb/lldb-private-enumerations.h"
46 using namespace lldb_private
;
47 using namespace lldb_private::plugin::dwarf
;
49 char SymbolFileDWARFDebugMap::ID
;
51 // Subclass lldb_private::Module so we can intercept the
52 // "Module::GetObjectFile()" (so we can fixup the object file sections) and
53 // also for "Module::GetSymbolFile()" (so we can fixup the symbol file id.
55 const SymbolFileDWARFDebugMap::FileRangeMap
&
56 SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
57 SymbolFileDWARFDebugMap
*exe_symfile
) {
58 if (file_range_map_valid
)
59 return file_range_map
;
61 file_range_map_valid
= true;
63 Module
*oso_module
= exe_symfile
->GetModuleByCompUnitInfo(this);
65 return file_range_map
;
67 ObjectFile
*oso_objfile
= oso_module
->GetObjectFile();
69 return file_range_map
;
71 Log
*log
= GetLog(DWARFLog::DebugMap
);
74 "%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s')",
75 static_cast<void *>(this),
76 oso_module
->GetSpecificationDescription().c_str());
78 std::vector
<SymbolFileDWARFDebugMap::CompileUnitInfo
*> cu_infos
;
79 if (exe_symfile
->GetCompUnitInfosForModule(oso_module
, cu_infos
)) {
80 for (auto comp_unit_info
: cu_infos
) {
81 Symtab
*exe_symtab
= exe_symfile
->GetObjectFile()->GetSymtab();
82 ModuleSP
oso_module_sp(oso_objfile
->GetModule());
83 Symtab
*oso_symtab
= oso_objfile
->GetSymtab();
85 /// const uint32_t fun_resolve_flags = SymbolContext::Module |
86 /// eSymbolContextCompUnit | eSymbolContextFunction;
87 // SectionList *oso_sections = oso_objfile->Sections();
88 // Now we need to make sections that map from zero based object file
89 // addresses to where things ended up in the main executable.
91 assert(comp_unit_info
->first_symbol_index
!= UINT32_MAX
);
92 // End index is one past the last valid symbol index
93 const uint32_t oso_end_idx
= comp_unit_info
->last_symbol_index
+ 1;
94 for (uint32_t idx
= comp_unit_info
->first_symbol_index
+
95 2; // Skip the N_SO and N_OSO
96 idx
< oso_end_idx
; ++idx
) {
97 Symbol
*exe_symbol
= exe_symtab
->SymbolAtIndex(idx
);
99 if (!exe_symbol
->IsDebug())
102 switch (exe_symbol
->GetType()) {
106 case eSymbolTypeCode
: {
107 // For each N_FUN, or function that we run into in the debug map we
108 // make a new section that we add to the sections found in the .o
109 // file. This new section has the file address set to what the
110 // addresses are in the .o file, and the load address is adjusted
111 // to match where it ended up in the final executable! We do this
112 // before we parse any dwarf info so that when it goes get parsed
113 // all section/offset addresses that get registered will resolve
114 // correctly to the new addresses in the main executable.
116 // First we find the original symbol in the .o file's symbol table
117 Symbol
*oso_fun_symbol
= oso_symtab
->FindFirstSymbolWithNameAndType(
118 exe_symbol
->GetMangled().GetName(Mangled::ePreferMangled
),
119 eSymbolTypeCode
, Symtab::eDebugNo
, Symtab::eVisibilityAny
);
120 if (oso_fun_symbol
) {
121 // Add the inverse OSO file address to debug map entry mapping
122 exe_symfile
->AddOSOFileRange(
123 this, exe_symbol
->GetAddressRef().GetFileAddress(),
124 exe_symbol
->GetByteSize(),
125 oso_fun_symbol
->GetAddressRef().GetFileAddress(),
126 oso_fun_symbol
->GetByteSize());
130 case eSymbolTypeData
: {
131 // For each N_GSYM we remap the address for the global by making a
132 // new section that we add to the sections found in the .o file.
133 // This new section has the file address set to what the addresses
134 // are in the .o file, and the load address is adjusted to match
135 // where it ended up in the final executable! We do this before we
136 // parse any dwarf info so that when it goes get parsed all
137 // section/offset addresses that get registered will resolve
138 // correctly to the new addresses in the main executable. We
139 // initially set the section size to be 1 byte, but will need to
140 // fix up these addresses further after all globals have been
141 // parsed to span the gaps, or we can find the global variable
142 // sizes from the DWARF info as we are parsing.
144 // Next we find the non-stab entry that corresponds to the N_GSYM
146 Symbol
*oso_gsym_symbol
=
147 oso_symtab
->FindFirstSymbolWithNameAndType(
148 exe_symbol
->GetMangled().GetName(Mangled::ePreferMangled
),
149 eSymbolTypeData
, Symtab::eDebugNo
, Symtab::eVisibilityAny
);
150 if (exe_symbol
&& oso_gsym_symbol
&& exe_symbol
->ValueIsAddress() &&
151 oso_gsym_symbol
->ValueIsAddress()) {
152 // Add the inverse OSO file address to debug map entry mapping
153 exe_symfile
->AddOSOFileRange(
154 this, exe_symbol
->GetAddressRef().GetFileAddress(),
155 exe_symbol
->GetByteSize(),
156 oso_gsym_symbol
->GetAddressRef().GetFileAddress(),
157 oso_gsym_symbol
->GetByteSize());
164 exe_symfile
->FinalizeOSOFileRanges(this);
165 // We don't need the symbols anymore for the .o files
166 oso_objfile
->ClearSymtab();
169 return file_range_map
;
172 namespace lldb_private::plugin
{
174 class DebugMapModule
: public Module
{
176 DebugMapModule(const ModuleSP
&exe_module_sp
, uint32_t cu_idx
,
177 const FileSpec
&file_spec
, const ArchSpec
&arch
,
178 ConstString object_name
, off_t object_offset
,
179 const llvm::sys::TimePoint
<> object_mod_time
)
180 : Module(file_spec
, arch
, object_name
, object_offset
, object_mod_time
),
181 m_exe_module_wp(exe_module_sp
), m_cu_idx(cu_idx
) {}
183 ~DebugMapModule() override
= default;
186 GetSymbolFile(bool can_create
= true,
187 lldb_private::Stream
*feedback_strm
= nullptr) override
{
189 if (m_symfile_up
.get() || !can_create
)
190 return m_symfile_up
? m_symfile_up
->GetSymbolFile() : nullptr;
192 ModuleSP
exe_module_sp(m_exe_module_wp
.lock());
194 // Now get the object file outside of a locking scope
195 ObjectFile
*oso_objfile
= GetObjectFile();
197 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
198 if (SymbolFile
*symfile
=
199 Module::GetSymbolFile(can_create
, feedback_strm
)) {
200 // Set a pointer to this class to set our OSO DWARF file know that
201 // the DWARF is being used along with a debug map and that it will
202 // have the remapped sections that we do below.
203 SymbolFileDWARF
*oso_symfile
=
204 SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(symfile
);
209 ObjectFile
*exe_objfile
= exe_module_sp
->GetObjectFile();
210 SymbolFile
*exe_symfile
= exe_module_sp
->GetSymbolFile();
212 if (exe_objfile
&& exe_symfile
) {
213 oso_symfile
->SetDebugMapModule(exe_module_sp
);
214 // Set the ID of the symbol file DWARF to the index of the OSO
215 // shifted left by 32 bits to provide a unique prefix for any
216 // UserID's that get created in the symbol file.
217 oso_symfile
->SetFileIndex((uint64_t)m_cu_idx
);
227 ModuleWP m_exe_module_wp
;
228 const uint32_t m_cu_idx
;
231 } // namespace lldb_private::plugin
233 void SymbolFileDWARFDebugMap::Initialize() {
234 PluginManager::RegisterPlugin(GetPluginNameStatic(),
235 GetPluginDescriptionStatic(), CreateInstance
);
238 void SymbolFileDWARFDebugMap::Terminate() {
239 PluginManager::UnregisterPlugin(CreateInstance
);
242 llvm::StringRef
SymbolFileDWARFDebugMap::GetPluginDescriptionStatic() {
243 return "DWARF and DWARF3 debug symbol file reader (debug map).";
246 SymbolFile
*SymbolFileDWARFDebugMap::CreateInstance(ObjectFileSP objfile_sp
) {
247 return new SymbolFileDWARFDebugMap(std::move(objfile_sp
));
250 SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap(ObjectFileSP objfile_sp
)
251 : SymbolFileCommon(std::move(objfile_sp
)), m_flags(), m_compile_unit_infos(),
252 m_func_indexes(), m_glob_indexes(),
253 m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate
) {}
255 SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() = default;
257 void SymbolFileDWARFDebugMap::InitializeObject() {}
259 void SymbolFileDWARFDebugMap::InitOSO() {
260 if (m_flags
.test(kHaveInitializedOSOs
))
263 m_flags
.set(kHaveInitializedOSOs
);
265 // If the object file has been stripped, there is no sense in looking further
266 // as all of the debug symbols for the debug map will not be available
267 if (m_objfile_sp
->IsStripped())
270 // Also make sure the file type is some sort of executable. Core files, debug
271 // info files (dSYM), object files (.o files), and stub libraries all can
272 switch (m_objfile_sp
->GetType()) {
273 case ObjectFile::eTypeInvalid
:
274 case ObjectFile::eTypeCoreFile
:
275 case ObjectFile::eTypeDebugInfo
:
276 case ObjectFile::eTypeObjectFile
:
277 case ObjectFile::eTypeStubLibrary
:
278 case ObjectFile::eTypeUnknown
:
279 case ObjectFile::eTypeJIT
:
282 case ObjectFile::eTypeExecutable
:
283 case ObjectFile::eTypeDynamicLinker
:
284 case ObjectFile::eTypeSharedLibrary
:
288 // In order to get the abilities of this plug-in, we look at the list of
289 // N_OSO entries (object files) from the symbol table and make sure that
290 // these files exist and also contain valid DWARF. If we get any of that then
291 // we return the abilities of the first N_OSO's DWARF.
293 Symtab
*symtab
= m_objfile_sp
->GetSymtab();
297 Log
*log
= GetLog(DWARFLog::DebugMap
);
299 std::vector
<uint32_t> oso_indexes
;
300 // When a mach-o symbol is encoded, the n_type field is encoded in bits
301 // 23:16, and the n_desc field is encoded in bits 15:0.
303 // To find all N_OSO entries that are part of the DWARF + debug map we find
304 // only object file symbols with the flags value as follows: bits 23:16 ==
305 // 0x66 (N_OSO) bits 15: 0 == 0x0001 (specifies this is a debug map object
307 const uint32_t k_oso_symbol_flags_value
= 0x660001u
;
309 const uint32_t oso_index_count
=
310 symtab
->AppendSymbolIndexesWithTypeAndFlagsValue(
311 eSymbolTypeObjectFile
, k_oso_symbol_flags_value
, oso_indexes
);
313 if (oso_index_count
== 0)
316 symtab
->AppendSymbolIndexesWithType(eSymbolTypeCode
, Symtab::eDebugYes
,
317 Symtab::eVisibilityAny
, m_func_indexes
);
318 symtab
->AppendSymbolIndexesWithType(eSymbolTypeData
, Symtab::eDebugYes
,
319 Symtab::eVisibilityAny
, m_glob_indexes
);
321 symtab
->SortSymbolIndexesByValue(m_func_indexes
, true);
322 symtab
->SortSymbolIndexesByValue(m_glob_indexes
, true);
324 for (uint32_t sym_idx
:
325 llvm::concat
<uint32_t>(m_func_indexes
, m_glob_indexes
)) {
326 const Symbol
*symbol
= symtab
->SymbolAtIndex(sym_idx
);
327 lldb::addr_t file_addr
= symbol
->GetAddressRef().GetFileAddress();
328 lldb::addr_t byte_size
= symbol
->GetByteSize();
329 DebugMap::Entry
debug_map_entry(file_addr
, byte_size
,
330 OSOEntry(sym_idx
, LLDB_INVALID_ADDRESS
));
331 m_debug_map
.Append(debug_map_entry
);
335 m_compile_unit_infos
.resize(oso_index_count
);
337 for (uint32_t i
= 0; i
< oso_index_count
; ++i
) {
338 const uint32_t so_idx
= oso_indexes
[i
] - 1;
339 const uint32_t oso_idx
= oso_indexes
[i
];
340 const Symbol
*so_symbol
= symtab
->SymbolAtIndex(so_idx
);
341 const Symbol
*oso_symbol
= symtab
->SymbolAtIndex(oso_idx
);
342 if (so_symbol
&& oso_symbol
&&
343 so_symbol
->GetType() == eSymbolTypeSourceFile
&&
344 oso_symbol
->GetType() == eSymbolTypeObjectFile
) {
345 m_compile_unit_infos
[i
].so_file
.SetFile(so_symbol
->GetName().AsCString(),
346 FileSpec::Style::native
);
347 m_compile_unit_infos
[i
].oso_path
= oso_symbol
->GetName();
348 m_compile_unit_infos
[i
].oso_mod_time
=
349 llvm::sys::toTimePoint(oso_symbol
->GetIntegerValue(0));
350 uint32_t sibling_idx
= so_symbol
->GetSiblingIndex();
351 // The sibling index can't be less that or equal to the current index
353 if (sibling_idx
<= i
|| sibling_idx
== UINT32_MAX
) {
354 m_objfile_sp
->GetModule()->ReportError(
355 "N_SO in symbol with UID {0} has invalid sibling in debug "
357 "please file a bug and attach the binary listed in this error",
360 const Symbol
*last_symbol
= symtab
->SymbolAtIndex(sibling_idx
- 1);
361 m_compile_unit_infos
[i
].first_symbol_index
= so_idx
;
362 m_compile_unit_infos
[i
].last_symbol_index
= sibling_idx
- 1;
363 m_compile_unit_infos
[i
].first_symbol_id
= so_symbol
->GetID();
364 m_compile_unit_infos
[i
].last_symbol_id
= last_symbol
->GetID();
366 LLDB_LOGF(log
, "Initialized OSO 0x%8.8x: file=%s", i
,
367 oso_symbol
->GetName().GetCString());
370 if (oso_symbol
== nullptr)
371 m_objfile_sp
->GetModule()->ReportError(
372 "N_OSO symbol[{0}] can't be found, please file a bug and "
374 "the binary listed in this error",
376 else if (so_symbol
== nullptr)
377 m_objfile_sp
->GetModule()->ReportError(
378 "N_SO not found for N_OSO symbol[{0}], please file a bug and "
379 "attach the binary listed in this error",
381 else if (so_symbol
->GetType() != eSymbolTypeSourceFile
)
382 m_objfile_sp
->GetModule()->ReportError(
383 "N_SO has incorrect symbol type ({0}) for N_OSO "
385 "please file a bug and attach the binary listed in this error",
386 so_symbol
->GetType(), oso_idx
);
387 else if (oso_symbol
->GetType() != eSymbolTypeSourceFile
)
388 m_objfile_sp
->GetModule()->ReportError(
389 "N_OSO has incorrect symbol type ({0}) for N_OSO "
391 "please file a bug and attach the binary listed in this error",
392 oso_symbol
->GetType(), oso_idx
);
397 Module
*SymbolFileDWARFDebugMap::GetModuleByOSOIndex(uint32_t oso_idx
) {
398 const uint32_t cu_count
= GetNumCompileUnits();
399 if (oso_idx
< cu_count
)
400 return GetModuleByCompUnitInfo(&m_compile_unit_infos
[oso_idx
]);
404 Module
*SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo(
405 CompileUnitInfo
*comp_unit_info
) {
406 if (!comp_unit_info
->oso_sp
) {
407 auto pos
= m_oso_map
.find(
408 {comp_unit_info
->oso_path
, comp_unit_info
->oso_mod_time
});
409 if (pos
!= m_oso_map
.end()) {
410 comp_unit_info
->oso_sp
= pos
->second
;
412 ObjectFile
*obj_file
= GetObjectFile();
413 comp_unit_info
->oso_sp
= std::make_shared
<OSOInfo
>();
414 m_oso_map
[{comp_unit_info
->oso_path
, comp_unit_info
->oso_mod_time
}] =
415 comp_unit_info
->oso_sp
;
416 const char *oso_path
= comp_unit_info
->oso_path
.GetCString();
417 FileSpec
oso_file(oso_path
);
418 ConstString oso_object
;
419 if (FileSystem::Instance().Exists(oso_file
)) {
420 // The modification time returned by the FS can have a higher precision
421 // than the one from the CU.
422 auto oso_mod_time
= std::chrono::time_point_cast
<std::chrono::seconds
>(
423 FileSystem::Instance().GetModificationTime(oso_file
));
424 // A timestamp of 0 means that the linker was in deterministic mode. In
425 // that case, we should skip the check against the filesystem last
426 // modification timestamp, since it will never match.
427 if (comp_unit_info
->oso_mod_time
!= llvm::sys::TimePoint
<>() &&
428 oso_mod_time
!= comp_unit_info
->oso_mod_time
) {
429 comp_unit_info
->oso_load_error
= Status::FromErrorStringWithFormat(
430 "debug map object file \"%s\" changed (actual: 0x%8.8x, debug "
431 "map: 0x%8.8x) since this executable was linked, debug info "
432 "will not be loaded",
433 oso_file
.GetPath().c_str(),
434 (uint32_t)llvm::sys::toTimeT(oso_mod_time
),
435 (uint32_t)llvm::sys::toTimeT(comp_unit_info
->oso_mod_time
));
436 obj_file
->GetModule()->ReportError(
437 "{0}", comp_unit_info
->oso_load_error
.AsCString());
442 const bool must_exist
= true;
444 if (!ObjectFile::SplitArchivePathWithObject(oso_path
, oso_file
,
445 oso_object
, must_exist
)) {
446 comp_unit_info
->oso_load_error
= Status::FromErrorStringWithFormat(
447 "debug map object file \"%s\" containing debug info does not "
448 "exist, debug info will not be loaded",
449 comp_unit_info
->oso_path
.GetCString());
453 // Always create a new module for .o files. Why? Because we use the debug
454 // map, to add new sections to each .o file and even though a .o file
455 // might not have changed, the sections that get added to the .o file can
458 // Only adopt the architecture from the module (not the vendor or OS)
459 // since .o files for "i386-apple-ios" will historically show up as "i386
460 // -apple-macosx" due to the lack of a LC_VERSION_MIN_MACOSX or
461 // LC_VERSION_MIN_IPHONEOS load command...
462 oso_arch
.SetTriple(m_objfile_sp
->GetModule()
468 comp_unit_info
->oso_sp
->module_sp
= std::make_shared
<DebugMapModule
>(
469 obj_file
->GetModule(), GetCompUnitInfoIndex(comp_unit_info
), oso_file
,
470 oso_arch
, oso_object
, 0,
471 oso_object
? comp_unit_info
->oso_mod_time
: llvm::sys::TimePoint
<>());
473 if (oso_object
&& !comp_unit_info
->oso_sp
->module_sp
->GetObjectFile() &&
474 FileSystem::Instance().Exists(oso_file
)) {
475 // If we are loading a .o file from a .a file the "oso_object" will
476 // have a valid value name and if the .a file exists, either the .o
477 // file didn't exist in the .a file or the mod time didn't match.
478 comp_unit_info
->oso_load_error
= Status::FromErrorStringWithFormat(
479 "\"%s\" object from the \"%s\" archive: "
480 "either the .o file doesn't exist in the archive or the "
481 "modification time (0x%8.8x) of the .o file doesn't match",
482 oso_object
.AsCString(), oso_file
.GetPath().c_str(),
483 (uint32_t)llvm::sys::toTimeT(comp_unit_info
->oso_mod_time
));
487 if (comp_unit_info
->oso_sp
)
488 return comp_unit_info
->oso_sp
->module_sp
.get();
492 bool SymbolFileDWARFDebugMap::GetFileSpecForSO(uint32_t oso_idx
,
493 FileSpec
&file_spec
) {
494 if (oso_idx
< m_compile_unit_infos
.size()) {
495 if (m_compile_unit_infos
[oso_idx
].so_file
) {
496 file_spec
= m_compile_unit_infos
[oso_idx
].so_file
;
503 ObjectFile
*SymbolFileDWARFDebugMap::GetObjectFileByOSOIndex(uint32_t oso_idx
) {
504 Module
*oso_module
= GetModuleByOSOIndex(oso_idx
);
506 return oso_module
->GetObjectFile();
511 SymbolFileDWARFDebugMap::GetSymbolFile(const SymbolContext
&sc
) {
512 return GetSymbolFile(*sc
.comp_unit
);
516 SymbolFileDWARFDebugMap::GetSymbolFile(const CompileUnit
&comp_unit
) {
517 CompileUnitInfo
*comp_unit_info
= GetCompUnitInfo(comp_unit
);
519 return GetSymbolFileByCompUnitInfo(comp_unit_info
);
523 ObjectFile
*SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo(
524 CompileUnitInfo
*comp_unit_info
) {
525 Module
*oso_module
= GetModuleByCompUnitInfo(comp_unit_info
);
527 return oso_module
->GetObjectFile();
531 uint32_t SymbolFileDWARFDebugMap::GetCompUnitInfoIndex(
532 const CompileUnitInfo
*comp_unit_info
) {
533 if (!m_compile_unit_infos
.empty()) {
534 const CompileUnitInfo
*first_comp_unit_info
= &m_compile_unit_infos
.front();
535 const CompileUnitInfo
*last_comp_unit_info
= &m_compile_unit_infos
.back();
536 if (first_comp_unit_info
<= comp_unit_info
&&
537 comp_unit_info
<= last_comp_unit_info
)
538 return comp_unit_info
- first_comp_unit_info
;
544 SymbolFileDWARFDebugMap::GetSymbolFileByOSOIndex(uint32_t oso_idx
) {
545 unsigned size
= m_compile_unit_infos
.size();
547 return GetSymbolFileByCompUnitInfo(&m_compile_unit_infos
[oso_idx
]);
552 SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(SymbolFile
*sym_file
) {
554 sym_file
->GetPluginName() == SymbolFileDWARF::GetPluginNameStatic())
555 return static_cast<SymbolFileDWARF
*>(sym_file
);
559 SymbolFileDWARF
*SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo(
560 CompileUnitInfo
*comp_unit_info
) {
561 if (Module
*oso_module
= GetModuleByCompUnitInfo(comp_unit_info
))
562 return GetSymbolFileAsSymbolFileDWARF(oso_module
->GetSymbolFile());
566 uint32_t SymbolFileDWARFDebugMap::CalculateAbilities() {
567 // In order to get the abilities of this plug-in, we look at the list of
568 // N_OSO entries (object files) from the symbol table and make sure that
569 // these files exist and also contain valid DWARF. If we get any of that then
570 // we return the abilities of the first N_OSO's DWARF.
572 const uint32_t oso_index_count
= GetNumCompileUnits();
573 if (oso_index_count
> 0) {
575 if (!m_compile_unit_infos
.empty()) {
576 return SymbolFile::CompileUnits
| SymbolFile::Functions
|
577 SymbolFile::Blocks
| SymbolFile::GlobalVariables
|
578 SymbolFile::LocalVariables
| SymbolFile::VariableTypes
|
579 SymbolFile::LineTables
;
585 uint32_t SymbolFileDWARFDebugMap::CalculateNumCompileUnits() {
587 return m_compile_unit_infos
.size();
590 CompUnitSP
SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx
) {
591 CompUnitSP comp_unit_sp
;
592 const uint32_t cu_count
= GetNumCompileUnits();
594 if (cu_idx
< cu_count
) {
595 auto &cu_info
= m_compile_unit_infos
[cu_idx
];
596 Module
*oso_module
= GetModuleByCompUnitInfo(&cu_info
);
598 FileSpec so_file_spec
;
599 if (GetFileSpecForSO(cu_idx
, so_file_spec
)) {
600 // User zero as the ID to match the compile unit at offset zero in each
602 lldb::user_id_t cu_id
= 0;
603 cu_info
.compile_units_sps
.push_back(std::make_shared
<CompileUnit
>(
604 m_objfile_sp
->GetModule(), nullptr,
605 std::make_shared
<SupportFile
>(so_file_spec
), cu_id
,
606 eLanguageTypeUnknown
, eLazyBoolCalculate
));
607 cu_info
.id_to_index_map
.insert({0, 0});
608 SetCompileUnitAtIndex(cu_idx
, cu_info
.compile_units_sps
[0]);
609 // If there's a symbol file also register all the extra compile units.
610 if (SymbolFileDWARF
*oso_symfile
=
611 GetSymbolFileByCompUnitInfo(&cu_info
)) {
612 auto num_dwarf_units
= oso_symfile
->DebugInfo().GetNumUnits();
613 for (size_t i
= 0; i
< num_dwarf_units
; ++i
) {
614 auto *dwarf_unit
= oso_symfile
->DebugInfo().GetUnitAtIndex(i
);
615 if (auto *dwarf_cu
= llvm::dyn_cast
<DWARFCompileUnit
>(dwarf_unit
)) {
616 // The "main" one was already registered.
617 if (dwarf_cu
->GetID() == 0)
619 cu_info
.compile_units_sps
.push_back(std::make_shared
<CompileUnit
>(
620 m_objfile_sp
->GetModule(), nullptr,
621 std::make_shared
<SupportFile
>(so_file_spec
),
622 dwarf_cu
->GetID(), eLanguageTypeUnknown
, eLazyBoolCalculate
));
623 cu_info
.id_to_index_map
.insert(
624 {dwarf_cu
->GetID(), cu_info
.compile_units_sps
.size() - 1});
630 if (!cu_info
.compile_units_sps
.empty())
631 comp_unit_sp
= cu_info
.compile_units_sps
[0];
637 SymbolFileDWARFDebugMap::CompileUnitInfo
*
638 SymbolFileDWARFDebugMap::GetCompUnitInfo(const SymbolContext
&sc
) {
639 return GetCompUnitInfo(*sc
.comp_unit
);
642 SymbolFileDWARFDebugMap::CompileUnitInfo
*
643 SymbolFileDWARFDebugMap::GetCompUnitInfo(const CompileUnit
&comp_unit
) {
644 const uint32_t cu_count
= GetNumCompileUnits();
645 for (uint32_t i
= 0; i
< cu_count
; ++i
) {
646 auto &id_to_index_map
= m_compile_unit_infos
[i
].id_to_index_map
;
648 auto it
= id_to_index_map
.find(comp_unit
.GetID());
649 if (it
!= id_to_index_map
.end() &&
651 m_compile_unit_infos
[i
].compile_units_sps
[it
->getSecond()].get())
652 return &m_compile_unit_infos
[i
];
657 size_t SymbolFileDWARFDebugMap::GetCompUnitInfosForModule(
658 const lldb_private::Module
*module
,
659 std::vector
<CompileUnitInfo
*> &cu_infos
) {
660 const uint32_t cu_count
= GetNumCompileUnits();
661 for (uint32_t i
= 0; i
< cu_count
; ++i
) {
662 if (module
== GetModuleByCompUnitInfo(&m_compile_unit_infos
[i
]))
663 cu_infos
.push_back(&m_compile_unit_infos
[i
]);
665 return cu_infos
.size();
669 SymbolFileDWARFDebugMap::ParseLanguage(CompileUnit
&comp_unit
) {
670 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
671 SymbolFileDWARF
*oso_dwarf
= GetSymbolFile(comp_unit
);
673 return oso_dwarf
->ParseLanguage(comp_unit
);
674 return eLanguageTypeUnknown
;
677 XcodeSDK
SymbolFileDWARFDebugMap::ParseXcodeSDK(CompileUnit
&comp_unit
) {
678 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
679 SymbolFileDWARF
*oso_dwarf
= GetSymbolFile(comp_unit
);
681 return oso_dwarf
->ParseXcodeSDK(comp_unit
);
685 llvm::SmallSet
<lldb::LanguageType
, 4>
686 SymbolFileDWARFDebugMap::ParseAllLanguages(
687 lldb_private::CompileUnit
&comp_unit
) {
688 llvm::SmallSet
<lldb::LanguageType
, 4> langs
;
689 auto *info
= GetCompUnitInfo(comp_unit
);
690 for (auto &comp_unit
: info
->compile_units_sps
) {
691 langs
.insert(comp_unit
->GetLanguage());
696 size_t SymbolFileDWARFDebugMap::ParseFunctions(CompileUnit
&comp_unit
) {
697 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
698 SymbolFileDWARF
*oso_dwarf
= GetSymbolFile(comp_unit
);
700 return oso_dwarf
->ParseFunctions(comp_unit
);
704 bool SymbolFileDWARFDebugMap::ParseLineTable(CompileUnit
&comp_unit
) {
705 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
706 SymbolFileDWARF
*oso_dwarf
= GetSymbolFile(comp_unit
);
708 return oso_dwarf
->ParseLineTable(comp_unit
);
712 bool SymbolFileDWARFDebugMap::ParseDebugMacros(CompileUnit
&comp_unit
) {
713 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
714 SymbolFileDWARF
*oso_dwarf
= GetSymbolFile(comp_unit
);
716 return oso_dwarf
->ParseDebugMacros(comp_unit
);
720 bool SymbolFileDWARFDebugMap::ForEachExternalModule(
721 CompileUnit
&comp_unit
,
722 llvm::DenseSet
<lldb_private::SymbolFile
*> &visited_symbol_files
,
723 llvm::function_ref
<bool(Module
&)> f
) {
724 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
725 SymbolFileDWARF
*oso_dwarf
= GetSymbolFile(comp_unit
);
727 return oso_dwarf
->ForEachExternalModule(comp_unit
, visited_symbol_files
, f
);
731 bool SymbolFileDWARFDebugMap::ParseSupportFiles(
732 CompileUnit
&comp_unit
, SupportFileList
&support_files
) {
733 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
734 SymbolFileDWARF
*oso_dwarf
= GetSymbolFile(comp_unit
);
736 return oso_dwarf
->ParseSupportFiles(comp_unit
, support_files
);
740 bool SymbolFileDWARFDebugMap::ParseIsOptimized(CompileUnit
&comp_unit
) {
741 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
742 SymbolFileDWARF
*oso_dwarf
= GetSymbolFile(comp_unit
);
744 return oso_dwarf
->ParseIsOptimized(comp_unit
);
748 bool SymbolFileDWARFDebugMap::ParseImportedModules(
749 const SymbolContext
&sc
, std::vector
<SourceModule
> &imported_modules
) {
750 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
751 SymbolFileDWARF
*oso_dwarf
= GetSymbolFile(sc
);
753 return oso_dwarf
->ParseImportedModules(sc
, imported_modules
);
757 size_t SymbolFileDWARFDebugMap::ParseBlocksRecursive(Function
&func
) {
758 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
759 CompileUnit
*comp_unit
= func
.GetCompileUnit();
763 SymbolFileDWARF
*oso_dwarf
= GetSymbolFile(*comp_unit
);
765 return oso_dwarf
->ParseBlocksRecursive(func
);
769 size_t SymbolFileDWARFDebugMap::ParseTypes(CompileUnit
&comp_unit
) {
770 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
771 SymbolFileDWARF
*oso_dwarf
= GetSymbolFile(comp_unit
);
773 return oso_dwarf
->ParseTypes(comp_unit
);
778 SymbolFileDWARFDebugMap::ParseVariablesForContext(const SymbolContext
&sc
) {
779 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
780 SymbolFileDWARF
*oso_dwarf
= GetSymbolFile(sc
);
782 return oso_dwarf
->ParseVariablesForContext(sc
);
786 Type
*SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid
) {
787 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
788 const uint64_t oso_idx
= GetOSOIndexFromUserID(type_uid
);
789 SymbolFileDWARF
*oso_dwarf
= GetSymbolFileByOSOIndex(oso_idx
);
791 return oso_dwarf
->ResolveTypeUID(type_uid
);
795 std::optional
<SymbolFile::ArrayInfo
>
796 SymbolFileDWARFDebugMap::GetDynamicArrayInfoForUID(
797 lldb::user_id_t type_uid
, const lldb_private::ExecutionContext
*exe_ctx
) {
798 const uint64_t oso_idx
= GetOSOIndexFromUserID(type_uid
);
799 SymbolFileDWARF
*oso_dwarf
= GetSymbolFileByOSOIndex(oso_idx
);
801 return oso_dwarf
->GetDynamicArrayInfoForUID(type_uid
, exe_ctx
);
805 bool SymbolFileDWARFDebugMap::CompleteType(CompilerType
&compiler_type
) {
806 bool success
= false;
808 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
809 if (oso_dwarf
->HasForwardDeclForCompilerType(compiler_type
)) {
810 oso_dwarf
->CompleteType(compiler_type
);
812 return IterationAction::Stop
;
814 return IterationAction::Continue
;
821 SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address
&exe_so_addr
,
822 SymbolContextItem resolve_scope
,
824 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
825 uint32_t resolved_flags
= 0;
826 Symtab
*symtab
= m_objfile_sp
->GetSymtab();
828 const addr_t exe_file_addr
= exe_so_addr
.GetFileAddress();
830 const DebugMap::Entry
*debug_map_entry
=
831 m_debug_map
.FindEntryThatContains(exe_file_addr
);
832 if (debug_map_entry
) {
835 symtab
->SymbolAtIndex(debug_map_entry
->data
.GetExeSymbolIndex());
837 if (sc
.symbol
!= nullptr) {
838 resolved_flags
|= eSymbolContextSymbol
;
840 uint32_t oso_idx
= 0;
841 CompileUnitInfo
*comp_unit_info
=
842 GetCompileUnitInfoForSymbolWithID(sc
.symbol
->GetID(), &oso_idx
);
843 if (comp_unit_info
) {
844 comp_unit_info
->GetFileRangeMap(this);
845 Module
*oso_module
= GetModuleByCompUnitInfo(comp_unit_info
);
847 lldb::addr_t oso_file_addr
=
848 exe_file_addr
- debug_map_entry
->GetRangeBase() +
849 debug_map_entry
->data
.GetOSOFileAddress();
851 if (oso_module
->ResolveFileAddress(oso_file_addr
, oso_so_addr
)) {
852 if (SymbolFile
*sym_file
= oso_module
->GetSymbolFile()) {
853 resolved_flags
|= sym_file
->ResolveSymbolContext(
854 oso_so_addr
, resolve_scope
, sc
);
856 ObjectFile
*obj_file
= GetObjectFile();
857 LLDB_LOG(GetLog(DWARFLog::DebugMap
),
858 "Failed to get symfile for OSO: {0} in module: {1}",
859 oso_module
->GetFileSpec(),
860 obj_file
? obj_file
->GetFileSpec()
861 : FileSpec("unknown"));
869 return resolved_flags
;
872 uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
873 const SourceLocationSpec
&src_location_spec
,
874 SymbolContextItem resolve_scope
, SymbolContextList
&sc_list
) {
875 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
876 const uint32_t initial
= sc_list
.GetSize();
877 const uint32_t cu_count
= GetNumCompileUnits();
879 for (uint32_t i
= 0; i
< cu_count
; ++i
) {
880 // If we are checking for inlines, then we need to look through all compile
881 // units no matter if "file_spec" matches.
882 bool resolve
= src_location_spec
.GetCheckInlines();
885 FileSpec so_file_spec
;
886 if (GetFileSpecForSO(i
, so_file_spec
))
888 FileSpec::Match(src_location_spec
.GetFileSpec(), so_file_spec
);
891 SymbolFileDWARF
*oso_dwarf
= GetSymbolFileByOSOIndex(i
);
893 oso_dwarf
->ResolveSymbolContext(src_location_spec
, resolve_scope
,
897 return sc_list
.GetSize() - initial
;
900 void SymbolFileDWARFDebugMap::PrivateFindGlobalVariables(
901 ConstString name
, const CompilerDeclContext
&parent_decl_ctx
,
902 const std::vector
<uint32_t>
903 &indexes
, // Indexes into the symbol table that match "name"
904 uint32_t max_matches
, VariableList
&variables
) {
905 const size_t match_count
= indexes
.size();
906 for (size_t i
= 0; i
< match_count
; ++i
) {
908 CompileUnitInfo
*comp_unit_info
=
909 GetCompileUnitInfoForSymbolWithIndex(indexes
[i
], &oso_idx
);
910 if (comp_unit_info
) {
911 SymbolFileDWARF
*oso_dwarf
= GetSymbolFileByOSOIndex(oso_idx
);
913 oso_dwarf
->FindGlobalVariables(name
, parent_decl_ctx
, max_matches
,
915 if (variables
.GetSize() > max_matches
)
922 void SymbolFileDWARFDebugMap::FindGlobalVariables(
923 ConstString name
, const CompilerDeclContext
&parent_decl_ctx
,
924 uint32_t max_matches
, VariableList
&variables
) {
925 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
926 uint32_t total_matches
= 0;
928 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
929 const uint32_t old_size
= variables
.GetSize();
930 oso_dwarf
->FindGlobalVariables(name
, parent_decl_ctx
, max_matches
,
932 const uint32_t oso_matches
= variables
.GetSize() - old_size
;
933 if (oso_matches
> 0) {
934 total_matches
+= oso_matches
;
936 // Are we getting all matches?
937 if (max_matches
== UINT32_MAX
)
938 return IterationAction::Continue
; // Yep, continue getting everything
940 // If we have found enough matches, lets get out
941 if (max_matches
>= total_matches
)
942 return IterationAction::Stop
;
944 // Update the max matches for any subsequent calls to find globals in any
945 // other object files with DWARF
946 max_matches
-= oso_matches
;
949 return IterationAction::Continue
;
953 void SymbolFileDWARFDebugMap::FindGlobalVariables(
954 const RegularExpression
®ex
, uint32_t max_matches
,
955 VariableList
&variables
) {
956 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
957 uint32_t total_matches
= 0;
958 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
959 const uint32_t old_size
= variables
.GetSize();
960 oso_dwarf
->FindGlobalVariables(regex
, max_matches
, variables
);
962 const uint32_t oso_matches
= variables
.GetSize() - old_size
;
963 if (oso_matches
> 0) {
964 total_matches
+= oso_matches
;
966 // Are we getting all matches?
967 if (max_matches
== UINT32_MAX
)
968 return IterationAction::Continue
; // Yep, continue getting everything
970 // If we have found enough matches, lets get out
971 if (max_matches
>= total_matches
)
972 return IterationAction::Stop
;
974 // Update the max matches for any subsequent calls to find globals in any
975 // other object files with DWARF
976 max_matches
-= oso_matches
;
979 return IterationAction::Continue
;
983 int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex(
984 uint32_t *symbol_idx_ptr
, const CompileUnitInfo
*comp_unit_info
) {
985 const uint32_t symbol_idx
= *symbol_idx_ptr
;
987 if (symbol_idx
< comp_unit_info
->first_symbol_index
)
990 if (symbol_idx
<= comp_unit_info
->last_symbol_index
)
996 int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID(
997 user_id_t
*symbol_idx_ptr
, const CompileUnitInfo
*comp_unit_info
) {
998 const user_id_t symbol_id
= *symbol_idx_ptr
;
1000 if (symbol_id
< comp_unit_info
->first_symbol_id
)
1003 if (symbol_id
<= comp_unit_info
->last_symbol_id
)
1009 SymbolFileDWARFDebugMap::CompileUnitInfo
*
1010 SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex(
1011 uint32_t symbol_idx
, uint32_t *oso_idx_ptr
) {
1012 const uint32_t oso_index_count
= m_compile_unit_infos
.size();
1013 CompileUnitInfo
*comp_unit_info
= nullptr;
1014 if (oso_index_count
) {
1015 comp_unit_info
= (CompileUnitInfo
*)bsearch(
1016 &symbol_idx
, &m_compile_unit_infos
[0], m_compile_unit_infos
.size(),
1017 sizeof(CompileUnitInfo
),
1018 (ComparisonFunction
)SymbolContainsSymbolWithIndex
);
1022 if (comp_unit_info
!= nullptr)
1023 *oso_idx_ptr
= comp_unit_info
- &m_compile_unit_infos
[0];
1025 *oso_idx_ptr
= UINT32_MAX
;
1027 return comp_unit_info
;
1030 SymbolFileDWARFDebugMap::CompileUnitInfo
*
1031 SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID(
1032 user_id_t symbol_id
, uint32_t *oso_idx_ptr
) {
1033 const uint32_t oso_index_count
= m_compile_unit_infos
.size();
1034 CompileUnitInfo
*comp_unit_info
= nullptr;
1035 if (oso_index_count
) {
1036 comp_unit_info
= (CompileUnitInfo
*)::bsearch(
1037 &symbol_id
, &m_compile_unit_infos
[0], m_compile_unit_infos
.size(),
1038 sizeof(CompileUnitInfo
),
1039 (ComparisonFunction
)SymbolContainsSymbolWithID
);
1043 if (comp_unit_info
!= nullptr)
1044 *oso_idx_ptr
= comp_unit_info
- &m_compile_unit_infos
[0];
1046 *oso_idx_ptr
= UINT32_MAX
;
1048 return comp_unit_info
;
1051 static void RemoveFunctionsWithModuleNotEqualTo(const ModuleSP
&module_sp
,
1052 SymbolContextList
&sc_list
,
1053 uint32_t start_idx
) {
1054 // We found functions in .o files. Not all functions in the .o files will
1055 // have made it into the final output file. The ones that did make it into
1056 // the final output file will have a section whose module matches the module
1057 // from the ObjectFile for this SymbolFile. When the modules don't match,
1058 // then we have something that was in a .o file, but doesn't map to anything
1059 // in the final executable.
1060 uint32_t i
= start_idx
;
1061 while (i
< sc_list
.GetSize()) {
1063 sc_list
.GetContextAtIndex(i
, sc
);
1065 const SectionSP
section_sp(
1066 sc
.function
->GetAddressRange().GetBaseAddress().GetSection());
1067 if (section_sp
->GetModule() != module_sp
) {
1068 sc_list
.RemoveContextAtIndex(i
);
1076 void SymbolFileDWARFDebugMap::FindFunctions(
1077 const Module::LookupInfo
&lookup_info
,
1078 const CompilerDeclContext
&parent_decl_ctx
, bool include_inlines
,
1079 SymbolContextList
&sc_list
) {
1080 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
1081 LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::FindFunctions (name = %s)",
1082 lookup_info
.GetLookupName().GetCString());
1084 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
1085 uint32_t sc_idx
= sc_list
.GetSize();
1086 oso_dwarf
->FindFunctions(lookup_info
, parent_decl_ctx
, include_inlines
,
1088 if (!sc_list
.IsEmpty()) {
1089 RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp
->GetModule(), sc_list
,
1092 return IterationAction::Continue
;
1096 void SymbolFileDWARFDebugMap::FindFunctions(const RegularExpression
®ex
,
1097 bool include_inlines
,
1098 SymbolContextList
&sc_list
) {
1099 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
1100 LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::FindFunctions (regex = '%s')",
1101 regex
.GetText().str().c_str());
1103 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
1104 uint32_t sc_idx
= sc_list
.GetSize();
1106 oso_dwarf
->FindFunctions(regex
, include_inlines
, sc_list
);
1107 if (!sc_list
.IsEmpty()) {
1108 RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp
->GetModule(), sc_list
,
1111 return IterationAction::Continue
;
1115 void SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope
*sc_scope
,
1116 lldb::TypeClass type_mask
,
1117 TypeList
&type_list
) {
1118 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
1119 LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)",
1122 SymbolFileDWARF
*oso_dwarf
= nullptr;
1125 sc_scope
->CalculateSymbolContext(&sc
);
1127 CompileUnitInfo
*cu_info
= GetCompUnitInfo(sc
);
1129 oso_dwarf
= GetSymbolFileByCompUnitInfo(cu_info
);
1131 oso_dwarf
->GetTypes(sc_scope
, type_mask
, type_list
);
1134 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
1135 oso_dwarf
->GetTypes(sc_scope
, type_mask
, type_list
);
1136 return IterationAction::Continue
;
1141 std::vector
<std::unique_ptr
<lldb_private::CallEdge
>>
1142 SymbolFileDWARFDebugMap::ParseCallEdgesInFunction(
1143 lldb_private::UserID func_id
) {
1144 uint32_t oso_idx
= GetOSOIndexFromUserID(func_id
.GetID());
1145 SymbolFileDWARF
*oso_dwarf
= GetSymbolFileByOSOIndex(oso_idx
);
1147 return oso_dwarf
->ParseCallEdgesInFunction(func_id
);
1151 DWARFDIE
SymbolFileDWARFDebugMap::FindDefinitionDIE(const DWARFDIE
&die
) {
1153 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
1154 result
= oso_dwarf
->FindDefinitionDIE(die
);
1155 return result
? IterationAction::Stop
: IterationAction::Continue
;
1160 bool SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type(
1161 SymbolFileDWARF
*skip_dwarf_oso
) {
1162 if (m_supports_DW_AT_APPLE_objc_complete_type
== eLazyBoolCalculate
) {
1163 m_supports_DW_AT_APPLE_objc_complete_type
= eLazyBoolNo
;
1164 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
1165 if (skip_dwarf_oso
!= oso_dwarf
&&
1166 oso_dwarf
->Supports_DW_AT_APPLE_objc_complete_type(nullptr)) {
1167 m_supports_DW_AT_APPLE_objc_complete_type
= eLazyBoolYes
;
1168 return IterationAction::Stop
;
1170 return IterationAction::Continue
;
1173 return m_supports_DW_AT_APPLE_objc_complete_type
== eLazyBoolYes
;
1176 TypeSP
SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
1177 const DWARFDIE
&die
, ConstString type_name
,
1178 bool must_be_implementation
) {
1179 // If we have a debug map, we will have an Objective-C symbol whose name is
1180 // the type name and whose type is eSymbolTypeObjCClass. If we can find that
1181 // symbol and find its containing parent, we can locate the .o file that will
1182 // contain the implementation definition since it will be scoped inside the
1183 // N_SO and we can then locate the SymbolFileDWARF that corresponds to that
1185 SymbolFileDWARF
*oso_dwarf
= nullptr;
1187 ObjectFile
*module_objfile
= m_objfile_sp
->GetModule()->GetObjectFile();
1188 if (module_objfile
) {
1189 Symtab
*symtab
= module_objfile
->GetSymtab();
1191 Symbol
*objc_class_symbol
= symtab
->FindFirstSymbolWithNameAndType(
1192 type_name
, eSymbolTypeObjCClass
, Symtab::eDebugAny
,
1193 Symtab::eVisibilityAny
);
1194 if (objc_class_symbol
) {
1195 // Get the N_SO symbol that contains the objective C class symbol as
1196 // this should be the .o file that contains the real definition...
1197 const Symbol
*source_file_symbol
= symtab
->GetParent(objc_class_symbol
);
1199 if (source_file_symbol
&&
1200 source_file_symbol
->GetType() == eSymbolTypeSourceFile
) {
1201 const uint32_t source_file_symbol_idx
=
1202 symtab
->GetIndexForSymbol(source_file_symbol
);
1203 if (source_file_symbol_idx
!= UINT32_MAX
) {
1204 CompileUnitInfo
*compile_unit_info
=
1205 GetCompileUnitInfoForSymbolWithIndex(source_file_symbol_idx
,
1207 if (compile_unit_info
) {
1208 oso_dwarf
= GetSymbolFileByCompUnitInfo(compile_unit_info
);
1210 TypeSP
type_sp(oso_dwarf
->FindCompleteObjCDefinitionTypeForDIE(
1211 die
, type_name
, must_be_implementation
));
1223 // Only search all .o files for the definition if we don't need the
1224 // implementation because otherwise, with a valid debug map we should have
1225 // the ObjC class symbol and the code above should have found it.
1226 if (!must_be_implementation
) {
1229 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
1230 type_sp
= oso_dwarf
->FindCompleteObjCDefinitionTypeForDIE(
1231 die
, type_name
, must_be_implementation
);
1232 return type_sp
? IterationAction::Stop
: IterationAction::Continue
;
1240 void SymbolFileDWARFDebugMap::FindTypes(const TypeQuery
&query
,
1241 TypeResults
&results
) {
1242 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
1243 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
1244 oso_dwarf
->FindTypes(query
, results
);
1245 return results
.Done(query
) ? IterationAction::Stop
1246 : IterationAction::Continue
;
1250 CompilerDeclContext
SymbolFileDWARFDebugMap::FindNamespace(
1251 lldb_private::ConstString name
, const CompilerDeclContext
&parent_decl_ctx
,
1252 bool only_root_namespaces
) {
1253 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
1254 CompilerDeclContext matching_namespace
;
1256 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
1257 matching_namespace
=
1258 oso_dwarf
->FindNamespace(name
, parent_decl_ctx
, only_root_namespaces
);
1260 return matching_namespace
? IterationAction::Stop
1261 : IterationAction::Continue
;
1264 return matching_namespace
;
1267 void SymbolFileDWARFDebugMap::DumpClangAST(Stream
&s
) {
1268 ForEachSymbolFile([&s
](SymbolFileDWARF
*oso_dwarf
) {
1269 oso_dwarf
->DumpClangAST(s
);
1270 // The underlying assumption is that DumpClangAST(...) will obtain the
1271 // AST from the underlying TypeSystem and therefore we only need to do
1272 // this once and can stop after the first iteration hence we return true.
1273 return IterationAction::Stop
;
1277 bool SymbolFileDWARFDebugMap::GetSeparateDebugInfo(
1278 lldb_private::StructuredData::Dictionary
&d
, bool errors_only
) {
1279 StructuredData::Array separate_debug_info_files
;
1280 const uint32_t cu_count
= GetNumCompileUnits();
1281 for (uint32_t cu_idx
= 0; cu_idx
< cu_count
; ++cu_idx
) {
1282 const auto &info
= m_compile_unit_infos
[cu_idx
];
1283 StructuredData::DictionarySP oso_data
=
1284 std::make_shared
<StructuredData::Dictionary
>();
1285 oso_data
->AddStringItem("so_file", info
.so_file
.GetPath());
1286 oso_data
->AddStringItem("oso_path", info
.oso_path
);
1287 oso_data
->AddIntegerItem("oso_mod_time",
1288 (uint32_t)llvm::sys::toTimeT(info
.oso_mod_time
));
1290 bool loaded_successfully
= false;
1291 if (GetModuleByOSOIndex(cu_idx
)) {
1292 // If we have a valid pointer to the module, we successfully
1293 // loaded the oso if there are no load errors.
1294 if (!info
.oso_load_error
.Fail()) {
1295 loaded_successfully
= true;
1298 if (!loaded_successfully
) {
1299 oso_data
->AddStringItem("error", info
.oso_load_error
.AsCString());
1301 oso_data
->AddBooleanItem("loaded", loaded_successfully
);
1302 if (!errors_only
|| oso_data
->HasKey("error"))
1303 separate_debug_info_files
.AddItem(oso_data
);
1306 d
.AddStringItem("type", "oso");
1307 d
.AddStringItem("symfile", GetMainObjectFile()->GetFileSpec().GetPath());
1308 d
.AddItem("separate-debug-info-files",
1309 std::make_shared
<StructuredData::Array
>(
1310 std::move(separate_debug_info_files
)));
1315 SymbolFileDWARFDebugMap::GetCompileUnit(SymbolFileDWARF
*oso_dwarf
, DWARFCompileUnit
&dwarf_cu
) {
1317 const uint32_t cu_count
= GetNumCompileUnits();
1318 for (uint32_t cu_idx
= 0; cu_idx
< cu_count
; ++cu_idx
) {
1319 SymbolFileDWARF
*oso_symfile
=
1320 GetSymbolFileByCompUnitInfo(&m_compile_unit_infos
[cu_idx
]);
1321 if (oso_symfile
== oso_dwarf
) {
1322 if (m_compile_unit_infos
[cu_idx
].compile_units_sps
.empty())
1323 ParseCompileUnitAtIndex(cu_idx
);
1325 auto &id_to_index_map
= m_compile_unit_infos
[cu_idx
].id_to_index_map
;
1326 auto it
= id_to_index_map
.find(dwarf_cu
.GetID());
1327 if (it
!= id_to_index_map
.end())
1328 return m_compile_unit_infos
[cu_idx
]
1329 .compile_units_sps
[it
->getSecond()];
1333 llvm_unreachable("this shouldn't happen");
1336 SymbolFileDWARFDebugMap::CompileUnitInfo
*
1337 SymbolFileDWARFDebugMap::GetCompileUnitInfo(SymbolFileDWARF
*oso_dwarf
) {
1339 const uint32_t cu_count
= GetNumCompileUnits();
1340 for (uint32_t cu_idx
= 0; cu_idx
< cu_count
; ++cu_idx
) {
1341 SymbolFileDWARF
*oso_symfile
=
1342 GetSymbolFileByCompUnitInfo(&m_compile_unit_infos
[cu_idx
]);
1343 if (oso_symfile
== oso_dwarf
) {
1344 return &m_compile_unit_infos
[cu_idx
];
1351 void SymbolFileDWARFDebugMap::SetCompileUnit(SymbolFileDWARF
*oso_dwarf
,
1352 const CompUnitSP
&cu_sp
) {
1354 const uint32_t cu_count
= GetNumCompileUnits();
1355 for (uint32_t cu_idx
= 0; cu_idx
< cu_count
; ++cu_idx
) {
1356 SymbolFileDWARF
*oso_symfile
=
1357 GetSymbolFileByCompUnitInfo(&m_compile_unit_infos
[cu_idx
]);
1358 if (oso_symfile
== oso_dwarf
) {
1359 if (!m_compile_unit_infos
[cu_idx
].compile_units_sps
.empty()) {
1360 assert(m_compile_unit_infos
[cu_idx
].compile_units_sps
[0].get() ==
1363 assert(cu_sp
->GetID() == 0 &&
1364 "Setting first compile unit but with id different than 0!");
1365 auto &compile_units_sps
= m_compile_unit_infos
[cu_idx
].compile_units_sps
;
1366 compile_units_sps
.push_back(cu_sp
);
1367 m_compile_unit_infos
[cu_idx
].id_to_index_map
.insert(
1368 {cu_sp
->GetID(), compile_units_sps
.size() - 1});
1370 SetCompileUnitAtIndex(cu_idx
, cu_sp
);
1378 SymbolFileDWARFDebugMap::GetDeclContextForUID(lldb::user_id_t type_uid
) {
1379 const uint64_t oso_idx
= GetOSOIndexFromUserID(type_uid
);
1380 if (SymbolFileDWARF
*oso_dwarf
= GetSymbolFileByOSOIndex(oso_idx
))
1381 return oso_dwarf
->GetDeclContextForUID(type_uid
);
1386 SymbolFileDWARFDebugMap::GetDeclContextContainingUID(lldb::user_id_t type_uid
) {
1387 const uint64_t oso_idx
= GetOSOIndexFromUserID(type_uid
);
1388 if (SymbolFileDWARF
*oso_dwarf
= GetSymbolFileByOSOIndex(oso_idx
))
1389 return oso_dwarf
->GetDeclContextContainingUID(type_uid
);
1393 std::vector
<CompilerContext
>
1394 SymbolFileDWARFDebugMap::GetCompilerContextForUID(lldb::user_id_t type_uid
) {
1395 const uint64_t oso_idx
= GetOSOIndexFromUserID(type_uid
);
1396 if (SymbolFileDWARF
*oso_dwarf
= GetSymbolFileByOSOIndex(oso_idx
))
1397 return oso_dwarf
->GetCompilerContextForUID(type_uid
);
1401 void SymbolFileDWARFDebugMap::ParseDeclsForContext(
1402 lldb_private::CompilerDeclContext decl_ctx
) {
1403 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
1404 oso_dwarf
->ParseDeclsForContext(decl_ctx
);
1405 return IterationAction::Continue
;
1409 bool SymbolFileDWARFDebugMap::AddOSOFileRange(CompileUnitInfo
*cu_info
,
1410 lldb::addr_t exe_file_addr
,
1411 lldb::addr_t exe_byte_size
,
1412 lldb::addr_t oso_file_addr
,
1413 lldb::addr_t oso_byte_size
) {
1414 const uint32_t debug_map_idx
=
1415 m_debug_map
.FindEntryIndexThatContains(exe_file_addr
);
1416 if (debug_map_idx
!= UINT32_MAX
) {
1417 DebugMap::Entry
*debug_map_entry
=
1418 m_debug_map
.FindEntryThatContains(exe_file_addr
);
1419 debug_map_entry
->data
.SetOSOFileAddress(oso_file_addr
);
1420 addr_t range_size
= std::min
<addr_t
>(exe_byte_size
, oso_byte_size
);
1421 if (range_size
== 0) {
1422 range_size
= std::max
<addr_t
>(exe_byte_size
, oso_byte_size
);
1423 if (range_size
== 0)
1426 cu_info
->file_range_map
.Append(
1427 FileRangeMap::Entry(oso_file_addr
, range_size
, exe_file_addr
));
1433 void SymbolFileDWARFDebugMap::FinalizeOSOFileRanges(CompileUnitInfo
*cu_info
) {
1434 cu_info
->file_range_map
.Sort();
1435 #if defined(DEBUG_OSO_DMAP)
1436 const FileRangeMap
&oso_file_range_map
= cu_info
->GetFileRangeMap(this);
1437 const size_t n
= oso_file_range_map
.GetSize();
1438 printf("SymbolFileDWARFDebugMap::FinalizeOSOFileRanges (cu_info = %p) %s\n",
1439 cu_info
, cu_info
->oso_sp
->module_sp
->GetFileSpec().GetPath().c_str());
1440 for (size_t i
= 0; i
< n
; ++i
) {
1441 const FileRangeMap::Entry
&entry
= oso_file_range_map
.GetEntryRef(i
);
1442 printf("oso [0x%16.16" PRIx64
" - 0x%16.16" PRIx64
1443 ") ==> exe [0x%16.16" PRIx64
" - 0x%16.16" PRIx64
")\n",
1444 entry
.GetRangeBase(), entry
.GetRangeEnd(), entry
.data
,
1445 entry
.data
+ entry
.GetByteSize());
1451 SymbolFileDWARFDebugMap::LinkOSOFileAddress(SymbolFileDWARF
*oso_symfile
,
1452 lldb::addr_t oso_file_addr
) {
1453 CompileUnitInfo
*cu_info
= GetCompileUnitInfo(oso_symfile
);
1455 const FileRangeMap::Entry
*oso_range_entry
=
1456 cu_info
->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr
);
1457 if (oso_range_entry
) {
1458 const DebugMap::Entry
*debug_map_entry
=
1459 m_debug_map
.FindEntryThatContains(oso_range_entry
->data
);
1460 if (debug_map_entry
) {
1461 const lldb::addr_t offset
=
1462 oso_file_addr
- oso_range_entry
->GetRangeBase();
1463 const lldb::addr_t exe_file_addr
=
1464 debug_map_entry
->GetRangeBase() + offset
;
1465 return exe_file_addr
;
1469 return LLDB_INVALID_ADDRESS
;
1472 bool SymbolFileDWARFDebugMap::LinkOSOAddress(Address
&addr
) {
1473 // Make sure this address hasn't been fixed already
1474 Module
*exe_module
= GetObjectFile()->GetModule().get();
1475 Module
*addr_module
= addr
.GetModule().get();
1476 if (addr_module
== exe_module
)
1477 return true; // Address is already in terms of the main executable module
1479 CompileUnitInfo
*cu_info
= GetCompileUnitInfo(
1480 GetSymbolFileAsSymbolFileDWARF(addr_module
->GetSymbolFile()));
1482 const lldb::addr_t oso_file_addr
= addr
.GetFileAddress();
1483 const FileRangeMap::Entry
*oso_range_entry
=
1484 cu_info
->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr
);
1485 if (oso_range_entry
) {
1486 const DebugMap::Entry
*debug_map_entry
=
1487 m_debug_map
.FindEntryThatContains(oso_range_entry
->data
);
1488 if (debug_map_entry
) {
1489 const lldb::addr_t offset
=
1490 oso_file_addr
- oso_range_entry
->GetRangeBase();
1491 const lldb::addr_t exe_file_addr
=
1492 debug_map_entry
->GetRangeBase() + offset
;
1493 return exe_module
->ResolveFileAddress(exe_file_addr
, addr
);
1500 LineTable
*SymbolFileDWARFDebugMap::LinkOSOLineTable(SymbolFileDWARF
*oso_dwarf
,
1501 LineTable
*line_table
) {
1502 CompileUnitInfo
*cu_info
= GetCompileUnitInfo(oso_dwarf
);
1504 return line_table
->LinkLineTable(cu_info
->GetFileRangeMap(this));
1509 SymbolFileDWARFDebugMap::AddOSOARanges(SymbolFileDWARF
*dwarf2Data
,
1510 DWARFDebugAranges
*debug_aranges
) {
1511 size_t num_line_entries_added
= 0;
1512 if (debug_aranges
&& dwarf2Data
) {
1513 CompileUnitInfo
*compile_unit_info
= GetCompileUnitInfo(dwarf2Data
);
1514 if (compile_unit_info
) {
1515 const FileRangeMap
&file_range_map
=
1516 compile_unit_info
->GetFileRangeMap(this);
1517 for (size_t idx
= 0; idx
< file_range_map
.GetSize(); idx
++) {
1518 const FileRangeMap::Entry
*entry
= file_range_map
.GetEntryAtIndex(idx
);
1520 debug_aranges
->AppendRange(*dwarf2Data
->GetFileIndex(),
1521 entry
->GetRangeBase(),
1522 entry
->GetRangeEnd());
1523 num_line_entries_added
++;
1528 return num_line_entries_added
;
1531 ModuleList
SymbolFileDWARFDebugMap::GetDebugInfoModules() {
1532 ModuleList oso_modules
;
1533 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
1534 ObjectFile
*oso_objfile
= oso_dwarf
->GetObjectFile();
1536 ModuleSP module_sp
= oso_objfile
->GetModule();
1538 oso_modules
.Append(module_sp
);
1540 return IterationAction::Continue
;
1545 Status
SymbolFileDWARFDebugMap::CalculateFrameVariableError(StackFrame
&frame
) {
1546 std::lock_guard
<std::recursive_mutex
> guard(GetModuleMutex());
1548 // We need to make sure that our PC value from the frame matches the module
1549 // for this object file since we will lookup the PC file address in the debug
1551 Address pc_addr
= frame
.GetFrameCodeAddress();
1552 if (pc_addr
.GetModule() == m_objfile_sp
->GetModule()) {
1553 Symtab
*symtab
= m_objfile_sp
->GetSymtab();
1555 const DebugMap::Entry
*debug_map_entry
=
1556 m_debug_map
.FindEntryThatContains(pc_addr
.GetFileAddress());
1557 if (debug_map_entry
) {
1559 symtab
->SymbolAtIndex(debug_map_entry
->data
.GetExeSymbolIndex());
1561 uint32_t oso_idx
= 0;
1562 CompileUnitInfo
*comp_unit_info
=
1563 GetCompileUnitInfoForSymbolWithID(symbol
->GetID(), &oso_idx
);
1564 if (comp_unit_info
) {
1565 Module
*oso_module
= GetModuleByCompUnitInfo(comp_unit_info
);
1567 // Check the .o file's DWARF in case it has an error to display.
1568 SymbolFile
*oso_sym_file
= oso_module
->GetSymbolFile();
1570 return oso_sym_file
->GetFrameVariableError(frame
);
1572 // If we don't have a valid OSO module here, then something went
1573 // wrong as we have a symbol for the address in the debug map, but
1574 // we weren't able to open the .o file. Display an appropriate
1576 if (comp_unit_info
->oso_load_error
.Fail())
1577 return comp_unit_info
->oso_load_error
.Clone();
1579 return Status::FromErrorStringWithFormat(
1580 "unable to load debug map object file \"%s\" "
1581 "exist, debug info will not be loaded",
1582 comp_unit_info
->oso_path
.GetCString());
1591 void SymbolFileDWARFDebugMap::GetCompileOptions(
1592 std::unordered_map
<lldb::CompUnitSP
, lldb_private::Args
> &args
) {
1594 ForEachSymbolFile([&](SymbolFileDWARF
*oso_dwarf
) {
1595 oso_dwarf
->GetCompileOptions(args
);
1596 return IterationAction::Continue
;