From 5cc319a42a914b24b164a94d9a563c728a7a4026 Mon Sep 17 00:00:00 2001 From: Richard Mitton Date: Thu, 19 Sep 2013 23:21:01 +0000 Subject: [PATCH] Added support for generate DWARF .debug_aranges sections automatically. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191052 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCELFStreamer.h | 2 + include/llvm/MC/MCStreamer.h | 19 ++ include/llvm/Support/Dwarf.h | 3 +- lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 3 + lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 14 ++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 206 +++++++++++++++++- lib/CodeGen/AsmPrinter/DwarfDebug.h | 15 +- lib/MC/MCAsmStreamer.cpp | 11 + lib/MC/MCELFStreamer.cpp | 16 +- lib/MC/MCMachOStreamer.cpp | 6 +- lib/MC/MCNullStreamer.cpp | 2 +- lib/MC/MCPureStreamer.cpp | 2 +- lib/MC/MCStreamer.cpp | 15 +- lib/MC/WinCOFFStreamer.cpp | 2 +- .../MCTargetDesc/AArch64ELFStreamer.cpp | 2 +- .../ARM/MCTargetDesc/ARMELFStreamer.cpp | 2 +- test/DebugInfo/dwarf-aranges.ll | 94 ++++++++ test/DebugInfo/multiple-aranges.ll | 65 ++++++ 18 files changed, 453 insertions(+), 26 deletions(-) create mode 100644 test/DebugInfo/dwarf-aranges.ll create mode 100644 test/DebugInfo/multiple-aranges.ll diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index bff0cbad5bf..76369ccb231 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -85,6 +85,8 @@ public: virtual void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned); + virtual void Flush(); + virtual void FinishImpl(); /// @} diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index cd297a4d9da..8cb5c493237 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -86,6 +86,10 @@ private: MCSymbol *LastSymbol; + // SymbolOrdering - Tracks an index to represent the order + // a symbol was emitted in. Zero means we did not emit that symbol. + DenseMap SymbolOrdering; + /// SectionStack - This is stack of current and previous section /// values saved by PushSection. SmallVector, 4> SectionStack; @@ -185,6 +189,12 @@ public: return MCSectionSubPair(); } + /// GetSymbolOrder - Returns an index to represent the order + /// a symbol was emitted in. (zero if we did not emit that symbol) + unsigned GetSymbolOrder(const MCSymbol *Sym) const { + return SymbolOrdering.lookup(Sym); + } + /// ChangeSection - Update streamer for a new active section. /// /// This is called by PopSection and SwitchSection, if the current @@ -264,6 +274,12 @@ public: /// InitToTextSection - Create a text section and switch the streamer to it. virtual void InitToTextSection() = 0; + /// AssignSection - Sets the symbol's section. + /// + /// Each emitted symbol will be tracked in the ordering table, + /// so we can sort on them later. + void AssignSection(MCSymbol *Symbol, const MCSection *Section); + /// EmitLabel - Emit a label for @p Symbol into the current section. /// /// This corresponds to an assembler statement such as: @@ -620,6 +636,9 @@ public: /// these methods there. virtual void EmitTCEntry(const MCSymbol &S); + /// Flush - Causes any cached state to be written out. + virtual void Flush() {} + /// FinishImpl - Streamer specific finalization. virtual void FinishImpl() = 0; /// Finish - Finish emission of machine code. diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index 7b87c6a90d0..d924788057e 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -59,7 +59,8 @@ enum LLVMConstants { DWARF_VERSION = 4, // Default dwarf version we output. DW_CIE_VERSION = 1, // Common frame information version. DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes. - DW_PUBNAMES_VERSION = 2 // Section version number for .debug_pubnames. + DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames. + DW_ARANGES_VERSION = 2 // Section version number for .debug_aranges. }; // Special ID values that distinguish a CIE from a FDE in DWARF CFI. diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index d0173f63163..e66237706bc 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -881,6 +881,9 @@ bool AsmPrinter::doFinalization(Module &M) { if (!ModuleFlags.empty()) getObjFileLowering().emitModuleFlags(OutStreamer, ModuleFlags, Mang, TM); + // Make sure we wrote out everything we need. + OutStreamer.Flush(); + // Finalize debug and EH information. if (DE) { { diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 4893c25c098..2638b3150f0 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -181,6 +181,12 @@ void CompileUnit::addLabel(DIE *Die, uint16_t Attribute, uint16_t Form, const MCSymbol *Label) { DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); Die->addValue(Attribute, Form, Value); + + SymbolCU Entry; + Entry.CU = this; + Entry.Sym = Label; + + DD->addLabel(Entry); } /// addLabelAddress - Add a dwarf label attribute data and value using @@ -188,6 +194,14 @@ void CompileUnit::addLabel(DIE *Die, uint16_t Attribute, uint16_t Form, /// void CompileUnit::addLabelAddress(DIE *Die, uint16_t Attribute, MCSymbol *Label) { + if (Label) { + SymbolCU Entry; + Entry.CU = this; + Entry.Sym = Label; + + DD->addLabel(Entry); + } + if (!DD->useSplitDwarf()) { if (Label != NULL) { DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index a8ebf45e6e9..f45e2f24310 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -924,7 +924,7 @@ void DwarfDebug::beginModule() { MMI->setDebugInfoAvailability(true); // Prime section data. - SectionMap.insert(Asm->getObjFileLowering().getTextSection()); + SectionMap[Asm->getObjFileLowering().getTextSection()]; } // Attach DW_AT_inline attribute with inlined subprogram DIEs. @@ -1077,16 +1077,39 @@ void DwarfDebug::finalizeModuleInfo() { } void DwarfDebug::endSections() { - // Standard sections final addresses. - Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection()); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("text_end")); - Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection()); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("data_end")); + // Filter labels by section. + for (size_t n = 0; n < Labels.size(); n++) { + const SymbolCU &SCU = Labels[n]; + if (SCU.Sym->isInSection()) { + // Make a note of this symbol and it's section. + const MCSection *Section = &SCU.Sym->getSection(); + if (!Section->getKind().isMetadata()) + SectionMap[Section].push_back(SCU); + } else { + // Some symbols (e.g. common/bss on mach-o) can have no section but still + // appear in the output. This sucks as we rely on sections to build + // arange spans. We can do it without, but it's icky. + SectionMap[NULL].push_back(SCU); + } + } - // End text sections. - for (unsigned I = 0, E = SectionMap.size(); I != E; ++I) { - Asm->OutStreamer.SwitchSection(SectionMap[I]); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_end", I+1)); + // Add terminating symbols for each section. + for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end(); + it++) { + const MCSection *Section = it->first; + MCSymbol *Sym = NULL; + + if (Section) { + Sym = Asm->GetTempSymbol(Section->getLabelEndName()); + Asm->OutStreamer.SwitchSection(Section); + Asm->OutStreamer.EmitLabel(Sym); + } + + // Insert a final terminator. + SymbolCU Entry; + Entry.CU = NULL; + Entry.Sym = Sym; + SectionMap[Section].push_back(Entry); } } @@ -2659,11 +2682,172 @@ void DwarfDebug::emitDebugLoc() { } } -// Emit visible names into a debug aranges section. +struct SymbolCUSorter { + SymbolCUSorter(const MCStreamer &s) : Streamer(s) {} + const MCStreamer &Streamer; + + bool operator() (const SymbolCU &A, const SymbolCU &B) { + unsigned IA = A.Sym ? Streamer.GetSymbolOrder(A.Sym) : 0; + unsigned IB = B.Sym ? Streamer.GetSymbolOrder(B.Sym) : 0; + + // Symbols with no order assigned should be placed at the end. + // (e.g. section end labels) + if (IA == 0) + IA = (unsigned)(-1); + if (IB == 0) + IB = (unsigned)(-1); + return IA < IB; + } +}; + +static bool SectionSort(const MCSection *A, const MCSection *B) { + std::string LA = (A ? A->getLabelBeginName() : ""); + std::string LB = (B ? B->getLabelBeginName() : ""); + return LA < LB; +} + +static bool CUSort(const CompileUnit *A, const CompileUnit *B) { + return (A->getUniqueID() < B->getUniqueID()); +} + +struct ArangeSpan { + const MCSymbol *Start, *End; +}; + +// Emit a debug aranges section, containing a CU lookup for any +// address we can tie back to a CU. void DwarfDebug::emitDebugARanges() { // Start the dwarf aranges section. Asm->OutStreamer .SwitchSection(Asm->getObjFileLowering().getDwarfARangesSection()); + + typedef DenseMap > SpansType; + + SpansType Spans; + + // Build a list of sections used. + std::vector Sections; + for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end(); + it++) { + const MCSection *Section = it->first; + Sections.push_back(Section); + } + + // Sort the sections into order. + // This is only done to ensure consistent output order across different runs. + std::sort(Sections.begin(), Sections.end(), SectionSort); + + // Build a set of address spans, sorted by CU. + for (size_t SecIdx=0;SecIdx &List = SectionMap[Section]; + if (List.size() < 2) + continue; + + // Sort the symbols by offset within the section. + SymbolCUSorter sorter(Asm->OutStreamer); + std::sort(List.begin(), List.end(), sorter); + + // If we have no section (e.g. common), just write out + // individual spans for each symbol. + if (Section == NULL) { + for (size_t n = 0; n < List.size(); n++) { + const SymbolCU &Cur = List[n]; + + ArangeSpan Span; + Span.Start = Cur.Sym; + Span.End = NULL; + if (Cur.CU) + Spans[Cur.CU].push_back(Span); + } + } else { + // Build spans between each label. + const MCSymbol *StartSym = List[0].Sym; + for (size_t n = 1; n < List.size(); n++) { + const SymbolCU &Prev = List[n - 1]; + const SymbolCU &Cur = List[n]; + + // Try and build the longest span we can within the same CU. + if (Cur.CU != Prev.CU) { + ArangeSpan Span; + Span.Start = StartSym; + Span.End = Cur.Sym; + Spans[Prev.CU].push_back(Span); + StartSym = Cur.Sym; + } + } + } + } + + const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection(); + unsigned PtrSize = Asm->getDataLayout().getPointerSize(); + + // Build a list of CUs used. + std::vector CUs; + for (SpansType::iterator it = Spans.begin(); it != Spans.end(); it++) { + CompileUnit *CU = it->first; + CUs.push_back(CU); + } + + // Sort the CU list (again, to ensure consistent output order). + std::sort(CUs.begin(), CUs.end(), CUSort); + + // Emit an arange table for each CU we used. + for (size_t CUIdx=0;CUIdx &List = Spans[CU]; + + // Emit size of content not including length itself. + unsigned ContentSize + = sizeof(int16_t) // DWARF ARange version number + + sizeof(int32_t) // Offset of CU in the .debug_info section + + sizeof(int8_t) // Pointer Size (in bytes) + + sizeof(int8_t); // Segment Size (in bytes) + + unsigned TupleSize = PtrSize * 2; + + // 7.20 in the Dwarf specs requires the table to be aligned to a tuple. + unsigned Padding = 0; + while (((sizeof(int32_t) + ContentSize + Padding) % TupleSize) != 0) + Padding++; + + ContentSize += Padding; + ContentSize += (List.size() + 1) * TupleSize; + + // For each compile unit, write the list of spans it covers. + Asm->OutStreamer.AddComment("Length of ARange Set"); + Asm->EmitInt32(ContentSize); + Asm->OutStreamer.AddComment("DWARF Arange version number"); + Asm->EmitInt16(dwarf::DW_ARANGES_VERSION); + Asm->OutStreamer.AddComment("Offset Into Debug Info Section"); + Asm->EmitSectionOffset( + Asm->GetTempSymbol(ISec->getLabelBeginName(), CU->getUniqueID()), + DwarfInfoSectionSym); + Asm->OutStreamer.AddComment("Address Size (in bytes)"); + Asm->EmitInt8(PtrSize); + Asm->OutStreamer.AddComment("Segment Size (in bytes)"); + Asm->EmitInt8(0); + + for (unsigned n = 0; n < Padding; n++) + Asm->EmitInt8(0xff); + + for (unsigned n = 0; n < List.size(); n++) { + const ArangeSpan &Span = List[n]; + Asm->EmitLabelReference(Span.Start, PtrSize); + + // Calculate the size as being from the span start to it's end. + // If we have no valid end symbol, then we just cover the first byte. + // (this sucks, but I can't seem to figure out how to get the size) + if (Span.End) + Asm->EmitLabelDifference(Span.End, Span.Start, PtrSize); + else + Asm->OutStreamer.EmitIntValue(1, PtrSize); + } + + Asm->OutStreamer.AddComment("ARange terminator"); + Asm->OutStreamer.EmitIntValue(0, PtrSize); + Asm->OutStreamer.EmitIntValue(0, PtrSize); + } } // Emit visible names into a debug ranges section. diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 5a03e9fb580..8fe60c77be5 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -300,6 +300,12 @@ public: unsigned getCUOffset(DIE *Die); }; +/// \brief Helper used to pair up a symbol and it's DWARF compile unit. +struct SymbolCU { + const MCSymbol *Sym; + CompileUnit *CU; +}; + /// \brief Collects and handles dwarf debug information. class DwarfDebug { // Target of Dwarf emission. @@ -332,8 +338,12 @@ class DwarfDebug { // separated by a zero byte, mapped to a unique id. StringMap SourceIdMap; + // List of all labels used in the output. + std::vector Labels; + // Provides a unique id per text section. - SetVector SectionMap; + typedef DenseMap > SectionMapType; + SectionMapType SectionMap; // List of arguments for current function. SmallVector CurrentFnArguments; @@ -669,6 +679,9 @@ public: /// type units. void addTypeUnitType(DIE *Die) { TypeUnits.push_back(Die); } + /// \brief Add a label so that arange data can be generated for it. + void addLabel(SymbolCU SCU) { Labels.push_back(SCU); } + /// \brief Look up the source id with the given directory and source file /// names. If none currently exists, create a new id and insert it in the /// SourceIds map. diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 2456d8de827..e57025e1019 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -533,6 +533,9 @@ void MCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { + const MCSection *Section = getContext().getObjectFileInfo()->getBSSSection(); + AssignSection(Symbol, Section); + OS << "\t.comm\t" << *Symbol << ',' << Size; if (ByteAlignment != 0) { if (MAI->getCOMMDirectiveAlignmentIsInBytes()) @@ -549,6 +552,9 @@ void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, /// @param Size - The size of the common symbol. void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlign) { + const MCSection *Section = getContext().getObjectFileInfo()->getBSSSection(); + AssignSection(Symbol, Section); + OS << "\t.lcomm\t" << *Symbol << ',' << Size; if (ByteAlign > 1) { switch (MAI->getLCOMMDirectiveAlignmentType()) { @@ -568,6 +574,9 @@ void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { + if (Symbol) + AssignSection(Symbol, Section); + // Note: a .zerofill directive does not switch sections. OS << ".zerofill "; @@ -588,6 +597,8 @@ void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, // e.g. _a. void MCAsmStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { + AssignSection(Symbol, Section); + assert(Symbol != NULL && "Symbol shouldn't be NULL!"); // Instead of using the Section we'll just use the shortcut. // This is a mach-o specific directive and section. diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index a04352a8b28..0ed040d5be3 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -272,7 +272,8 @@ void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, ELF::SHF_WRITE | ELF::SHF_ALLOC, SectionKind::getBSS()); - Symbol->setSection(*Section); + + AssignSection(Symbol, Section); struct LocalCommon L = {&SD, Size, ByteAlignment}; LocalCommons.push_back(L); @@ -527,9 +528,7 @@ void MCELFStreamer::EmitBundleUnlock() { SD->setBundleLockState(MCSectionData::NotBundleLocked); } -void MCELFStreamer::FinishImpl() { - EmitFrames(NULL, true); - +void MCELFStreamer::Flush() { for (std::vector::const_iterator i = LocalCommons.begin(), e = LocalCommons.end(); i != e; ++i) { @@ -550,8 +549,17 @@ void MCELFStreamer::FinishImpl() { SectData.setAlignment(ByteAlignment); } + LocalCommons.clear(); +} + +void MCELFStreamer::FinishImpl() { + EmitFrames(NULL, true); + + Flush(); + this->MCObjectStreamer::FinishImpl(); } + void MCELFStreamer::EmitTCEntry(const MCSymbol &S) { // Creates a R_PPC64_TOC relocation MCObjectStreamer::EmitSymbolValue(&S, 8); diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index e628461f1d6..2c4707f58ce 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -123,7 +123,7 @@ void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); // isSymbolLinkerVisible uses the section. - Symbol->setSection(*getCurrentSection().first); + AssignSection(Symbol, getCurrentSection().first); // We have to create a new fragment if this is an atom defining symbol, // fragments cannot span atoms. if (getAssembler().isSymbolLinkerVisible(*Symbol)) @@ -327,6 +327,8 @@ void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself. assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + AssignSection(Symbol, NULL); + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); SD.setExternal(true); SD.setCommon(Size, ByteAlignment); @@ -363,7 +365,7 @@ void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, MCFragment *F = new MCFillFragment(0, 0, Size, &SectData); SD.setFragment(F); - Symbol->setSection(*Section); + AssignSection(Symbol, Section); // Update the maximum alignment on the zero fill section if necessary. if (ByteAlignment > SectData.getAlignment()) diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index 87a7db69cd8..2ddc4f0f71e 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -37,7 +37,7 @@ namespace { virtual void EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); assert(getCurrentSection().first &&"Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection().first); + AssignSection(Symbol, getCurrentSection().first); } virtual void EmitDebugLabel(MCSymbol *Symbol) { EmitLabel(Symbol); diff --git a/lib/MC/MCPureStreamer.cpp b/lib/MC/MCPureStreamer.cpp index c6c772c6e2a..a83caf6080b 100644 --- a/lib/MC/MCPureStreamer.cpp +++ b/lib/MC/MCPureStreamer.cpp @@ -121,7 +121,7 @@ void MCPureStreamer::EmitLabel(MCSymbol *Symbol) { assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); assert(getCurrentSection().first && "Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection().first); + AssignSection(Symbol, getCurrentSection().first); MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index c2a20f9ca6a..4ffde674766 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -191,17 +191,28 @@ void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) { } +void MCStreamer::AssignSection(MCSymbol *Symbol, const MCSection *Section) { + if (Section) + Symbol->setSection(*Section); + else + Symbol->setUndefined(); + + // As we emit symbols into a section, track the order so that they can + // be sorted upon later. Zero is reserved to mean 'unemitted'. + SymbolOrdering[Symbol] = 1 + SymbolOrdering.size(); +} + void MCStreamer::EmitLabel(MCSymbol *Symbol) { assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); assert(getCurrentSection().first && "Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection().first); + AssignSection(Symbol, getCurrentSection().first); LastSymbol = Symbol; } void MCStreamer::EmitDebugLabel(MCSymbol *Symbol) { assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); assert(getCurrentSection().first && "Cannot emit before setting section!"); - Symbol->setSection(*getCurrentSection().first); + AssignSection(Symbol, getCurrentSection().first); LastSymbol = Symbol; } diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp index 3f0449dc467..dd98aa5f304 100644 --- a/lib/MC/WinCOFFStreamer.cpp +++ b/lib/MC/WinCOFFStreamer.cpp @@ -164,7 +164,7 @@ void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, SymbolData.setExternal(External); - Symbol->setSection(*Section); + AssignSection(Symbol, Section); if (ByteAlignment != 1) new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, &SectionData); diff --git a/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp b/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp index 104e4d242df..8e2be8185eb 100644 --- a/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp +++ b/lib/Target/AArch64/MCTargetDesc/AArch64ELFStreamer.cpp @@ -129,7 +129,7 @@ private: MCELF::SetType(SD, ELF::STT_NOTYPE); MCELF::SetBinding(SD, ELF::STB_LOCAL); SD.setExternal(false); - Symbol->setSection(*getCurrentSection().first); + AssignSection(Symbol, getCurrentSection().first); const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext()); Symbol->setVariableValue(Value); diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp index 6b9820565b5..37a80d5b8cf 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -183,7 +183,7 @@ private: MCELF::SetType(SD, ELF::STT_NOTYPE); MCELF::SetBinding(SD, ELF::STB_LOCAL); SD.setExternal(false); - Symbol->setSection(*getCurrentSection().first); + AssignSection(Symbol, getCurrentSection().first); const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext()); Symbol->setVariableValue(Value); diff --git a/test/DebugInfo/dwarf-aranges.ll b/test/DebugInfo/dwarf-aranges.ll new file mode 100644 index 00000000000..eae5c790d82 --- /dev/null +++ b/test/DebugInfo/dwarf-aranges.ll @@ -0,0 +1,94 @@ +; RUN: llc < %s | FileCheck -check-prefix=CHECK-HEADER %s +; RUN: llc < %s | FileCheck -check-prefix=CHECK-CODE %s +; RUN: llc < %s | FileCheck -check-prefix=CHECK-DATA %s +; RUN: llc < %s | FileCheck -check-prefix=CHECK-BSS %s +; RUN: llc < %s | FileCheck -check-prefix=CHECK-CUSTOM %s + + +; -- header -- +; CHECK-HEADER: .short 2 # DWARF Arange version number +; CHECK-HEADER-NEXT: .long .L.debug_info_begin0 +; CHECK-HEADER-NEXT: .byte 8 # Address Size (in bytes) +; CHECK-HEADER-NEXT: .byte 0 # Segment Size (in bytes) +; -- alignment -- +; CHECK-HEADER-NEXT: .byte +; CHECK-HEADER-NEXT: .byte +; CHECK-HEADER-NEXT: .byte +; CHECK-HEADER-NEXT: .byte +; -- finish -- +; CHECK-HEADER: # ARange terminator + + +; CHECK-CODE: .short 2 # DWARF Arange version number +; CHECK-CODE: .quad .Lfunc_begin0 +; CHECK-CODE: # ARange terminator + +; CHECK-DATA: .short 2 # DWARF Arange version number +; CHECK-DATA: .quad some_data +; CHECK-DATA-NEXT: -some_data +; CHECK-DATA-NEXT: .quad +; CHECK-DATA: # ARange terminator + +; CHECK-BSS: .short 2 # DWARF Arange version number +; CHECK-BSS: .quad some_bss +; CHECK-BSS-NEXT: -some_bss +; CHECK-BSS-NEXT: .quad +; CHECK-BSS: # ARange terminator + +; CHECK-CUSTOM: .short 2 # DWARF Arange version number +; CHECK-CUSTOM: .quad some_other +; CHECK-CUSTOM-NEXT: -some_other +; CHECK-CUSTOM-NEXT: .quad +; CHECK-CUSTOM: # ARange terminator + + + + +; -- source code -- +; Generated from: "clang -c -g -emit-llvm" +; +; int some_data = 4; +; int some_bss; +; int some_other __attribute__ ((section ("strangesection"))) = 5; +; +; void some_code() +; { +; some_bss += some_data + some_other; +; } + +target triple = "x86_64-unknown-linux-gnu" + +@some_data = global i32 4, align 4 +@some_other = global i32 5, section "strangesection", align 4 +@some_bss = common global i32 0, align 4 + +define void @some_code() { +entry: + %0 = load i32* @some_data, align 4, !dbg !14 + %1 = load i32* @some_other, align 4, !dbg !14 + %add = add nsw i32 %0, %1, !dbg !14 + %2 = load i32* @some_bss, align 4, !dbg !14 + %add1 = add nsw i32 %2, %add, !dbg !14 + store i32 %add1, i32* @some_bss, align 4, !dbg !14 + ret void, !dbg !15 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!13} + +!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.4 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !8, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/home/kayamon/test.c] [DW_LANG_C99] +!1 = metadata !{metadata !"test.c", metadata !"/home/kayamon"} +!2 = metadata !{i32 0} +!3 = metadata !{metadata !4} +!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"some_code", metadata !"some_code", metadata !"", i32 5, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 0, i1 false, void ()* @some_code, null, null, metadata !2, i32 6} ; [ DW_TAG_subprogram ] [line 5] [def] [scope 6] [some_code] +!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/home/kayamon/test.c] +!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = metadata !{null} +!8 = metadata !{metadata !9, metadata !11, metadata !12} +!9 = metadata !{i32 786484, i32 0, null, metadata !"some_data", metadata !"some_data", metadata !"", metadata !5, i32 1, metadata !10, i32 0, i32 1, i32* @some_data, null} ; [ DW_TAG_variable ] [some_data] [line 1] [def] +!10 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!11 = metadata !{i32 786484, i32 0, null, metadata !"some_other", metadata !"some_other", metadata !"", metadata !5, i32 3, metadata !10, i32 0, i32 1, i32* @some_other, null} ; [ DW_TAG_variable ] [some_other] [line 3] [def] +!12 = metadata !{i32 786484, i32 0, null, metadata !"some_bss", metadata !"some_bss", metadata !"", metadata !5, i32 2, metadata !10, i32 0, i32 1, i32* @some_bss, null} ; [ DW_TAG_variable ] [some_bss] [line 2] [def] +!13 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} +!14 = metadata !{i32 7, i32 0, metadata !4, null} +!15 = metadata !{i32 8, i32 0, metadata !4, null} ; [ DW_TAG_imported_declaration ] diff --git a/test/DebugInfo/multiple-aranges.ll b/test/DebugInfo/multiple-aranges.ll new file mode 100644 index 00000000000..08c4fa66845 --- /dev/null +++ b/test/DebugInfo/multiple-aranges.ll @@ -0,0 +1,65 @@ +; RUN: llc < %s | FileCheck %s + +; First CU +; CHECK: .long 44 # Length of ARange Set +; CHECK-NEXT: .short 2 # DWARF Arange version number +; CHECK-NEXT: .long .L.debug_info_begin0 # Offset Into Debug Info Section +; CHECK-NEXT: .byte 8 # Address Size (in bytes) +; CHECK-NEXT: .byte 0 # Segment Size (in bytes) +; CHECK-NEXT: .byte 255 +; CHECK-NEXT: .byte 255 +; CHECK-NEXT: .byte 255 +; CHECK-NEXT: .byte 255 +; CHECK-NEXT: .quad kittens +; CHECK-NEXT: .Lset0 = rainbows-kittens +; CHECK-NEXT: .quad .Lset0 +; CHECK-NEXT: .quad 0 # ARange terminator +; CHECK-NEXT: .quad 0 + +; Second CU +; CHECK-NEXT: .long 44 # Length of ARange Set +; CHECK-NEXT: .short 2 # DWARF Arange version number +; CHECK-NEXT: .long .L.debug_info_begin1 # Offset Into Debug Info Section +; CHECK-NEXT: .byte 8 # Address Size (in bytes) +; CHECK-NEXT: .byte 0 # Segment Size (in bytes) +; CHECK-NEXT: .byte 255 +; CHECK-NEXT: .byte 255 +; CHECK-NEXT: .byte 255 +; CHECK-NEXT: .byte 255 +; CHECK-NEXT: .quad rainbows +; CHECK-NEXT: .Lset1 = .L.data_end-rainbows +; CHECK-NEXT: .quad .Lset1 +; CHECK-NEXT: .quad 0 # ARange terminator +; CHECK-NEXT: .quad 0 + + +; Generated from: clang -c -g -emit-llvm +; llvm-link test1.bc test2.bc -o test.bc +; test1.c: int kittens = 4; +; test2.c: int rainbows = 5; + + + + +; ModuleID = 'test.bc' +target triple = "x86_64-unknown-linux-gnu" + +@kittens = global i32 4, align 4 +@rainbows = global i32 5, align 4 + +!llvm.dbg.cu = !{!0, !7} +!llvm.module.flags = !{!12} + +!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.4 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !2, metadata !3, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/home/kayamon/test1.c] [DW_LANG_C99] +!1 = metadata !{metadata !"test1.c", metadata !"/home/kayamon"} +!2 = metadata !{i32 0} +!3 = metadata !{metadata !4} +!4 = metadata !{i32 786484, i32 0, null, metadata !"kittens", metadata !"kittens", metadata !"", metadata !5, i32 1, metadata !6, i32 0, i32 1, i32* @kittens, null} ; [ DW_TAG_variable ] [kittens] [line 1] [def] +!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/home/kayamon/test1.c] +!6 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!7 = metadata !{i32 786449, metadata !8, i32 12, metadata !"clang version 3.4 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !2, metadata !9, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/home/kayamon/test2.c] [DW_LANG_C99] +!8 = metadata !{metadata !"test2.c", metadata !"/home/kayamon"} +!9 = metadata !{metadata !10} +!10 = metadata !{i32 786484, i32 0, null, metadata !"rainbows", metadata !"rainbows", metadata !"", metadata !11, i32 1, metadata !6, i32 0, i32 1, i32* @rainbows, null} ; [ DW_TAG_variable ] [rainbows] [line 1] [def] +!11 = metadata !{i32 786473, metadata !8} ; [ DW_TAG_file_type ] [/home/kayamon/test2.c] +!12 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}