[llvm-dwp] Support debug_tu_index

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254827 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Blaikie 2015-12-05 03:05:45 +00:00
parent 8893466777
commit 543e02b438
6 changed files with 160 additions and 66 deletions

View File

@ -118,6 +118,7 @@ protected:
// These are for Fission DWP files.
MCSection *DwarfCUIndexSection;
MCSection *DwarfTUIndexSection;
/// Section for newer gnu pubnames.
MCSection *DwarfGnuPubNamesSection;
@ -266,6 +267,7 @@ public:
MCSection *getDwarfStrOffDWOSection() const { return DwarfStrOffDWOSection; }
MCSection *getDwarfAddrSection() const { return DwarfAddrSection; }
MCSection *getDwarfCUIndexSection() const { return DwarfCUIndexSection; }
MCSection *getDwarfTUIndexSection() const { return DwarfTUIndexSection; }
MCSection *getCOFFDebugSymbolsSection() const {
return COFFDebugSymbolsSection;

View File

@ -262,6 +262,9 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(Triple T) {
DwarfCUIndexSection =
Ctx->getMachOSection("__DWARF", "__debug_cu_index", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
DwarfTUIndexSection =
Ctx->getMachOSection("__DWARF", "__debug_tu_index", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
StackMapSection = Ctx->getMachOSection("__LLVM_STACKMAPS", "__llvm_stackmaps",
0, SectionKind::getMetadata());
@ -537,6 +540,8 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(Triple T) {
// DWP Sections
DwarfCUIndexSection =
Ctx->getELFSection(".debug_cu_index", ELF::SHT_PROGBITS, 0);
DwarfTUIndexSection =
Ctx->getELFSection(".debug_tu_index", ELF::SHT_PROGBITS, 0);
StackMapSection =
Ctx->getELFSection(".llvm_stackmaps", ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
@ -725,6 +730,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(Triple T) {
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ,
SectionKind::getMetadata());
DwarfTUIndexSection = Ctx->getCOFFSection(
".debug_tu_index",
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ,
SectionKind::getMetadata());
DwarfAccelNamesSection = Ctx->getCOFFSection(
".apple_names",
COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |

View File

@ -13,48 +13,73 @@ b.cpp:
void b(bar) {
}
CHECK: .debug_abbrev.dwo contents:
CHECK: Abbrev table for offset: 0x00000000
CHECK-LABEL: .debug_abbrev.dwo contents:
CHECK-LABEL: Abbrev table for offset:
CHECK: 0x0000[[AAOFF:.*]]
CHECK: DW_TAG_compile_unit
CHECK: DW_TAG_variable
CHECK: DW_TAG_structure_type
CHECK: Abbrev table for offset: 0x00000031
CHECK-LABEL: Abbrev table for offset:
CHECK: 0x0000[[BAOFF:.*]]
CHECK: DW_TAG_compile_unit
CHECK: DW_TAG_structure_type
CHECK: DW_TAG_subprogram
CHECK: DW_TAG_formal_parameter
CHECK: .debug_info.dwo contents:
CHECK: 0x00000000: Compile Unit: length = 0x00000025 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000029)
CHECK: [[AOFF:0x[0-9a-f]*]]:
CHECK-LABEL: Compile Unit: length = 0x00000029 version = 0x0004 abbr_offset =
CHECK: 0x[[AAOFF]] addr_size = 0x08 (next unit at [[BOFF:.*]])
CHECK: DW_TAG_compile_unit
CHECK: DW_AT_name {{.*}} "a.cpp"
CHECK: DW_AT_GNU_dwo_id {{.*}} ([[DWOA:.*]])
CHECK: DW_TAG_variable
CHECK: DW_AT_name {{.*}} "a"
CHECK: DW_TAG_structure_type
CHECK: DW_AT_name {{.*}} "foo"
CHECK: DW_AT_signature {{.*}} ([[FOOSIG:.*]])
CHECK: 0x00000029: Compile Unit: length = 0x00000031 version = 0x0004 abbr_offset = 0x0031 addr_size = 0x08 (next unit at 0x0000005e)
CHECK: [[BOFF]]:
CHECK-LABEL: Compile Unit: length = 0x00000035 version = 0x0004 abbr_offset =
CHECK: 0x[[BAOFF]] addr_size = 0x08 (next unit at [[XOFF:.*]])
CHECK: DW_AT_name {{.*}} "b.cpp"
CHECK: DW_AT_GNU_dwo_id {{.*}} ([[DWOB:.*]])
CHECK: DW_TAG_structure_type
CHECK: DW_AT_name {{.*}} "bar"
CHECK: DW_AT_signature {{.*}} ([[BARSIG:.*]])
CHECK: DW_TAG_subprogram
CHECK: DW_AT_name {{.*}} "b"
CHECK: DW_TAG_formal_parameter
CHECK: .debug_cu_index contents:
CHECK: Index Signature INFO ABBREV LINE STR_OFFSETS
CHECK: 3 [[DWOA]] [0x00000000, 0x00000029) [0x00000000, 0x00000031) [0x00000000, 0x00000011) [0x00000000, 0x00000010)
CHECK: 4 [[DWOB]] [0x00000029, 0x0000005e) [0x00000031, 0x00000075) [0x00000011, 0x00000022) [0x00000010, 0x00000024)
CHECK-LABEL: .debug_types.dwo contents:
CHECK: [[FOOUOFF:0x[0-9a-f]*]]:
CHECK-LABEL: Type Unit: length = 0x00000020 version = 0x0004 abbr_offset =
CHECK: 0x[[AAOFF]] addr_size = 0x08 type_signature = [[FOOSIG]] type_offset = 0x[[FOOOFF:.*]] (next unit at [[BARUOFF:.*]])
CHECK: DW_TAG_type_unit
CHECK: [[FOOOFF]]: DW_TAG_structure_type
CHECK: DW_AT_name {{.*}} "foo"
CHECK: [[BARUOFF]]:
CHECK-LABEL: Type Unit: length = 0x00000020 version = 0x0004 abbr_offset =
CHECK: 0x[[BAOFF]] addr_size = 0x08 type_signature = [[BARSIG]] type_offset = 0x001e (next unit at [[XUOFF:.*]])
CHECK: DW_TAG_type_unit
CHECK: 0x00000042: DW_TAG_structure_type
CHECK: DW_AT_name {{.*}} "bar"
CHECK: .debug_str.dwo contents:
CHECK-LABEL: .debug_cu_index contents:
CHECK: Index Signature INFO ABBREV LINE STR_OFFSETS
CHECK: 1 [[DWOA]] {{\[}}[[AOFF]], [[BOFF]]) [0x0000[[AAOFF]], 0x0000[[BAOFF]]) [0x00000000, 0x0000001a) [0x00000000, 0x00000010)
CHECK: 3 [[DWOB]] {{\[}}[[BOFF]], [[XOFF]]) [0x0000[[BAOFF]], 0x00000099) [0x0000001a, 0x00000034) [0x00000010, 0x00000024)
CHECK-LABEL: .debug_tu_index contents:
CHECK: Index Signature TYPES ABBREV LINE STR_OFFSETS
CHECK: 1 [[FOOSIG]] {{\[}}[[FOOUOFF]], [[BARUOFF]]) [0x0000[[AAOFF]], 0x0000[[BAOFF]]) [0x00000000, 0x0000001a) [0x00000000, 0x00000010)
CHECK: 4 [[BARSIG]] {{\[}}[[BARUOFF]], [[XUOFF]]) [0x0000[[BAOFF]], 0x00000099) [0x0000001a, 0x00000034) [0x00000010, 0x00000024)
CHECK-LABEL: .debug_str.dwo contents:
CHECK: "clang version
CHECK: 0x[[ACPP:.*]]: "a.cpp"
CHECK-NOT: "clang version
CHECK: 0x[[BCPP:.*]]: "b.cpp"
CHECK: .debug_str_offsets.dwo contents:
CHECK-LABEL: .debug_str_offsets.dwo contents:
CHECK: : 00000000
CHECK: : [[ACPP]]
CHECK: : 00000000

View File

@ -130,6 +130,90 @@ static uint64_t getCUSignature(StringRef Abbrev, StringRef Info) {
return InfoData.getU64(&Offset);
}
struct UnitIndexEntry {
uint64_t Signature;
DWARFUnitIndex::Entry::SectionContribution Contributions[8];
};
static void addAllTypes(std::vector<UnitIndexEntry> &TypeIndexEntries,
uint32_t OutTypesOffset, StringRef Types,
const UnitIndexEntry &CUEntry) {
uint32_t Offset = 0;
DataExtractor Data(Types, true, 0);
while (Data.isValidOffset(Offset)) {
TypeIndexEntries.push_back(CUEntry);
auto &Entry = TypeIndexEntries.back();
// Zero out the debug_info contribution
Entry.Contributions[0] = {};
auto &C = Entry.Contributions[DW_SECT_TYPES - DW_SECT_INFO];
C.Offset = OutTypesOffset + Offset;
auto PrevOffset = Offset;
// Length of the unit, including the 4 byte length field.
C.Length = Data.getU32(&Offset) + 4;
Data.getU16(&Offset); // Version
Data.getU32(&Offset); // Abbrev offset
Data.getU8(&Offset); // Address size
Entry.Signature = Data.getU64(&Offset);
Offset = PrevOffset + C.Length;
}
}
static void
writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
ArrayRef<UnitIndexEntry> IndexEntries,
uint32_t DWARFUnitIndex::Entry::SectionContribution::*Field) {
for (const auto &E : IndexEntries)
for (size_t i = 0; i != array_lengthof(E.Contributions); ++i)
if (ContributionOffsets[i])
Out.EmitIntValue(E.Contributions[i].*Field, 4);
}
static void writeIndex(MCStreamer &Out, MCSection *Section,
ArrayRef<unsigned> ContributionOffsets,
ArrayRef<UnitIndexEntry> IndexEntries) {
unsigned Columns = 0;
for (auto &C : ContributionOffsets)
if (C)
++Columns;
std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
uint64_t Mask = Buckets.size() - 1;
for (size_t i = 0; i != IndexEntries.size(); ++i) {
auto S = IndexEntries[i].Signature;
auto H = S & Mask;
while (Buckets[H])
H += ((S >> 32) & Mask) | 1;
Buckets[H] = i + 1;
}
Out.SwitchSection(Section);
Out.EmitIntValue(2, 4); // Version
Out.EmitIntValue(Columns, 4); // Columns
Out.EmitIntValue(IndexEntries.size(), 4); // Num Units
Out.EmitIntValue(Buckets.size(), 4); // Num Buckets
// Write the signatures.
for (const auto &I : Buckets)
Out.EmitIntValue(I ? IndexEntries[I - 1].Signature : 0, 8);
// Write the indexes.
for (const auto &I : Buckets)
Out.EmitIntValue(I, 4);
// Write the column headers (which sections will appear in the table)
for (size_t i = 0; i != ContributionOffsets.size(); ++i)
if (ContributionOffsets[i])
Out.EmitIntValue(i + DW_SECT_INFO, 4);
// Write the offsets.
writeIndexTable(Out, ContributionOffsets, IndexEntries,
&DWARFUnitIndex::Entry::SectionContribution::Offset);
// Write the lengths.
writeIndexTable(Out, ContributionOffsets, IndexEntries,
&DWARFUnitIndex::Entry::SectionContribution::Length);
}
static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
const auto &MCOFI = *Out.getContext().getObjectFileInfo();
MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
@ -143,12 +227,8 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
{"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
{"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}}};
struct UnitIndexEntry {
uint64_t Signature;
DWARFUnitIndex::Entry::SectionContribution Contributions[8];
};
std::vector<UnitIndexEntry> IndexEntries;
std::vector<UnitIndexEntry> TypeIndexEntries;
StringMap<uint32_t> Strings;
uint32_t StringOffset = 0;
@ -167,6 +247,9 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
StringRef CurStrOffsetSection;
StringRef InfoSection;
StringRef AbbrevSection;
StringRef TypesSection;
auto TypesOffset = ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO];
for (const auto &Section : ErrOrObj->getBinary()->sections()) {
StringRef Name;
@ -188,12 +271,18 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
ContributionOffsets[Index] +=
(CurEntry.Contributions[Index].Length = Contents.size());
if (Kind == DW_SECT_INFO) {
assert(InfoSection.empty());
switch (Kind) {
case DW_SECT_INFO:
InfoSection = Contents;
} else if (Kind == DW_SECT_ABBREV) {
assert(AbbrevSection.empty());
break;
case DW_SECT_ABBREV:
AbbrevSection = Contents;
break;
case DW_SECT_TYPES:
TypesSection = Contents;
break;
default:
break;
}
}
@ -211,6 +300,7 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
assert(!AbbrevSection.empty());
assert(!InfoSection.empty());
CurEntry.Signature = getCUSignature(AbbrevSection, InfoSection);
addAllTypes(TypeIndexEntries, TypesOffset, TypesSection, CurEntry);
if (auto Err = writeStringsAndOffsets(Out, Strings, StringOffset,
StrSection, StrOffsetSection,
@ -218,52 +308,19 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
return Err;
}
unsigned Columns = 0;
for (auto &C : ContributionOffsets)
if (C)
++Columns;
// Lie about there being no info contributions so the TU index only includes
// the type unit contribution
ContributionOffsets[0] = 0;
writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
TypeIndexEntries);
std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
uint64_t Mask = Buckets.size() - 1;
for (size_t i = 0; i != IndexEntries.size(); ++i) {
auto S = IndexEntries[i].Signature;
auto H = S & Mask;
while (Buckets[H])
H += ((S >> 32) & Mask) | 1;
Buckets[H] = i + 1;
}
// Lie about the type contribution
ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO] = 0;
// Unlie about the info contribution
ContributionOffsets[0] = 1;
Out.SwitchSection(MCOFI.getDwarfCUIndexSection());
Out.EmitIntValue(2, 4); // Version
Out.EmitIntValue(Columns, 4); // Columns
Out.EmitIntValue(IndexEntries.size(), 4); // Num Units
// FIXME: This is not the right number of buckets for a real hash.
Out.EmitIntValue(Buckets.size(), 4); // Num Buckets
// Write the signatures.
for (const auto &I : Buckets)
Out.EmitIntValue(I ? IndexEntries[I - 1].Signature : 0, 8);
// Write the indexes.
for (const auto &I : Buckets)
Out.EmitIntValue(I, 4);
// Write the column headers (which sections will appear in the table)
for (size_t i = 0; i != array_lengthof(ContributionOffsets); ++i)
if (ContributionOffsets[i])
Out.EmitIntValue(i + DW_SECT_INFO, 4);
// Write the offsets.
for (const auto &E : IndexEntries)
for (size_t i = 0; i != array_lengthof(E.Contributions); ++i)
if (ContributionOffsets[i])
Out.EmitIntValue(E.Contributions[i].Offset, 4);
// Write the lengths.
for (const auto &E : IndexEntries)
for (size_t i = 0; i != array_lengthof(E.Contributions); ++i)
if (ContributionOffsets[i])
Out.EmitIntValue(E.Contributions[i].Length, 4);
writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
IndexEntries);
return std::error_code();
}