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
This commit is contained in:
Oliver Stannard 2014-06-19 15:52:37 +00:00
parent bb804ee909
commit 591f9ee076
8 changed files with 220 additions and 70 deletions

View File

@ -123,6 +123,15 @@ public:
Map.erase(Pos); Map.erase(Pos);
Vector.pop_back(); Vector.pop_back();
} }
/// \brief Remove the element given by Iterator.
/// Returns an iterator to the element following the one which was removed,
/// which may be end().
typename VectorType::iterator erase(typename VectorType::iterator Iterator) {
typename MapType::iterator MapIterator = Map.find(Iterator->first);
Map.erase(MapIterator);
return Vector.erase(Iterator);
}
}; };
} }

View File

@ -11,10 +11,12 @@
#define LLVM_MC_MCCONTEXT_H #define LLVM_MC_MCCONTEXT_H
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/SectionKind.h" #include "llvm/MC/SectionKind.h"
#include "llvm/Support/Allocator.h" #include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
@ -129,11 +131,10 @@ namespace llvm {
/// assembly source files. /// assembly source files.
unsigned GenDwarfFileNumber; unsigned GenDwarfFileNumber;
/// The default initial text section that we generate dwarf debugging line /// Symbols created for the start and end of each section, used for
/// info for when generating dwarf assembly source files. /// generating the .debug_ranges and .debug_aranges sections.
const MCSection *GenDwarfSection; MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> >
/// Symbols created for the start and end of this section. SectionStartEndSyms;
MCSymbol *GenDwarfSectionStartSym, *GenDwarfSectionEndSym;
/// The information gathered from labels that will have dwarf label /// The information gathered from labels that will have dwarf label
/// entries when generating dwarf assembly source files. /// entries when generating dwarf assembly source files.
@ -374,16 +375,18 @@ namespace llvm {
void setGenDwarfFileNumber(unsigned FileNumber) { void setGenDwarfFileNumber(unsigned FileNumber) {
GenDwarfFileNumber = FileNumber; GenDwarfFileNumber = FileNumber;
} }
const MCSection *getGenDwarfSection() { return GenDwarfSection; } MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> > &
void setGenDwarfSection(const MCSection *Sec) { GenDwarfSection = Sec; } getGenDwarfSectionSyms() {
MCSymbol *getGenDwarfSectionStartSym() { return GenDwarfSectionStartSym; } return SectionStartEndSyms;
void setGenDwarfSectionStartSym(MCSymbol *Sym) {
GenDwarfSectionStartSym = Sym;
} }
MCSymbol *getGenDwarfSectionEndSym() { return GenDwarfSectionEndSym; } std::pair<MapVector<const MCSection *,
void setGenDwarfSectionEndSym(MCSymbol *Sym) { std::pair<MCSymbol *, MCSymbol *> >::iterator,
GenDwarfSectionEndSym = Sym; bool>
addGenDwarfSection(const MCSection *Sec) {
return SectionStartEndSyms.insert(
std::make_pair(Sec, std::make_pair(nullptr, nullptr)));
} }
void finalizeDwarfSections(MCStreamer &MCOS);
const std::vector<MCGenDwarfLabelEntry> &getMCGenDwarfLabelEntries() const { const std::vector<MCGenDwarfLabelEntry> &getMCGenDwarfLabelEntries() const {
return MCGenDwarfLabelEntries; return MCGenDwarfLabelEntries;
} }

View File

@ -126,6 +126,10 @@ public:
void EmitFill(uint64_t NumBytes, uint8_t FillValue) override; void EmitFill(uint64_t NumBytes, uint8_t FillValue) override;
void EmitZeros(uint64_t NumBytes) override; void EmitZeros(uint64_t NumBytes) override;
void FinishImpl() override; void FinishImpl() override;
virtual bool mayHaveInstructions() const {
return getCurrentSectionData()->hasInstructions();
}
}; };
} // end namespace llvm } // end namespace llvm

View File

@ -722,6 +722,8 @@ public:
virtual void FinishImpl() = 0; virtual void FinishImpl() = 0;
/// Finish - Finish emission of machine code. /// Finish - Finish emission of machine code.
void Finish(); void Finish();
virtual bool mayHaveInstructions() const { return true; }
}; };
/// createNullStreamer - Create a dummy machine code streamer, which does /// createNullStreamer - Create a dummy machine code streamer, which does

View File

@ -340,6 +340,29 @@ bool MCContext::isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID) {
return !MCDwarfFiles[FileNumber].Name.empty(); return !MCDwarfFiles[FileNumber].Name.empty();
} }
/// finalizeDwarfSections - Emit end symbols for each non-empty code section.
/// Also remove empty sections from SectionStartEndSyms, to avoid generating
/// useless debug info for them.
void MCContext::finalizeDwarfSections(MCStreamer &MCOS) {
MCContext &context = MCOS.getContext();
auto sec = SectionStartEndSyms.begin();
while (sec != SectionStartEndSyms.end()) {
assert(sec->second.first && "Start symbol must be set by now");
MCOS.SwitchSection(sec->first);
if (MCOS.mayHaveInstructions()) {
MCSymbol *SectionEndSym = context.CreateTempSymbol();
MCOS.EmitLabel(SectionEndSym);
sec->second.second = SectionEndSym;
++sec;
} else {
MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> >::iterator
to_erase = sec;
sec = SectionStartEndSyms.erase(to_erase);
}
}
}
void MCContext::FatalError(SMLoc Loc, const Twine &Msg) const { void MCContext::FatalError(SMLoc Loc, const Twine &Msg) const {
// If we have a source manager and a location, use it. Otherwise just // If we have a source manager and a location, use it. Otherwise just
// use the generic report_fatal_error(). // use the generic report_fatal_error().

View File

@ -19,6 +19,7 @@
#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
@ -518,8 +519,12 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit); MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit);
MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1);
EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4); EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4);
EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); if (MCOS->getContext().getGenDwarfSectionSyms().size() > 1) {
EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); EmitAbbrev(MCOS, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4);
} else {
EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);
}
EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
if (!context.getCompilationDir().empty()) if (!context.getCompilationDir().empty())
EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string); EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string);
@ -552,20 +557,14 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
} }
// When generating dwarf for assembly source files this emits the data for // When generating dwarf for assembly source files this emits the data for
// .debug_aranges section. Which contains a header and a table of pairs of // .debug_aranges section. This section contains a header and a table of pairs
// PointerSize'ed values for the address and size of section(s) with line table // of PointerSize'ed values for the address and size of section(s) with line
// entries (just the default .text in our case) and a terminating pair of zeros. // table entries.
static void EmitGenDwarfAranges(MCStreamer *MCOS, static void EmitGenDwarfAranges(MCStreamer *MCOS,
const MCSymbol *InfoSectionSymbol) { const MCSymbol *InfoSectionSymbol) {
MCContext &context = MCOS->getContext(); MCContext &context = MCOS->getContext();
// Create a symbol at the end of the section that we are creating the dwarf auto &Sections = context.getGenDwarfSectionSyms();
// debugging info to use later in here as part of the expression to calculate
// the size of the section for the table.
MCOS->SwitchSection(context.getGenDwarfSection());
MCSymbol *SectionEndSym = context.CreateTempSymbol();
MCOS->EmitLabel(SectionEndSym);
context.setGenDwarfSectionEndSym(SectionEndSym);
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
@ -583,8 +582,8 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS,
Length += Pad; Length += Pad;
// Add the size of the pair of PointerSize'ed values for the address and size // Add the size of the pair of PointerSize'ed values for the address and size
// of the one default .text section we have in the table. // of each section we have in the table.
Length += 2 * AddrSize; Length += 2 * AddrSize * Sections.size();
// And the pair of terminating zeros. // And the pair of terminating zeros.
Length += 2 * AddrSize; Length += 2 * AddrSize;
@ -608,14 +607,21 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS,
for(int i = 0; i < Pad; i++) for(int i = 0; i < Pad; i++)
MCOS->EmitIntValue(0, 1); MCOS->EmitIntValue(0, 1);
// Now emit the table of pairs of PointerSize'ed values for the section(s) // Now emit the table of pairs of PointerSize'ed values for the section
// address and size, in our case just the one default .text section. // addresses and sizes.
const MCExpr *Addr = MCSymbolRefExpr::Create( for (const auto &sec : Sections) {
context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); MCSymbol* StartSymbol = sec.second.first;
const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, MCSymbol* EndSymbol = sec.second.second;
*context.getGenDwarfSectionStartSym(), *SectionEndSym, 0); assert(StartSymbol && "StartSymbol must not be NULL");
MCOS->EmitValue(Addr, AddrSize); assert(EndSymbol && "EndSymbol must not be NULL");
MCOS->EmitAbsValue(Size, AddrSize);
const MCExpr *Addr = MCSymbolRefExpr::Create(
StartSymbol, MCSymbolRefExpr::VK_None, context);
const MCExpr *Size = MakeStartMinusEndExpr(*MCOS,
*StartSymbol, *EndSymbol, 0);
MCOS->EmitValue(Addr, AddrSize);
MCOS->EmitAbsValue(Size, AddrSize);
}
// And finally the pair of terminating zeros. // And finally the pair of terminating zeros.
MCOS->EmitIntValue(0, AddrSize); MCOS->EmitIntValue(0, AddrSize);
@ -627,7 +633,8 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS,
// DIE and a list of label DIEs. // DIE and a list of label DIEs.
static void EmitGenDwarfInfo(MCStreamer *MCOS, static void EmitGenDwarfInfo(MCStreamer *MCOS,
const MCSymbol *AbbrevSectionSymbol, const MCSymbol *AbbrevSectionSymbol,
const MCSymbol *LineSectionSymbol) { const MCSymbol *LineSectionSymbol,
const MCSymbol *RangesSectionSymbol) {
MCContext &context = MCOS->getContext(); MCContext &context = MCOS->getContext();
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
@ -674,15 +681,37 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS,
MCOS->EmitIntValue(0, 4); MCOS->EmitIntValue(0, 4);
} }
// AT_low_pc, the first address of the default .text section. if (RangesSectionSymbol) {
const MCExpr *Start = MCSymbolRefExpr::Create( // There are multiple sections containing code, so we must use the
context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); // .debug_ranges sections.
MCOS->EmitValue(Start, AddrSize);
// AT_high_pc, the last address of the default .text section. // AT_ranges, the 4 byte offset from the start of the .debug_ranges section
const MCExpr *End = MCSymbolRefExpr::Create( // to the address range list for this compilation unit.
context.getGenDwarfSectionEndSym(), MCSymbolRefExpr::VK_None, context); MCOS->EmitSymbolValue(RangesSectionSymbol, 4);
MCOS->EmitValue(End, AddrSize); } else {
// If we only have one non-empty code section, we can use the simpler
// AT_low_pc and AT_high_pc attributes.
// Find the first (and only) non-empty text section
auto &Sections = context.getGenDwarfSectionSyms();
const auto TextSection = Sections.begin();
assert(TextSection != Sections.end() && "No text section found");
MCSymbol* StartSymbol = TextSection->second.first;
MCSymbol* EndSymbol = TextSection->second.second;
assert(StartSymbol && "StartSymbol must not be NULL");
assert(EndSymbol && "EndSymbol must not be NULL");
// AT_low_pc, the first address of the default .text section.
const MCExpr *Start = MCSymbolRefExpr::Create(
StartSymbol, MCSymbolRefExpr::VK_None, context);
MCOS->EmitValue(Start, AddrSize);
// AT_high_pc, the last address of the default .text section.
const MCExpr *End = MCSymbolRefExpr::Create(
EndSymbol, MCSymbolRefExpr::VK_None, context);
MCOS->EmitValue(End, AddrSize);
}
// AT_name, the name of the source file. Reconstruct from the first directory // AT_name, the name of the source file. Reconstruct from the first directory
// and file table entries. // and file table entries.
@ -766,13 +795,51 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS,
MCOS->EmitLabel(InfoEnd); MCOS->EmitLabel(InfoEnd);
} }
// When generating dwarf for assembly source files this emits the data for
// .debug_ranges section. We only emit one range list, which spans all of the
// executable sections of this file.
static void EmitGenDwarfRanges(MCStreamer *MCOS) {
MCContext &context = MCOS->getContext();
auto &Sections = context.getGenDwarfSectionSyms();
const MCAsmInfo *AsmInfo = context.getAsmInfo();
int AddrSize = AsmInfo->getPointerSize();
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
for (const auto sec : Sections) {
MCSymbol* StartSymbol = sec.second.first;
MCSymbol* EndSymbol = sec.second.second;
assert(StartSymbol && "StartSymbol must not be NULL");
assert(EndSymbol && "EndSymbol must not be NULL");
// Emit a base address selection entry for the start of this section
const MCExpr *SectionStartAddr = MCSymbolRefExpr::Create(
StartSymbol, MCSymbolRefExpr::VK_None, context);
MCOS->EmitFill(AddrSize, 0xFF);
MCOS->EmitValue(SectionStartAddr, AddrSize);
// Emit a range list entry spanning this section
const MCExpr *SectionSize = MakeStartMinusEndExpr(*MCOS,
*StartSymbol, *EndSymbol, 0);
MCOS->EmitIntValue(0, AddrSize);
MCOS->EmitAbsValue(SectionSize, AddrSize);
}
// Emit end of list entry
MCOS->EmitIntValue(0, AddrSize);
MCOS->EmitIntValue(0, AddrSize);
}
// //
// When generating dwarf for assembly source files this emits the Dwarf // When generating dwarf for assembly source files this emits the Dwarf
// sections. // sections.
// //
void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
// Create the dwarf sections in this order (.debug_line already created).
MCContext &context = MCOS->getContext(); MCContext &context = MCOS->getContext();
// Create the dwarf sections in this order (.debug_line already created).
const MCAsmInfo *AsmInfo = context.getAsmInfo(); const MCAsmInfo *AsmInfo = context.getAsmInfo();
bool CreateDwarfSectionSymbols = bool CreateDwarfSectionSymbols =
AsmInfo->doesDwarfUseRelocationsAcrossSections(); AsmInfo->doesDwarfUseRelocationsAcrossSections();
@ -781,6 +848,22 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0); LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0);
MCSymbol *AbbrevSectionSymbol = nullptr; MCSymbol *AbbrevSectionSymbol = nullptr;
MCSymbol *InfoSectionSymbol = nullptr; MCSymbol *InfoSectionSymbol = nullptr;
MCSymbol *RangesSectionSymbol = NULL;
// Create end symbols for each section, and remove empty sections
MCOS->getContext().finalizeDwarfSections(*MCOS);
// If there are no sections to generate debug info for, we don't need
// to do anything
if (MCOS->getContext().getGenDwarfSectionSyms().empty())
return;
// We only need to use the .debug_ranges section if we have multiple
// code sections.
const bool UseRangesSection =
MCOS->getContext().getGenDwarfSectionSyms().size() > 1;
CreateDwarfSectionSymbols |= UseRangesSection;
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
if (CreateDwarfSectionSymbols) { if (CreateDwarfSectionSymbols) {
InfoSectionSymbol = context.CreateTempSymbol(); InfoSectionSymbol = context.CreateTempSymbol();
@ -791,20 +874,30 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
AbbrevSectionSymbol = context.CreateTempSymbol(); AbbrevSectionSymbol = context.CreateTempSymbol();
MCOS->EmitLabel(AbbrevSectionSymbol); MCOS->EmitLabel(AbbrevSectionSymbol);
} }
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); if (UseRangesSection) {
MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection());
if (CreateDwarfSectionSymbols) {
RangesSectionSymbol = context.CreateTempSymbol();
MCOS->EmitLabel(RangesSectionSymbol);
}
}
// If there are no line table entries then do not emit any section contents. assert((RangesSectionSymbol != NULL) || !UseRangesSection);
if (!context.hasMCLineSections())
return; MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
// Output the data for .debug_aranges section. // Output the data for .debug_aranges section.
EmitGenDwarfAranges(MCOS, InfoSectionSymbol); EmitGenDwarfAranges(MCOS, InfoSectionSymbol);
if (UseRangesSection)
EmitGenDwarfRanges(MCOS);
// Output the data for .debug_abbrev section. // Output the data for .debug_abbrev section.
EmitGenDwarfAbbrev(MCOS); EmitGenDwarfAbbrev(MCOS);
// Output the data for .debug_info section. // Output the data for .debug_info section.
EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol); EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol,
RangesSectionSymbol);
} }
// //
@ -815,12 +908,13 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
// //
void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
SourceMgr &SrcMgr, SMLoc &Loc) { SourceMgr &SrcMgr, SMLoc &Loc) {
// We won't create dwarf labels for temporary symbols or symbols not in // We won't create dwarf labels for temporary symbols.
// the default text.
if (Symbol->isTemporary()) if (Symbol->isTemporary())
return; return;
MCContext &context = MCOS->getContext(); MCContext &context = MCOS->getContext();
if (context.getGenDwarfSection() != MCOS->getCurrentSection().first) // We won't create dwarf labels for symbols in sections that we are not
// generating debug info for.
if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSection().first))
return; return;
// The dwarf label's name does not have the symbol name's leading // The dwarf label's name does not have the symbol name's leading

View File

@ -633,10 +633,12 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// If we are generating dwarf for assembly source files save the initial text // If we are generating dwarf for assembly source files save the initial text
// section and generate a .file directive. // section and generate a .file directive.
if (getContext().getGenDwarfForAssembly()) { if (getContext().getGenDwarfForAssembly()) {
getContext().setGenDwarfSection(getStreamer().getCurrentSection().first);
MCSymbol *SectionStartSym = getContext().CreateTempSymbol(); MCSymbol *SectionStartSym = getContext().CreateTempSymbol();
getStreamer().EmitLabel(SectionStartSym); getStreamer().EmitLabel(SectionStartSym);
getContext().setGenDwarfSectionStartSym(SectionStartSym); auto InsertResult = getContext().addGenDwarfSection(
getStreamer().getCurrentSection().first);
assert(InsertResult.second && ".text section should not have debug info yet");
InsertResult.first->second.first = SectionStartSym;
getContext().setGenDwarfFileNumber(getStreamer().EmitDwarfFileDirective( getContext().setGenDwarfFileNumber(getStreamer().EmitDwarfFileDirective(
0, StringRef(), getContext().getMainFileName())); 0, StringRef(), getContext().getMainFileName()));
} }
@ -1592,12 +1594,11 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) {
printMessage(IDLoc, SourceMgr::DK_Note, OS.str()); printMessage(IDLoc, SourceMgr::DK_Note, OS.str());
} }
// If we are generating dwarf for assembly source files and the current // If we are generating dwarf for the current section then generate a .loc
// section is the initial text section then generate a .loc directive for // directive for the instruction.
// the instruction.
if (!HadError && getContext().getGenDwarfForAssembly() && if (!HadError && getContext().getGenDwarfForAssembly() &&
getContext().getGenDwarfSection() == getContext().getGenDwarfSectionSyms().count(
getStreamer().getCurrentSection().first) { getStreamer().getCurrentSection().first)) {
unsigned Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); unsigned Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer);
@ -2029,7 +2030,7 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
break; break;
if (FAI >= NParameters) { if (FAI >= NParameters) {
assert(M && "expected macro to be defined"); assert(M && "expected macro to be defined");
Error(IDLoc, Error(IDLoc,
"parameter named '" + FA.Name + "' does not exist for macro '" + "parameter named '" + FA.Name + "' does not exist for macro '" +
M->Name + "'"); M->Name + "'");

View File

@ -150,7 +150,7 @@ public:
private: private:
bool ParseSectionName(StringRef &SectionName); bool ParseSectionName(StringRef &SectionName);
bool ParseSectionArguments(bool IsPush); bool ParseSectionArguments(bool IsPush, SMLoc loc);
unsigned parseSunStyleSectionFlags(); unsigned parseSunStyleSectionFlags();
}; };
@ -382,7 +382,7 @@ unsigned ELFAsmParser::parseSunStyleSectionFlags() {
bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) { bool ELFAsmParser::ParseDirectivePushSection(StringRef s, SMLoc loc) {
getStreamer().PushSection(); getStreamer().PushSection();
if (ParseSectionArguments(/*IsPush=*/true)) { if (ParseSectionArguments(/*IsPush=*/true, loc)) {
getStreamer().PopSection(); getStreamer().PopSection();
return true; return true;
} }
@ -397,11 +397,11 @@ bool ELFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {
} }
// FIXME: This is a work in progress. // FIXME: This is a work in progress.
bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc loc) {
return ParseSectionArguments(/*IsPush=*/false); return ParseSectionArguments(/*IsPush=*/false, loc);
} }
bool ELFAsmParser::ParseSectionArguments(bool IsPush) { bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
StringRef SectionName; StringRef SectionName;
if (ParseSectionName(SectionName)) if (ParseSectionName(SectionName))
@ -545,10 +545,24 @@ EndStmt:
} }
SectionKind Kind = computeSectionKind(Flags, Size); SectionKind Kind = computeSectionKind(Flags, Size);
getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type, const MCSection *ELFSection = getContext().getELFSection(
Flags, Kind, Size, SectionName, Type, Flags, Kind, Size, GroupName);
GroupName), getStreamer().SwitchSection(ELFSection, Subsection);
Subsection);
if (getContext().getGenDwarfForAssembly()) {
auto &Sections = getContext().getGenDwarfSectionSyms();
auto InsertResult = Sections.insert(
std::make_pair(ELFSection, std::make_pair(nullptr, nullptr)));
if (InsertResult.second) {
if (getContext().getDwarfVersion() <= 2)
Error(loc, "DWARF2 only supports one section per compilation unit");
MCSymbol *SectionStartSymbol = getContext().CreateTempSymbol();
getStreamer().EmitLabel(SectionStartSymbol);
InsertResult.first->second.first = SectionStartSymbol;
}
}
return false; return false;
} }