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 {
21daefdbf3SDavid Blaikie DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
22daefdbf3SDavid Blaikie     : Asm(AP), StrPool(DA, *Asm, Pref) {}
2385f80d71SDavid Blaikie 
2405e736fbSDavid Blaikie DwarfFile::~DwarfFile() {}
2585f80d71SDavid Blaikie 
2685f80d71SDavid Blaikie // Define a unique number for the abbreviation.
2785f80d71SDavid Blaikie //
2885f80d71SDavid Blaikie void DwarfFile::assignAbbrevNumber(DIEAbbrev &Abbrev) {
2985f80d71SDavid Blaikie   // Check the set for priors.
3085f80d71SDavid Blaikie   DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev);
3185f80d71SDavid Blaikie 
3285f80d71SDavid Blaikie   // If it's newly added.
3385f80d71SDavid Blaikie   if (InSet == &Abbrev) {
3485f80d71SDavid Blaikie     // Add to abbreviation list.
3585f80d71SDavid Blaikie     Abbreviations.push_back(&Abbrev);
3685f80d71SDavid Blaikie 
3785f80d71SDavid Blaikie     // Assign the vector position + 1 as its number.
3885f80d71SDavid Blaikie     Abbrev.setNumber(Abbreviations.size());
3985f80d71SDavid Blaikie   } else {
4085f80d71SDavid Blaikie     // Assign existing abbreviation number.
4185f80d71SDavid Blaikie     Abbrev.setNumber(InSet->getNumber());
4285f80d71SDavid Blaikie   }
4385f80d71SDavid Blaikie }
4485f80d71SDavid Blaikie 
4585f80d71SDavid Blaikie void DwarfFile::addUnit(std::unique_ptr<DwarfUnit> U) {
4685f80d71SDavid Blaikie   CUs.push_back(std::move(U));
4785f80d71SDavid Blaikie }
4885f80d71SDavid Blaikie 
4985f80d71SDavid Blaikie // Emit the various dwarf units to the unit section USection with
5085f80d71SDavid Blaikie // the abbreviations going into ASection.
5185f80d71SDavid Blaikie void DwarfFile::emitUnits(DwarfDebug *DD, const MCSymbol *ASectionSym) {
5285f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
53adcde36cSDavid Blaikie     DIE &Die = TheU->getUnitDie();
5485f80d71SDavid Blaikie     const MCSection *USection = TheU->getSection();
5585f80d71SDavid Blaikie     Asm->OutStreamer.SwitchSection(USection);
5685f80d71SDavid Blaikie 
5785f80d71SDavid Blaikie     // Emit the compile units header.
5885f80d71SDavid Blaikie     Asm->OutStreamer.EmitLabel(TheU->getLabelBegin());
5985f80d71SDavid Blaikie 
6085f80d71SDavid Blaikie     // Emit size of content not including length itself
6185f80d71SDavid Blaikie     Asm->OutStreamer.AddComment("Length of Unit");
62adcde36cSDavid Blaikie     Asm->EmitInt32(TheU->getHeaderSize() + Die.getSize());
6385f80d71SDavid Blaikie 
6485f80d71SDavid Blaikie     TheU->emitHeader(ASectionSym);
6585f80d71SDavid Blaikie 
66adcde36cSDavid Blaikie     DD->emitDIE(Die);
6785f80d71SDavid Blaikie     Asm->OutStreamer.EmitLabel(TheU->getLabelEnd());
6885f80d71SDavid Blaikie   }
6985f80d71SDavid Blaikie }
7085f80d71SDavid Blaikie // Compute the size and offset for each DIE.
7185f80d71SDavid Blaikie void DwarfFile::computeSizeAndOffsets() {
7285f80d71SDavid Blaikie   // Offset from the first CU in the debug info section is 0 initially.
7385f80d71SDavid Blaikie   unsigned SecOffset = 0;
7485f80d71SDavid Blaikie 
7585f80d71SDavid Blaikie   // Iterate over each compile unit and set the size and offsets for each
7685f80d71SDavid Blaikie   // DIE within each compile unit. All offsets are CU relative.
7785f80d71SDavid Blaikie   for (const auto &TheU : CUs) {
7885f80d71SDavid Blaikie     TheU->setDebugInfoOffset(SecOffset);
7985f80d71SDavid Blaikie 
8085f80d71SDavid Blaikie     // CU-relative offset is reset to 0 here.
8185f80d71SDavid Blaikie     unsigned Offset = sizeof(int32_t) +      // Length of Unit Info
8285f80d71SDavid Blaikie                       TheU->getHeaderSize(); // Unit-specific headers
8385f80d71SDavid Blaikie 
8485f80d71SDavid Blaikie     // EndOffset here is CU-relative, after laying out
8585f80d71SDavid Blaikie     // all of the CU DIE.
86adcde36cSDavid Blaikie     unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset);
8785f80d71SDavid Blaikie     SecOffset += EndOffset;
8885f80d71SDavid Blaikie   }
8985f80d71SDavid Blaikie }
9085f80d71SDavid Blaikie // Compute the size and offset of a DIE. The offset is relative to start of the
9185f80d71SDavid Blaikie // CU. It returns the offset after laying out the DIE.
9285f80d71SDavid Blaikie unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
9385f80d71SDavid Blaikie   // Record the abbreviation.
9485f80d71SDavid Blaikie   assignAbbrevNumber(Die.getAbbrev());
9585f80d71SDavid Blaikie 
9685f80d71SDavid Blaikie   // Get the abbreviation for this DIE.
9785f80d71SDavid Blaikie   const DIEAbbrev &Abbrev = Die.getAbbrev();
9885f80d71SDavid Blaikie 
9985f80d71SDavid Blaikie   // Set DIE offset
10085f80d71SDavid Blaikie   Die.setOffset(Offset);
10185f80d71SDavid Blaikie 
10285f80d71SDavid Blaikie   // Start the size with the size of abbreviation code.
10385f80d71SDavid Blaikie   Offset += getULEB128Size(Die.getAbbrevNumber());
10485f80d71SDavid Blaikie 
10585f80d71SDavid Blaikie   const SmallVectorImpl<DIEValue *> &Values = Die.getValues();
10685f80d71SDavid Blaikie   const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
10785f80d71SDavid Blaikie 
10885f80d71SDavid Blaikie   // Size the DIE attribute values.
10985f80d71SDavid Blaikie   for (unsigned i = 0, N = Values.size(); i < N; ++i)
11085f80d71SDavid Blaikie     // Size attribute value.
11185f80d71SDavid Blaikie     Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm());
11285f80d71SDavid Blaikie 
11385f80d71SDavid Blaikie   // Get the children.
11485f80d71SDavid Blaikie   const auto &Children = Die.getChildren();
11585f80d71SDavid Blaikie 
11685f80d71SDavid Blaikie   // Size the DIE children if any.
11785f80d71SDavid Blaikie   if (!Children.empty()) {
11885f80d71SDavid Blaikie     assert(Abbrev.hasChildren() && "Children flag not set");
11985f80d71SDavid Blaikie 
12085f80d71SDavid Blaikie     for (auto &Child : Children)
12185f80d71SDavid Blaikie       Offset = computeSizeAndOffset(*Child, Offset);
12285f80d71SDavid Blaikie 
12385f80d71SDavid Blaikie     // End of children marker.
12485f80d71SDavid Blaikie     Offset += sizeof(int8_t);
12585f80d71SDavid Blaikie   }
12685f80d71SDavid Blaikie 
12785f80d71SDavid Blaikie   Die.setSize(Offset - Die.getOffset());
12885f80d71SDavid Blaikie   return Offset;
12985f80d71SDavid Blaikie }
13085f80d71SDavid Blaikie void DwarfFile::emitAbbrevs(const MCSection *Section) {
13185f80d71SDavid Blaikie   // Check to see if it is worth the effort.
13285f80d71SDavid Blaikie   if (!Abbreviations.empty()) {
13385f80d71SDavid Blaikie     // Start the debug abbrev section.
13485f80d71SDavid Blaikie     Asm->OutStreamer.SwitchSection(Section);
13585f80d71SDavid Blaikie 
13685f80d71SDavid Blaikie     // For each abbrevation.
13785f80d71SDavid Blaikie     for (const DIEAbbrev *Abbrev : Abbreviations) {
13885f80d71SDavid Blaikie       // Emit the abbrevations code (base 1 index.)
13985f80d71SDavid Blaikie       Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
14085f80d71SDavid Blaikie 
14185f80d71SDavid Blaikie       // Emit the abbreviations data.
14285f80d71SDavid Blaikie       Abbrev->Emit(Asm);
14385f80d71SDavid Blaikie     }
14485f80d71SDavid Blaikie 
14585f80d71SDavid Blaikie     // Mark end of abbreviations.
14685f80d71SDavid Blaikie     Asm->EmitULEB128(0, "EOM(3)");
14785f80d71SDavid Blaikie   }
14885f80d71SDavid Blaikie }
14985f80d71SDavid Blaikie 
15085f80d71SDavid Blaikie // Emit strings into a string section.
15185f80d71SDavid Blaikie void DwarfFile::emitStrings(const MCSection *StrSection,
152*6741bb09SDavid Blaikie                             const MCSection *OffsetSection) {
153*6741bb09SDavid Blaikie   StrPool.emit(*Asm, StrSection, OffsetSection);
15485f80d71SDavid Blaikie }
15585f80d71SDavid Blaikie }
156