Skip to content

Commit

Permalink
[llvm-dwp] Adding support for v5 index writing
Browse files Browse the repository at this point in the history
This patch adds general support for DWARFv5 index writing.
In particular, this means only allowing inputs with one version,
either DWARFv5 or DWARFv4.

This patch adds the .debug_macro section as an example,
but the DWARFv5 type support and loc and rangelists are still
missing (and upcoming).

Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D102315
  • Loading branch information
ktran authored and dwblaikie committed Jun 2, 2021
1 parent fa51c5a commit 6e2d304
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 53 deletions.
55 changes: 55 additions & 0 deletions llvm/test/tools/llvm-dwp/X86/debug_macro_v5.s
@@ -0,0 +1,55 @@
# This test checks the support for writing macro sections and their index (v5).

# RUN: llvm-mc -triple x86_64-unknown-linux --filetype=obj --split-dwarf-file=%t.dwo -dwarf-version=5 %s -o %t.o
# RUN: llvm-dwp %t.dwo -o %t.dwp 2>&1
# RUN: llvm-dwarfdump -debug-macro -debug-cu-index %t.dwp | FileCheck %s

# CHECK-DAG: .debug_macro.dwo contents:
# CHECK: macro header: version = 0x0005, flags = 0x00, format = DWARF32
# CHECK-NEXT: DW_MACRO_start_file - lineno: 0 filenum: 0
# CHECK-NEXT: DW_MACRO_define_strx - lineno: 1 macro: x 5
# CHECK-NEXT: DW_MACRO_end_file

# CHECK-DAG: .debug_cu_index contents:
# CHECK-NEXT: version = 5, units = 1, slots = 2
# CHECK: Index Signature INFO ABBREV STR_OFFSETS MACRO
# CHECK: 1 0x0000000000000000 [0x00000000, 0x00000019) [0x00000000, 0x00000008) [0x00000000, 0x0000000c) [0x00000000, 0x0000000b)

.section .debug_info.dwo,"e",@progbits
.long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
.Ldebug_info_dwo_start0:
.short 5 # DWARF version number
.byte 5 # DWARF Unit Type (DW_UT_split_compile)
.byte 8 # Address Size (in bytes)
.long 0 # Offset Into Abbrev. Section
.quad 0
.byte 1 # Abbrev [1] 0x14:0x5 DW_TAG_compile_unit
.long 0 # DW_AT_macros
.Ldebug_info_dwo_end0:
.section .debug_macro.dwo,"e",@progbits
.short 5 # Macro information version
.byte 0 # Flags: 32 bit
.byte 3 # DW_MACRO_start_file
.byte 0 # Line Number
.byte 0 # File Number
.byte 11 # DW_MACRO_define_strx
.byte 1 # Line Number
.byte 0 # Macro String
.byte 4 # DW_MACRO_end_file
.byte 0 # End Of Macro List Mark
.section .debug_abbrev.dwo,"e",@progbits
.byte 1 # Abbreviation Code
.byte 17 # DW_TAG_compile_unit
.byte 0 # DW_CHILDREN_no
.byte 121 # DW_AT_macros
.byte 23 # DW_FORM_sec_offset
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 0 # EOM(3)
.section .debug_str.dwo,"eMS",@progbits,1
.asciz "x 5" # string offset=0
.section .debug_str_offsets.dwo,"e",@progbits
.long 8 # Length of String Offsets Set
.short 5
.short 0
.long 0
@@ -1,19 +1,20 @@
# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.dwp
# RUN: not llvm-dwp %t.dwp -o %t 2>&1 | FileCheck %s

# CHECK: error: unsupported cu_index version: 5 (only version 2 is supported)
# CHECK: error: incompatible cu_index versions, found 2 and expecting 5
.section .debug_info.dwo, "e", @progbits
.long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
.Ldebug_info_dwo_start0:
.short 5 # DWARF version number
.byte 5 # DWARF Unit type
.byte 5 # DWARF Unit type (DW_UT_split_compile)
.byte 8 # Address Size (in bytes)
.long 0 # Offset Into Abbrev. Section
.quad -346972125991005518
.byte 0 # Abbrev [9] 0xb:0x37 DW_TAG_compile_unit
.Ldebug_info_dwo_end0:
.section .debug_cu_index, "", @progbits
## Header:
.short 5 # Version
.short 2 # Version
.space 2 # Padding
.long 2 # Section count
.long 1 # Unit count
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/tools/llvm-dwp/X86/info-v5.s
Expand Up @@ -9,7 +9,7 @@
#CHECK: 0x00000000: Compile Unit: length = 0x00000050, format = DWARF32, version = 0x0005, unit_type = DW_UT_split_compile, abbr_offset = 0x0000, addr_size = 0x08, DWO_id = [[DWOID:.*]] (next unit at 0x00000054)

# CHECK-DAG: .debug_cu_index contents:
# CHECK: version = 2, units = 1, slots = 2
# CHECK: version = 5, units = 1, slots = 2
# CHECK: Index Signature INFO ABBREV
# CHECK: 1 [[DWOID]] [0x00000000, 0x00000054) [0x00000000, 0x0000002a)

Expand Down
Expand Up @@ -5,7 +5,7 @@
## of version 2 and a TU index of version 5. A valid TU is not required, but
## the .debug_types.dwo section should not be empty.

# CHECK: error: unsupported tu_index version: 5 (only version 2 is supported)
# CHECK: error: expected index version 2, but got: 5

.section .debug_abbrev.dwo, "e", @progbits
.LAbbrevBegin:
Expand Down
126 changes: 78 additions & 48 deletions llvm/tools/llvm-dwp/llvm-dwp.cpp
Expand Up @@ -174,7 +174,7 @@ static void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
MCSection *StrOffsetSection,
StringRef CurStrSection,
StringRef CurStrOffsetSection,
const InfoSectionUnitHeader &Header) {
uint16_t Version) {
// Could possibly produce an error or warning if one of these was non-null but
// the other was null.
if (CurStrSection.empty() || CurStrOffsetSection.empty())
Expand All @@ -195,7 +195,7 @@ static void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,

Out.SwitchSection(StrOffsetSection);

uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Header.Version);
uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Version);
uint64_t Offset = 0;
uint64_t Size = CurStrOffsetSection.size();
// FIXME: This can be caused by bad input and should be handled as such.
Expand Down Expand Up @@ -340,10 +340,10 @@ static bool isSupportedSectionKind(DWARFSectionKind Kind) {

// Convert an internal section identifier into the index to use with
// UnitIndexEntry::Contributions.
static unsigned getContributionIndex(DWARFSectionKind Kind) {
// Assuming the pre-standard DWP format.
assert(serializeSectionKind(Kind, 2) >= DW_SECT_INFO);
return serializeSectionKind(Kind, 2) - DW_SECT_INFO;
static unsigned getContributionIndex(DWARFSectionKind Kind,
uint32_t IndexVersion) {
assert(serializeSectionKind(Kind, IndexVersion) >= DW_SECT_INFO);
return serializeSectionKind(Kind, IndexVersion) - DW_SECT_INFO;
}

// Convert a UnitIndexEntry::Contributions index to the corresponding on-disk
Expand Down Expand Up @@ -379,12 +379,14 @@ static void addAllTypesFromDWP(
for (auto Kind : TUIndex.getColumnKinds()) {
if (!isSupportedSectionKind(Kind))
continue;
auto &C = Entry.Contributions[getContributionIndex(Kind)];
auto &C =
Entry.Contributions[getContributionIndex(Kind, TUIndex.getVersion())];
C.Offset += I->Offset;
C.Length = I->Length;
++I;
}
unsigned TypesIndex = getContributionIndex(DW_SECT_EXT_TYPES);
unsigned TypesIndex =
getContributionIndex(DW_SECT_EXT_TYPES, TUIndex.getVersion());
auto &C = Entry.Contributions[TypesIndex];
Out.emitBytes(Types.substr(
C.Offset - TUEntry.Contributions[TypesIndex].Offset, C.Length));
Expand All @@ -406,7 +408,7 @@ static void addAllTypes(MCStreamer &Out,
UnitIndexEntry Entry = CUEntry;
// Zero out the debug_info contribution
Entry.Contributions[0] = {};
auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES)];
auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES, 2)];
C.Offset = TypesOffset;
auto PrevOffset = Offset;
// Length of the unit, including the 4 byte length field.
Expand Down Expand Up @@ -438,10 +440,10 @@ writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
Out.emitIntValue(E.second.Contributions[i].*Field, 4);
}

static void
writeIndex(MCStreamer &Out, MCSection *Section,
ArrayRef<unsigned> ContributionOffsets,
const MapVector<uint64_t, UnitIndexEntry> &IndexEntries) {
static void writeIndex(MCStreamer &Out, MCSection *Section,
ArrayRef<unsigned> ContributionOffsets,
const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
uint32_t IndexVersion) {
if (IndexEntries.empty())
return;

Expand All @@ -467,7 +469,7 @@ writeIndex(MCStreamer &Out, MCSection *Section,
}

Out.SwitchSection(Section);
Out.emitIntValue(2, 4); // Version
Out.emitIntValue(IndexVersion, 4); // Version
Out.emitIntValue(Columns, 4); // Columns
Out.emitIntValue(IndexEntries.size(), 4); // Num Units
Out.emitIntValue(Buckets.size(), 4); // Num Buckets
Expand Down Expand Up @@ -551,7 +553,8 @@ static Error handleSection(
StringRef &CurStrSection, StringRef &CurStrOffsetSection,
std::vector<StringRef> &CurTypesSection,
std::vector<StringRef> &CurInfoSection, StringRef &AbbrevSection,
StringRef &CurCUIndexSection, StringRef &CurTUIndexSection) {
StringRef &CurCUIndexSection, StringRef &CurTUIndexSection,
std::vector<std::pair<DWARFSectionKind, uint32_t>> &SectionLength) {
if (Section.isBSS())
return Error::success();

Expand All @@ -578,11 +581,8 @@ static Error handleSection(
return Error::success();

if (DWARFSectionKind Kind = SectionPair->second.second) {
auto Index = getContributionIndex(Kind);
if (Kind != DW_SECT_EXT_TYPES && Kind != DW_SECT_INFO) {
CurEntry.Contributions[Index].Offset = ContributionOffsets[Index];
ContributionOffsets[Index] +=
(CurEntry.Contributions[Index].Length = Contents.size());
SectionLength.push_back(std::make_pair(Kind, Contents.size()));
}

if (Kind == DW_SECT_ABBREV) {
Expand Down Expand Up @@ -664,6 +664,7 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
{"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},
{"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
{"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
{"debug_macro.dwo", {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}},
{"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
{"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
{"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
Expand All @@ -672,6 +673,8 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;

uint32_t ContributionOffsets[8] = {};
uint16_t Version = 0;
uint32_t IndexVersion = 0;

DWPStringPool Strings(Out, StrSection);

Expand All @@ -698,14 +701,19 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
StringRef CurCUIndexSection;
StringRef CurTUIndexSection;

// This maps each section contained in this file to its length.
// This information is later on used to calculate the contributions,
// i.e. offset and length, of each compile/type unit to a section.
std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;

for (const auto &Section : Obj.sections())
if (auto Err = handleSection(
KnownSections, StrSection, StrOffsetSection, TypesSection,
CUIndexSection, TUIndexSection, InfoSection, Section, Out,
UncompressedSections, ContributionOffsets, CurEntry,
CurStrSection, CurStrOffsetSection, CurTypesSection,
CurInfoSection, AbbrevSection, CurCUIndexSection,
CurTUIndexSection))
CurTUIndexSection, SectionLength))
return Err;

if (CurInfoSection.empty())
Expand All @@ -717,11 +725,25 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
return HeaderOrErr.takeError();
InfoSectionUnitHeader &Header = *HeaderOrErr;

if (Version == 0) {
Version = Header.Version;
IndexVersion = Version < 5 ? 2 : 5;
} else if (Version != Header.Version) {
return make_error<DWPError>("incompatible DWARF compile unit versions.");
}

writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
CurStrOffsetSection, Header);
CurStrOffsetSection, Header.Version);

for (auto Pair : SectionLength) {
auto Index = getContributionIndex(Pair.first, IndexVersion);
CurEntry.Contributions[Index].Offset = ContributionOffsets[Index];
ContributionOffsets[Index] +=
(CurEntry.Contributions[Index].Length = Pair.second);
}

uint32_t &InfoSectionOffset =
ContributionOffsets[getContributionIndex(DW_SECT_INFO)];
ContributionOffsets[getContributionIndex(DW_SECT_INFO, IndexVersion)];
if (CurCUIndexSection.empty()) {
bool FoundCUUnit = false;
Out.SwitchSection(InfoSection);
Expand All @@ -737,7 +759,8 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
InfoSectionUnitHeader &Header = *HeaderOrError;

UnitIndexEntry Entry = CurEntry;
auto &C = Entry.Contributions[getContributionIndex(DW_SECT_INFO)];
auto &C = Entry.Contributions[getContributionIndex(DW_SECT_INFO,
IndexVersion)];
C.Offset = InfoSectionOffset;
C.Length = Header.Length + 4;

Expand Down Expand Up @@ -768,11 +791,12 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
if (!FoundCUUnit)
return make_error<DWPError>("no compile unit found in file: " + Input);

// Add types from the .debug_types section from DWARF < 5.
addAllTypes(Out, TypeIndexEntries, TypesSection, CurTypesSection,
CurEntry,
ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]);

if (IndexVersion == 2) {
// Add types from the .debug_types section from DWARF < 5.
addAllTypes(
Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry,
ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)]);
}
continue;
}

Expand All @@ -785,10 +809,10 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
if (!CUIndex.parse(CUIndexData))
return make_error<DWPError>("failed to parse cu_index");
if (CUIndex.getVersion() != 2)
return make_error<DWPError>(
"unsupported cu_index version: " + utostr(CUIndex.getVersion()) +
" (only version 2 is supported)");
if (CUIndex.getVersion() != IndexVersion)
return make_error<DWPError>("incompatible cu_index versions, found " +
utostr(CUIndex.getVersion()) +
" and expecting " + utostr(IndexVersion));

Out.SwitchSection(InfoSection);
for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
Expand Down Expand Up @@ -821,12 +845,13 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
for (auto Kind : CUIndex.getColumnKinds()) {
if (!isSupportedSectionKind(Kind))
continue;
auto &C = NewEntry.Contributions[getContributionIndex(Kind)];
auto &C =
NewEntry.Contributions[getContributionIndex(Kind, IndexVersion)];
C.Offset += I->Offset;
C.Length = I->Length;
++I;
}
unsigned Index = getContributionIndex(DW_SECT_INFO);
unsigned Index = getContributionIndex(DW_SECT_INFO, IndexVersion);
auto &C = NewEntry.Contributions[Index];
Out.emitBytes(CUInfoSection);
C.Offset = InfoSectionOffset;
Expand All @@ -841,30 +866,35 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
if (!TUIndex.parse(TUIndexData))
return make_error<DWPError>("failed to parse tu_index");
if (TUIndex.getVersion() != 2)
return make_error<DWPError>(
"unsupported tu_index version: " + utostr(TUIndex.getVersion()) +
" (only version 2 is supported)");
return make_error<DWPError>("expected index version 2, but got: " +
utostr(TUIndex.getVersion()));

addAllTypesFromDWP(
Out, TypeIndexEntries, TUIndex, TypesSection, CurTypesSection.front(),
CurEntry,
ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]);
ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)]);
}
}

// Lie about there being no info contributions so the TU index only includes
// the type unit contribution
ContributionOffsets[0] = 0;
if (Version < 5) {
// Lie about there being no info contributions so the TU index only includes
// the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
// contribution to the info section, so we do not want to lie about it.
ContributionOffsets[0] = 0;
}
writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
TypeIndexEntries);

// Lie about the type contribution
ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)] = 0;
// Unlie about the info contribution
ContributionOffsets[0] = 1;
TypeIndexEntries, IndexVersion);

if (Version < 5) {
// Lie about the type contribution for DWARF < 5. In DWARFv5 the type
// section does not exist, so no need to do anything about this.
ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0;
// Unlie about the info contribution
ContributionOffsets[0] = 1;
}

writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
IndexEntries);
IndexEntries, IndexVersion);

return Error::success();
}
Expand Down

0 comments on commit 6e2d304

Please sign in to comment.