aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp')
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp487
1 files changed, 307 insertions, 180 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index c982d59c2830..d45a8b56efe4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -94,6 +94,8 @@
using namespace lldb;
using namespace lldb_private;
+char SymbolFileDWARF::ID;
+
// static inline bool
// child_requires_parent_class_union_or_struct_to_be_completed (dw_tag_t tag)
//{
@@ -179,36 +181,46 @@ ParseLLVMLineTable(lldb_private::DWARFContext &context,
return *line_table;
}
-static FileSpecList ParseSupportFilesFromPrologue(
- const lldb::ModuleSP &module,
- const llvm::DWARFDebugLine::Prologue &prologue, FileSpec::Style style,
- llvm::StringRef compile_dir = {}, FileSpec first_file = {}) {
+static llvm::Optional<std::string>
+GetFileByIndex(const llvm::DWARFDebugLine::Prologue &prologue, size_t idx,
+ llvm::StringRef compile_dir, FileSpec::Style style) {
+ // Try to get an absolute path first.
+ std::string abs_path;
+ auto absolute = llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath;
+ if (prologue.getFileNameByIndex(idx, compile_dir, absolute, abs_path, style))
+ return std::move(abs_path);
+
+ // Otherwise ask for a relative path.
+ std::string rel_path;
+ auto relative = llvm::DILineInfoSpecifier::FileLineInfoKind::Default;
+ if (!prologue.getFileNameByIndex(idx, compile_dir, relative, rel_path, style))
+ return {};
+ return std::move(rel_path);
+}
+
+static FileSpecList
+ParseSupportFilesFromPrologue(const lldb::ModuleSP &module,
+ const llvm::DWARFDebugLine::Prologue &prologue,
+ FileSpec::Style style,
+ llvm::StringRef compile_dir = {}) {
FileSpecList support_files;
- support_files.Append(first_file);
+ size_t first_file = 0;
+ if (prologue.getVersion() <= 4) {
+ // File index 0 is not valid before DWARF v5. Add a dummy entry to ensure
+ // support file list indices match those we get from the debug info and line
+ // tables.
+ support_files.Append(FileSpec());
+ first_file = 1;
+ }
const size_t number_of_files = prologue.FileNames.size();
- for (size_t idx = 1; idx <= number_of_files; ++idx) {
- std::string original_file;
- if (!prologue.getFileNameByIndex(
- idx, compile_dir,
- llvm::DILineInfoSpecifier::FileLineInfoKind::Default, original_file,
- style)) {
- // Always add an entry so the indexes remain correct.
- support_files.EmplaceBack();
- continue;
- }
-
+ for (size_t idx = first_file; idx <= number_of_files; ++idx) {
std::string remapped_file;
- if (!prologue.getFileNameByIndex(
- idx, compile_dir,
- llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
- remapped_file, style)) {
- // Always add an entry so the indexes remain correct.
- support_files.EmplaceBack(original_file, style);
- continue;
- }
+ if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style))
+ if (!module->RemapSourceFile(llvm::StringRef(*file_path), remapped_file))
+ remapped_file = std::move(*file_path);
- module->RemapSourceFile(llvm::StringRef(original_file), remapped_file);
+ // Unconditionally add an entry, so the indices match up.
support_files.EmplaceBack(remapped_file, style);
}
@@ -585,22 +597,6 @@ void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type,
m_objfile_sp->ReadSectionData(section_sp.get(), data);
}
-const DWARFDataExtractor &SymbolFileDWARF::DebugLocData() {
- const DWARFDataExtractor &debugLocData = get_debug_loc_data();
- if (debugLocData.GetByteSize() > 0)
- return debugLocData;
- return get_debug_loclists_data();
-}
-
-const DWARFDataExtractor &SymbolFileDWARF::get_debug_loc_data() {
- return GetCachedSectionData(eSectionTypeDWARFDebugLoc, m_data_debug_loc);
-}
-
-const DWARFDataExtractor &SymbolFileDWARF::get_debug_loclists_data() {
- return GetCachedSectionData(eSectionTypeDWARFDebugLocLists,
- m_data_debug_loclists);
-}
-
DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() {
if (m_abbr)
return m_abbr.get();
@@ -672,21 +668,6 @@ DWARFDebugRanges *SymbolFileDWARF::GetDebugRanges() {
return m_ranges.get();
}
-DWARFDebugRngLists *SymbolFileDWARF::GetDebugRngLists() {
- if (!m_rnglists) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION,
- static_cast<void *>(this));
-
- if (m_context.getOrLoadRngListsData().GetByteSize() > 0)
- m_rnglists.reset(new DWARFDebugRngLists());
-
- if (m_rnglists)
- m_rnglists->Extract(m_context);
- }
- return m_rnglists.get();
-}
-
lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
CompUnitSP cu_sp;
CompileUnit *comp_unit = (CompileUnit *)dwarf_cu.GetUserData();
@@ -703,7 +684,8 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
} else {
ModuleSP module_sp(m_objfile_sp->GetModule());
if (module_sp) {
- const DWARFDIE cu_die = dwarf_cu.DIE();
+ const DWARFBaseDIE cu_die =
+ dwarf_cu.GetNonSkeletonUnit().GetUnitDIEOnly();
if (cu_die) {
FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle());
if (cu_file_spec) {
@@ -721,7 +703,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
LanguageType cu_language = DWARFUnit::LanguageTypeFromDWARF(
cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0));
- bool is_optimized = dwarf_cu.GetIsOptimized();
+ bool is_optimized = dwarf_cu.GetNonSkeletonUnit().GetIsOptimized();
BuildCuTranslationTable();
cu_sp = std::make_shared<CompileUnit>(
module_sp, &dwarf_cu, cu_file_spec,
@@ -828,15 +810,20 @@ lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) {
}
size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) {
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "SymbolFileDWARF::ParseFunctions");
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
if (!dwarf_cu)
return 0;
size_t functions_added = 0;
- std::vector<DWARFDIE> function_dies;
- dwarf_cu->AppendDIEsWithTag(DW_TAG_subprogram, function_dies);
- for (const DWARFDIE &die : function_dies) {
+ dwarf_cu = &dwarf_cu->GetNonSkeletonUnit();
+ for (DWARFDebugInfoEntry &entry : dwarf_cu->dies()) {
+ if (entry.Tag() != DW_TAG_subprogram)
+ continue;
+
+ DWARFDIE die(dwarf_cu, &entry);
if (comp_unit.FindFunctionByUID(die.GetID()))
continue;
if (ParseFunction(comp_unit, die))
@@ -846,16 +833,32 @@ size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) {
return functions_added;
}
-void SymbolFileDWARF::ForEachExternalModule(
- CompileUnit &comp_unit, llvm::function_ref<void(ModuleSP)> f) {
- UpdateExternalModuleListIfNeeded();
+bool SymbolFileDWARF::ForEachExternalModule(
+ CompileUnit &comp_unit,
+ llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
+ llvm::function_ref<bool(Module &)> lambda) {
+ // Only visit each symbol file once.
+ if (!visited_symbol_files.insert(this).second)
+ return false;
+ UpdateExternalModuleListIfNeeded();
for (auto &p : m_external_type_modules) {
ModuleSP module = p.second;
- f(module);
- for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i)
- module->GetCompileUnitAtIndex(i)->ForEachExternalModule(f);
+ if (!module)
+ continue;
+
+ // Invoke the action and potentially early-exit.
+ if (lambda(*module))
+ return true;
+
+ for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) {
+ auto cu = module->GetCompileUnitAtIndex(i);
+ bool early_exit = cu->ForEachExternalModule(visited_symbol_files, lambda);
+ if (early_exit)
+ return true;
+ }
}
+ return false;
}
bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit,
@@ -961,7 +964,7 @@ bool SymbolFileDWARF::ParseImportedModules(
DW_AT_LLVM_include_path, nullptr))
module.search_path = ConstString(include_path);
if (const char *sysroot = module_die.GetAttributeValueAsString(
- DW_AT_LLVM_isysroot, nullptr))
+ DW_AT_LLVM_sysroot, nullptr))
module.sysroot = ConstString(sysroot);
imported_modules.push_back(module);
}
@@ -1023,7 +1026,7 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) {
comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue(
comp_unit.GetModule(), line_table->Prologue, dwarf_cu->GetPathStyle(),
- dwarf_cu->GetCompilationDirectory().GetCString(), FileSpec(comp_unit)));
+ dwarf_cu->GetCompilationDirectory().GetCString()));
return true;
}
@@ -1507,7 +1510,7 @@ bool SymbolFileDWARF::GetFunction(const DWARFDIE &die, SymbolContext &sc) {
return false;
}
-lldb::ModuleSP SymbolFileDWARF::GetDWOModule(ConstString name) {
+lldb::ModuleSP SymbolFileDWARF::GetExternalModule(ConstString name) {
UpdateExternalModuleListIfNeeded();
const auto &pos = m_external_type_modules.find(name);
if (pos != m_external_type_modules.end())
@@ -1532,12 +1535,48 @@ SymbolFileDWARF::GetDIE(const DIERef &die_ref) {
return DWARFDIE();
}
+/// Return the DW_AT_(GNU_)dwo_name.
+static const char *GetDWOName(DWARFCompileUnit &dwarf_cu,
+ const DWARFDebugInfoEntry &cu_die) {
+ const char *dwo_name =
+ cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_GNU_dwo_name, nullptr);
+ if (!dwo_name)
+ dwo_name =
+ cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_dwo_name, nullptr);
+ return dwo_name;
+}
+
+/// Return the DW_AT_(GNU_)dwo_id.
+/// FIXME: Technically 0 is a valid hash.
+static uint64_t GetDWOId(DWARFCompileUnit &dwarf_cu,
+ const DWARFDebugInfoEntry &cu_die) {
+ uint64_t dwo_id =
+ cu_die.GetAttributeValueAsUnsigned(&dwarf_cu, DW_AT_GNU_dwo_id, 0);
+ if (!dwo_id)
+ dwo_id = cu_die.GetAttributeValueAsUnsigned(&dwarf_cu, DW_AT_dwo_id, 0);
+ return dwo_id;
+}
+
+llvm::Optional<uint64_t> SymbolFileDWARF::GetDWOId() {
+ if (GetNumCompileUnits() == 1) {
+ if (auto comp_unit = GetCompileUnitAtIndex(0))
+ if (DWARFCompileUnit *cu = llvm::dyn_cast_or_null<DWARFCompileUnit>(
+ GetDWARFCompileUnit(comp_unit.get())))
+ if (DWARFDebugInfoEntry *cu_die = cu->DIE().GetDIE())
+ if (uint64_t dwo_id = ::GetDWOId(*cu, *cu_die))
+ return dwo_id;
+ }
+ return {};
+}
+
std::unique_ptr<SymbolFileDWARFDwo>
SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
DWARFUnit &unit, const DWARFDebugInfoEntry &cu_die) {
- // If we are using a dSYM file, we never want the standard DWO files since
- // the -gmodules support uses the same DWO machanism to specify full debug
- // info files for modules.
+ // If this is a Darwin-style debug map (non-.dSYM) symbol file,
+ // never attempt to load ELF-style DWO files since the -gmodules
+ // support uses the same DWO machanism to specify full debug info
+ // files for modules. This is handled in
+ // UpdateExternalModuleListIfNeeded().
if (GetDebugMapSymfile())
return nullptr;
@@ -1546,15 +1585,13 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
if (!dwarf_cu)
return nullptr;
- const char *dwo_name =
- cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_GNU_dwo_name, nullptr);
+ const char *dwo_name = GetDWOName(*dwarf_cu, cu_die);
if (!dwo_name)
return nullptr;
SymbolFileDWARFDwp *dwp_symfile = GetDwpSymbolFile();
if (dwp_symfile) {
- uint64_t dwo_id =
- cu_die.GetAttributeValueAsUnsigned(dwarf_cu, DW_AT_GNU_dwo_id, 0);
+ uint64_t dwo_id = ::GetDWOId(*dwarf_cu, cu_die);
std::unique_ptr<SymbolFileDWARFDwo> dwo_symfile =
dwp_symfile->GetSymbolFileForDwoId(*dwarf_cu, dwo_id);
if (dwo_symfile)
@@ -1594,76 +1631,101 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() {
if (m_fetched_external_modules)
return;
m_fetched_external_modules = true;
-
DWARFDebugInfo *debug_info = DebugInfo();
+ // Follow DWO skeleton unit breadcrumbs.
const uint32_t num_compile_units = GetNumCompileUnits();
for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- DWARFUnit *dwarf_cu = debug_info->GetUnitAtIndex(cu_idx);
+ auto *dwarf_cu =
+ llvm::dyn_cast<DWARFCompileUnit>(debug_info->GetUnitAtIndex(cu_idx));
+ if (!dwarf_cu)
+ continue;
const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly();
- if (die && !die.HasChildren()) {
- const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
+ if (!die || die.HasChildren() || !die.GetDIE())
+ continue;
- if (name) {
- ConstString const_name(name);
- if (m_external_type_modules.find(const_name) ==
- m_external_type_modules.end()) {
- ModuleSP module_sp;
- const char *dwo_path =
- die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
- if (dwo_path) {
- ModuleSpec dwo_module_spec;
- dwo_module_spec.GetFileSpec().SetFile(dwo_path,
- FileSpec::Style::native);
- if (dwo_module_spec.GetFileSpec().IsRelative()) {
- const char *comp_dir =
- die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr);
- if (comp_dir) {
- dwo_module_spec.GetFileSpec().SetFile(comp_dir,
- FileSpec::Style::native);
- FileSystem::Instance().Resolve(dwo_module_spec.GetFileSpec());
- dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path);
- }
- }
- dwo_module_spec.GetArchitecture() =
- m_objfile_sp->GetModule()->GetArchitecture();
+ const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
+ if (!name)
+ continue;
- // When LLDB loads "external" modules it looks at the presence of
- // DW_AT_GNU_dwo_name. However, when the already created module
- // (corresponding to .dwo itself) is being processed, it will see
- // the presence of DW_AT_GNU_dwo_name (which contains the name of
- // dwo file) and will try to call ModuleList::GetSharedModule
- // again. In some cases (i.e. for empty files) Clang 4.0 generates
- // a *.dwo file which has DW_AT_GNU_dwo_name, but no
- // DW_AT_comp_dir. In this case the method
- // ModuleList::GetSharedModule will fail and the warning will be
- // printed. However, as one can notice in this case we don't
- // actually need to try to load the already loaded module
- // (corresponding to .dwo) so we simply skip it.
- if (m_objfile_sp->GetFileSpec().GetFileNameExtension() == ".dwo" &&
- llvm::StringRef(m_objfile_sp->GetFileSpec().GetPath())
- .endswith(dwo_module_spec.GetFileSpec().GetPath())) {
- continue;
- }
+ ConstString const_name(name);
+ ModuleSP &module_sp = m_external_type_modules[const_name];
+ if (module_sp)
+ continue;
- Status error = ModuleList::GetSharedModule(
- dwo_module_spec, module_sp, nullptr, nullptr, nullptr);
- if (!module_sp) {
- GetObjectFile()->GetModule()->ReportWarning(
- "0x%8.8x: unable to locate module needed for external types: "
- "%s\nerror: %s\nDebugging will be degraded due to missing "
- "types. Rebuilding your project will regenerate the needed "
- "module files.",
- die.GetOffset(),
- dwo_module_spec.GetFileSpec().GetPath().c_str(),
- error.AsCString("unknown error"));
- }
- }
- m_external_type_modules[const_name] = module_sp;
- }
+ const char *dwo_path = GetDWOName(*dwarf_cu, *die.GetDIE());
+ if (!dwo_path)
+ continue;
+
+ ModuleSpec dwo_module_spec;
+ dwo_module_spec.GetFileSpec().SetFile(dwo_path, FileSpec::Style::native);
+ if (dwo_module_spec.GetFileSpec().IsRelative()) {
+ const char *comp_dir =
+ die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr);
+ if (comp_dir) {
+ dwo_module_spec.GetFileSpec().SetFile(comp_dir,
+ FileSpec::Style::native);
+ FileSystem::Instance().Resolve(dwo_module_spec.GetFileSpec());
+ dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path);
}
}
+ dwo_module_spec.GetArchitecture() =
+ m_objfile_sp->GetModule()->GetArchitecture();
+
+ // When LLDB loads "external" modules it looks at the presence of
+ // DW_AT_dwo_name. However, when the already created module
+ // (corresponding to .dwo itself) is being processed, it will see
+ // the presence of DW_AT_dwo_name (which contains the name of dwo
+ // file) and will try to call ModuleList::GetSharedModule
+ // again. In some cases (i.e., for empty files) Clang 4.0
+ // generates a *.dwo file which has DW_AT_dwo_name, but no
+ // DW_AT_comp_dir. In this case the method
+ // ModuleList::GetSharedModule will fail and the warning will be
+ // printed. However, as one can notice in this case we don't
+ // actually need to try to load the already loaded module
+ // (corresponding to .dwo) so we simply skip it.
+ if (m_objfile_sp->GetFileSpec().GetFileNameExtension() == ".dwo" &&
+ llvm::StringRef(m_objfile_sp->GetFileSpec().GetPath())
+ .endswith(dwo_module_spec.GetFileSpec().GetPath())) {
+ continue;
+ }
+
+ Status error = ModuleList::GetSharedModule(dwo_module_spec, module_sp,
+ nullptr, nullptr, nullptr);
+ if (!module_sp) {
+ GetObjectFile()->GetModule()->ReportWarning(
+ "0x%8.8x: unable to locate module needed for external types: "
+ "%s\nerror: %s\nDebugging will be degraded due to missing "
+ "types. Rebuilding the project will regenerate the needed "
+ "module files.",
+ die.GetOffset(), dwo_module_spec.GetFileSpec().GetPath().c_str(),
+ error.AsCString("unknown error"));
+ continue;
+ }
+
+ // Verify the DWO hash.
+ // FIXME: Technically "0" is a valid hash.
+ uint64_t dwo_id = ::GetDWOId(*dwarf_cu, *die.GetDIE());
+ if (!dwo_id)
+ continue;
+
+ auto *dwo_symfile =
+ llvm::dyn_cast_or_null<SymbolFileDWARF>(module_sp->GetSymbolFile());
+ if (!dwo_symfile)
+ continue;
+ llvm::Optional<uint64_t> dwo_dwo_id = dwo_symfile->GetDWOId();
+ if (!dwo_dwo_id)
+ continue;
+
+ if (dwo_id != dwo_dwo_id) {
+ GetObjectFile()->GetModule()->ReportWarning(
+ "0x%8.8x: Module %s is out-of-date (hash mismatch). Type information "
+ "from this module may be incomplete or inconsistent with the rest of "
+ "the program. Rebuilding the project will regenerate the needed "
+ "module files.",
+ die.GetOffset(), dwo_module_spec.GetFileSpec().GetPath().c_str());
+ }
}
}
@@ -1867,9 +1929,8 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
if (!dc_cu)
continue;
- const bool full_match = (bool)file_spec.GetDirectory();
bool file_spec_matches_cu_file_spec =
- FileSpec::Equal(file_spec, *dc_cu, full_match);
+ FileSpec::Match(file_spec, dc_cu->GetPrimaryFile());
if (check_inlines || file_spec_matches_cu_file_spec) {
SymbolContext sc(m_objfile_sp->GetModule());
sc.comp_unit = dc_cu;
@@ -2208,9 +2269,12 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
addr = sc.function->GetAddressRange().GetBaseAddress();
}
- if (addr.IsValid()) {
- sc_list.Append(sc);
- return true;
+
+ if (auto section_sp = addr.GetSection()) {
+ if (section_sp->GetPermissions() & ePermissionsExecutable) {
+ sc_list.Append(sc);
+ return true;
+ }
}
}
@@ -2364,12 +2428,10 @@ void SymbolFileDWARF::FindTypes(
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
- // Make sure we haven't already searched this SymbolFile before...
- if (searched_symbol_files.count(this))
+ // Make sure we haven't already searched this SymbolFile before.
+ if (!searched_symbol_files.insert(this).second)
return;
- searched_symbol_files.insert(this);
-
DWARFDebugInfo *info = DebugInfo();
if (!info)
return;
@@ -2451,8 +2513,13 @@ void SymbolFileDWARF::FindTypes(
}
}
-void SymbolFileDWARF::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
- LanguageSet languages, TypeMap &types) {
+void SymbolFileDWARF::FindTypes(
+ llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {
+ // Make sure we haven't already searched this SymbolFile before.
+ if (!searched_symbol_files.insert(this).second)
+ return;
+
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
if (pattern.empty())
return;
@@ -2482,11 +2549,22 @@ void SymbolFileDWARF::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
if (!contextMatches(die_context, pattern))
continue;
- if (Type *matching_type = ResolveType(die, true, true))
+ if (Type *matching_type = ResolveType(die, true, true)) {
// We found a type pointer, now find the shared pointer form our type
// list.
types.InsertUnique(matching_type->shared_from_this());
+ }
}
+
+ // Next search through the reachable Clang modules. This only applies for
+ // DWARF objects compiled with -gmodules that haven't been processed by
+ // dsymutil.
+ UpdateExternalModuleListIfNeeded();
+
+ for (const auto &pair : m_external_type_modules)
+ if (ModuleSP external_module_sp = pair.second)
+ external_module_sp->FindTypes(pattern, languages, searched_symbol_files,
+ types);
}
CompilerDeclContext
@@ -3268,15 +3346,17 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
module, DataExtractor(data, block_offset, block_length),
die.GetCU());
} else {
- DataExtractor data = DebugLocData();
- const dw_offset_t offset = form_value.Unsigned();
+ DataExtractor data = die.GetCU()->GetLocationData();
+ dw_offset_t offset = form_value.Unsigned();
+ if (form_value.Form() == DW_FORM_loclistx)
+ offset = die.GetCU()->GetLoclistOffset(offset).getValueOr(-1);
if (data.ValidOffset(offset)) {
data = DataExtractor(data, offset, data.GetByteSize() - offset);
location = DWARFExpression(module, data, die.GetCU());
assert(func_low_pc != LLDB_INVALID_ADDRESS);
- location.SetLocationListSlide(
- func_low_pc -
- attributes.CompileUnitAtIndex(i)->GetBaseAddress());
+ location.SetLocationListAddresses(
+ attributes.CompileUnitAtIndex(i)->GetBaseAddress(),
+ func_low_pc);
}
}
} break;
@@ -3685,8 +3765,8 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
if (child.Tag() != DW_TAG_call_site_parameter)
continue;
- llvm::Optional<DWARFExpression> LocationInCallee = {};
- llvm::Optional<DWARFExpression> LocationInCaller = {};
+ llvm::Optional<DWARFExpression> LocationInCallee;
+ llvm::Optional<DWARFExpression> LocationInCaller;
DWARFAttributes attributes;
const size_t num_attributes = child.GetAttributes(attributes);
@@ -3725,7 +3805,7 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
}
/// Collect call graph edges present in a function DIE.
-static std::vector<lldb_private::CallEdge>
+static std::vector<std::unique_ptr<lldb_private::CallEdge>>
CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
// Check if the function has a supported call site-related attribute.
// TODO: In the future it may be worthwhile to support call_all_source_calls.
@@ -3743,32 +3823,87 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
// to be DWARF5-compliant. This may need to be done lazily to be performant.
// For now, assume that all entries are nested directly under the subprogram
// (this is the kind of DWARF LLVM produces) and parse them eagerly.
- std::vector<CallEdge> call_edges;
+ std::vector<std::unique_ptr<CallEdge>> call_edges;
for (DWARFDIE child = function_die.GetFirstChild(); child.IsValid();
child = child.GetSibling()) {
if (child.Tag() != DW_TAG_call_site)
continue;
- // Extract DW_AT_call_origin (the call target's DIE).
- DWARFDIE call_origin = child.GetReferencedDIE(DW_AT_call_origin);
- if (!call_origin.IsValid()) {
- LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}",
- function_die.GetPubname());
+ llvm::Optional<DWARFDIE> call_origin;
+ llvm::Optional<DWARFExpression> call_target;
+ addr_t return_pc = LLDB_INVALID_ADDRESS;
+
+ DWARFAttributes attributes;
+ const size_t num_attributes = child.GetAttributes(attributes);
+ for (size_t i = 0; i < num_attributes; ++i) {
+ DWARFFormValue form_value;
+ if (!attributes.ExtractFormValueAtIndex(i, form_value)) {
+ LLDB_LOG(log, "CollectCallEdges: Could not extract TAG_call_site form");
+ break;
+ }
+
+ dw_attr_t attr = attributes.AttributeAtIndex(i);
+
+ // Extract DW_AT_call_origin (the call target's DIE).
+ if (attr == DW_AT_call_origin) {
+ call_origin = form_value.Reference();
+ if (!call_origin->IsValid()) {
+ LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}",
+ function_die.GetPubname());
+ break;
+ }
+ }
+
+ // Extract DW_AT_call_return_pc (the PC the call returns to) if it's
+ // available. It should only ever be unavailable for tail call edges, in
+ // which case use LLDB_INVALID_ADDRESS.
+ if (attr == DW_AT_call_return_pc)
+ return_pc = form_value.Address();
+
+ // Extract DW_AT_call_target (the location of the address of the indirect
+ // call).
+ if (attr == DW_AT_call_target) {
+ if (!DWARFFormValue::IsBlockForm(form_value.Form())) {
+ LLDB_LOG(log,
+ "CollectCallEdges: AT_call_target does not have block form");
+ break;
+ }
+
+ auto data = child.GetData();
+ uint32_t block_offset = form_value.BlockData() - data.GetDataStart();
+ uint32_t block_length = form_value.Unsigned();
+ call_target = DWARFExpression(
+ module, DataExtractor(data, block_offset, block_length),
+ child.GetCU());
+ }
+ }
+ if (!call_origin && !call_target) {
+ LLDB_LOG(log, "CollectCallEdges: call site without any call target");
continue;
}
- // Extract DW_AT_call_return_pc (the PC the call returns to) if it's
- // available. It should only ever be unavailable for tail call edges, in
- // which case use LLDB_INVALID_ADDRESS.
- addr_t return_pc = child.GetAttributeValueAsAddress(DW_AT_call_return_pc,
- LLDB_INVALID_ADDRESS);
-
// Extract call site parameters.
CallSiteParameterArray parameters =
CollectCallSiteParameters(module, child);
- LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})",
- call_origin.GetPubname(), return_pc);
+ std::unique_ptr<CallEdge> edge;
+ if (call_origin) {
+ LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})",
+ call_origin->GetPubname(), return_pc);
+ edge = std::make_unique<DirectCallEdge>(call_origin->GetMangledName(),
+ return_pc, std::move(parameters));
+ } else {
+ if (log) {
+ StreamString call_target_desc;
+ call_target->GetDescription(&call_target_desc, eDescriptionLevelBrief,
+ LLDB_INVALID_ADDRESS, nullptr);
+ LLDB_LOG(log, "CollectCallEdges: Found indirect call target: {0}",
+ call_target_desc.GetString());
+ }
+ edge = std::make_unique<IndirectCallEdge>(*call_target, return_pc,
+ std::move(parameters));
+ }
+
if (log && parameters.size()) {
for (const CallSiteParameter &param : parameters) {
StreamString callee_loc_desc, caller_loc_desc;
@@ -3783,13 +3918,12 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
}
}
- call_edges.emplace_back(call_origin.GetMangledName(), return_pc,
- std::move(parameters));
+ call_edges.push_back(std::move(edge));
}
return call_edges;
}
-std::vector<lldb_private::CallEdge>
+std::vector<std::unique_ptr<lldb_private::CallEdge>>
SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) {
DWARFDIE func_die = GetDIE(func_id.GetID());
if (func_die.IsValid())
@@ -3829,13 +3963,6 @@ SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
return m_debug_map_symfile;
}
-DWARFExpression::LocationListFormat
-SymbolFileDWARF::GetLocationListFormat() const {
- if (m_data_debug_loclists.m_data.GetByteSize() > 0)
- return DWARFExpression::LocLists;
- return DWARFExpression::RegularLocationList;
-}
-
SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() {
llvm::call_once(m_dwp_symfile_once_flag, [this]() {
ModuleSpec module_spec;