10b57cec5SDimitry Andric //===- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework -----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "DwarfFile.h"
100b57cec5SDimitry Andric #include "DwarfCompileUnit.h"
110b57cec5SDimitry Andric #include "DwarfDebug.h"
120b57cec5SDimitry Andric #include "DwarfUnit.h"
130b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
140b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
15*af732203SDimitry Andric #include "llvm/IR/Metadata.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
170b57cec5SDimitry Andric #include <algorithm>
180b57cec5SDimitry Andric #include <cstdint>
190b57cec5SDimitry Andric
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric
DwarfFile(AsmPrinter * AP,StringRef Pref,BumpPtrAllocator & DA)220b57cec5SDimitry Andric DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
230b57cec5SDimitry Andric : Asm(AP), Abbrevs(AbbrevAllocator), StrPool(DA, *Asm, Pref) {}
240b57cec5SDimitry Andric
addUnit(std::unique_ptr<DwarfCompileUnit> U)250b57cec5SDimitry Andric void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) {
260b57cec5SDimitry Andric CUs.push_back(std::move(U));
270b57cec5SDimitry Andric }
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric // Emit the various dwarf units to the unit section USection with
300b57cec5SDimitry Andric // the abbreviations going into ASection.
emitUnits(bool UseOffsets)310b57cec5SDimitry Andric void DwarfFile::emitUnits(bool UseOffsets) {
320b57cec5SDimitry Andric for (const auto &TheU : CUs)
330b57cec5SDimitry Andric emitUnit(TheU.get(), UseOffsets);
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric
emitUnit(DwarfUnit * TheU,bool UseOffsets)360b57cec5SDimitry Andric void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) {
370b57cec5SDimitry Andric if (TheU->getCUNode()->isDebugDirectivesOnly())
380b57cec5SDimitry Andric return;
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric MCSection *S = TheU->getSection();
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric if (!S)
430b57cec5SDimitry Andric return;
440b57cec5SDimitry Andric
450b57cec5SDimitry Andric // Skip CUs that ended up not being needed (split CUs that were abandoned
460b57cec5SDimitry Andric // because they added no information beyond the non-split CU)
470b57cec5SDimitry Andric if (llvm::empty(TheU->getUnitDie().values()))
480b57cec5SDimitry Andric return;
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric Asm->OutStreamer->SwitchSection(S);
510b57cec5SDimitry Andric TheU->emitHeader(UseOffsets);
520b57cec5SDimitry Andric Asm->emitDwarfDIE(TheU->getUnitDie());
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric if (MCSymbol *EndLabel = TheU->getEndLabel())
555ffd83dbSDimitry Andric Asm->OutStreamer->emitLabel(EndLabel);
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric
580b57cec5SDimitry Andric // Compute the size and offset for each DIE.
computeSizeAndOffsets()590b57cec5SDimitry Andric void DwarfFile::computeSizeAndOffsets() {
600b57cec5SDimitry Andric // Offset from the first CU in the debug info section is 0 initially.
61*af732203SDimitry Andric uint64_t SecOffset = 0;
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric // Iterate over each compile unit and set the size and offsets for each
640b57cec5SDimitry Andric // DIE within each compile unit. All offsets are CU relative.
650b57cec5SDimitry Andric for (const auto &TheU : CUs) {
660b57cec5SDimitry Andric if (TheU->getCUNode()->isDebugDirectivesOnly())
670b57cec5SDimitry Andric continue;
680b57cec5SDimitry Andric
690b57cec5SDimitry Andric // Skip CUs that ended up not being needed (split CUs that were abandoned
700b57cec5SDimitry Andric // because they added no information beyond the non-split CU)
710b57cec5SDimitry Andric if (llvm::empty(TheU->getUnitDie().values()))
720b57cec5SDimitry Andric return;
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric TheU->setDebugSectionOffset(SecOffset);
750b57cec5SDimitry Andric SecOffset += computeSizeAndOffsetsForUnit(TheU.get());
760b57cec5SDimitry Andric }
77*af732203SDimitry Andric if (SecOffset > UINT32_MAX && !Asm->isDwarf64())
78*af732203SDimitry Andric report_fatal_error("The generated debug information is too large "
79*af732203SDimitry Andric "for the 32-bit DWARF format.");
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric
computeSizeAndOffsetsForUnit(DwarfUnit * TheU)820b57cec5SDimitry Andric unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit *TheU) {
830b57cec5SDimitry Andric // CU-relative offset is reset to 0 here.
84*af732203SDimitry Andric unsigned Offset = Asm->getUnitLengthFieldByteSize() + // Length of Unit Info
850b57cec5SDimitry Andric TheU->getHeaderSize(); // Unit-specific headers
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric // The return value here is CU-relative, after laying out
880b57cec5SDimitry Andric // all of the CU DIE.
890b57cec5SDimitry Andric return computeSizeAndOffset(TheU->getUnitDie(), Offset);
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric // Compute the size and offset of a DIE. The offset is relative to start of the
930b57cec5SDimitry Andric // CU. It returns the offset after laying out the DIE.
computeSizeAndOffset(DIE & Die,unsigned Offset)940b57cec5SDimitry Andric unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
950b57cec5SDimitry Andric return Die.computeOffsetsAndAbbrevs(Asm, Abbrevs, Offset);
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
emitAbbrevs(MCSection * Section)980b57cec5SDimitry Andric void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); }
990b57cec5SDimitry Andric
1000b57cec5SDimitry Andric // Emit strings into a string section.
emitStrings(MCSection * StrSection,MCSection * OffsetSection,bool UseRelativeOffsets)1010b57cec5SDimitry Andric void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection,
1020b57cec5SDimitry Andric bool UseRelativeOffsets) {
1030b57cec5SDimitry Andric StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets);
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric
addScopeVariable(LexicalScope * LS,DbgVariable * Var)1060b57cec5SDimitry Andric bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
1070b57cec5SDimitry Andric auto &ScopeVars = ScopeVariables[LS];
1080b57cec5SDimitry Andric const DILocalVariable *DV = Var->getVariable();
1090b57cec5SDimitry Andric if (unsigned ArgNum = DV->getArg()) {
1100b57cec5SDimitry Andric auto Cached = ScopeVars.Args.find(ArgNum);
1110b57cec5SDimitry Andric if (Cached == ScopeVars.Args.end())
1120b57cec5SDimitry Andric ScopeVars.Args[ArgNum] = Var;
1130b57cec5SDimitry Andric else {
1140b57cec5SDimitry Andric Cached->second->addMMIEntry(*Var);
1150b57cec5SDimitry Andric return false;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric } else {
1180b57cec5SDimitry Andric ScopeVars.Locals.push_back(Var);
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric return true;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric
addScopeLabel(LexicalScope * LS,DbgLabel * Label)1230b57cec5SDimitry Andric void DwarfFile::addScopeLabel(LexicalScope *LS, DbgLabel *Label) {
1240b57cec5SDimitry Andric SmallVectorImpl<DbgLabel *> &Labels = ScopeLabels[LS];
1250b57cec5SDimitry Andric Labels.push_back(Label);
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric std::pair<uint32_t, RangeSpanList *>
addRange(const DwarfCompileUnit & CU,SmallVector<RangeSpan,2> R)1290b57cec5SDimitry Andric DwarfFile::addRange(const DwarfCompileUnit &CU, SmallVector<RangeSpan, 2> R) {
1300b57cec5SDimitry Andric CURangeLists.push_back(
131480093f4SDimitry Andric RangeSpanList{Asm->createTempSymbol("debug_ranges"), &CU, std::move(R)});
1320b57cec5SDimitry Andric return std::make_pair(CURangeLists.size() - 1, &CURangeLists.back());
1330b57cec5SDimitry Andric }
134