Skip to content

[lldb] Switch to llvm::DWARFUnitHeader #89808

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class DWARFCompileUnit : public DWARFUnit {

private:
DWARFCompileUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
const DWARFUnitHeader &header,
const llvm::DWARFUnitHeader &header,
const llvm::DWARFAbbreviationDeclarationSet &abbrevs,
DIERef::Section section, bool is_dwo)
: DWARFUnit(dwarf, uid, header, abbrevs, section, is_dwo) {}
Expand Down
6 changes: 3 additions & 3 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ class DWARFTypeUnit : public DWARFUnit {

void Dump(Stream *s) const override;

uint64_t GetTypeHash() { return m_header.GetTypeHash(); }
uint64_t GetTypeHash() { return m_header.getTypeHash(); }

dw_offset_t GetTypeOffset() { return GetOffset() + m_header.GetTypeOffset(); }
dw_offset_t GetTypeOffset() { return GetOffset() + m_header.getTypeOffset(); }

static bool classof(const DWARFUnit *unit) { return unit->IsTypeUnit(); }

private:
DWARFTypeUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
const DWARFUnitHeader &header,
const llvm::DWARFUnitHeader &header,
const llvm::DWARFAbbreviationDeclarationSet &abbrevs,
DIERef::Section section, bool is_dwo)
: DWARFUnit(dwarf, uid, header, abbrevs, section, is_dwo) {}
Expand Down
137 changes: 34 additions & 103 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ using namespace lldb_private::plugin::dwarf;
extern int g_verbose;

DWARFUnit::DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
const DWARFUnitHeader &header,
const llvm::DWARFUnitHeader &header,
const llvm::DWARFAbbreviationDeclarationSet &abbrevs,
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_has_parsed_non_skeleton_unit(false), m_dwo_id(header.GetDWOId()) {}
m_has_parsed_non_skeleton_unit(false), m_dwo_id(header.getDWOId()) {}

DWARFUnit::~DWARFUnit() = default;

Expand Down Expand Up @@ -345,7 +345,7 @@ void DWARFUnit::ExtractDIEsRWLocked() {
void DWARFUnit::SetDwoStrOffsetsBase() {
lldb::offset_t baseOffset = 0;

if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) {
if (const llvm::DWARFUnitIndex::Entry *entry = m_header.getIndexEntry()) {
if (const auto *contribution =
entry->getContribution(llvm::DW_SECT_STR_OFFSETS))
baseOffset = contribution->getOffset();
Expand Down Expand Up @@ -489,7 +489,7 @@ ParseListTableHeader(const llvm::DWARFDataExtractor &data, uint64_t offset,

void DWARFUnit::SetLoclistsBase(dw_addr_t loclists_base) {
uint64_t offset = 0;
if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) {
if (const llvm::DWARFUnitIndex::Entry *entry = m_header.getIndexEntry()) {
const auto *contribution = entry->getContribution(llvm::DW_SECT_LOCLISTS);
if (!contribution) {
GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
Expand Down Expand Up @@ -533,7 +533,7 @@ DWARFDataExtractor DWARFUnit::GetLocationData() const {
DWARFContext &Ctx = GetSymbolFileDWARF().GetDWARFContext();
const DWARFDataExtractor &data =
GetVersion() >= 5 ? Ctx.getOrLoadLocListsData() : Ctx.getOrLoadLocData();
if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) {
if (const llvm::DWARFUnitIndex::Entry *entry = m_header.getIndexEntry()) {
if (const auto *contribution = entry->getContribution(
GetVersion() >= 5 ? llvm::DW_SECT_LOCLISTS : llvm::DW_SECT_EXT_LOC))
return DWARFDataExtractor(data, contribution->getOffset(),
Expand All @@ -546,7 +546,7 @@ DWARFDataExtractor DWARFUnit::GetLocationData() const {
DWARFDataExtractor DWARFUnit::GetRnglistData() const {
DWARFContext &Ctx = GetSymbolFileDWARF().GetDWARFContext();
const DWARFDataExtractor &data = Ctx.getOrLoadRngListsData();
if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) {
if (const llvm::DWARFUnitIndex::Entry *entry = m_header.getIndexEntry()) {
if (const auto *contribution =
entry->getContribution(llvm::DW_SECT_RNGLISTS))
return DWARFDataExtractor(data, contribution->getOffset(),
Expand Down Expand Up @@ -924,111 +924,42 @@ const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() {
return *m_func_aranges_up;
}

llvm::Error DWARFUnitHeader::ApplyIndexEntry(
const llvm::DWARFUnitIndex::Entry *index_entry) {
// We should only be calling this function when the index entry is not set and
// we have a valid one to set it to.
assert(index_entry);
assert(!m_index_entry);

if (m_abbr_offset)
return llvm::createStringError(
llvm::inconvertibleErrorCode(),
"Package unit with a non-zero abbreviation offset");

auto *unit_contrib = index_entry->getContribution();
if (!unit_contrib || unit_contrib->getLength32() != m_length + 4)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"Inconsistent DWARF package unit index");

auto *abbr_entry = index_entry->getContribution(llvm::DW_SECT_ABBREV);
if (!abbr_entry)
return llvm::createStringError(
llvm::inconvertibleErrorCode(),
"DWARF package index missing abbreviation column");

m_abbr_offset = abbr_entry->getOffset();
m_index_entry = index_entry;
return llvm::Error::success();
}

llvm::Expected<DWARFUnitHeader>
DWARFUnitHeader::extract(const DWARFDataExtractor &data,
DIERef::Section section, DWARFContext &context,
lldb::offset_t *offset_ptr) {
DWARFUnitHeader header;
header.m_offset = *offset_ptr;
header.m_length = data.GetDWARFInitialLength(offset_ptr);
header.m_version = data.GetU16(offset_ptr);
if (header.m_version == 5) {
header.m_unit_type = data.GetU8(offset_ptr);
header.m_addr_size = data.GetU8(offset_ptr);
header.m_abbr_offset = data.GetDWARFOffset(offset_ptr);
if (header.m_unit_type == llvm::dwarf::DW_UT_skeleton ||
header.m_unit_type == llvm::dwarf::DW_UT_split_compile)
header.m_dwo_id = data.GetU64(offset_ptr);
} else {
header.m_abbr_offset = data.GetDWARFOffset(offset_ptr);
header.m_addr_size = data.GetU8(offset_ptr);
header.m_unit_type =
section == DIERef::Section::DebugTypes ? DW_UT_type : DW_UT_compile;
}

if (header.IsTypeUnit()) {
header.m_type_hash = data.GetU64(offset_ptr);
header.m_type_offset = data.GetDWARFOffset(offset_ptr);
}

bool length_OK = data.ValidOffset(header.GetNextUnitOffset() - 1);
bool version_OK = SymbolFileDWARF::SupportedVersion(header.m_version);
bool addr_size_OK = (header.m_addr_size == 2) || (header.m_addr_size == 4) ||
(header.m_addr_size == 8);
bool type_offset_OK =
!header.IsTypeUnit() || (header.m_type_offset <= header.GetLength());

if (!length_OK)
return llvm::make_error<llvm::object::GenericBinaryError>(
"Invalid unit length");
if (!version_OK)
return llvm::make_error<llvm::object::GenericBinaryError>(
"Unsupported unit version");
if (!addr_size_OK)
return llvm::make_error<llvm::object::GenericBinaryError>(
"Invalid unit address size");
if (!type_offset_OK)
return llvm::make_error<llvm::object::GenericBinaryError>(
"Type offset out of range");

return header;
}

llvm::Expected<DWARFUnitSP>
DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid,
const DWARFDataExtractor &debug_info,
DIERef::Section section, lldb::offset_t *offset_ptr) {
assert(debug_info.ValidOffset(*offset_ptr));

DWARFContext &context = dwarf.GetDWARFContext();
auto expected_header =
DWARFUnitHeader::extract(debug_info, section, context, offset_ptr);
if (!expected_header)
return expected_header.takeError();

// FIXME: Either properly map between DIERef::Section and
// llvm::DWARFSectionKind or switch to llvm's definition entirely.
llvm::DWARFSectionKind section_kind_llvm =
section == DIERef::Section::DebugInfo
? llvm::DWARFSectionKind::DW_SECT_INFO
: llvm::DWARFSectionKind::DW_SECT_EXT_TYPES;

llvm::DWARFDataExtractor debug_info_llvm = debug_info.GetAsLLVMDWARF();
llvm::DWARFUnitHeader header;
if (llvm::Error extract_err = header.extract(
context.GetAsLLVM(), debug_info_llvm, offset_ptr, section_kind_llvm))
return std::move(extract_err);

if (context.isDwo()) {
const llvm::DWARFUnitIndex::Entry *entry = nullptr;
const llvm::DWARFUnitIndex &index = expected_header->IsTypeUnit()
const llvm::DWARFUnitIndex &index = header.isTypeUnit()
? context.GetAsLLVM().getTUIndex()
: context.GetAsLLVM().getCUIndex();
if (index) {
if (expected_header->IsTypeUnit())
entry = index.getFromHash(expected_header->GetTypeHash());
else if (auto dwo_id = expected_header->GetDWOId())
if (header.isTypeUnit())
entry = index.getFromHash(header.getTypeHash());
else if (auto dwo_id = header.getDWOId())
entry = index.getFromHash(*dwo_id);
}
if (!entry)
entry = index.getFromOffset(expected_header->GetOffset());
entry = index.getFromOffset(header.getOffset());
if (entry)
if (llvm::Error err = expected_header->ApplyIndexEntry(entry))
if (llvm::Error err = header.applyIndexEntry(entry))
return std::move(err);
}

Expand All @@ -1039,13 +970,13 @@ DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid,

bool abbr_offset_OK =
dwarf.GetDWARFContext().getOrLoadAbbrevData().ValidOffset(
expected_header->GetAbbrOffset());
header.getAbbrOffset());
if (!abbr_offset_OK)
return llvm::make_error<llvm::object::GenericBinaryError>(
"Abbreviation offset for unit is not valid");

llvm::Expected<const llvm::DWARFAbbreviationDeclarationSet *> abbrevs_or_err =
abbr->getAbbreviationDeclarationSet(expected_header->GetAbbrOffset());
abbr->getAbbreviationDeclarationSet(header.getAbbrOffset());
if (!abbrevs_or_err)
return abbrevs_or_err.takeError();

Expand All @@ -1055,11 +986,11 @@ DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid,
"No abbrev exists at the specified offset.");

bool is_dwo = dwarf.GetDWARFContext().isDwo();
if (expected_header->IsTypeUnit())
return DWARFUnitSP(new DWARFTypeUnit(dwarf, uid, *expected_header, *abbrevs,
section, is_dwo));
return DWARFUnitSP(new DWARFCompileUnit(dwarf, uid, *expected_header,
*abbrevs, section, is_dwo));
if (header.isTypeUnit())
return DWARFUnitSP(
new DWARFTypeUnit(dwarf, uid, header, *abbrevs, section, is_dwo));
return DWARFUnitSP(
new DWARFCompileUnit(dwarf, uid, header, *abbrevs, section, is_dwo));
}

const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const {
Expand All @@ -1069,7 +1000,7 @@ const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const {
}

uint32_t DWARFUnit::GetHeaderByteSize() const {
switch (m_header.GetUnitType()) {
switch (m_header.getUnitType()) {
case llvm::dwarf::DW_UT_compile:
case llvm::dwarf::DW_UT_partial:
return GetVersion() < 5 ? 11 : 12;
Expand Down Expand Up @@ -1106,7 +1037,7 @@ DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) {
llvm::DWARFDataExtractor data = GetRnglistData().GetAsLLVMDWARF();

// As DW_AT_rnglists_base may be missing we need to call setAddressSize.
data.setAddressSize(m_header.GetAddressByteSize());
data.setAddressSize(m_header.getAddressByteSize());
auto range_list_or_error = GetRnglistTable()->findList(data, offset);
if (!range_list_or_error)
return range_list_or_error.takeError();
Expand Down
68 changes: 10 additions & 58 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,54 +38,6 @@ enum DWARFProducer {
eProducerOther
};

/// Base class describing the header of any kind of "unit." Some information
/// is specific to certain unit types. We separate this class out so we can
/// parse the header before deciding what specific kind of unit to construct.
class DWARFUnitHeader {
dw_offset_t m_offset = 0;
dw_offset_t m_length = 0;
uint16_t m_version = 0;
dw_offset_t m_abbr_offset = 0;

const llvm::DWARFUnitIndex::Entry *m_index_entry = nullptr;

uint8_t m_unit_type = 0;
uint8_t m_addr_size = 0;

uint64_t m_type_hash = 0;
uint32_t m_type_offset = 0;

std::optional<uint64_t> m_dwo_id;

DWARFUnitHeader() = default;

public:
dw_offset_t GetOffset() const { return m_offset; }
uint16_t GetVersion() const { return m_version; }
uint16_t GetAddressByteSize() const { return m_addr_size; }
dw_offset_t GetLength() const { return m_length; }
dw_offset_t GetAbbrOffset() const { return m_abbr_offset; }
uint8_t GetUnitType() const { return m_unit_type; }
const llvm::DWARFUnitIndex::Entry *GetIndexEntry() const {
return m_index_entry;
}
uint64_t GetTypeHash() const { return m_type_hash; }
dw_offset_t GetTypeOffset() const { return m_type_offset; }
std::optional<uint64_t> GetDWOId() const { return m_dwo_id; }
bool IsTypeUnit() const {
return m_unit_type == llvm::dwarf::DW_UT_type ||
m_unit_type == llvm::dwarf::DW_UT_split_type;
}
dw_offset_t GetNextUnitOffset() const { return m_offset + m_length + 4; }

llvm::Error ApplyIndexEntry(const llvm::DWARFUnitIndex::Entry *index_entry);

static llvm::Expected<DWARFUnitHeader> extract(const DWARFDataExtractor &data,
DIERef::Section section,
DWARFContext &dwarf_context,
lldb::offset_t *offset_ptr);
};

class DWARFUnit : public UserID {
using die_iterator_range =
llvm::iterator_range<DWARFDebugInfoEntry::collection::iterator>;
Expand All @@ -105,7 +57,7 @@ class DWARFUnit : public UserID {
/// the DWO ID in the compile unit header and we sometimes only want to access
/// this cheap value without causing the more expensive attribute fetches that
/// GetDWOId() uses.
std::optional<uint64_t> GetHeaderDWOId() { return m_header.GetDWOId(); }
std::optional<uint64_t> GetHeaderDWOId() { return m_header.getDWOId(); }
void ExtractUnitDIEIfNeeded();
void ExtractUnitDIENoDwoIfNeeded();
void ExtractDIEsIfNeeded();
Expand Down Expand Up @@ -143,7 +95,7 @@ class DWARFUnit : public UserID {
uint32_t GetHeaderByteSize() const;

// Offset of the initial length field.
dw_offset_t GetOffset() const { return m_header.GetOffset(); }
dw_offset_t GetOffset() const { return m_header.getOffset(); }
/// Get the size in bytes of the length field in the header.
///
/// In DWARF32 this is just 4 bytes
Expand All @@ -159,15 +111,15 @@ class DWARFUnit : public UserID {
dw_offset_t GetFirstDIEOffset() const {
return GetOffset() + GetHeaderByteSize();
}
dw_offset_t GetNextUnitOffset() const { return m_header.GetNextUnitOffset(); }
dw_offset_t GetNextUnitOffset() const { return m_header.getNextUnitOffset(); }
// Size of the CU data (without initial length and without header).
size_t GetDebugInfoSize() const;
// Size of the CU data incl. header but without initial length.
dw_offset_t GetLength() const { return m_header.GetLength(); }
uint16_t GetVersion() const { return m_header.GetVersion(); }
dw_offset_t GetLength() const { return m_header.getLength(); }
uint16_t GetVersion() const { return m_header.getVersion(); }
const llvm::DWARFAbbreviationDeclarationSet *GetAbbreviations() const;
dw_offset_t GetAbbrevOffset() const;
uint8_t GetAddressByteSize() const { return m_header.GetAddressByteSize(); }
uint8_t GetAddressByteSize() const { return m_header.getAddressByteSize(); }
dw_addr_t GetAddrBase() const { return m_addr_base.value_or(0); }
dw_addr_t GetBaseAddress() const { return m_base_addr; }
dw_offset_t GetLineTableOffset();
Expand Down Expand Up @@ -250,8 +202,8 @@ class DWARFUnit : public UserID {

DIERef::Section GetDebugSection() const { return m_section; }

uint8_t GetUnitType() const { return m_header.GetUnitType(); }
bool IsTypeUnit() const { return m_header.IsTypeUnit(); }
uint8_t GetUnitType() const { return m_header.getUnitType(); }
bool IsTypeUnit() const { return m_header.isTypeUnit(); }
/// Note that this check only works for DWARF5+.
bool IsSkeletonUnit() const {
return GetUnitType() == llvm::dwarf::DW_UT_skeleton;
Expand Down Expand Up @@ -320,7 +272,7 @@ class DWARFUnit : public UserID {

protected:
DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
const DWARFUnitHeader &header,
const llvm::DWARFUnitHeader &header,
const llvm::DWARFAbbreviationDeclarationSet &abbrevs,
DIERef::Section section, bool is_dwo);

Expand Down Expand Up @@ -352,7 +304,7 @@ class DWARFUnit : public UserID {

SymbolFileDWARF &m_dwarf;
std::shared_ptr<DWARFUnit> m_dwo;
DWARFUnitHeader m_header;
llvm::DWARFUnitHeader m_header;
const llvm::DWARFAbbreviationDeclarationSet *m_abbrevs = nullptr;
lldb_private::CompileUnit *m_lldb_cu = nullptr;
// If this is a DWO file, we have a backlink to our skeleton compile unit.
Expand Down
Loading