mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-23 11:04:49 +00:00
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
This commit is contained in:
parent
70e0b047be
commit
5cc319a42a
@ -85,6 +85,8 @@ public:
|
||||
|
||||
virtual void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned);
|
||||
|
||||
virtual void Flush();
|
||||
|
||||
virtual void FinishImpl();
|
||||
/// @}
|
||||
|
||||
|
@ -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<const MCSymbol *, unsigned> SymbolOrdering;
|
||||
|
||||
/// SectionStack - This is stack of current and previous section
|
||||
/// values saved by PushSection.
|
||||
SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 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.
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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<CompileUnit *, std::vector<ArangeSpan> > SpansType;
|
||||
|
||||
SpansType Spans;
|
||||
|
||||
// Build a list of sections used.
|
||||
std::vector<const MCSection *> 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<Sections.size();SecIdx++) {
|
||||
const MCSection *Section = Sections[SecIdx];
|
||||
SmallVector<SymbolCU, 8> &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<CompileUnit *> 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<CUs.size();CUIdx++) {
|
||||
CompileUnit *CU = CUs[CUIdx];
|
||||
std::vector<ArangeSpan> &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.
|
||||
|
@ -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<unsigned, BumpPtrAllocator&> SourceIdMap;
|
||||
|
||||
// List of all labels used in the output.
|
||||
std::vector<SymbolCU> Labels;
|
||||
|
||||
// Provides a unique id per text section.
|
||||
SetVector<const MCSection*> SectionMap;
|
||||
typedef DenseMap<const MCSection *, SmallVector<SymbolCU, 8> > SectionMapType;
|
||||
SectionMapType SectionMap;
|
||||
|
||||
// List of arguments for current function.
|
||||
SmallVector<DbgVariable *, 8> 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.
|
||||
|
@ -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.
|
||||
|
@ -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<LocalCommon>::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);
|
||||
|
@ -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())
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
94
test/DebugInfo/dwarf-aranges.ll
Normal file
94
test/DebugInfo/dwarf-aranges.ll
Normal file
@ -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 ]
|
65
test/DebugInfo/multiple-aranges.ll
Normal file
65
test/DebugInfo/multiple-aranges.ll
Normal file
@ -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}
|
Loading…
x
Reference in New Issue
Block a user