Skip to content

Commit

Permalink
DWARF: Add "dwo_num" field to the DIERef class
Browse files Browse the repository at this point in the history
Summary:
When dwo support was introduced, it used a trick where debug info
entries were referenced by the offset of the compile unit in the main
file, but the die offset was relative to the dwo file. Although there
was some elegance to it, this representation was starting to reach its
breaking point:
- the fact that the skeleton compile unit owned the DWO file meant that
  it was impossible (or at least hard and unintuitive) to support DWO
  files containing more than one compile unit. These kinds of files are
  produced by LTO for example.
- it made it impossible to reference any DIEs in the skeleton compile
  unit (although the skeleton units are generally empty, clang still
  puts some info into them with -fsplit-dwarf-inlining).
- (current motivation) it made it very hard to support type units placed
  in DWO files, as type units don't have any skeleton units which could
  be referenced in the main file

This patch addresses this problem by introducing an new
"dwo_num" field to the DIERef class, whose purpose is to identify the
dwo file. It's kind of similar to the dwo_id field in DWARF5 unit
headers, but while this is a 64bit hash whose main purpose is to catch
file mismatches, this is just a smaller integer used to indentify a
loaded dwo file. Currently, this is based on the index of the skeleton
compile unit which owns the dwo file, but it is intended to be
eventually independent of that (to support the LTO use case).

Simultaneously the cu_offset is dropped to conserve space, as it is no
longer necessary.  This means we can remove the "BaseObjectOffset" field
from the DWARFUnit class. It also means we can remove some of the
workarounds put in place to support the skeleton-unit+dwo-die combo.
More work is needed to remove all of them, which is out of scope of this
patch.

Reviewers: JDevlieghere, clayborg, aprantl

Subscribers: mehdi_amini, dexonsmith, arphaman, lldb-commits

Differential Revision: https://reviews.llvm.org/D63428

llvm-svn: 364009
  • Loading branch information
labath committed Jun 21, 2019
1 parent b9b1aaf commit 3b92698
Show file tree
Hide file tree
Showing 24 changed files with 136 additions and 138 deletions.
10 changes: 10 additions & 0 deletions lldb/lit/SymbolFile/DWARF/find-variable-file.cpp
Expand Up @@ -8,6 +8,16 @@
// RUN: lldb-test symbols --file=find-variable-file-2.cpp --find=variable %t | \
// RUN: FileCheck --check-prefix=TWO %s

// Run the same test with split-dwarf. This is interesting because the two
// split compile units will have the same offset (0).
// RUN: %clang -g -c -o %t-1.o --target=x86_64-pc-linux -gsplit-dwarf %s
// RUN: %clang -g -c -o %t-2.o --target=x86_64-pc-linux -gsplit-dwarf %S/Inputs/find-variable-file-2.cpp
// RUN: ld.lld %t-1.o %t-2.o -o %t
// RUN: lldb-test symbols --file=find-variable-file.cpp --find=variable %t | \
// RUN: FileCheck --check-prefix=ONE %s
// RUN: lldb-test symbols --file=find-variable-file-2.cpp --find=variable %t | \
// RUN: FileCheck --check-prefix=TWO %s

// RUN: %clang -g -c -o %t-1.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf %s
// RUN: %clang -g -c -o %t-2.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf %S/Inputs/find-variable-file-2.cpp
// RUN: ld.lld %t-1.o %t-2.o -o %t
Expand Down
5 changes: 2 additions & 3 deletions lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
Expand Up @@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//

#include "Plugins/SymbolFile/DWARF/AppleDWARFIndex.h"
#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
Expand Down Expand Up @@ -133,14 +132,14 @@ void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {
m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets);
}

void AppleDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info,
void AppleDWARFIndex::GetFunctions(ConstString name, SymbolFileDWARF &dwarf,
const CompilerDeclContext &parent_decl_ctx,
uint32_t name_type_mask,
std::vector<DWARFDIE> &dies) {
DIEArray offsets;
m_apple_names_up->FindByName(name.GetStringRef(), offsets);
for (const DIERef &die_ref : offsets) {
ProcessFunctionDIE(name.GetStringRef(), die_ref, info, parent_decl_ctx,
ProcessFunctionDIE(name.GetStringRef(), die_ref, dwarf, parent_decl_ctx,
name_type_mask, dies);
}
}
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h
Expand Up @@ -42,7 +42,7 @@ class AppleDWARFIndex : public DWARFIndex {
void GetTypes(ConstString name, DIEArray &offsets) override;
void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override;
void GetNamespaces(ConstString name, DIEArray &offsets) override;
void GetFunctions(ConstString name, DWARFDebugInfo &info,
void GetFunctions(ConstString name, SymbolFileDWARF &dwarf,
const CompilerDeclContext &parent_decl_ctx,
uint32_t name_type_mask,
std::vector<DWARFDIE> &dies) override;
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp
Expand Up @@ -11,8 +11,8 @@

void llvm::format_provider<DIERef>::format(const DIERef &ref, raw_ostream &OS,
StringRef Style) {
if (ref.dwo_num())
OS << format_hex_no_prefix(*ref.dwo_num(), 8) << "/";
OS << (ref.section() == DIERef::DebugInfo ? "INFO" : "TYPE");
if (ref.unit_offset())
OS << "/" << format_hex_no_prefix(*ref.unit_offset(), 8);
OS << "/" << format_hex_no_prefix(ref.die_offset(), 8);
}
39 changes: 21 additions & 18 deletions lldb/source/Plugins/SymbolFile/DWARF/DIERef.h
Expand Up @@ -12,42 +12,45 @@
#include "lldb/Core/dwarf.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/FormatProviders.h"
#include <cassert>
#include <vector>

/// Identifies a DWARF debug info entry within a given Module. It contains three
/// "coordinates":
/// - section: identifies the section of the debug info entry: debug_info or
/// debug_types
/// - unit_offset: the offset of the unit containing the debug info entry. For
/// regular (unsplit) units, this field is optional, as the die_offset is
/// enough to uniquely identify the containing unit. For split units, this
/// field must contain the offset of the skeleton unit in the main object
/// file.
/// - die_offset: The offset of te debug info entry as an absolute offset from
/// - dwo_num: identifies the dwo file in the Module. If this field is not set,
/// the DIERef references the main file.
/// - section: identifies the section of the debug info entry in the given file:
/// debug_info or debug_types.
/// - die_offset: The offset of the debug info entry as an absolute offset from
/// the beginning of the section specified in the section field.
class DIERef {
public:
enum Section : uint8_t { DebugInfo, DebugTypes };

DIERef(Section s, llvm::Optional<dw_offset_t> u, dw_offset_t d)
: m_section(s), m_unit_offset(u.getValueOr(DW_INVALID_OFFSET)),
m_die_offset(d) {}

Section section() const { return static_cast<Section>(m_section); }
DIERef(llvm::Optional<uint32_t> dwo_num, Section section,
dw_offset_t die_offset)
: m_dwo_num(dwo_num.getValueOr(0)), m_dwo_num_valid(bool(dwo_num)),
m_section(section), m_die_offset(die_offset) {
assert(this->dwo_num() == dwo_num && "Dwo number out of range?");
}

llvm::Optional<dw_offset_t> unit_offset() const {
if (m_unit_offset != DW_INVALID_OFFSET)
return m_unit_offset;
llvm::Optional<uint32_t> dwo_num() const {
if (m_dwo_num_valid)
return m_dwo_num;
return llvm::None;
}

Section section() const { return static_cast<Section>(m_section); }

dw_offset_t die_offset() const { return m_die_offset; }

private:
unsigned m_section : 1;
dw_offset_t m_unit_offset;
uint32_t m_dwo_num : 30;
uint32_t m_dwo_num_valid : 1;
uint32_t m_section : 1;
dw_offset_t m_die_offset;
};
static_assert(sizeof(DIERef) == 8, "");

typedef std::vector<DIERef> DIEArray;

Expand Down
6 changes: 2 additions & 4 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
Expand Up @@ -21,10 +21,8 @@ llvm::Optional<DIERef> DWARFBaseDIE::GetDIERef() const {
if (!IsValid())
return llvm::None;

dw_offset_t cu_offset = m_cu->GetOffset();
if (m_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
cu_offset = m_cu->GetBaseObjOffset();
return DIERef(m_cu->GetDebugSection(), cu_offset, m_die->GetOffset());
return DIERef(m_cu->GetSymbolFileDWARF().GetDwoNum(), m_cu->GetDebugSection(),
m_die->GetOffset());
}

dw_tag_t DWARFBaseDIE::Tag() const {
Expand Down
6 changes: 3 additions & 3 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
Expand Up @@ -151,9 +151,9 @@ DWARFDIE::LookupDeepestBlock(lldb::addr_t file_addr) const {
if (cu->ContainsDIEOffset(block_die->GetOffset()))
return DWARFDIE(cu, block_die);
else
return DWARFDIE(dwarf->DebugInfo()->GetUnit(
DIERef(cu->GetDebugSection(), cu->GetOffset(),
block_die->GetOffset())),
return DWARFDIE(dwarf->DebugInfo()->GetUnit(DIERef(
cu->GetSymbolFileDWARF().GetDwoNum(),
cu->GetDebugSection(), block_die->GetOffset())),
block_die);
}
}
Expand Down
2 changes: 0 additions & 2 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
Expand Up @@ -149,8 +149,6 @@ DWARFUnit *DWARFDebugInfo::GetUnitAtOffset(DIERef::Section section,
}

DWARFUnit *DWARFDebugInfo::GetUnit(const DIERef &die_ref) {
if (die_ref.unit_offset())
return GetUnitAtOffset(die_ref.section(), *die_ref.unit_offset());
return GetUnitContainingDIEOffset(die_ref.section(), die_ref.die_offset());
}

Expand Down
21 changes: 5 additions & 16 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
Expand Up @@ -226,12 +226,6 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
DWARFRangeList &ranges, int &decl_file, int &decl_line, int &decl_column,
int &call_file, int &call_line, int &call_column,
DWARFExpression *frame_base) const {
SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile();
if (dwo_symbol_file)
return GetDIENamesAndRanges(
dwo_symbol_file->GetCompileUnit(), name, mangled, ranges, decl_file,
decl_line, decl_column, call_file, call_line, call_column, frame_base);

dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
std::vector<DWARFDIE> dies;
Expand Down Expand Up @@ -611,16 +605,7 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &form_value,
dw_offset_t *end_attr_offset_ptr,
bool check_specification_or_abstract_origin) const {
SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile();
if (dwo_symbol_file && m_tag != DW_TAG_compile_unit &&
m_tag != DW_TAG_partial_unit)
return GetAttributeValue(dwo_symbol_file->GetCompileUnit(), attr,
form_value, end_attr_offset_ptr,
check_specification_or_abstract_origin);

auto abbrevDecl = GetAbbreviationDeclarationPtr(cu);

if (abbrevDecl) {
if (auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu)) {
uint32_t attr_idx = abbrevDecl->FindAttributeIndex(attr);

if (attr_idx != DW_INVALID_INDEX) {
Expand Down Expand Up @@ -665,6 +650,10 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
}
}

// If we're a unit DIE, also check the attributes of the dwo unit (if any).
if (GetParent())
return 0;
SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile();
if (!dwo_symbol_file)
return 0;

Expand Down
9 changes: 4 additions & 5 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
Expand Up @@ -7,22 +7,21 @@
//===----------------------------------------------------------------------===//

#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"

#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"

using namespace lldb_private;
using namespace lldb;

DWARFIndex::~DWARFIndex() = default;

void DWARFIndex::ProcessFunctionDIE(llvm::StringRef name, DIERef ref,
DWARFDebugInfo &info,
SymbolFileDWARF &dwarf,
const CompilerDeclContext &parent_decl_ctx,
uint32_t name_type_mask,
std::vector<DWARFDIE> &dies) {
DWARFDIE die = info.GetDIE(ref);
DWARFDIE die = dwarf.GetDIE(ref);
if (!die) {
ReportInvalidDIERef(ref, name);
return;
Expand Down
5 changes: 2 additions & 3 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
Expand Up @@ -13,7 +13,6 @@
#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
#include "Plugins/SymbolFile/DWARF/DWARFFormValue.h"

class DWARFDebugInfo;
class DWARFDeclContext;
class DWARFDIE;

Expand All @@ -40,7 +39,7 @@ class DWARFIndex {
virtual void GetTypes(ConstString name, DIEArray &offsets) = 0;
virtual void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) = 0;
virtual void GetNamespaces(ConstString name, DIEArray &offsets) = 0;
virtual void GetFunctions(ConstString name, DWARFDebugInfo &info,
virtual void GetFunctions(ConstString name, SymbolFileDWARF &dwarf,
const CompilerDeclContext &parent_decl_ctx,
uint32_t name_type_mask,
std::vector<DWARFDIE> &dies) = 0;
Expand All @@ -58,7 +57,7 @@ class DWARFIndex {
/// "parent_decl_ctx" and "name_type_mask", it is inserted into the "dies"
/// vector.
void ProcessFunctionDIE(llvm::StringRef name, DIERef ref,
DWARFDebugInfo &info,
SymbolFileDWARF &dwarf,
const CompilerDeclContext &parent_decl_ctx,
uint32_t name_type_mask, std::vector<DWARFDIE> &dies);
};
Expand Down
13 changes: 6 additions & 7 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
Expand Up @@ -363,7 +363,6 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
else if (gnu_ranges_base)
dwo_cu->SetRangesBase(*gnu_ranges_base);

dwo_cu->SetBaseObjOffset(GetOffset());
SetDwoStrOffsetsBase(dwo_cu);
}

Expand Down Expand Up @@ -419,10 +418,6 @@ void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) {
m_ranges_base = ranges_base;
}

void DWARFUnit::SetBaseObjOffset(dw_offset_t base_obj_offset) {
m_base_obj_offset = base_obj_offset;
}

void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) {
m_str_offsets_base = str_offsets_base;
}
Expand Down Expand Up @@ -480,6 +475,12 @@ DWARFUnit::GetDIE(dw_offset_t die_offset) {
return DWARFDIE(); // Not found
}

DWARFUnit &DWARFUnit::GetNonSkeletonUnit() {
if (SymbolFileDWARFDwo *dwo = GetDwoSymbolFile())
return *dwo->GetCompileUnit();
return *this;
}

uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) {
if (cu)
return cu->GetAddressByteSize();
Expand Down Expand Up @@ -719,8 +720,6 @@ SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const {
return m_dwo_symbol_file.get();
}

dw_offset_t DWARFUnit::GetBaseObjOffset() const { return m_base_obj_offset; }

const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() {
if (m_func_aranges_up == nullptr) {
m_func_aranges_up.reset(new DWARFDebugAranges());
Expand Down
8 changes: 2 additions & 6 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
Expand Up @@ -148,7 +148,6 @@ class DWARFUnit : public lldb_private::UserID {
dw_addr_t GetStrOffsetsBase() const { return m_str_offsets_base; }
void SetAddrBase(dw_addr_t addr_base);
void SetRangesBase(dw_addr_t ranges_base);
void SetBaseObjOffset(dw_offset_t base_obj_offset);
void SetStrOffsetsBase(dw_offset_t str_offsets_base);
virtual void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) = 0;

Expand All @@ -166,6 +165,8 @@ class DWARFUnit : public lldb_private::UserID {

DWARFDIE GetDIE(dw_offset_t die_offset);

DWARFUnit &GetNonSkeletonUnit();

static uint8_t GetAddressByteSize(const DWARFUnit *cu);

static uint8_t GetDefaultAddressSize();
Expand Down Expand Up @@ -203,8 +204,6 @@ class DWARFUnit : public lldb_private::UserID {

SymbolFileDWARFDwo *GetDwoSymbolFile() const;

dw_offset_t GetBaseObjOffset() const;

die_iterator_range dies() {
ExtractDIEsIfNeeded();
return die_iterator_range(m_die_array.begin(), m_die_array.end());
Expand Down Expand Up @@ -284,9 +283,6 @@ class DWARFUnit : public lldb_private::UserID {
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_ranges_base = 0; // Value of DW_AT_ranges_base
// If this is a dwo compile unit this is the offset of the base compile unit
// in the main object file
dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET;

/// Value of DW_AT_stmt_list.
dw_offset_t m_line_table_offset = DW_INVALID_OFFSET;
Expand Down
14 changes: 7 additions & 7 deletions lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
Expand Up @@ -64,10 +64,11 @@ DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) {
// GetDwoSymbolFile to call this automatically because of mutual recursion
// between this and DWARFDebugInfoEntry::GetAttributeValue.
cu->ExtractUnitDIEIfNeeded();
uint64_t die_bias = cu->GetDwoSymbolFile() ? 0 : *cu_offset;
cu = &cu->GetNonSkeletonUnit();

if (llvm::Optional<uint64_t> die_offset = entry.getDIEUnitOffset())
return DIERef(DIERef::Section::DebugInfo, *cu_offset, die_bias + *die_offset);
return DIERef(cu->GetSymbolFileDWARF().GetDwoNum(),
DIERef::Section::DebugInfo, cu->GetOffset() + *die_offset);

return llvm::None;
}
Expand Down Expand Up @@ -165,8 +166,7 @@ void DebugNamesDWARFIndex::GetCompleteObjCClass(ConstString class_name,
if (!ref)
continue;

DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo,
*ref->unit_offset());
DWARFUnit *cu = m_debug_info.GetUnit(*ref);
if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) {
incomplete_types.push_back(*ref);
continue;
Expand Down Expand Up @@ -222,12 +222,12 @@ void DebugNamesDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {
}

void DebugNamesDWARFIndex::GetFunctions(
ConstString name, DWARFDebugInfo &info,
ConstString name, SymbolFileDWARF &dwarf,
const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
std::vector<DWARFDIE> &dies) {

std::vector<DWARFDIE> v;
m_fallback.GetFunctions(name, info, parent_decl_ctx, name_type_mask, v);
m_fallback.GetFunctions(name, dwarf, parent_decl_ctx, name_type_mask, v);

for (const DebugNames::Entry &entry :
m_debug_names_up->equal_range(name.GetStringRef())) {
Expand All @@ -236,7 +236,7 @@ void DebugNamesDWARFIndex::GetFunctions(
continue;

if (llvm::Optional<DIERef> ref = ToDIERef(entry))
ProcessFunctionDIE(name.GetStringRef(), *ref, info, parent_decl_ctx,
ProcessFunctionDIE(name.GetStringRef(), *ref, dwarf, parent_decl_ctx,
name_type_mask, v);
}

Expand Down
Expand Up @@ -34,7 +34,7 @@ class DebugNamesDWARFIndex : public DWARFIndex {
void GetTypes(ConstString name, DIEArray &offsets) override;
void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override;
void GetNamespaces(ConstString name, DIEArray &offsets) override;
void GetFunctions(ConstString name, DWARFDebugInfo &info,
void GetFunctions(ConstString name, SymbolFileDWARF &dwarf,
const CompilerDeclContext &parent_decl_ctx,
uint32_t name_type_mask,
std::vector<DWARFDIE> &dies) override;
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
Expand Up @@ -61,7 +61,7 @@ class DWARFMappedHash {
DIEInfo(dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h);

explicit operator DIERef() const {
return DIERef(DIERef::Section::DebugInfo, llvm::None, die_offset);
return DIERef(llvm::None, DIERef::Section::DebugInfo, die_offset);
}
};

Expand Down

0 comments on commit 3b92698

Please sign in to comment.