109467b48Spatrick //===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick
909467b48Spatrick #include "llvm/MC/MCDwarf.h"
1009467b48Spatrick #include "llvm/ADT/ArrayRef.h"
1109467b48Spatrick #include "llvm/ADT/DenseMap.h"
1209467b48Spatrick #include "llvm/ADT/Hashing.h"
1309467b48Spatrick #include "llvm/ADT/STLExtras.h"
1409467b48Spatrick #include "llvm/ADT/SmallString.h"
1509467b48Spatrick #include "llvm/ADT/SmallVector.h"
1609467b48Spatrick #include "llvm/ADT/StringRef.h"
1709467b48Spatrick #include "llvm/ADT/Twine.h"
1809467b48Spatrick #include "llvm/BinaryFormat/Dwarf.h"
1909467b48Spatrick #include "llvm/Config/config.h"
2009467b48Spatrick #include "llvm/MC/MCAsmInfo.h"
2109467b48Spatrick #include "llvm/MC/MCContext.h"
2209467b48Spatrick #include "llvm/MC/MCExpr.h"
2309467b48Spatrick #include "llvm/MC/MCObjectFileInfo.h"
2409467b48Spatrick #include "llvm/MC/MCObjectStreamer.h"
2509467b48Spatrick #include "llvm/MC/MCRegisterInfo.h"
2609467b48Spatrick #include "llvm/MC/MCSection.h"
2709467b48Spatrick #include "llvm/MC/MCStreamer.h"
2809467b48Spatrick #include "llvm/MC/MCSymbol.h"
2909467b48Spatrick #include "llvm/Support/Casting.h"
3009467b48Spatrick #include "llvm/Support/Endian.h"
3109467b48Spatrick #include "llvm/Support/EndianStream.h"
3209467b48Spatrick #include "llvm/Support/ErrorHandling.h"
3309467b48Spatrick #include "llvm/Support/LEB128.h"
3409467b48Spatrick #include "llvm/Support/MathExtras.h"
3509467b48Spatrick #include "llvm/Support/Path.h"
3609467b48Spatrick #include "llvm/Support/SourceMgr.h"
3709467b48Spatrick #include "llvm/Support/raw_ostream.h"
3809467b48Spatrick #include <cassert>
3909467b48Spatrick #include <cstdint>
40*d415bd75Srobert #include <optional>
4109467b48Spatrick #include <string>
4209467b48Spatrick #include <utility>
4309467b48Spatrick #include <vector>
4409467b48Spatrick
4509467b48Spatrick using namespace llvm;
4609467b48Spatrick
emitListsTableHeaderStart(MCStreamer & S)47097a140dSpatrick MCSymbol *mcdwarf::emitListsTableHeaderStart(MCStreamer &S) {
4873471bf0Spatrick MCSymbol *Start = S.getContext().createTempSymbol("debug_list_header_start");
4973471bf0Spatrick MCSymbol *End = S.getContext().createTempSymbol("debug_list_header_end");
50097a140dSpatrick auto DwarfFormat = S.getContext().getDwarfFormat();
51097a140dSpatrick if (DwarfFormat == dwarf::DWARF64) {
52097a140dSpatrick S.AddComment("DWARF64 mark");
53097a140dSpatrick S.emitInt32(dwarf::DW_LENGTH_DWARF64);
54097a140dSpatrick }
55097a140dSpatrick S.AddComment("Length");
56097a140dSpatrick S.emitAbsoluteSymbolDiff(End, Start,
57097a140dSpatrick dwarf::getDwarfOffsetByteSize(DwarfFormat));
58097a140dSpatrick S.emitLabel(Start);
59097a140dSpatrick S.AddComment("Version");
60097a140dSpatrick S.emitInt16(S.getContext().getDwarfVersion());
61097a140dSpatrick S.AddComment("Address size");
62097a140dSpatrick S.emitInt8(S.getContext().getAsmInfo()->getCodePointerSize());
63097a140dSpatrick S.AddComment("Segment selector size");
64097a140dSpatrick S.emitInt8(0);
65097a140dSpatrick return End;
66097a140dSpatrick }
67097a140dSpatrick
ScaleAddrDelta(MCContext & Context,uint64_t AddrDelta)6809467b48Spatrick static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) {
6909467b48Spatrick unsigned MinInsnLength = Context.getAsmInfo()->getMinInstAlignment();
7009467b48Spatrick if (MinInsnLength == 1)
7109467b48Spatrick return AddrDelta;
7209467b48Spatrick if (AddrDelta % MinInsnLength != 0) {
7309467b48Spatrick // TODO: report this error, but really only once.
7409467b48Spatrick ;
7509467b48Spatrick }
7609467b48Spatrick return AddrDelta / MinInsnLength;
7709467b48Spatrick }
7809467b48Spatrick
MCDwarfLineStr(MCContext & Ctx)79*d415bd75Srobert MCDwarfLineStr::MCDwarfLineStr(MCContext &Ctx) {
80*d415bd75Srobert UseRelocs = Ctx.getAsmInfo()->doesDwarfUseRelocationsAcrossSections();
81*d415bd75Srobert if (UseRelocs)
82*d415bd75Srobert LineStrLabel =
83*d415bd75Srobert Ctx.getObjectFileInfo()->getDwarfLineStrSection()->getBeginSymbol();
84*d415bd75Srobert }
85*d415bd75Srobert
8609467b48Spatrick //
8709467b48Spatrick // This is called when an instruction is assembled into the specified section
8809467b48Spatrick // and if there is information from the last .loc directive that has yet to have
8909467b48Spatrick // a line entry made for it is made.
9009467b48Spatrick //
make(MCStreamer * MCOS,MCSection * Section)9173471bf0Spatrick void MCDwarfLineEntry::make(MCStreamer *MCOS, MCSection *Section) {
9209467b48Spatrick if (!MCOS->getContext().getDwarfLocSeen())
9309467b48Spatrick return;
9409467b48Spatrick
9509467b48Spatrick // Create a symbol at in the current section for use in the line entry.
9609467b48Spatrick MCSymbol *LineSym = MCOS->getContext().createTempSymbol();
9709467b48Spatrick // Set the value of the symbol to use for the MCDwarfLineEntry.
98097a140dSpatrick MCOS->emitLabel(LineSym);
9909467b48Spatrick
10009467b48Spatrick // Get the current .loc info saved in the context.
10109467b48Spatrick const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc();
10209467b48Spatrick
10309467b48Spatrick // Create a (local) line entry with the symbol and the current .loc info.
10409467b48Spatrick MCDwarfLineEntry LineEntry(LineSym, DwarfLoc);
10509467b48Spatrick
10609467b48Spatrick // clear DwarfLocSeen saying the current .loc info is now used.
10709467b48Spatrick MCOS->getContext().clearDwarfLocSeen();
10809467b48Spatrick
10909467b48Spatrick // Add the line entry to this section's entries.
11009467b48Spatrick MCOS->getContext()
11109467b48Spatrick .getMCDwarfLineTable(MCOS->getContext().getDwarfCompileUnitID())
11209467b48Spatrick .getMCLineSections()
11309467b48Spatrick .addLineEntry(LineEntry, Section);
11409467b48Spatrick }
11509467b48Spatrick
11609467b48Spatrick //
117*d415bd75Srobert // This helper routine returns an expression of End - Start - IntVal .
11809467b48Spatrick //
makeEndMinusStartExpr(MCContext & Ctx,const MCSymbol & Start,const MCSymbol & End,int IntVal)119097a140dSpatrick static inline const MCExpr *makeEndMinusStartExpr(MCContext &Ctx,
12009467b48Spatrick const MCSymbol &Start,
12109467b48Spatrick const MCSymbol &End,
12209467b48Spatrick int IntVal) {
12309467b48Spatrick MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
124097a140dSpatrick const MCExpr *Res = MCSymbolRefExpr::create(&End, Variant, Ctx);
125097a140dSpatrick const MCExpr *RHS = MCSymbolRefExpr::create(&Start, Variant, Ctx);
126097a140dSpatrick const MCExpr *Res1 = MCBinaryExpr::create(MCBinaryExpr::Sub, Res, RHS, Ctx);
127097a140dSpatrick const MCExpr *Res2 = MCConstantExpr::create(IntVal, Ctx);
128097a140dSpatrick const MCExpr *Res3 = MCBinaryExpr::create(MCBinaryExpr::Sub, Res1, Res2, Ctx);
12909467b48Spatrick return Res3;
13009467b48Spatrick }
13109467b48Spatrick
13209467b48Spatrick //
13309467b48Spatrick // This helper routine returns an expression of Start + IntVal .
13409467b48Spatrick //
13509467b48Spatrick static inline const MCExpr *
makeStartPlusIntExpr(MCContext & Ctx,const MCSymbol & Start,int IntVal)13609467b48Spatrick makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) {
13709467b48Spatrick MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
13809467b48Spatrick const MCExpr *LHS = MCSymbolRefExpr::create(&Start, Variant, Ctx);
13909467b48Spatrick const MCExpr *RHS = MCConstantExpr::create(IntVal, Ctx);
14009467b48Spatrick const MCExpr *Res = MCBinaryExpr::create(MCBinaryExpr::Add, LHS, RHS, Ctx);
14109467b48Spatrick return Res;
14209467b48Spatrick }
14309467b48Spatrick
addEndEntry(MCSymbol * EndLabel)144*d415bd75Srobert void MCLineSection::addEndEntry(MCSymbol *EndLabel) {
145*d415bd75Srobert auto *Sec = &EndLabel->getSection();
146*d415bd75Srobert // The line table may be empty, which we should skip adding an end entry.
147*d415bd75Srobert // There are two cases:
148*d415bd75Srobert // (1) MCAsmStreamer - emitDwarfLocDirective emits a location directive in
149*d415bd75Srobert // place instead of adding a line entry if the target has
150*d415bd75Srobert // usesDwarfFileAndLocDirectives.
151*d415bd75Srobert // (2) MCObjectStreamer - if a function has incomplete debug info where
152*d415bd75Srobert // instructions don't have DILocations, the line entries are missing.
153*d415bd75Srobert auto I = MCLineDivisions.find(Sec);
154*d415bd75Srobert if (I != MCLineDivisions.end()) {
155*d415bd75Srobert auto &Entries = I->second;
156*d415bd75Srobert auto EndEntry = Entries.back();
157*d415bd75Srobert EndEntry.setEndLabel(EndLabel);
158*d415bd75Srobert Entries.push_back(EndEntry);
159*d415bd75Srobert }
160*d415bd75Srobert }
161*d415bd75Srobert
16209467b48Spatrick //
16309467b48Spatrick // This emits the Dwarf line table for the specified section from the entries
16409467b48Spatrick // in the LineSection.
16509467b48Spatrick //
emitOne(MCStreamer * MCOS,MCSection * Section,const MCLineSection::MCDwarfLineEntryCollection & LineEntries)166*d415bd75Srobert void MCDwarfLineTable::emitOne(
16773471bf0Spatrick MCStreamer *MCOS, MCSection *Section,
16809467b48Spatrick const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
169*d415bd75Srobert
170*d415bd75Srobert unsigned FileNum, LastLine, Column, Flags, Isa, Discriminator;
171*d415bd75Srobert MCSymbol *LastLabel;
172*d415bd75Srobert auto init = [&]() {
173*d415bd75Srobert FileNum = 1;
174*d415bd75Srobert LastLine = 1;
175*d415bd75Srobert Column = 0;
176*d415bd75Srobert Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
177*d415bd75Srobert Isa = 0;
178*d415bd75Srobert Discriminator = 0;
179*d415bd75Srobert LastLabel = nullptr;
180*d415bd75Srobert };
181*d415bd75Srobert init();
18209467b48Spatrick
18309467b48Spatrick // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
184*d415bd75Srobert bool EndEntryEmitted = false;
18509467b48Spatrick for (const MCDwarfLineEntry &LineEntry : LineEntries) {
186*d415bd75Srobert MCSymbol *Label = LineEntry.getLabel();
187*d415bd75Srobert const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();
188*d415bd75Srobert if (LineEntry.IsEndEntry) {
189*d415bd75Srobert MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, Label,
190*d415bd75Srobert asmInfo->getCodePointerSize());
191*d415bd75Srobert init();
192*d415bd75Srobert EndEntryEmitted = true;
193*d415bd75Srobert continue;
194*d415bd75Srobert }
195*d415bd75Srobert
19609467b48Spatrick int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
19709467b48Spatrick
19809467b48Spatrick if (FileNum != LineEntry.getFileNum()) {
19909467b48Spatrick FileNum = LineEntry.getFileNum();
200097a140dSpatrick MCOS->emitInt8(dwarf::DW_LNS_set_file);
201097a140dSpatrick MCOS->emitULEB128IntValue(FileNum);
20209467b48Spatrick }
20309467b48Spatrick if (Column != LineEntry.getColumn()) {
20409467b48Spatrick Column = LineEntry.getColumn();
205097a140dSpatrick MCOS->emitInt8(dwarf::DW_LNS_set_column);
206097a140dSpatrick MCOS->emitULEB128IntValue(Column);
20709467b48Spatrick }
20809467b48Spatrick if (Discriminator != LineEntry.getDiscriminator() &&
20909467b48Spatrick MCOS->getContext().getDwarfVersion() >= 4) {
21009467b48Spatrick Discriminator = LineEntry.getDiscriminator();
21109467b48Spatrick unsigned Size = getULEB128Size(Discriminator);
212097a140dSpatrick MCOS->emitInt8(dwarf::DW_LNS_extended_op);
213097a140dSpatrick MCOS->emitULEB128IntValue(Size + 1);
214097a140dSpatrick MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
215097a140dSpatrick MCOS->emitULEB128IntValue(Discriminator);
21609467b48Spatrick }
21709467b48Spatrick if (Isa != LineEntry.getIsa()) {
21809467b48Spatrick Isa = LineEntry.getIsa();
219097a140dSpatrick MCOS->emitInt8(dwarf::DW_LNS_set_isa);
220097a140dSpatrick MCOS->emitULEB128IntValue(Isa);
22109467b48Spatrick }
22209467b48Spatrick if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
22309467b48Spatrick Flags = LineEntry.getFlags();
224097a140dSpatrick MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
22509467b48Spatrick }
22609467b48Spatrick if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
227097a140dSpatrick MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
22809467b48Spatrick if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
229097a140dSpatrick MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
23009467b48Spatrick if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
231097a140dSpatrick MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
23209467b48Spatrick
23309467b48Spatrick // At this point we want to emit/create the sequence to encode the delta in
23409467b48Spatrick // line numbers and the increment of the address from the previous Label
23509467b48Spatrick // and the current Label.
236097a140dSpatrick MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
23709467b48Spatrick asmInfo->getCodePointerSize());
23809467b48Spatrick
23909467b48Spatrick Discriminator = 0;
24009467b48Spatrick LastLine = LineEntry.getLine();
24109467b48Spatrick LastLabel = Label;
24209467b48Spatrick }
24309467b48Spatrick
24473471bf0Spatrick // Generate DWARF line end entry.
245*d415bd75Srobert // We do not need this for DwarfDebug that explicitly terminates the line
246*d415bd75Srobert // table using ranges whenever CU or section changes. However, the MC path
247*d415bd75Srobert // does not track ranges nor terminate the line table. In that case,
248*d415bd75Srobert // conservatively use the section end symbol to end the line table.
249*d415bd75Srobert if (!EndEntryEmitted)
25073471bf0Spatrick MCOS->emitDwarfLineEndEntry(Section, LastLabel);
25109467b48Spatrick }
25209467b48Spatrick
25309467b48Spatrick //
25409467b48Spatrick // This emits the Dwarf file and the line tables.
25509467b48Spatrick //
emit(MCStreamer * MCOS,MCDwarfLineTableParams Params)25673471bf0Spatrick void MCDwarfLineTable::emit(MCStreamer *MCOS, MCDwarfLineTableParams Params) {
25709467b48Spatrick MCContext &context = MCOS->getContext();
25809467b48Spatrick
25909467b48Spatrick auto &LineTables = context.getMCDwarfLineTables();
26009467b48Spatrick
26109467b48Spatrick // Bail out early so we don't switch to the debug_line section needlessly and
26209467b48Spatrick // in doing so create an unnecessary (if empty) section.
26309467b48Spatrick if (LineTables.empty())
26409467b48Spatrick return;
26509467b48Spatrick
26609467b48Spatrick // In a v5 non-split line table, put the strings in a separate section.
267*d415bd75Srobert std::optional<MCDwarfLineStr> LineStr;
26809467b48Spatrick if (context.getDwarfVersion() >= 5)
269*d415bd75Srobert LineStr.emplace(context);
27009467b48Spatrick
27109467b48Spatrick // Switch to the section where the table will be emitted into.
272*d415bd75Srobert MCOS->switchSection(context.getObjectFileInfo()->getDwarfLineSection());
27309467b48Spatrick
27409467b48Spatrick // Handle the rest of the Compile Units.
27509467b48Spatrick for (const auto &CUIDTablePair : LineTables) {
27673471bf0Spatrick CUIDTablePair.second.emitCU(MCOS, Params, LineStr);
27709467b48Spatrick }
27809467b48Spatrick
27909467b48Spatrick if (LineStr)
28009467b48Spatrick LineStr->emitSection(MCOS);
28109467b48Spatrick }
28209467b48Spatrick
Emit(MCStreamer & MCOS,MCDwarfLineTableParams Params,MCSection * Section) const28309467b48Spatrick void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
28409467b48Spatrick MCSection *Section) const {
28509467b48Spatrick if (!HasSplitLineTable)
28609467b48Spatrick return;
287*d415bd75Srobert std::optional<MCDwarfLineStr> NoLineStr(std::nullopt);
288*d415bd75Srobert MCOS.switchSection(Section);
289*d415bd75Srobert MCOS.emitLabel(Header.Emit(&MCOS, Params, std::nullopt, NoLineStr).second);
29009467b48Spatrick }
29109467b48Spatrick
29209467b48Spatrick std::pair<MCSymbol *, MCSymbol *>
Emit(MCStreamer * MCOS,MCDwarfLineTableParams Params,std::optional<MCDwarfLineStr> & LineStr) const29309467b48Spatrick MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
294*d415bd75Srobert std::optional<MCDwarfLineStr> &LineStr) const {
29509467b48Spatrick static const char StandardOpcodeLengths[] = {
29609467b48Spatrick 0, // length of DW_LNS_copy
29709467b48Spatrick 1, // length of DW_LNS_advance_pc
29809467b48Spatrick 1, // length of DW_LNS_advance_line
29909467b48Spatrick 1, // length of DW_LNS_set_file
30009467b48Spatrick 1, // length of DW_LNS_set_column
30109467b48Spatrick 0, // length of DW_LNS_negate_stmt
30209467b48Spatrick 0, // length of DW_LNS_set_basic_block
30309467b48Spatrick 0, // length of DW_LNS_const_add_pc
30409467b48Spatrick 1, // length of DW_LNS_fixed_advance_pc
30509467b48Spatrick 0, // length of DW_LNS_set_prologue_end
30609467b48Spatrick 0, // length of DW_LNS_set_epilogue_begin
30709467b48Spatrick 1 // DW_LNS_set_isa
30809467b48Spatrick };
309*d415bd75Srobert assert(std::size(StandardOpcodeLengths) >=
31009467b48Spatrick (Params.DWARF2LineOpcodeBase - 1U));
311*d415bd75Srobert return Emit(MCOS, Params,
312*d415bd75Srobert ArrayRef(StandardOpcodeLengths, Params.DWARF2LineOpcodeBase - 1),
31309467b48Spatrick LineStr);
31409467b48Spatrick }
31509467b48Spatrick
forceExpAbs(MCStreamer & OS,const MCExpr * Expr)31609467b48Spatrick static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) {
31709467b48Spatrick MCContext &Context = OS.getContext();
31809467b48Spatrick assert(!isa<MCSymbolRefExpr>(Expr));
31909467b48Spatrick if (Context.getAsmInfo()->hasAggressiveSymbolFolding())
32009467b48Spatrick return Expr;
32109467b48Spatrick
32209467b48Spatrick MCSymbol *ABS = Context.createTempSymbol();
323097a140dSpatrick OS.emitAssignment(ABS, Expr);
32409467b48Spatrick return MCSymbolRefExpr::create(ABS, Context);
32509467b48Spatrick }
32609467b48Spatrick
emitAbsValue(MCStreamer & OS,const MCExpr * Value,unsigned Size)32709467b48Spatrick static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) {
32809467b48Spatrick const MCExpr *ABS = forceExpAbs(OS, Value);
329097a140dSpatrick OS.emitValue(ABS, Size);
33009467b48Spatrick }
33109467b48Spatrick
emitSection(MCStreamer * MCOS)33209467b48Spatrick void MCDwarfLineStr::emitSection(MCStreamer *MCOS) {
33309467b48Spatrick // Switch to the .debug_line_str section.
334*d415bd75Srobert MCOS->switchSection(
33509467b48Spatrick MCOS->getContext().getObjectFileInfo()->getDwarfLineStrSection());
336*d415bd75Srobert SmallString<0> Data = getFinalizedData();
337*d415bd75Srobert MCOS->emitBinaryData(Data.str());
338*d415bd75Srobert }
339*d415bd75Srobert
getFinalizedData()340*d415bd75Srobert SmallString<0> MCDwarfLineStr::getFinalizedData() {
34109467b48Spatrick // Emit the strings without perturbing the offsets we used.
342*d415bd75Srobert if (!LineStrings.isFinalized())
34309467b48Spatrick LineStrings.finalizeInOrder();
34409467b48Spatrick SmallString<0> Data;
34509467b48Spatrick Data.resize(LineStrings.getSize());
34609467b48Spatrick LineStrings.write((uint8_t *)Data.data());
347*d415bd75Srobert return Data;
34809467b48Spatrick }
34909467b48Spatrick
emitRef(MCStreamer * MCOS,StringRef Path)35009467b48Spatrick void MCDwarfLineStr::emitRef(MCStreamer *MCOS, StringRef Path) {
351097a140dSpatrick int RefSize =
352097a140dSpatrick dwarf::getDwarfOffsetByteSize(MCOS->getContext().getDwarfFormat());
35309467b48Spatrick size_t Offset = LineStrings.add(Path);
35409467b48Spatrick if (UseRelocs) {
35509467b48Spatrick MCContext &Ctx = MCOS->getContext();
356097a140dSpatrick MCOS->emitValue(makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset), RefSize);
35709467b48Spatrick } else
358097a140dSpatrick MCOS->emitIntValue(Offset, RefSize);
35909467b48Spatrick }
36009467b48Spatrick
emitV2FileDirTables(MCStreamer * MCOS) const36109467b48Spatrick void MCDwarfLineTableHeader::emitV2FileDirTables(MCStreamer *MCOS) const {
36209467b48Spatrick // First the directory table.
36309467b48Spatrick for (auto &Dir : MCDwarfDirs) {
364097a140dSpatrick MCOS->emitBytes(Dir); // The DirectoryName, and...
365097a140dSpatrick MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
36609467b48Spatrick }
367097a140dSpatrick MCOS->emitInt8(0); // Terminate the directory list.
36809467b48Spatrick
36909467b48Spatrick // Second the file table.
37009467b48Spatrick for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
37109467b48Spatrick assert(!MCDwarfFiles[i].Name.empty());
372097a140dSpatrick MCOS->emitBytes(MCDwarfFiles[i].Name); // FileName and...
373097a140dSpatrick MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
374097a140dSpatrick MCOS->emitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number.
375097a140dSpatrick MCOS->emitInt8(0); // Last modification timestamp (always 0).
376097a140dSpatrick MCOS->emitInt8(0); // File size (always 0).
37709467b48Spatrick }
378097a140dSpatrick MCOS->emitInt8(0); // Terminate the file list.
37909467b48Spatrick }
38009467b48Spatrick
emitOneV5FileEntry(MCStreamer * MCOS,const MCDwarfFile & DwarfFile,bool EmitMD5,bool HasSource,std::optional<MCDwarfLineStr> & LineStr)38109467b48Spatrick static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
38209467b48Spatrick bool EmitMD5, bool HasSource,
383*d415bd75Srobert std::optional<MCDwarfLineStr> &LineStr) {
38409467b48Spatrick assert(!DwarfFile.Name.empty());
38509467b48Spatrick if (LineStr)
38609467b48Spatrick LineStr->emitRef(MCOS, DwarfFile.Name);
38709467b48Spatrick else {
388097a140dSpatrick MCOS->emitBytes(DwarfFile.Name); // FileName and...
389097a140dSpatrick MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
39009467b48Spatrick }
391097a140dSpatrick MCOS->emitULEB128IntValue(DwarfFile.DirIndex); // Directory number.
39209467b48Spatrick if (EmitMD5) {
39309467b48Spatrick const MD5::MD5Result &Cksum = *DwarfFile.Checksum;
394097a140dSpatrick MCOS->emitBinaryData(
395*d415bd75Srobert StringRef(reinterpret_cast<const char *>(Cksum.data()), Cksum.size()));
39609467b48Spatrick }
39709467b48Spatrick if (HasSource) {
39809467b48Spatrick if (LineStr)
399*d415bd75Srobert LineStr->emitRef(MCOS, DwarfFile.Source.value_or(StringRef()));
40009467b48Spatrick else {
401*d415bd75Srobert MCOS->emitBytes(DwarfFile.Source.value_or(StringRef())); // Source and...
402097a140dSpatrick MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
40309467b48Spatrick }
40409467b48Spatrick }
40509467b48Spatrick }
40609467b48Spatrick
emitV5FileDirTables(MCStreamer * MCOS,std::optional<MCDwarfLineStr> & LineStr) const40709467b48Spatrick void MCDwarfLineTableHeader::emitV5FileDirTables(
408*d415bd75Srobert MCStreamer *MCOS, std::optional<MCDwarfLineStr> &LineStr) const {
40909467b48Spatrick // The directory format, which is just a list of the directory paths. In a
41009467b48Spatrick // non-split object, these are references to .debug_line_str; in a split
41109467b48Spatrick // object, they are inline strings.
412097a140dSpatrick MCOS->emitInt8(1);
413097a140dSpatrick MCOS->emitULEB128IntValue(dwarf::DW_LNCT_path);
414097a140dSpatrick MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
41509467b48Spatrick : dwarf::DW_FORM_string);
416097a140dSpatrick MCOS->emitULEB128IntValue(MCDwarfDirs.size() + 1);
41709467b48Spatrick // Try not to emit an empty compilation directory.
418*d415bd75Srobert SmallString<256> Dir;
419*d415bd75Srobert StringRef CompDir = MCOS->getContext().getCompilationDir();
420*d415bd75Srobert if (!CompilationDir.empty()) {
421*d415bd75Srobert Dir = CompilationDir;
422*d415bd75Srobert MCOS->getContext().remapDebugPath(Dir);
423*d415bd75Srobert CompDir = Dir.str();
424*d415bd75Srobert if (LineStr)
425*d415bd75Srobert CompDir = LineStr->getSaver().save(CompDir);
426*d415bd75Srobert }
42709467b48Spatrick if (LineStr) {
42809467b48Spatrick // Record path strings, emit references here.
42909467b48Spatrick LineStr->emitRef(MCOS, CompDir);
43009467b48Spatrick for (const auto &Dir : MCDwarfDirs)
43109467b48Spatrick LineStr->emitRef(MCOS, Dir);
43209467b48Spatrick } else {
43309467b48Spatrick // The list of directory paths. Compilation directory comes first.
434097a140dSpatrick MCOS->emitBytes(CompDir);
435097a140dSpatrick MCOS->emitBytes(StringRef("\0", 1));
43609467b48Spatrick for (const auto &Dir : MCDwarfDirs) {
437097a140dSpatrick MCOS->emitBytes(Dir); // The DirectoryName, and...
438097a140dSpatrick MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
43909467b48Spatrick }
44009467b48Spatrick }
44109467b48Spatrick
44209467b48Spatrick // The file format, which is the inline null-terminated filename and a
44309467b48Spatrick // directory index. We don't track file size/timestamp so don't emit them
44409467b48Spatrick // in the v5 table. Emit MD5 checksums and source if we have them.
44509467b48Spatrick uint64_t Entries = 2;
44609467b48Spatrick if (HasAllMD5)
44709467b48Spatrick Entries += 1;
44809467b48Spatrick if (HasSource)
44909467b48Spatrick Entries += 1;
450097a140dSpatrick MCOS->emitInt8(Entries);
451097a140dSpatrick MCOS->emitULEB128IntValue(dwarf::DW_LNCT_path);
452097a140dSpatrick MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
45309467b48Spatrick : dwarf::DW_FORM_string);
454097a140dSpatrick MCOS->emitULEB128IntValue(dwarf::DW_LNCT_directory_index);
455097a140dSpatrick MCOS->emitULEB128IntValue(dwarf::DW_FORM_udata);
45609467b48Spatrick if (HasAllMD5) {
457097a140dSpatrick MCOS->emitULEB128IntValue(dwarf::DW_LNCT_MD5);
458097a140dSpatrick MCOS->emitULEB128IntValue(dwarf::DW_FORM_data16);
45909467b48Spatrick }
46009467b48Spatrick if (HasSource) {
461097a140dSpatrick MCOS->emitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
462097a140dSpatrick MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
46309467b48Spatrick : dwarf::DW_FORM_string);
46409467b48Spatrick }
46509467b48Spatrick // Then the counted list of files. The root file is file #0, then emit the
46609467b48Spatrick // files as provide by .file directives.
46709467b48Spatrick // MCDwarfFiles has an unused element [0] so use size() not size()+1.
46809467b48Spatrick // But sometimes MCDwarfFiles is empty, in which case we still emit one file.
469097a140dSpatrick MCOS->emitULEB128IntValue(MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size());
47009467b48Spatrick // To accommodate assembler source written for DWARF v4 but trying to emit
47109467b48Spatrick // v5: If we didn't see a root file explicitly, replicate file #1.
47209467b48Spatrick assert((!RootFile.Name.empty() || MCDwarfFiles.size() >= 1) &&
47309467b48Spatrick "No root file and no .file directives");
47409467b48Spatrick emitOneV5FileEntry(MCOS, RootFile.Name.empty() ? MCDwarfFiles[1] : RootFile,
47509467b48Spatrick HasAllMD5, HasSource, LineStr);
47609467b48Spatrick for (unsigned i = 1; i < MCDwarfFiles.size(); ++i)
47709467b48Spatrick emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasSource, LineStr);
47809467b48Spatrick }
47909467b48Spatrick
48009467b48Spatrick std::pair<MCSymbol *, MCSymbol *>
Emit(MCStreamer * MCOS,MCDwarfLineTableParams Params,ArrayRef<char> StandardOpcodeLengths,std::optional<MCDwarfLineStr> & LineStr) const48109467b48Spatrick MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
48209467b48Spatrick ArrayRef<char> StandardOpcodeLengths,
483*d415bd75Srobert std::optional<MCDwarfLineStr> &LineStr) const {
48409467b48Spatrick MCContext &context = MCOS->getContext();
48509467b48Spatrick
48609467b48Spatrick // Create a symbol at the beginning of the line table.
48709467b48Spatrick MCSymbol *LineStartSym = Label;
48809467b48Spatrick if (!LineStartSym)
48909467b48Spatrick LineStartSym = context.createTempSymbol();
49073471bf0Spatrick
49109467b48Spatrick // Set the value of the symbol, as we are at the start of the line table.
49273471bf0Spatrick MCOS->emitDwarfLineStartLabel(LineStartSym);
49309467b48Spatrick
494097a140dSpatrick unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());
495097a140dSpatrick
49673471bf0Spatrick MCSymbol *LineEndSym = MCOS->emitDwarfUnitLength("debug_line", "unit length");
49709467b48Spatrick
49809467b48Spatrick // Next 2 bytes is the Version.
49909467b48Spatrick unsigned LineTableVersion = context.getDwarfVersion();
500097a140dSpatrick MCOS->emitInt16(LineTableVersion);
50109467b48Spatrick
50209467b48Spatrick // In v5, we get address info next.
50309467b48Spatrick if (LineTableVersion >= 5) {
504097a140dSpatrick MCOS->emitInt8(context.getAsmInfo()->getCodePointerSize());
505097a140dSpatrick MCOS->emitInt8(0); // Segment selector; same as EmitGenDwarfAranges.
50609467b48Spatrick }
50709467b48Spatrick
50873471bf0Spatrick // Create symbols for the start/end of the prologue.
50973471bf0Spatrick MCSymbol *ProStartSym = context.createTempSymbol("prologue_start");
51073471bf0Spatrick MCSymbol *ProEndSym = context.createTempSymbol("prologue_end");
51109467b48Spatrick
512097a140dSpatrick // Length of the prologue, is the next 4 bytes (8 bytes for DWARF64). This is
513097a140dSpatrick // actually the length from after the length word, to the end of the prologue.
51473471bf0Spatrick MCOS->emitAbsoluteSymbolDiff(ProEndSym, ProStartSym, OffsetSize);
51573471bf0Spatrick
51673471bf0Spatrick MCOS->emitLabel(ProStartSym);
51709467b48Spatrick
51809467b48Spatrick // Parameters of the state machine, are next.
519097a140dSpatrick MCOS->emitInt8(context.getAsmInfo()->getMinInstAlignment());
52009467b48Spatrick // maximum_operations_per_instruction
52109467b48Spatrick // For non-VLIW architectures this field is always 1.
52209467b48Spatrick // FIXME: VLIW architectures need to update this field accordingly.
52309467b48Spatrick if (LineTableVersion >= 4)
524097a140dSpatrick MCOS->emitInt8(1);
525097a140dSpatrick MCOS->emitInt8(DWARF2_LINE_DEFAULT_IS_STMT);
526097a140dSpatrick MCOS->emitInt8(Params.DWARF2LineBase);
527097a140dSpatrick MCOS->emitInt8(Params.DWARF2LineRange);
528097a140dSpatrick MCOS->emitInt8(StandardOpcodeLengths.size() + 1);
52909467b48Spatrick
53009467b48Spatrick // Standard opcode lengths
53109467b48Spatrick for (char Length : StandardOpcodeLengths)
532097a140dSpatrick MCOS->emitInt8(Length);
53309467b48Spatrick
53409467b48Spatrick // Put out the directory and file tables. The formats vary depending on
53509467b48Spatrick // the version.
53609467b48Spatrick if (LineTableVersion >= 5)
53709467b48Spatrick emitV5FileDirTables(MCOS, LineStr);
53809467b48Spatrick else
53909467b48Spatrick emitV2FileDirTables(MCOS);
54009467b48Spatrick
54109467b48Spatrick // This is the end of the prologue, so set the value of the symbol at the
54209467b48Spatrick // end of the prologue (that was used in a previous expression).
543097a140dSpatrick MCOS->emitLabel(ProEndSym);
54409467b48Spatrick
54509467b48Spatrick return std::make_pair(LineStartSym, LineEndSym);
54609467b48Spatrick }
54709467b48Spatrick
emitCU(MCStreamer * MCOS,MCDwarfLineTableParams Params,std::optional<MCDwarfLineStr> & LineStr) const54873471bf0Spatrick void MCDwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
549*d415bd75Srobert std::optional<MCDwarfLineStr> &LineStr) const {
55009467b48Spatrick MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
55109467b48Spatrick
55209467b48Spatrick // Put out the line tables.
55309467b48Spatrick for (const auto &LineSec : MCLineSections.getMCLineEntries())
554*d415bd75Srobert emitOne(MCOS, LineSec.first, LineSec.second);
55509467b48Spatrick
55609467b48Spatrick // This is the end of the section, so set the value of the symbol at the end
55709467b48Spatrick // of this section (that was used in a previous expression).
558097a140dSpatrick MCOS->emitLabel(LineEndSym);
55909467b48Spatrick }
56009467b48Spatrick
561*d415bd75Srobert Expected<unsigned>
tryGetFile(StringRef & Directory,StringRef & FileName,std::optional<MD5::MD5Result> Checksum,std::optional<StringRef> Source,uint16_t DwarfVersion,unsigned FileNumber)562*d415bd75Srobert MCDwarfLineTable::tryGetFile(StringRef &Directory, StringRef &FileName,
563*d415bd75Srobert std::optional<MD5::MD5Result> Checksum,
564*d415bd75Srobert std::optional<StringRef> Source,
565*d415bd75Srobert uint16_t DwarfVersion, unsigned FileNumber) {
56609467b48Spatrick return Header.tryGetFile(Directory, FileName, Checksum, Source, DwarfVersion,
56709467b48Spatrick FileNumber);
56809467b48Spatrick }
56909467b48Spatrick
isRootFile(const MCDwarfFile & RootFile,StringRef & Directory,StringRef & FileName,std::optional<MD5::MD5Result> Checksum)57009467b48Spatrick static bool isRootFile(const MCDwarfFile &RootFile, StringRef &Directory,
571*d415bd75Srobert StringRef &FileName,
572*d415bd75Srobert std::optional<MD5::MD5Result> Checksum) {
573*d415bd75Srobert if (RootFile.Name.empty() || StringRef(RootFile.Name) != FileName)
57409467b48Spatrick return false;
57509467b48Spatrick return RootFile.Checksum == Checksum;
57609467b48Spatrick }
57709467b48Spatrick
57809467b48Spatrick Expected<unsigned>
tryGetFile(StringRef & Directory,StringRef & FileName,std::optional<MD5::MD5Result> Checksum,std::optional<StringRef> Source,uint16_t DwarfVersion,unsigned FileNumber)579*d415bd75Srobert MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, StringRef &FileName,
580*d415bd75Srobert std::optional<MD5::MD5Result> Checksum,
581*d415bd75Srobert std::optional<StringRef> Source,
582*d415bd75Srobert uint16_t DwarfVersion, unsigned FileNumber) {
58309467b48Spatrick if (Directory == CompilationDir)
58409467b48Spatrick Directory = "";
58509467b48Spatrick if (FileName.empty()) {
58609467b48Spatrick FileName = "<stdin>";
58709467b48Spatrick Directory = "";
58809467b48Spatrick }
58909467b48Spatrick assert(!FileName.empty());
59009467b48Spatrick // Keep track of whether any or all files have an MD5 checksum.
59109467b48Spatrick // If any files have embedded source, they all must.
59209467b48Spatrick if (MCDwarfFiles.empty()) {
593*d415bd75Srobert trackMD5Usage(Checksum.has_value());
594*d415bd75Srobert HasSource = (Source != std::nullopt);
59509467b48Spatrick }
596*d415bd75Srobert if (DwarfVersion >= 5 && isRootFile(RootFile, Directory, FileName, Checksum))
59709467b48Spatrick return 0;
59809467b48Spatrick if (FileNumber == 0) {
59909467b48Spatrick // File numbers start with 1 and/or after any file numbers
60009467b48Spatrick // allocated by inline-assembler .file directives.
60109467b48Spatrick FileNumber = MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size();
60209467b48Spatrick SmallString<256> Buffer;
60309467b48Spatrick auto IterBool = SourceIdMap.insert(
60409467b48Spatrick std::make_pair((Directory + Twine('\0') + FileName).toStringRef(Buffer),
60509467b48Spatrick FileNumber));
60609467b48Spatrick if (!IterBool.second)
60709467b48Spatrick return IterBool.first->second;
60809467b48Spatrick }
60909467b48Spatrick // Make space for this FileNumber in the MCDwarfFiles vector if needed.
61009467b48Spatrick if (FileNumber >= MCDwarfFiles.size())
61109467b48Spatrick MCDwarfFiles.resize(FileNumber + 1);
61209467b48Spatrick
61309467b48Spatrick // Get the new MCDwarfFile slot for this FileNumber.
61409467b48Spatrick MCDwarfFile &File = MCDwarfFiles[FileNumber];
61509467b48Spatrick
61609467b48Spatrick // It is an error to see the same number more than once.
61709467b48Spatrick if (!File.Name.empty())
61809467b48Spatrick return make_error<StringError>("file number already allocated",
61909467b48Spatrick inconvertibleErrorCode());
62009467b48Spatrick
62109467b48Spatrick // If any files have embedded source, they all must.
622*d415bd75Srobert if (HasSource != (Source != std::nullopt))
62309467b48Spatrick return make_error<StringError>("inconsistent use of embedded source",
62409467b48Spatrick inconvertibleErrorCode());
62509467b48Spatrick
62609467b48Spatrick if (Directory.empty()) {
62709467b48Spatrick // Separate the directory part from the basename of the FileName.
62809467b48Spatrick StringRef tFileName = sys::path::filename(FileName);
62909467b48Spatrick if (!tFileName.empty()) {
63009467b48Spatrick Directory = sys::path::parent_path(FileName);
63109467b48Spatrick if (!Directory.empty())
63209467b48Spatrick FileName = tFileName;
63309467b48Spatrick }
63409467b48Spatrick }
63509467b48Spatrick
63609467b48Spatrick // Find or make an entry in the MCDwarfDirs vector for this Directory.
63709467b48Spatrick // Capture directory name.
63809467b48Spatrick unsigned DirIndex;
63909467b48Spatrick if (Directory.empty()) {
64009467b48Spatrick // For FileNames with no directories a DirIndex of 0 is used.
64109467b48Spatrick DirIndex = 0;
64209467b48Spatrick } else {
64309467b48Spatrick DirIndex = llvm::find(MCDwarfDirs, Directory) - MCDwarfDirs.begin();
64409467b48Spatrick if (DirIndex >= MCDwarfDirs.size())
645097a140dSpatrick MCDwarfDirs.push_back(std::string(Directory));
64609467b48Spatrick // The DirIndex is one based, as DirIndex of 0 is used for FileNames with
64709467b48Spatrick // no directories. MCDwarfDirs[] is unlike MCDwarfFiles[] in that the
64809467b48Spatrick // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames
64909467b48Spatrick // are stored at MCDwarfFiles[FileNumber].Name .
65009467b48Spatrick DirIndex++;
65109467b48Spatrick }
65209467b48Spatrick
653097a140dSpatrick File.Name = std::string(FileName);
65409467b48Spatrick File.DirIndex = DirIndex;
65509467b48Spatrick File.Checksum = Checksum;
656*d415bd75Srobert trackMD5Usage(Checksum.has_value());
65709467b48Spatrick File.Source = Source;
65809467b48Spatrick if (Source)
65909467b48Spatrick HasSource = true;
66009467b48Spatrick
66109467b48Spatrick // return the allocated FileNumber.
66209467b48Spatrick return FileNumber;
66309467b48Spatrick }
66409467b48Spatrick
66509467b48Spatrick /// Utility function to emit the encoding to a streamer.
Emit(MCStreamer * MCOS,MCDwarfLineTableParams Params,int64_t LineDelta,uint64_t AddrDelta)66609467b48Spatrick void MCDwarfLineAddr::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
66709467b48Spatrick int64_t LineDelta, uint64_t AddrDelta) {
66809467b48Spatrick MCContext &Context = MCOS->getContext();
66909467b48Spatrick SmallString<256> Tmp;
67009467b48Spatrick raw_svector_ostream OS(Tmp);
67109467b48Spatrick MCDwarfLineAddr::Encode(Context, Params, LineDelta, AddrDelta, OS);
672097a140dSpatrick MCOS->emitBytes(OS.str());
67309467b48Spatrick }
67409467b48Spatrick
67509467b48Spatrick /// Given a special op, return the address skip amount (in units of
67609467b48Spatrick /// DWARF2_LINE_MIN_INSN_LENGTH).
SpecialAddr(MCDwarfLineTableParams Params,uint64_t op)67709467b48Spatrick static uint64_t SpecialAddr(MCDwarfLineTableParams Params, uint64_t op) {
67809467b48Spatrick return (op - Params.DWARF2LineOpcodeBase) / Params.DWARF2LineRange;
67909467b48Spatrick }
68009467b48Spatrick
68109467b48Spatrick /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
Encode(MCContext & Context,MCDwarfLineTableParams Params,int64_t LineDelta,uint64_t AddrDelta,raw_ostream & OS)68209467b48Spatrick void MCDwarfLineAddr::Encode(MCContext &Context, MCDwarfLineTableParams Params,
68309467b48Spatrick int64_t LineDelta, uint64_t AddrDelta,
68409467b48Spatrick raw_ostream &OS) {
68509467b48Spatrick uint64_t Temp, Opcode;
68609467b48Spatrick bool NeedCopy = false;
68709467b48Spatrick
68809467b48Spatrick // The maximum address skip amount that can be encoded with a special op.
68909467b48Spatrick uint64_t MaxSpecialAddrDelta = SpecialAddr(Params, 255);
69009467b48Spatrick
69109467b48Spatrick // Scale the address delta by the minimum instruction length.
69209467b48Spatrick AddrDelta = ScaleAddrDelta(Context, AddrDelta);
69309467b48Spatrick
69409467b48Spatrick // A LineDelta of INT64_MAX is a signal that this is actually a
69509467b48Spatrick // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the
69609467b48Spatrick // end_sequence to emit the matrix entry.
69709467b48Spatrick if (LineDelta == INT64_MAX) {
69809467b48Spatrick if (AddrDelta == MaxSpecialAddrDelta)
69909467b48Spatrick OS << char(dwarf::DW_LNS_const_add_pc);
70009467b48Spatrick else if (AddrDelta) {
70109467b48Spatrick OS << char(dwarf::DW_LNS_advance_pc);
70209467b48Spatrick encodeULEB128(AddrDelta, OS);
70309467b48Spatrick }
70409467b48Spatrick OS << char(dwarf::DW_LNS_extended_op);
70509467b48Spatrick OS << char(1);
70609467b48Spatrick OS << char(dwarf::DW_LNE_end_sequence);
70709467b48Spatrick return;
70809467b48Spatrick }
70909467b48Spatrick
71009467b48Spatrick // Bias the line delta by the base.
71109467b48Spatrick Temp = LineDelta - Params.DWARF2LineBase;
71209467b48Spatrick
71309467b48Spatrick // If the line increment is out of range of a special opcode, we must encode
71409467b48Spatrick // it with DW_LNS_advance_line.
71509467b48Spatrick if (Temp >= Params.DWARF2LineRange ||
71609467b48Spatrick Temp + Params.DWARF2LineOpcodeBase > 255) {
71709467b48Spatrick OS << char(dwarf::DW_LNS_advance_line);
71809467b48Spatrick encodeSLEB128(LineDelta, OS);
71909467b48Spatrick
72009467b48Spatrick LineDelta = 0;
72109467b48Spatrick Temp = 0 - Params.DWARF2LineBase;
72209467b48Spatrick NeedCopy = true;
72309467b48Spatrick }
72409467b48Spatrick
72509467b48Spatrick // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode.
72609467b48Spatrick if (LineDelta == 0 && AddrDelta == 0) {
72709467b48Spatrick OS << char(dwarf::DW_LNS_copy);
72809467b48Spatrick return;
72909467b48Spatrick }
73009467b48Spatrick
73109467b48Spatrick // Bias the opcode by the special opcode base.
73209467b48Spatrick Temp += Params.DWARF2LineOpcodeBase;
73309467b48Spatrick
73409467b48Spatrick // Avoid overflow when addr_delta is large.
73509467b48Spatrick if (AddrDelta < 256 + MaxSpecialAddrDelta) {
73609467b48Spatrick // Try using a special opcode.
73709467b48Spatrick Opcode = Temp + AddrDelta * Params.DWARF2LineRange;
73809467b48Spatrick if (Opcode <= 255) {
73909467b48Spatrick OS << char(Opcode);
74009467b48Spatrick return;
74109467b48Spatrick }
74209467b48Spatrick
74309467b48Spatrick // Try using DW_LNS_const_add_pc followed by special op.
74409467b48Spatrick Opcode = Temp + (AddrDelta - MaxSpecialAddrDelta) * Params.DWARF2LineRange;
74509467b48Spatrick if (Opcode <= 255) {
74609467b48Spatrick OS << char(dwarf::DW_LNS_const_add_pc);
74709467b48Spatrick OS << char(Opcode);
74809467b48Spatrick return;
74909467b48Spatrick }
75009467b48Spatrick }
75109467b48Spatrick
75209467b48Spatrick // Otherwise use DW_LNS_advance_pc.
75309467b48Spatrick OS << char(dwarf::DW_LNS_advance_pc);
75409467b48Spatrick encodeULEB128(AddrDelta, OS);
75509467b48Spatrick
75609467b48Spatrick if (NeedCopy)
75709467b48Spatrick OS << char(dwarf::DW_LNS_copy);
75809467b48Spatrick else {
75909467b48Spatrick assert(Temp <= 255 && "Buggy special opcode encoding.");
76009467b48Spatrick OS << char(Temp);
76109467b48Spatrick }
76209467b48Spatrick }
76309467b48Spatrick
76409467b48Spatrick // Utility function to write a tuple for .debug_abbrev.
EmitAbbrev(MCStreamer * MCOS,uint64_t Name,uint64_t Form)76509467b48Spatrick static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {
766097a140dSpatrick MCOS->emitULEB128IntValue(Name);
767097a140dSpatrick MCOS->emitULEB128IntValue(Form);
76809467b48Spatrick }
76909467b48Spatrick
77009467b48Spatrick // When generating dwarf for assembly source files this emits
77109467b48Spatrick // the data for .debug_abbrev section which contains three DIEs.
EmitGenDwarfAbbrev(MCStreamer * MCOS)77209467b48Spatrick static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {
77309467b48Spatrick MCContext &context = MCOS->getContext();
774*d415bd75Srobert MCOS->switchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
77509467b48Spatrick
77609467b48Spatrick // DW_TAG_compile_unit DIE abbrev (1).
777097a140dSpatrick MCOS->emitULEB128IntValue(1);
778097a140dSpatrick MCOS->emitULEB128IntValue(dwarf::DW_TAG_compile_unit);
779097a140dSpatrick MCOS->emitInt8(dwarf::DW_CHILDREN_yes);
780097a140dSpatrick dwarf::Form SecOffsetForm =
781097a140dSpatrick context.getDwarfVersion() >= 4
78209467b48Spatrick ? dwarf::DW_FORM_sec_offset
783097a140dSpatrick : (context.getDwarfFormat() == dwarf::DWARF64 ? dwarf::DW_FORM_data8
78409467b48Spatrick : dwarf::DW_FORM_data4);
785097a140dSpatrick EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, SecOffsetForm);
78609467b48Spatrick if (context.getGenDwarfSectionSyms().size() > 1 &&
78709467b48Spatrick context.getDwarfVersion() >= 3) {
788097a140dSpatrick EmitAbbrev(MCOS, dwarf::DW_AT_ranges, SecOffsetForm);
78909467b48Spatrick } else {
79009467b48Spatrick EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
79109467b48Spatrick EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);
79209467b48Spatrick }
79309467b48Spatrick EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
79409467b48Spatrick if (!context.getCompilationDir().empty())
79509467b48Spatrick EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string);
79609467b48Spatrick StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
79709467b48Spatrick if (!DwarfDebugFlags.empty())
79809467b48Spatrick EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string);
79909467b48Spatrick EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string);
80009467b48Spatrick EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2);
80109467b48Spatrick EmitAbbrev(MCOS, 0, 0);
80209467b48Spatrick
80309467b48Spatrick // DW_TAG_label DIE abbrev (2).
804097a140dSpatrick MCOS->emitULEB128IntValue(2);
805097a140dSpatrick MCOS->emitULEB128IntValue(dwarf::DW_TAG_label);
806097a140dSpatrick MCOS->emitInt8(dwarf::DW_CHILDREN_no);
80709467b48Spatrick EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
80809467b48Spatrick EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4);
80909467b48Spatrick EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4);
81009467b48Spatrick EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
81109467b48Spatrick EmitAbbrev(MCOS, 0, 0);
81209467b48Spatrick
81309467b48Spatrick // Terminate the abbreviations for this compilation unit.
814097a140dSpatrick MCOS->emitInt8(0);
81509467b48Spatrick }
81609467b48Spatrick
81709467b48Spatrick // When generating dwarf for assembly source files this emits the data for
81809467b48Spatrick // .debug_aranges section. This section contains a header and a table of pairs
81909467b48Spatrick // of PointerSize'ed values for the address and size of section(s) with line
82009467b48Spatrick // table entries.
EmitGenDwarfAranges(MCStreamer * MCOS,const MCSymbol * InfoSectionSymbol)82109467b48Spatrick static void EmitGenDwarfAranges(MCStreamer *MCOS,
82209467b48Spatrick const MCSymbol *InfoSectionSymbol) {
82309467b48Spatrick MCContext &context = MCOS->getContext();
82409467b48Spatrick
82509467b48Spatrick auto &Sections = context.getGenDwarfSectionSyms();
82609467b48Spatrick
827*d415bd75Srobert MCOS->switchSection(context.getObjectFileInfo()->getDwarfARangesSection());
82809467b48Spatrick
829097a140dSpatrick unsigned UnitLengthBytes =
830097a140dSpatrick dwarf::getUnitLengthFieldByteSize(context.getDwarfFormat());
831097a140dSpatrick unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());
832097a140dSpatrick
83309467b48Spatrick // This will be the length of the .debug_aranges section, first account for
83409467b48Spatrick // the size of each item in the header (see below where we emit these items).
835097a140dSpatrick int Length = UnitLengthBytes + 2 + OffsetSize + 1 + 1;
83609467b48Spatrick
83709467b48Spatrick // Figure the padding after the header before the table of address and size
83809467b48Spatrick // pairs who's values are PointerSize'ed.
83909467b48Spatrick const MCAsmInfo *asmInfo = context.getAsmInfo();
84009467b48Spatrick int AddrSize = asmInfo->getCodePointerSize();
84109467b48Spatrick int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1));
84209467b48Spatrick if (Pad == 2 * AddrSize)
84309467b48Spatrick Pad = 0;
84409467b48Spatrick Length += Pad;
84509467b48Spatrick
84609467b48Spatrick // Add the size of the pair of PointerSize'ed values for the address and size
84709467b48Spatrick // of each section we have in the table.
84809467b48Spatrick Length += 2 * AddrSize * Sections.size();
84909467b48Spatrick // And the pair of terminating zeros.
85009467b48Spatrick Length += 2 * AddrSize;
85109467b48Spatrick
85209467b48Spatrick // Emit the header for this section.
853097a140dSpatrick if (context.getDwarfFormat() == dwarf::DWARF64)
854097a140dSpatrick // The DWARF64 mark.
855097a140dSpatrick MCOS->emitInt32(dwarf::DW_LENGTH_DWARF64);
856097a140dSpatrick // The 4 (8 for DWARF64) byte length not including the length of the unit
857097a140dSpatrick // length field itself.
858097a140dSpatrick MCOS->emitIntValue(Length - UnitLengthBytes, OffsetSize);
85909467b48Spatrick // The 2 byte version, which is 2.
860097a140dSpatrick MCOS->emitInt16(2);
861097a140dSpatrick // The 4 (8 for DWARF64) byte offset to the compile unit in the .debug_info
862097a140dSpatrick // from the start of the .debug_info.
86309467b48Spatrick if (InfoSectionSymbol)
864097a140dSpatrick MCOS->emitSymbolValue(InfoSectionSymbol, OffsetSize,
86509467b48Spatrick asmInfo->needsDwarfSectionOffsetDirective());
86609467b48Spatrick else
867097a140dSpatrick MCOS->emitIntValue(0, OffsetSize);
86809467b48Spatrick // The 1 byte size of an address.
869097a140dSpatrick MCOS->emitInt8(AddrSize);
87009467b48Spatrick // The 1 byte size of a segment descriptor, we use a value of zero.
871097a140dSpatrick MCOS->emitInt8(0);
87209467b48Spatrick // Align the header with the padding if needed, before we put out the table.
87309467b48Spatrick for(int i = 0; i < Pad; i++)
874097a140dSpatrick MCOS->emitInt8(0);
87509467b48Spatrick
87609467b48Spatrick // Now emit the table of pairs of PointerSize'ed values for the section
87709467b48Spatrick // addresses and sizes.
87809467b48Spatrick for (MCSection *Sec : Sections) {
87909467b48Spatrick const MCSymbol *StartSymbol = Sec->getBeginSymbol();
88009467b48Spatrick MCSymbol *EndSymbol = Sec->getEndSymbol(context);
88109467b48Spatrick assert(StartSymbol && "StartSymbol must not be NULL");
88209467b48Spatrick assert(EndSymbol && "EndSymbol must not be NULL");
88309467b48Spatrick
88409467b48Spatrick const MCExpr *Addr = MCSymbolRefExpr::create(
88509467b48Spatrick StartSymbol, MCSymbolRefExpr::VK_None, context);
886097a140dSpatrick const MCExpr *Size =
887097a140dSpatrick makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);
888097a140dSpatrick MCOS->emitValue(Addr, AddrSize);
88909467b48Spatrick emitAbsValue(*MCOS, Size, AddrSize);
89009467b48Spatrick }
89109467b48Spatrick
89209467b48Spatrick // And finally the pair of terminating zeros.
893097a140dSpatrick MCOS->emitIntValue(0, AddrSize);
894097a140dSpatrick MCOS->emitIntValue(0, AddrSize);
89509467b48Spatrick }
89609467b48Spatrick
89709467b48Spatrick // When generating dwarf for assembly source files this emits the data for
89809467b48Spatrick // .debug_info section which contains three parts. The header, the compile_unit
89909467b48Spatrick // DIE and a list of label DIEs.
EmitGenDwarfInfo(MCStreamer * MCOS,const MCSymbol * AbbrevSectionSymbol,const MCSymbol * LineSectionSymbol,const MCSymbol * RangesSymbol)90009467b48Spatrick static void EmitGenDwarfInfo(MCStreamer *MCOS,
90109467b48Spatrick const MCSymbol *AbbrevSectionSymbol,
90209467b48Spatrick const MCSymbol *LineSectionSymbol,
903097a140dSpatrick const MCSymbol *RangesSymbol) {
90409467b48Spatrick MCContext &context = MCOS->getContext();
90509467b48Spatrick
906*d415bd75Srobert MCOS->switchSection(context.getObjectFileInfo()->getDwarfInfoSection());
90709467b48Spatrick
90809467b48Spatrick // Create a symbol at the start and end of this section used in here for the
90909467b48Spatrick // expression to calculate the length in the header.
91009467b48Spatrick MCSymbol *InfoStart = context.createTempSymbol();
911097a140dSpatrick MCOS->emitLabel(InfoStart);
91209467b48Spatrick MCSymbol *InfoEnd = context.createTempSymbol();
91309467b48Spatrick
91409467b48Spatrick // First part: the header.
91509467b48Spatrick
916097a140dSpatrick unsigned UnitLengthBytes =
917097a140dSpatrick dwarf::getUnitLengthFieldByteSize(context.getDwarfFormat());
918097a140dSpatrick unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());
919097a140dSpatrick
920097a140dSpatrick if (context.getDwarfFormat() == dwarf::DWARF64)
921097a140dSpatrick // Emit DWARF64 mark.
922097a140dSpatrick MCOS->emitInt32(dwarf::DW_LENGTH_DWARF64);
923097a140dSpatrick
924097a140dSpatrick // The 4 (8 for DWARF64) byte total length of the information for this
925097a140dSpatrick // compilation unit, not including the unit length field itself.
926097a140dSpatrick const MCExpr *Length =
927097a140dSpatrick makeEndMinusStartExpr(context, *InfoStart, *InfoEnd, UnitLengthBytes);
928097a140dSpatrick emitAbsValue(*MCOS, Length, OffsetSize);
92909467b48Spatrick
93009467b48Spatrick // The 2 byte DWARF version.
931097a140dSpatrick MCOS->emitInt16(context.getDwarfVersion());
93209467b48Spatrick
93309467b48Spatrick // The DWARF v5 header has unit type, address size, abbrev offset.
93409467b48Spatrick // Earlier versions have abbrev offset, address size.
93509467b48Spatrick const MCAsmInfo &AsmInfo = *context.getAsmInfo();
93609467b48Spatrick int AddrSize = AsmInfo.getCodePointerSize();
93709467b48Spatrick if (context.getDwarfVersion() >= 5) {
938097a140dSpatrick MCOS->emitInt8(dwarf::DW_UT_compile);
939097a140dSpatrick MCOS->emitInt8(AddrSize);
94009467b48Spatrick }
941097a140dSpatrick // The 4 (8 for DWARF64) byte offset to the debug abbrevs from the start of
942097a140dSpatrick // the .debug_abbrev.
943097a140dSpatrick if (AbbrevSectionSymbol)
944097a140dSpatrick MCOS->emitSymbolValue(AbbrevSectionSymbol, OffsetSize,
94509467b48Spatrick AsmInfo.needsDwarfSectionOffsetDirective());
946097a140dSpatrick else
947097a140dSpatrick // Since the abbrevs are at the start of the section, the offset is zero.
948097a140dSpatrick MCOS->emitIntValue(0, OffsetSize);
94909467b48Spatrick if (context.getDwarfVersion() <= 4)
950097a140dSpatrick MCOS->emitInt8(AddrSize);
95109467b48Spatrick
95209467b48Spatrick // Second part: the compile_unit DIE.
95309467b48Spatrick
95409467b48Spatrick // The DW_TAG_compile_unit DIE abbrev (1).
955097a140dSpatrick MCOS->emitULEB128IntValue(1);
95609467b48Spatrick
957097a140dSpatrick // DW_AT_stmt_list, a 4 (8 for DWARF64) byte offset from the start of the
958097a140dSpatrick // .debug_line section.
95909467b48Spatrick if (LineSectionSymbol)
960097a140dSpatrick MCOS->emitSymbolValue(LineSectionSymbol, OffsetSize,
96109467b48Spatrick AsmInfo.needsDwarfSectionOffsetDirective());
96209467b48Spatrick else
963097a140dSpatrick // The line table is at the start of the section, so the offset is zero.
964097a140dSpatrick MCOS->emitIntValue(0, OffsetSize);
96509467b48Spatrick
966097a140dSpatrick if (RangesSymbol) {
967097a140dSpatrick // There are multiple sections containing code, so we must use
968097a140dSpatrick // .debug_ranges/.debug_rnglists. AT_ranges, the 4/8 byte offset from the
969097a140dSpatrick // start of the .debug_ranges/.debug_rnglists.
970097a140dSpatrick MCOS->emitSymbolValue(RangesSymbol, OffsetSize);
97109467b48Spatrick } else {
97209467b48Spatrick // If we only have one non-empty code section, we can use the simpler
97309467b48Spatrick // AT_low_pc and AT_high_pc attributes.
97409467b48Spatrick
97509467b48Spatrick // Find the first (and only) non-empty text section
97609467b48Spatrick auto &Sections = context.getGenDwarfSectionSyms();
97709467b48Spatrick const auto TextSection = Sections.begin();
97809467b48Spatrick assert(TextSection != Sections.end() && "No text section found");
97909467b48Spatrick
98009467b48Spatrick MCSymbol *StartSymbol = (*TextSection)->getBeginSymbol();
98109467b48Spatrick MCSymbol *EndSymbol = (*TextSection)->getEndSymbol(context);
98209467b48Spatrick assert(StartSymbol && "StartSymbol must not be NULL");
98309467b48Spatrick assert(EndSymbol && "EndSymbol must not be NULL");
98409467b48Spatrick
98509467b48Spatrick // AT_low_pc, the first address of the default .text section.
98609467b48Spatrick const MCExpr *Start = MCSymbolRefExpr::create(
98709467b48Spatrick StartSymbol, MCSymbolRefExpr::VK_None, context);
988097a140dSpatrick MCOS->emitValue(Start, AddrSize);
98909467b48Spatrick
99009467b48Spatrick // AT_high_pc, the last address of the default .text section.
99109467b48Spatrick const MCExpr *End = MCSymbolRefExpr::create(
99209467b48Spatrick EndSymbol, MCSymbolRefExpr::VK_None, context);
993097a140dSpatrick MCOS->emitValue(End, AddrSize);
99409467b48Spatrick }
99509467b48Spatrick
99609467b48Spatrick // AT_name, the name of the source file. Reconstruct from the first directory
99709467b48Spatrick // and file table entries.
99809467b48Spatrick const SmallVectorImpl<std::string> &MCDwarfDirs = context.getMCDwarfDirs();
99909467b48Spatrick if (MCDwarfDirs.size() > 0) {
1000097a140dSpatrick MCOS->emitBytes(MCDwarfDirs[0]);
1001097a140dSpatrick MCOS->emitBytes(sys::path::get_separator());
100209467b48Spatrick }
100309467b48Spatrick const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles = context.getMCDwarfFiles();
100409467b48Spatrick // MCDwarfFiles might be empty if we have an empty source file.
100509467b48Spatrick // If it's not empty, [0] is unused and [1] is the first actual file.
100609467b48Spatrick assert(MCDwarfFiles.empty() || MCDwarfFiles.size() >= 2);
100709467b48Spatrick const MCDwarfFile &RootFile =
100809467b48Spatrick MCDwarfFiles.empty()
100909467b48Spatrick ? context.getMCDwarfLineTable(/*CUID=*/0).getRootFile()
101009467b48Spatrick : MCDwarfFiles[1];
1011097a140dSpatrick MCOS->emitBytes(RootFile.Name);
1012097a140dSpatrick MCOS->emitInt8(0); // NULL byte to terminate the string.
101309467b48Spatrick
101409467b48Spatrick // AT_comp_dir, the working directory the assembly was done in.
101509467b48Spatrick if (!context.getCompilationDir().empty()) {
1016097a140dSpatrick MCOS->emitBytes(context.getCompilationDir());
1017097a140dSpatrick MCOS->emitInt8(0); // NULL byte to terminate the string.
101809467b48Spatrick }
101909467b48Spatrick
102009467b48Spatrick // AT_APPLE_flags, the command line arguments of the assembler tool.
102109467b48Spatrick StringRef DwarfDebugFlags = context.getDwarfDebugFlags();
102209467b48Spatrick if (!DwarfDebugFlags.empty()){
1023097a140dSpatrick MCOS->emitBytes(DwarfDebugFlags);
1024097a140dSpatrick MCOS->emitInt8(0); // NULL byte to terminate the string.
102509467b48Spatrick }
102609467b48Spatrick
102709467b48Spatrick // AT_producer, the version of the assembler tool.
102809467b48Spatrick StringRef DwarfDebugProducer = context.getDwarfDebugProducer();
102909467b48Spatrick if (!DwarfDebugProducer.empty())
1030097a140dSpatrick MCOS->emitBytes(DwarfDebugProducer);
103109467b48Spatrick else
1032097a140dSpatrick MCOS->emitBytes(StringRef("llvm-mc (based on LLVM " PACKAGE_VERSION ")"));
1033097a140dSpatrick MCOS->emitInt8(0); // NULL byte to terminate the string.
103409467b48Spatrick
103509467b48Spatrick // AT_language, a 4 byte value. We use DW_LANG_Mips_Assembler as the dwarf2
103609467b48Spatrick // draft has no standard code for assembler.
1037097a140dSpatrick MCOS->emitInt16(dwarf::DW_LANG_Mips_Assembler);
103809467b48Spatrick
103909467b48Spatrick // Third part: the list of label DIEs.
104009467b48Spatrick
104109467b48Spatrick // Loop on saved info for dwarf labels and create the DIEs for them.
104209467b48Spatrick const std::vector<MCGenDwarfLabelEntry> &Entries =
104309467b48Spatrick MCOS->getContext().getMCGenDwarfLabelEntries();
104409467b48Spatrick for (const auto &Entry : Entries) {
104509467b48Spatrick // The DW_TAG_label DIE abbrev (2).
1046097a140dSpatrick MCOS->emitULEB128IntValue(2);
104709467b48Spatrick
104809467b48Spatrick // AT_name, of the label without any leading underbar.
1049097a140dSpatrick MCOS->emitBytes(Entry.getName());
1050097a140dSpatrick MCOS->emitInt8(0); // NULL byte to terminate the string.
105109467b48Spatrick
105209467b48Spatrick // AT_decl_file, index into the file table.
1053097a140dSpatrick MCOS->emitInt32(Entry.getFileNumber());
105409467b48Spatrick
105509467b48Spatrick // AT_decl_line, source line number.
1056097a140dSpatrick MCOS->emitInt32(Entry.getLineNumber());
105709467b48Spatrick
105809467b48Spatrick // AT_low_pc, start address of the label.
105909467b48Spatrick const MCExpr *AT_low_pc = MCSymbolRefExpr::create(Entry.getLabel(),
106009467b48Spatrick MCSymbolRefExpr::VK_None, context);
1061097a140dSpatrick MCOS->emitValue(AT_low_pc, AddrSize);
106209467b48Spatrick }
106309467b48Spatrick
106409467b48Spatrick // Add the NULL DIE terminating the Compile Unit DIE's.
1065097a140dSpatrick MCOS->emitInt8(0);
106609467b48Spatrick
106709467b48Spatrick // Now set the value of the symbol at the end of the info section.
1068097a140dSpatrick MCOS->emitLabel(InfoEnd);
106909467b48Spatrick }
107009467b48Spatrick
107109467b48Spatrick // When generating dwarf for assembly source files this emits the data for
107209467b48Spatrick // .debug_ranges section. We only emit one range list, which spans all of the
107309467b48Spatrick // executable sections of this file.
emitGenDwarfRanges(MCStreamer * MCOS)1074097a140dSpatrick static MCSymbol *emitGenDwarfRanges(MCStreamer *MCOS) {
107509467b48Spatrick MCContext &context = MCOS->getContext();
107609467b48Spatrick auto &Sections = context.getGenDwarfSectionSyms();
107709467b48Spatrick
107809467b48Spatrick const MCAsmInfo *AsmInfo = context.getAsmInfo();
107909467b48Spatrick int AddrSize = AsmInfo->getCodePointerSize();
1080097a140dSpatrick MCSymbol *RangesSymbol;
108109467b48Spatrick
1082097a140dSpatrick if (MCOS->getContext().getDwarfVersion() >= 5) {
1083*d415bd75Srobert MCOS->switchSection(context.getObjectFileInfo()->getDwarfRnglistsSection());
1084097a140dSpatrick MCSymbol *EndSymbol = mcdwarf::emitListsTableHeaderStart(*MCOS);
1085097a140dSpatrick MCOS->AddComment("Offset entry count");
1086097a140dSpatrick MCOS->emitInt32(0);
108773471bf0Spatrick RangesSymbol = context.createTempSymbol("debug_rnglist0_start");
1088097a140dSpatrick MCOS->emitLabel(RangesSymbol);
108909467b48Spatrick for (MCSection *Sec : Sections) {
109009467b48Spatrick const MCSymbol *StartSymbol = Sec->getBeginSymbol();
1091097a140dSpatrick const MCSymbol *EndSymbol = Sec->getEndSymbol(context);
1092097a140dSpatrick const MCExpr *SectionStartAddr = MCSymbolRefExpr::create(
1093097a140dSpatrick StartSymbol, MCSymbolRefExpr::VK_None, context);
1094097a140dSpatrick const MCExpr *SectionSize =
1095097a140dSpatrick makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);
1096097a140dSpatrick MCOS->emitInt8(dwarf::DW_RLE_start_length);
1097097a140dSpatrick MCOS->emitValue(SectionStartAddr, AddrSize);
1098097a140dSpatrick MCOS->emitULEB128Value(SectionSize);
1099097a140dSpatrick }
1100097a140dSpatrick MCOS->emitInt8(dwarf::DW_RLE_end_of_list);
1101097a140dSpatrick MCOS->emitLabel(EndSymbol);
1102097a140dSpatrick } else {
1103*d415bd75Srobert MCOS->switchSection(context.getObjectFileInfo()->getDwarfRangesSection());
110473471bf0Spatrick RangesSymbol = context.createTempSymbol("debug_ranges_start");
1105097a140dSpatrick MCOS->emitLabel(RangesSymbol);
1106097a140dSpatrick for (MCSection *Sec : Sections) {
1107097a140dSpatrick const MCSymbol *StartSymbol = Sec->getBeginSymbol();
1108097a140dSpatrick const MCSymbol *EndSymbol = Sec->getEndSymbol(context);
110909467b48Spatrick
1110097a140dSpatrick // Emit a base address selection entry for the section start.
111109467b48Spatrick const MCExpr *SectionStartAddr = MCSymbolRefExpr::create(
111209467b48Spatrick StartSymbol, MCSymbolRefExpr::VK_None, context);
111309467b48Spatrick MCOS->emitFill(AddrSize, 0xFF);
1114097a140dSpatrick MCOS->emitValue(SectionStartAddr, AddrSize);
111509467b48Spatrick
1116097a140dSpatrick // Emit a range list entry spanning this section.
1117097a140dSpatrick const MCExpr *SectionSize =
1118097a140dSpatrick makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);
1119097a140dSpatrick MCOS->emitIntValue(0, AddrSize);
112009467b48Spatrick emitAbsValue(*MCOS, SectionSize, AddrSize);
112109467b48Spatrick }
112209467b48Spatrick
112309467b48Spatrick // Emit end of list entry
1124097a140dSpatrick MCOS->emitIntValue(0, AddrSize);
1125097a140dSpatrick MCOS->emitIntValue(0, AddrSize);
1126097a140dSpatrick }
1127097a140dSpatrick
1128097a140dSpatrick return RangesSymbol;
112909467b48Spatrick }
113009467b48Spatrick
113109467b48Spatrick //
113209467b48Spatrick // When generating dwarf for assembly source files this emits the Dwarf
113309467b48Spatrick // sections.
113409467b48Spatrick //
Emit(MCStreamer * MCOS)113509467b48Spatrick void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {
113609467b48Spatrick MCContext &context = MCOS->getContext();
113709467b48Spatrick
113809467b48Spatrick // Create the dwarf sections in this order (.debug_line already created).
113909467b48Spatrick const MCAsmInfo *AsmInfo = context.getAsmInfo();
114009467b48Spatrick bool CreateDwarfSectionSymbols =
114109467b48Spatrick AsmInfo->doesDwarfUseRelocationsAcrossSections();
114209467b48Spatrick MCSymbol *LineSectionSymbol = nullptr;
114309467b48Spatrick if (CreateDwarfSectionSymbols)
114409467b48Spatrick LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0);
114509467b48Spatrick MCSymbol *AbbrevSectionSymbol = nullptr;
114609467b48Spatrick MCSymbol *InfoSectionSymbol = nullptr;
1147097a140dSpatrick MCSymbol *RangesSymbol = nullptr;
114809467b48Spatrick
114909467b48Spatrick // Create end symbols for each section, and remove empty sections
115009467b48Spatrick MCOS->getContext().finalizeDwarfSections(*MCOS);
115109467b48Spatrick
115209467b48Spatrick // If there are no sections to generate debug info for, we don't need
115309467b48Spatrick // to do anything
115409467b48Spatrick if (MCOS->getContext().getGenDwarfSectionSyms().empty())
115509467b48Spatrick return;
115609467b48Spatrick
115709467b48Spatrick // We only use the .debug_ranges section if we have multiple code sections,
115809467b48Spatrick // and we are emitting a DWARF version which supports it.
115909467b48Spatrick const bool UseRangesSection =
116009467b48Spatrick MCOS->getContext().getGenDwarfSectionSyms().size() > 1 &&
116109467b48Spatrick MCOS->getContext().getDwarfVersion() >= 3;
116209467b48Spatrick CreateDwarfSectionSymbols |= UseRangesSection;
116309467b48Spatrick
1164*d415bd75Srobert MCOS->switchSection(context.getObjectFileInfo()->getDwarfInfoSection());
116509467b48Spatrick if (CreateDwarfSectionSymbols) {
116609467b48Spatrick InfoSectionSymbol = context.createTempSymbol();
1167097a140dSpatrick MCOS->emitLabel(InfoSectionSymbol);
116809467b48Spatrick }
1169*d415bd75Srobert MCOS->switchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
117009467b48Spatrick if (CreateDwarfSectionSymbols) {
117109467b48Spatrick AbbrevSectionSymbol = context.createTempSymbol();
1172097a140dSpatrick MCOS->emitLabel(AbbrevSectionSymbol);
117309467b48Spatrick }
117409467b48Spatrick
1175*d415bd75Srobert MCOS->switchSection(context.getObjectFileInfo()->getDwarfARangesSection());
117609467b48Spatrick
117709467b48Spatrick // Output the data for .debug_aranges section.
117809467b48Spatrick EmitGenDwarfAranges(MCOS, InfoSectionSymbol);
117909467b48Spatrick
1180097a140dSpatrick if (UseRangesSection) {
1181097a140dSpatrick RangesSymbol = emitGenDwarfRanges(MCOS);
1182097a140dSpatrick assert(RangesSymbol);
1183097a140dSpatrick }
118409467b48Spatrick
118509467b48Spatrick // Output the data for .debug_abbrev section.
118609467b48Spatrick EmitGenDwarfAbbrev(MCOS);
118709467b48Spatrick
118809467b48Spatrick // Output the data for .debug_info section.
1189097a140dSpatrick EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, RangesSymbol);
119009467b48Spatrick }
119109467b48Spatrick
119209467b48Spatrick //
119309467b48Spatrick // When generating dwarf for assembly source files this is called when symbol
119409467b48Spatrick // for a label is created. If this symbol is not a temporary and is in the
119509467b48Spatrick // section that dwarf is being generated for, save the needed info to create
119609467b48Spatrick // a dwarf label.
119709467b48Spatrick //
Make(MCSymbol * Symbol,MCStreamer * MCOS,SourceMgr & SrcMgr,SMLoc & Loc)119809467b48Spatrick void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,
119909467b48Spatrick SourceMgr &SrcMgr, SMLoc &Loc) {
120009467b48Spatrick // We won't create dwarf labels for temporary symbols.
120109467b48Spatrick if (Symbol->isTemporary())
120209467b48Spatrick return;
120309467b48Spatrick MCContext &context = MCOS->getContext();
120409467b48Spatrick // We won't create dwarf labels for symbols in sections that we are not
120509467b48Spatrick // generating debug info for.
120609467b48Spatrick if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSectionOnly()))
120709467b48Spatrick return;
120809467b48Spatrick
120909467b48Spatrick // The dwarf label's name does not have the symbol name's leading
121009467b48Spatrick // underbar if any.
121109467b48Spatrick StringRef Name = Symbol->getName();
121209467b48Spatrick if (Name.startswith("_"))
121309467b48Spatrick Name = Name.substr(1, Name.size()-1);
121409467b48Spatrick
121509467b48Spatrick // Get the dwarf file number to be used for the dwarf label.
121609467b48Spatrick unsigned FileNumber = context.getGenDwarfFileNumber();
121709467b48Spatrick
121809467b48Spatrick // Finding the line number is the expensive part which is why we just don't
121909467b48Spatrick // pass it in as for some symbols we won't create a dwarf label.
122009467b48Spatrick unsigned CurBuffer = SrcMgr.FindBufferContainingLoc(Loc);
122109467b48Spatrick unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer);
122209467b48Spatrick
122309467b48Spatrick // We create a temporary symbol for use for the AT_high_pc and AT_low_pc
122409467b48Spatrick // values so that they don't have things like an ARM thumb bit from the
122509467b48Spatrick // original symbol. So when used they won't get a low bit set after
122609467b48Spatrick // relocation.
122709467b48Spatrick MCSymbol *Label = context.createTempSymbol();
1228097a140dSpatrick MCOS->emitLabel(Label);
122909467b48Spatrick
123009467b48Spatrick // Create and entry for the info and add it to the other entries.
123109467b48Spatrick MCOS->getContext().addMCGenDwarfLabelEntry(
123209467b48Spatrick MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label));
123309467b48Spatrick }
123409467b48Spatrick
getDataAlignmentFactor(MCStreamer & streamer)123509467b48Spatrick static int getDataAlignmentFactor(MCStreamer &streamer) {
123609467b48Spatrick MCContext &context = streamer.getContext();
123709467b48Spatrick const MCAsmInfo *asmInfo = context.getAsmInfo();
123809467b48Spatrick int size = asmInfo->getCalleeSaveStackSlotSize();
123909467b48Spatrick if (asmInfo->isStackGrowthDirectionUp())
124009467b48Spatrick return size;
124109467b48Spatrick else
124209467b48Spatrick return -size;
124309467b48Spatrick }
124409467b48Spatrick
getSizeForEncoding(MCStreamer & streamer,unsigned symbolEncoding)124509467b48Spatrick static unsigned getSizeForEncoding(MCStreamer &streamer,
124609467b48Spatrick unsigned symbolEncoding) {
124709467b48Spatrick MCContext &context = streamer.getContext();
124809467b48Spatrick unsigned format = symbolEncoding & 0x0f;
124909467b48Spatrick switch (format) {
125009467b48Spatrick default: llvm_unreachable("Unknown Encoding");
125109467b48Spatrick case dwarf::DW_EH_PE_absptr:
125209467b48Spatrick case dwarf::DW_EH_PE_signed:
125309467b48Spatrick return context.getAsmInfo()->getCodePointerSize();
125409467b48Spatrick case dwarf::DW_EH_PE_udata2:
125509467b48Spatrick case dwarf::DW_EH_PE_sdata2:
125609467b48Spatrick return 2;
125709467b48Spatrick case dwarf::DW_EH_PE_udata4:
125809467b48Spatrick case dwarf::DW_EH_PE_sdata4:
125909467b48Spatrick return 4;
126009467b48Spatrick case dwarf::DW_EH_PE_udata8:
126109467b48Spatrick case dwarf::DW_EH_PE_sdata8:
126209467b48Spatrick return 8;
126309467b48Spatrick }
126409467b48Spatrick }
126509467b48Spatrick
emitFDESymbol(MCObjectStreamer & streamer,const MCSymbol & symbol,unsigned symbolEncoding,bool isEH)126609467b48Spatrick static void emitFDESymbol(MCObjectStreamer &streamer, const MCSymbol &symbol,
126709467b48Spatrick unsigned symbolEncoding, bool isEH) {
126809467b48Spatrick MCContext &context = streamer.getContext();
126909467b48Spatrick const MCAsmInfo *asmInfo = context.getAsmInfo();
127009467b48Spatrick const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol,
127109467b48Spatrick symbolEncoding,
127209467b48Spatrick streamer);
127309467b48Spatrick unsigned size = getSizeForEncoding(streamer, symbolEncoding);
127409467b48Spatrick if (asmInfo->doDwarfFDESymbolsUseAbsDiff() && isEH)
127509467b48Spatrick emitAbsValue(streamer, v, size);
127609467b48Spatrick else
1277097a140dSpatrick streamer.emitValue(v, size);
127809467b48Spatrick }
127909467b48Spatrick
EmitPersonality(MCStreamer & streamer,const MCSymbol & symbol,unsigned symbolEncoding)128009467b48Spatrick static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,
128109467b48Spatrick unsigned symbolEncoding) {
128209467b48Spatrick MCContext &context = streamer.getContext();
128309467b48Spatrick const MCAsmInfo *asmInfo = context.getAsmInfo();
128409467b48Spatrick const MCExpr *v = asmInfo->getExprForPersonalitySymbol(&symbol,
128509467b48Spatrick symbolEncoding,
128609467b48Spatrick streamer);
128709467b48Spatrick unsigned size = getSizeForEncoding(streamer, symbolEncoding);
1288097a140dSpatrick streamer.emitValue(v, size);
128909467b48Spatrick }
129009467b48Spatrick
129109467b48Spatrick namespace {
129209467b48Spatrick
129309467b48Spatrick class FrameEmitterImpl {
129409467b48Spatrick int CFAOffset = 0;
129509467b48Spatrick int InitialCFAOffset = 0;
129609467b48Spatrick bool IsEH;
129709467b48Spatrick MCObjectStreamer &Streamer;
129809467b48Spatrick
129909467b48Spatrick public:
FrameEmitterImpl(bool IsEH,MCObjectStreamer & Streamer)130009467b48Spatrick FrameEmitterImpl(bool IsEH, MCObjectStreamer &Streamer)
130109467b48Spatrick : IsEH(IsEH), Streamer(Streamer) {}
130209467b48Spatrick
130309467b48Spatrick /// Emit the unwind information in a compact way.
130409467b48Spatrick void EmitCompactUnwind(const MCDwarfFrameInfo &frame);
130509467b48Spatrick
130609467b48Spatrick const MCSymbol &EmitCIE(const MCDwarfFrameInfo &F);
130709467b48Spatrick void EmitFDE(const MCSymbol &cieStart, const MCDwarfFrameInfo &frame,
130809467b48Spatrick bool LastInSection, const MCSymbol &SectionStart);
1309097a140dSpatrick void emitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
131009467b48Spatrick MCSymbol *BaseLabel);
1311097a140dSpatrick void emitCFIInstruction(const MCCFIInstruction &Instr);
131209467b48Spatrick };
131309467b48Spatrick
131409467b48Spatrick } // end anonymous namespace
131509467b48Spatrick
emitEncodingByte(MCObjectStreamer & Streamer,unsigned Encoding)131609467b48Spatrick static void emitEncodingByte(MCObjectStreamer &Streamer, unsigned Encoding) {
1317097a140dSpatrick Streamer.emitInt8(Encoding);
131809467b48Spatrick }
131909467b48Spatrick
emitCFIInstruction(const MCCFIInstruction & Instr)1320097a140dSpatrick void FrameEmitterImpl::emitCFIInstruction(const MCCFIInstruction &Instr) {
132109467b48Spatrick int dataAlignmentFactor = getDataAlignmentFactor(Streamer);
132209467b48Spatrick auto *MRI = Streamer.getContext().getRegisterInfo();
132309467b48Spatrick
132409467b48Spatrick switch (Instr.getOperation()) {
132509467b48Spatrick case MCCFIInstruction::OpRegister: {
132609467b48Spatrick unsigned Reg1 = Instr.getRegister();
132709467b48Spatrick unsigned Reg2 = Instr.getRegister2();
132809467b48Spatrick if (!IsEH) {
132909467b48Spatrick Reg1 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg1);
133009467b48Spatrick Reg2 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg2);
133109467b48Spatrick }
1332097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_register);
1333097a140dSpatrick Streamer.emitULEB128IntValue(Reg1);
1334097a140dSpatrick Streamer.emitULEB128IntValue(Reg2);
133509467b48Spatrick return;
133609467b48Spatrick }
133709467b48Spatrick case MCCFIInstruction::OpWindowSave:
1338097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_GNU_window_save);
133909467b48Spatrick return;
134009467b48Spatrick
134109467b48Spatrick case MCCFIInstruction::OpNegateRAState:
1342097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_AARCH64_negate_ra_state);
134309467b48Spatrick return;
134409467b48Spatrick
134509467b48Spatrick case MCCFIInstruction::OpUndefined: {
134609467b48Spatrick unsigned Reg = Instr.getRegister();
1347097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_undefined);
1348097a140dSpatrick Streamer.emitULEB128IntValue(Reg);
134909467b48Spatrick return;
135009467b48Spatrick }
135109467b48Spatrick case MCCFIInstruction::OpAdjustCfaOffset:
135209467b48Spatrick case MCCFIInstruction::OpDefCfaOffset: {
135309467b48Spatrick const bool IsRelative =
135409467b48Spatrick Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset;
135509467b48Spatrick
1356097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_def_cfa_offset);
135709467b48Spatrick
135809467b48Spatrick if (IsRelative)
135909467b48Spatrick CFAOffset += Instr.getOffset();
136009467b48Spatrick else
1361097a140dSpatrick CFAOffset = Instr.getOffset();
136209467b48Spatrick
1363097a140dSpatrick Streamer.emitULEB128IntValue(CFAOffset);
136409467b48Spatrick
136509467b48Spatrick return;
136609467b48Spatrick }
136709467b48Spatrick case MCCFIInstruction::OpDefCfa: {
136809467b48Spatrick unsigned Reg = Instr.getRegister();
136909467b48Spatrick if (!IsEH)
137009467b48Spatrick Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
1371097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_def_cfa);
1372097a140dSpatrick Streamer.emitULEB128IntValue(Reg);
1373097a140dSpatrick CFAOffset = Instr.getOffset();
1374097a140dSpatrick Streamer.emitULEB128IntValue(CFAOffset);
137509467b48Spatrick
137609467b48Spatrick return;
137709467b48Spatrick }
137809467b48Spatrick case MCCFIInstruction::OpDefCfaRegister: {
137909467b48Spatrick unsigned Reg = Instr.getRegister();
138009467b48Spatrick if (!IsEH)
138109467b48Spatrick Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
1382097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_def_cfa_register);
1383097a140dSpatrick Streamer.emitULEB128IntValue(Reg);
138409467b48Spatrick
138509467b48Spatrick return;
138609467b48Spatrick }
138773471bf0Spatrick // TODO: Implement `_sf` variants if/when they need to be emitted.
138873471bf0Spatrick case MCCFIInstruction::OpLLVMDefAspaceCfa: {
138973471bf0Spatrick unsigned Reg = Instr.getRegister();
139073471bf0Spatrick if (!IsEH)
139173471bf0Spatrick Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
139273471bf0Spatrick Streamer.emitIntValue(dwarf::DW_CFA_LLVM_def_aspace_cfa, 1);
139373471bf0Spatrick Streamer.emitULEB128IntValue(Reg);
139473471bf0Spatrick CFAOffset = Instr.getOffset();
139573471bf0Spatrick Streamer.emitULEB128IntValue(CFAOffset);
139673471bf0Spatrick Streamer.emitULEB128IntValue(Instr.getAddressSpace());
139773471bf0Spatrick
139873471bf0Spatrick return;
139973471bf0Spatrick }
140009467b48Spatrick case MCCFIInstruction::OpOffset:
140109467b48Spatrick case MCCFIInstruction::OpRelOffset: {
140209467b48Spatrick const bool IsRelative =
140309467b48Spatrick Instr.getOperation() == MCCFIInstruction::OpRelOffset;
140409467b48Spatrick
140509467b48Spatrick unsigned Reg = Instr.getRegister();
140609467b48Spatrick if (!IsEH)
140709467b48Spatrick Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
140809467b48Spatrick
140909467b48Spatrick int Offset = Instr.getOffset();
141009467b48Spatrick if (IsRelative)
141109467b48Spatrick Offset -= CFAOffset;
141209467b48Spatrick Offset = Offset / dataAlignmentFactor;
141309467b48Spatrick
141409467b48Spatrick if (Offset < 0) {
1415097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_offset_extended_sf);
1416097a140dSpatrick Streamer.emitULEB128IntValue(Reg);
1417097a140dSpatrick Streamer.emitSLEB128IntValue(Offset);
141809467b48Spatrick } else if (Reg < 64) {
1419097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_offset + Reg);
1420097a140dSpatrick Streamer.emitULEB128IntValue(Offset);
142109467b48Spatrick } else {
1422097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_offset_extended);
1423097a140dSpatrick Streamer.emitULEB128IntValue(Reg);
1424097a140dSpatrick Streamer.emitULEB128IntValue(Offset);
142509467b48Spatrick }
142609467b48Spatrick return;
142709467b48Spatrick }
142809467b48Spatrick case MCCFIInstruction::OpRememberState:
1429097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_remember_state);
143009467b48Spatrick return;
143109467b48Spatrick case MCCFIInstruction::OpRestoreState:
1432097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_restore_state);
143309467b48Spatrick return;
143409467b48Spatrick case MCCFIInstruction::OpSameValue: {
143509467b48Spatrick unsigned Reg = Instr.getRegister();
1436097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_same_value);
1437097a140dSpatrick Streamer.emitULEB128IntValue(Reg);
143809467b48Spatrick return;
143909467b48Spatrick }
144009467b48Spatrick case MCCFIInstruction::OpRestore: {
144109467b48Spatrick unsigned Reg = Instr.getRegister();
144209467b48Spatrick if (!IsEH)
144309467b48Spatrick Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
144409467b48Spatrick if (Reg < 64) {
1445097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_restore | Reg);
144609467b48Spatrick } else {
1447097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_restore_extended);
1448097a140dSpatrick Streamer.emitULEB128IntValue(Reg);
144909467b48Spatrick }
145009467b48Spatrick return;
145109467b48Spatrick }
145209467b48Spatrick case MCCFIInstruction::OpGnuArgsSize:
1453097a140dSpatrick Streamer.emitInt8(dwarf::DW_CFA_GNU_args_size);
1454097a140dSpatrick Streamer.emitULEB128IntValue(Instr.getOffset());
145509467b48Spatrick return;
145609467b48Spatrick
145709467b48Spatrick case MCCFIInstruction::OpEscape:
1458097a140dSpatrick Streamer.emitBytes(Instr.getValues());
145909467b48Spatrick return;
146009467b48Spatrick }
146109467b48Spatrick llvm_unreachable("Unhandled case in switch");
146209467b48Spatrick }
146309467b48Spatrick
146409467b48Spatrick /// Emit frame instructions to describe the layout of the frame.
emitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,MCSymbol * BaseLabel)1465097a140dSpatrick void FrameEmitterImpl::emitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,
146609467b48Spatrick MCSymbol *BaseLabel) {
146709467b48Spatrick for (const MCCFIInstruction &Instr : Instrs) {
146809467b48Spatrick MCSymbol *Label = Instr.getLabel();
146909467b48Spatrick // Throw out move if the label is invalid.
147009467b48Spatrick if (Label && !Label->isDefined()) continue; // Not emitted, in dead code.
147109467b48Spatrick
147209467b48Spatrick // Advance row if new location.
147309467b48Spatrick if (BaseLabel && Label) {
147409467b48Spatrick MCSymbol *ThisSym = Label;
147509467b48Spatrick if (ThisSym != BaseLabel) {
1476097a140dSpatrick Streamer.emitDwarfAdvanceFrameAddr(BaseLabel, ThisSym);
147709467b48Spatrick BaseLabel = ThisSym;
147809467b48Spatrick }
147909467b48Spatrick }
148009467b48Spatrick
1481097a140dSpatrick emitCFIInstruction(Instr);
148209467b48Spatrick }
148309467b48Spatrick }
148409467b48Spatrick
148509467b48Spatrick /// Emit the unwind information in a compact way.
EmitCompactUnwind(const MCDwarfFrameInfo & Frame)148609467b48Spatrick void FrameEmitterImpl::EmitCompactUnwind(const MCDwarfFrameInfo &Frame) {
148709467b48Spatrick MCContext &Context = Streamer.getContext();
148809467b48Spatrick const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
148909467b48Spatrick
149009467b48Spatrick // range-start range-length compact-unwind-enc personality-func lsda
149109467b48Spatrick // _foo LfooEnd-_foo 0x00000023 0 0
149209467b48Spatrick // _bar LbarEnd-_bar 0x00000025 __gxx_personality except_tab1
149309467b48Spatrick //
149409467b48Spatrick // .section __LD,__compact_unwind,regular,debug
149509467b48Spatrick //
149609467b48Spatrick // # compact unwind for _foo
149709467b48Spatrick // .quad _foo
149809467b48Spatrick // .set L1,LfooEnd-_foo
149909467b48Spatrick // .long L1
150009467b48Spatrick // .long 0x01010001
150109467b48Spatrick // .quad 0
150209467b48Spatrick // .quad 0
150309467b48Spatrick //
150409467b48Spatrick // # compact unwind for _bar
150509467b48Spatrick // .quad _bar
150609467b48Spatrick // .set L2,LbarEnd-_bar
150709467b48Spatrick // .long L2
150809467b48Spatrick // .long 0x01020011
150909467b48Spatrick // .quad __gxx_personality
151009467b48Spatrick // .quad except_tab1
151109467b48Spatrick
151209467b48Spatrick uint32_t Encoding = Frame.CompactUnwindEncoding;
151309467b48Spatrick if (!Encoding) return;
151409467b48Spatrick bool DwarfEHFrameOnly = (Encoding == MOFI->getCompactUnwindDwarfEHFrameOnly());
151509467b48Spatrick
151609467b48Spatrick // The encoding needs to know we have an LSDA.
151709467b48Spatrick if (!DwarfEHFrameOnly && Frame.Lsda)
151809467b48Spatrick Encoding |= 0x40000000;
151909467b48Spatrick
152009467b48Spatrick // Range Start
152109467b48Spatrick unsigned FDEEncoding = MOFI->getFDEEncoding();
152209467b48Spatrick unsigned Size = getSizeForEncoding(Streamer, FDEEncoding);
1523097a140dSpatrick Streamer.emitSymbolValue(Frame.Begin, Size);
152409467b48Spatrick
152509467b48Spatrick // Range Length
1526097a140dSpatrick const MCExpr *Range =
1527097a140dSpatrick makeEndMinusStartExpr(Context, *Frame.Begin, *Frame.End, 0);
152809467b48Spatrick emitAbsValue(Streamer, Range, 4);
152909467b48Spatrick
153009467b48Spatrick // Compact Encoding
153109467b48Spatrick Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4);
1532097a140dSpatrick Streamer.emitIntValue(Encoding, Size);
153309467b48Spatrick
153409467b48Spatrick // Personality Function
153509467b48Spatrick Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr);
153609467b48Spatrick if (!DwarfEHFrameOnly && Frame.Personality)
1537097a140dSpatrick Streamer.emitSymbolValue(Frame.Personality, Size);
153809467b48Spatrick else
1539097a140dSpatrick Streamer.emitIntValue(0, Size); // No personality fn
154009467b48Spatrick
154109467b48Spatrick // LSDA
154209467b48Spatrick Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding);
154309467b48Spatrick if (!DwarfEHFrameOnly && Frame.Lsda)
1544097a140dSpatrick Streamer.emitSymbolValue(Frame.Lsda, Size);
154509467b48Spatrick else
1546097a140dSpatrick Streamer.emitIntValue(0, Size); // No LSDA
154709467b48Spatrick }
154809467b48Spatrick
getCIEVersion(bool IsEH,unsigned DwarfVersion)154909467b48Spatrick static unsigned getCIEVersion(bool IsEH, unsigned DwarfVersion) {
155009467b48Spatrick if (IsEH)
155109467b48Spatrick return 1;
155209467b48Spatrick switch (DwarfVersion) {
155309467b48Spatrick case 2:
155409467b48Spatrick return 1;
155509467b48Spatrick case 3:
155609467b48Spatrick return 3;
155709467b48Spatrick case 4:
155809467b48Spatrick case 5:
155909467b48Spatrick return 4;
156009467b48Spatrick }
156109467b48Spatrick llvm_unreachable("Unknown version");
156209467b48Spatrick }
156309467b48Spatrick
EmitCIE(const MCDwarfFrameInfo & Frame)156409467b48Spatrick const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {
156509467b48Spatrick MCContext &context = Streamer.getContext();
156609467b48Spatrick const MCRegisterInfo *MRI = context.getRegisterInfo();
156709467b48Spatrick const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
156809467b48Spatrick
156909467b48Spatrick MCSymbol *sectionStart = context.createTempSymbol();
1570097a140dSpatrick Streamer.emitLabel(sectionStart);
157109467b48Spatrick
157209467b48Spatrick MCSymbol *sectionEnd = context.createTempSymbol();
157309467b48Spatrick
1574097a140dSpatrick dwarf::DwarfFormat Format = IsEH ? dwarf::DWARF32 : context.getDwarfFormat();
1575097a140dSpatrick unsigned UnitLengthBytes = dwarf::getUnitLengthFieldByteSize(Format);
1576097a140dSpatrick unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(Format);
1577097a140dSpatrick bool IsDwarf64 = Format == dwarf::DWARF64;
1578097a140dSpatrick
1579097a140dSpatrick if (IsDwarf64)
1580097a140dSpatrick // DWARF64 mark
1581097a140dSpatrick Streamer.emitInt32(dwarf::DW_LENGTH_DWARF64);
1582097a140dSpatrick
158309467b48Spatrick // Length
1584097a140dSpatrick const MCExpr *Length = makeEndMinusStartExpr(context, *sectionStart,
1585097a140dSpatrick *sectionEnd, UnitLengthBytes);
1586097a140dSpatrick emitAbsValue(Streamer, Length, OffsetSize);
158709467b48Spatrick
158809467b48Spatrick // CIE ID
1589097a140dSpatrick uint64_t CIE_ID =
1590097a140dSpatrick IsEH ? 0 : (IsDwarf64 ? dwarf::DW64_CIE_ID : dwarf::DW_CIE_ID);
1591097a140dSpatrick Streamer.emitIntValue(CIE_ID, OffsetSize);
159209467b48Spatrick
159309467b48Spatrick // Version
159409467b48Spatrick uint8_t CIEVersion = getCIEVersion(IsEH, context.getDwarfVersion());
1595097a140dSpatrick Streamer.emitInt8(CIEVersion);
159609467b48Spatrick
159709467b48Spatrick if (IsEH) {
159809467b48Spatrick SmallString<8> Augmentation;
159909467b48Spatrick Augmentation += "z";
160009467b48Spatrick if (Frame.Personality)
160109467b48Spatrick Augmentation += "P";
160209467b48Spatrick if (Frame.Lsda)
160309467b48Spatrick Augmentation += "L";
160409467b48Spatrick Augmentation += "R";
160509467b48Spatrick if (Frame.IsSignalFrame)
160609467b48Spatrick Augmentation += "S";
160709467b48Spatrick if (Frame.IsBKeyFrame)
160809467b48Spatrick Augmentation += "B";
1609*d415bd75Srobert if (Frame.IsMTETaggedFrame)
1610*d415bd75Srobert Augmentation += "G";
1611097a140dSpatrick Streamer.emitBytes(Augmentation);
161209467b48Spatrick }
1613097a140dSpatrick Streamer.emitInt8(0);
161409467b48Spatrick
161509467b48Spatrick if (CIEVersion >= 4) {
161609467b48Spatrick // Address Size
1617097a140dSpatrick Streamer.emitInt8(context.getAsmInfo()->getCodePointerSize());
161809467b48Spatrick
161909467b48Spatrick // Segment Descriptor Size
1620097a140dSpatrick Streamer.emitInt8(0);
162109467b48Spatrick }
162209467b48Spatrick
162309467b48Spatrick // Code Alignment Factor
1624097a140dSpatrick Streamer.emitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment());
162509467b48Spatrick
162609467b48Spatrick // Data Alignment Factor
1627097a140dSpatrick Streamer.emitSLEB128IntValue(getDataAlignmentFactor(Streamer));
162809467b48Spatrick
162909467b48Spatrick // Return Address Register
163009467b48Spatrick unsigned RAReg = Frame.RAReg;
163109467b48Spatrick if (RAReg == static_cast<unsigned>(INT_MAX))
163209467b48Spatrick RAReg = MRI->getDwarfRegNum(MRI->getRARegister(), IsEH);
163309467b48Spatrick
163409467b48Spatrick if (CIEVersion == 1) {
163509467b48Spatrick assert(RAReg <= 255 &&
163609467b48Spatrick "DWARF 2 encodes return_address_register in one byte");
1637097a140dSpatrick Streamer.emitInt8(RAReg);
163809467b48Spatrick } else {
1639097a140dSpatrick Streamer.emitULEB128IntValue(RAReg);
164009467b48Spatrick }
164109467b48Spatrick
164209467b48Spatrick // Augmentation Data Length (optional)
164309467b48Spatrick unsigned augmentationLength = 0;
164409467b48Spatrick if (IsEH) {
164509467b48Spatrick if (Frame.Personality) {
164609467b48Spatrick // Personality Encoding
164709467b48Spatrick augmentationLength += 1;
164809467b48Spatrick // Personality
164909467b48Spatrick augmentationLength +=
165009467b48Spatrick getSizeForEncoding(Streamer, Frame.PersonalityEncoding);
165109467b48Spatrick }
165209467b48Spatrick if (Frame.Lsda)
165309467b48Spatrick augmentationLength += 1;
165409467b48Spatrick // Encoding of the FDE pointers
165509467b48Spatrick augmentationLength += 1;
165609467b48Spatrick
1657097a140dSpatrick Streamer.emitULEB128IntValue(augmentationLength);
165809467b48Spatrick
165909467b48Spatrick // Augmentation Data (optional)
166009467b48Spatrick if (Frame.Personality) {
166109467b48Spatrick // Personality Encoding
166209467b48Spatrick emitEncodingByte(Streamer, Frame.PersonalityEncoding);
166309467b48Spatrick // Personality
166409467b48Spatrick EmitPersonality(Streamer, *Frame.Personality, Frame.PersonalityEncoding);
166509467b48Spatrick }
166609467b48Spatrick
166709467b48Spatrick if (Frame.Lsda)
166809467b48Spatrick emitEncodingByte(Streamer, Frame.LsdaEncoding);
166909467b48Spatrick
167009467b48Spatrick // Encoding of the FDE pointers
167109467b48Spatrick emitEncodingByte(Streamer, MOFI->getFDEEncoding());
167209467b48Spatrick }
167309467b48Spatrick
167409467b48Spatrick // Initial Instructions
167509467b48Spatrick
167609467b48Spatrick const MCAsmInfo *MAI = context.getAsmInfo();
167709467b48Spatrick if (!Frame.IsSimple) {
167809467b48Spatrick const std::vector<MCCFIInstruction> &Instructions =
167909467b48Spatrick MAI->getInitialFrameState();
1680097a140dSpatrick emitCFIInstructions(Instructions, nullptr);
168109467b48Spatrick }
168209467b48Spatrick
168309467b48Spatrick InitialCFAOffset = CFAOffset;
168409467b48Spatrick
168509467b48Spatrick // Padding
1686*d415bd75Srobert Streamer.emitValueToAlignment(Align(IsEH ? 4 : MAI->getCodePointerSize()));
168709467b48Spatrick
1688097a140dSpatrick Streamer.emitLabel(sectionEnd);
168909467b48Spatrick return *sectionStart;
169009467b48Spatrick }
169109467b48Spatrick
EmitFDE(const MCSymbol & cieStart,const MCDwarfFrameInfo & frame,bool LastInSection,const MCSymbol & SectionStart)169209467b48Spatrick void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart,
169309467b48Spatrick const MCDwarfFrameInfo &frame,
169409467b48Spatrick bool LastInSection,
169509467b48Spatrick const MCSymbol &SectionStart) {
169609467b48Spatrick MCContext &context = Streamer.getContext();
169709467b48Spatrick MCSymbol *fdeStart = context.createTempSymbol();
169809467b48Spatrick MCSymbol *fdeEnd = context.createTempSymbol();
169909467b48Spatrick const MCObjectFileInfo *MOFI = context.getObjectFileInfo();
170009467b48Spatrick
170109467b48Spatrick CFAOffset = InitialCFAOffset;
170209467b48Spatrick
1703097a140dSpatrick dwarf::DwarfFormat Format = IsEH ? dwarf::DWARF32 : context.getDwarfFormat();
1704097a140dSpatrick unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(Format);
170509467b48Spatrick
1706097a140dSpatrick if (Format == dwarf::DWARF64)
1707097a140dSpatrick // DWARF64 mark
1708097a140dSpatrick Streamer.emitInt32(dwarf::DW_LENGTH_DWARF64);
1709097a140dSpatrick
1710097a140dSpatrick // Length
1711097a140dSpatrick const MCExpr *Length = makeEndMinusStartExpr(context, *fdeStart, *fdeEnd, 0);
1712097a140dSpatrick emitAbsValue(Streamer, Length, OffsetSize);
1713097a140dSpatrick
1714097a140dSpatrick Streamer.emitLabel(fdeStart);
171509467b48Spatrick
171609467b48Spatrick // CIE Pointer
171709467b48Spatrick const MCAsmInfo *asmInfo = context.getAsmInfo();
171809467b48Spatrick if (IsEH) {
171909467b48Spatrick const MCExpr *offset =
1720097a140dSpatrick makeEndMinusStartExpr(context, cieStart, *fdeStart, 0);
1721097a140dSpatrick emitAbsValue(Streamer, offset, OffsetSize);
172209467b48Spatrick } else if (!asmInfo->doesDwarfUseRelocationsAcrossSections()) {
172309467b48Spatrick const MCExpr *offset =
1724097a140dSpatrick makeEndMinusStartExpr(context, SectionStart, cieStart, 0);
1725097a140dSpatrick emitAbsValue(Streamer, offset, OffsetSize);
172609467b48Spatrick } else {
1727097a140dSpatrick Streamer.emitSymbolValue(&cieStart, OffsetSize,
172809467b48Spatrick asmInfo->needsDwarfSectionOffsetDirective());
172909467b48Spatrick }
173009467b48Spatrick
173109467b48Spatrick // PC Begin
173209467b48Spatrick unsigned PCEncoding =
173309467b48Spatrick IsEH ? MOFI->getFDEEncoding() : (unsigned)dwarf::DW_EH_PE_absptr;
173409467b48Spatrick unsigned PCSize = getSizeForEncoding(Streamer, PCEncoding);
173509467b48Spatrick emitFDESymbol(Streamer, *frame.Begin, PCEncoding, IsEH);
173609467b48Spatrick
173709467b48Spatrick // PC Range
173809467b48Spatrick const MCExpr *Range =
1739097a140dSpatrick makeEndMinusStartExpr(context, *frame.Begin, *frame.End, 0);
174009467b48Spatrick emitAbsValue(Streamer, Range, PCSize);
174109467b48Spatrick
174209467b48Spatrick if (IsEH) {
174309467b48Spatrick // Augmentation Data Length
174409467b48Spatrick unsigned augmentationLength = 0;
174509467b48Spatrick
174609467b48Spatrick if (frame.Lsda)
174709467b48Spatrick augmentationLength += getSizeForEncoding(Streamer, frame.LsdaEncoding);
174809467b48Spatrick
1749097a140dSpatrick Streamer.emitULEB128IntValue(augmentationLength);
175009467b48Spatrick
175109467b48Spatrick // Augmentation Data
175209467b48Spatrick if (frame.Lsda)
175309467b48Spatrick emitFDESymbol(Streamer, *frame.Lsda, frame.LsdaEncoding, true);
175409467b48Spatrick }
175509467b48Spatrick
175609467b48Spatrick // Call Frame Instructions
1757097a140dSpatrick emitCFIInstructions(frame.Instructions, frame.Begin);
175809467b48Spatrick
175909467b48Spatrick // Padding
176009467b48Spatrick // The size of a .eh_frame section has to be a multiple of the alignment
176109467b48Spatrick // since a null CIE is interpreted as the end. Old systems overaligned
176209467b48Spatrick // .eh_frame, so we do too and account for it in the last FDE.
1763*d415bd75Srobert unsigned Alignment = LastInSection ? asmInfo->getCodePointerSize() : PCSize;
1764*d415bd75Srobert Streamer.emitValueToAlignment(Align(Alignment));
176509467b48Spatrick
1766097a140dSpatrick Streamer.emitLabel(fdeEnd);
176709467b48Spatrick }
176809467b48Spatrick
176909467b48Spatrick namespace {
177009467b48Spatrick
177109467b48Spatrick struct CIEKey {
getEmptyKey__anon703b1a400311::CIEKey177209467b48Spatrick static const CIEKey getEmptyKey() {
177309467b48Spatrick return CIEKey(nullptr, 0, -1, false, false, static_cast<unsigned>(INT_MAX),
1774*d415bd75Srobert false, false);
177509467b48Spatrick }
177609467b48Spatrick
getTombstoneKey__anon703b1a400311::CIEKey177709467b48Spatrick static const CIEKey getTombstoneKey() {
177809467b48Spatrick return CIEKey(nullptr, -1, 0, false, false, static_cast<unsigned>(INT_MAX),
1779*d415bd75Srobert false, false);
178009467b48Spatrick }
178109467b48Spatrick
CIEKey__anon703b1a400311::CIEKey178209467b48Spatrick CIEKey(const MCSymbol *Personality, unsigned PersonalityEncoding,
178309467b48Spatrick unsigned LSDAEncoding, bool IsSignalFrame, bool IsSimple,
1784*d415bd75Srobert unsigned RAReg, bool IsBKeyFrame, bool IsMTETaggedFrame)
178509467b48Spatrick : Personality(Personality), PersonalityEncoding(PersonalityEncoding),
178609467b48Spatrick LsdaEncoding(LSDAEncoding), IsSignalFrame(IsSignalFrame),
1787*d415bd75Srobert IsSimple(IsSimple), RAReg(RAReg), IsBKeyFrame(IsBKeyFrame),
1788*d415bd75Srobert IsMTETaggedFrame(IsMTETaggedFrame) {}
178909467b48Spatrick
CIEKey__anon703b1a400311::CIEKey179009467b48Spatrick explicit CIEKey(const MCDwarfFrameInfo &Frame)
179109467b48Spatrick : Personality(Frame.Personality),
179209467b48Spatrick PersonalityEncoding(Frame.PersonalityEncoding),
179309467b48Spatrick LsdaEncoding(Frame.LsdaEncoding), IsSignalFrame(Frame.IsSignalFrame),
179409467b48Spatrick IsSimple(Frame.IsSimple), RAReg(Frame.RAReg),
1795*d415bd75Srobert IsBKeyFrame(Frame.IsBKeyFrame),
1796*d415bd75Srobert IsMTETaggedFrame(Frame.IsMTETaggedFrame) {}
179709467b48Spatrick
PersonalityName__anon703b1a400311::CIEKey179809467b48Spatrick StringRef PersonalityName() const {
179909467b48Spatrick if (!Personality)
180009467b48Spatrick return StringRef();
180109467b48Spatrick return Personality->getName();
180209467b48Spatrick }
180309467b48Spatrick
operator <__anon703b1a400311::CIEKey180409467b48Spatrick bool operator<(const CIEKey &Other) const {
180509467b48Spatrick return std::make_tuple(PersonalityName(), PersonalityEncoding, LsdaEncoding,
1806*d415bd75Srobert IsSignalFrame, IsSimple, RAReg, IsBKeyFrame,
1807*d415bd75Srobert IsMTETaggedFrame) <
180809467b48Spatrick std::make_tuple(Other.PersonalityName(), Other.PersonalityEncoding,
180909467b48Spatrick Other.LsdaEncoding, Other.IsSignalFrame,
1810*d415bd75Srobert Other.IsSimple, Other.RAReg, Other.IsBKeyFrame,
1811*d415bd75Srobert Other.IsMTETaggedFrame);
181209467b48Spatrick }
181309467b48Spatrick
181409467b48Spatrick const MCSymbol *Personality;
181509467b48Spatrick unsigned PersonalityEncoding;
181609467b48Spatrick unsigned LsdaEncoding;
181709467b48Spatrick bool IsSignalFrame;
181809467b48Spatrick bool IsSimple;
181909467b48Spatrick unsigned RAReg;
182009467b48Spatrick bool IsBKeyFrame;
1821*d415bd75Srobert bool IsMTETaggedFrame;
182209467b48Spatrick };
182309467b48Spatrick
182409467b48Spatrick } // end anonymous namespace
182509467b48Spatrick
182609467b48Spatrick namespace llvm {
182709467b48Spatrick
182809467b48Spatrick template <> struct DenseMapInfo<CIEKey> {
getEmptyKeyllvm::DenseMapInfo182909467b48Spatrick static CIEKey getEmptyKey() { return CIEKey::getEmptyKey(); }
getTombstoneKeyllvm::DenseMapInfo183009467b48Spatrick static CIEKey getTombstoneKey() { return CIEKey::getTombstoneKey(); }
183109467b48Spatrick
getHashValuellvm::DenseMapInfo183209467b48Spatrick static unsigned getHashValue(const CIEKey &Key) {
1833*d415bd75Srobert return static_cast<unsigned>(
1834*d415bd75Srobert hash_combine(Key.Personality, Key.PersonalityEncoding, Key.LsdaEncoding,
1835*d415bd75Srobert Key.IsSignalFrame, Key.IsSimple, Key.RAReg,
1836*d415bd75Srobert Key.IsBKeyFrame, Key.IsMTETaggedFrame));
183709467b48Spatrick }
183809467b48Spatrick
isEqualllvm::DenseMapInfo183909467b48Spatrick static bool isEqual(const CIEKey &LHS, const CIEKey &RHS) {
184009467b48Spatrick return LHS.Personality == RHS.Personality &&
184109467b48Spatrick LHS.PersonalityEncoding == RHS.PersonalityEncoding &&
184209467b48Spatrick LHS.LsdaEncoding == RHS.LsdaEncoding &&
184309467b48Spatrick LHS.IsSignalFrame == RHS.IsSignalFrame &&
184409467b48Spatrick LHS.IsSimple == RHS.IsSimple && LHS.RAReg == RHS.RAReg &&
1845*d415bd75Srobert LHS.IsBKeyFrame == RHS.IsBKeyFrame &&
1846*d415bd75Srobert LHS.IsMTETaggedFrame == RHS.IsMTETaggedFrame;
184709467b48Spatrick }
184809467b48Spatrick };
184909467b48Spatrick
185009467b48Spatrick } // end namespace llvm
185109467b48Spatrick
Emit(MCObjectStreamer & Streamer,MCAsmBackend * MAB,bool IsEH)185209467b48Spatrick void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,
185309467b48Spatrick bool IsEH) {
185409467b48Spatrick MCContext &Context = Streamer.getContext();
185509467b48Spatrick const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();
185609467b48Spatrick const MCAsmInfo *AsmInfo = Context.getAsmInfo();
185709467b48Spatrick FrameEmitterImpl Emitter(IsEH, Streamer);
185809467b48Spatrick ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getDwarfFrameInfos();
185909467b48Spatrick
186009467b48Spatrick // Emit the compact unwind info if available.
186109467b48Spatrick bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame();
186209467b48Spatrick if (IsEH && MOFI->getCompactUnwindSection()) {
1863*d415bd75Srobert Streamer.generateCompactUnwindEncodings(MAB);
186409467b48Spatrick bool SectionEmitted = false;
186509467b48Spatrick for (const MCDwarfFrameInfo &Frame : FrameArray) {
186609467b48Spatrick if (Frame.CompactUnwindEncoding == 0) continue;
186709467b48Spatrick if (!SectionEmitted) {
1868*d415bd75Srobert Streamer.switchSection(MOFI->getCompactUnwindSection());
1869*d415bd75Srobert Streamer.emitValueToAlignment(Align(AsmInfo->getCodePointerSize()));
187009467b48Spatrick SectionEmitted = true;
187109467b48Spatrick }
187209467b48Spatrick NeedsEHFrameSection |=
187309467b48Spatrick Frame.CompactUnwindEncoding ==
187409467b48Spatrick MOFI->getCompactUnwindDwarfEHFrameOnly();
187509467b48Spatrick Emitter.EmitCompactUnwind(Frame);
187609467b48Spatrick }
187709467b48Spatrick }
187809467b48Spatrick
187909467b48Spatrick if (!NeedsEHFrameSection) return;
188009467b48Spatrick
188109467b48Spatrick MCSection &Section =
188209467b48Spatrick IsEH ? *const_cast<MCObjectFileInfo *>(MOFI)->getEHFrameSection()
188309467b48Spatrick : *MOFI->getDwarfFrameSection();
188409467b48Spatrick
1885*d415bd75Srobert Streamer.switchSection(&Section);
188609467b48Spatrick MCSymbol *SectionStart = Context.createTempSymbol();
1887097a140dSpatrick Streamer.emitLabel(SectionStart);
188809467b48Spatrick
188909467b48Spatrick DenseMap<CIEKey, const MCSymbol *> CIEStarts;
189009467b48Spatrick
189109467b48Spatrick const MCSymbol *DummyDebugKey = nullptr;
189209467b48Spatrick bool CanOmitDwarf = MOFI->getOmitDwarfIfHaveCompactUnwind();
189309467b48Spatrick // Sort the FDEs by their corresponding CIE before we emit them.
189409467b48Spatrick // This isn't technically necessary according to the DWARF standard,
189509467b48Spatrick // but the Android libunwindstack rejects eh_frame sections where
189609467b48Spatrick // an FDE refers to a CIE other than the closest previous CIE.
189709467b48Spatrick std::vector<MCDwarfFrameInfo> FrameArrayX(FrameArray.begin(), FrameArray.end());
189809467b48Spatrick llvm::stable_sort(FrameArrayX,
189909467b48Spatrick [](const MCDwarfFrameInfo &X, const MCDwarfFrameInfo &Y) {
190009467b48Spatrick return CIEKey(X) < CIEKey(Y);
190109467b48Spatrick });
190209467b48Spatrick for (auto I = FrameArrayX.begin(), E = FrameArrayX.end(); I != E;) {
190309467b48Spatrick const MCDwarfFrameInfo &Frame = *I;
190409467b48Spatrick ++I;
190509467b48Spatrick if (CanOmitDwarf && Frame.CompactUnwindEncoding !=
190609467b48Spatrick MOFI->getCompactUnwindDwarfEHFrameOnly())
190709467b48Spatrick // Don't generate an EH frame if we don't need one. I.e., it's taken care
190809467b48Spatrick // of by the compact unwind encoding.
190909467b48Spatrick continue;
191009467b48Spatrick
191109467b48Spatrick CIEKey Key(Frame);
191209467b48Spatrick const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey;
191309467b48Spatrick if (!CIEStart)
191409467b48Spatrick CIEStart = &Emitter.EmitCIE(Frame);
191509467b48Spatrick
191609467b48Spatrick Emitter.EmitFDE(*CIEStart, Frame, I == E, *SectionStart);
191709467b48Spatrick }
191809467b48Spatrick }
191909467b48Spatrick
EmitAdvanceLoc(MCObjectStreamer & Streamer,uint64_t AddrDelta)192009467b48Spatrick void MCDwarfFrameEmitter::EmitAdvanceLoc(MCObjectStreamer &Streamer,
192109467b48Spatrick uint64_t AddrDelta) {
192209467b48Spatrick MCContext &Context = Streamer.getContext();
192309467b48Spatrick SmallString<256> Tmp;
192409467b48Spatrick raw_svector_ostream OS(Tmp);
192509467b48Spatrick MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OS);
1926097a140dSpatrick Streamer.emitBytes(OS.str());
192709467b48Spatrick }
192809467b48Spatrick
EncodeAdvanceLoc(MCContext & Context,uint64_t AddrDelta,raw_ostream & OS)192909467b48Spatrick void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context,
193073471bf0Spatrick uint64_t AddrDelta,
193173471bf0Spatrick raw_ostream &OS) {
193209467b48Spatrick // Scale the address delta by the minimum instruction length.
193309467b48Spatrick AddrDelta = ScaleAddrDelta(Context, AddrDelta);
193473471bf0Spatrick if (AddrDelta == 0)
193573471bf0Spatrick return;
193609467b48Spatrick
193709467b48Spatrick support::endianness E =
193809467b48Spatrick Context.getAsmInfo()->isLittleEndian() ? support::little : support::big;
193973471bf0Spatrick
194073471bf0Spatrick if (isUIntN(6, AddrDelta)) {
194109467b48Spatrick uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;
194209467b48Spatrick OS << Opcode;
194309467b48Spatrick } else if (isUInt<8>(AddrDelta)) {
194409467b48Spatrick OS << uint8_t(dwarf::DW_CFA_advance_loc1);
194509467b48Spatrick OS << uint8_t(AddrDelta);
194609467b48Spatrick } else if (isUInt<16>(AddrDelta)) {
194709467b48Spatrick OS << uint8_t(dwarf::DW_CFA_advance_loc2);
194809467b48Spatrick support::endian::write<uint16_t>(OS, AddrDelta, E);
194909467b48Spatrick } else {
195009467b48Spatrick assert(isUInt<32>(AddrDelta));
195109467b48Spatrick OS << uint8_t(dwarf::DW_CFA_advance_loc4);
195209467b48Spatrick support::endian::write<uint32_t>(OS, AddrDelta, E);
195309467b48Spatrick }
195409467b48Spatrick }
1955