DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
StringRef SOS, StringRef AOS, bool LE,
- const DWARFUnitSectionBase &UnitSection)
- : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {}
+ const DWARFUnitSectionBase &UnitSection,
+ const DWARFUnitIndex::Entry *Entry)
+ : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection,
+ Entry) {}
void dump(raw_ostream &OS);
+ static const DWARFSectionKind Section = DW_SECT_INFO;
// VTable anchor.
~DWARFCompileUnit() override;
};
DWARFUnitSection<DWARFCompileUnit> CUs;
std::vector<DWARFUnitSection<DWARFTypeUnit>> TUs;
+ std::unique_ptr<DWARFUnitIndex> CUIndex;
+ std::unique_ptr<DWARFUnitIndex> TUIndex;
std::unique_ptr<DWARFDebugAbbrev> Abbrev;
std::unique_ptr<DWARFDebugLoc> Loc;
std::unique_ptr<DWARFDebugAranges> Aranges;
return DWOCUs[index].get();
}
+ const DWARFUnitIndex &getCUIndex();
+ const DWARFUnitIndex &getTUIndex();
+
/// Get a pointer to the parsed DebugAbbrev object.
const DWARFDebugAbbrev *getDebugAbbrev();
DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
StringRef SOS, StringRef AOS, bool LE,
- const DWARFUnitSectionBase &UnitSection)
- : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {}
+ const DWARFUnitSectionBase &UnitSection,
+ const DWARFUnitIndex::Entry *Entry)
+ : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection,
+ Entry) {}
uint32_t getHeaderSize() const override {
return DWARFUnit::getHeaderSize() + 12;
}
void dump(raw_ostream &OS);
+ static const DWARFSectionKind Section = DW_SECT_TYPES;
+
protected:
bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override;
};
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
#include <vector>
namespace llvm {
virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0;
void parse(DWARFContext &C, const DWARFSection &Section);
- void parseDWO(DWARFContext &C, const DWARFSection &DWOSection);
+ void parseDWO(DWARFContext &C, const DWARFSection &DWOSection,
+ DWARFUnitIndex *Index = nullptr);
protected:
virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section,
~DWARFUnitSectionBase() = default;
};
+const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
+ DWARFSectionKind Kind);
+
/// Concrete instance of DWARFUnitSection, specialized for one Unit type.
template<typename UnitType>
class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
StringRef SOS, StringRef AOS, bool LE) override {
if (Parsed)
return;
+ const auto &Index = getDWARFUnitIndex(Context, UnitType::Section);
DataExtractor Data(Section.Data, LE, 0);
uint32_t Offset = 0;
while (Data.isValidOffset(Offset)) {
- auto U = llvm::make_unique<UnitType>(Context, Section, DA, RS, SS, SOS,
- AOS, LE, *this);
+ auto U =
+ llvm::make_unique<UnitType>(Context, Section, DA, RS, SS, SOS, AOS,
+ LE, *this, Index.getFromOffset(Offset));
if (!U->extract(Data, &Offset))
break;
this->push_back(std::move(U));
};
std::unique_ptr<DWOHolder> DWO;
+ const DWARFUnitIndex::Entry *IndexEntry;
+
protected:
virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr);
/// Size in bytes of the unit header.
DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
StringRef SOS, StringRef AOS, bool LE,
- const DWARFUnitSectionBase &UnitSection);
+ const DWARFUnitSectionBase &UnitSection,
+ const DWARFUnitIndex::Entry *IndexEntry = nullptr);
virtual ~DWARFUnit();
namespace llvm {
+enum DWARFSectionKind {
+ DW_SECT_INFO = 1,
+ DW_SECT_TYPES,
+ DW_SECT_ABBREV,
+ DW_SECT_LINE,
+ DW_SECT_LOC,
+ DW_SECT_STR_OFFSETS,
+ DW_SECT_MACINFO,
+ DW_SECT_MACRO,
+};
+
class DWARFUnitIndex {
struct Header {
uint32_t Version;
void dump(raw_ostream &OS) const;
};
- struct HashRow {
+public:
+ class Entry {
+ const DWARFUnitIndex *Index;
uint64_t Signature;
struct SectionContribution {
uint32_t Offset;
- uint32_t Size;
+ uint32_t Length;
};
std::unique_ptr<SectionContribution[]> Contributions;
- };
+ friend class DWARFUnitIndex;
- enum DwarfSection {
- DW_SECT_INFO = 1,
- DW_SECT_TYPES,
- DW_SECT_ABBREV,
- DW_SECT_LINE,
- DW_SECT_LOC,
- DW_SECT_STR_OFFSETS,
- DW_SECT_MACINFO,
- DW_SECT_MACRO,
+ public:
+ const SectionContribution *getOffset(DWARFSectionKind Sec) const;
+ const SectionContribution *getOffset() const;
};
struct Header Header;
- std::unique_ptr<DwarfSection[]> ColumnKinds;
- std::unique_ptr<HashRow[]> Rows;
+ int InfoColumn = -1;
+ std::unique_ptr<DWARFSectionKind[]> ColumnKinds;
+ std::unique_ptr<Entry[]> Rows;
- static StringRef getColumnHeader(DwarfSection DS);
+ static StringRef getColumnHeader(DWARFSectionKind DS);
public:
bool parse(DataExtractor IndexData);
void dump(raw_ostream &OS) const;
+ const Entry *getFromOffset(uint32_t Offset) const;
};
}
getStringSection(), isLittleEndian());
}
+const DWARFUnitIndex &DWARFContext::getCUIndex() {
+ if (CUIndex)
+ return *CUIndex;
+
+ DataExtractor CUIndexData(getCUIndexSection(), isLittleEndian(), 0);
+
+ CUIndex = llvm::make_unique<DWARFUnitIndex>();
+ CUIndex->parse(CUIndexData);
+ return *CUIndex;
+}
+
+const DWARFUnitIndex &DWARFContext::getTUIndex() {
+ if (TUIndex)
+ return *TUIndex;
+
+ DataExtractor TUIndexData(getTUIndexSection(), isLittleEndian(), 0);
+
+ TUIndex = llvm::make_unique<DWARFUnitIndex>();
+ TUIndex->parse(TUIndexData);
+ return *TUIndex;
+}
+
const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
if (Abbrev)
return Abbrev.get();
#include "llvm/Support/Path.h"
#include <cstdio>
-using namespace llvm;
+namespace llvm {
using namespace dwarf;
void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) {
}
void DWARFUnitSectionBase::parseDWO(DWARFContext &C,
- const DWARFSection &DWOSection) {
+ const DWARFSection &DWOSection,
+ DWARFUnitIndex *Index) {
parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), C.getRangeDWOSection(),
C.getStringDWOSection(), C.getStringOffsetDWOSection(),
C.getAddrSection(), C.isLittleEndian());
DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
StringRef SOS, StringRef AOS, bool LE,
- const DWARFUnitSectionBase &UnitSection)
+ const DWARFUnitSectionBase &UnitSection,
+ const DWARFUnitIndex::Entry *IndexEntry)
: Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS),
StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS),
- isLittleEndian(LE), UnitSection(UnitSection) {
+ isLittleEndian(LE), UnitSection(UnitSection), IndexEntry(IndexEntry) {
clear();
}
Length = debug_info.getU32(offset_ptr);
Version = debug_info.getU16(offset_ptr);
uint64_t AbbrOffset = debug_info.getU32(offset_ptr);
+ if (IndexEntry) {
+ if (AbbrOffset)
+ return false;
+ auto *UnitContrib = IndexEntry->getOffset();
+ if (!UnitContrib || UnitContrib->Length != (Length + 4))
+ return false;
+ auto *AbbrEntry = IndexEntry->getOffset(DW_SECT_ABBREV);
+ if (!AbbrEntry)
+ return false;
+ AbbrOffset = AbbrEntry->Offset;
+ }
AddrSize = debug_info.getU8(offset_ptr);
bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
return DWARFDebugInfoEntryInlinedChain();
return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address);
}
+
+const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
+ DWARFSectionKind Kind) {
+ if (Kind == DW_SECT_INFO)
+ return Context.getCUIndex();
+ assert(Kind == DW_SECT_TYPES);
+ return Context.getTUIndex();
+}
+}
(2 * Header.NumUnits + 1) * 4 * Header.NumColumns))
return false;
- Rows = llvm::make_unique<HashRow[]>(Header.NumBuckets);
+ Rows = llvm::make_unique<Entry[]>(Header.NumBuckets);
auto Contribs =
- llvm::make_unique<HashRow::SectionContribution *[]>(Header.NumUnits);
- ColumnKinds = llvm::make_unique<DwarfSection[]>(Header.NumColumns);
+ llvm::make_unique<Entry::SectionContribution *[]>(Header.NumUnits);
+ ColumnKinds = llvm::make_unique<DWARFSectionKind[]>(Header.NumColumns);
// Read Hash Table of Signatures
for (unsigned i = 0; i != Header.NumBuckets; ++i)
auto Index = IndexData.getU32(&Offset);
if (!Index)
continue;
+ Rows[i].Index = this;
Rows[i].Contributions =
- llvm::make_unique<HashRow::SectionContribution[]>(Header.NumColumns);
+ llvm::make_unique<Entry::SectionContribution[]>(Header.NumColumns);
Contribs[Index - 1] = Rows[i].Contributions.get();
}
// Read the Column Headers
- for (unsigned i = 0; i != Header.NumColumns; ++i)
- ColumnKinds[i] = static_cast<DwarfSection>(IndexData.getU32(&Offset));
+ for (unsigned i = 0; i != Header.NumColumns; ++i) {
+ ColumnKinds[i] = static_cast<DWARFSectionKind>(IndexData.getU32(&Offset));
+ if (ColumnKinds[i] == DW_SECT_INFO || ColumnKinds[i] == DW_SECT_TYPES) {
+ if (InfoColumn != -1)
+ return false;
+ InfoColumn = i;
+ }
+ }
+
+ if (InfoColumn == -1)
+ return false;
// Read Table of Section Offsets
for (unsigned i = 0; i != Header.NumUnits; ++i) {
auto *Contrib = Contribs[i];
- for (unsigned i = 0; i != Header.NumColumns; ++i) {
+ for (unsigned i = 0; i != Header.NumColumns; ++i)
Contrib[i].Offset = IndexData.getU32(&Offset);
- }
}
// Read Table of Section Sizes
for (unsigned i = 0; i != Header.NumUnits; ++i) {
auto *Contrib = Contribs[i];
- for (unsigned i = 0; i != Header.NumColumns; ++i) {
- Contrib[i].Size = IndexData.getU32(&Offset);
- }
+ for (unsigned i = 0; i != Header.NumColumns; ++i)
+ Contrib[i].Length = IndexData.getU32(&Offset);
}
return true;
}
-StringRef DWARFUnitIndex::getColumnHeader(DwarfSection DS) {
+StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) {
#define CASE(DS) \
case DW_SECT_##DS: \
return #DS;
CASE(MACINFO);
CASE(MACRO);
}
- llvm_unreachable("unknown DwarfSection");
+ llvm_unreachable("unknown DWARFSectionKind");
}
void DWARFUnitIndex::dump(raw_ostream &OS) const {
OS << format("%5u 0x%016" PRIx64 " ", i, Row.Signature);
for (unsigned i = 0; i != Header.NumColumns; ++i) {
auto &Contrib = Contribs[i];
- OS << format("[0x%08u, 0x%08u) ", Contrib.Offset,
- Contrib.Offset + Contrib.Size);
+ OS << format("[0x%08x, 0x%08x) ", Contrib.Offset,
+ Contrib.Offset + Contrib.Length);
}
OS << '\n';
}
}
}
+
+const DWARFUnitIndex::Entry::SectionContribution *
+DWARFUnitIndex::Entry::getOffset(DWARFSectionKind Sec) const {
+ uint32_t i = 0;
+ for (; i != Index->Header.NumColumns; ++i)
+ if (Index->ColumnKinds[i] == Sec)
+ return &Contributions[i];
+ return nullptr;
+}
+const DWARFUnitIndex::Entry::SectionContribution *
+DWARFUnitIndex::Entry::getOffset() const {
+ return &Contributions[Index->InfoColumn];
+}
+
+const DWARFUnitIndex::Entry *
+DWARFUnitIndex::getFromOffset(uint32_t Offset) const {
+ for (uint32_t i = 0; i != Header.NumBuckets; ++i)
+ if (const auto &Contribs = Rows[i].Contributions)
+ if (Contribs[InfoColumn].Offset == Offset)
+ return &Rows[i];
+ return nullptr;
+}
}
; foo a;
; b.cpp:
; struct bar { };
-; bar b;
+; bar b() {
+; }
+
+; CHECK: .debug_info.dwo contents:
+; CHECK: Compile Unit
+
+; Verify that the second CU uses the index for its abbrev offset
+; CHECK: Compile Unit
+; CHECK-SAME: abbr_offset = 0x0043
+; CHECK: DW_TAG_compile_unit
+; CHECK-NOT: DW_TAG
+; FIXME: Implement str_offsets support so we find b.cpp here \/
+; CHECK: DW_AT_name {{.*}} "a.cpp"
+
+; Verify that abbreviations are decoded using the abbrev offset in the index
+; CHECK: DW_TAG_subprogram
+; CHECK: DW_TAG_structure_type
; CHECK: .debug_cu_index contents:
; CHECK-NEXT: version = 2 slots = 16
-; CHECK: Index Signature INFO ABBREV LINE STR_OFFSETS
+; CHECK: Index Signature INFO ABBREV LINE STR_OFFSETS
; CHECK-NEXT: ----- ------------------ ------------------------ ------------------------ ------------------------ ------------------------
-; CHECK-NEXT: 8 0x03c30756e2d45008 [0x00000000, 0x00000045) [0x00000000, 0x00000067) [0x00000000, 0x00000026) [0x00000000, 0x00000016)
-; CHECK-NEXT: 12 0x9aeb3a61ed48510c [0x00000045, 0x00000090) [0x00000067, 0x00000134) [0x00000026, 0x00000052) [0x00000016, 0x00000032)
+; CHECK-NEXT: 2 0xfef104c25502f092 [0x0000002d, 0x0000005f) [0x00000043, 0x0000008e) [0x0000001a, 0x00000034) [0x00000010, 0x00000024)
+; CHECK-NEXT: 8 0x03c30756e2d45008 [0x00000000, 0x0000002d) [0x00000000, 0x00000043) [0x00000000, 0x0000001a) [0x00000000, 0x00000010)
; CHECK: .debug_tu_index contents:
; CHECK-NEXT: version = 2 slots = 16
; CHECK: Index Signature TYPES ABBREV LINE STR_OFFSETS
; CHECK-NEXT: ----- ------------------ ------------------------ ------------------------ ------------------------ ------------------------
-; CHECK-NEXT: 8 0x1d02f3be30cc5688 [0x00000036, 0x00000072) [0x00000067, 0x00000134) [0x00000026, 0x00000052) [0x00000016, 0x00000032)
-; CHECK-NEXT: 12 0x3875c0e21cda63fc [0x00000000, 0x00000036) [0x00000000, 0x00000067) [0x00000000, 0x00000026) [0x00000000, 0x00000016)
+; CHECK-NEXT: 8 0x1d02f3be30cc5688 [0x00000024, 0x00000048) [0x00000043, 0x0000008e) [0x0000001a, 0x00000034) [0x00000010, 0x00000024)
+; CHECK-NEXT: 12 0x3875c0e21cda63fc [0x00000000, 0x00000024) [0x00000000, 0x00000043) [0x00000000, 0x0000001a) [0x00000000, 0x00000010)
-; TODO: use the index section offset info to correctly dump debug_info
+; TODO: use the index section offset info to correctly dump strings in debug info
+; TODO: use the index section offset info to correctly dump file names in debug info