Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 591f9ee

Browse files
committed
Emit DWARF info for all code section in an assembly file
Currently, when using llvm as an assembler, DWARF debug information is only generated for the .text section. This patch modifies this so that DWARF info is emitted for all executable sections. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211273 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent bb804ee commit 591f9ee

File tree

8 files changed

+220
-70
lines changed

8 files changed

+220
-70
lines changed

include/llvm/ADT/MapVector.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@ class MapVector {
123123
Map.erase(Pos);
124124
Vector.pop_back();
125125
}
126+
127+
/// \brief Remove the element given by Iterator.
128+
/// Returns an iterator to the element following the one which was removed,
129+
/// which may be end().
130+
typename VectorType::iterator erase(typename VectorType::iterator Iterator) {
131+
typename MapType::iterator MapIterator = Map.find(Iterator->first);
132+
Map.erase(MapIterator);
133+
return Vector.erase(Iterator);
134+
}
126135
};
127136

128137
}

include/llvm/MC/MCContext.h

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@
1111
#define LLVM_MC_MCCONTEXT_H
1212

1313
#include "llvm/ADT/DenseMap.h"
14+
#include "llvm/ADT/SetVector.h"
1415
#include "llvm/ADT/SmallString.h"
1516
#include "llvm/ADT/SmallVector.h"
1617
#include "llvm/ADT/StringMap.h"
1718
#include "llvm/MC/MCDwarf.h"
19+
#include "llvm/MC/MCStreamer.h"
1820
#include "llvm/MC/SectionKind.h"
1921
#include "llvm/Support/Allocator.h"
2022
#include "llvm/Support/Compiler.h"
@@ -129,11 +131,10 @@ namespace llvm {
129131
/// assembly source files.
130132
unsigned GenDwarfFileNumber;
131133

132-
/// The default initial text section that we generate dwarf debugging line
133-
/// info for when generating dwarf assembly source files.
134-
const MCSection *GenDwarfSection;
135-
/// Symbols created for the start and end of this section.
136-
MCSymbol *GenDwarfSectionStartSym, *GenDwarfSectionEndSym;
134+
/// Symbols created for the start and end of each section, used for
135+
/// generating the .debug_ranges and .debug_aranges sections.
136+
MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> >
137+
SectionStartEndSyms;
137138

138139
/// The information gathered from labels that will have dwarf label
139140
/// entries when generating dwarf assembly source files.
@@ -374,16 +375,18 @@ namespace llvm {
374375
void setGenDwarfFileNumber(unsigned FileNumber) {
375376
GenDwarfFileNumber = FileNumber;
376377
}
377-
const MCSection *getGenDwarfSection() { return GenDwarfSection; }
378-
void setGenDwarfSection(const MCSection *Sec) { GenDwarfSection = Sec; }
379-
MCSymbol *getGenDwarfSectionStartSym() { return GenDwarfSectionStartSym; }
380-
void setGenDwarfSectionStartSym(MCSymbol *Sym) {
381-
GenDwarfSectionStartSym = Sym;
378+
MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> > &
379+
getGenDwarfSectionSyms() {
380+
return SectionStartEndSyms;
382381
}
383-
MCSymbol *getGenDwarfSectionEndSym() { return GenDwarfSectionEndSym; }
384-
void setGenDwarfSectionEndSym(MCSymbol *Sym) {
385-
GenDwarfSectionEndSym = Sym;
382+
std::pair<MapVector<const MCSection *,
383+
std::pair<MCSymbol *, MCSymbol *> >::iterator,
384+
bool>
385+
addGenDwarfSection(const MCSection *Sec) {
386+
return SectionStartEndSyms.insert(
387+
std::make_pair(Sec, std::make_pair(nullptr, nullptr)));
386388
}
389+
void finalizeDwarfSections(MCStreamer &MCOS);
387390
const std::vector<MCGenDwarfLabelEntry> &getMCGenDwarfLabelEntries() const {
388391
return MCGenDwarfLabelEntries;
389392
}

include/llvm/MC/MCObjectStreamer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ class MCObjectStreamer : public MCStreamer {
126126
void EmitFill(uint64_t NumBytes, uint8_t FillValue) override;
127127
void EmitZeros(uint64_t NumBytes) override;
128128
void FinishImpl() override;
129+
130+
virtual bool mayHaveInstructions() const {
131+
return getCurrentSectionData()->hasInstructions();
132+
}
129133
};
130134

131135
} // end namespace llvm

include/llvm/MC/MCStreamer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,8 @@ class MCStreamer {
722722
virtual void FinishImpl() = 0;
723723
/// Finish - Finish emission of machine code.
724724
void Finish();
725+
726+
virtual bool mayHaveInstructions() const { return true; }
725727
};
726728

727729
/// createNullStreamer - Create a dummy machine code streamer, which does

lib/MC/MCContext.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,29 @@ bool MCContext::isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID) {
340340
return !MCDwarfFiles[FileNumber].Name.empty();
341341
}
342342

343+
/// finalizeDwarfSections - Emit end symbols for each non-empty code section.
344+
/// Also remove empty sections from SectionStartEndSyms, to avoid generating
345+
/// useless debug info for them.
346+
void MCContext::finalizeDwarfSections(MCStreamer &MCOS) {
347+
MCContext &context = MCOS.getContext();
348+
349+
auto sec = SectionStartEndSyms.begin();
350+
while (sec != SectionStartEndSyms.end()) {
351+
assert(sec->second.first && "Start symbol must be set by now");
352+
MCOS.SwitchSection(sec->first);
353+
if (MCOS.mayHaveInstructions()) {
354+
MCSymbol *SectionEndSym = context.CreateTempSymbol();
355+
MCOS.EmitLabel(SectionEndSym);
356+
sec->second.second = SectionEndSym;
357+
++sec;
358+
} else {
359+
MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> >::iterator
360+
to_erase = sec;
361+
sec = SectionStartEndSyms.erase(to_erase);
362+
}
363+
}
364+
}
365+
343366
void MCContext::FatalError(SMLoc Loc, const Twine &Msg) const {
344367
// If we have a source manager and a location, use it. Otherwise just
345368
// use the generic report_fatal_error().

lib/MC/MCDwarf.cpp

Lines changed: 134 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/MC/MCObjectFileInfo.h"
2020
#include "llvm/MC/MCObjectStreamer.h"
2121
#include "llvm/MC/MCRegisterInfo.h"
22+
#include "llvm/MC/MCSection.h"
2223
#include "llvm/MC/MCSymbol.h"
2324
#include "llvm/Support/Debug.h"
2425
#include "llvm/Support/ErrorHandling.h"
@@ -518,8 +519,12 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
518519
MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit);
519520
MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
520521
EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4);
521-
EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
522-
EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);
522+
if (MCOS->getContext().getGenDwarfSectionSyms().size() > 1) {
523+
EmitAbbrev(MCOS, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4);
524+
} else {
525+
EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
526+
EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);
527+
}
523528
EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
524529
if (!context.getCompilationDir().empty())
525530
EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string);
@@ -552,20 +557,14 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
552557
}
553558

554559
// When generating dwarf for assembly source files this emits the data for
555-
// .debug_aranges section. Which contains a header and a table of pairs of
556-
// PointerSize'ed values for the address and size of section(s) with line table
557-
// entries (just the default .text in our case) and a terminating pair of zeros.
560+
// .debug_aranges section. This section contains a header and a table of pairs
561+
// of PointerSize'ed values for the address and size of section(s) with line
562+
// table entries.
558563
static void EmitGenDwarfAranges(MCStreamer *MCOS,
559564
const MCSymbol *InfoSectionSymbol) {
560565
MCContext &context = MCOS->getContext();
561566

562-
// Create a symbol at the end of the section that we are creating the dwarf
563-
// debugging info to use later in here as part of the expression to calculate
564-
// the size of the section for the table.
565-
MCOS->SwitchSection(context.getGenDwarfSection());
566-
MCSymbol *SectionEndSym = context.CreateTempSymbol();
567-
MCOS->EmitLabel(SectionEndSym);
568-
context.setGenDwarfSectionEndSym(SectionEndSym);
567+
auto &Sections = context.getGenDwarfSectionSyms();
569568

570569
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
571570

@@ -583,8 +582,8 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS,
583582
Length += Pad;
584583

585584
// Add the size of the pair of PointerSize'ed values for the address and size
586-
// of the one default .text section we have in the table.
587-
Length += 2 * AddrSize;
585+
// of each section we have in the table.
586+
Length += 2 * AddrSize * Sections.size();
588587
// And the pair of terminating zeros.
589588
Length += 2 * AddrSize;
590589

@@ -608,14 +607,21 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS,
608607
for(int i = 0; i < Pad; i++)
609608
MCOS->EmitIntValue(0, 1);
610609

611-
// Now emit the table of pairs of PointerSize'ed values for the section(s)
612-
// address and size, in our case just the one default .text section.
613-
const MCExpr *Addr = MCSymbolRefExpr::Create(
614-
context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context);
615-
const MCExpr *Size = MakeStartMinusEndExpr(*MCOS,
616-
*context.getGenDwarfSectionStartSym(), *SectionEndSym, 0);
617-
MCOS->EmitValue(Addr, AddrSize);
618-
MCOS->EmitAbsValue(Size, AddrSize);
610+
// Now emit the table of pairs of PointerSize'ed values for the section
611+
// addresses and sizes.
612+
for (const auto &sec : Sections) {
613+
MCSymbol* StartSymbol = sec.second.first;
614+
MCSymbol* EndSymbol = sec.second.second;
615+
assert(StartSymbol && "StartSymbol must not be NULL");
616+
assert(EndSymbol && "EndSymbol must not be NULL");
617+
618+
const MCExpr *Addr = MCSymbolRefExpr::Create(
619+
StartSymbol, MCSymbolRefExpr::VK_None, context);
620+
const MCExpr *Size = MakeStartMinusEndExpr(*MCOS,
621+
*StartSymbol, *EndSymbol, 0);
622+
MCOS->EmitValue(Addr, AddrSize);
623+
MCOS->EmitAbsValue(Size, AddrSize);
624+
}
619625

620626
// And finally the pair of terminating zeros.
621627
MCOS->EmitIntValue(0, AddrSize);
@@ -627,7 +633,8 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS,
627633
// DIE and a list of label DIEs.
628634
static void EmitGenDwarfInfo(MCStreamer *MCOS,
629635
const MCSymbol *AbbrevSectionSymbol,
630-
const MCSymbol *LineSectionSymbol) {
636+
const MCSymbol *LineSectionSymbol,
637+
const MCSymbol *RangesSectionSymbol) {
631638
MCContext &context = MCOS->getContext();
632639

633640
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
@@ -674,15 +681,37 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS,
674681
MCOS->EmitIntValue(0, 4);
675682
}
676683

677-
// AT_low_pc, the first address of the default .text section.
678-
const MCExpr *Start = MCSymbolRefExpr::Create(
679-
context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context);
680-
MCOS->EmitValue(Start, AddrSize);
684+
if (RangesSectionSymbol) {
685+
// There are multiple sections containing code, so we must use the
686+
// .debug_ranges sections.
681687

682-
// AT_high_pc, the last address of the default .text section.
683-
const MCExpr *End = MCSymbolRefExpr::Create(
684-
context.getGenDwarfSectionEndSym(), MCSymbolRefExpr::VK_None, context);
685-
MCOS->EmitValue(End, AddrSize);
688+
// AT_ranges, the 4 byte offset from the start of the .debug_ranges section
689+
// to the address range list for this compilation unit.
690+
MCOS->EmitSymbolValue(RangesSectionSymbol, 4);
691+
} else {
692+
// If we only have one non-empty code section, we can use the simpler
693+
// AT_low_pc and AT_high_pc attributes.
694+
695+
// Find the first (and only) non-empty text section
696+
auto &Sections = context.getGenDwarfSectionSyms();
697+
const auto TextSection = Sections.begin();
698+
assert(TextSection != Sections.end() && "No text section found");
699+
700+
MCSymbol* StartSymbol = TextSection->second.first;
701+
MCSymbol* EndSymbol = TextSection->second.second;
702+
assert(StartSymbol && "StartSymbol must not be NULL");
703+
assert(EndSymbol && "EndSymbol must not be NULL");
704+
705+
// AT_low_pc, the first address of the default .text section.
706+
const MCExpr *Start = MCSymbolRefExpr::Create(
707+
StartSymbol, MCSymbolRefExpr::VK_None, context);
708+
MCOS->EmitValue(Start, AddrSize);
709+
710+
// AT_high_pc, the last address of the default .text section.
711+
const MCExpr *End = MCSymbolRefExpr::Create(
712+
EndSymbol, MCSymbolRefExpr::VK_None, context);
713+
MCOS->EmitValue(End, AddrSize);
714+
}
686715

687716
// AT_name, the name of the source file. Reconstruct from the first directory
688717
// and file table entries.
@@ -766,13 +795,51 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS,
766795
MCOS->EmitLabel(InfoEnd);
767796
}
768797

798+
// When generating dwarf for assembly source files this emits the data for
799+
// .debug_ranges section. We only emit one range list, which spans all of the
800+
// executable sections of this file.
801+
static void EmitGenDwarfRanges(MCStreamer *MCOS) {
802+
MCContext &context = MCOS->getContext();
803+
auto &Sections = context.getGenDwarfSectionSyms();
804+
805+
const MCAsmInfo *AsmInfo = context.getAsmInfo();
806+
int AddrSize = AsmInfo->getPointerSize();
807+
808+
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
809+
810+
for (const auto sec : Sections) {
811+
812+
MCSymbol* StartSymbol = sec.second.first;
813+
MCSymbol* EndSymbol = sec.second.second;
814+
assert(StartSymbol && "StartSymbol must not be NULL");
815+
assert(EndSymbol && "EndSymbol must not be NULL");
816+
817+
// Emit a base address selection entry for the start of this section
818+
const MCExpr *SectionStartAddr = MCSymbolRefExpr::Create(
819+
StartSymbol, MCSymbolRefExpr::VK_None, context);
820+
MCOS->EmitFill(AddrSize, 0xFF);
821+
MCOS->EmitValue(SectionStartAddr, AddrSize);
822+
823+
// Emit a range list entry spanning this section
824+
const MCExpr *SectionSize = MakeStartMinusEndExpr(*MCOS,
825+
*StartSymbol, *EndSymbol, 0);
826+
MCOS->EmitIntValue(0, AddrSize);
827+
MCOS->EmitAbsValue(SectionSize, AddrSize);
828+
}
829+
830+
// Emit end of list entry
831+
MCOS->EmitIntValue(0, AddrSize);
832+
MCOS->EmitIntValue(0, AddrSize);
833+
}
834+
769835
//
770836
// When generating dwarf for assembly source files this emits the Dwarf
771837
// sections.
772838
//
773839
void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
774-
// Create the dwarf sections in this order (.debug_line already created).
775840
MCContext &context = MCOS->getContext();
841+
842+
// Create the dwarf sections in this order (.debug_line already created).
776843
const MCAsmInfo *AsmInfo = context.getAsmInfo();
777844
bool CreateDwarfSectionSymbols =
778845
AsmInfo->doesDwarfUseRelocationsAcrossSections();
@@ -781,6 +848,22 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
781848
LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0);
782849
MCSymbol *AbbrevSectionSymbol = nullptr;
783850
MCSymbol *InfoSectionSymbol = nullptr;
851+
MCSymbol *RangesSectionSymbol = NULL;
852+
853+
// Create end symbols for each section, and remove empty sections
854+
MCOS->getContext().finalizeDwarfSections(*MCOS);
855+
856+
// If there are no sections to generate debug info for, we don't need
857+
// to do anything
858+
if (MCOS->getContext().getGenDwarfSectionSyms().empty())
859+
return;
860+
861+
// We only need to use the .debug_ranges section if we have multiple
862+
// code sections.
863+
const bool UseRangesSection =
864+
MCOS->getContext().getGenDwarfSectionSyms().size() > 1;
865+
CreateDwarfSectionSymbols |= UseRangesSection;
866+
784867
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
785868
if (CreateDwarfSectionSymbols) {
786869
InfoSectionSymbol = context.CreateTempSymbol();
@@ -791,20 +874,30 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
791874
AbbrevSectionSymbol = context.CreateTempSymbol();
792875
MCOS->EmitLabel(AbbrevSectionSymbol);
793876
}
794-
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
877+
if (UseRangesSection) {
878+
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
879+
if (CreateDwarfSectionSymbols) {
880+
RangesSectionSymbol = context.CreateTempSymbol();
881+
MCOS->EmitLabel(RangesSectionSymbol);
882+
}
883+
}
795884

796-
// If there are no line table entries then do not emit any section contents.
797-
if (!context.hasMCLineSections())
798-
return;
885+
assert((RangesSectionSymbol != NULL) || !UseRangesSection);
886+
887+
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
799888

800889
// Output the data for .debug_aranges section.
801890
EmitGenDwarfAranges(MCOS, InfoSectionSymbol);
802891

892+
if (UseRangesSection)
893+
EmitGenDwarfRanges(MCOS);
894+
803895
// Output the data for .debug_abbrev section.
804896
EmitGenDwarfAbbrev(MCOS);
805897

806898
// Output the data for .debug_info section.
807-
EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol);
899+
EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol,
900+
RangesSectionSymbol);
808901
}
809902

810903
//
@@ -815,12 +908,13 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
815908
//
816909
void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
817910
SourceMgr &SrcMgr, SMLoc &Loc) {
818-
// We won't create dwarf labels for temporary symbols or symbols not in
819-
// the default text.
911+
// We won't create dwarf labels for temporary symbols.
820912
if (Symbol->isTemporary())
821913
return;
822914
MCContext &context = MCOS->getContext();
823-
if (context.getGenDwarfSection() != MCOS->getCurrentSection().first)
915+
// We won't create dwarf labels for symbols in sections that we are not
916+
// generating debug info for.
917+
if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSection().first))
824918
return;
825919

826920
// The dwarf label's name does not have the symbol name's leading

0 commit comments

Comments
 (0)