Newer
Older
// Emit visible names into a hashed accelerator table section.
Eric Christopher
committed
void DwarfDebug::emitAccelNames() {
DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset,
dwarf::DW_FORM_data4));
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
CompileUnit *TheCU = I->second;
const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelNames();
for (StringMap<std::vector<DIE*> >::const_iterator
Eric Christopher
committed
GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
const std::vector<DIE *> &Entities = GI->second;
for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
DE = Entities.end(); DI != DE; ++DI)
AT.AddName(Name, (*DI));
Eric Christopher
committed
}
}
AT.FinalizeTable(Asm, "Names");
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfAccelNamesSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
AT.Emit(Asm, SectionBegin, &InfoHolder);
Eric Christopher
committed
}
// Emit objective C classes and categories into a hashed accelerator table
// section.
Eric Christopher
committed
void DwarfDebug::emitAccelObjC() {
DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset,
dwarf::DW_FORM_data4));
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
CompileUnit *TheCU = I->second;
const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelObjC();
for (StringMap<std::vector<DIE*> >::const_iterator
GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
const std::vector<DIE *> &Entities = GI->second;
Eric Christopher
committed
for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
DE = Entities.end(); DI != DE; ++DI)
AT.AddName(Name, (*DI));
}
}
AT.FinalizeTable(Asm, "ObjC");
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering()
.getDwarfAccelObjCSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
AT.Emit(Asm, SectionBegin, &InfoHolder);
Eric Christopher
committed
}
// Emit namespace dies into a hashed accelerator table.
Eric Christopher
committed
void DwarfDebug::emitAccelNamespaces() {
DwarfAccelTable AT(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset,
dwarf::DW_FORM_data4));
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
CompileUnit *TheCU = I->second;
const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelNamespace();
for (StringMap<std::vector<DIE*> >::const_iterator
Eric Christopher
committed
GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
const std::vector<DIE *> &Entities = GI->second;
for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
DE = Entities.end(); DI != DE; ++DI)
AT.AddName(Name, (*DI));
Eric Christopher
committed
}
}
AT.FinalizeTable(Asm, "namespac");
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering()
.getDwarfAccelNamespaceSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
AT.Emit(Asm, SectionBegin, &InfoHolder);
Eric Christopher
committed
}
// Emit type dies into a hashed accelerator table.
Eric Christopher
committed
void DwarfDebug::emitAccelTypes() {
std::vector<DwarfAccelTable::Atom> Atoms;
Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeDIEOffset,
dwarf::DW_FORM_data4));
Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeTag,
dwarf::DW_FORM_data2));
Atoms.push_back(DwarfAccelTable::Atom(DwarfAccelTable::eAtomTypeTypeFlags,
dwarf::DW_FORM_data1));
DwarfAccelTable AT(Atoms);
Eric Christopher
committed
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
CompileUnit *TheCU = I->second;
const StringMap<std::vector<std::pair<DIE*, unsigned > > > &Names
= TheCU->getAccelTypes();
for (StringMap<std::vector<std::pair<DIE*, unsigned> > >::const_iterator
Eric Christopher
committed
GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
const std::vector<std::pair<DIE *, unsigned> > &Entities = GI->second;
for (std::vector<std::pair<DIE *, unsigned> >::const_iterator DI
= Entities.begin(), DE = Entities.end(); DI !=DE; ++DI)
AT.AddName(Name, (*DI).first, (*DI).second);
Eric Christopher
committed
}
}
AT.FinalizeTable(Asm, "types");
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering()
.getDwarfAccelTypesSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
// Emit the full data.
AT.Emit(Asm, SectionBegin, &InfoHolder);
Eric Christopher
committed
}
for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
E = CUMap.end(); I != E; ++I) {
CompileUnit *TheCU = I->second;
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfPubTypesSection());
Asm->OutStreamer.AddComment("Length of Public Types Info");
Asm->EmitLabelDifference(
Asm->GetTempSymbol("pubtypes_end", TheCU->getUniqueID()),
Asm->GetTempSymbol("pubtypes_begin", TheCU->getUniqueID()), 4);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_begin",
TheCU->getUniqueID()));
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DWARF Version");
Asm->EmitInt16(dwarf::DWARF_VERSION);
Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection();
Asm->EmitSectionOffset(Asm->GetTempSymbol(ISec->getLabelBeginName(),
TheCU->getUniqueID()),
Asm->OutStreamer.AddComment("Compilation Unit Length");
Asm->EmitLabelDifference(Asm->GetTempSymbol(ISec->getLabelEndName(),
TheCU->getUniqueID()),
Asm->GetTempSymbol(ISec->getLabelBeginName(),
TheCU->getUniqueID()),
const StringMap<DIE*> &Globals = TheCU->getGlobalTypes();
for (StringMap<DIE*>::const_iterator
GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
const char *Name = GI->getKeyData();
Nick Lewycky
committed
DIE *Entity = GI->second;
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset");
Asm->EmitInt32(Entity->getOffset());
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("External Name");
Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1));
Asm->OutStreamer.AddComment("End Mark");
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubtypes_end",
TheCU->getUniqueID()));
// Emit strings into a string section.
void DwarfUnits::emitStrings(const MCSection *StrSection,
const MCSection *OffsetSection = NULL,
const MCSymbol *StrSecSym = NULL) {
if (StringPool.empty()) return;
// Start the dwarf str section.
Asm->OutStreamer.SwitchSection(StrSection);
// Get all of the string pool entries and put them in an array by their ID so
// we can sort them.
SmallVector<std::pair<unsigned,
StringMapEntry<std::pair<MCSymbol*, unsigned> >*>, 64> Entries;
for (StringMap<std::pair<MCSymbol*, unsigned> >::iterator
I = StringPool.begin(), E = StringPool.end();
Entries.push_back(std::make_pair(I->second.second, &*I));
array_pod_sort(Entries.begin(), Entries.end());
for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
// Emit a label for reference from debug information entries.
Asm->OutStreamer.EmitLabel(Entries[i].second->getValue().first);
// Emit the string itself with a terminating null byte.
Benjamin Kramer
committed
Asm->OutStreamer.EmitBytes(StringRef(Entries[i].second->getKeyData(),
Entries[i].second->getKeyLength()+1));
// If we've got an offset section go ahead and emit that now as well.
if (OffsetSection) {
Asm->OutStreamer.SwitchSection(OffsetSection);
unsigned offset = 0;
unsigned size = 4; // FIXME: DWARF64 is 8.
for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
Asm->OutStreamer.EmitIntValue(offset, size);
offset += Entries[i].second->getKeyLength() + 1;
}
}
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
// Emit strings into a string section.
void DwarfUnits::emitAddresses(const MCSection *AddrSection) {
if (AddressPool.empty()) return;
// Start the dwarf addr section.
Asm->OutStreamer.SwitchSection(AddrSection);
// Get all of the string pool entries and put them in an array by their ID so
// we can sort them.
SmallVector<std::pair<unsigned,
std::pair<MCSymbol*, unsigned>* >, 64> Entries;
for (DenseMap<MCSymbol*, std::pair<MCSymbol*, unsigned> >::iterator
I = AddressPool.begin(), E = AddressPool.end();
I != E; ++I)
Entries.push_back(std::make_pair(I->second.second, &(I->second)));
array_pod_sort(Entries.begin(), Entries.end());
for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
// Emit a label for reference from debug information entries.
MCSymbol *Sym = Entries[i].second->first;
if (Sym)
Asm->EmitLabelReference(Entries[i].second->first,
Asm->getDataLayout().getPointerSize());
else
Asm->OutStreamer.EmitIntValue(0, Asm->getDataLayout().getPointerSize());
}
}
// Emit visible names into a debug str section.
void DwarfDebug::emitDebugStr() {
DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection());
}
// Emit visible names into a debug loc section.
void DwarfDebug::emitDebugLoc() {
if (DotDebugLocEntries.empty())
return;
for (SmallVector<DotDebugLocEntry, 4>::iterator
I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end();
I != E; ++I) {
DotDebugLocEntry &Entry = *I;
if (I + 1 != DotDebugLocEntries.end())
Entry.Merge(I+1);
}
Daniel Dunbar
committed
// Start the dwarf loc section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfLocSection());
unsigned char Size = Asm->getDataLayout().getPointerSize();
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0));
unsigned index = 1;
for (SmallVector<DotDebugLocEntry, 4>::iterator
I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end();
DotDebugLocEntry &Entry = *I;
if (Entry.isMerged()) continue;
Asm->OutStreamer.EmitIntValue(0, Size);
Asm->OutStreamer.EmitIntValue(0, Size);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index));
Asm->OutStreamer.EmitSymbolValue(Entry.Begin, Size);
Asm->OutStreamer.EmitSymbolValue(Entry.End, Size);
Devang Patel
committed
DIVariable DV(Entry.Variable);
Asm->OutStreamer.AddComment("Loc expr size");
MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol();
MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol();
Asm->EmitLabelDifference(end, begin, 2);
Asm->OutStreamer.EmitLabel(begin);
if (Entry.isInt()) {
Devang Patel
committed
DIBasicType BTy(DV.getType());
if (BTy.Verify() &&
Devang Patel
committed
|| BTy.getEncoding() == dwarf::DW_ATE_signed_char)) {
Asm->OutStreamer.AddComment("DW_OP_consts");
Asm->EmitInt8(dwarf::DW_OP_consts);
Asm->EmitSLEB128(Entry.getInt());
Devang Patel
committed
} else {
Asm->OutStreamer.AddComment("DW_OP_constu");
Asm->EmitInt8(dwarf::DW_OP_constu);
Asm->EmitULEB128(Entry.getInt());
Devang Patel
committed
}
} else if (Entry.isLocation()) {
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
// Regular entry.
Asm->EmitDwarfRegOp(Entry.Loc);
else {
// Complex address entry.
unsigned N = DV.getNumAddrElements();
unsigned i = 0;
if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) {
if (Entry.Loc.getOffset()) {
i = 2;
Asm->EmitDwarfRegOp(Entry.Loc);
Asm->OutStreamer.AddComment("DW_OP_deref");
Asm->EmitInt8(dwarf::DW_OP_deref);
Asm->OutStreamer.AddComment("DW_OP_plus_uconst");
Asm->EmitInt8(dwarf::DW_OP_plus_uconst);
Asm->EmitSLEB128(DV.getAddrElement(1));
} else {
// If first address element is OpPlus then emit
// DW_OP_breg + Offset instead of DW_OP_reg + Offset.
MachineLocation Loc(Entry.Loc.getReg(), DV.getAddrElement(1));
Asm->EmitDwarfRegOp(Loc);
i = 2;
}
Asm->EmitDwarfRegOp(Entry.Loc);
}
// Emit remaining complex address elements.
for (; i < N; ++i) {
uint64_t Element = DV.getAddrElement(i);
if (Element == DIBuilder::OpPlus) {
Asm->EmitInt8(dwarf::DW_OP_plus_uconst);
Asm->EmitULEB128(DV.getAddrElement(++i));
} else if (Element == DIBuilder::OpDeref) {
Asm->EmitInt8(dwarf::DW_OP_deref);
} else
llvm_unreachable("unknown Opcode found in complex address");
Devang Patel
committed
}
}
// else ... ignore constant fp. There is not any good way to
// to represent them here in dwarf.
Asm->OutStreamer.EmitLabel(end);
// Emit visible names into a debug aranges section.
void DwarfDebug::emitDebugARanges() {
// Start the dwarf aranges section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfARangesSection());
Bill Wendling
committed
}
// Emit visible names into a debug ranges section.
void DwarfDebug::emitDebugRanges() {
// Start the dwarf ranges section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfRangesSection());
unsigned char Size = Asm->getDataLayout().getPointerSize();
Devang Patel
committed
for (SmallVector<const MCSymbol *, 8>::iterator
I = DebugRangeSymbols.begin(), E = DebugRangeSymbols.end();
Devang Patel
committed
I != E; ++I) {
if (*I)
Asm->OutStreamer.EmitSymbolValue(const_cast<MCSymbol*>(*I), Size);
Asm->OutStreamer.EmitIntValue(0, Size);
// Emit visible names into a debug macinfo section.
void DwarfDebug::emitDebugMacInfo() {
Asm->getObjFileLowering().getDwarfMacroInfoSection()) {
// Start the dwarf macinfo section.
Asm->OutStreamer.SwitchSection(LineInfo);
// Emit inline info using following format.
// Section Header:
// 1. length of section
// 2. Dwarf version number
// 3. address size.
//
// Entries (one "entry" for each function that was inlined):
//
// 1. offset into __debug_str section for MIPS linkage name, if exists;
// otherwise offset into __debug_str for regular function name.
// 2. offset into __debug_str section for regular function name.
// 3. an unsigned LEB128 number indicating the number of distinct inlining
// instances for the function.
//
// The rest of the entry consists of a {die_offset, low_pc} pair for each
// inlined instance; the die_offset points to the inlined_subroutine die in the
// __debug_info section, and the low_pc is the starting address for the
// inlining instance.
void DwarfDebug::emitDebugInlineInfo() {
if (!Asm->MAI->doesDwarfUseInlineInfoSection())
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfDebugInlineSection());
Asm->OutStreamer.AddComment("Length of Debug Inlined Information Entry");
Asm->EmitLabelDifference(Asm->GetTempSymbol("debug_inlined_end", 1),
Asm->GetTempSymbol("debug_inlined_begin", 1), 4);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_begin", 1));
Asm->OutStreamer.AddComment("Dwarf Version");
Asm->EmitInt16(dwarf::DWARF_VERSION);
Asm->OutStreamer.AddComment("Address Size (in bytes)");
Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
for (SmallVector<const MDNode *, 4>::iterator I = InlinedSPNodes.begin(),
E = InlinedSPNodes.end(); I != E; ++I) {
const MDNode *Node = *I;
DenseMap<const MDNode *, SmallVector<InlineInfoLabels, 4> >::iterator II
SmallVector<InlineInfoLabels, 4> &Labels = II->second;
StringRef LName = SP.getLinkageName();
StringRef Name = SP.getName();
Asm->OutStreamer.AddComment("MIPS linkage name");
if (LName.empty())
Asm->EmitSectionOffset(InfoHolder.getStringPoolEntry(Name),
DwarfStrSectionSym);
else
Asm->EmitSectionOffset(InfoHolder
.getStringPoolEntry(getRealLinkageName(LName)),
DwarfStrSectionSym);
Asm->OutStreamer.AddComment("Function name");
Asm->EmitSectionOffset(InfoHolder.getStringPoolEntry(Name),
DwarfStrSectionSym);
Asm->EmitULEB128(Labels.size(), "Inline count");
for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(),
LE = Labels.end(); LI != LE; ++LI) {
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DIE offset");
Asm->EmitInt32(LI->second->getOffset());
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("low_pc");
Asm->OutStreamer.EmitSymbolValue(LI->first,
Asm->getDataLayout().getPointerSize());
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_end", 1));
// DWARF5 Experimental Separate Dwarf emitters.
// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list,
// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id,
// DW_AT_ranges_base, DW_AT_addr_base. If DW_AT_ranges is present,
// DW_AT_low_pc and DW_AT_high_pc are not used, and vice versa.
CompileUnit *DwarfDebug::constructSkeletonCU(const MDNode *N) {
DICompileUnit DIUnit(N);
CompilationDir = DIUnit.getDirectory();
DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
CompileUnit *NewCU = new CompileUnit(GlobalCUIndexCount++,
DIUnit.getLanguage(), Die, Asm,
this, &SkeletonHolder);
SmallString<16> T(DIUnit.getFilename());
sys::path::replace_extension(T, ".dwo");
StringRef FN = sys::path::filename(T);
NewCU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name, FN);
// This should be a unique identifier when we want to build .dwp files.
NewCU->addUInt(Die, dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, 0);
// FIXME: The addr base should be relative for each compile unit, however,
// this one is going to be 0 anyhow.
NewCU->addUInt(Die, dwarf::DW_AT_GNU_addr_base, dwarf::DW_FORM_sec_offset, 0);
// 2.17.1 requires that we use DW_AT_low_pc for a single entry point
// into an entity. We're using 0, or a NULL label for this.
NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0);
// DW_AT_stmt_list is a offset of line number information for this
// compile unit in debug_line section.
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset,
DwarfLineSectionSym);
else
NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, 0);
if (!CompilationDir.empty())
NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
SkeletonHolder.addUnit(NewCU);
SkeletonCUs.push_back(NewCU);
return NewCU;
}
void DwarfDebug::emitSkeletonAbbrevs(const MCSection *Section) {
assert(useSplitDwarf() && "No split dwarf debug info?");
emitAbbrevs(Section, &SkeletonAbbrevs);
}
// Emit the .debug_info.dwo section for separated dwarf. This contains the
// compile units that would normally be in debug_info.
void DwarfDebug::emitDebugInfoDWO() {
assert(useSplitDwarf() && "No split dwarf debug info?");
InfoHolder.emitUnits(this, Asm->getObjFileLowering().getDwarfInfoDWOSection(),
Asm->getObjFileLowering().getDwarfAbbrevDWOSection(),
DwarfAbbrevDWOSectionSym);
}
// Emit the .debug_abbrev.dwo section for separated dwarf. This contains the
// abbreviations for the .debug_info.dwo section.
void DwarfDebug::emitDebugAbbrevDWO() {
assert(useSplitDwarf() && "No split dwarf?");
emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevDWOSection(),
&Abbreviations);
}
// Emit the .debug_str.dwo section for separated dwarf. This contains the
// string section and is identical in format to traditional .debug_str
// sections.
void DwarfDebug::emitDebugStrDWO() {
assert(useSplitDwarf() && "No split dwarf?");
const MCSection *OffSec = Asm->getObjFileLowering()
.getDwarfStrOffDWOSection();
const MCSymbol *StrSym = DwarfStrSectionSym;
InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
OffSec, StrSym);