forked from OSchip/llvm-project
[lldb] [DWARF-5] Be lazier about loading .dwo files
This change makes sure that DwarfUnit does not load a .dwo file until necessary. I also take advantage of DWARF 5's guarantee that the first support file is also the primary file to make it possible to create a compile unit without loading the .dwo file. Review By: jankratochvil, dblaikie Differential Revision: https://reviews.llvm.org/D100299
This commit is contained in:
parent
ce52e0339f
commit
e7b8ba103a
|
@ -442,6 +442,7 @@ private:
|
|||
|
||||
CompileUnit(const CompileUnit &) = delete;
|
||||
const CompileUnit &operator=(const CompileUnit &) = delete;
|
||||
const char *GetCachedLanguage() const;
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
|
|
@ -35,12 +35,12 @@ DWARFUnit::DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
|
|||
DIERef::Section section, bool is_dwo)
|
||||
: UserID(uid), m_dwarf(dwarf), m_header(header), m_abbrevs(&abbrevs),
|
||||
m_cancel_scopes(false), m_section(section), m_is_dwo(is_dwo),
|
||||
m_dwo_id(header.GetDWOId()) {}
|
||||
m_has_parsed_non_skeleton_unit(false), m_dwo_id(header.GetDWOId()) {}
|
||||
|
||||
DWARFUnit::~DWARFUnit() = default;
|
||||
|
||||
// Parses first DIE of a compile unit.
|
||||
void DWARFUnit::ExtractUnitDIEIfNeeded() {
|
||||
// Parses first DIE of a compile unit, excluding DWO.
|
||||
void DWARFUnit::ExtractUnitDIENoDwoIfNeeded() {
|
||||
{
|
||||
llvm::sys::ScopedReader lock(m_first_die_mutex);
|
||||
if (m_first_die)
|
||||
|
@ -50,7 +50,8 @@ void DWARFUnit::ExtractUnitDIEIfNeeded() {
|
|||
if (m_first_die)
|
||||
return; // Already parsed
|
||||
|
||||
LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractUnitDIEIfNeeded()", GetOffset());
|
||||
LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractUnitDIENoDwoIfNeeded()",
|
||||
GetOffset());
|
||||
|
||||
// Set the offset to that of the first DIE and calculate the start of the
|
||||
// next compilation unit header.
|
||||
|
@ -66,6 +67,58 @@ void DWARFUnit::ExtractUnitDIEIfNeeded() {
|
|||
}
|
||||
}
|
||||
|
||||
// Parses first DIE of a compile unit including DWO.
|
||||
void DWARFUnit::ExtractUnitDIEIfNeeded() {
|
||||
ExtractUnitDIENoDwoIfNeeded();
|
||||
|
||||
if (m_has_parsed_non_skeleton_unit)
|
||||
return;
|
||||
|
||||
m_has_parsed_non_skeleton_unit = true;
|
||||
|
||||
std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
|
||||
m_dwarf.GetDwoSymbolFileForCompileUnit(*this, m_first_die);
|
||||
if (!dwo_symbol_file)
|
||||
return;
|
||||
|
||||
DWARFUnit *dwo_cu = dwo_symbol_file->GetDWOCompileUnitForHash(m_dwo_id);
|
||||
|
||||
if (!dwo_cu)
|
||||
return; // Can't fetch the compile unit from the dwo file.
|
||||
dwo_cu->SetUserData(this);
|
||||
|
||||
DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
|
||||
if (!dwo_cu_die.IsValid())
|
||||
return; // Can't fetch the compile unit DIE from the dwo file.
|
||||
|
||||
// Here for DWO CU we want to use the address base set in the skeleton unit
|
||||
// (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base
|
||||
// otherwise. We do that because pre-DWARF v5 could use the DW_AT_GNU_*
|
||||
// attributes which were applicable to the DWO units. The corresponding
|
||||
// DW_AT_* attributes standardized in DWARF v5 are also applicable to the
|
||||
// main unit in contrast.
|
||||
if (m_addr_base)
|
||||
dwo_cu->SetAddrBase(*m_addr_base);
|
||||
else if (m_gnu_addr_base)
|
||||
dwo_cu->SetAddrBase(*m_gnu_addr_base);
|
||||
|
||||
if (GetVersion() <= 4 && m_gnu_ranges_base)
|
||||
dwo_cu->SetRangesBase(*m_gnu_ranges_base);
|
||||
else if (dwo_symbol_file->GetDWARFContext()
|
||||
.getOrLoadRngListsData()
|
||||
.GetByteSize() > 0)
|
||||
dwo_cu->SetRangesBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
|
||||
|
||||
if (GetVersion() >= 5 &&
|
||||
dwo_symbol_file->GetDWARFContext().getOrLoadLocListsData().GetByteSize() >
|
||||
0)
|
||||
dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
|
||||
|
||||
dwo_cu->SetBaseAddress(GetBaseAddress());
|
||||
|
||||
m_dwo = std::shared_ptr<DWARFUnit>(std::move(dwo_symbol_file), dwo_cu);
|
||||
}
|
||||
|
||||
// Parses a compile unit and indexes its DIEs if it hasn't already been done.
|
||||
// It will leave this compile unit extracted forever.
|
||||
void DWARFUnit::ExtractDIEsIfNeeded() {
|
||||
|
@ -291,14 +344,12 @@ void DWARFUnit::SetDwoStrOffsetsBase() {
|
|||
}
|
||||
|
||||
uint64_t DWARFUnit::GetDWOId() {
|
||||
ExtractUnitDIEIfNeeded();
|
||||
ExtractUnitDIENoDwoIfNeeded();
|
||||
return m_dwo_id;
|
||||
}
|
||||
|
||||
// m_die_array_mutex must be already held as read/write.
|
||||
void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
|
||||
llvm::Optional<uint64_t> addr_base, gnu_addr_base, gnu_ranges_base;
|
||||
|
||||
DWARFAttributes attributes;
|
||||
size_t num_attributes = cu_die.GetAttributes(this, attributes);
|
||||
|
||||
|
@ -308,8 +359,7 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
|
|||
continue;
|
||||
DWARFFormValue form_value;
|
||||
if (attributes.ExtractFormValueAtIndex(i, form_value)) {
|
||||
addr_base = form_value.Unsigned();
|
||||
SetAddrBase(*addr_base);
|
||||
SetAddrBase(form_value.Unsigned());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -341,10 +391,10 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
|
|||
m_line_table_offset = form_value.Unsigned();
|
||||
break;
|
||||
case DW_AT_GNU_addr_base:
|
||||
gnu_addr_base = form_value.Unsigned();
|
||||
m_gnu_addr_base = form_value.Unsigned();
|
||||
break;
|
||||
case DW_AT_GNU_ranges_base:
|
||||
gnu_ranges_base = form_value.Unsigned();
|
||||
m_gnu_ranges_base = form_value.Unsigned();
|
||||
break;
|
||||
case DW_AT_GNU_dwo_id:
|
||||
m_dwo_id = form_value.Unsigned();
|
||||
|
@ -353,50 +403,10 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
|
|||
}
|
||||
|
||||
if (m_is_dwo) {
|
||||
m_has_parsed_non_skeleton_unit = true;
|
||||
SetDwoStrOffsetsBase();
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
|
||||
m_dwarf.GetDwoSymbolFileForCompileUnit(*this, cu_die);
|
||||
if (!dwo_symbol_file)
|
||||
return;
|
||||
|
||||
DWARFUnit *dwo_cu = dwo_symbol_file->GetDWOCompileUnitForHash(m_dwo_id);
|
||||
|
||||
if (!dwo_cu)
|
||||
return; // Can't fetch the compile unit from the dwo file.
|
||||
dwo_cu->SetUserData(this);
|
||||
|
||||
DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
|
||||
if (!dwo_cu_die.IsValid())
|
||||
return; // Can't fetch the compile unit DIE from the dwo file.
|
||||
|
||||
// Here for DWO CU we want to use the address base set in the skeleton unit
|
||||
// (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base
|
||||
// otherwise. We do that because pre-DWARF v5 could use the DW_AT_GNU_*
|
||||
// attributes which were applicable to the DWO units. The corresponding
|
||||
// DW_AT_* attributes standardized in DWARF v5 are also applicable to the main
|
||||
// unit in contrast.
|
||||
if (addr_base)
|
||||
dwo_cu->SetAddrBase(*addr_base);
|
||||
else if (gnu_addr_base)
|
||||
dwo_cu->SetAddrBase(*gnu_addr_base);
|
||||
|
||||
if (GetVersion() <= 4 && gnu_ranges_base)
|
||||
dwo_cu->SetRangesBase(*gnu_ranges_base);
|
||||
else if (dwo_symbol_file->GetDWARFContext()
|
||||
.getOrLoadRngListsData()
|
||||
.GetByteSize() > 0)
|
||||
dwo_cu->SetRangesBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
|
||||
|
||||
if (GetVersion() >= 5 &&
|
||||
dwo_symbol_file->GetDWARFContext().getOrLoadLocListsData().GetByteSize() >
|
||||
0)
|
||||
dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
|
||||
dwo_cu->SetBaseAddress(GetBaseAddress());
|
||||
|
||||
m_dwo = std::shared_ptr<DWARFUnit>(std::move(dwo_symbol_file), dwo_cu);
|
||||
}
|
||||
|
||||
size_t DWARFUnit::GetDebugInfoSize() const {
|
||||
|
@ -412,7 +422,7 @@ dw_offset_t DWARFUnit::GetAbbrevOffset() const {
|
|||
}
|
||||
|
||||
dw_offset_t DWARFUnit::GetLineTableOffset() {
|
||||
ExtractUnitDIEIfNeeded();
|
||||
ExtractUnitDIENoDwoIfNeeded();
|
||||
return m_line_table_offset;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,6 +92,7 @@ public:
|
|||
uint64_t GetDWOId();
|
||||
|
||||
void ExtractUnitDIEIfNeeded();
|
||||
void ExtractUnitDIENoDwoIfNeeded();
|
||||
void ExtractDIEsIfNeeded();
|
||||
|
||||
class ScopedExtractDIEs {
|
||||
|
@ -151,7 +152,7 @@ public:
|
|||
const DWARFAbbreviationDeclarationSet *GetAbbreviations() const;
|
||||
dw_offset_t GetAbbrevOffset() const;
|
||||
uint8_t GetAddressByteSize() const { return m_header.GetAddressByteSize(); }
|
||||
dw_addr_t GetAddrBase() const { return m_addr_base; }
|
||||
dw_addr_t GetAddrBase() const { return m_addr_base ? *m_addr_base : 0; }
|
||||
dw_addr_t GetBaseAddress() const { return m_base_addr; }
|
||||
dw_offset_t GetLineTableOffset();
|
||||
dw_addr_t GetRangesBase() const { return m_ranges_base; }
|
||||
|
@ -268,7 +269,7 @@ protected:
|
|||
// Get the DWARF unit DWARF debug information entry. Parse the single DIE
|
||||
// if needed.
|
||||
const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() {
|
||||
ExtractUnitDIEIfNeeded();
|
||||
ExtractUnitDIENoDwoIfNeeded();
|
||||
// m_first_die_mutex is not required as m_first_die is never cleared.
|
||||
if (!m_first_die)
|
||||
return NULL;
|
||||
|
@ -315,9 +316,11 @@ protected:
|
|||
lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate;
|
||||
llvm::Optional<lldb_private::FileSpec> m_comp_dir;
|
||||
llvm::Optional<lldb_private::FileSpec> m_file_spec;
|
||||
dw_addr_t m_addr_base = 0; ///< Value of DW_AT_addr_base.
|
||||
dw_addr_t m_loclists_base = 0; ///< Value of DW_AT_loclists_base.
|
||||
dw_addr_t m_ranges_base = 0; ///< Value of DW_AT_rnglists_base.
|
||||
llvm::Optional<dw_addr_t> m_addr_base; ///< Value of DW_AT_addr_base.
|
||||
dw_addr_t m_loclists_base = 0; ///< Value of DW_AT_loclists_base.
|
||||
dw_addr_t m_ranges_base = 0; ///< Value of DW_AT_rnglists_base.
|
||||
llvm::Optional<uint64_t> m_gnu_addr_base;
|
||||
llvm::Optional<uint64_t> m_gnu_ranges_base;
|
||||
|
||||
/// Value of DW_AT_stmt_list.
|
||||
dw_offset_t m_line_table_offset = DW_INVALID_OFFSET;
|
||||
|
@ -330,6 +333,7 @@ protected:
|
|||
|
||||
const DIERef::Section m_section;
|
||||
bool m_is_dwo;
|
||||
bool m_has_parsed_non_skeleton_unit;
|
||||
/// Value of DW_AT_GNU_dwo_id (v4) or dwo_id from CU header (v5).
|
||||
uint64_t m_dwo_id;
|
||||
|
||||
|
|
|
@ -687,6 +687,17 @@ static void MakeAbsoluteAndRemap(FileSpec &file_spec, DWARFUnit &dwarf_cu,
|
|||
file_spec.SetFile(*remapped_file, FileSpec::Style::native);
|
||||
}
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
||||
lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
|
||||
CompUnitSP cu_sp;
|
||||
CompileUnit *comp_unit = (CompileUnit *)dwarf_cu.GetUserData();
|
||||
|
@ -701,25 +712,66 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
|
|||
} else {
|
||||
ModuleSP module_sp(m_objfile_sp->GetModule());
|
||||
if (module_sp) {
|
||||
const DWARFBaseDIE cu_die =
|
||||
dwarf_cu.GetNonSkeletonUnit().GetUnitDIEOnly();
|
||||
if (cu_die) {
|
||||
FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle());
|
||||
MakeAbsoluteAndRemap(cu_file_spec, dwarf_cu, module_sp);
|
||||
|
||||
LanguageType cu_language = SymbolFileDWARF::LanguageTypeFromDWARF(
|
||||
cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0));
|
||||
|
||||
bool is_optimized = dwarf_cu.GetNonSkeletonUnit().GetIsOptimized();
|
||||
auto initialize_cu = [&](const FileSpec &file_spec,
|
||||
LanguageType cu_language) {
|
||||
BuildCuTranslationTable();
|
||||
cu_sp = std::make_shared<CompileUnit>(
|
||||
module_sp, &dwarf_cu, cu_file_spec,
|
||||
module_sp, &dwarf_cu, file_spec,
|
||||
*GetDWARFUnitIndex(dwarf_cu.GetID()), cu_language,
|
||||
is_optimized ? eLazyBoolYes : eLazyBoolNo);
|
||||
eLazyBoolCalculate);
|
||||
|
||||
dwarf_cu.SetUserData(cu_sp.get());
|
||||
|
||||
SetCompileUnitAtIndex(dwarf_cu.GetID(), cu_sp);
|
||||
};
|
||||
|
||||
auto lazy_initialize_cu = [&]() {
|
||||
// If the version is < 5, we can't do lazy initialization.
|
||||
if (dwarf_cu.GetVersion() < 5)
|
||||
return false;
|
||||
|
||||
// If there is no DWO, there is no reason to initialize
|
||||
// lazily; we will do eager initialization in that case.
|
||||
if (GetDebugMapSymfile())
|
||||
return false;
|
||||
const DWARFBaseDIE cu_die = dwarf_cu.GetUnitDIEOnly();
|
||||
if (!cu_die)
|
||||
return false;
|
||||
if (!GetDWOName(dwarf_cu, *cu_die.GetDIE()))
|
||||
return false;
|
||||
|
||||
// With DWARFv5 we can assume that the first support
|
||||
// file is also the name of the compile unit. This
|
||||
// allows us to avoid loading the non-skeleton unit,
|
||||
// which may be in a separate DWO file.
|
||||
FileSpecList support_files;
|
||||
if (!ParseSupportFiles(dwarf_cu, module_sp, support_files))
|
||||
return false;
|
||||
if (support_files.GetSize() == 0)
|
||||
return false;
|
||||
|
||||
initialize_cu(support_files.GetFileSpecAtIndex(0),
|
||||
eLanguageTypeUnknown);
|
||||
cu_sp->SetSupportFiles(std::move(support_files));
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!lazy_initialize_cu()) {
|
||||
// Eagerly initialize compile unit
|
||||
const DWARFBaseDIE cu_die =
|
||||
dwarf_cu.GetNonSkeletonUnit().GetUnitDIEOnly();
|
||||
if (cu_die) {
|
||||
LanguageType cu_language = SymbolFileDWARF::LanguageTypeFromDWARF(
|
||||
dwarf_cu.GetDWARFLanguageType());
|
||||
|
||||
FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle());
|
||||
|
||||
// Path needs to be remapped in this case. In the support files
|
||||
// case ParseSupportFiles takes care of the remapping.
|
||||
MakeAbsoluteAndRemap(cu_file_spec, dwarf_cu, module_sp);
|
||||
|
||||
initialize_cu(cu_file_spec, cu_language);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -807,7 +859,7 @@ lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) {
|
|||
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
|
||||
DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
|
||||
if (dwarf_cu)
|
||||
return GetLanguage(*dwarf_cu);
|
||||
return GetLanguage(dwarf_cu->GetNonSkeletonUnit());
|
||||
else
|
||||
return eLanguageTypeUnknown;
|
||||
}
|
||||
|
@ -898,18 +950,29 @@ bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit,
|
|||
if (!dwarf_cu)
|
||||
return false;
|
||||
|
||||
dw_offset_t offset = dwarf_cu->GetLineTableOffset();
|
||||
if (!ParseSupportFiles(*dwarf_cu, comp_unit.GetModule(), support_files))
|
||||
return false;
|
||||
|
||||
comp_unit.SetSupportFiles(support_files);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SymbolFileDWARF::ParseSupportFiles(DWARFUnit &dwarf_cu,
|
||||
const ModuleSP &module,
|
||||
FileSpecList &support_files) {
|
||||
|
||||
dw_offset_t offset = dwarf_cu.GetLineTableOffset();
|
||||
if (offset == DW_INVALID_OFFSET)
|
||||
return false;
|
||||
|
||||
llvm::DWARFDebugLine::Prologue prologue;
|
||||
if (!ParseLLVMLineTablePrologue(m_context, prologue, offset,
|
||||
dwarf_cu->GetOffset()))
|
||||
dwarf_cu.GetOffset()))
|
||||
return false;
|
||||
|
||||
comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue(
|
||||
comp_unit.GetModule(), prologue, dwarf_cu->GetPathStyle(),
|
||||
dwarf_cu->GetCompilationDirectory().GetCString()));
|
||||
support_files = ParseSupportFilesFromPrologue(
|
||||
module, prologue, dwarf_cu.GetPathStyle(),
|
||||
dwarf_cu.GetCompilationDirectory().GetCString());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -965,7 +1028,7 @@ bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) {
|
|||
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
|
||||
DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
|
||||
if (dwarf_cu)
|
||||
return dwarf_cu->GetIsOptimized();
|
||||
return dwarf_cu->GetNonSkeletonUnit().GetIsOptimized();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1585,17 +1648,6 @@ SymbolFileDWARF::GetDIE(const DIERef &die_ref) {
|
|||
return DebugInfo().GetDIE(die_ref);
|
||||
}
|
||||
|
||||
/// 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,
|
||||
|
|
|
@ -368,6 +368,9 @@ protected:
|
|||
lldb::TypeSP ParseType(const lldb_private::SymbolContext &sc,
|
||||
const DWARFDIE &die, bool *type_is_new);
|
||||
|
||||
bool ParseSupportFiles(DWARFUnit &dwarf_cu, const lldb::ModuleSP &module,
|
||||
lldb_private::FileSpecList &support_files);
|
||||
|
||||
lldb_private::Type *ResolveTypeUID(const DWARFDIE &die,
|
||||
bool assert_not_being_parsed);
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ void CompileUnit::DumpSymbolContext(Stream *s) {
|
|||
|
||||
void CompileUnit::GetDescription(Stream *s,
|
||||
lldb::DescriptionLevel level) const {
|
||||
const char *language = Language::GetNameForLanguageType(m_language);
|
||||
const char *language = GetCachedLanguage();
|
||||
*s << "id = " << (const UserID &)*this << ", file = \""
|
||||
<< this->GetPrimaryFile() << "\", language = \"" << language << '"';
|
||||
}
|
||||
|
@ -97,12 +97,18 @@ lldb::FunctionSP CompileUnit::FindFunction(
|
|||
return {};
|
||||
}
|
||||
|
||||
const char *CompileUnit::GetCachedLanguage() const {
|
||||
if (m_flags.IsClear(flagsParsedLanguage))
|
||||
return "<not loaded>";
|
||||
return Language::GetNameForLanguageType(m_language);
|
||||
}
|
||||
|
||||
// Dump the current contents of this object. No functions that cause on demand
|
||||
// parsing of functions, globals, statics are called, so this is a good
|
||||
// function to call to get an idea of the current contents of the CompileUnit
|
||||
// object.
|
||||
void CompileUnit::Dump(Stream *s, bool show_context) const {
|
||||
const char *language = Language::GetNameForLanguageType(m_language);
|
||||
const char *language = GetCachedLanguage();
|
||||
|
||||
s->Printf("%p: ", static_cast<const void *>(this));
|
||||
s->Indent();
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
// Test we load dwo information lazily.
|
||||
|
||||
// RUN: %clang_host %s -fno-standalone-debug -g \
|
||||
// RUN: -gdwarf-5 -gpubnames -gsplit-dwarf -c -o %t1.o -DONE
|
||||
// RUN: %clang_host %s -fno-standalone-debug -g \
|
||||
// RUN: -gdwarf-5 -gpubnames -gsplit-dwarf -c -o %t2.o -DTWO
|
||||
// RUN: %clang_host %t1.o %t2.o -o %t
|
||||
// RUN: %lldb %t -o "log enable ll""db object" -o "settings set stop-line-count-before 0" \
|
||||
// RUN: -o "b main" -o "run" -o "image lookup -n main -v" -b | FileCheck %s
|
||||
|
||||
// CHECK-NOT: 2.dwo,
|
||||
// CHECK: (lldb) b main
|
||||
// CHECK-NOT: 2.dwo,
|
||||
// CHECK: 1.dwo,
|
||||
// CHECK-NOT: 2.dwo,
|
||||
// CHECK: (lldb) run
|
||||
// CHECK-NOT: 2.dwo,
|
||||
// CHECK: stop reason = breakpoint
|
||||
// CHECK-NOT: 2.dwo,
|
||||
// CHECK: (lldb) image lookup
|
||||
// CHECK-NOT: 2.dwo,
|
||||
// CHECK: CompileUnit: id = {0x00000000}, file =
|
||||
// CHECK-SAME: language = "c99"
|
||||
// CHECK-NOT: 2.dwo,
|
||||
|
||||
#ifdef ONE
|
||||
int main() { return 0; }
|
||||
#else
|
||||
int x;
|
||||
#endif
|
|
@ -1 +1 @@
|
|||
config.suffixes = ['.cpp', '.m', '.mm', '.s', '.test', '.ll']
|
||||
config.suffixes = ['.cpp', '.m', '.mm', '.s', '.test', '.ll', '.c']
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// Test that optimized flag is properly included in DWARF.
|
||||
|
||||
// RUN: %clang_host %s -fno-standalone-debug -glldb \
|
||||
// RUN: -gdwarf-5 -gpubnames -gsplit-dwarf -O3 -c -o %t1.o
|
||||
|
||||
// RUN: llvm-dwarfdump %t1.o | FileCheck %s --check-prefix DWARFDUMP_O
|
||||
// RUN: llvm-dwarfdump %t1.dwo | FileCheck %s --check-prefix DWARFDUMP_DWO
|
||||
// RUN: %lldb -b -o 'script lldb.SBDebugger.Create().CreateTarget("%t1.o").FindFunctions("main",lldb.eFunctionNameTypeAuto).GetContextAtIndex(0).GetFunction().GetIsOptimized()' | FileCheck %s
|
||||
|
||||
// DWARFDUMP_O-NOT: DW_AT_APPLE_optimized
|
||||
//
|
||||
// DWARFDUMP_DWO: DW_TAG_compile_unit
|
||||
// DWARFDUMP_DWO-NOT: DW_TAG_
|
||||
// DWARFDUMP_DWO: DW_AT_APPLE_optimized (true)
|
||||
|
||||
// CHECK: (lldb) script lldb.SBDebugger.Create()
|
||||
// CHECK-NEXT: True
|
||||
|
||||
int main(void) { return 0; }
|
|
@ -10,40 +10,40 @@
|
|||
# CHECK: (INT3) A = 3
|
||||
|
||||
# CHECK-LABEL: image lookup -v -n F1
|
||||
# CHECK: CompileUnit: id = {0x00000001}, file = "1.c", language = "unknown"
|
||||
# CHECK: CompileUnit: id = {0x00000001}, file = "1.c", language = "<not loaded>"
|
||||
# CHECK: Function: {{.*}}, name = "F1", range = [0x0000000000000001-0x0000000000000002)
|
||||
# CHECK: Variable: {{.*}}, name = "x", type = "int", location = DW_OP_reg1 RDX
|
||||
|
||||
# SYMBOLS: Compile units:
|
||||
# SYMBOLS-NEXT: CompileUnit{0x00000000}, language = "unknown", file = '0.c'
|
||||
# SYMBOLS-NEXT: CompileUnit{0x00000000}, language = "<not loaded>", file = '0.c'
|
||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x0
|
||||
# SYMBOLS-NEXT: Function{{.*}}, demangled = F0
|
||||
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000000-0x00000001)
|
||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
|
||||
# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000001, 0x0000000000000001): DW_OP_reg0 RAX
|
||||
# SYMBOLS-EMPTY:
|
||||
# SYMBOLS-NEXT: CompileUnit{0x00000001}, language = "unknown", file = '1.c'
|
||||
# SYMBOLS-NEXT: CompileUnit{0x00000001}, language = "<not loaded>", file = '1.c'
|
||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x2
|
||||
# SYMBOLS-NEXT: Function{{.*}}, demangled = F1
|
||||
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000001-0x00000002)
|
||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
|
||||
# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000003, 0x0000000000000001): DW_OP_reg1 RDX
|
||||
# SYMBOLS-EMPTY:
|
||||
# SYMBOLS-NEXT: CompileUnit{0x00000002}, language = "unknown", file = '2.c'
|
||||
# SYMBOLS-NEXT: CompileUnit{0x00000002}, language = "<not loaded>", file = '2.c'
|
||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x4
|
||||
# SYMBOLS-NEXT: Function{{.*}}, demangled = F2
|
||||
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000002-0x00000003)
|
||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
|
||||
# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000005, 0x0000000000000001): DW_OP_reg2 RCX
|
||||
# SYMBOLS-EMPTY:
|
||||
# SYMBOLS-NEXT: CompileUnit{0x00000003}, language = "unknown", file = '3.c'
|
||||
# SYMBOLS-NEXT: CompileUnit{0x00000003}, language = "<not loaded>", file = '3.c'
|
||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x6
|
||||
# SYMBOLS-NEXT: Function{{.*}}, demangled = F3
|
||||
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000003-0x00000004)
|
||||
# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
|
||||
# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000007, 0x0000000000000001): DW_OP_reg3 RBX
|
||||
# SYMBOLS-EMPTY:
|
||||
# SYMBOLS-NEXT: CompileUnit{0x00000004}, language = "unknown", file = ''
|
||||
# SYMBOLS-NEXT: CompileUnit{0x00000004}, language = "<not loaded>", file = ''
|
||||
# SYMBOLS-EMPTY:
|
||||
|
||||
.section .debug_abbrev,"",@progbits
|
||||
|
|
Loading…
Reference in New Issue