1 //===-- SymbolFileDWARFDebugMap.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 "SymbolFileDWARFDebugMap.h"
10 #include "DWARFCompileUnit.h"
11 #include "DWARFDebugAranges.h"
12 #include "DWARFDebugInfo.h"
13
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/Timer.h"
22 #include "lldb/Utility/StreamString.h"
23
24 //#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT
25 #if defined(DEBUG_OSO_DMAP)
26 #include "lldb/Core/StreamFile.h"
27 #endif
28
29 #include "lldb/Symbol/CompileUnit.h"
30 #include "lldb/Symbol/LineTable.h"
31 #include "lldb/Symbol/ObjectFile.h"
32 #include "lldb/Symbol/SymbolVendor.h"
33 #include "lldb/Symbol/TypeMap.h"
34 #include "lldb/Symbol/VariableList.h"
35 #include "llvm/Support/ScopedPrinter.h"
36
37 #include "lldb/Target/StackFrame.h"
38
39 #include "LogChannelDWARF.h"
40 #include "SymbolFileDWARF.h"
41
42 #include <memory>
43 #include <optional>
44
45 using namespace lldb;
46 using namespace lldb_private;
47
48 char SymbolFileDWARFDebugMap::ID;
49
50 // Subclass lldb_private::Module so we can intercept the
51 // "Module::GetObjectFile()" (so we can fixup the object file sections) and
52 // also for "Module::GetSymbolFile()" (so we can fixup the symbol file id.
53
54 const SymbolFileDWARFDebugMap::FileRangeMap &
GetFileRangeMap(SymbolFileDWARFDebugMap * exe_symfile)55 SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
56 SymbolFileDWARFDebugMap *exe_symfile) {
57 if (file_range_map_valid)
58 return file_range_map;
59
60 file_range_map_valid = true;
61
62 Module *oso_module = exe_symfile->GetModuleByCompUnitInfo(this);
63 if (!oso_module)
64 return file_range_map;
65
66 ObjectFile *oso_objfile = oso_module->GetObjectFile();
67 if (!oso_objfile)
68 return file_range_map;
69
70 Log *log = GetLog(DWARFLog::DebugMap);
71 LLDB_LOGF(
72 log,
73 "%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s')",
74 static_cast<void *>(this),
75 oso_module->GetSpecificationDescription().c_str());
76
77 std::vector<SymbolFileDWARFDebugMap::CompileUnitInfo *> cu_infos;
78 if (exe_symfile->GetCompUnitInfosForModule(oso_module, cu_infos)) {
79 for (auto comp_unit_info : cu_infos) {
80 Symtab *exe_symtab = exe_symfile->GetObjectFile()->GetSymtab();
81 ModuleSP oso_module_sp(oso_objfile->GetModule());
82 Symtab *oso_symtab = oso_objfile->GetSymtab();
83
84 /// const uint32_t fun_resolve_flags = SymbolContext::Module |
85 /// eSymbolContextCompUnit | eSymbolContextFunction;
86 // SectionList *oso_sections = oso_objfile->Sections();
87 // Now we need to make sections that map from zero based object file
88 // addresses to where things ended up in the main executable.
89
90 assert(comp_unit_info->first_symbol_index != UINT32_MAX);
91 // End index is one past the last valid symbol index
92 const uint32_t oso_end_idx = comp_unit_info->last_symbol_index + 1;
93 for (uint32_t idx = comp_unit_info->first_symbol_index +
94 2; // Skip the N_SO and N_OSO
95 idx < oso_end_idx; ++idx) {
96 Symbol *exe_symbol = exe_symtab->SymbolAtIndex(idx);
97 if (exe_symbol) {
98 if (!exe_symbol->IsDebug())
99 continue;
100
101 switch (exe_symbol->GetType()) {
102 default:
103 break;
104
105 case eSymbolTypeCode: {
106 // For each N_FUN, or function that we run into in the debug map we
107 // make a new section that we add to the sections found in the .o
108 // file. This new section has the file address set to what the
109 // addresses are in the .o file, and the load address is adjusted
110 // to match where it ended up in the final executable! We do this
111 // before we parse any dwarf info so that when it goes get parsed
112 // all section/offset addresses that get registered will resolve
113 // correctly to the new addresses in the main executable.
114
115 // First we find the original symbol in the .o file's symbol table
116 Symbol *oso_fun_symbol = oso_symtab->FindFirstSymbolWithNameAndType(
117 exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
118 eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny);
119 if (oso_fun_symbol) {
120 // Add the inverse OSO file address to debug map entry mapping
121 exe_symfile->AddOSOFileRange(
122 this, exe_symbol->GetAddressRef().GetFileAddress(),
123 exe_symbol->GetByteSize(),
124 oso_fun_symbol->GetAddressRef().GetFileAddress(),
125 oso_fun_symbol->GetByteSize());
126 }
127 } break;
128
129 case eSymbolTypeData: {
130 // For each N_GSYM we remap the address for the global by making a
131 // new section that we add to the sections found in the .o file.
132 // This new section has the file address set to what the addresses
133 // are in the .o file, and the load address is adjusted to match
134 // where it ended up in the final executable! We do this before we
135 // parse any dwarf info so that when it goes get parsed all
136 // section/offset addresses that get registered will resolve
137 // correctly to the new addresses in the main executable. We
138 // initially set the section size to be 1 byte, but will need to
139 // fix up these addresses further after all globals have been
140 // parsed to span the gaps, or we can find the global variable
141 // sizes from the DWARF info as we are parsing.
142
143 // Next we find the non-stab entry that corresponds to the N_GSYM
144 // in the .o file
145 Symbol *oso_gsym_symbol =
146 oso_symtab->FindFirstSymbolWithNameAndType(
147 exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
148 eSymbolTypeData, Symtab::eDebugNo, Symtab::eVisibilityAny);
149 if (exe_symbol && oso_gsym_symbol && exe_symbol->ValueIsAddress() &&
150 oso_gsym_symbol->ValueIsAddress()) {
151 // Add the inverse OSO file address to debug map entry mapping
152 exe_symfile->AddOSOFileRange(
153 this, exe_symbol->GetAddressRef().GetFileAddress(),
154 exe_symbol->GetByteSize(),
155 oso_gsym_symbol->GetAddressRef().GetFileAddress(),
156 oso_gsym_symbol->GetByteSize());
157 }
158 } break;
159 }
160 }
161 }
162
163 exe_symfile->FinalizeOSOFileRanges(this);
164 // We don't need the symbols anymore for the .o files
165 oso_objfile->ClearSymtab();
166 }
167 }
168 return file_range_map;
169 }
170
171 class DebugMapModule : public Module {
172 public:
DebugMapModule(const ModuleSP & exe_module_sp,uint32_t cu_idx,const FileSpec & file_spec,const ArchSpec & arch,const ConstString * object_name,off_t object_offset,const llvm::sys::TimePoint<> object_mod_time)173 DebugMapModule(const ModuleSP &exe_module_sp, uint32_t cu_idx,
174 const FileSpec &file_spec, const ArchSpec &arch,
175 const ConstString *object_name, off_t object_offset,
176 const llvm::sys::TimePoint<> object_mod_time)
177 : Module(file_spec, arch, object_name, object_offset, object_mod_time),
178 m_exe_module_wp(exe_module_sp), m_cu_idx(cu_idx) {}
179
180 ~DebugMapModule() override = default;
181
182 SymbolFile *
GetSymbolFile(bool can_create=true,lldb_private::Stream * feedback_strm=nullptr)183 GetSymbolFile(bool can_create = true,
184 lldb_private::Stream *feedback_strm = nullptr) override {
185 // Scope for locker
186 if (m_symfile_up.get() || !can_create)
187 return m_symfile_up ? m_symfile_up->GetSymbolFile() : nullptr;
188
189 ModuleSP exe_module_sp(m_exe_module_wp.lock());
190 if (exe_module_sp) {
191 // Now get the object file outside of a locking scope
192 ObjectFile *oso_objfile = GetObjectFile();
193 if (oso_objfile) {
194 std::lock_guard<std::recursive_mutex> guard(m_mutex);
195 if (SymbolFile *symfile =
196 Module::GetSymbolFile(can_create, feedback_strm)) {
197 // Set a pointer to this class to set our OSO DWARF file know that
198 // the DWARF is being used along with a debug map and that it will
199 // have the remapped sections that we do below.
200 SymbolFileDWARF *oso_symfile =
201 SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(symfile);
202
203 if (!oso_symfile)
204 return nullptr;
205
206 ObjectFile *exe_objfile = exe_module_sp->GetObjectFile();
207 SymbolFile *exe_symfile = exe_module_sp->GetSymbolFile();
208
209 if (exe_objfile && exe_symfile) {
210 oso_symfile->SetDebugMapModule(exe_module_sp);
211 // Set the ID of the symbol file DWARF to the index of the OSO
212 // shifted left by 32 bits to provide a unique prefix for any
213 // UserID's that get created in the symbol file.
214 oso_symfile->SetID(((uint64_t)m_cu_idx + 1ull) << 32ull);
215 }
216 return symfile;
217 }
218 }
219 }
220 return nullptr;
221 }
222
223 protected:
224 ModuleWP m_exe_module_wp;
225 const uint32_t m_cu_idx;
226 };
227
Initialize()228 void SymbolFileDWARFDebugMap::Initialize() {
229 PluginManager::RegisterPlugin(GetPluginNameStatic(),
230 GetPluginDescriptionStatic(), CreateInstance);
231 }
232
Terminate()233 void SymbolFileDWARFDebugMap::Terminate() {
234 PluginManager::UnregisterPlugin(CreateInstance);
235 }
236
GetPluginDescriptionStatic()237 llvm::StringRef SymbolFileDWARFDebugMap::GetPluginDescriptionStatic() {
238 return "DWARF and DWARF3 debug symbol file reader (debug map).";
239 }
240
CreateInstance(ObjectFileSP objfile_sp)241 SymbolFile *SymbolFileDWARFDebugMap::CreateInstance(ObjectFileSP objfile_sp) {
242 return new SymbolFileDWARFDebugMap(std::move(objfile_sp));
243 }
244
SymbolFileDWARFDebugMap(ObjectFileSP objfile_sp)245 SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap(ObjectFileSP objfile_sp)
246 : SymbolFileCommon(std::move(objfile_sp)), m_flags(), m_compile_unit_infos(),
247 m_func_indexes(), m_glob_indexes(),
248 m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {}
249
250 SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() = default;
251
InitializeObject()252 void SymbolFileDWARFDebugMap::InitializeObject() {}
253
InitOSO()254 void SymbolFileDWARFDebugMap::InitOSO() {
255 if (m_flags.test(kHaveInitializedOSOs))
256 return;
257
258 m_flags.set(kHaveInitializedOSOs);
259
260 // If the object file has been stripped, there is no sense in looking further
261 // as all of the debug symbols for the debug map will not be available
262 if (m_objfile_sp->IsStripped())
263 return;
264
265 // Also make sure the file type is some sort of executable. Core files, debug
266 // info files (dSYM), object files (.o files), and stub libraries all can
267 switch (m_objfile_sp->GetType()) {
268 case ObjectFile::eTypeInvalid:
269 case ObjectFile::eTypeCoreFile:
270 case ObjectFile::eTypeDebugInfo:
271 case ObjectFile::eTypeObjectFile:
272 case ObjectFile::eTypeStubLibrary:
273 case ObjectFile::eTypeUnknown:
274 case ObjectFile::eTypeJIT:
275 return;
276
277 case ObjectFile::eTypeExecutable:
278 case ObjectFile::eTypeDynamicLinker:
279 case ObjectFile::eTypeSharedLibrary:
280 break;
281 }
282
283 // In order to get the abilities of this plug-in, we look at the list of
284 // N_OSO entries (object files) from the symbol table and make sure that
285 // these files exist and also contain valid DWARF. If we get any of that then
286 // we return the abilities of the first N_OSO's DWARF.
287
288 Symtab *symtab = m_objfile_sp->GetSymtab();
289 if (symtab) {
290 Log *log = GetLog(DWARFLog::DebugMap);
291
292 std::vector<uint32_t> oso_indexes;
293 // When a mach-o symbol is encoded, the n_type field is encoded in bits
294 // 23:16, and the n_desc field is encoded in bits 15:0.
295 //
296 // To find all N_OSO entries that are part of the DWARF + debug map we find
297 // only object file symbols with the flags value as follows: bits 23:16 ==
298 // 0x66 (N_OSO) bits 15: 0 == 0x0001 (specifies this is a debug map object
299 // file)
300 const uint32_t k_oso_symbol_flags_value = 0x660001u;
301
302 const uint32_t oso_index_count =
303 symtab->AppendSymbolIndexesWithTypeAndFlagsValue(
304 eSymbolTypeObjectFile, k_oso_symbol_flags_value, oso_indexes);
305
306 if (oso_index_count > 0) {
307 symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugYes,
308 Symtab::eVisibilityAny,
309 m_func_indexes);
310 symtab->AppendSymbolIndexesWithType(eSymbolTypeData, Symtab::eDebugYes,
311 Symtab::eVisibilityAny,
312 m_glob_indexes);
313
314 symtab->SortSymbolIndexesByValue(m_func_indexes, true);
315 symtab->SortSymbolIndexesByValue(m_glob_indexes, true);
316
317 for (uint32_t sym_idx : m_func_indexes) {
318 const Symbol *symbol = symtab->SymbolAtIndex(sym_idx);
319 lldb::addr_t file_addr = symbol->GetAddressRef().GetFileAddress();
320 lldb::addr_t byte_size = symbol->GetByteSize();
321 DebugMap::Entry debug_map_entry(
322 file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS));
323 m_debug_map.Append(debug_map_entry);
324 }
325 for (uint32_t sym_idx : 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(
330 file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS));
331 m_debug_map.Append(debug_map_entry);
332 }
333 m_debug_map.Sort();
334
335 m_compile_unit_infos.resize(oso_index_count);
336
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(
346 so_symbol->GetName().AsCString(), 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
352 // "i"
353 if (sibling_idx == UINT32_MAX) {
354 m_objfile_sp->GetModule()->ReportError(
355 "N_SO in symbol with UID {0} has invalid sibling in debug "
356 "map, "
357 "please file a bug and attach the binary listed in this error",
358 so_symbol->GetID());
359 } else {
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();
365
366 LLDB_LOGF(log, "Initialized OSO 0x%8.8x: file=%s", i,
367 oso_symbol->GetName().GetCString());
368 }
369 } else {
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 "
373 "attach "
374 "the binary listed in this error",
375 oso_idx);
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",
380 oso_idx);
381 else if (so_symbol->GetType() != eSymbolTypeSourceFile)
382 m_objfile_sp->GetModule()->ReportError(
383 "N_SO has incorrect symbol type ({0}) for N_OSO "
384 "symbol[{1}], "
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 "
390 "symbol[{1}], "
391 "please file a bug and attach the binary listed in this error",
392 oso_symbol->GetType(), oso_idx);
393 }
394 }
395 }
396 }
397 }
398
GetModuleByOSOIndex(uint32_t oso_idx)399 Module *SymbolFileDWARFDebugMap::GetModuleByOSOIndex(uint32_t oso_idx) {
400 const uint32_t cu_count = GetNumCompileUnits();
401 if (oso_idx < cu_count)
402 return GetModuleByCompUnitInfo(&m_compile_unit_infos[oso_idx]);
403 return nullptr;
404 }
405
GetModuleByCompUnitInfo(CompileUnitInfo * comp_unit_info)406 Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo(
407 CompileUnitInfo *comp_unit_info) {
408 if (!comp_unit_info->oso_sp) {
409 auto pos = m_oso_map.find(
410 {comp_unit_info->oso_path, comp_unit_info->oso_mod_time});
411 if (pos != m_oso_map.end()) {
412 comp_unit_info->oso_sp = pos->second;
413 } else {
414 ObjectFile *obj_file = GetObjectFile();
415 comp_unit_info->oso_sp = std::make_shared<OSOInfo>();
416 m_oso_map[{comp_unit_info->oso_path, comp_unit_info->oso_mod_time}] =
417 comp_unit_info->oso_sp;
418 const char *oso_path = comp_unit_info->oso_path.GetCString();
419 FileSpec oso_file(oso_path);
420 ConstString oso_object;
421 if (FileSystem::Instance().Exists(oso_file)) {
422 // The modification time returned by the FS can have a higher precision
423 // than the one from the CU.
424 auto oso_mod_time = std::chrono::time_point_cast<std::chrono::seconds>(
425 FileSystem::Instance().GetModificationTime(oso_file));
426 // A timestamp of 0 means that the linker was in deterministic mode. In
427 // that case, we should skip the check against the filesystem last
428 // modification timestamp, since it will never match.
429 if (comp_unit_info->oso_mod_time != llvm::sys::TimePoint<>() &&
430 oso_mod_time != comp_unit_info->oso_mod_time) {
431 comp_unit_info->oso_load_error.SetErrorStringWithFormat(
432 "debug map object file \"%s\" changed (actual: 0x%8.8x, debug "
433 "map: 0x%8.8x) since this executable was linked, debug info "
434 "will not be loaded", oso_file.GetPath().c_str(),
435 (uint32_t)llvm::sys::toTimeT(oso_mod_time),
436 (uint32_t)llvm::sys::toTimeT(comp_unit_info->oso_mod_time));
437 obj_file->GetModule()->ReportError(
438 "{0}", comp_unit_info->oso_load_error.AsCString());
439 return nullptr;
440 }
441
442 } else {
443 const bool must_exist = true;
444
445 if (!ObjectFile::SplitArchivePathWithObject(oso_path, oso_file,
446 oso_object, must_exist)) {
447 comp_unit_info->oso_load_error.SetErrorStringWithFormat(
448 "debug map object file \"%s\" containing debug info does not "
449 "exist, debug info will not be loaded",
450 comp_unit_info->oso_path.GetCString());
451 return nullptr;
452 }
453 }
454 // Always create a new module for .o files. Why? Because we use the debug
455 // map, to add new sections to each .o file and even though a .o file
456 // might not have changed, the sections that get added to the .o file can
457 // change.
458 ArchSpec oso_arch;
459 // Only adopt the architecture from the module (not the vendor or OS)
460 // since .o files for "i386-apple-ios" will historically show up as "i386
461 // -apple-macosx" due to the lack of a LC_VERSION_MIN_MACOSX or
462 // LC_VERSION_MIN_IPHONEOS load command...
463 oso_arch.SetTriple(m_objfile_sp->GetModule()
464 ->GetArchitecture()
465 .GetTriple()
466 .getArchName()
467 .str()
468 .c_str());
469 comp_unit_info->oso_sp->module_sp = std::make_shared<DebugMapModule>(
470 obj_file->GetModule(), GetCompUnitInfoIndex(comp_unit_info), oso_file,
471 oso_arch, oso_object ? &oso_object : nullptr, 0,
472 oso_object ? comp_unit_info->oso_mod_time : llvm::sys::TimePoint<>());
473
474 if (!comp_unit_info->oso_sp->module_sp || !comp_unit_info->oso_sp->module_sp->GetObjectFile()) {
475 if (oso_object && FileSystem::Instance().Exists(oso_file)) {
476 // If we are loading a .o file from a .a file the "oso_object" will
477 // have a valid value name and if the .a file exists, either the .o
478 // file didn't exist in the .a file or the mod time didn't match.
479 comp_unit_info->oso_load_error.SetErrorStringWithFormat(
480 "\"%s\" object from the \"%s\" archive: "
481 "either the .o file doesn't exist in the archive or the "
482 "modification time (0x%8.8x) of the .o file doesn't match",
483 oso_object.AsCString(), oso_file.GetPath().c_str(),
484 (uint32_t)llvm::sys::toTimeT(comp_unit_info->oso_mod_time));
485 }
486 }
487 }
488 }
489 if (comp_unit_info->oso_sp)
490 return comp_unit_info->oso_sp->module_sp.get();
491 return nullptr;
492 }
493
GetFileSpecForSO(uint32_t oso_idx,FileSpec & file_spec)494 bool SymbolFileDWARFDebugMap::GetFileSpecForSO(uint32_t oso_idx,
495 FileSpec &file_spec) {
496 if (oso_idx < m_compile_unit_infos.size()) {
497 if (m_compile_unit_infos[oso_idx].so_file) {
498 file_spec = m_compile_unit_infos[oso_idx].so_file;
499 return true;
500 }
501 }
502 return false;
503 }
504
GetObjectFileByOSOIndex(uint32_t oso_idx)505 ObjectFile *SymbolFileDWARFDebugMap::GetObjectFileByOSOIndex(uint32_t oso_idx) {
506 Module *oso_module = GetModuleByOSOIndex(oso_idx);
507 if (oso_module)
508 return oso_module->GetObjectFile();
509 return nullptr;
510 }
511
512 SymbolFileDWARF *
GetSymbolFile(const SymbolContext & sc)513 SymbolFileDWARFDebugMap::GetSymbolFile(const SymbolContext &sc) {
514 return GetSymbolFile(*sc.comp_unit);
515 }
516
517 SymbolFileDWARF *
GetSymbolFile(const CompileUnit & comp_unit)518 SymbolFileDWARFDebugMap::GetSymbolFile(const CompileUnit &comp_unit) {
519 CompileUnitInfo *comp_unit_info = GetCompUnitInfo(comp_unit);
520 if (comp_unit_info)
521 return GetSymbolFileByCompUnitInfo(comp_unit_info);
522 return nullptr;
523 }
524
GetObjectFileByCompUnitInfo(CompileUnitInfo * comp_unit_info)525 ObjectFile *SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo(
526 CompileUnitInfo *comp_unit_info) {
527 Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info);
528 if (oso_module)
529 return oso_module->GetObjectFile();
530 return nullptr;
531 }
532
GetCompUnitInfoIndex(const CompileUnitInfo * comp_unit_info)533 uint32_t SymbolFileDWARFDebugMap::GetCompUnitInfoIndex(
534 const CompileUnitInfo *comp_unit_info) {
535 if (!m_compile_unit_infos.empty()) {
536 const CompileUnitInfo *first_comp_unit_info = &m_compile_unit_infos.front();
537 const CompileUnitInfo *last_comp_unit_info = &m_compile_unit_infos.back();
538 if (first_comp_unit_info <= comp_unit_info &&
539 comp_unit_info <= last_comp_unit_info)
540 return comp_unit_info - first_comp_unit_info;
541 }
542 return UINT32_MAX;
543 }
544
545 SymbolFileDWARF *
GetSymbolFileByOSOIndex(uint32_t oso_idx)546 SymbolFileDWARFDebugMap::GetSymbolFileByOSOIndex(uint32_t oso_idx) {
547 unsigned size = m_compile_unit_infos.size();
548 if (oso_idx < size)
549 return GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[oso_idx]);
550 return nullptr;
551 }
552
553 SymbolFileDWARF *
GetSymbolFileAsSymbolFileDWARF(SymbolFile * sym_file)554 SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(SymbolFile *sym_file) {
555 if (sym_file &&
556 sym_file->GetPluginName() == SymbolFileDWARF::GetPluginNameStatic())
557 return static_cast<SymbolFileDWARF *>(sym_file);
558 return nullptr;
559 }
560
GetSymbolFileByCompUnitInfo(CompileUnitInfo * comp_unit_info)561 SymbolFileDWARF *SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo(
562 CompileUnitInfo *comp_unit_info) {
563 if (Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info))
564 return GetSymbolFileAsSymbolFileDWARF(oso_module->GetSymbolFile());
565 return nullptr;
566 }
567
CalculateAbilities()568 uint32_t SymbolFileDWARFDebugMap::CalculateAbilities() {
569 // In order to get the abilities of this plug-in, we look at the list of
570 // N_OSO entries (object files) from the symbol table and make sure that
571 // these files exist and also contain valid DWARF. If we get any of that then
572 // we return the abilities of the first N_OSO's DWARF.
573
574 const uint32_t oso_index_count = GetNumCompileUnits();
575 if (oso_index_count > 0) {
576 InitOSO();
577 if (!m_compile_unit_infos.empty()) {
578 return SymbolFile::CompileUnits | SymbolFile::Functions |
579 SymbolFile::Blocks | SymbolFile::GlobalVariables |
580 SymbolFile::LocalVariables | SymbolFile::VariableTypes |
581 SymbolFile::LineTables;
582 }
583 }
584 return 0;
585 }
586
CalculateNumCompileUnits()587 uint32_t SymbolFileDWARFDebugMap::CalculateNumCompileUnits() {
588 InitOSO();
589 return m_compile_unit_infos.size();
590 }
591
ParseCompileUnitAtIndex(uint32_t cu_idx)592 CompUnitSP SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) {
593 CompUnitSP comp_unit_sp;
594 const uint32_t cu_count = GetNumCompileUnits();
595
596 if (cu_idx < cu_count) {
597 auto &cu_info = m_compile_unit_infos[cu_idx];
598 Module *oso_module = GetModuleByCompUnitInfo(&cu_info);
599 if (oso_module) {
600 FileSpec so_file_spec;
601 if (GetFileSpecForSO(cu_idx, so_file_spec)) {
602 // User zero as the ID to match the compile unit at offset zero in each
603 // .o file.
604 lldb::user_id_t cu_id = 0;
605 cu_info.compile_units_sps.push_back(
606 std::make_shared<CompileUnit>(
607 m_objfile_sp->GetModule(), nullptr, so_file_spec, cu_id,
608 eLanguageTypeUnknown, eLazyBoolCalculate));
609 cu_info.id_to_index_map.insert({0, 0});
610 SetCompileUnitAtIndex(cu_idx, cu_info.compile_units_sps[0]);
611 // If there's a symbol file also register all the extra compile units.
612 if (SymbolFileDWARF *oso_symfile =
613 GetSymbolFileByCompUnitInfo(&cu_info)) {
614 auto num_dwarf_units = oso_symfile->DebugInfo().GetNumUnits();
615 for (size_t i = 0; i < num_dwarf_units; ++i) {
616 auto *dwarf_unit = oso_symfile->DebugInfo().GetUnitAtIndex(i);
617 if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(dwarf_unit)) {
618 // The "main" one was already registered.
619 if (dwarf_cu->GetID() == 0)
620 continue;
621 cu_info.compile_units_sps.push_back(std::make_shared<CompileUnit>(
622 m_objfile_sp->GetModule(), nullptr, so_file_spec,
623 dwarf_cu->GetID(), eLanguageTypeUnknown, eLazyBoolCalculate));
624 cu_info.id_to_index_map.insert(
625 {dwarf_cu->GetID(), cu_info.compile_units_sps.size() - 1});
626 }
627 }
628 }
629 }
630 }
631 if (!cu_info.compile_units_sps.empty())
632 comp_unit_sp = cu_info.compile_units_sps[0];
633 }
634
635 return comp_unit_sp;
636 }
637
638 SymbolFileDWARFDebugMap::CompileUnitInfo *
GetCompUnitInfo(const SymbolContext & sc)639 SymbolFileDWARFDebugMap::GetCompUnitInfo(const SymbolContext &sc) {
640 return GetCompUnitInfo(*sc.comp_unit);
641 }
642
643 SymbolFileDWARFDebugMap::CompileUnitInfo *
GetCompUnitInfo(const CompileUnit & comp_unit)644 SymbolFileDWARFDebugMap::GetCompUnitInfo(const CompileUnit &comp_unit) {
645 const uint32_t cu_count = GetNumCompileUnits();
646 for (uint32_t i = 0; i < cu_count; ++i) {
647 auto &id_to_index_map = m_compile_unit_infos[i].id_to_index_map;
648
649 auto it = id_to_index_map.find(comp_unit.GetID());
650 if (it != id_to_index_map.end() &&
651 &comp_unit ==
652 m_compile_unit_infos[i].compile_units_sps[it->getSecond()].get())
653 return &m_compile_unit_infos[i];
654 }
655 return nullptr;
656 }
657
GetCompUnitInfosForModule(const lldb_private::Module * module,std::vector<CompileUnitInfo * > & cu_infos)658 size_t SymbolFileDWARFDebugMap::GetCompUnitInfosForModule(
659 const lldb_private::Module *module,
660 std::vector<CompileUnitInfo *> &cu_infos) {
661 const uint32_t cu_count = GetNumCompileUnits();
662 for (uint32_t i = 0; i < cu_count; ++i) {
663 if (module == GetModuleByCompUnitInfo(&m_compile_unit_infos[i]))
664 cu_infos.push_back(&m_compile_unit_infos[i]);
665 }
666 return cu_infos.size();
667 }
668
669 lldb::LanguageType
ParseLanguage(CompileUnit & comp_unit)670 SymbolFileDWARFDebugMap::ParseLanguage(CompileUnit &comp_unit) {
671 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
672 SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
673 if (oso_dwarf)
674 return oso_dwarf->ParseLanguage(comp_unit);
675 return eLanguageTypeUnknown;
676 }
677
ParseXcodeSDK(CompileUnit & comp_unit)678 XcodeSDK SymbolFileDWARFDebugMap::ParseXcodeSDK(CompileUnit &comp_unit) {
679 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
680 SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
681 if (oso_dwarf)
682 return oso_dwarf->ParseXcodeSDK(comp_unit);
683 return {};
684 }
685
ParseFunctions(CompileUnit & comp_unit)686 size_t SymbolFileDWARFDebugMap::ParseFunctions(CompileUnit &comp_unit) {
687 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
688 SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
689 if (oso_dwarf)
690 return oso_dwarf->ParseFunctions(comp_unit);
691 return 0;
692 }
693
ParseLineTable(CompileUnit & comp_unit)694 bool SymbolFileDWARFDebugMap::ParseLineTable(CompileUnit &comp_unit) {
695 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
696 SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
697 if (oso_dwarf)
698 return oso_dwarf->ParseLineTable(comp_unit);
699 return false;
700 }
701
ParseDebugMacros(CompileUnit & comp_unit)702 bool SymbolFileDWARFDebugMap::ParseDebugMacros(CompileUnit &comp_unit) {
703 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
704 SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
705 if (oso_dwarf)
706 return oso_dwarf->ParseDebugMacros(comp_unit);
707 return false;
708 }
709
ForEachExternalModule(CompileUnit & comp_unit,llvm::DenseSet<lldb_private::SymbolFile * > & visited_symbol_files,llvm::function_ref<bool (Module &)> f)710 bool SymbolFileDWARFDebugMap::ForEachExternalModule(
711 CompileUnit &comp_unit,
712 llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
713 llvm::function_ref<bool(Module &)> f) {
714 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
715 SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
716 if (oso_dwarf)
717 return oso_dwarf->ForEachExternalModule(comp_unit, visited_symbol_files, f);
718 return false;
719 }
720
ParseSupportFiles(CompileUnit & comp_unit,FileSpecList & support_files)721 bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit,
722 FileSpecList &support_files) {
723 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
724 SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
725 if (oso_dwarf)
726 return oso_dwarf->ParseSupportFiles(comp_unit, support_files);
727 return false;
728 }
729
ParseIsOptimized(CompileUnit & comp_unit)730 bool SymbolFileDWARFDebugMap::ParseIsOptimized(CompileUnit &comp_unit) {
731 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
732 SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
733 if (oso_dwarf)
734 return oso_dwarf->ParseIsOptimized(comp_unit);
735 return false;
736 }
737
ParseImportedModules(const SymbolContext & sc,std::vector<SourceModule> & imported_modules)738 bool SymbolFileDWARFDebugMap::ParseImportedModules(
739 const SymbolContext &sc, std::vector<SourceModule> &imported_modules) {
740 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
741 SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
742 if (oso_dwarf)
743 return oso_dwarf->ParseImportedModules(sc, imported_modules);
744 return false;
745 }
746
ParseBlocksRecursive(Function & func)747 size_t SymbolFileDWARFDebugMap::ParseBlocksRecursive(Function &func) {
748 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
749 CompileUnit *comp_unit = func.GetCompileUnit();
750 if (!comp_unit)
751 return 0;
752
753 SymbolFileDWARF *oso_dwarf = GetSymbolFile(*comp_unit);
754 if (oso_dwarf)
755 return oso_dwarf->ParseBlocksRecursive(func);
756 return 0;
757 }
758
ParseTypes(CompileUnit & comp_unit)759 size_t SymbolFileDWARFDebugMap::ParseTypes(CompileUnit &comp_unit) {
760 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
761 SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
762 if (oso_dwarf)
763 return oso_dwarf->ParseTypes(comp_unit);
764 return 0;
765 }
766
767 size_t
ParseVariablesForContext(const SymbolContext & sc)768 SymbolFileDWARFDebugMap::ParseVariablesForContext(const SymbolContext &sc) {
769 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
770 SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
771 if (oso_dwarf)
772 return oso_dwarf->ParseVariablesForContext(sc);
773 return 0;
774 }
775
ResolveTypeUID(lldb::user_id_t type_uid)776 Type *SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) {
777 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
778 const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
779 SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
780 if (oso_dwarf)
781 return oso_dwarf->ResolveTypeUID(type_uid);
782 return nullptr;
783 }
784
785 std::optional<SymbolFile::ArrayInfo>
GetDynamicArrayInfoForUID(lldb::user_id_t type_uid,const lldb_private::ExecutionContext * exe_ctx)786 SymbolFileDWARFDebugMap::GetDynamicArrayInfoForUID(
787 lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
788 const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
789 SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
790 if (oso_dwarf)
791 return oso_dwarf->GetDynamicArrayInfoForUID(type_uid, exe_ctx);
792 return std::nullopt;
793 }
794
CompleteType(CompilerType & compiler_type)795 bool SymbolFileDWARFDebugMap::CompleteType(CompilerType &compiler_type) {
796 bool success = false;
797 if (compiler_type) {
798 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
799 if (oso_dwarf->HasForwardDeclForClangType(compiler_type)) {
800 oso_dwarf->CompleteType(compiler_type);
801 success = true;
802 return true;
803 }
804 return false;
805 });
806 }
807 return success;
808 }
809
810 uint32_t
ResolveSymbolContext(const Address & exe_so_addr,SymbolContextItem resolve_scope,SymbolContext & sc)811 SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr,
812 SymbolContextItem resolve_scope,
813 SymbolContext &sc) {
814 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
815 uint32_t resolved_flags = 0;
816 Symtab *symtab = m_objfile_sp->GetSymtab();
817 if (symtab) {
818 const addr_t exe_file_addr = exe_so_addr.GetFileAddress();
819
820 const DebugMap::Entry *debug_map_entry =
821 m_debug_map.FindEntryThatContains(exe_file_addr);
822 if (debug_map_entry) {
823
824 sc.symbol =
825 symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex());
826
827 if (sc.symbol != nullptr) {
828 resolved_flags |= eSymbolContextSymbol;
829
830 uint32_t oso_idx = 0;
831 CompileUnitInfo *comp_unit_info =
832 GetCompileUnitInfoForSymbolWithID(sc.symbol->GetID(), &oso_idx);
833 if (comp_unit_info) {
834 comp_unit_info->GetFileRangeMap(this);
835 Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info);
836 if (oso_module) {
837 lldb::addr_t oso_file_addr =
838 exe_file_addr - debug_map_entry->GetRangeBase() +
839 debug_map_entry->data.GetOSOFileAddress();
840 Address oso_so_addr;
841 if (oso_module->ResolveFileAddress(oso_file_addr, oso_so_addr)) {
842 resolved_flags |=
843 oso_module->GetSymbolFile()->ResolveSymbolContext(
844 oso_so_addr, resolve_scope, sc);
845 }
846 }
847 }
848 }
849 }
850 }
851 return resolved_flags;
852 }
853
ResolveSymbolContext(const SourceLocationSpec & src_location_spec,SymbolContextItem resolve_scope,SymbolContextList & sc_list)854 uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
855 const SourceLocationSpec &src_location_spec,
856 SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
857 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
858 const uint32_t initial = sc_list.GetSize();
859 const uint32_t cu_count = GetNumCompileUnits();
860
861 for (uint32_t i = 0; i < cu_count; ++i) {
862 // If we are checking for inlines, then we need to look through all compile
863 // units no matter if "file_spec" matches.
864 bool resolve = src_location_spec.GetCheckInlines();
865
866 if (!resolve) {
867 FileSpec so_file_spec;
868 if (GetFileSpecForSO(i, so_file_spec))
869 resolve =
870 FileSpec::Match(src_location_spec.GetFileSpec(), so_file_spec);
871 }
872 if (resolve) {
873 SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(i);
874 if (oso_dwarf)
875 oso_dwarf->ResolveSymbolContext(src_location_spec, resolve_scope,
876 sc_list);
877 }
878 }
879 return sc_list.GetSize() - initial;
880 }
881
PrivateFindGlobalVariables(ConstString name,const CompilerDeclContext & parent_decl_ctx,const std::vector<uint32_t> & indexes,uint32_t max_matches,VariableList & variables)882 void SymbolFileDWARFDebugMap::PrivateFindGlobalVariables(
883 ConstString name, const CompilerDeclContext &parent_decl_ctx,
884 const std::vector<uint32_t>
885 &indexes, // Indexes into the symbol table that match "name"
886 uint32_t max_matches, VariableList &variables) {
887 const size_t match_count = indexes.size();
888 for (size_t i = 0; i < match_count; ++i) {
889 uint32_t oso_idx;
890 CompileUnitInfo *comp_unit_info =
891 GetCompileUnitInfoForSymbolWithIndex(indexes[i], &oso_idx);
892 if (comp_unit_info) {
893 SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
894 if (oso_dwarf) {
895 oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches,
896 variables);
897 if (variables.GetSize() > max_matches)
898 break;
899 }
900 }
901 }
902 }
903
FindGlobalVariables(ConstString name,const CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,VariableList & variables)904 void SymbolFileDWARFDebugMap::FindGlobalVariables(
905 ConstString name, const CompilerDeclContext &parent_decl_ctx,
906 uint32_t max_matches, VariableList &variables) {
907 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
908 uint32_t total_matches = 0;
909
910 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
911 const uint32_t old_size = variables.GetSize();
912 oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches,
913 variables);
914 const uint32_t oso_matches = variables.GetSize() - old_size;
915 if (oso_matches > 0) {
916 total_matches += oso_matches;
917
918 // Are we getting all matches?
919 if (max_matches == UINT32_MAX)
920 return false; // Yep, continue getting everything
921
922 // If we have found enough matches, lets get out
923 if (max_matches >= total_matches)
924 return true;
925
926 // Update the max matches for any subsequent calls to find globals in any
927 // other object files with DWARF
928 max_matches -= oso_matches;
929 }
930
931 return false;
932 });
933 }
934
FindGlobalVariables(const RegularExpression & regex,uint32_t max_matches,VariableList & variables)935 void SymbolFileDWARFDebugMap::FindGlobalVariables(
936 const RegularExpression ®ex, uint32_t max_matches,
937 VariableList &variables) {
938 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
939 uint32_t total_matches = 0;
940 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
941 const uint32_t old_size = variables.GetSize();
942 oso_dwarf->FindGlobalVariables(regex, max_matches, variables);
943
944 const uint32_t oso_matches = variables.GetSize() - old_size;
945 if (oso_matches > 0) {
946 total_matches += oso_matches;
947
948 // Are we getting all matches?
949 if (max_matches == UINT32_MAX)
950 return false; // Yep, continue getting everything
951
952 // If we have found enough matches, lets get out
953 if (max_matches >= total_matches)
954 return true;
955
956 // Update the max matches for any subsequent calls to find globals in any
957 // other object files with DWARF
958 max_matches -= oso_matches;
959 }
960
961 return false;
962 });
963 }
964
SymbolContainsSymbolWithIndex(uint32_t * symbol_idx_ptr,const CompileUnitInfo * comp_unit_info)965 int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex(
966 uint32_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info) {
967 const uint32_t symbol_idx = *symbol_idx_ptr;
968
969 if (symbol_idx < comp_unit_info->first_symbol_index)
970 return -1;
971
972 if (symbol_idx <= comp_unit_info->last_symbol_index)
973 return 0;
974
975 return 1;
976 }
977
SymbolContainsSymbolWithID(user_id_t * symbol_idx_ptr,const CompileUnitInfo * comp_unit_info)978 int SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID(
979 user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info) {
980 const user_id_t symbol_id = *symbol_idx_ptr;
981
982 if (symbol_id < comp_unit_info->first_symbol_id)
983 return -1;
984
985 if (symbol_id <= comp_unit_info->last_symbol_id)
986 return 0;
987
988 return 1;
989 }
990
991 SymbolFileDWARFDebugMap::CompileUnitInfo *
GetCompileUnitInfoForSymbolWithIndex(uint32_t symbol_idx,uint32_t * oso_idx_ptr)992 SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex(
993 uint32_t symbol_idx, uint32_t *oso_idx_ptr) {
994 const uint32_t oso_index_count = m_compile_unit_infos.size();
995 CompileUnitInfo *comp_unit_info = nullptr;
996 if (oso_index_count) {
997 comp_unit_info = (CompileUnitInfo *)bsearch(
998 &symbol_idx, &m_compile_unit_infos[0], m_compile_unit_infos.size(),
999 sizeof(CompileUnitInfo),
1000 (ComparisonFunction)SymbolContainsSymbolWithIndex);
1001 }
1002
1003 if (oso_idx_ptr) {
1004 if (comp_unit_info != nullptr)
1005 *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0];
1006 else
1007 *oso_idx_ptr = UINT32_MAX;
1008 }
1009 return comp_unit_info;
1010 }
1011
1012 SymbolFileDWARFDebugMap::CompileUnitInfo *
GetCompileUnitInfoForSymbolWithID(user_id_t symbol_id,uint32_t * oso_idx_ptr)1013 SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID(
1014 user_id_t symbol_id, uint32_t *oso_idx_ptr) {
1015 const uint32_t oso_index_count = m_compile_unit_infos.size();
1016 CompileUnitInfo *comp_unit_info = nullptr;
1017 if (oso_index_count) {
1018 comp_unit_info = (CompileUnitInfo *)::bsearch(
1019 &symbol_id, &m_compile_unit_infos[0], m_compile_unit_infos.size(),
1020 sizeof(CompileUnitInfo),
1021 (ComparisonFunction)SymbolContainsSymbolWithID);
1022 }
1023
1024 if (oso_idx_ptr) {
1025 if (comp_unit_info != nullptr)
1026 *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0];
1027 else
1028 *oso_idx_ptr = UINT32_MAX;
1029 }
1030 return comp_unit_info;
1031 }
1032
RemoveFunctionsWithModuleNotEqualTo(const ModuleSP & module_sp,SymbolContextList & sc_list,uint32_t start_idx)1033 static void RemoveFunctionsWithModuleNotEqualTo(const ModuleSP &module_sp,
1034 SymbolContextList &sc_list,
1035 uint32_t start_idx) {
1036 // We found functions in .o files. Not all functions in the .o files will
1037 // have made it into the final output file. The ones that did make it into
1038 // the final output file will have a section whose module matches the module
1039 // from the ObjectFile for this SymbolFile. When the modules don't match,
1040 // then we have something that was in a .o file, but doesn't map to anything
1041 // in the final executable.
1042 uint32_t i = start_idx;
1043 while (i < sc_list.GetSize()) {
1044 SymbolContext sc;
1045 sc_list.GetContextAtIndex(i, sc);
1046 if (sc.function) {
1047 const SectionSP section_sp(
1048 sc.function->GetAddressRange().GetBaseAddress().GetSection());
1049 if (section_sp->GetModule() != module_sp) {
1050 sc_list.RemoveContextAtIndex(i);
1051 continue;
1052 }
1053 }
1054 ++i;
1055 }
1056 }
1057
FindFunctions(const Module::LookupInfo & lookup_info,const CompilerDeclContext & parent_decl_ctx,bool include_inlines,SymbolContextList & sc_list)1058 void SymbolFileDWARFDebugMap::FindFunctions(
1059 const Module::LookupInfo &lookup_info,
1060 const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
1061 SymbolContextList &sc_list) {
1062 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1063 LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::FindFunctions (name = %s)",
1064 lookup_info.GetLookupName().GetCString());
1065
1066 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1067 uint32_t sc_idx = sc_list.GetSize();
1068 oso_dwarf->FindFunctions(lookup_info, parent_decl_ctx, include_inlines,
1069 sc_list);
1070 if (!sc_list.IsEmpty()) {
1071 RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list,
1072 sc_idx);
1073 }
1074 return false;
1075 });
1076 }
1077
FindFunctions(const RegularExpression & regex,bool include_inlines,SymbolContextList & sc_list)1078 void SymbolFileDWARFDebugMap::FindFunctions(const RegularExpression ®ex,
1079 bool include_inlines,
1080 SymbolContextList &sc_list) {
1081 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1082 LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::FindFunctions (regex = '%s')",
1083 regex.GetText().str().c_str());
1084
1085 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1086 uint32_t sc_idx = sc_list.GetSize();
1087
1088 oso_dwarf->FindFunctions(regex, include_inlines, sc_list);
1089 if (!sc_list.IsEmpty()) {
1090 RemoveFunctionsWithModuleNotEqualTo(m_objfile_sp->GetModule(), sc_list,
1091 sc_idx);
1092 }
1093 return false;
1094 });
1095 }
1096
GetTypes(SymbolContextScope * sc_scope,lldb::TypeClass type_mask,TypeList & type_list)1097 void SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope,
1098 lldb::TypeClass type_mask,
1099 TypeList &type_list) {
1100 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1101 LLDB_SCOPED_TIMERF("SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)",
1102 type_mask);
1103
1104 SymbolFileDWARF *oso_dwarf = nullptr;
1105 if (sc_scope) {
1106 SymbolContext sc;
1107 sc_scope->CalculateSymbolContext(&sc);
1108
1109 CompileUnitInfo *cu_info = GetCompUnitInfo(sc);
1110 if (cu_info) {
1111 oso_dwarf = GetSymbolFileByCompUnitInfo(cu_info);
1112 if (oso_dwarf)
1113 oso_dwarf->GetTypes(sc_scope, type_mask, type_list);
1114 }
1115 } else {
1116 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1117 oso_dwarf->GetTypes(sc_scope, type_mask, type_list);
1118 return false;
1119 });
1120 }
1121 }
1122
1123 std::vector<std::unique_ptr<lldb_private::CallEdge>>
ParseCallEdgesInFunction(UserID func_id)1124 SymbolFileDWARFDebugMap::ParseCallEdgesInFunction(UserID func_id) {
1125 uint32_t oso_idx = GetOSOIndexFromUserID(func_id.GetID());
1126 SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
1127 if (oso_dwarf)
1128 return oso_dwarf->ParseCallEdgesInFunction(func_id);
1129 return {};
1130 }
1131
FindDefinitionTypeForDWARFDeclContext(const DWARFDIE & die)1132 TypeSP SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext(
1133 const DWARFDIE &die) {
1134 TypeSP type_sp;
1135 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1136 type_sp = oso_dwarf->FindDefinitionTypeForDWARFDeclContext(die);
1137 return ((bool)type_sp);
1138 });
1139 return type_sp;
1140 }
1141
Supports_DW_AT_APPLE_objc_complete_type(SymbolFileDWARF * skip_dwarf_oso)1142 bool SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type(
1143 SymbolFileDWARF *skip_dwarf_oso) {
1144 if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) {
1145 m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo;
1146 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1147 if (skip_dwarf_oso != oso_dwarf &&
1148 oso_dwarf->Supports_DW_AT_APPLE_objc_complete_type(nullptr)) {
1149 m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes;
1150 return true;
1151 }
1152 return false;
1153 });
1154 }
1155 return m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolYes;
1156 }
1157
FindCompleteObjCDefinitionTypeForDIE(const DWARFDIE & die,ConstString type_name,bool must_be_implementation)1158 TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
1159 const DWARFDIE &die, ConstString type_name,
1160 bool must_be_implementation) {
1161 // If we have a debug map, we will have an Objective-C symbol whose name is
1162 // the type name and whose type is eSymbolTypeObjCClass. If we can find that
1163 // symbol and find its containing parent, we can locate the .o file that will
1164 // contain the implementation definition since it will be scoped inside the
1165 // N_SO and we can then locate the SymbolFileDWARF that corresponds to that
1166 // N_SO.
1167 SymbolFileDWARF *oso_dwarf = nullptr;
1168 TypeSP type_sp;
1169 ObjectFile *module_objfile = m_objfile_sp->GetModule()->GetObjectFile();
1170 if (module_objfile) {
1171 Symtab *symtab = module_objfile->GetSymtab();
1172 if (symtab) {
1173 Symbol *objc_class_symbol = symtab->FindFirstSymbolWithNameAndType(
1174 type_name, eSymbolTypeObjCClass, Symtab::eDebugAny,
1175 Symtab::eVisibilityAny);
1176 if (objc_class_symbol) {
1177 // Get the N_SO symbol that contains the objective C class symbol as
1178 // this should be the .o file that contains the real definition...
1179 const Symbol *source_file_symbol = symtab->GetParent(objc_class_symbol);
1180
1181 if (source_file_symbol &&
1182 source_file_symbol->GetType() == eSymbolTypeSourceFile) {
1183 const uint32_t source_file_symbol_idx =
1184 symtab->GetIndexForSymbol(source_file_symbol);
1185 if (source_file_symbol_idx != UINT32_MAX) {
1186 CompileUnitInfo *compile_unit_info =
1187 GetCompileUnitInfoForSymbolWithIndex(source_file_symbol_idx,
1188 nullptr);
1189 if (compile_unit_info) {
1190 oso_dwarf = GetSymbolFileByCompUnitInfo(compile_unit_info);
1191 if (oso_dwarf) {
1192 TypeSP type_sp(oso_dwarf->FindCompleteObjCDefinitionTypeForDIE(
1193 die, type_name, must_be_implementation));
1194 if (type_sp) {
1195 return type_sp;
1196 }
1197 }
1198 }
1199 }
1200 }
1201 }
1202 }
1203 }
1204
1205 // Only search all .o files for the definition if we don't need the
1206 // implementation because otherwise, with a valid debug map we should have
1207 // the ObjC class symbol and the code above should have found it.
1208 if (!must_be_implementation) {
1209 TypeSP type_sp;
1210
1211 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1212 type_sp = oso_dwarf->FindCompleteObjCDefinitionTypeForDIE(
1213 die, type_name, must_be_implementation);
1214 return (bool)type_sp;
1215 });
1216
1217 return type_sp;
1218 }
1219 return TypeSP();
1220 }
1221
FindTypes(ConstString name,const CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,llvm::DenseSet<lldb_private::SymbolFile * > & searched_symbol_files,TypeMap & types)1222 void SymbolFileDWARFDebugMap::FindTypes(
1223 ConstString name, const CompilerDeclContext &parent_decl_ctx,
1224 uint32_t max_matches,
1225 llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
1226 TypeMap &types) {
1227 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1228 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1229 oso_dwarf->FindTypes(name, parent_decl_ctx, max_matches,
1230 searched_symbol_files, types);
1231 return types.GetSize() >= max_matches;
1232 });
1233 }
1234
FindTypes(llvm::ArrayRef<CompilerContext> context,LanguageSet languages,llvm::DenseSet<lldb_private::SymbolFile * > & searched_symbol_files,TypeMap & types)1235 void SymbolFileDWARFDebugMap::FindTypes(
1236 llvm::ArrayRef<CompilerContext> context, LanguageSet languages,
1237 llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
1238 TypeMap &types) {
1239 LLDB_SCOPED_TIMER();
1240 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1241 oso_dwarf->FindTypes(context, languages, searched_symbol_files, types);
1242 return false;
1243 });
1244 }
1245
FindNamespace(lldb_private::ConstString name,const CompilerDeclContext & parent_decl_ctx)1246 CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace(
1247 lldb_private::ConstString name,
1248 const CompilerDeclContext &parent_decl_ctx) {
1249 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1250 CompilerDeclContext matching_namespace;
1251
1252 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1253 matching_namespace = oso_dwarf->FindNamespace(name, parent_decl_ctx);
1254
1255 return (bool)matching_namespace;
1256 });
1257
1258 return matching_namespace;
1259 }
1260
DumpClangAST(Stream & s)1261 void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s) {
1262 ForEachSymbolFile([&s](SymbolFileDWARF *oso_dwarf) -> bool {
1263 oso_dwarf->DumpClangAST(s);
1264 // The underlying assumption is that DumpClangAST(...) will obtain the
1265 // AST from the underlying TypeSystem and therefore we only need to do
1266 // this once and can stop after the first iteration hence we return true.
1267 return true;
1268 });
1269 }
1270
1271 lldb::CompUnitSP
GetCompileUnit(SymbolFileDWARF * oso_dwarf,DWARFCompileUnit & dwarf_cu)1272 SymbolFileDWARFDebugMap::GetCompileUnit(SymbolFileDWARF *oso_dwarf, DWARFCompileUnit &dwarf_cu) {
1273 if (oso_dwarf) {
1274 const uint32_t cu_count = GetNumCompileUnits();
1275 for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
1276 SymbolFileDWARF *oso_symfile =
1277 GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
1278 if (oso_symfile == oso_dwarf) {
1279 if (m_compile_unit_infos[cu_idx].compile_units_sps.empty())
1280 ParseCompileUnitAtIndex(cu_idx);
1281
1282 auto &id_to_index_map = m_compile_unit_infos[cu_idx].id_to_index_map;
1283 auto it = id_to_index_map.find(dwarf_cu.GetID());
1284 if (it != id_to_index_map.end())
1285 return m_compile_unit_infos[cu_idx]
1286 .compile_units_sps[it->getSecond()];
1287 }
1288 }
1289 }
1290 llvm_unreachable("this shouldn't happen");
1291 }
1292
1293 SymbolFileDWARFDebugMap::CompileUnitInfo *
GetCompileUnitInfo(SymbolFileDWARF * oso_dwarf)1294 SymbolFileDWARFDebugMap::GetCompileUnitInfo(SymbolFileDWARF *oso_dwarf) {
1295 if (oso_dwarf) {
1296 const uint32_t cu_count = GetNumCompileUnits();
1297 for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
1298 SymbolFileDWARF *oso_symfile =
1299 GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
1300 if (oso_symfile == oso_dwarf) {
1301 return &m_compile_unit_infos[cu_idx];
1302 }
1303 }
1304 }
1305 return nullptr;
1306 }
1307
SetCompileUnit(SymbolFileDWARF * oso_dwarf,const CompUnitSP & cu_sp)1308 void SymbolFileDWARFDebugMap::SetCompileUnit(SymbolFileDWARF *oso_dwarf,
1309 const CompUnitSP &cu_sp) {
1310 if (oso_dwarf) {
1311 const uint32_t cu_count = GetNumCompileUnits();
1312 for (uint32_t cu_idx = 0; cu_idx < cu_count; ++cu_idx) {
1313 SymbolFileDWARF *oso_symfile =
1314 GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[cu_idx]);
1315 if (oso_symfile == oso_dwarf) {
1316 if (!m_compile_unit_infos[cu_idx].compile_units_sps.empty()) {
1317 assert(m_compile_unit_infos[cu_idx].compile_units_sps[0].get() ==
1318 cu_sp.get());
1319 } else {
1320 assert(cu_sp->GetID() == 0 &&
1321 "Setting first compile unit but with id different than 0!");
1322 auto &compile_units_sps = m_compile_unit_infos[cu_idx].compile_units_sps;
1323 compile_units_sps.push_back(cu_sp);
1324 m_compile_unit_infos[cu_idx].id_to_index_map.insert(
1325 {cu_sp->GetID(), compile_units_sps.size() - 1});
1326
1327 SetCompileUnitAtIndex(cu_idx, cu_sp);
1328 }
1329 }
1330 }
1331 }
1332 }
1333
1334 CompilerDeclContext
GetDeclContextForUID(lldb::user_id_t type_uid)1335 SymbolFileDWARFDebugMap::GetDeclContextForUID(lldb::user_id_t type_uid) {
1336 const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
1337 SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
1338 if (oso_dwarf)
1339 return oso_dwarf->GetDeclContextForUID(type_uid);
1340 return CompilerDeclContext();
1341 }
1342
1343 CompilerDeclContext
GetDeclContextContainingUID(lldb::user_id_t type_uid)1344 SymbolFileDWARFDebugMap::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
1345 const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
1346 SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
1347 if (oso_dwarf)
1348 return oso_dwarf->GetDeclContextContainingUID(type_uid);
1349 return CompilerDeclContext();
1350 }
1351
ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx)1352 void SymbolFileDWARFDebugMap::ParseDeclsForContext(
1353 lldb_private::CompilerDeclContext decl_ctx) {
1354 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1355 oso_dwarf->ParseDeclsForContext(decl_ctx);
1356 return true; // Keep iterating
1357 });
1358 }
1359
AddOSOFileRange(CompileUnitInfo * cu_info,lldb::addr_t exe_file_addr,lldb::addr_t exe_byte_size,lldb::addr_t oso_file_addr,lldb::addr_t oso_byte_size)1360 bool SymbolFileDWARFDebugMap::AddOSOFileRange(CompileUnitInfo *cu_info,
1361 lldb::addr_t exe_file_addr,
1362 lldb::addr_t exe_byte_size,
1363 lldb::addr_t oso_file_addr,
1364 lldb::addr_t oso_byte_size) {
1365 const uint32_t debug_map_idx =
1366 m_debug_map.FindEntryIndexThatContains(exe_file_addr);
1367 if (debug_map_idx != UINT32_MAX) {
1368 DebugMap::Entry *debug_map_entry =
1369 m_debug_map.FindEntryThatContains(exe_file_addr);
1370 debug_map_entry->data.SetOSOFileAddress(oso_file_addr);
1371 addr_t range_size = std::min<addr_t>(exe_byte_size, oso_byte_size);
1372 if (range_size == 0) {
1373 range_size = std::max<addr_t>(exe_byte_size, oso_byte_size);
1374 if (range_size == 0)
1375 range_size = 1;
1376 }
1377 cu_info->file_range_map.Append(
1378 FileRangeMap::Entry(oso_file_addr, range_size, exe_file_addr));
1379 return true;
1380 }
1381 return false;
1382 }
1383
FinalizeOSOFileRanges(CompileUnitInfo * cu_info)1384 void SymbolFileDWARFDebugMap::FinalizeOSOFileRanges(CompileUnitInfo *cu_info) {
1385 cu_info->file_range_map.Sort();
1386 #if defined(DEBUG_OSO_DMAP)
1387 const FileRangeMap &oso_file_range_map = cu_info->GetFileRangeMap(this);
1388 const size_t n = oso_file_range_map.GetSize();
1389 printf("SymbolFileDWARFDebugMap::FinalizeOSOFileRanges (cu_info = %p) %s\n",
1390 cu_info, cu_info->oso_sp->module_sp->GetFileSpec().GetPath().c_str());
1391 for (size_t i = 0; i < n; ++i) {
1392 const FileRangeMap::Entry &entry = oso_file_range_map.GetEntryRef(i);
1393 printf("oso [0x%16.16" PRIx64 " - 0x%16.16" PRIx64
1394 ") ==> exe [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n",
1395 entry.GetRangeBase(), entry.GetRangeEnd(), entry.data,
1396 entry.data + entry.GetByteSize());
1397 }
1398 #endif
1399 }
1400
1401 lldb::addr_t
LinkOSOFileAddress(SymbolFileDWARF * oso_symfile,lldb::addr_t oso_file_addr)1402 SymbolFileDWARFDebugMap::LinkOSOFileAddress(SymbolFileDWARF *oso_symfile,
1403 lldb::addr_t oso_file_addr) {
1404 CompileUnitInfo *cu_info = GetCompileUnitInfo(oso_symfile);
1405 if (cu_info) {
1406 const FileRangeMap::Entry *oso_range_entry =
1407 cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr);
1408 if (oso_range_entry) {
1409 const DebugMap::Entry *debug_map_entry =
1410 m_debug_map.FindEntryThatContains(oso_range_entry->data);
1411 if (debug_map_entry) {
1412 const lldb::addr_t offset =
1413 oso_file_addr - oso_range_entry->GetRangeBase();
1414 const lldb::addr_t exe_file_addr =
1415 debug_map_entry->GetRangeBase() + offset;
1416 return exe_file_addr;
1417 }
1418 }
1419 }
1420 return LLDB_INVALID_ADDRESS;
1421 }
1422
LinkOSOAddress(Address & addr)1423 bool SymbolFileDWARFDebugMap::LinkOSOAddress(Address &addr) {
1424 // Make sure this address hasn't been fixed already
1425 Module *exe_module = GetObjectFile()->GetModule().get();
1426 Module *addr_module = addr.GetModule().get();
1427 if (addr_module == exe_module)
1428 return true; // Address is already in terms of the main executable module
1429
1430 CompileUnitInfo *cu_info = GetCompileUnitInfo(
1431 GetSymbolFileAsSymbolFileDWARF(addr_module->GetSymbolFile()));
1432 if (cu_info) {
1433 const lldb::addr_t oso_file_addr = addr.GetFileAddress();
1434 const FileRangeMap::Entry *oso_range_entry =
1435 cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr);
1436 if (oso_range_entry) {
1437 const DebugMap::Entry *debug_map_entry =
1438 m_debug_map.FindEntryThatContains(oso_range_entry->data);
1439 if (debug_map_entry) {
1440 const lldb::addr_t offset =
1441 oso_file_addr - oso_range_entry->GetRangeBase();
1442 const lldb::addr_t exe_file_addr =
1443 debug_map_entry->GetRangeBase() + offset;
1444 return exe_module->ResolveFileAddress(exe_file_addr, addr);
1445 }
1446 }
1447 }
1448 return true;
1449 }
1450
LinkOSOLineTable(SymbolFileDWARF * oso_dwarf,LineTable * line_table)1451 LineTable *SymbolFileDWARFDebugMap::LinkOSOLineTable(SymbolFileDWARF *oso_dwarf,
1452 LineTable *line_table) {
1453 CompileUnitInfo *cu_info = GetCompileUnitInfo(oso_dwarf);
1454 if (cu_info)
1455 return line_table->LinkLineTable(cu_info->GetFileRangeMap(this));
1456 return nullptr;
1457 }
1458
1459 size_t
AddOSOARanges(SymbolFileDWARF * dwarf2Data,DWARFDebugAranges * debug_aranges)1460 SymbolFileDWARFDebugMap::AddOSOARanges(SymbolFileDWARF *dwarf2Data,
1461 DWARFDebugAranges *debug_aranges) {
1462 size_t num_line_entries_added = 0;
1463 if (debug_aranges && dwarf2Data) {
1464 CompileUnitInfo *compile_unit_info = GetCompileUnitInfo(dwarf2Data);
1465 if (compile_unit_info) {
1466 const FileRangeMap &file_range_map =
1467 compile_unit_info->GetFileRangeMap(this);
1468 for (size_t idx = 0; idx < file_range_map.GetSize(); idx++) {
1469 const FileRangeMap::Entry *entry = file_range_map.GetEntryAtIndex(idx);
1470 if (entry) {
1471 debug_aranges->AppendRange(dwarf2Data->GetID(), entry->GetRangeBase(),
1472 entry->GetRangeEnd());
1473 num_line_entries_added++;
1474 }
1475 }
1476 }
1477 }
1478 return num_line_entries_added;
1479 }
1480
GetDebugInfoModules()1481 ModuleList SymbolFileDWARFDebugMap::GetDebugInfoModules() {
1482 ModuleList oso_modules;
1483 ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
1484 ObjectFile *oso_objfile = oso_dwarf->GetObjectFile();
1485 if (oso_objfile) {
1486 ModuleSP module_sp = oso_objfile->GetModule();
1487 if (module_sp)
1488 oso_modules.Append(module_sp);
1489 }
1490 return false; // Keep iterating
1491 });
1492 return oso_modules;
1493 }
1494
CalculateFrameVariableError(StackFrame & frame)1495 Status SymbolFileDWARFDebugMap::CalculateFrameVariableError(StackFrame &frame) {
1496 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1497
1498 // We need to make sure that our PC value from the frame matches the module
1499 // for this object file since we will lookup the PC file address in the debug
1500 // map below.
1501 Address pc_addr = frame.GetFrameCodeAddress();
1502 if (pc_addr.GetModule() == m_objfile_sp->GetModule()) {
1503 Symtab *symtab = m_objfile_sp->GetSymtab();
1504 if (symtab) {
1505 const DebugMap::Entry *debug_map_entry =
1506 m_debug_map.FindEntryThatContains(pc_addr.GetFileAddress());
1507 if (debug_map_entry) {
1508 Symbol *symbol =
1509 symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex());
1510 if (symbol) {
1511 uint32_t oso_idx = 0;
1512 CompileUnitInfo *comp_unit_info =
1513 GetCompileUnitInfoForSymbolWithID(symbol->GetID(), &oso_idx);
1514 if (comp_unit_info) {
1515 Module *oso_module = GetModuleByCompUnitInfo(comp_unit_info);
1516 if (oso_module) {
1517 // Check the .o file's DWARF in case it has an error to display.
1518 SymbolFile *oso_sym_file = oso_module->GetSymbolFile();
1519 if (oso_sym_file)
1520 return oso_sym_file->GetFrameVariableError(frame);
1521 }
1522 // If we don't have a valid OSO module here, then something went
1523 // wrong as we have a symbol for the address in the debug map, but
1524 // we weren't able to open the .o file. Display an appropriate
1525 // error
1526 if (comp_unit_info->oso_load_error.Fail())
1527 return comp_unit_info->oso_load_error;
1528 else
1529 return Status("unable to load debug map object file \"%s\" "
1530 "exist, debug info will not be loaded",
1531 comp_unit_info->oso_path.GetCString());
1532 }
1533 }
1534 }
1535 }
1536 }
1537 return Status();
1538 }
1539