forked from OSchip/llvm-project
[DWARF] Generate DWARF v5 string offsets tables along with strx* index forms.
Summary: This is the producer side for DWARF v5 string offsets tables. The reader/consumer side was committed with r321295. All compile and type units in a module share a contribution to the string offsets table. Indirect strings use the strx{1,2,3,4} index forms. Reviewers: dblaikie, aprantl, JDevliegehere Differential Revision: https://reviews.llvm.org/D42021 llvm-svn: 323546
This commit is contained in:
parent
b8ae262bd3
commit
456b555ffe
|
@ -388,6 +388,7 @@ void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
|
||||||
case dwarf::DW_FORM_data2:
|
case dwarf::DW_FORM_data2:
|
||||||
case dwarf::DW_FORM_strx2:
|
case dwarf::DW_FORM_strx2:
|
||||||
case dwarf::DW_FORM_addrx2:
|
case dwarf::DW_FORM_addrx2:
|
||||||
|
case dwarf::DW_FORM_strx3:
|
||||||
case dwarf::DW_FORM_strp:
|
case dwarf::DW_FORM_strp:
|
||||||
case dwarf::DW_FORM_ref4:
|
case dwarf::DW_FORM_ref4:
|
||||||
case dwarf::DW_FORM_data4:
|
case dwarf::DW_FORM_data4:
|
||||||
|
@ -410,6 +411,7 @@ void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
|
||||||
case dwarf::DW_FORM_GNU_str_index:
|
case dwarf::DW_FORM_GNU_str_index:
|
||||||
case dwarf::DW_FORM_GNU_addr_index:
|
case dwarf::DW_FORM_GNU_addr_index:
|
||||||
case dwarf::DW_FORM_ref_udata:
|
case dwarf::DW_FORM_ref_udata:
|
||||||
|
case dwarf::DW_FORM_strx:
|
||||||
case dwarf::DW_FORM_udata:
|
case dwarf::DW_FORM_udata:
|
||||||
Asm->EmitULEB128(Integer);
|
Asm->EmitULEB128(Integer);
|
||||||
return;
|
return;
|
||||||
|
@ -438,6 +440,8 @@ unsigned DIEInteger::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
||||||
case dwarf::DW_FORM_strx2:
|
case dwarf::DW_FORM_strx2:
|
||||||
case dwarf::DW_FORM_addrx2:
|
case dwarf::DW_FORM_addrx2:
|
||||||
return sizeof(int16_t);
|
return sizeof(int16_t);
|
||||||
|
case dwarf::DW_FORM_strx3:
|
||||||
|
return 3;
|
||||||
case dwarf::DW_FORM_ref4:
|
case dwarf::DW_FORM_ref4:
|
||||||
case dwarf::DW_FORM_data4:
|
case dwarf::DW_FORM_data4:
|
||||||
case dwarf::DW_FORM_ref_sup4:
|
case dwarf::DW_FORM_ref_sup4:
|
||||||
|
@ -469,6 +473,7 @@ unsigned DIEInteger::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
||||||
case dwarf::DW_FORM_GNU_str_index:
|
case dwarf::DW_FORM_GNU_str_index:
|
||||||
case dwarf::DW_FORM_GNU_addr_index:
|
case dwarf::DW_FORM_GNU_addr_index:
|
||||||
case dwarf::DW_FORM_ref_udata:
|
case dwarf::DW_FORM_ref_udata:
|
||||||
|
case dwarf::DW_FORM_strx:
|
||||||
case dwarf::DW_FORM_udata:
|
case dwarf::DW_FORM_udata:
|
||||||
return getULEB128Size(Integer);
|
return getULEB128Size(Integer);
|
||||||
case dwarf::DW_FORM_sdata:
|
case dwarf::DW_FORM_sdata:
|
||||||
|
@ -564,44 +569,46 @@ void DIEDelta::print(raw_ostream &O) const {
|
||||||
/// EmitValue - Emit string value.
|
/// EmitValue - Emit string value.
|
||||||
///
|
///
|
||||||
void DIEString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
|
void DIEString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
|
||||||
assert(
|
|
||||||
(Form == dwarf::DW_FORM_strp || Form == dwarf::DW_FORM_GNU_str_index) &&
|
|
||||||
"Expected valid string form");
|
|
||||||
|
|
||||||
// Index of string in symbol table.
|
// Index of string in symbol table.
|
||||||
if (Form == dwarf::DW_FORM_GNU_str_index) {
|
switch (Form) {
|
||||||
|
case dwarf::DW_FORM_GNU_str_index:
|
||||||
|
case dwarf::DW_FORM_strx:
|
||||||
|
case dwarf::DW_FORM_strx1:
|
||||||
|
case dwarf::DW_FORM_strx2:
|
||||||
|
case dwarf::DW_FORM_strx3:
|
||||||
|
case dwarf::DW_FORM_strx4:
|
||||||
DIEInteger(S.getIndex()).EmitValue(AP, Form);
|
DIEInteger(S.getIndex()).EmitValue(AP, Form);
|
||||||
return;
|
return;
|
||||||
}
|
case dwarf::DW_FORM_strp:
|
||||||
|
if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
|
||||||
// Relocatable symbol.
|
DIELabel(S.getSymbol()).EmitValue(AP, Form);
|
||||||
assert(Form == dwarf::DW_FORM_strp);
|
else
|
||||||
if (AP->MAI->doesDwarfUseRelocationsAcrossSections()) {
|
DIEInteger(S.getOffset()).EmitValue(AP, Form);
|
||||||
DIELabel(S.getSymbol()).EmitValue(AP, Form);
|
|
||||||
return;
|
return;
|
||||||
|
default:
|
||||||
|
llvm_unreachable("Expected valid string form");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offset into symbol table.
|
|
||||||
DIEInteger(S.getOffset()).EmitValue(AP, Form);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SizeOf - Determine size of delta value in bytes.
|
/// SizeOf - Determine size of delta value in bytes.
|
||||||
///
|
///
|
||||||
unsigned DIEString::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
unsigned DIEString::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
||||||
assert(
|
|
||||||
(Form == dwarf::DW_FORM_strp || Form == dwarf::DW_FORM_GNU_str_index) &&
|
|
||||||
"Expected valid string form");
|
|
||||||
|
|
||||||
// Index of string in symbol table.
|
// Index of string in symbol table.
|
||||||
if (Form == dwarf::DW_FORM_GNU_str_index)
|
switch (Form) {
|
||||||
|
case dwarf::DW_FORM_GNU_str_index:
|
||||||
|
case dwarf::DW_FORM_strx:
|
||||||
|
case dwarf::DW_FORM_strx1:
|
||||||
|
case dwarf::DW_FORM_strx2:
|
||||||
|
case dwarf::DW_FORM_strx3:
|
||||||
|
case dwarf::DW_FORM_strx4:
|
||||||
return DIEInteger(S.getIndex()).SizeOf(AP, Form);
|
return DIEInteger(S.getIndex()).SizeOf(AP, Form);
|
||||||
|
case dwarf::DW_FORM_strp:
|
||||||
// Relocatable symbol.
|
if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
|
||||||
if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
|
return DIELabel(S.getSymbol()).SizeOf(AP, Form);
|
||||||
return DIELabel(S.getSymbol()).SizeOf(AP, Form);
|
return DIEInteger(S.getOffset()).SizeOf(AP, Form);
|
||||||
|
default:
|
||||||
// Offset into symbol table.
|
llvm_unreachable("Expected valid string form");
|
||||||
return DIEInteger(S.getOffset()).SizeOf(AP, Form);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVM_DUMP_METHOD
|
LLVM_DUMP_METHOD
|
||||||
|
|
|
@ -323,6 +323,12 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
|
||||||
// GDB does not fully support the DWARF 4 representation for bitfields.
|
// GDB does not fully support the DWARF 4 representation for bitfields.
|
||||||
UseDWARF2Bitfields = (DwarfVersion < 4) || tuneForGDB();
|
UseDWARF2Bitfields = (DwarfVersion < 4) || tuneForGDB();
|
||||||
|
|
||||||
|
// The DWARF v5 string offsets table has - possibly shared - contributions
|
||||||
|
// from each compile and type unit each preceded by a header. The string
|
||||||
|
// offsets table used by the pre-DWARF v5 split-DWARF implementation uses
|
||||||
|
// a monolithic string offsets table without any header.
|
||||||
|
UseSegmentedStringOffsetsTable = DwarfVersion >= 5;
|
||||||
|
|
||||||
Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion);
|
Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,6 +494,10 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
|
||||||
DIUnit->getSourceLanguage());
|
DIUnit->getSourceLanguage());
|
||||||
NewCU.addString(Die, dwarf::DW_AT_name, FN);
|
NewCU.addString(Die, dwarf::DW_AT_name, FN);
|
||||||
|
|
||||||
|
// Add DW_str_offsets_base to the unit DIE, except for split units.
|
||||||
|
if (useSegmentedStringOffsetsTable() && !useSplitDwarf())
|
||||||
|
NewCU.addStringOffsetsStart();
|
||||||
|
|
||||||
if (!useSplitDwarf()) {
|
if (!useSplitDwarf()) {
|
||||||
NewCU.initStmtList();
|
NewCU.initStmtList();
|
||||||
|
|
||||||
|
@ -592,6 +602,13 @@ void DwarfDebug::beginModule() {
|
||||||
GVMap[GVE->getVariable()].push_back({&Global, GVE->getExpression()});
|
GVMap[GVE->getVariable()].push_back({&Global, GVE->getExpression()});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the symbol that designates the start of the unit's contribution
|
||||||
|
// to the string offsets table. In a split DWARF scenario, only the skeleton
|
||||||
|
// unit has the DW_AT_str_offsets_base attribute (and hence needs the symbol).
|
||||||
|
if (useSegmentedStringOffsetsTable())
|
||||||
|
(useSplitDwarf() ? SkeletonHolder : InfoHolder)
|
||||||
|
.setStringOffsetsStartSym(Asm->createTempSymbol("str_offsets_base"));
|
||||||
|
|
||||||
for (DICompileUnit *CUNode : M->debug_compile_units()) {
|
for (DICompileUnit *CUNode : M->debug_compile_units()) {
|
||||||
// FIXME: Move local imported entities into a list attached to the
|
// FIXME: Move local imported entities into a list attached to the
|
||||||
// subprogram, then this search won't be needed and a
|
// subprogram, then this search won't be needed and a
|
||||||
|
@ -1401,6 +1418,12 @@ void DwarfDebug::emitAbbreviations() {
|
||||||
Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection());
|
Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DwarfDebug::emitStringOffsetsTableHeader() {
|
||||||
|
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
|
||||||
|
Holder.emitStringOffsetsTableHeader(
|
||||||
|
Asm->getObjFileLowering().getDwarfStrOffSection());
|
||||||
|
}
|
||||||
|
|
||||||
void DwarfDebug::emitAccel(DwarfAccelTable &Accel, MCSection *Section,
|
void DwarfDebug::emitAccel(DwarfAccelTable &Accel, MCSection *Section,
|
||||||
StringRef TableName) {
|
StringRef TableName) {
|
||||||
Accel.FinalizeTable(Asm, TableName);
|
Accel.FinalizeTable(Asm, TableName);
|
||||||
|
@ -1575,8 +1598,14 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name,
|
||||||
|
|
||||||
/// Emit null-terminated strings into a debug str section.
|
/// Emit null-terminated strings into a debug str section.
|
||||||
void DwarfDebug::emitDebugStr() {
|
void DwarfDebug::emitDebugStr() {
|
||||||
|
MCSection *StringOffsetsSection = nullptr;
|
||||||
|
if (useSegmentedStringOffsetsTable()) {
|
||||||
|
emitStringOffsetsTableHeader();
|
||||||
|
StringOffsetsSection = Asm->getObjFileLowering().getDwarfStrOffSection();
|
||||||
|
}
|
||||||
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
|
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
|
||||||
Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection());
|
Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection(),
|
||||||
|
StringOffsetsSection, /* UseRelativeOffsets = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
|
void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
|
||||||
|
@ -2026,6 +2055,9 @@ DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) {
|
||||||
|
|
||||||
NewCU.initStmtList();
|
NewCU.initStmtList();
|
||||||
|
|
||||||
|
if (useSegmentedStringOffsetsTable())
|
||||||
|
NewCU.addStringOffsetsStart();
|
||||||
|
|
||||||
initSkeletonUnit(CU, NewCU.getUnitDie(), std::move(OwnedUnit));
|
initSkeletonUnit(CU, NewCU.getUnitDie(), std::move(OwnedUnit));
|
||||||
|
|
||||||
return NewCU;
|
return NewCU;
|
||||||
|
@ -2053,14 +2085,22 @@ void DwarfDebug::emitDebugLineDWO() {
|
||||||
SplitTypeUnitFileTable.Emit(*Asm->OutStreamer, MCDwarfLineTableParams());
|
SplitTypeUnitFileTable.Emit(*Asm->OutStreamer, MCDwarfLineTableParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DwarfDebug::emitStringOffsetsTableHeaderDWO() {
|
||||||
|
assert(useSplitDwarf() && "No split dwarf?");
|
||||||
|
InfoHolder.emitStringOffsetsTableHeader(
|
||||||
|
Asm->getObjFileLowering().getDwarfStrOffDWOSection());
|
||||||
|
}
|
||||||
|
|
||||||
// Emit the .debug_str.dwo section for separated dwarf. This contains the
|
// Emit the .debug_str.dwo section for separated dwarf. This contains the
|
||||||
// string section and is identical in format to traditional .debug_str
|
// string section and is identical in format to traditional .debug_str
|
||||||
// sections.
|
// sections.
|
||||||
void DwarfDebug::emitDebugStrDWO() {
|
void DwarfDebug::emitDebugStrDWO() {
|
||||||
|
if (useSegmentedStringOffsetsTable())
|
||||||
|
emitStringOffsetsTableHeaderDWO();
|
||||||
assert(useSplitDwarf() && "No split dwarf?");
|
assert(useSplitDwarf() && "No split dwarf?");
|
||||||
MCSection *OffSec = Asm->getObjFileLowering().getDwarfStrOffDWOSection();
|
MCSection *OffSec = Asm->getObjFileLowering().getDwarfStrOffDWOSection();
|
||||||
InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
|
InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
|
||||||
OffSec);
|
OffSec, /* UseRelativeOffsets = */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) {
|
MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) {
|
||||||
|
@ -2120,6 +2160,11 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
|
||||||
NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesSection(Signature));
|
NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesSection(Signature));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add DW_AT_str_offsets_base to the type unit DIE, but not for split type
|
||||||
|
// units.
|
||||||
|
if (useSegmentedStringOffsetsTable() && !useSplitDwarf())
|
||||||
|
NewTU.addStringOffsetsStart();
|
||||||
|
|
||||||
NewTU.setType(NewTU.createTypeDIE(CTy));
|
NewTU.setType(NewTU.createTypeDIE(CTy));
|
||||||
|
|
||||||
if (TopLevelType) {
|
if (TopLevelType) {
|
||||||
|
|
|
@ -261,6 +261,12 @@ class DwarfDebug : public DebugHandlerBase {
|
||||||
bool HasAppleExtensionAttributes;
|
bool HasAppleExtensionAttributes;
|
||||||
bool HasSplitDwarf;
|
bool HasSplitDwarf;
|
||||||
|
|
||||||
|
/// Whether to generate the DWARF v5 string offsets table.
|
||||||
|
/// It consists of a series of contributions, each preceded by a header.
|
||||||
|
/// The pre-DWARF v5 string offsets table for split dwarf is, in contrast,
|
||||||
|
/// a monolithic sequence of string offsets.
|
||||||
|
bool UseSegmentedStringOffsetsTable;
|
||||||
|
|
||||||
/// Separated Dwarf Variables
|
/// Separated Dwarf Variables
|
||||||
/// In general these will all be for bits that are left in the
|
/// In general these will all be for bits that are left in the
|
||||||
/// original object file, rather than things that are meant
|
/// original object file, rather than things that are meant
|
||||||
|
@ -324,6 +330,9 @@ class DwarfDebug : public DebugHandlerBase {
|
||||||
/// Emit the abbreviation section.
|
/// Emit the abbreviation section.
|
||||||
void emitAbbreviations();
|
void emitAbbreviations();
|
||||||
|
|
||||||
|
/// Emit the string offsets table header.
|
||||||
|
void emitStringOffsetsTableHeader();
|
||||||
|
|
||||||
/// Emit a specified accelerator table.
|
/// Emit a specified accelerator table.
|
||||||
void emitAccel(DwarfAccelTable &Accel, MCSection *Section,
|
void emitAccel(DwarfAccelTable &Accel, MCSection *Section,
|
||||||
StringRef TableName);
|
StringRef TableName);
|
||||||
|
@ -388,6 +397,9 @@ class DwarfDebug : public DebugHandlerBase {
|
||||||
/// Emit the debug line dwo section.
|
/// Emit the debug line dwo section.
|
||||||
void emitDebugLineDWO();
|
void emitDebugLineDWO();
|
||||||
|
|
||||||
|
/// Emit the dwo stringoffsets table header.
|
||||||
|
void emitStringOffsetsTableHeaderDWO();
|
||||||
|
|
||||||
/// Emit the debug str dwo section.
|
/// Emit the debug str dwo section.
|
||||||
void emitDebugStrDWO();
|
void emitDebugStrDWO();
|
||||||
|
|
||||||
|
@ -492,6 +504,16 @@ public:
|
||||||
/// split dwarf proposal support.
|
/// split dwarf proposal support.
|
||||||
bool useSplitDwarf() const { return HasSplitDwarf; }
|
bool useSplitDwarf() const { return HasSplitDwarf; }
|
||||||
|
|
||||||
|
/// Returns whether to generate a string offsets table with (possibly shared)
|
||||||
|
/// contributions from each CU and type unit. This implies the use of
|
||||||
|
/// DW_FORM_strx* indirect references with DWARF v5 and beyond. Note that
|
||||||
|
/// DW_FORM_GNU_str_index is also an indirect reference, but it is used with
|
||||||
|
/// a pre-DWARF v5 implementation of split DWARF sections, which uses a
|
||||||
|
/// monolithic string offsets table.
|
||||||
|
bool useSegmentedStringOffsetsTable() const {
|
||||||
|
return UseSegmentedStringOffsetsTable;
|
||||||
|
}
|
||||||
|
|
||||||
bool shareAcrossDWOCUs() const;
|
bool shareAcrossDWOCUs() const;
|
||||||
|
|
||||||
/// Returns the Dwarf Version.
|
/// Returns the Dwarf Version.
|
||||||
|
|
|
@ -28,6 +28,26 @@ void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) {
|
||||||
CUs.push_back(std::move(U));
|
CUs.push_back(std::move(U));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DwarfFile::emitStringOffsetsTableHeader(MCSection *Section) {
|
||||||
|
if (StrPool.empty())
|
||||||
|
return;
|
||||||
|
Asm->OutStreamer->SwitchSection(Section);
|
||||||
|
unsigned EntrySize = 4;
|
||||||
|
// FIXME: DWARF64
|
||||||
|
// We are emitting the header for a contribution to the string offsets
|
||||||
|
// table. The header consists of an entry with the contribution's
|
||||||
|
// size (not including the size of the header), the DWARF version and
|
||||||
|
// 2 bytes of padding.
|
||||||
|
Asm->EmitInt32(StrPool.size() * EntrySize);
|
||||||
|
Asm->EmitInt16(Asm->getDwarfVersion());
|
||||||
|
Asm->EmitInt16(0);
|
||||||
|
// Define the symbol that marks the start of the contribution. It is
|
||||||
|
// referenced by most unit headers via DW_AT_str_offsets_base.
|
||||||
|
// Split units do not use the attribute.
|
||||||
|
if (StringOffsetsStartSym)
|
||||||
|
Asm->OutStreamer->EmitLabel(StringOffsetsStartSym);
|
||||||
|
}
|
||||||
|
|
||||||
// Emit the various dwarf units to the unit section USection with
|
// Emit the various dwarf units to the unit section USection with
|
||||||
// the abbreviations going into ASection.
|
// the abbreviations going into ASection.
|
||||||
void DwarfFile::emitUnits(bool UseOffsets) {
|
void DwarfFile::emitUnits(bool UseOffsets) {
|
||||||
|
@ -77,8 +97,9 @@ unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
|
||||||
void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); }
|
void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); }
|
||||||
|
|
||||||
// Emit strings into a string section.
|
// Emit strings into a string section.
|
||||||
void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection) {
|
void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection,
|
||||||
StrPool.emit(*Asm, StrSection, OffsetSection);
|
bool UseRelativeOffsets) {
|
||||||
|
StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
|
bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
|
||||||
|
|
|
@ -43,6 +43,10 @@ class DwarfFile {
|
||||||
|
|
||||||
DwarfStringPool StrPool;
|
DwarfStringPool StrPool;
|
||||||
|
|
||||||
|
/// DWARF v5: The symbol that designates the start of the contribution to
|
||||||
|
/// the string offsets table. The contribution is shared by all units.
|
||||||
|
MCSymbol *StringOffsetsStartSym = nullptr;
|
||||||
|
|
||||||
// Collection of dbg variables of a scope.
|
// Collection of dbg variables of a scope.
|
||||||
DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8>> ScopeVariables;
|
DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8>> ScopeVariables;
|
||||||
|
|
||||||
|
@ -75,6 +79,9 @@ public:
|
||||||
/// \brief Add a unit to the list of CUs.
|
/// \brief Add a unit to the list of CUs.
|
||||||
void addUnit(std::unique_ptr<DwarfCompileUnit> U);
|
void addUnit(std::unique_ptr<DwarfCompileUnit> U);
|
||||||
|
|
||||||
|
/// Emit the string table offsets header.
|
||||||
|
void emitStringOffsetsTableHeader(MCSection *Section);
|
||||||
|
|
||||||
/// \brief Emit all of the units to the section listed with the given
|
/// \brief Emit all of the units to the section listed with the given
|
||||||
/// abbreviation section.
|
/// abbreviation section.
|
||||||
void emitUnits(bool UseOffsets);
|
void emitUnits(bool UseOffsets);
|
||||||
|
@ -85,12 +92,20 @@ public:
|
||||||
/// \brief Emit a set of abbreviations to the specific section.
|
/// \brief Emit a set of abbreviations to the specific section.
|
||||||
void emitAbbrevs(MCSection *);
|
void emitAbbrevs(MCSection *);
|
||||||
|
|
||||||
/// \brief Emit all of the strings to the section given.
|
/// Emit all of the strings to the section given. If OffsetSection is
|
||||||
void emitStrings(MCSection *StrSection, MCSection *OffsetSection = nullptr);
|
/// non-null, emit a table of string offsets to it. If UseRelativeOffsets
|
||||||
|
/// is false, emit absolute offsets to the strings. Otherwise, emit
|
||||||
|
/// relocatable references to the strings if they are supported by the target.
|
||||||
|
void emitStrings(MCSection *StrSection, MCSection *OffsetSection = nullptr,
|
||||||
|
bool UseRelativeOffsets = false);
|
||||||
|
|
||||||
/// \brief Returns the string pool.
|
/// \brief Returns the string pool.
|
||||||
DwarfStringPool &getStringPool() { return StrPool; }
|
DwarfStringPool &getStringPool() { return StrPool; }
|
||||||
|
|
||||||
|
MCSymbol *getStringOffsetsStartSym() const { return StringOffsetsStartSym; }
|
||||||
|
|
||||||
|
void setStringOffsetsStartSym(MCSymbol *Sym) { StringOffsetsStartSym = Sym; }
|
||||||
|
|
||||||
/// \returns false if the variable was merged with a previous one.
|
/// \returns false if the variable was merged with a previous one.
|
||||||
bool addScopeVariable(LexicalScope *LS, DbgVariable *Var);
|
bool addScopeVariable(LexicalScope *LS, DbgVariable *Var);
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,
|
||||||
}
|
}
|
||||||
|
|
||||||
void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
|
void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
|
||||||
MCSection *OffsetSection) {
|
MCSection *OffsetSection, bool UseRelativeOffsets) {
|
||||||
if (Pool.empty())
|
if (Pool.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -74,6 +74,9 @@ void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
|
||||||
Asm.OutStreamer->SwitchSection(OffsetSection);
|
Asm.OutStreamer->SwitchSection(OffsetSection);
|
||||||
unsigned size = 4; // FIXME: DWARF64 is 8.
|
unsigned size = 4; // FIXME: DWARF64 is 8.
|
||||||
for (const auto &Entry : Entries)
|
for (const auto &Entry : Entries)
|
||||||
Asm.OutStreamer->EmitIntValue(Entry->getValue().Offset, size);
|
if (UseRelativeOffsets)
|
||||||
|
Asm.emitDwarfStringOffset(Entry->getValue());
|
||||||
|
else
|
||||||
|
Asm.OutStreamer->EmitIntValue(Entry->getValue().Offset, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,10 +37,13 @@ public:
|
||||||
DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm, StringRef Prefix);
|
DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm, StringRef Prefix);
|
||||||
|
|
||||||
void emit(AsmPrinter &Asm, MCSection *StrSection,
|
void emit(AsmPrinter &Asm, MCSection *StrSection,
|
||||||
MCSection *OffsetSection = nullptr);
|
MCSection *OffsetSection = nullptr,
|
||||||
|
bool UseRelativeOffsets = false);
|
||||||
|
|
||||||
bool empty() const { return Pool.empty(); }
|
bool empty() const { return Pool.empty(); }
|
||||||
|
|
||||||
|
unsigned size() const { return Pool.size(); }
|
||||||
|
|
||||||
/// Get a reference to an entry in the string pool.
|
/// Get a reference to an entry in the string pool.
|
||||||
EntryRef getEntry(AsmPrinter &Asm, StringRef Str);
|
EntryRef getEntry(AsmPrinter &Asm, StringRef Str);
|
||||||
};
|
};
|
||||||
|
|
|
@ -241,9 +241,22 @@ void DwarfUnit::addSInt(DIELoc &Die, Optional<dwarf::Form> Form,
|
||||||
|
|
||||||
void DwarfUnit::addString(DIE &Die, dwarf::Attribute Attribute,
|
void DwarfUnit::addString(DIE &Die, dwarf::Attribute Attribute,
|
||||||
StringRef String) {
|
StringRef String) {
|
||||||
Die.addValue(DIEValueAllocator, Attribute,
|
auto StringPoolEntry = DU->getStringPool().getEntry(*Asm, String);
|
||||||
isDwoUnit() ? dwarf::DW_FORM_GNU_str_index : dwarf::DW_FORM_strp,
|
dwarf::Form IxForm =
|
||||||
DIEString(DU->getStringPool().getEntry(*Asm, String)));
|
isDwoUnit() ? dwarf::DW_FORM_GNU_str_index : dwarf::DW_FORM_strp;
|
||||||
|
// For DWARF v5 and beyond, use the smallest strx? form possible.
|
||||||
|
if (useSegmentedStringOffsetsTable()) {
|
||||||
|
IxForm = dwarf::DW_FORM_strx1;
|
||||||
|
unsigned Index = StringPoolEntry.getIndex();
|
||||||
|
if (Index > 0xffffff)
|
||||||
|
IxForm = dwarf::DW_FORM_strx4;
|
||||||
|
else if (Index > 0xffff)
|
||||||
|
IxForm = dwarf::DW_FORM_strx3;
|
||||||
|
else if (Index > 0xff)
|
||||||
|
IxForm = dwarf::DW_FORM_strx2;
|
||||||
|
}
|
||||||
|
Die.addValue(DIEValueAllocator, Attribute, IxForm,
|
||||||
|
DIEString(StringPoolEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
DIEValueList::value_iterator DwarfUnit::addLabel(DIEValueList &Die,
|
DIEValueList::value_iterator DwarfUnit::addLabel(DIEValueList &Die,
|
||||||
|
@ -1660,3 +1673,10 @@ const MCSymbol *DwarfUnit::getCrossSectionRelativeBaseAddress() const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return getSection()->getBeginSymbol();
|
return getSection()->getBeginSymbol();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DwarfUnit::addStringOffsetsStart() {
|
||||||
|
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
|
||||||
|
addSectionLabel(getUnitDie(), dwarf::DW_AT_str_offsets_base,
|
||||||
|
DU->getStringOffsetsStartSym(),
|
||||||
|
TLOF.getDwarfStrOffSection()->getBeginSymbol());
|
||||||
|
}
|
||||||
|
|
|
@ -273,6 +273,10 @@ public:
|
||||||
/// call insertDIE if MD is not null.
|
/// call insertDIE if MD is not null.
|
||||||
DIE &createAndAddDIE(unsigned Tag, DIE &Parent, const DINode *N = nullptr);
|
DIE &createAndAddDIE(unsigned Tag, DIE &Parent, const DINode *N = nullptr);
|
||||||
|
|
||||||
|
bool useSegmentedStringOffsetsTable() const {
|
||||||
|
return DD->useSegmentedStringOffsetsTable();
|
||||||
|
}
|
||||||
|
|
||||||
/// Compute the size of a header for this unit, not including the initial
|
/// Compute the size of a header for this unit, not including the initial
|
||||||
/// length field.
|
/// length field.
|
||||||
virtual unsigned getHeaderSize() const {
|
virtual unsigned getHeaderSize() const {
|
||||||
|
@ -286,6 +290,9 @@ public:
|
||||||
/// Emit the header for this unit, not including the initial length field.
|
/// Emit the header for this unit, not including the initial length field.
|
||||||
virtual void emitHeader(bool UseOffsets) = 0;
|
virtual void emitHeader(bool UseOffsets) = 0;
|
||||||
|
|
||||||
|
/// Add the DW_AT_str_offsets_base attribute to the unit DIE.
|
||||||
|
void addStringOffsetsStart();
|
||||||
|
|
||||||
virtual DwarfCompileUnit &getCU() = 0;
|
virtual DwarfCompileUnit &getCU() = 0;
|
||||||
|
|
||||||
void constructTypeDIE(DIE &Buffer, const DICompositeType *CTy);
|
void constructTypeDIE(DIE &Buffer, const DICompositeType *CTy);
|
||||||
|
|
|
@ -0,0 +1,293 @@
|
||||||
|
; REQUIRES: object-emission
|
||||||
|
; RUN: %llc_dwarf -filetype=obj < %s | llvm-dwarfdump -all -show-form -v - \
|
||||||
|
; RUN: | FileCheck %s
|
||||||
|
;
|
||||||
|
; Generated from the following source with clang -S -emit-llvm -gdwarf-5.
|
||||||
|
;
|
||||||
|
; enum E {
|
||||||
|
; econst1,
|
||||||
|
; econst2,
|
||||||
|
; ...
|
||||||
|
; econst254
|
||||||
|
; } glob;
|
||||||
|
;
|
||||||
|
; This test verifies that we generate DW_FORM_strx2 for indexed strings properly.
|
||||||
|
; Check that the first usage of DW_FORM_strx2 is with index 256.
|
||||||
|
;
|
||||||
|
; CHECK: .debug_info contents:
|
||||||
|
; CHECK-NOT: DW_FORM_strx2
|
||||||
|
; CHECK: DW_AT_name [DW_FORM_strx2] ( indexed (00000100) string =
|
||||||
|
|
||||||
|
; ModuleID = 'enum.cpp'
|
||||||
|
source_filename = "enum.cpp"
|
||||||
|
|
||||||
|
@glob = global i32 0, align 4, !dbg !0
|
||||||
|
|
||||||
|
!llvm.dbg.cu = !{!2}
|
||||||
|
!llvm.module.flags = !{!260, !261, !262}
|
||||||
|
!llvm.ident = !{!263}
|
||||||
|
|
||||||
|
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
|
||||||
|
!1 = distinct !DIGlobalVariable(name: "glob", scope: !2, file: !3, line: 255, type: !5, isLocal: false, isDefinition: true)
|
||||||
|
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 (trunk 322415)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !259)
|
||||||
|
!3 = !DIFile(filename: "enum.cpp", directory: "/home/test", checksumkind: CSK_MD5, checksum: "8965080a8027790e641e30c7762c53a0")
|
||||||
|
!4 = !{!5}
|
||||||
|
!5 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E", file: !3, line: 1, size: 32, elements: !6, identifier: "_ZTS1E")
|
||||||
|
!6 = !{!7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40, !41, !42, !43, !44, !45, !46, !47, !48, !49, !50, !51, !52, !53, !54, !55, !56, !57, !58, !59, !60, !61, !62, !63, !64, !65, !66, !67, !68, !69, !70, !71, !72, !73, !74, !75, !76, !77, !78, !79, !80, !81, !82, !83, !84, !85, !86, !87, !88, !89, !90, !91, !92, !93, !94, !95, !96, !97, !98, !99, !100, !101, !102, !103, !104, !105, !106, !107, !108, !109, !110, !111, !112, !113, !114, !115, !116, !117, !118, !119, !120, !121, !122, !123, !124, !125, !126, !127, !128, !129, !130, !131, !132, !133, !134, !135, !136, !137, !138, !139, !140, !141, !142, !143, !144, !145, !146, !147, !148, !149, !150, !151, !152, !153, !154, !155, !156, !157, !158, !159, !160, !161, !162, !163, !164, !165, !166, !167, !168, !169, !170, !171, !172, !173, !174, !175, !176, !177, !178, !179, !180, !181, !182, !183, !184, !185, !186, !187, !188, !189, !190, !191, !192, !193, !194, !195, !196, !197, !198, !199, !200, !201, !202, !203, !204, !205, !206, !207, !208, !209, !210, !211, !212, !213, !214, !215, !216, !217, !218, !219, !220, !221, !222, !223, !224, !225, !226, !227, !228, !229, !230, !231, !232, !233, !234, !235, !236, !237, !238, !239, !240, !241, !242, !243, !244, !245, !246, !247, !248, !249, !250, !251, !252, !253, !254, !255, !256, !257, !258}
|
||||||
|
!7 = !DIEnumerator(name: "econst1", value: 0)
|
||||||
|
!8 = !DIEnumerator(name: "econst2", value: 1)
|
||||||
|
!9 = !DIEnumerator(name: "econst3", value: 2)
|
||||||
|
!10 = !DIEnumerator(name: "econst4", value: 3)
|
||||||
|
!11 = !DIEnumerator(name: "econst5", value: 4)
|
||||||
|
!12 = !DIEnumerator(name: "econst6", value: 5)
|
||||||
|
!13 = !DIEnumerator(name: "econst7", value: 6)
|
||||||
|
!14 = !DIEnumerator(name: "econst8", value: 7)
|
||||||
|
!15 = !DIEnumerator(name: "econst9", value: 8)
|
||||||
|
!16 = !DIEnumerator(name: "econst10", value: 9)
|
||||||
|
!17 = !DIEnumerator(name: "econst11", value: 10)
|
||||||
|
!18 = !DIEnumerator(name: "econst12", value: 11)
|
||||||
|
!19 = !DIEnumerator(name: "econst13", value: 12)
|
||||||
|
!20 = !DIEnumerator(name: "econst14", value: 13)
|
||||||
|
!21 = !DIEnumerator(name: "econst15", value: 14)
|
||||||
|
!22 = !DIEnumerator(name: "econst16", value: 15)
|
||||||
|
!23 = !DIEnumerator(name: "econst17", value: 16)
|
||||||
|
!24 = !DIEnumerator(name: "econst18", value: 17)
|
||||||
|
!25 = !DIEnumerator(name: "econst19", value: 18)
|
||||||
|
!26 = !DIEnumerator(name: "econst20", value: 19)
|
||||||
|
!27 = !DIEnumerator(name: "econst21", value: 20)
|
||||||
|
!28 = !DIEnumerator(name: "econst22", value: 21)
|
||||||
|
!29 = !DIEnumerator(name: "econst23", value: 22)
|
||||||
|
!30 = !DIEnumerator(name: "econst24", value: 23)
|
||||||
|
!31 = !DIEnumerator(name: "econst25", value: 24)
|
||||||
|
!32 = !DIEnumerator(name: "econst26", value: 25)
|
||||||
|
!33 = !DIEnumerator(name: "econst27", value: 26)
|
||||||
|
!34 = !DIEnumerator(name: "econst28", value: 27)
|
||||||
|
!35 = !DIEnumerator(name: "econst29", value: 28)
|
||||||
|
!36 = !DIEnumerator(name: "econst30", value: 29)
|
||||||
|
!37 = !DIEnumerator(name: "econst31", value: 30)
|
||||||
|
!38 = !DIEnumerator(name: "econst32", value: 31)
|
||||||
|
!39 = !DIEnumerator(name: "econst33", value: 32)
|
||||||
|
!40 = !DIEnumerator(name: "econst34", value: 33)
|
||||||
|
!41 = !DIEnumerator(name: "econst35", value: 34)
|
||||||
|
!42 = !DIEnumerator(name: "econst36", value: 35)
|
||||||
|
!43 = !DIEnumerator(name: "econst37", value: 36)
|
||||||
|
!44 = !DIEnumerator(name: "econst38", value: 37)
|
||||||
|
!45 = !DIEnumerator(name: "econst39", value: 38)
|
||||||
|
!46 = !DIEnumerator(name: "econst40", value: 39)
|
||||||
|
!47 = !DIEnumerator(name: "econst41", value: 40)
|
||||||
|
!48 = !DIEnumerator(name: "econst42", value: 41)
|
||||||
|
!49 = !DIEnumerator(name: "econst43", value: 42)
|
||||||
|
!50 = !DIEnumerator(name: "econst44", value: 43)
|
||||||
|
!51 = !DIEnumerator(name: "econst45", value: 44)
|
||||||
|
!52 = !DIEnumerator(name: "econst46", value: 45)
|
||||||
|
!53 = !DIEnumerator(name: "econst47", value: 46)
|
||||||
|
!54 = !DIEnumerator(name: "econst48", value: 47)
|
||||||
|
!55 = !DIEnumerator(name: "econst49", value: 48)
|
||||||
|
!56 = !DIEnumerator(name: "econst50", value: 49)
|
||||||
|
!57 = !DIEnumerator(name: "econst51", value: 50)
|
||||||
|
!58 = !DIEnumerator(name: "econst52", value: 51)
|
||||||
|
!59 = !DIEnumerator(name: "econst53", value: 52)
|
||||||
|
!60 = !DIEnumerator(name: "econst54", value: 53)
|
||||||
|
!61 = !DIEnumerator(name: "econst55", value: 54)
|
||||||
|
!62 = !DIEnumerator(name: "econst56", value: 55)
|
||||||
|
!63 = !DIEnumerator(name: "econst57", value: 56)
|
||||||
|
!64 = !DIEnumerator(name: "econst58", value: 57)
|
||||||
|
!65 = !DIEnumerator(name: "econst59", value: 58)
|
||||||
|
!66 = !DIEnumerator(name: "econst60", value: 59)
|
||||||
|
!67 = !DIEnumerator(name: "econst61", value: 60)
|
||||||
|
!68 = !DIEnumerator(name: "econst62", value: 61)
|
||||||
|
!69 = !DIEnumerator(name: "econst63", value: 62)
|
||||||
|
!70 = !DIEnumerator(name: "econst64", value: 63)
|
||||||
|
!71 = !DIEnumerator(name: "econst65", value: 64)
|
||||||
|
!72 = !DIEnumerator(name: "econst66", value: 65)
|
||||||
|
!73 = !DIEnumerator(name: "econst67", value: 66)
|
||||||
|
!74 = !DIEnumerator(name: "econst68", value: 67)
|
||||||
|
!75 = !DIEnumerator(name: "econst69", value: 68)
|
||||||
|
!76 = !DIEnumerator(name: "econst70", value: 69)
|
||||||
|
!77 = !DIEnumerator(name: "econst71", value: 70)
|
||||||
|
!78 = !DIEnumerator(name: "econst72", value: 71)
|
||||||
|
!79 = !DIEnumerator(name: "econst73", value: 72)
|
||||||
|
!80 = !DIEnumerator(name: "econst74", value: 73)
|
||||||
|
!81 = !DIEnumerator(name: "econst75", value: 74)
|
||||||
|
!82 = !DIEnumerator(name: "econst76", value: 75)
|
||||||
|
!83 = !DIEnumerator(name: "econst77", value: 76)
|
||||||
|
!84 = !DIEnumerator(name: "econst78", value: 77)
|
||||||
|
!85 = !DIEnumerator(name: "econst79", value: 78)
|
||||||
|
!86 = !DIEnumerator(name: "econst80", value: 79)
|
||||||
|
!87 = !DIEnumerator(name: "econst81", value: 80)
|
||||||
|
!88 = !DIEnumerator(name: "econst82", value: 81)
|
||||||
|
!89 = !DIEnumerator(name: "econst83", value: 82)
|
||||||
|
!90 = !DIEnumerator(name: "econst84", value: 83)
|
||||||
|
!91 = !DIEnumerator(name: "econst85", value: 84)
|
||||||
|
!92 = !DIEnumerator(name: "econst86", value: 85)
|
||||||
|
!93 = !DIEnumerator(name: "econst87", value: 86)
|
||||||
|
!94 = !DIEnumerator(name: "econst88", value: 87)
|
||||||
|
!95 = !DIEnumerator(name: "econst89", value: 88)
|
||||||
|
!96 = !DIEnumerator(name: "econst90", value: 89)
|
||||||
|
!97 = !DIEnumerator(name: "econst91", value: 90)
|
||||||
|
!98 = !DIEnumerator(name: "econst92", value: 91)
|
||||||
|
!99 = !DIEnumerator(name: "econst93", value: 92)
|
||||||
|
!100 = !DIEnumerator(name: "econst94", value: 93)
|
||||||
|
!101 = !DIEnumerator(name: "econst95", value: 94)
|
||||||
|
!102 = !DIEnumerator(name: "econst96", value: 95)
|
||||||
|
!103 = !DIEnumerator(name: "econst97", value: 96)
|
||||||
|
!104 = !DIEnumerator(name: "econst98", value: 97)
|
||||||
|
!105 = !DIEnumerator(name: "econst99", value: 98)
|
||||||
|
!106 = !DIEnumerator(name: "econst100", value: 99)
|
||||||
|
!107 = !DIEnumerator(name: "econst101", value: 100)
|
||||||
|
!108 = !DIEnumerator(name: "econst102", value: 101)
|
||||||
|
!109 = !DIEnumerator(name: "econst103", value: 102)
|
||||||
|
!110 = !DIEnumerator(name: "econst104", value: 103)
|
||||||
|
!111 = !DIEnumerator(name: "econst105", value: 104)
|
||||||
|
!112 = !DIEnumerator(name: "econst106", value: 105)
|
||||||
|
!113 = !DIEnumerator(name: "econst107", value: 106)
|
||||||
|
!114 = !DIEnumerator(name: "econst108", value: 107)
|
||||||
|
!115 = !DIEnumerator(name: "econst109", value: 108)
|
||||||
|
!116 = !DIEnumerator(name: "econst110", value: 109)
|
||||||
|
!117 = !DIEnumerator(name: "econst111", value: 110)
|
||||||
|
!118 = !DIEnumerator(name: "econst112", value: 111)
|
||||||
|
!119 = !DIEnumerator(name: "econst113", value: 112)
|
||||||
|
!120 = !DIEnumerator(name: "econst114", value: 113)
|
||||||
|
!121 = !DIEnumerator(name: "econst115", value: 114)
|
||||||
|
!122 = !DIEnumerator(name: "econst116", value: 115)
|
||||||
|
!123 = !DIEnumerator(name: "econst117", value: 116)
|
||||||
|
!124 = !DIEnumerator(name: "econst118", value: 117)
|
||||||
|
!125 = !DIEnumerator(name: "econst119", value: 118)
|
||||||
|
!126 = !DIEnumerator(name: "econst120", value: 119)
|
||||||
|
!127 = !DIEnumerator(name: "econst121", value: 120)
|
||||||
|
!128 = !DIEnumerator(name: "econst122", value: 121)
|
||||||
|
!129 = !DIEnumerator(name: "econst123", value: 122)
|
||||||
|
!130 = !DIEnumerator(name: "econst124", value: 123)
|
||||||
|
!131 = !DIEnumerator(name: "econst125", value: 124)
|
||||||
|
!132 = !DIEnumerator(name: "econst126", value: 125)
|
||||||
|
!133 = !DIEnumerator(name: "econst127", value: 126)
|
||||||
|
!134 = !DIEnumerator(name: "econst128", value: 127)
|
||||||
|
!135 = !DIEnumerator(name: "econst129", value: 128)
|
||||||
|
!136 = !DIEnumerator(name: "econst130", value: 129)
|
||||||
|
!137 = !DIEnumerator(name: "econst131", value: 130)
|
||||||
|
!138 = !DIEnumerator(name: "econst132", value: 131)
|
||||||
|
!139 = !DIEnumerator(name: "econst133", value: 132)
|
||||||
|
!140 = !DIEnumerator(name: "econst134", value: 133)
|
||||||
|
!141 = !DIEnumerator(name: "econst135", value: 134)
|
||||||
|
!142 = !DIEnumerator(name: "econst136", value: 135)
|
||||||
|
!143 = !DIEnumerator(name: "econst137", value: 136)
|
||||||
|
!144 = !DIEnumerator(name: "econst138", value: 137)
|
||||||
|
!145 = !DIEnumerator(name: "econst139", value: 138)
|
||||||
|
!146 = !DIEnumerator(name: "econst140", value: 139)
|
||||||
|
!147 = !DIEnumerator(name: "econst141", value: 140)
|
||||||
|
!148 = !DIEnumerator(name: "econst142", value: 141)
|
||||||
|
!149 = !DIEnumerator(name: "econst143", value: 142)
|
||||||
|
!150 = !DIEnumerator(name: "econst144", value: 143)
|
||||||
|
!151 = !DIEnumerator(name: "econst145", value: 144)
|
||||||
|
!152 = !DIEnumerator(name: "econst146", value: 145)
|
||||||
|
!153 = !DIEnumerator(name: "econst147", value: 146)
|
||||||
|
!154 = !DIEnumerator(name: "econst148", value: 147)
|
||||||
|
!155 = !DIEnumerator(name: "econst149", value: 148)
|
||||||
|
!156 = !DIEnumerator(name: "econst150", value: 149)
|
||||||
|
!157 = !DIEnumerator(name: "econst151", value: 150)
|
||||||
|
!158 = !DIEnumerator(name: "econst152", value: 151)
|
||||||
|
!159 = !DIEnumerator(name: "econst153", value: 152)
|
||||||
|
!160 = !DIEnumerator(name: "econst154", value: 153)
|
||||||
|
!161 = !DIEnumerator(name: "econst155", value: 154)
|
||||||
|
!162 = !DIEnumerator(name: "econst156", value: 155)
|
||||||
|
!163 = !DIEnumerator(name: "econst157", value: 156)
|
||||||
|
!164 = !DIEnumerator(name: "econst158", value: 157)
|
||||||
|
!165 = !DIEnumerator(name: "econst159", value: 158)
|
||||||
|
!166 = !DIEnumerator(name: "econst160", value: 159)
|
||||||
|
!167 = !DIEnumerator(name: "econst161", value: 160)
|
||||||
|
!168 = !DIEnumerator(name: "econst162", value: 161)
|
||||||
|
!169 = !DIEnumerator(name: "econst163", value: 162)
|
||||||
|
!170 = !DIEnumerator(name: "econst164", value: 163)
|
||||||
|
!171 = !DIEnumerator(name: "econst165", value: 164)
|
||||||
|
!172 = !DIEnumerator(name: "econst166", value: 165)
|
||||||
|
!173 = !DIEnumerator(name: "econst167", value: 166)
|
||||||
|
!174 = !DIEnumerator(name: "econst168", value: 167)
|
||||||
|
!175 = !DIEnumerator(name: "econst169", value: 168)
|
||||||
|
!176 = !DIEnumerator(name: "econst170", value: 169)
|
||||||
|
!177 = !DIEnumerator(name: "econst171", value: 170)
|
||||||
|
!178 = !DIEnumerator(name: "econst172", value: 171)
|
||||||
|
!179 = !DIEnumerator(name: "econst173", value: 172)
|
||||||
|
!180 = !DIEnumerator(name: "econst174", value: 173)
|
||||||
|
!181 = !DIEnumerator(name: "econst175", value: 174)
|
||||||
|
!182 = !DIEnumerator(name: "econst176", value: 175)
|
||||||
|
!183 = !DIEnumerator(name: "econst177", value: 176)
|
||||||
|
!184 = !DIEnumerator(name: "econst178", value: 177)
|
||||||
|
!185 = !DIEnumerator(name: "econst179", value: 178)
|
||||||
|
!186 = !DIEnumerator(name: "econst180", value: 179)
|
||||||
|
!187 = !DIEnumerator(name: "econst181", value: 180)
|
||||||
|
!188 = !DIEnumerator(name: "econst182", value: 181)
|
||||||
|
!189 = !DIEnumerator(name: "econst183", value: 182)
|
||||||
|
!190 = !DIEnumerator(name: "econst184", value: 183)
|
||||||
|
!191 = !DIEnumerator(name: "econst185", value: 184)
|
||||||
|
!192 = !DIEnumerator(name: "econst186", value: 185)
|
||||||
|
!193 = !DIEnumerator(name: "econst187", value: 186)
|
||||||
|
!194 = !DIEnumerator(name: "econst188", value: 187)
|
||||||
|
!195 = !DIEnumerator(name: "econst189", value: 188)
|
||||||
|
!196 = !DIEnumerator(name: "econst190", value: 189)
|
||||||
|
!197 = !DIEnumerator(name: "econst191", value: 190)
|
||||||
|
!198 = !DIEnumerator(name: "econst192", value: 191)
|
||||||
|
!199 = !DIEnumerator(name: "econst193", value: 192)
|
||||||
|
!200 = !DIEnumerator(name: "econst194", value: 193)
|
||||||
|
!201 = !DIEnumerator(name: "econst195", value: 194)
|
||||||
|
!202 = !DIEnumerator(name: "econst196", value: 195)
|
||||||
|
!203 = !DIEnumerator(name: "econst197", value: 196)
|
||||||
|
!204 = !DIEnumerator(name: "econst198", value: 197)
|
||||||
|
!205 = !DIEnumerator(name: "econst199", value: 198)
|
||||||
|
!206 = !DIEnumerator(name: "econst200", value: 199)
|
||||||
|
!207 = !DIEnumerator(name: "econst201", value: 200)
|
||||||
|
!208 = !DIEnumerator(name: "econst202", value: 201)
|
||||||
|
!209 = !DIEnumerator(name: "econst203", value: 202)
|
||||||
|
!210 = !DIEnumerator(name: "econst204", value: 203)
|
||||||
|
!211 = !DIEnumerator(name: "econst205", value: 204)
|
||||||
|
!212 = !DIEnumerator(name: "econst206", value: 205)
|
||||||
|
!213 = !DIEnumerator(name: "econst207", value: 206)
|
||||||
|
!214 = !DIEnumerator(name: "econst208", value: 207)
|
||||||
|
!215 = !DIEnumerator(name: "econst209", value: 208)
|
||||||
|
!216 = !DIEnumerator(name: "econst210", value: 209)
|
||||||
|
!217 = !DIEnumerator(name: "econst211", value: 210)
|
||||||
|
!218 = !DIEnumerator(name: "econst212", value: 211)
|
||||||
|
!219 = !DIEnumerator(name: "econst213", value: 212)
|
||||||
|
!220 = !DIEnumerator(name: "econst214", value: 213)
|
||||||
|
!221 = !DIEnumerator(name: "econst215", value: 214)
|
||||||
|
!222 = !DIEnumerator(name: "econst216", value: 215)
|
||||||
|
!223 = !DIEnumerator(name: "econst217", value: 216)
|
||||||
|
!224 = !DIEnumerator(name: "econst218", value: 217)
|
||||||
|
!225 = !DIEnumerator(name: "econst219", value: 218)
|
||||||
|
!226 = !DIEnumerator(name: "econst220", value: 219)
|
||||||
|
!227 = !DIEnumerator(name: "econst221", value: 220)
|
||||||
|
!228 = !DIEnumerator(name: "econst222", value: 221)
|
||||||
|
!229 = !DIEnumerator(name: "econst223", value: 222)
|
||||||
|
!230 = !DIEnumerator(name: "econst224", value: 223)
|
||||||
|
!231 = !DIEnumerator(name: "econst225", value: 224)
|
||||||
|
!232 = !DIEnumerator(name: "econst226", value: 225)
|
||||||
|
!233 = !DIEnumerator(name: "econst227", value: 226)
|
||||||
|
!234 = !DIEnumerator(name: "econst228", value: 227)
|
||||||
|
!235 = !DIEnumerator(name: "econst229", value: 228)
|
||||||
|
!236 = !DIEnumerator(name: "econst230", value: 229)
|
||||||
|
!237 = !DIEnumerator(name: "econst231", value: 230)
|
||||||
|
!238 = !DIEnumerator(name: "econst232", value: 231)
|
||||||
|
!239 = !DIEnumerator(name: "econst233", value: 232)
|
||||||
|
!240 = !DIEnumerator(name: "econst234", value: 233)
|
||||||
|
!241 = !DIEnumerator(name: "econst235", value: 234)
|
||||||
|
!242 = !DIEnumerator(name: "econst236", value: 235)
|
||||||
|
!243 = !DIEnumerator(name: "econst237", value: 236)
|
||||||
|
!244 = !DIEnumerator(name: "econst238", value: 237)
|
||||||
|
!245 = !DIEnumerator(name: "econst239", value: 238)
|
||||||
|
!246 = !DIEnumerator(name: "econst240", value: 239)
|
||||||
|
!247 = !DIEnumerator(name: "econst241", value: 240)
|
||||||
|
!248 = !DIEnumerator(name: "econst242", value: 241)
|
||||||
|
!249 = !DIEnumerator(name: "econst243", value: 242)
|
||||||
|
!250 = !DIEnumerator(name: "econst244", value: 243)
|
||||||
|
!251 = !DIEnumerator(name: "econst245", value: 244)
|
||||||
|
!252 = !DIEnumerator(name: "econst246", value: 245)
|
||||||
|
!253 = !DIEnumerator(name: "econst247", value: 246)
|
||||||
|
!254 = !DIEnumerator(name: "econst248", value: 247)
|
||||||
|
!255 = !DIEnumerator(name: "econst249", value: 248)
|
||||||
|
!256 = !DIEnumerator(name: "econst250", value: 249)
|
||||||
|
!257 = !DIEnumerator(name: "econst251", value: 250)
|
||||||
|
!258 = !DIEnumerator(name: "econst252", value: 251)
|
||||||
|
!259 = !{!0}
|
||||||
|
!260 = !{i32 2, !"Dwarf Version", i32 5}
|
||||||
|
!261 = !{i32 2, !"Debug Info Version", i32 3}
|
||||||
|
!262 = !{i32 1, !"wchar_size", i32 4}
|
||||||
|
!263 = !{!"clang version 7.0.0 (trunk 322415)"}
|
|
@ -0,0 +1,159 @@
|
||||||
|
; REQUIRES: object-emission
|
||||||
|
; RUN: %llc_dwarf -filetype=obj < %s | llvm-dwarfdump -v - | FileCheck --check-prefix=DEFAULT \
|
||||||
|
; RUN: --check-prefix=BOTH %s
|
||||||
|
; RUN: %llc_dwarf -filetype=obj -generate-type-units < %s | llvm-dwarfdump -v - | \
|
||||||
|
; RUN: FileCheck --check-prefix=TYPEUNITS --check-prefix=BOTH %s
|
||||||
|
;
|
||||||
|
; Check that we generate the DWARF v5 string offsets section correctly when we
|
||||||
|
; have multiple compile and type units. All units share one contribution to
|
||||||
|
; the string offsets section.
|
||||||
|
;
|
||||||
|
; Constructed from the following sources with
|
||||||
|
; clang -gdwarf-5 -emit-llvm -S a.cpp
|
||||||
|
; clang -gdwarf-5 -emit-llvm -S b.cpp
|
||||||
|
; clang -gdwarf-5 -emit-llvm -S c.cpp
|
||||||
|
; llvm-link a.ll b.ll c.ll -o test.bc
|
||||||
|
; llvm-dis test.bc -o test.ll
|
||||||
|
;
|
||||||
|
; a.cpp:
|
||||||
|
; enum E1 {a, b, c};
|
||||||
|
; E1 glob1;
|
||||||
|
;
|
||||||
|
; b.cpp:
|
||||||
|
; enum E2 {d, e, f};
|
||||||
|
; E2 glob2;
|
||||||
|
;
|
||||||
|
; c.cpp:
|
||||||
|
; enum E3 {g, h, i};
|
||||||
|
; E3 glob3;
|
||||||
|
;
|
||||||
|
; Check that all 3 compile units have the correct DW_AT_str_offsets_base attributes
|
||||||
|
; with the correct offsets. Check that strings referenced by compile units 2 and 3
|
||||||
|
; are displayed correctly.
|
||||||
|
;
|
||||||
|
; CU 1
|
||||||
|
; BOTH: .debug_info contents:
|
||||||
|
; BOTH-NOT: .contents:
|
||||||
|
; BOTH: DW_TAG_compile_unit
|
||||||
|
; BOTH-NOT: {{DW_TAG|NULL}}
|
||||||
|
; BOTH: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x[[CU1_STROFF:[0-9a-f]+]])
|
||||||
|
;
|
||||||
|
; CU 2
|
||||||
|
; BOTH-NOT: contents:
|
||||||
|
; BOTH: DW_TAG_compile_unit
|
||||||
|
; BOTH-NOT: {{DW_TAG|NULL}}
|
||||||
|
; BOTH: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x[[CU1_STROFF]])
|
||||||
|
; BOTH-NOT: NULL
|
||||||
|
; BOTH: DW_TAG_variable
|
||||||
|
; BOTH-NOT: {{DW_TAG|NULL}}
|
||||||
|
; BOTH: DW_AT_name [DW_FORM_strx1] ( indexed (00000009) string = "glob2")
|
||||||
|
;
|
||||||
|
; CU 3
|
||||||
|
; BOTH-NOT: contents:
|
||||||
|
; BOTH: DW_TAG_compile_unit
|
||||||
|
; BOTH-NOT: {{DW_TAG|NULL}}
|
||||||
|
; BOTH: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x[[CU1_STROFF]])
|
||||||
|
; BOTH-NOT: NULL
|
||||||
|
; BOTH: DW_TAG_variable
|
||||||
|
; BOTH-NOT: {{DW_TAG|NULL}}
|
||||||
|
; BOTH: DW_AT_name [DW_FORM_strx1] ( indexed (0000000f) string = "glob3")
|
||||||
|
;
|
||||||
|
; Verify that all 3 type units have the proper DW_AT_str_offsets_base attribute.
|
||||||
|
; TYPEUNITS: .debug_types contents:
|
||||||
|
; TYPEUNITS-NOT: contents:
|
||||||
|
; TYPEUNITS: DW_TAG_type_unit
|
||||||
|
; TYPEUNITS-NOT: {{DW_TAG|NULL}}
|
||||||
|
; TYPEUNITS: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x[[CU1_STROFF]])
|
||||||
|
; TYPEUNITS-NOT: NULL
|
||||||
|
; TYPEUNITS: DW_TAG_enumerator
|
||||||
|
; TYPEUNITS-NOT: NULL
|
||||||
|
; TYPEUNITS: DW_TAG_enumerator
|
||||||
|
; TYPEUNITS-NOT: {{DW_TAG|NULL}}
|
||||||
|
; TYPEUNITS: DW_AT_name [DW_FORM_strx1] ( indexed (00000005) string = "b")
|
||||||
|
; TYPEUNITS-NOT: contents:
|
||||||
|
; TYPEUNITS: DW_TAG_type_unit
|
||||||
|
; TYPEUNITS-NOT: {{DW_TAG|NULL}}
|
||||||
|
; TYPEUNITS: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x[[CU1_STROFF]])
|
||||||
|
; TYPEUNITS-NOT: NULL
|
||||||
|
; TYPEUNITS: DW_TAG_enumeration_type
|
||||||
|
; TYPEUNITS: DW_AT_name [DW_FORM_strx1] ( indexed (0000000d) string = "E2")
|
||||||
|
; TYPEUNITS-NOT: contents:
|
||||||
|
; TYPEUNITS: DW_TAG_type_unit
|
||||||
|
; TYPEUNITS-NOT: {{DW_TAG|NULL}}
|
||||||
|
; TYPEUNITS: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x[[CU1_STROFF]])
|
||||||
|
; TYPEUNITS-NOT: NULL
|
||||||
|
; TYPEUNITS: DW_TAG_enumeration_type
|
||||||
|
; TYPEUNITS: DW_AT_name [DW_FORM_strx1] ( indexed (00000013) string = "E3")
|
||||||
|
;
|
||||||
|
; Extract the offset of a string to verify that it is referenced in the string
|
||||||
|
; offsets section.
|
||||||
|
; BOTH: .debug_str contents:
|
||||||
|
; BOTH-NOT: contents:
|
||||||
|
; BOTH: 0x[[GLOB2OFF:[0-9a-f]+]]: "glob2"
|
||||||
|
;
|
||||||
|
; Check the .debug_str_offsets section header and make sure the referenced string
|
||||||
|
; has the correct offset.
|
||||||
|
; BOTH: .debug_str_offsets contents:
|
||||||
|
; BOTH-NEXT: 0x00000000: Contribution size = 80, Format = DWARF32, Version = 5
|
||||||
|
; BOTH-NEXT: 0x[[CU1_STROFF]]:
|
||||||
|
; BOTH-NEXT: {{.*:}}
|
||||||
|
; BOTH-NEXT: {{.*:}}
|
||||||
|
; BOTH-NEXT: {{.*:}}
|
||||||
|
; BOTH-NEXT: {{.*:}}
|
||||||
|
; BOTH-NEXT: {{.*:}}
|
||||||
|
; BOTH-NEXT: {{.*:}}
|
||||||
|
; BOTH-NEXT: {{.*:}}
|
||||||
|
; BOTH-NEXT: {{.*:}}
|
||||||
|
; The string with index 9 should be "glob2"
|
||||||
|
; BOTH-NEXT: {{.*:}} [[GLOB2OFF]]
|
||||||
|
;
|
||||||
|
; ModuleID = 'test.bc'
|
||||||
|
source_filename = "llvm-link"
|
||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
@glob1 = global i32 0, align 4, !dbg !0
|
||||||
|
@glob2 = global i32 0, align 4, !dbg !11
|
||||||
|
@glob3 = global i32 0, align 4, !dbg !22
|
||||||
|
|
||||||
|
!llvm.dbg.cu = !{!2, !13, !24}
|
||||||
|
!llvm.ident = !{!33, !33, !33}
|
||||||
|
!llvm.module.flags = !{!34, !35, !36}
|
||||||
|
|
||||||
|
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
|
||||||
|
!1 = distinct !DIGlobalVariable(name: "glob1", scope: !2, file: !3, line: 2, type: !5, isLocal: false, isDefinition: true)
|
||||||
|
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 (trunk 322415)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !10)
|
||||||
|
!3 = !DIFile(filename: "a1.cpp", directory: "/home/test", checksumkind: CSK_MD5, checksum: "2ca3eeed18355d6ebbae671eafda5aae")
|
||||||
|
!4 = !{!5}
|
||||||
|
!5 = distinct !DICompositeType(tag: DW_TAG_enumeration_type, name: "E1", file: !3, line: 1, size: 32, elements: !6, identifier: "_ZTS2E1")
|
||||||
|
!6 = !{!7, !8, !9}
|
||||||
|
!7 = !DIEnumerator(name: "a", value: 0)
|
||||||
|
!8 = !DIEnumerator(name: "b", value: 1)
|
||||||
|
!9 = !DIEnumerator(name: "c", value: 2)
|
||||||
|
!10 = !{!0}
|
||||||
|
!11 = !DIGlobalVariableExpression(var: !12, expr: !DIExpression())
|
||||||
|
!12 = distinct !DIGlobalVariable(name: "glob2", scope: !13, file: !14, line: 2, type: !16, isLocal: false, isDefinition: true)
|
||||||
|
!13 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !14, producer: "clang version 7.0.0 (trunk 322415)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !15, globals: !21)
|
||||||
|
!14 = !DIFile(filename: "b.cpp", directory: "/home/test", checksumkind: CSK_MD5, checksum: "0e254f89617ecb6c4e5473546a99435c")
|
||||||
|
!15 = !{!16}
|
||||||
|
!16 = distinct !DICompositeType(tag: DW_TAG_enumeration_type, name: "E2", file: !14, line: 1, size: 32, elements: !17, identifier: "_ZTS2E2")
|
||||||
|
!17 = !{!18, !19, !20}
|
||||||
|
!18 = !DIEnumerator(name: "d", value: 0)
|
||||||
|
!19 = !DIEnumerator(name: "e", value: 1)
|
||||||
|
!20 = !DIEnumerator(name: "f", value: 2)
|
||||||
|
!21 = !{!11}
|
||||||
|
!22 = !DIGlobalVariableExpression(var: !23, expr: !DIExpression())
|
||||||
|
!23 = distinct !DIGlobalVariable(name: "glob3", scope: !24, file: !25, line: 2, type: !27, isLocal: false, isDefinition: true)
|
||||||
|
!24 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !25, producer: "clang version 7.0.0 (trunk 322415)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !26, globals: !32)
|
||||||
|
!25 = !DIFile(filename: "c.cpp", directory: "/home/test", checksumkind: CSK_MD5, checksum: "7835aaaa683fa09d295adef0e934d392")
|
||||||
|
!26 = !{!27}
|
||||||
|
!27 = distinct !DICompositeType(tag: DW_TAG_enumeration_type, name: "E3", file: !25, line: 1, size: 32, elements: !28, identifier: "_ZTS2E3")
|
||||||
|
!28 = !{!29, !30, !31}
|
||||||
|
!29 = !DIEnumerator(name: "g", value: 0)
|
||||||
|
!30 = !DIEnumerator(name: "h", value: 1)
|
||||||
|
!31 = !DIEnumerator(name: "i", value: 2)
|
||||||
|
!32 = !{!22}
|
||||||
|
!33 = !{!"clang version 7.0.0 (trunk 322415)"}
|
||||||
|
!34 = !{i32 2, !"Dwarf Version", i32 5}
|
||||||
|
!35 = !{i32 2, !"Debug Info Version", i32 3}
|
||||||
|
!36 = !{i32 1, !"wchar_size", i32 4}
|
|
@ -0,0 +1,122 @@
|
||||||
|
; REQUIRES: object-emission
|
||||||
|
; RUN: %llc_dwarf -filetype=obj < %s | llvm-dwarfdump -v - | FileCheck --check-prefix=MONOLITHIC %s
|
||||||
|
; RUN: %llc_dwarf -split-dwarf-file=%t.dwo -filetype=obj < %s | llvm-dwarfdump -v - \
|
||||||
|
; RUN: | FileCheck --check-prefix=SPLIT %s
|
||||||
|
|
||||||
|
; This basic test checks the emission of a DWARF v5 string offsets table in
|
||||||
|
; the split and non-split (monolithic) scenario.
|
||||||
|
;
|
||||||
|
; Constructed from the following source with
|
||||||
|
; clang -S -emit-llvm -gdwarf-5
|
||||||
|
;
|
||||||
|
; enum E {a, b, c};
|
||||||
|
; E glob;
|
||||||
|
;
|
||||||
|
; In the non-split scenario, check the DW_AT_str_offsets_base attribute
|
||||||
|
; in .debug_abbrev.
|
||||||
|
; MONOLITHIC: .debug_abbrev contents:
|
||||||
|
; MONOLITHIC-NOT: contents:
|
||||||
|
; MONOLITHIC: DW_TAG_compile_unit
|
||||||
|
; MONOLITHIC-NOT: DW_TAG
|
||||||
|
; MONOLITHIC: DW_AT_str_offsets_base DW_FORM_sec_offset
|
||||||
|
|
||||||
|
; Check that indexed strings come out correctly and that the DW_str_offsets_base attribute
|
||||||
|
; is there and has the right value.
|
||||||
|
; MONOLITHIC: .debug_info contents:
|
||||||
|
; MONOLITHIC-NOT: contents:
|
||||||
|
; MONOLITHIC: DW_TAG_compile_unit
|
||||||
|
; MONOLITHIC-NOT: {{DW_TAG|NULL}}
|
||||||
|
; MONOLITHIC: DW_AT_producer [DW_FORM_strx1] ( indexed (00000000) string = "clang{{.*}}")
|
||||||
|
; MONOLITHIC-NOT: {{DW_TAG|NULL}}
|
||||||
|
; MONOLITHIC: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008)
|
||||||
|
; MONOLITHIC-NOT: {{DW_TAG|NULL}}
|
||||||
|
; MONOLITHIC: DW_AT_comp_dir [DW_FORM_strx1] ( indexed (00000002) string = "/home/{{.*}}")
|
||||||
|
|
||||||
|
; Extract the string offsets from the .debug_str section so we can check that
|
||||||
|
; they are referenced correctly in the .debug_str_offsets section.
|
||||||
|
; MONOLITHIC: .debug_str contents:
|
||||||
|
; MONOLITHIC-NEXT: 0x00000000:
|
||||||
|
; MONOLITHIC-NEXT: 0x[[STRING2:[0-9a-f]]]
|
||||||
|
; MONOLITHIC-NEXT: 0x[[STRING3:[0-9a-f]]]
|
||||||
|
; MONOLITHIC-NEXT: 0x[[STRING4:[0-9a-f]]]
|
||||||
|
|
||||||
|
; Verify that the .debug_str_offsets section is there and that it starts
|
||||||
|
; with an 8-byte header, followed by offsets into the .debug_str section.
|
||||||
|
; MONOLITHIC: .debug_str_offsets contents:
|
||||||
|
; MONOLITHIC-NEXT: Contribution size = 32, Format = DWARF32, Version = 5
|
||||||
|
; MONOLITHIC-NEXT: 0x00000008: 00000000
|
||||||
|
; MONOLITHIC-NEXT: 0x0000000c: [[STRING2]]
|
||||||
|
; MONOLITHIC-NEXT: 0x00000010: [[STRING3]]
|
||||||
|
; MONOLITHIC-NEXT: 0x00000014: [[STRING4]]
|
||||||
|
|
||||||
|
; For split dwarf, verify that the skeleton unit has the DW_AT_str_offsets_base
|
||||||
|
; attribute and that it has the right value.
|
||||||
|
;
|
||||||
|
; SPLIT: .debug_info contents:
|
||||||
|
; SPLIT-NEXT: 0x00000000: Compile Unit:{{.*}}DW_UT_skeleton
|
||||||
|
; SPLIT-NOT: contents:
|
||||||
|
; SPLIT: DW_TAG_compile_unit
|
||||||
|
; SPLIT-NOT: {{DW_TAG|contents:}}
|
||||||
|
; SPLIT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008)
|
||||||
|
|
||||||
|
; Check for the split CU in .debug_info.dwo.
|
||||||
|
; SPLIT: .debug_info.dwo contents:
|
||||||
|
; SPLIT-NEXT: 0x00000000: Compile Unit:{{.*}}DW_UT_split_compile
|
||||||
|
; SPLIT-NOT: contents:
|
||||||
|
; SPLIT: DW_TAG_compile_unit
|
||||||
|
;
|
||||||
|
; Check that a couple of indexed strings are displayed correctly and that
|
||||||
|
; they have the right format (DW_FORM_strx1).
|
||||||
|
; SPLIT-NOT: contents:
|
||||||
|
; SPLIT: DW_TAG_enumerator
|
||||||
|
; SPLIT-NOT: {{DW_TAG|NULL}}
|
||||||
|
; SPLIT: DW_AT_name [DW_FORM_strx1] ( indexed (00000004) string = "a")
|
||||||
|
; SPLIT-NOT: contents:
|
||||||
|
; SPLIT: DW_TAG_enumerator
|
||||||
|
; SPLIT-NOT: {{DW_TAG|NULL}}
|
||||||
|
; SPLIT: DW_AT_name [DW_FORM_strx1] ( indexed (00000005) string = "b")
|
||||||
|
;
|
||||||
|
; Extract the string offsets referenced in the main file by the skeleton unit.
|
||||||
|
; SPLIT: .debug_str contents:
|
||||||
|
; SPLIT-NEXT: 0x00000000:
|
||||||
|
; SPLIT-NEXT: 0x[[STRING2SPLIT:[0-9a-f]*]]
|
||||||
|
;
|
||||||
|
; Extract the string offsets referenced in the .dwo file by the split unit.
|
||||||
|
; SPLIT: .debug_str.dwo contents:
|
||||||
|
; SPLIT-NEXT: 0x00000000:
|
||||||
|
; SPLIT-NEXT: 0x[[STRING2DWO:[0-9a-f]*]]
|
||||||
|
; SPLIT-NEXT: 0x[[STRING3DWO:[0-9a-f]*]]
|
||||||
|
;
|
||||||
|
; Check the string offsets sections in both the main and the .dwo files and
|
||||||
|
; verify that the extracted string offsets are referenced correctly.
|
||||||
|
; SPLIT: .debug_str_offsets contents:
|
||||||
|
; SPLIT-NEXT: 0x00000000: Contribution size = 8, Format = DWARF32, Version = 5
|
||||||
|
; SPLIT-NEXT: 0x00000008: 00000000
|
||||||
|
; SPLIT-NEXT: 0x0000000c: [[STRING2SPLIT]]
|
||||||
|
; SPLIT: .debug_str_offsets.dwo contents:
|
||||||
|
; SPLIT-NEXT: 0x00000000: Contribution size = 32, Format = DWARF32, Version = 5
|
||||||
|
; SPLIT-NEXT: 0x00000008: 00000000
|
||||||
|
; SPLIT-NEXT: 0x0000000c: [[STRING2DWO]]
|
||||||
|
; SPLIT-NEXT: 0x00000010: [[STRING3DWO]]
|
||||||
|
|
||||||
|
@glob = global i32 0, align 4, !dbg !0
|
||||||
|
|
||||||
|
!llvm.dbg.cu = !{!2}
|
||||||
|
!llvm.module.flags = !{!11, !12, !13}
|
||||||
|
!llvm.ident = !{!14}
|
||||||
|
|
||||||
|
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
|
||||||
|
!1 = distinct !DIGlobalVariable(name: "glob", scope: !2, file: !3, line: 3, type: !5, isLocal: false, isDefinition: true)
|
||||||
|
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 (trunk 322415)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !10)
|
||||||
|
!3 = !DIFile(filename: "en.cpp", directory: "/home/test", checksumkind: CSK_MD5, checksum: "d96b2e2d618e550f0ddd0b6a49c98b02")
|
||||||
|
!4 = !{!5}
|
||||||
|
!5 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E", file: !3, line: 1, size: 32, elements: !6, identifier: "_ZTS1E")
|
||||||
|
!6 = !{!7, !8, !9}
|
||||||
|
!7 = !DIEnumerator(name: "a", value: 0)
|
||||||
|
!8 = !DIEnumerator(name: "b", value: 1)
|
||||||
|
!9 = !DIEnumerator(name: "c", value: 2)
|
||||||
|
!10 = !{!0}
|
||||||
|
!11 = !{i32 2, !"Dwarf Version", i32 5}
|
||||||
|
!12 = !{i32 2, !"Debug Info Version", i32 3}
|
||||||
|
!13 = !{i32 1, !"wchar_size", i32 4}
|
||||||
|
!14 = !{!"clang version 7.0.0 (trunk 322415)"}
|
Loading…
Reference in New Issue