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 
2405e736fbSDavid 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 // Define a unique number for the abbreviation.
5285f80d71SDavid Blaikie //
5385f80d71SDavid Blaikie void DwarfFile::assignAbbrevNumber(DIEAbbrev &Abbrev) {
5485f80d71SDavid Blaikie   // Check the set for priors.
5585f80d71SDavid Blaikie   DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev);
5685f80d71SDavid Blaikie 
5785f80d71SDavid Blaikie   // If it's newly added.
5885f80d71SDavid Blaikie   if (InSet == &Abbrev) {
5985f80d71SDavid Blaikie     // Add to abbreviation list.
6085f80d71SDavid Blaikie     Abbreviations.push_back(&Abbrev);
6185f80d71SDavid Blaikie 
6285f80d71SDavid Blaikie     // Assign the vector position + 1 as its number.
6385f80d71SDavid Blaikie     Abbrev.setNumber(Abbreviations.size());
6485f80d71SDavid Blaikie   } else {
6585f80d71SDavid Blaikie     // Assign existing abbreviation number.
6685f80d71SDavid Blaikie     Abbrev.setNumber(InSet->getNumber());
6785f80d71SDavid Blaikie   }
6885f80d71SDavid Blaikie }
6985f80d71SDavid Blaikie 
7085f80d71SDavid Blaikie void DwarfFile::addUnit(std::unique_ptr<DwarfUnit> U) {
7185f80d71SDavid Blaikie   CUs.push_back(std::move(U));
7285f80d71SDavid Blaikie }
7385f80d71SDavid Blaikie 
7485f80d71SDavid Blaikie // Emit the various dwarf units to the unit section USection with
7585f80d71SDavid Blaikie // the abbreviations going into ASection.
7685f80d71SDavid Blaikie void DwarfFile::emitUnits(DwarfDebug *DD, const MCSymbol *ASectionSym) {
7785f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
78*adcde36cSDavid Blaikie     DIE &Die = TheU->getUnitDie();
7985f80d71SDavid Blaikie     const MCSection *USection = TheU->getSection();
8085f80d71SDavid Blaikie     Asm->OutStreamer.SwitchSection(USection);
8185f80d71SDavid Blaikie 
8285f80d71SDavid Blaikie     // Emit the compile units header.
8385f80d71SDavid Blaikie     Asm->OutStreamer.EmitLabel(TheU->getLabelBegin());
8485f80d71SDavid Blaikie 
8585f80d71SDavid Blaikie     // Emit size of content not including length itself
8685f80d71SDavid Blaikie     Asm->OutStreamer.AddComment("Length of Unit");
87*adcde36cSDavid Blaikie     Asm->EmitInt32(TheU->getHeaderSize() + Die.getSize());
8885f80d71SDavid Blaikie 
8985f80d71SDavid Blaikie     TheU->emitHeader(ASectionSym);
9085f80d71SDavid Blaikie 
91*adcde36cSDavid Blaikie     DD->emitDIE(Die);
9285f80d71SDavid Blaikie     Asm->OutStreamer.EmitLabel(TheU->getLabelEnd());
9385f80d71SDavid Blaikie   }
9485f80d71SDavid Blaikie }
9585f80d71SDavid Blaikie // Compute the size and offset for each DIE.
9685f80d71SDavid Blaikie void DwarfFile::computeSizeAndOffsets() {
9785f80d71SDavid Blaikie   // Offset from the first CU in the debug info section is 0 initially.
9885f80d71SDavid Blaikie   unsigned SecOffset = 0;
9985f80d71SDavid Blaikie 
10085f80d71SDavid Blaikie   // Iterate over each compile unit and set the size and offsets for each
10185f80d71SDavid Blaikie   // DIE within each compile unit. All offsets are CU relative.
10285f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
10385f80d71SDavid Blaikie     TheU->setDebugInfoOffset(SecOffset);
10485f80d71SDavid Blaikie 
10585f80d71SDavid Blaikie     // CU-relative offset is reset to 0 here.
10685f80d71SDavid Blaikie     unsigned Offset = sizeof(int32_t) +      // Length of Unit Info
10785f80d71SDavid Blaikie                       TheU->getHeaderSize(); // Unit-specific headers
10885f80d71SDavid Blaikie 
10985f80d71SDavid Blaikie     // EndOffset here is CU-relative, after laying out
11085f80d71SDavid Blaikie     // all of the CU DIE.
111*adcde36cSDavid Blaikie     unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset);
11285f80d71SDavid Blaikie     SecOffset += EndOffset;
11385f80d71SDavid Blaikie   }
11485f80d71SDavid Blaikie }
11585f80d71SDavid Blaikie // Compute the size and offset of a DIE. The offset is relative to start of the
11685f80d71SDavid Blaikie // CU. It returns the offset after laying out the DIE.
11785f80d71SDavid Blaikie unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
11885f80d71SDavid Blaikie   // Record the abbreviation.
11985f80d71SDavid Blaikie   assignAbbrevNumber(Die.getAbbrev());
12085f80d71SDavid Blaikie 
12185f80d71SDavid Blaikie   // Get the abbreviation for this DIE.
12285f80d71SDavid Blaikie   const DIEAbbrev &Abbrev = Die.getAbbrev();
12385f80d71SDavid Blaikie 
12485f80d71SDavid Blaikie   // Set DIE offset
12585f80d71SDavid Blaikie   Die.setOffset(Offset);
12685f80d71SDavid Blaikie 
12785f80d71SDavid Blaikie   // Start the size with the size of abbreviation code.
12885f80d71SDavid Blaikie   Offset += getULEB128Size(Die.getAbbrevNumber());
12985f80d71SDavid Blaikie 
13085f80d71SDavid Blaikie   const SmallVectorImpl<DIEValue *> &Values = Die.getValues();
13185f80d71SDavid Blaikie   const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
13285f80d71SDavid Blaikie 
13385f80d71SDavid Blaikie   // Size the DIE attribute values.
13485f80d71SDavid Blaikie   for (unsigned i = 0, N = Values.size(); i < N; ++i)
13585f80d71SDavid Blaikie     // Size attribute value.
13685f80d71SDavid Blaikie     Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm());
13785f80d71SDavid Blaikie 
13885f80d71SDavid Blaikie   // Get the children.
13985f80d71SDavid Blaikie   const auto &Children = Die.getChildren();
14085f80d71SDavid Blaikie 
14185f80d71SDavid Blaikie   // Size the DIE children if any.
14285f80d71SDavid Blaikie   if (!Children.empty()) {
14385f80d71SDavid Blaikie     assert(Abbrev.hasChildren() && "Children flag not set");
14485f80d71SDavid Blaikie 
14585f80d71SDavid Blaikie     for (auto &Child : Children)
14685f80d71SDavid Blaikie       Offset = computeSizeAndOffset(*Child, Offset);
14785f80d71SDavid Blaikie 
14885f80d71SDavid Blaikie     // End of children marker.
14985f80d71SDavid Blaikie     Offset += sizeof(int8_t);
15085f80d71SDavid Blaikie   }
15185f80d71SDavid Blaikie 
15285f80d71SDavid Blaikie   Die.setSize(Offset - Die.getOffset());
15385f80d71SDavid Blaikie   return Offset;
15485f80d71SDavid Blaikie }
15585f80d71SDavid Blaikie void DwarfFile::emitAbbrevs(const MCSection *Section) {
15685f80d71SDavid Blaikie   // Check to see if it is worth the effort.
15785f80d71SDavid Blaikie   if (!Abbreviations.empty()) {
15885f80d71SDavid Blaikie     // Start the debug abbrev section.
15985f80d71SDavid Blaikie     Asm->OutStreamer.SwitchSection(Section);
16085f80d71SDavid Blaikie 
16185f80d71SDavid Blaikie     // For each abbrevation.
16285f80d71SDavid Blaikie     for (const DIEAbbrev *Abbrev : Abbreviations) {
16385f80d71SDavid Blaikie       // Emit the abbrevations code (base 1 index.)
16485f80d71SDavid Blaikie       Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
16585f80d71SDavid Blaikie 
16685f80d71SDavid Blaikie       // Emit the abbreviations data.
16785f80d71SDavid Blaikie       Abbrev->Emit(Asm);
16885f80d71SDavid Blaikie     }
16985f80d71SDavid Blaikie 
17085f80d71SDavid Blaikie     // Mark end of abbreviations.
17185f80d71SDavid Blaikie     Asm->EmitULEB128(0, "EOM(3)");
17285f80d71SDavid Blaikie   }
17385f80d71SDavid Blaikie }
17485f80d71SDavid Blaikie 
17585f80d71SDavid Blaikie // Emit strings into a string section.
17685f80d71SDavid Blaikie void DwarfFile::emitStrings(const MCSection *StrSection,
17785f80d71SDavid Blaikie                             const MCSection *OffsetSection,
17885f80d71SDavid Blaikie                             const MCSymbol *StrSecSym) {
17985f80d71SDavid Blaikie 
18085f80d71SDavid Blaikie   if (StringPool.empty())
18185f80d71SDavid Blaikie     return;
18285f80d71SDavid Blaikie 
18385f80d71SDavid Blaikie   // Start the dwarf str section.
18485f80d71SDavid Blaikie   Asm->OutStreamer.SwitchSection(StrSection);
18585f80d71SDavid Blaikie 
18685f80d71SDavid Blaikie   // Get all of the string pool entries and put them in an array by their ID so
18785f80d71SDavid Blaikie   // we can sort them.
18885f80d71SDavid Blaikie   SmallVector<std::pair<unsigned, const StrPool::value_type *>, 64> Entries;
18985f80d71SDavid Blaikie 
19085f80d71SDavid Blaikie   for (const auto &I : StringPool)
19185f80d71SDavid Blaikie     Entries.push_back(std::make_pair(I.second.second, &I));
19285f80d71SDavid Blaikie 
19385f80d71SDavid Blaikie   array_pod_sort(Entries.begin(), Entries.end());
19485f80d71SDavid Blaikie 
19585f80d71SDavid Blaikie   for (const auto &Entry : Entries) {
19685f80d71SDavid Blaikie     // Emit a label for reference from debug information entries.
19785f80d71SDavid Blaikie     Asm->OutStreamer.EmitLabel(Entry.second->getValue().first);
19885f80d71SDavid Blaikie 
19985f80d71SDavid Blaikie     // Emit the string itself with a terminating null byte.
20085f80d71SDavid Blaikie     Asm->OutStreamer.EmitBytes(StringRef(Entry.second->getKeyData(),
20185f80d71SDavid Blaikie                                          Entry.second->getKeyLength() + 1));
20285f80d71SDavid Blaikie   }
20385f80d71SDavid Blaikie 
20485f80d71SDavid Blaikie   // If we've got an offset section go ahead and emit that now as well.
20585f80d71SDavid Blaikie   if (OffsetSection) {
20685f80d71SDavid Blaikie     Asm->OutStreamer.SwitchSection(OffsetSection);
20785f80d71SDavid Blaikie     unsigned offset = 0;
20885f80d71SDavid Blaikie     unsigned size = 4; // FIXME: DWARF64 is 8.
20985f80d71SDavid Blaikie     for (const auto &Entry : Entries) {
21085f80d71SDavid Blaikie       Asm->OutStreamer.EmitIntValue(offset, size);
21185f80d71SDavid Blaikie       offset += Entry.second->getKeyLength() + 1;
21285f80d71SDavid Blaikie     }
21385f80d71SDavid Blaikie   }
21485f80d71SDavid Blaikie }
21585f80d71SDavid Blaikie }
216