diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index 32d6cb2c45c..f33f0f999d7 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -197,6 +197,7 @@ void DIEInteger::EmitValue(AsmPrinter *Asm, unsigned Form) const { case dwarf::DW_FORM_data4: Size = 4; break; case dwarf::DW_FORM_ref8: // Fall thru case dwarf::DW_FORM_data8: Size = 8; break; + case dwarf::DW_FORM_GNU_str_index: Asm->EmitULEB128(Integer); return; case dwarf::DW_FORM_udata: Asm->EmitULEB128(Integer); return; case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return; case dwarf::DW_FORM_addr: @@ -220,6 +221,7 @@ unsigned DIEInteger::SizeOf(AsmPrinter *AP, unsigned Form) const { case dwarf::DW_FORM_data4: return sizeof(int32_t); case dwarf::DW_FORM_ref8: // Fall thru case dwarf::DW_FORM_data8: return sizeof(int64_t); + case dwarf::DW_FORM_GNU_str_index: return MCAsmInfo::getULEB128Size(Integer); case dwarf::DW_FORM_udata: return MCAsmInfo::getULEB128Size(Integer); case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer); case dwarf::DW_FORM_addr: return AP->getDataLayout().getPointerSize(); diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 854d82c2c58..60d7cd3945a 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -128,6 +128,27 @@ void CompileUnit::addSInt(DIE *Die, unsigned Attribute, /// reference to the string pool instead of immediate strings so that DIEs have /// more predictable sizes. void CompileUnit::addString(DIE *Die, unsigned Attribute, StringRef String) { + if (!DD->useSplitDwarf()) { + MCSymbol *Symb = DU->getStringPoolEntry(String); + DIEValue *Value; + if (Asm->needsRelocationsForDwarfStringPool()) + Value = new (DIEValueAllocator) DIELabel(Symb); + else { + MCSymbol *StringPool = DU->getStringPoolSym(); + Value = new (DIEValueAllocator) DIEDelta(Symb, StringPool); + } + Die->addValue(Attribute, dwarf::DW_FORM_strp, Value); + } else { + unsigned idx = DU->getStringPoolIndex(String); + DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); + Die->addValue(Attribute, dwarf::DW_FORM_GNU_str_index, Value); + } +} + +/// addLocalString - Add a string attribute data and value. This is guaranteed +/// to be in the local string pool instead of indirected. +void CompileUnit::addLocalString(DIE *Die, unsigned Attribute, + StringRef String) { MCSymbol *Symb = DU->getStringPoolEntry(String); DIEValue *Value; if (Asm->needsRelocationsForDwarfStringPool()) diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 368234ba862..f210dcc03b5 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -198,6 +198,10 @@ public: /// void addString(DIE *Die, unsigned Attribute, const StringRef Str); + /// addLocalString - Add a string attribute data and value. + /// + void addLocalString(DIE *Die, unsigned Attribute, const StringRef Str); + /// addLabel - Add a Dwarf label attribute data and value. /// void addLabel(DIE *Die, unsigned Attribute, unsigned Form, diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 321256a613c..11b853f17ba 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -228,6 +228,16 @@ MCSymbol *DwarfUnits::getStringPoolEntry(StringRef Str) { return Entry.first = Asm->GetTempSymbol(StringPref, Entry.second); } +unsigned DwarfUnits::getStringPoolIndex(StringRef Str) { + std::pair &Entry = + StringPool->GetOrCreateValue(Str).getValue(); + if (Entry.first) return Entry.second; + + Entry.second = NextStringPoolNumber++; + Entry.first = Asm->GetTempSymbol(StringPref, Entry.second); + return Entry.second; +} + // Define a unique number for the abbreviation. // void DwarfUnits::assignAbbrevNumber(DIEAbbrev &Abbrev) { @@ -2116,12 +2126,14 @@ void DwarfDebug::emitDebugPubTypes() { } // Emit strings into a string section. -void DwarfUnits::emitStrings(const MCSection *Section) { +void DwarfUnits::emitStrings(const MCSection *StrSection, + const MCSection *OffsetSection = NULL, + const MCSymbol *StrSecSym = NULL) { if (StringPool->empty()) return; // Start the dwarf str section. - Asm->OutStreamer.SwitchSection(Section); + Asm->OutStreamer.SwitchSection(StrSection); // Get all of the string pool entries and put them in an array by their ID so // we can sort them. @@ -2144,6 +2156,17 @@ void DwarfUnits::emitStrings(const MCSection *Section) { Entries[i].second->getKeyLength()+1), 0/*addrspace*/); } + + // If we've got an offset section go ahead and emit that now as well. + if (OffsetSection) { + Asm->OutStreamer.SwitchSection(OffsetSection); + unsigned offset = 0; + unsigned size = 4; + for (unsigned i = 0, e = Entries.size(); i != e; ++i) { + Asm->OutStreamer.EmitIntValue(offset, size, 0); + offset += Entries[i].second->getKeyLength() + 1; + } + } } // Emit visible names into a debug str section. @@ -2377,7 +2400,7 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const MDNode *N) { DIUnit.getLanguage(), Die, Asm, this, &SkeletonHolder); // FIXME: This should be the .dwo file. - NewCU->addString(Die, dwarf::DW_AT_GNU_dwo_name, FN); + NewCU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name, FN); // FIXME: We also need DW_AT_addr_base and DW_AT_dwo_id. @@ -2393,7 +2416,7 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const MDNode *N) { NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0); if (!CompilationDir.empty()) - NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); + NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir); SkeletonHolder.addUnit(NewCU); @@ -2458,5 +2481,8 @@ void DwarfDebug::emitDebugAbbrevDWO() { // sections. void DwarfDebug::emitDebugStrDWO() { assert(useSplitDwarf() && "No split dwarf?"); - InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection()); + const MCSection *OffSec = Asm->getObjFileLowering().getDwarfStrOffDWOSection(); + const MCSymbol *StrSym = DwarfStrSectionSym; + InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(), + OffSec, StrSym); } diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 59e4890dec4..cc6c0f7e638 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -240,7 +240,7 @@ public: const MCSymbol *); /// \brief Emit all of the strings to the section given. - void emitStrings(const MCSection *); + void emitStrings(const MCSection *, const MCSection *, const MCSymbol *); /// \brief Returns the entry into the start of the pool. MCSymbol *getStringPoolSym(); @@ -249,6 +249,10 @@ public: /// string text. MCSymbol *getStringPoolEntry(StringRef Str); + /// \brief Returns the index into the string pool with the given + /// string text. + unsigned getStringPoolIndex(StringRef Str); + /// \brief Returns the string pool. StrPool *getStringPool() { return StringPool; } }; diff --git a/lib/DebugInfo/DWARFCompileUnit.h b/lib/DebugInfo/DWARFCompileUnit.h index ba638dff212..c58664f2234 100644 --- a/lib/DebugInfo/DWARFCompileUnit.h +++ b/lib/DebugInfo/DWARFCompileUnit.h @@ -28,6 +28,7 @@ class DWARFCompileUnit { StringRef AbbrevSection; StringRef RangeSection; StringRef StringSection; + StringRef StringOffsetSection; const RelocAddrMap *RelocMap; bool isLittleEndian; @@ -42,13 +43,16 @@ class DWARFCompileUnit { public: DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, - StringRef RS, StringRef SS, const RelocAddrMap *M, bool LE) : + StringRef RS, StringRef SS, StringRef SOS, + const RelocAddrMap *M, bool LE) : Abbrev(DA), InfoSection(IS), AbbrevSection(AS), - RangeSection(RS), StringSection(SS), RelocMap(M), isLittleEndian(LE) { + RangeSection(RS), StringSection(SS), StringOffsetSection(SOS), + RelocMap(M), isLittleEndian(LE) { clear(); } StringRef getStringSection() const { return StringSection; } + StringRef getStringOffsetSection() const { return StringOffsetSection; } const RelocAddrMap *getRelocMap() const { return RelocMap; } DataExtractor getDebugInfoExtractor() const; diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index 1270e6ec72a..d6d9fcf3ea8 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -152,7 +152,8 @@ void DWARFContext::parseCompileUnits() { while (DIData.isValidOffset(offset)) { CUs.push_back(DWARFCompileUnit(getDebugAbbrev(), getInfoSection(), getAbbrevSection(), getRangeSection(), - getStringSection(), &infoRelocMap(), + getStringSection(), "", + &infoRelocMap(), isLittleEndian())); if (!CUs.back().extract(DIData, &offset)) { CUs.pop_back(); @@ -172,6 +173,7 @@ void DWARFContext::parseDWOCompileUnits() { getAbbrevDWOSection(), getRangeDWOSection(), getStringDWOSection(), + getStringOffsetDWOSection(), &infoDWORelocMap(), isLittleEndian())); if (!DWOCUs.back().extract(DIData, &offset)) { @@ -382,6 +384,8 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : AbbrevDWOSection = data; else if (name == "debug_str.dwo") StringDWOSection = data; + else if (name == "debug_str_offsets.dwo") + StringOffsetDWOSection = data; // Any more debug info sections go here. else continue; diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h index 0c3eb30a64c..c6d6283f53a 100644 --- a/lib/DebugInfo/DWARFContext.h +++ b/lib/DebugInfo/DWARFContext.h @@ -106,6 +106,7 @@ public: virtual StringRef getInfoDWOSection() = 0; virtual StringRef getAbbrevDWOSection() = 0; virtual StringRef getStringDWOSection() = 0; + virtual StringRef getStringOffsetDWOSection() = 0; virtual StringRef getRangeDWOSection() = 0; virtual const RelocAddrMap &infoDWORelocMap() const = 0; @@ -140,6 +141,7 @@ class DWARFContextInMemory : public DWARFContext { StringRef InfoDWOSection; StringRef AbbrevDWOSection; StringRef StringDWOSection; + StringRef StringOffsetDWOSection; StringRef RangeDWOSection; public: @@ -157,6 +159,9 @@ public: virtual StringRef getInfoDWOSection() { return InfoDWOSection; } virtual StringRef getAbbrevDWOSection() { return AbbrevDWOSection; } virtual StringRef getStringDWOSection() { return StringDWOSection; } + virtual StringRef getStringOffsetDWOSection() { + return StringOffsetDWOSection; + } virtual StringRef getRangeDWOSection() { return RangeDWOSection; } virtual const RelocAddrMap &infoDWORelocMap() const { return InfoDWORelocMap; } }; diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp index c083b8c61bc..bb118501c11 100644 --- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ b/lib/DebugInfo/DWARFDebugInfoEntry.cpp @@ -12,6 +12,7 @@ #include "DWARFContext.h" #include "DWARFDebugAbbrev.h" #include "DWARFFormValue.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -113,9 +114,14 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu, uint32_t i; uint16_t form; for (i=0; igetFormByIndex(i); - const uint8_t fixed_skip_size = fixed_form_sizes[form]; + // FIXME: Currently we're checking if this is less than the last + // entry in the fixed_form_sizes table, but this should be changed + // to use dynamic dispatch. + const uint8_t fixed_skip_size = (form < DW_FORM_ref_sig8) ? + fixed_form_sizes[form] : 0; if (fixed_skip_size) offset += fixed_skip_size; else { @@ -187,6 +193,8 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu, case DW_FORM_sdata: case DW_FORM_udata: case DW_FORM_ref_udata: + case DW_FORM_GNU_str_index: + case DW_FORM_GNU_addr_index: debug_info_data.getULEB128(&offset); break; @@ -207,7 +215,6 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu, return false; } offset += form_size; - } while (form_is_indirect); } } @@ -327,6 +334,8 @@ DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu, case DW_FORM_sdata: case DW_FORM_udata: case DW_FORM_ref_udata: + case DW_FORM_GNU_str_index: + case DW_FORM_GNU_addr_index: debug_info_data.getULEB128(&offset); break; diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp index 1610db27d2c..47fad8bcfbc 100644 --- a/lib/DebugInfo/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARFFormValue.cpp @@ -46,8 +46,6 @@ static const uint8_t form_sizes_addr4[] = { 0, // 0x18 DW_FORM_exprloc 0, // 0x19 DW_FORM_flag_present 8, // 0x20 DW_FORM_ref_sig8 - 4, // 0x1f01 DW_FORM_GNU_addr_index - 4, // 0x1f02 DW_FORM_GNU_str_index }; static const uint8_t form_sizes_addr8[] = { @@ -78,8 +76,6 @@ static const uint8_t form_sizes_addr8[] = { 0, // 0x18 DW_FORM_exprloc 0, // 0x19 DW_FORM_flag_present 8, // 0x20 DW_FORM_ref_sig8 - 8, // 0x1f01 DW_FORM_GNU_addr_index - 8, // 0x1f01 DW_FORM_GNU_str_index }; const uint8_t * @@ -295,6 +291,8 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, case DW_FORM_sdata: case DW_FORM_udata: case DW_FORM_ref_udata: + case DW_FORM_GNU_str_index: + case DW_FORM_GNU_addr_index: debug_info_data.getULEB128(offset_ptr); return true; @@ -321,6 +319,7 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, void DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const { DataExtractor debug_str_data(cu->getStringSection(), true, 0); + DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0); uint64_t uvalue = getUnsigned(); bool cu_relative_offset = false; @@ -379,6 +378,17 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const { } break; } + case DW_FORM_GNU_str_index: { + OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); + const char *dbg_str = getIndirectCString(&debug_str_data, + &debug_str_offset_data); + if (dbg_str) { + OS << '"'; + OS.write_escaped(dbg_str); + OS << '"'; + } + break; + } case DW_FORM_ref_addr: OS << format("0x%016" PRIx64, uvalue); break; @@ -436,6 +446,16 @@ DWARFFormValue::getAsCString(const DataExtractor *debug_str_data_ptr) const { return NULL; } +const char* +DWARFFormValue::getIndirectCString(const DataExtractor *DS, + const DataExtractor *DSO) const { + if (!DS || !DSO) return NULL; + + uint32_t offset = Value.uval * 4; + uint32_t soffset = DSO->getULEB128(&offset); + return DS->getCStr(&soffset); +} + uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const { uint64_t die_offset = Value.uval; switch (Form) { diff --git a/lib/DebugInfo/DWARFFormValue.h b/lib/DebugInfo/DWARFFormValue.h index c5b590db95f..7768c1848fa 100644 --- a/lib/DebugInfo/DWARFFormValue.h +++ b/lib/DebugInfo/DWARFFormValue.h @@ -64,6 +64,8 @@ public: uint64_t getUnsigned() const { return Value.uval; } int64_t getSigned() const { return Value.sval; } const char *getAsCString(const DataExtractor *debug_str_data_ptr) const; + const char *getIndirectCString(const DataExtractor *, + const DataExtractor *) const; bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, const DWARFCompileUnit *cu) const; static bool skipValue(uint16_t form, DataExtractor debug_info_data, diff --git a/test/DebugInfo/X86/fission-cu.ll b/test/DebugInfo/X86/fission-cu.ll index 22f59dd8a60..3ada3ef383f 100644 --- a/test/DebugInfo/X86/fission-cu.ll +++ b/test/DebugInfo/X86/fission-cu.ll @@ -30,10 +30,10 @@ ; FIXME: Strings will ultimately be a different form. ; CHECK: .debug_info.dwo contents: ; CHECK: DW_TAG_compile_unit -; CHECK: DW_AT_producer [DW_FORM_strp] +; CHECK: DW_AT_producer [DW_FORM_GNU_str_index] ( indexed (00000000) string = "clang version 3.3 (trunk 169021) (llvm/trunk 169020)") ; CHECK: DW_AT_language [DW_FORM_data2] (0x000c) -; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000035] = "baz.c") +; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000001) string = "baz.c") ; CHECK: DW_TAG_base_type -; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000061] = "int") +; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000004) string = "int") ; CHECK: DW_TAG_variable -; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000005f] = "a") +; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000003) string = "a")