Skip to content

Commit 21101b3

Browse files
committed
Added support for generate DWARF .debug_aranges sections automatically.
llvm-svn: 191052
1 parent 665d3ec commit 21101b3

File tree

18 files changed

+453
-26
lines changed

18 files changed

+453
-26
lines changed

llvm/include/llvm/MC/MCELFStreamer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ class MCELFStreamer : public MCObjectStreamer {
8585

8686
virtual void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned);
8787

88+
virtual void Flush();
89+
8890
virtual void FinishImpl();
8991
/// @}
9092

llvm/include/llvm/MC/MCStreamer.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ class MCStreamer {
8686

8787
MCSymbol *LastSymbol;
8888

89+
// SymbolOrdering - Tracks an index to represent the order
90+
// a symbol was emitted in. Zero means we did not emit that symbol.
91+
DenseMap<const MCSymbol *, unsigned> SymbolOrdering;
92+
8993
/// SectionStack - This is stack of current and previous section
9094
/// values saved by PushSection.
9195
SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack;
@@ -185,6 +189,12 @@ class MCStreamer {
185189
return MCSectionSubPair();
186190
}
187191

192+
/// GetSymbolOrder - Returns an index to represent the order
193+
/// a symbol was emitted in. (zero if we did not emit that symbol)
194+
unsigned GetSymbolOrder(const MCSymbol *Sym) const {
195+
return SymbolOrdering.lookup(Sym);
196+
}
197+
188198
/// ChangeSection - Update streamer for a new active section.
189199
///
190200
/// This is called by PopSection and SwitchSection, if the current
@@ -264,6 +274,12 @@ class MCStreamer {
264274
/// InitToTextSection - Create a text section and switch the streamer to it.
265275
virtual void InitToTextSection() = 0;
266276

277+
/// AssignSection - Sets the symbol's section.
278+
///
279+
/// Each emitted symbol will be tracked in the ordering table,
280+
/// so we can sort on them later.
281+
void AssignSection(MCSymbol *Symbol, const MCSection *Section);
282+
267283
/// EmitLabel - Emit a label for @p Symbol into the current section.
268284
///
269285
/// This corresponds to an assembler statement such as:
@@ -620,6 +636,9 @@ class MCStreamer {
620636
/// these methods there.
621637
virtual void EmitTCEntry(const MCSymbol &S);
622638

639+
/// Flush - Causes any cached state to be written out.
640+
virtual void Flush() {}
641+
623642
/// FinishImpl - Streamer specific finalization.
624643
virtual void FinishImpl() = 0;
625644
/// Finish - Finish emission of machine code.

llvm/include/llvm/Support/Dwarf.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ enum LLVMConstants {
5959
DWARF_VERSION = 4, // Default dwarf version we output.
6060
DW_CIE_VERSION = 1, // Common frame information version.
6161
DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes.
62-
DW_PUBNAMES_VERSION = 2 // Section version number for .debug_pubnames.
62+
DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames.
63+
DW_ARANGES_VERSION = 2 // Section version number for .debug_aranges.
6364
};
6465

6566
// Special ID values that distinguish a CIE from a FDE in DWARF CFI.

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,9 @@ bool AsmPrinter::doFinalization(Module &M) {
881881
if (!ModuleFlags.empty())
882882
getObjFileLowering().emitModuleFlags(OutStreamer, ModuleFlags, Mang, TM);
883883

884+
// Make sure we wrote out everything we need.
885+
OutStreamer.Flush();
886+
884887
// Finalize debug and EH information.
885888
if (DE) {
886889
{

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,13 +181,27 @@ void CompileUnit::addLabel(DIE *Die, uint16_t Attribute, uint16_t Form,
181181
const MCSymbol *Label) {
182182
DIEValue *Value = new (DIEValueAllocator) DIELabel(Label);
183183
Die->addValue(Attribute, Form, Value);
184+
185+
SymbolCU Entry;
186+
Entry.CU = this;
187+
Entry.Sym = Label;
188+
189+
DD->addLabel(Entry);
184190
}
185191

186192
/// addLabelAddress - Add a dwarf label attribute data and value using
187193
/// DW_FORM_addr or DW_FORM_GNU_addr_index.
188194
///
189195
void CompileUnit::addLabelAddress(DIE *Die, uint16_t Attribute,
190196
MCSymbol *Label) {
197+
if (Label) {
198+
SymbolCU Entry;
199+
Entry.CU = this;
200+
Entry.Sym = Label;
201+
202+
DD->addLabel(Entry);
203+
}
204+
191205
if (!DD->useSplitDwarf()) {
192206
if (Label != NULL) {
193207
DIEValue *Value = new (DIEValueAllocator) DIELabel(Label);

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 195 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,7 @@ void DwarfDebug::beginModule() {
924924
MMI->setDebugInfoAvailability(true);
925925

926926
// Prime section data.
927-
SectionMap.insert(Asm->getObjFileLowering().getTextSection());
927+
SectionMap[Asm->getObjFileLowering().getTextSection()];
928928
}
929929

930930
// Attach DW_AT_inline attribute with inlined subprogram DIEs.
@@ -1077,16 +1077,39 @@ void DwarfDebug::finalizeModuleInfo() {
10771077
}
10781078

10791079
void DwarfDebug::endSections() {
1080-
// Standard sections final addresses.
1081-
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection());
1082-
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("text_end"));
1083-
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getDataSection());
1084-
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("data_end"));
1080+
// Filter labels by section.
1081+
for (size_t n = 0; n < Labels.size(); n++) {
1082+
const SymbolCU &SCU = Labels[n];
1083+
if (SCU.Sym->isInSection()) {
1084+
// Make a note of this symbol and it's section.
1085+
const MCSection *Section = &SCU.Sym->getSection();
1086+
if (!Section->getKind().isMetadata())
1087+
SectionMap[Section].push_back(SCU);
1088+
} else {
1089+
// Some symbols (e.g. common/bss on mach-o) can have no section but still
1090+
// appear in the output. This sucks as we rely on sections to build
1091+
// arange spans. We can do it without, but it's icky.
1092+
SectionMap[NULL].push_back(SCU);
1093+
}
1094+
}
1095+
1096+
// Add terminating symbols for each section.
1097+
for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end();
1098+
it++) {
1099+
const MCSection *Section = it->first;
1100+
MCSymbol *Sym = NULL;
10851101

1086-
// End text sections.
1087-
for (unsigned I = 0, E = SectionMap.size(); I != E; ++I) {
1088-
Asm->OutStreamer.SwitchSection(SectionMap[I]);
1089-
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("section_end", I+1));
1102+
if (Section) {
1103+
Sym = Asm->GetTempSymbol(Section->getLabelEndName());
1104+
Asm->OutStreamer.SwitchSection(Section);
1105+
Asm->OutStreamer.EmitLabel(Sym);
1106+
}
1107+
1108+
// Insert a final terminator.
1109+
SymbolCU Entry;
1110+
Entry.CU = NULL;
1111+
Entry.Sym = Sym;
1112+
SectionMap[Section].push_back(Entry);
10901113
}
10911114
}
10921115

@@ -2659,11 +2682,172 @@ void DwarfDebug::emitDebugLoc() {
26592682
}
26602683
}
26612684

2662-
// Emit visible names into a debug aranges section.
2685+
struct SymbolCUSorter {
2686+
SymbolCUSorter(const MCStreamer &s) : Streamer(s) {}
2687+
const MCStreamer &Streamer;
2688+
2689+
bool operator() (const SymbolCU &A, const SymbolCU &B) {
2690+
unsigned IA = A.Sym ? Streamer.GetSymbolOrder(A.Sym) : 0;
2691+
unsigned IB = B.Sym ? Streamer.GetSymbolOrder(B.Sym) : 0;
2692+
2693+
// Symbols with no order assigned should be placed at the end.
2694+
// (e.g. section end labels)
2695+
if (IA == 0)
2696+
IA = (unsigned)(-1);
2697+
if (IB == 0)
2698+
IB = (unsigned)(-1);
2699+
return IA < IB;
2700+
}
2701+
};
2702+
2703+
static bool SectionSort(const MCSection *A, const MCSection *B) {
2704+
std::string LA = (A ? A->getLabelBeginName() : "");
2705+
std::string LB = (B ? B->getLabelBeginName() : "");
2706+
return LA < LB;
2707+
}
2708+
2709+
static bool CUSort(const CompileUnit *A, const CompileUnit *B) {
2710+
return (A->getUniqueID() < B->getUniqueID());
2711+
}
2712+
2713+
struct ArangeSpan {
2714+
const MCSymbol *Start, *End;
2715+
};
2716+
2717+
// Emit a debug aranges section, containing a CU lookup for any
2718+
// address we can tie back to a CU.
26632719
void DwarfDebug::emitDebugARanges() {
26642720
// Start the dwarf aranges section.
26652721
Asm->OutStreamer
26662722
.SwitchSection(Asm->getObjFileLowering().getDwarfARangesSection());
2723+
2724+
typedef DenseMap<CompileUnit *, std::vector<ArangeSpan> > SpansType;
2725+
2726+
SpansType Spans;
2727+
2728+
// Build a list of sections used.
2729+
std::vector<const MCSection *> Sections;
2730+
for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end();
2731+
it++) {
2732+
const MCSection *Section = it->first;
2733+
Sections.push_back(Section);
2734+
}
2735+
2736+
// Sort the sections into order.
2737+
// This is only done to ensure consistent output order across different runs.
2738+
std::sort(Sections.begin(), Sections.end(), SectionSort);
2739+
2740+
// Build a set of address spans, sorted by CU.
2741+
for (size_t SecIdx=0;SecIdx<Sections.size();SecIdx++) {
2742+
const MCSection *Section = Sections[SecIdx];
2743+
SmallVector<SymbolCU, 8> &List = SectionMap[Section];
2744+
if (List.size() < 2)
2745+
continue;
2746+
2747+
// Sort the symbols by offset within the section.
2748+
SymbolCUSorter sorter(Asm->OutStreamer);
2749+
std::sort(List.begin(), List.end(), sorter);
2750+
2751+
// If we have no section (e.g. common), just write out
2752+
// individual spans for each symbol.
2753+
if (Section == NULL) {
2754+
for (size_t n = 0; n < List.size(); n++) {
2755+
const SymbolCU &Cur = List[n];
2756+
2757+
ArangeSpan Span;
2758+
Span.Start = Cur.Sym;
2759+
Span.End = NULL;
2760+
if (Cur.CU)
2761+
Spans[Cur.CU].push_back(Span);
2762+
}
2763+
} else {
2764+
// Build spans between each label.
2765+
const MCSymbol *StartSym = List[0].Sym;
2766+
for (size_t n = 1; n < List.size(); n++) {
2767+
const SymbolCU &Prev = List[n - 1];
2768+
const SymbolCU &Cur = List[n];
2769+
2770+
// Try and build the longest span we can within the same CU.
2771+
if (Cur.CU != Prev.CU) {
2772+
ArangeSpan Span;
2773+
Span.Start = StartSym;
2774+
Span.End = Cur.Sym;
2775+
Spans[Prev.CU].push_back(Span);
2776+
StartSym = Cur.Sym;
2777+
}
2778+
}
2779+
}
2780+
}
2781+
2782+
const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection();
2783+
unsigned PtrSize = Asm->getDataLayout().getPointerSize();
2784+
2785+
// Build a list of CUs used.
2786+
std::vector<CompileUnit *> CUs;
2787+
for (SpansType::iterator it = Spans.begin(); it != Spans.end(); it++) {
2788+
CompileUnit *CU = it->first;
2789+
CUs.push_back(CU);
2790+
}
2791+
2792+
// Sort the CU list (again, to ensure consistent output order).
2793+
std::sort(CUs.begin(), CUs.end(), CUSort);
2794+
2795+
// Emit an arange table for each CU we used.
2796+
for (size_t CUIdx=0;CUIdx<CUs.size();CUIdx++) {
2797+
CompileUnit *CU = CUs[CUIdx];
2798+
std::vector<ArangeSpan> &List = Spans[CU];
2799+
2800+
// Emit size of content not including length itself.
2801+
unsigned ContentSize
2802+
= sizeof(int16_t) // DWARF ARange version number
2803+
+ sizeof(int32_t) // Offset of CU in the .debug_info section
2804+
+ sizeof(int8_t) // Pointer Size (in bytes)
2805+
+ sizeof(int8_t); // Segment Size (in bytes)
2806+
2807+
unsigned TupleSize = PtrSize * 2;
2808+
2809+
// 7.20 in the Dwarf specs requires the table to be aligned to a tuple.
2810+
unsigned Padding = 0;
2811+
while (((sizeof(int32_t) + ContentSize + Padding) % TupleSize) != 0)
2812+
Padding++;
2813+
2814+
ContentSize += Padding;
2815+
ContentSize += (List.size() + 1) * TupleSize;
2816+
2817+
// For each compile unit, write the list of spans it covers.
2818+
Asm->OutStreamer.AddComment("Length of ARange Set");
2819+
Asm->EmitInt32(ContentSize);
2820+
Asm->OutStreamer.AddComment("DWARF Arange version number");
2821+
Asm->EmitInt16(dwarf::DW_ARANGES_VERSION);
2822+
Asm->OutStreamer.AddComment("Offset Into Debug Info Section");
2823+
Asm->EmitSectionOffset(
2824+
Asm->GetTempSymbol(ISec->getLabelBeginName(), CU->getUniqueID()),
2825+
DwarfInfoSectionSym);
2826+
Asm->OutStreamer.AddComment("Address Size (in bytes)");
2827+
Asm->EmitInt8(PtrSize);
2828+
Asm->OutStreamer.AddComment("Segment Size (in bytes)");
2829+
Asm->EmitInt8(0);
2830+
2831+
for (unsigned n = 0; n < Padding; n++)
2832+
Asm->EmitInt8(0xff);
2833+
2834+
for (unsigned n = 0; n < List.size(); n++) {
2835+
const ArangeSpan &Span = List[n];
2836+
Asm->EmitLabelReference(Span.Start, PtrSize);
2837+
2838+
// Calculate the size as being from the span start to it's end.
2839+
// If we have no valid end symbol, then we just cover the first byte.
2840+
// (this sucks, but I can't seem to figure out how to get the size)
2841+
if (Span.End)
2842+
Asm->EmitLabelDifference(Span.End, Span.Start, PtrSize);
2843+
else
2844+
Asm->OutStreamer.EmitIntValue(1, PtrSize);
2845+
}
2846+
2847+
Asm->OutStreamer.AddComment("ARange terminator");
2848+
Asm->OutStreamer.EmitIntValue(0, PtrSize);
2849+
Asm->OutStreamer.EmitIntValue(0, PtrSize);
2850+
}
26672851
}
26682852

26692853
// Emit visible names into a debug ranges section.

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,12 @@ class DwarfUnits {
300300
unsigned getCUOffset(DIE *Die);
301301
};
302302

303+
/// \brief Helper used to pair up a symbol and it's DWARF compile unit.
304+
struct SymbolCU {
305+
const MCSymbol *Sym;
306+
CompileUnit *CU;
307+
};
308+
303309
/// \brief Collects and handles dwarf debug information.
304310
class DwarfDebug {
305311
// Target of Dwarf emission.
@@ -332,8 +338,12 @@ class DwarfDebug {
332338
// separated by a zero byte, mapped to a unique id.
333339
StringMap<unsigned, BumpPtrAllocator&> SourceIdMap;
334340

341+
// List of all labels used in the output.
342+
std::vector<SymbolCU> Labels;
343+
335344
// Provides a unique id per text section.
336-
SetVector<const MCSection*> SectionMap;
345+
typedef DenseMap<const MCSection *, SmallVector<SymbolCU, 8> > SectionMapType;
346+
SectionMapType SectionMap;
337347

338348
// List of arguments for current function.
339349
SmallVector<DbgVariable *, 8> CurrentFnArguments;
@@ -669,6 +679,9 @@ class DwarfDebug {
669679
/// type units.
670680
void addTypeUnitType(DIE *Die) { TypeUnits.push_back(Die); }
671681

682+
/// \brief Add a label so that arange data can be generated for it.
683+
void addLabel(SymbolCU SCU) { Labels.push_back(SCU); }
684+
672685
/// \brief Look up the source id with the given directory and source file
673686
/// names. If none currently exists, create a new id and insert it in the
674687
/// SourceIds map.

0 commit comments

Comments
 (0)