185f80d71SDavid Blaikie //===-- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework ----------------===//
285f80d71SDavid Blaikie //
385f80d71SDavid Blaikie //                     The LLVM Compiler Infrastructure
485f80d71SDavid Blaikie //
585f80d71SDavid Blaikie // This file is distributed under the University of Illinois Open Source
685f80d71SDavid Blaikie // License. See LICENSE.TXT for details.
785f80d71SDavid Blaikie //
885f80d71SDavid Blaikie //===----------------------------------------------------------------------===//
985f80d71SDavid Blaikie 
1085f80d71SDavid Blaikie #include "DwarfFile.h"
1185f80d71SDavid Blaikie 
1285f80d71SDavid Blaikie #include "DwarfDebug.h"
1385f80d71SDavid Blaikie #include "DwarfUnit.h"
1485f80d71SDavid Blaikie #include "llvm/MC/MCStreamer.h"
1585f80d71SDavid Blaikie #include "llvm/Support/LEB128.h"
1685f80d71SDavid Blaikie #include "llvm/IR/DataLayout.h"
1785f80d71SDavid Blaikie #include "llvm/ADT/STLExtras.h"
1885f80d71SDavid Blaikie #include "llvm/Target/TargetLoweringObjectFile.h"
1985f80d71SDavid Blaikie 
2085f80d71SDavid Blaikie namespace llvm {
2185f80d71SDavid Blaikie DwarfFile::DwarfFile(AsmPrinter *AP, const char *Pref, BumpPtrAllocator &DA)
2285f80d71SDavid Blaikie     : Asm(AP), StringPool(DA), NextStringPoolNumber(0), StringPref(Pref) {}
2385f80d71SDavid Blaikie 
24*05e736fbSDavid Blaikie DwarfFile::~DwarfFile() {}
2585f80d71SDavid Blaikie 
2685f80d71SDavid Blaikie MCSymbol *DwarfFile::getStringPoolSym() {
2785f80d71SDavid Blaikie   return Asm->GetTempSymbol(StringPref);
2885f80d71SDavid Blaikie }
2985f80d71SDavid Blaikie 
3085f80d71SDavid Blaikie MCSymbol *DwarfFile::getStringPoolEntry(StringRef Str) {
3185f80d71SDavid Blaikie   std::pair<MCSymbol *, unsigned> &Entry =
3285f80d71SDavid Blaikie       StringPool.GetOrCreateValue(Str).getValue();
3385f80d71SDavid Blaikie   if (Entry.first)
3485f80d71SDavid Blaikie     return Entry.first;
3585f80d71SDavid Blaikie 
3685f80d71SDavid Blaikie   Entry.second = NextStringPoolNumber++;
3785f80d71SDavid Blaikie   return Entry.first = Asm->GetTempSymbol(StringPref, Entry.second);
3885f80d71SDavid Blaikie }
3985f80d71SDavid Blaikie 
4085f80d71SDavid Blaikie unsigned DwarfFile::getStringPoolIndex(StringRef Str) {
4185f80d71SDavid Blaikie   std::pair<MCSymbol *, unsigned> &Entry =
4285f80d71SDavid Blaikie       StringPool.GetOrCreateValue(Str).getValue();
4385f80d71SDavid Blaikie   if (Entry.first)
4485f80d71SDavid Blaikie     return Entry.second;
4585f80d71SDavid Blaikie 
4685f80d71SDavid Blaikie   Entry.second = NextStringPoolNumber++;
4785f80d71SDavid Blaikie   Entry.first = Asm->GetTempSymbol(StringPref, Entry.second);
4885f80d71SDavid Blaikie   return Entry.second;
4985f80d71SDavid Blaikie }
5085f80d71SDavid Blaikie 
5185f80d71SDavid Blaikie unsigned DwarfFile::getAddrPoolIndex(const MCSymbol *Sym, bool TLS) {
5285f80d71SDavid Blaikie   std::pair<AddrPool::iterator, bool> P = AddressPool.insert(
5385f80d71SDavid Blaikie       std::make_pair(Sym, AddressPoolEntry(AddressPool.size(), TLS)));
5485f80d71SDavid Blaikie   return P.first->second.Number;
5585f80d71SDavid Blaikie }
5685f80d71SDavid Blaikie 
5785f80d71SDavid Blaikie // Define a unique number for the abbreviation.
5885f80d71SDavid Blaikie //
5985f80d71SDavid Blaikie void DwarfFile::assignAbbrevNumber(DIEAbbrev &Abbrev) {
6085f80d71SDavid Blaikie   // Check the set for priors.
6185f80d71SDavid Blaikie   DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev);
6285f80d71SDavid Blaikie 
6385f80d71SDavid Blaikie   // If it's newly added.
6485f80d71SDavid Blaikie   if (InSet == &Abbrev) {
6585f80d71SDavid Blaikie     // Add to abbreviation list.
6685f80d71SDavid Blaikie     Abbreviations.push_back(&Abbrev);
6785f80d71SDavid Blaikie 
6885f80d71SDavid Blaikie     // Assign the vector position + 1 as its number.
6985f80d71SDavid Blaikie     Abbrev.setNumber(Abbreviations.size());
7085f80d71SDavid Blaikie   } else {
7185f80d71SDavid Blaikie     // Assign existing abbreviation number.
7285f80d71SDavid Blaikie     Abbrev.setNumber(InSet->getNumber());
7385f80d71SDavid Blaikie   }
7485f80d71SDavid Blaikie }
7585f80d71SDavid Blaikie 
7685f80d71SDavid Blaikie void DwarfFile::addUnit(std::unique_ptr<DwarfUnit> U) {
7785f80d71SDavid Blaikie   CUs.push_back(std::move(U));
7885f80d71SDavid Blaikie }
7985f80d71SDavid Blaikie 
8085f80d71SDavid Blaikie // Emit the various dwarf units to the unit section USection with
8185f80d71SDavid Blaikie // the abbreviations going into ASection.
8285f80d71SDavid Blaikie void DwarfFile::emitUnits(DwarfDebug *DD, const MCSymbol *ASectionSym) {
8385f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
8485f80d71SDavid Blaikie     DIE *Die = TheU->getUnitDie();
8585f80d71SDavid Blaikie     const MCSection *USection = TheU->getSection();
8685f80d71SDavid Blaikie     Asm->OutStreamer.SwitchSection(USection);
8785f80d71SDavid Blaikie 
8885f80d71SDavid Blaikie     // Emit the compile units header.
8985f80d71SDavid Blaikie     Asm->OutStreamer.EmitLabel(TheU->getLabelBegin());
9085f80d71SDavid Blaikie 
9185f80d71SDavid Blaikie     // Emit size of content not including length itself
9285f80d71SDavid Blaikie     Asm->OutStreamer.AddComment("Length of Unit");
9385f80d71SDavid Blaikie     Asm->EmitInt32(TheU->getHeaderSize() + Die->getSize());
9485f80d71SDavid Blaikie 
9585f80d71SDavid Blaikie     TheU->emitHeader(ASectionSym);
9685f80d71SDavid Blaikie 
9785f80d71SDavid Blaikie     DD->emitDIE(*Die);
9885f80d71SDavid Blaikie     Asm->OutStreamer.EmitLabel(TheU->getLabelEnd());
9985f80d71SDavid Blaikie   }
10085f80d71SDavid Blaikie }
10185f80d71SDavid Blaikie // Compute the size and offset for each DIE.
10285f80d71SDavid Blaikie void DwarfFile::computeSizeAndOffsets() {
10385f80d71SDavid Blaikie   // Offset from the first CU in the debug info section is 0 initially.
10485f80d71SDavid Blaikie   unsigned SecOffset = 0;
10585f80d71SDavid Blaikie 
10685f80d71SDavid Blaikie   // Iterate over each compile unit and set the size and offsets for each
10785f80d71SDavid Blaikie   // DIE within each compile unit. All offsets are CU relative.
10885f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
10985f80d71SDavid Blaikie     TheU->setDebugInfoOffset(SecOffset);
11085f80d71SDavid Blaikie 
11185f80d71SDavid Blaikie     // CU-relative offset is reset to 0 here.
11285f80d71SDavid Blaikie     unsigned Offset = sizeof(int32_t) +      // Length of Unit Info
11385f80d71SDavid Blaikie                       TheU->getHeaderSize(); // Unit-specific headers
11485f80d71SDavid Blaikie 
11585f80d71SDavid Blaikie     // EndOffset here is CU-relative, after laying out
11685f80d71SDavid Blaikie     // all of the CU DIE.
11785f80d71SDavid Blaikie     unsigned EndOffset = computeSizeAndOffset(*TheU->getUnitDie(), Offset);
11885f80d71SDavid Blaikie     SecOffset += EndOffset;
11985f80d71SDavid Blaikie   }
12085f80d71SDavid Blaikie }
12185f80d71SDavid Blaikie // Compute the size and offset of a DIE. The offset is relative to start of the
12285f80d71SDavid Blaikie // CU. It returns the offset after laying out the DIE.
12385f80d71SDavid Blaikie unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
12485f80d71SDavid Blaikie   // Record the abbreviation.
12585f80d71SDavid Blaikie   assignAbbrevNumber(Die.getAbbrev());
12685f80d71SDavid Blaikie 
12785f80d71SDavid Blaikie   // Get the abbreviation for this DIE.
12885f80d71SDavid Blaikie   const DIEAbbrev &Abbrev = Die.getAbbrev();
12985f80d71SDavid Blaikie 
13085f80d71SDavid Blaikie   // Set DIE offset
13185f80d71SDavid Blaikie   Die.setOffset(Offset);
13285f80d71SDavid Blaikie 
13385f80d71SDavid Blaikie   // Start the size with the size of abbreviation code.
13485f80d71SDavid Blaikie   Offset += getULEB128Size(Die.getAbbrevNumber());
13585f80d71SDavid Blaikie 
13685f80d71SDavid Blaikie   const SmallVectorImpl<DIEValue *> &Values = Die.getValues();
13785f80d71SDavid Blaikie   const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
13885f80d71SDavid Blaikie 
13985f80d71SDavid Blaikie   // Size the DIE attribute values.
14085f80d71SDavid Blaikie   for (unsigned i = 0, N = Values.size(); i < N; ++i)
14185f80d71SDavid Blaikie     // Size attribute value.
14285f80d71SDavid Blaikie     Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm());
14385f80d71SDavid Blaikie 
14485f80d71SDavid Blaikie   // Get the children.
14585f80d71SDavid Blaikie   const auto &Children = Die.getChildren();
14685f80d71SDavid Blaikie 
14785f80d71SDavid Blaikie   // Size the DIE children if any.
14885f80d71SDavid Blaikie   if (!Children.empty()) {
14985f80d71SDavid Blaikie     assert(Abbrev.hasChildren() && "Children flag not set");
15085f80d71SDavid Blaikie 
15185f80d71SDavid Blaikie     for (auto &Child : Children)
15285f80d71SDavid Blaikie       Offset = computeSizeAndOffset(*Child, Offset);
15385f80d71SDavid Blaikie 
15485f80d71SDavid Blaikie     // End of children marker.
15585f80d71SDavid Blaikie     Offset += sizeof(int8_t);
15685f80d71SDavid Blaikie   }
15785f80d71SDavid Blaikie 
15885f80d71SDavid Blaikie   Die.setSize(Offset - Die.getOffset());
15985f80d71SDavid Blaikie   return Offset;
16085f80d71SDavid Blaikie }
16185f80d71SDavid Blaikie void DwarfFile::emitAbbrevs(const MCSection *Section) {
16285f80d71SDavid Blaikie   // Check to see if it is worth the effort.
16385f80d71SDavid Blaikie   if (!Abbreviations.empty()) {
16485f80d71SDavid Blaikie     // Start the debug abbrev section.
16585f80d71SDavid Blaikie     Asm->OutStreamer.SwitchSection(Section);
16685f80d71SDavid Blaikie 
16785f80d71SDavid Blaikie     // For each abbrevation.
16885f80d71SDavid Blaikie     for (const DIEAbbrev *Abbrev : Abbreviations) {
16985f80d71SDavid Blaikie       // Emit the abbrevations code (base 1 index.)
17085f80d71SDavid Blaikie       Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
17185f80d71SDavid Blaikie 
17285f80d71SDavid Blaikie       // Emit the abbreviations data.
17385f80d71SDavid Blaikie       Abbrev->Emit(Asm);
17485f80d71SDavid Blaikie     }
17585f80d71SDavid Blaikie 
17685f80d71SDavid Blaikie     // Mark end of abbreviations.
17785f80d71SDavid Blaikie     Asm->EmitULEB128(0, "EOM(3)");
17885f80d71SDavid Blaikie   }
17985f80d71SDavid Blaikie }
18085f80d71SDavid Blaikie 
18185f80d71SDavid Blaikie // Emit strings into a string section.
18285f80d71SDavid Blaikie void DwarfFile::emitStrings(const MCSection *StrSection,
18385f80d71SDavid Blaikie                             const MCSection *OffsetSection,
18485f80d71SDavid Blaikie                             const MCSymbol *StrSecSym) {
18585f80d71SDavid Blaikie 
18685f80d71SDavid Blaikie   if (StringPool.empty())
18785f80d71SDavid Blaikie     return;
18885f80d71SDavid Blaikie 
18985f80d71SDavid Blaikie   // Start the dwarf str section.
19085f80d71SDavid Blaikie   Asm->OutStreamer.SwitchSection(StrSection);
19185f80d71SDavid Blaikie 
19285f80d71SDavid Blaikie   // Get all of the string pool entries and put them in an array by their ID so
19385f80d71SDavid Blaikie   // we can sort them.
19485f80d71SDavid Blaikie   SmallVector<std::pair<unsigned, const StrPool::value_type *>, 64> Entries;
19585f80d71SDavid Blaikie 
19685f80d71SDavid Blaikie   for (const auto &I : StringPool)
19785f80d71SDavid Blaikie     Entries.push_back(std::make_pair(I.second.second, &I));
19885f80d71SDavid Blaikie 
19985f80d71SDavid Blaikie   array_pod_sort(Entries.begin(), Entries.end());
20085f80d71SDavid Blaikie 
20185f80d71SDavid Blaikie   for (const auto &Entry : Entries) {
20285f80d71SDavid Blaikie     // Emit a label for reference from debug information entries.
20385f80d71SDavid Blaikie     Asm->OutStreamer.EmitLabel(Entry.second->getValue().first);
20485f80d71SDavid Blaikie 
20585f80d71SDavid Blaikie     // Emit the string itself with a terminating null byte.
20685f80d71SDavid Blaikie     Asm->OutStreamer.EmitBytes(StringRef(Entry.second->getKeyData(),
20785f80d71SDavid Blaikie                                          Entry.second->getKeyLength() + 1));
20885f80d71SDavid Blaikie   }
20985f80d71SDavid Blaikie 
21085f80d71SDavid Blaikie   // If we've got an offset section go ahead and emit that now as well.
21185f80d71SDavid Blaikie   if (OffsetSection) {
21285f80d71SDavid Blaikie     Asm->OutStreamer.SwitchSection(OffsetSection);
21385f80d71SDavid Blaikie     unsigned offset = 0;
21485f80d71SDavid Blaikie     unsigned size = 4; // FIXME: DWARF64 is 8.
21585f80d71SDavid Blaikie     for (const auto &Entry : Entries) {
21685f80d71SDavid Blaikie       Asm->OutStreamer.EmitIntValue(offset, size);
21785f80d71SDavid Blaikie       offset += Entry.second->getKeyLength() + 1;
21885f80d71SDavid Blaikie     }
21985f80d71SDavid Blaikie   }
22085f80d71SDavid Blaikie }
22185f80d71SDavid Blaikie 
22285f80d71SDavid Blaikie // Emit addresses into the section given.
22385f80d71SDavid Blaikie void DwarfFile::emitAddresses(const MCSection *AddrSection) {
22485f80d71SDavid Blaikie 
22585f80d71SDavid Blaikie   if (AddressPool.empty())
22685f80d71SDavid Blaikie     return;
22785f80d71SDavid Blaikie 
22885f80d71SDavid Blaikie   // Start the dwarf addr section.
22985f80d71SDavid Blaikie   Asm->OutStreamer.SwitchSection(AddrSection);
23085f80d71SDavid Blaikie 
23185f80d71SDavid Blaikie   // Order the address pool entries by ID
23285f80d71SDavid Blaikie   SmallVector<const MCExpr *, 64> Entries(AddressPool.size());
23385f80d71SDavid Blaikie 
23485f80d71SDavid Blaikie   for (const auto &I : AddressPool)
23585f80d71SDavid Blaikie     Entries[I.second.Number] =
23685f80d71SDavid Blaikie         I.second.TLS
23785f80d71SDavid Blaikie             ? Asm->getObjFileLowering().getDebugThreadLocalSymbol(I.first)
23885f80d71SDavid Blaikie             : MCSymbolRefExpr::Create(I.first, Asm->OutContext);
23985f80d71SDavid Blaikie 
24085f80d71SDavid Blaikie   for (const MCExpr *Entry : Entries)
24185f80d71SDavid Blaikie     Asm->OutStreamer.EmitValue(Entry, Asm->getDataLayout().getPointerSize());
24285f80d71SDavid Blaikie }
24385f80d71SDavid Blaikie }
244