2009 lines · cpp
1//===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/MC/MCDwarf.h"10#include "llvm/ADT/ArrayRef.h"11#include "llvm/ADT/STLExtras.h"12#include "llvm/ADT/SmallString.h"13#include "llvm/ADT/SmallVector.h"14#include "llvm/ADT/StringRef.h"15#include "llvm/ADT/Twine.h"16#include "llvm/BinaryFormat/Dwarf.h"17#include "llvm/Config/config.h"18#include "llvm/MC/MCAsmInfo.h"19#include "llvm/MC/MCContext.h"20#include "llvm/MC/MCExpr.h"21#include "llvm/MC/MCObjectFileInfo.h"22#include "llvm/MC/MCObjectStreamer.h"23#include "llvm/MC/MCRegisterInfo.h"24#include "llvm/MC/MCSection.h"25#include "llvm/MC/MCStreamer.h"26#include "llvm/MC/MCSymbol.h"27#include "llvm/Support/Casting.h"28#include "llvm/Support/EndianStream.h"29#include "llvm/Support/ErrorHandling.h"30#include "llvm/Support/LEB128.h"31#include "llvm/Support/MathExtras.h"32#include "llvm/Support/Path.h"33#include "llvm/Support/SourceMgr.h"34#include "llvm/Support/raw_ostream.h"35#include <cassert>36#include <cstdint>37#include <optional>38#include <string>39#include <utility>40#include <vector>41 42using namespace llvm;43 44MCSymbol *mcdwarf::emitListsTableHeaderStart(MCStreamer &S) {45 MCSymbol *Start = S.getContext().createTempSymbol("debug_list_header_start");46 MCSymbol *End = S.getContext().createTempSymbol("debug_list_header_end");47 auto DwarfFormat = S.getContext().getDwarfFormat();48 if (DwarfFormat == dwarf::DWARF64) {49 S.AddComment("DWARF64 mark");50 S.emitInt32(dwarf::DW_LENGTH_DWARF64);51 }52 S.AddComment("Length");53 S.emitAbsoluteSymbolDiff(End, Start,54 dwarf::getDwarfOffsetByteSize(DwarfFormat));55 S.emitLabel(Start);56 S.AddComment("Version");57 S.emitInt16(S.getContext().getDwarfVersion());58 S.AddComment("Address size");59 S.emitInt8(S.getContext().getAsmInfo()->getCodePointerSize());60 S.AddComment("Segment selector size");61 S.emitInt8(0);62 return End;63}64 65static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) {66 unsigned MinInsnLength = Context.getAsmInfo()->getMinInstAlignment();67 if (MinInsnLength == 1)68 return AddrDelta;69 if (AddrDelta % MinInsnLength != 0) {70 // TODO: report this error, but really only once.71 ;72 }73 return AddrDelta / MinInsnLength;74}75 76MCDwarfLineStr::MCDwarfLineStr(MCContext &Ctx) {77 UseRelocs = Ctx.getAsmInfo()->doesDwarfUseRelocationsAcrossSections();78 if (UseRelocs) {79 MCSection *DwarfLineStrSection =80 Ctx.getObjectFileInfo()->getDwarfLineStrSection();81 assert(DwarfLineStrSection && "DwarfLineStrSection must not be NULL");82 LineStrLabel = DwarfLineStrSection->getBeginSymbol();83 }84}85 86//87// This is called when an instruction is assembled into the specified section88// and if there is information from the last .loc directive that has yet to have89// a line entry made for it is made.90//91void MCDwarfLineEntry::make(MCStreamer *MCOS, MCSection *Section) {92 if (!MCOS->getContext().getDwarfLocSeen())93 return;94 95 // Create a symbol at in the current section for use in the line entry.96 MCSymbol *LineSym = MCOS->getContext().createTempSymbol();97 // Set the value of the symbol to use for the MCDwarfLineEntry.98 MCOS->emitLabel(LineSym);99 100 // Get the current .loc info saved in the context.101 const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc();102 103 // Create a (local) line entry with the symbol and the current .loc info.104 MCDwarfLineEntry LineEntry(LineSym, DwarfLoc);105 106 // clear DwarfLocSeen saying the current .loc info is now used.107 MCOS->getContext().clearDwarfLocSeen();108 109 // Add the line entry to this section's entries.110 MCOS->getContext()111 .getMCDwarfLineTable(MCOS->getContext().getDwarfCompileUnitID())112 .getMCLineSections()113 .addLineEntry(LineEntry, Section);114}115 116//117// This helper routine returns an expression of End - Start - IntVal .118//119static inline const MCExpr *makeEndMinusStartExpr(MCContext &Ctx,120 const MCSymbol &Start,121 const MCSymbol &End,122 int IntVal) {123 const MCExpr *Res = MCSymbolRefExpr::create(&End, Ctx);124 const MCExpr *RHS = MCSymbolRefExpr::create(&Start, Ctx);125 const MCExpr *Res1 = MCBinaryExpr::create(MCBinaryExpr::Sub, Res, RHS, Ctx);126 const MCExpr *Res2 = MCConstantExpr::create(IntVal, Ctx);127 const MCExpr *Res3 = MCBinaryExpr::create(MCBinaryExpr::Sub, Res1, Res2, Ctx);128 return Res3;129}130 131//132// This helper routine returns an expression of Start + IntVal .133//134static inline const MCExpr *135makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) {136 const MCExpr *LHS = MCSymbolRefExpr::create(&Start, Ctx);137 const MCExpr *RHS = MCConstantExpr::create(IntVal, Ctx);138 const MCExpr *Res = MCBinaryExpr::create(MCBinaryExpr::Add, LHS, RHS, Ctx);139 return Res;140}141 142void MCLineSection::addEndEntry(MCSymbol *EndLabel) {143 auto *Sec = &EndLabel->getSection();144 // The line table may be empty, which we should skip adding an end entry.145 // There are three cases:146 // (1) MCAsmStreamer - emitDwarfLocDirective emits a location directive in147 // place instead of adding a line entry if the target has148 // usesDwarfFileAndLocDirectives.149 // (2) MCObjectStreamer - if a function has incomplete debug info where150 // instructions don't have DILocations, the line entries are missing.151 // (3) It's also possible that there are no prior line entries if the section152 // itself is empty before this end label.153 auto I = MCLineDivisions.find(Sec);154 if (I == MCLineDivisions.end()) // If section not found, do nothing.155 return;156 157 auto &Entries = I->second;158 // If no entries in this section's list, nothing to base the end entry on.159 if (Entries.empty())160 return;161 162 // Create the end entry based on the last existing entry.163 MCDwarfLineEntry EndEntry = Entries.back();164 165 // An end entry is just for marking the end of a sequence of code locations.166 // It should not carry forward a LineStreamLabel from a previous special entry167 // if Entries.back() happened to be such an entry. So here we clear168 // LineStreamLabel.169 EndEntry.LineStreamLabel = nullptr;170 EndEntry.setEndLabel(EndLabel);171 Entries.push_back(EndEntry);172}173 174//175// This emits the Dwarf line table for the specified section from the entries176// in the LineSection.177//178void MCDwarfLineTable::emitOne(179 MCStreamer *MCOS, MCSection *Section,180 const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {181 182 unsigned FileNum, LastLine, Column, Flags, Isa, Discriminator;183 bool IsAtStartSeq;184 MCSymbol *PrevLabel;185 auto init = [&]() {186 FileNum = 1;187 LastLine = 1;188 Column = 0;189 Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;190 Isa = 0;191 Discriminator = 0;192 PrevLabel = nullptr;193 IsAtStartSeq = true;194 };195 init();196 197 // Loop through each MCDwarfLineEntry and encode the dwarf line number table.198 bool EndEntryEmitted = false;199 for (auto It = LineEntries.begin(); It != LineEntries.end(); ++It) {200 auto LineEntry = *It;201 MCSymbol *CurrLabel = LineEntry.getLabel();202 const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();203 204 if (LineEntry.LineStreamLabel) {205 if (!IsAtStartSeq) {206 auto *Label = CurrLabel;207 auto NextIt = It + 1;208 // LineEntry with a null Label is probably a fake LineEntry we added209 // when `-emit-func-debug-line-table-offsets` in order to terminate the210 // sequence. Look for the next Label if possible, otherwise we will set211 // the PC to the end of the section.212 if (!Label && NextIt != LineEntries.end()) {213 Label = NextIt->getLabel();214 }215 MCOS->emitDwarfLineEndEntry(Section, PrevLabel,216 /*EndLabel =*/Label);217 init();218 }219 MCOS->emitLabel(LineEntry.LineStreamLabel, LineEntry.StreamLabelDefLoc);220 continue;221 }222 223 if (LineEntry.IsEndEntry) {224 MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, PrevLabel, CurrLabel,225 asmInfo->getCodePointerSize());226 init();227 EndEntryEmitted = true;228 continue;229 }230 231 int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;232 233 if (FileNum != LineEntry.getFileNum()) {234 FileNum = LineEntry.getFileNum();235 MCOS->emitInt8(dwarf::DW_LNS_set_file);236 MCOS->emitULEB128IntValue(FileNum);237 }238 if (Column != LineEntry.getColumn()) {239 Column = LineEntry.getColumn();240 MCOS->emitInt8(dwarf::DW_LNS_set_column);241 MCOS->emitULEB128IntValue(Column);242 }243 if (Discriminator != LineEntry.getDiscriminator() &&244 MCOS->getContext().getDwarfVersion() >= 4) {245 Discriminator = LineEntry.getDiscriminator();246 unsigned Size = getULEB128Size(Discriminator);247 MCOS->emitInt8(dwarf::DW_LNS_extended_op);248 MCOS->emitULEB128IntValue(Size + 1);249 MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);250 MCOS->emitULEB128IntValue(Discriminator);251 }252 if (Isa != LineEntry.getIsa()) {253 Isa = LineEntry.getIsa();254 MCOS->emitInt8(dwarf::DW_LNS_set_isa);255 MCOS->emitULEB128IntValue(Isa);256 }257 if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {258 Flags = LineEntry.getFlags();259 MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);260 }261 if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)262 MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);263 if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)264 MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);265 if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)266 MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);267 268 // At this point we want to emit/create the sequence to encode the delta in269 // line numbers and the increment of the address from the previous Label270 // and the current Label.271 MCOS->emitDwarfAdvanceLineAddr(LineDelta, PrevLabel, CurrLabel,272 asmInfo->getCodePointerSize());273 274 Discriminator = 0;275 LastLine = LineEntry.getLine();276 PrevLabel = CurrLabel;277 IsAtStartSeq = false;278 }279 280 // Generate DWARF line end entry.281 // We do not need this for DwarfDebug that explicitly terminates the line282 // table using ranges whenever CU or section changes. However, the MC path283 // does not track ranges nor terminate the line table. In that case,284 // conservatively use the section end symbol to end the line table.285 if (!EndEntryEmitted && !IsAtStartSeq)286 MCOS->emitDwarfLineEndEntry(Section, PrevLabel);287}288 289void MCDwarfLineTable::endCurrentSeqAndEmitLineStreamLabel(MCStreamer *MCOS,290 SMLoc DefLoc,291 StringRef Name) {292 auto &ctx = MCOS->getContext();293 auto *LineStreamLabel = ctx.getOrCreateSymbol(Name);294 auto *LineSym = ctx.createTempSymbol();295 MCOS->emitLabel(LineSym);296 const MCDwarfLoc &DwarfLoc = ctx.getCurrentDwarfLoc();297 298 // Create a 'fake' line entry by having LineStreamLabel be non-null. This299 // won't actually emit any line information, it will reset the line table300 // sequence and emit a label at the start of the new line table sequence.301 MCDwarfLineEntry LineEntry(LineSym, DwarfLoc, LineStreamLabel, DefLoc);302 getMCLineSections().addLineEntry(LineEntry, MCOS->getCurrentSectionOnly());303}304 305//306// This emits the Dwarf file and the line tables.307//308void MCDwarfLineTable::emit(MCStreamer *MCOS, MCDwarfLineTableParams Params) {309 MCContext &context = MCOS->getContext();310 311 auto &LineTables = context.getMCDwarfLineTables();312 313 // Bail out early so we don't switch to the debug_line section needlessly and314 // in doing so create an unnecessary (if empty) section.315 if (LineTables.empty())316 return;317 318 // In a v5 non-split line table, put the strings in a separate section.319 std::optional<MCDwarfLineStr> LineStr;320 if (context.getDwarfVersion() >= 5)321 LineStr.emplace(context);322 323 // Switch to the section where the table will be emitted into.324 MCOS->switchSection(context.getObjectFileInfo()->getDwarfLineSection());325 326 // Handle the rest of the Compile Units.327 for (const auto &CUIDTablePair : LineTables) {328 CUIDTablePair.second.emitCU(MCOS, Params, LineStr);329 }330 331 if (LineStr)332 LineStr->emitSection(MCOS);333}334 335void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,336 MCSection *Section) const {337 if (!HasSplitLineTable)338 return;339 std::optional<MCDwarfLineStr> NoLineStr(std::nullopt);340 MCOS.switchSection(Section);341 MCOS.emitLabel(Header.Emit(&MCOS, Params, {}, NoLineStr).second);342}343 344std::pair<MCSymbol *, MCSymbol *>345MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,346 std::optional<MCDwarfLineStr> &LineStr) const {347 static const char StandardOpcodeLengths[] = {348 0, // length of DW_LNS_copy349 1, // length of DW_LNS_advance_pc350 1, // length of DW_LNS_advance_line351 1, // length of DW_LNS_set_file352 1, // length of DW_LNS_set_column353 0, // length of DW_LNS_negate_stmt354 0, // length of DW_LNS_set_basic_block355 0, // length of DW_LNS_const_add_pc356 1, // length of DW_LNS_fixed_advance_pc357 0, // length of DW_LNS_set_prologue_end358 0, // length of DW_LNS_set_epilogue_begin359 1 // DW_LNS_set_isa360 };361 assert(std::size(StandardOpcodeLengths) >=362 (Params.DWARF2LineOpcodeBase - 1U));363 return Emit(MCOS, Params,364 ArrayRef(StandardOpcodeLengths, Params.DWARF2LineOpcodeBase - 1),365 LineStr);366}367 368static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) {369 MCContext &Context = OS.getContext();370 assert(!isa<MCSymbolRefExpr>(Expr));371 if (!Context.getAsmInfo()->doesSetDirectiveSuppressReloc())372 return Expr;373 374 // On Mach-O, try to avoid a relocation by using a set directive.375 MCSymbol *ABS = Context.createTempSymbol();376 OS.emitAssignment(ABS, Expr);377 return MCSymbolRefExpr::create(ABS, Context);378}379 380static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) {381 const MCExpr *ABS = forceExpAbs(OS, Value);382 OS.emitValue(ABS, Size);383}384 385void MCDwarfLineStr::emitSection(MCStreamer *MCOS) {386 // Switch to the .debug_line_str section.387 MCOS->switchSection(388 MCOS->getContext().getObjectFileInfo()->getDwarfLineStrSection());389 SmallString<0> Data = getFinalizedData();390 MCOS->emitBinaryData(Data.str());391}392 393SmallString<0> MCDwarfLineStr::getFinalizedData() {394 // Emit the strings without perturbing the offsets we used.395 if (!LineStrings.isFinalized())396 LineStrings.finalizeInOrder();397 SmallString<0> Data;398 Data.resize(LineStrings.getSize());399 LineStrings.write((uint8_t *)Data.data());400 return Data;401}402 403size_t MCDwarfLineStr::addString(StringRef Path) {404 return LineStrings.add(Path);405}406 407void MCDwarfLineStr::emitRef(MCStreamer *MCOS, StringRef Path) {408 int RefSize =409 dwarf::getDwarfOffsetByteSize(MCOS->getContext().getDwarfFormat());410 size_t Offset = addString(Path);411 if (UseRelocs) {412 MCContext &Ctx = MCOS->getContext();413 if (Ctx.getAsmInfo()->needsDwarfSectionOffsetDirective()) {414 MCOS->emitCOFFSecRel32(LineStrLabel, Offset);415 } else {416 MCOS->emitValue(makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset),417 RefSize);418 }419 } else420 MCOS->emitIntValue(Offset, RefSize);421}422 423void MCDwarfLineTableHeader::emitV2FileDirTables(MCStreamer *MCOS) const {424 // First the directory table.425 for (auto &Dir : MCDwarfDirs) {426 MCOS->emitBytes(Dir); // The DirectoryName, and...427 MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.428 }429 MCOS->emitInt8(0); // Terminate the directory list.430 431 // Second the file table.432 for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {433 assert(!MCDwarfFiles[i].Name.empty());434 MCOS->emitBytes(MCDwarfFiles[i].Name); // FileName and...435 MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.436 MCOS->emitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number.437 MCOS->emitInt8(0); // Last modification timestamp (always 0).438 MCOS->emitInt8(0); // File size (always 0).439 }440 MCOS->emitInt8(0); // Terminate the file list.441}442 443static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,444 bool EmitMD5, bool HasAnySource,445 std::optional<MCDwarfLineStr> &LineStr) {446 assert(!DwarfFile.Name.empty());447 if (LineStr)448 LineStr->emitRef(MCOS, DwarfFile.Name);449 else {450 MCOS->emitBytes(DwarfFile.Name); // FileName and...451 MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.452 }453 MCOS->emitULEB128IntValue(DwarfFile.DirIndex); // Directory number.454 if (EmitMD5) {455 const MD5::MD5Result &Cksum = *DwarfFile.Checksum;456 MCOS->emitBinaryData(457 StringRef(reinterpret_cast<const char *>(Cksum.data()), Cksum.size()));458 }459 if (HasAnySource) {460 // From https://dwarfstd.org/issues/180201.1.html461 // * The value is an empty null-terminated string if no source is available462 StringRef Source = DwarfFile.Source.value_or(StringRef());463 // * If the source is available but is an empty file then the value is a464 // null-terminated single "\n".465 if (DwarfFile.Source && DwarfFile.Source->empty())466 Source = "\n";467 if (LineStr)468 LineStr->emitRef(MCOS, Source);469 else {470 MCOS->emitBytes(Source); // Source and...471 MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.472 }473 }474}475 476void MCDwarfLineTableHeader::emitV5FileDirTables(477 MCStreamer *MCOS, std::optional<MCDwarfLineStr> &LineStr) const {478 // The directory format, which is just a list of the directory paths. In a479 // non-split object, these are references to .debug_line_str; in a split480 // object, they are inline strings.481 MCOS->emitInt8(1);482 MCOS->emitULEB128IntValue(dwarf::DW_LNCT_path);483 MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp484 : dwarf::DW_FORM_string);485 MCOS->emitULEB128IntValue(MCDwarfDirs.size() + 1);486 // Try not to emit an empty compilation directory.487 SmallString<256> Dir;488 StringRef CompDir = MCOS->getContext().getCompilationDir();489 if (!CompilationDir.empty()) {490 Dir = CompilationDir;491 MCOS->getContext().remapDebugPath(Dir);492 CompDir = Dir.str();493 if (LineStr)494 CompDir = LineStr->getSaver().save(CompDir);495 }496 if (LineStr) {497 // Record path strings, emit references here.498 LineStr->emitRef(MCOS, CompDir);499 for (const auto &Dir : MCDwarfDirs)500 LineStr->emitRef(MCOS, Dir);501 } else {502 // The list of directory paths. Compilation directory comes first.503 MCOS->emitBytes(CompDir);504 MCOS->emitBytes(StringRef("\0", 1));505 for (const auto &Dir : MCDwarfDirs) {506 MCOS->emitBytes(Dir); // The DirectoryName, and...507 MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.508 }509 }510 511 // The file format, which is the inline null-terminated filename and a512 // directory index. We don't track file size/timestamp so don't emit them513 // in the v5 table. Emit MD5 checksums and source if we have them.514 uint64_t Entries = 2;515 if (HasAllMD5)516 Entries += 1;517 if (HasAnySource)518 Entries += 1;519 MCOS->emitInt8(Entries);520 MCOS->emitULEB128IntValue(dwarf::DW_LNCT_path);521 MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp522 : dwarf::DW_FORM_string);523 MCOS->emitULEB128IntValue(dwarf::DW_LNCT_directory_index);524 MCOS->emitULEB128IntValue(dwarf::DW_FORM_udata);525 if (HasAllMD5) {526 MCOS->emitULEB128IntValue(dwarf::DW_LNCT_MD5);527 MCOS->emitULEB128IntValue(dwarf::DW_FORM_data16);528 }529 if (HasAnySource) {530 MCOS->emitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);531 MCOS->emitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp532 : dwarf::DW_FORM_string);533 }534 // Then the counted list of files. The root file is file #0, then emit the535 // files as provide by .file directives.536 // MCDwarfFiles has an unused element [0] so use size() not size()+1.537 // But sometimes MCDwarfFiles is empty, in which case we still emit one file.538 MCOS->emitULEB128IntValue(MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size());539 // To accommodate assembler source written for DWARF v4 but trying to emit540 // v5: If we didn't see a root file explicitly, replicate file #1.541 assert((!RootFile.Name.empty() || MCDwarfFiles.size() >= 1) &&542 "No root file and no .file directives");543 emitOneV5FileEntry(MCOS, RootFile.Name.empty() ? MCDwarfFiles[1] : RootFile,544 HasAllMD5, HasAnySource, LineStr);545 for (unsigned i = 1; i < MCDwarfFiles.size(); ++i)546 emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasAnySource, LineStr);547}548 549std::pair<MCSymbol *, MCSymbol *>550MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,551 ArrayRef<char> StandardOpcodeLengths,552 std::optional<MCDwarfLineStr> &LineStr) const {553 MCContext &context = MCOS->getContext();554 555 // Create a symbol at the beginning of the line table.556 MCSymbol *LineStartSym = Label;557 if (!LineStartSym)558 LineStartSym = context.createTempSymbol();559 560 // Set the value of the symbol, as we are at the start of the line table.561 MCOS->emitDwarfLineStartLabel(LineStartSym);562 563 unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());564 565 MCSymbol *LineEndSym = MCOS->emitDwarfUnitLength("debug_line", "unit length");566 567 // Next 2 bytes is the Version.568 unsigned LineTableVersion = context.getDwarfVersion();569 MCOS->emitInt16(LineTableVersion);570 571 // In v5, we get address info next.572 if (LineTableVersion >= 5) {573 MCOS->emitInt8(context.getAsmInfo()->getCodePointerSize());574 MCOS->emitInt8(0); // Segment selector; same as EmitGenDwarfAranges.575 }576 577 // Create symbols for the start/end of the prologue.578 MCSymbol *ProStartSym = context.createTempSymbol("prologue_start");579 MCSymbol *ProEndSym = context.createTempSymbol("prologue_end");580 581 // Length of the prologue, is the next 4 bytes (8 bytes for DWARF64). This is582 // actually the length from after the length word, to the end of the prologue.583 MCOS->emitAbsoluteSymbolDiff(ProEndSym, ProStartSym, OffsetSize);584 585 MCOS->emitLabel(ProStartSym);586 587 // Parameters of the state machine, are next.588 MCOS->emitInt8(context.getAsmInfo()->getMinInstAlignment());589 // maximum_operations_per_instruction590 // For non-VLIW architectures this field is always 1.591 // FIXME: VLIW architectures need to update this field accordingly.592 if (LineTableVersion >= 4)593 MCOS->emitInt8(1);594 MCOS->emitInt8(DWARF2_LINE_DEFAULT_IS_STMT);595 MCOS->emitInt8(Params.DWARF2LineBase);596 MCOS->emitInt8(Params.DWARF2LineRange);597 MCOS->emitInt8(StandardOpcodeLengths.size() + 1);598 599 // Standard opcode lengths600 for (char Length : StandardOpcodeLengths)601 MCOS->emitInt8(Length);602 603 // Put out the directory and file tables. The formats vary depending on604 // the version.605 if (LineTableVersion >= 5)606 emitV5FileDirTables(MCOS, LineStr);607 else608 emitV2FileDirTables(MCOS);609 610 // This is the end of the prologue, so set the value of the symbol at the611 // end of the prologue (that was used in a previous expression).612 MCOS->emitLabel(ProEndSym);613 614 return std::make_pair(LineStartSym, LineEndSym);615}616 617void MCDwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,618 std::optional<MCDwarfLineStr> &LineStr) const {619 MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;620 621 // Put out the line tables.622 for (const auto &LineSec : MCLineSections.getMCLineEntries())623 emitOne(MCOS, LineSec.first, LineSec.second);624 625 // This is the end of the section, so set the value of the symbol at the end626 // of this section (that was used in a previous expression).627 MCOS->emitLabel(LineEndSym);628}629 630Expected<unsigned>631MCDwarfLineTable::tryGetFile(StringRef &Directory, StringRef &FileName,632 std::optional<MD5::MD5Result> Checksum,633 std::optional<StringRef> Source,634 uint16_t DwarfVersion, unsigned FileNumber) {635 return Header.tryGetFile(Directory, FileName, Checksum, Source, DwarfVersion,636 FileNumber);637}638 639static bool isRootFile(const MCDwarfFile &RootFile, StringRef &Directory,640 StringRef &FileName,641 std::optional<MD5::MD5Result> Checksum) {642 if (RootFile.Name.empty() || StringRef(RootFile.Name) != FileName)643 return false;644 return RootFile.Checksum == Checksum;645}646 647Expected<unsigned>648MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, StringRef &FileName,649 std::optional<MD5::MD5Result> Checksum,650 std::optional<StringRef> Source,651 uint16_t DwarfVersion, unsigned FileNumber) {652 if (Directory == CompilationDir)653 Directory = "";654 if (FileName.empty()) {655 FileName = "<stdin>";656 Directory = "";657 }658 assert(!FileName.empty());659 // Keep track of whether any or all files have an MD5 checksum.660 // If any files have embedded source, they all must.661 if (MCDwarfFiles.empty()) {662 trackMD5Usage(Checksum.has_value());663 HasAnySource |= Source.has_value();664 }665 if (DwarfVersion >= 5 && isRootFile(RootFile, Directory, FileName, Checksum))666 return 0;667 if (FileNumber == 0) {668 // File numbers start with 1 and/or after any file numbers669 // allocated by inline-assembler .file directives.670 FileNumber = MCDwarfFiles.empty() ? 1 : MCDwarfFiles.size();671 SmallString<256> Buffer;672 auto IterBool = SourceIdMap.insert(673 std::make_pair((Directory + Twine('\0') + FileName).toStringRef(Buffer),674 FileNumber));675 if (!IterBool.second)676 return IterBool.first->second;677 }678 // Make space for this FileNumber in the MCDwarfFiles vector if needed.679 if (FileNumber >= MCDwarfFiles.size())680 MCDwarfFiles.resize(FileNumber + 1);681 682 // Get the new MCDwarfFile slot for this FileNumber.683 MCDwarfFile &File = MCDwarfFiles[FileNumber];684 685 // It is an error to see the same number more than once.686 if (!File.Name.empty())687 return make_error<StringError>("file number already allocated",688 inconvertibleErrorCode());689 690 if (Directory.empty()) {691 // Separate the directory part from the basename of the FileName.692 StringRef tFileName = sys::path::filename(FileName);693 if (!tFileName.empty()) {694 Directory = sys::path::parent_path(FileName);695 if (!Directory.empty())696 FileName = tFileName;697 }698 }699 700 // Find or make an entry in the MCDwarfDirs vector for this Directory.701 // Capture directory name.702 unsigned DirIndex;703 if (Directory.empty()) {704 // For FileNames with no directories a DirIndex of 0 is used.705 DirIndex = 0;706 } else {707 DirIndex = llvm::find(MCDwarfDirs, Directory) - MCDwarfDirs.begin();708 if (DirIndex >= MCDwarfDirs.size())709 MCDwarfDirs.push_back(std::string(Directory));710 // The DirIndex is one based, as DirIndex of 0 is used for FileNames with711 // no directories. MCDwarfDirs[] is unlike MCDwarfFiles[] in that the712 // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames713 // are stored at MCDwarfFiles[FileNumber].Name .714 DirIndex++;715 }716 717 File.Name = std::string(FileName);718 File.DirIndex = DirIndex;719 File.Checksum = Checksum;720 trackMD5Usage(Checksum.has_value());721 File.Source = Source;722 if (Source.has_value())723 HasAnySource = true;724 725 // return the allocated FileNumber.726 return FileNumber;727}728 729/// Utility function to emit the encoding to a streamer.730void MCDwarfLineAddr::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,731 int64_t LineDelta, uint64_t AddrDelta) {732 MCContext &Context = MCOS->getContext();733 SmallString<256> Tmp;734 MCDwarfLineAddr::encode(Context, Params, LineDelta, AddrDelta, Tmp);735 MCOS->emitBytes(Tmp);736}737 738/// Given a special op, return the address skip amount (in units of739/// DWARF2_LINE_MIN_INSN_LENGTH).740static uint64_t SpecialAddr(MCDwarfLineTableParams Params, uint64_t op) {741 return (op - Params.DWARF2LineOpcodeBase) / Params.DWARF2LineRange;742}743 744/// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.745void MCDwarfLineAddr::encode(MCContext &Context, MCDwarfLineTableParams Params,746 int64_t LineDelta, uint64_t AddrDelta,747 SmallVectorImpl<char> &Out) {748 uint8_t Buf[16];749 uint64_t Temp, Opcode;750 bool NeedCopy = false;751 752 // The maximum address skip amount that can be encoded with a special op.753 uint64_t MaxSpecialAddrDelta = SpecialAddr(Params, 255);754 755 // Scale the address delta by the minimum instruction length.756 AddrDelta = ScaleAddrDelta(Context, AddrDelta);757 758 // A LineDelta of INT64_MAX is a signal that this is actually a759 // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the760 // end_sequence to emit the matrix entry.761 if (LineDelta == INT64_MAX) {762 if (AddrDelta == MaxSpecialAddrDelta)763 Out.push_back(dwarf::DW_LNS_const_add_pc);764 else if (AddrDelta) {765 Out.push_back(dwarf::DW_LNS_advance_pc);766 Out.append(Buf, Buf + encodeULEB128(AddrDelta, Buf));767 }768 Out.push_back(dwarf::DW_LNS_extended_op);769 Out.push_back(1);770 Out.push_back(dwarf::DW_LNE_end_sequence);771 return;772 }773 774 // Bias the line delta by the base.775 Temp = LineDelta - Params.DWARF2LineBase;776 777 // If the line increment is out of range of a special opcode, we must encode778 // it with DW_LNS_advance_line.779 if (Temp >= Params.DWARF2LineRange ||780 Temp + Params.DWARF2LineOpcodeBase > 255) {781 Out.push_back(dwarf::DW_LNS_advance_line);782 Out.append(Buf, Buf + encodeSLEB128(LineDelta, Buf));783 784 LineDelta = 0;785 Temp = 0 - Params.DWARF2LineBase;786 NeedCopy = true;787 }788 789 // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode.790 if (LineDelta == 0 && AddrDelta == 0) {791 Out.push_back(dwarf::DW_LNS_copy);792 return;793 }794 795 // Bias the opcode by the special opcode base.796 Temp += Params.DWARF2LineOpcodeBase;797 798 // Avoid overflow when addr_delta is large.799 if (AddrDelta < 256 + MaxSpecialAddrDelta) {800 // Try using a special opcode.801 Opcode = Temp + AddrDelta * Params.DWARF2LineRange;802 if (Opcode <= 255) {803 Out.push_back(Opcode);804 return;805 }806 807 // Try using DW_LNS_const_add_pc followed by special op.808 Opcode = Temp + (AddrDelta - MaxSpecialAddrDelta) * Params.DWARF2LineRange;809 if (Opcode <= 255) {810 Out.push_back(dwarf::DW_LNS_const_add_pc);811 Out.push_back(Opcode);812 return;813 }814 }815 816 // Otherwise use DW_LNS_advance_pc.817 Out.push_back(dwarf::DW_LNS_advance_pc);818 Out.append(Buf, Buf + encodeULEB128(AddrDelta, Buf));819 820 if (NeedCopy)821 Out.push_back(dwarf::DW_LNS_copy);822 else {823 assert(Temp <= 255 && "Buggy special opcode encoding.");824 Out.push_back(Temp);825 }826}827 828// Utility function to write a tuple for .debug_abbrev.829static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) {830 MCOS->emitULEB128IntValue(Name);831 MCOS->emitULEB128IntValue(Form);832}833 834// When generating dwarf for assembly source files this emits835// the data for .debug_abbrev section which contains three DIEs.836static void EmitGenDwarfAbbrev(MCStreamer *MCOS) {837 MCContext &context = MCOS->getContext();838 MCOS->switchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());839 840 // DW_TAG_compile_unit DIE abbrev (1).841 MCOS->emitULEB128IntValue(1);842 MCOS->emitULEB128IntValue(dwarf::DW_TAG_compile_unit);843 MCOS->emitInt8(dwarf::DW_CHILDREN_yes);844 dwarf::Form SecOffsetForm =845 context.getDwarfVersion() >= 4846 ? dwarf::DW_FORM_sec_offset847 : (context.getDwarfFormat() == dwarf::DWARF64 ? dwarf::DW_FORM_data8848 : dwarf::DW_FORM_data4);849 EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, SecOffsetForm);850 if (context.getGenDwarfSectionSyms().size() > 1 &&851 context.getDwarfVersion() >= 3) {852 EmitAbbrev(MCOS, dwarf::DW_AT_ranges, SecOffsetForm);853 } else {854 EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);855 EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);856 }857 EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);858 if (!context.getCompilationDir().empty())859 EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string);860 StringRef DwarfDebugFlags = context.getDwarfDebugFlags();861 if (!DwarfDebugFlags.empty())862 EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string);863 EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string);864 EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2);865 EmitAbbrev(MCOS, 0, 0);866 867 // DW_TAG_label DIE abbrev (2).868 MCOS->emitULEB128IntValue(2);869 MCOS->emitULEB128IntValue(dwarf::DW_TAG_label);870 MCOS->emitInt8(dwarf::DW_CHILDREN_no);871 EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);872 EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4);873 EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4);874 EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);875 EmitAbbrev(MCOS, 0, 0);876 877 // Terminate the abbreviations for this compilation unit.878 MCOS->emitInt8(0);879}880 881// When generating dwarf for assembly source files this emits the data for882// .debug_aranges section. This section contains a header and a table of pairs883// of PointerSize'ed values for the address and size of section(s) with line884// table entries.885static void EmitGenDwarfAranges(MCStreamer *MCOS,886 const MCSymbol *InfoSectionSymbol) {887 MCContext &context = MCOS->getContext();888 889 auto &Sections = context.getGenDwarfSectionSyms();890 891 MCOS->switchSection(context.getObjectFileInfo()->getDwarfARangesSection());892 893 unsigned UnitLengthBytes =894 dwarf::getUnitLengthFieldByteSize(context.getDwarfFormat());895 unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());896 897 // This will be the length of the .debug_aranges section, first account for898 // the size of each item in the header (see below where we emit these items).899 int Length = UnitLengthBytes + 2 + OffsetSize + 1 + 1;900 901 // Figure the padding after the header before the table of address and size902 // pairs who's values are PointerSize'ed.903 const MCAsmInfo *asmInfo = context.getAsmInfo();904 int AddrSize = asmInfo->getCodePointerSize();905 int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1));906 if (Pad == 2 * AddrSize)907 Pad = 0;908 Length += Pad;909 910 // Add the size of the pair of PointerSize'ed values for the address and size911 // of each section we have in the table.912 Length += 2 * AddrSize * Sections.size();913 // And the pair of terminating zeros.914 Length += 2 * AddrSize;915 916 // Emit the header for this section.917 if (context.getDwarfFormat() == dwarf::DWARF64)918 // The DWARF64 mark.919 MCOS->emitInt32(dwarf::DW_LENGTH_DWARF64);920 // The 4 (8 for DWARF64) byte length not including the length of the unit921 // length field itself.922 MCOS->emitIntValue(Length - UnitLengthBytes, OffsetSize);923 // The 2 byte version, which is 2.924 MCOS->emitInt16(2);925 // The 4 (8 for DWARF64) byte offset to the compile unit in the .debug_info926 // from the start of the .debug_info.927 if (InfoSectionSymbol)928 MCOS->emitSymbolValue(InfoSectionSymbol, OffsetSize,929 asmInfo->needsDwarfSectionOffsetDirective());930 else931 MCOS->emitIntValue(0, OffsetSize);932 // The 1 byte size of an address.933 MCOS->emitInt8(AddrSize);934 // The 1 byte size of a segment descriptor, we use a value of zero.935 MCOS->emitInt8(0);936 // Align the header with the padding if needed, before we put out the table.937 for(int i = 0; i < Pad; i++)938 MCOS->emitInt8(0);939 940 // Now emit the table of pairs of PointerSize'ed values for the section941 // addresses and sizes.942 for (MCSection *Sec : Sections) {943 const MCSymbol *StartSymbol = Sec->getBeginSymbol();944 MCSymbol *EndSymbol = Sec->getEndSymbol(context);945 assert(StartSymbol && "StartSymbol must not be NULL");946 assert(EndSymbol && "EndSymbol must not be NULL");947 948 const MCExpr *Addr = MCSymbolRefExpr::create(StartSymbol, context);949 const MCExpr *Size =950 makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);951 MCOS->emitValue(Addr, AddrSize);952 emitAbsValue(*MCOS, Size, AddrSize);953 }954 955 // And finally the pair of terminating zeros.956 MCOS->emitIntValue(0, AddrSize);957 MCOS->emitIntValue(0, AddrSize);958}959 960// When generating dwarf for assembly source files this emits the data for961// .debug_info section which contains three parts. The header, the compile_unit962// DIE and a list of label DIEs.963static void EmitGenDwarfInfo(MCStreamer *MCOS,964 const MCSymbol *AbbrevSectionSymbol,965 const MCSymbol *LineSectionSymbol,966 const MCSymbol *RangesSymbol) {967 MCContext &context = MCOS->getContext();968 969 MCOS->switchSection(context.getObjectFileInfo()->getDwarfInfoSection());970 971 // Create a symbol at the start and end of this section used in here for the972 // expression to calculate the length in the header.973 MCSymbol *InfoStart = context.createTempSymbol();974 MCOS->emitLabel(InfoStart);975 MCSymbol *InfoEnd = context.createTempSymbol();976 977 // First part: the header.978 979 unsigned UnitLengthBytes =980 dwarf::getUnitLengthFieldByteSize(context.getDwarfFormat());981 unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(context.getDwarfFormat());982 983 if (context.getDwarfFormat() == dwarf::DWARF64)984 // Emit DWARF64 mark.985 MCOS->emitInt32(dwarf::DW_LENGTH_DWARF64);986 987 // The 4 (8 for DWARF64) byte total length of the information for this988 // compilation unit, not including the unit length field itself.989 const MCExpr *Length =990 makeEndMinusStartExpr(context, *InfoStart, *InfoEnd, UnitLengthBytes);991 emitAbsValue(*MCOS, Length, OffsetSize);992 993 // The 2 byte DWARF version.994 MCOS->emitInt16(context.getDwarfVersion());995 996 // The DWARF v5 header has unit type, address size, abbrev offset.997 // Earlier versions have abbrev offset, address size.998 const MCAsmInfo &AsmInfo = *context.getAsmInfo();999 int AddrSize = AsmInfo.getCodePointerSize();1000 if (context.getDwarfVersion() >= 5) {1001 MCOS->emitInt8(dwarf::DW_UT_compile);1002 MCOS->emitInt8(AddrSize);1003 }1004 // The 4 (8 for DWARF64) byte offset to the debug abbrevs from the start of1005 // the .debug_abbrev.1006 if (AbbrevSectionSymbol)1007 MCOS->emitSymbolValue(AbbrevSectionSymbol, OffsetSize,1008 AsmInfo.needsDwarfSectionOffsetDirective());1009 else1010 // Since the abbrevs are at the start of the section, the offset is zero.1011 MCOS->emitIntValue(0, OffsetSize);1012 if (context.getDwarfVersion() <= 4)1013 MCOS->emitInt8(AddrSize);1014 1015 // Second part: the compile_unit DIE.1016 1017 // The DW_TAG_compile_unit DIE abbrev (1).1018 MCOS->emitULEB128IntValue(1);1019 1020 // DW_AT_stmt_list, a 4 (8 for DWARF64) byte offset from the start of the1021 // .debug_line section.1022 if (LineSectionSymbol)1023 MCOS->emitSymbolValue(LineSectionSymbol, OffsetSize,1024 AsmInfo.needsDwarfSectionOffsetDirective());1025 else1026 // The line table is at the start of the section, so the offset is zero.1027 MCOS->emitIntValue(0, OffsetSize);1028 1029 if (RangesSymbol) {1030 // There are multiple sections containing code, so we must use1031 // .debug_ranges/.debug_rnglists. AT_ranges, the 4/8 byte offset from the1032 // start of the .debug_ranges/.debug_rnglists.1033 MCOS->emitSymbolValue(RangesSymbol, OffsetSize);1034 } else {1035 // If we only have one non-empty code section, we can use the simpler1036 // AT_low_pc and AT_high_pc attributes.1037 1038 // Find the first (and only) non-empty text section1039 auto &Sections = context.getGenDwarfSectionSyms();1040 const auto TextSection = Sections.begin();1041 assert(TextSection != Sections.end() && "No text section found");1042 1043 MCSymbol *StartSymbol = (*TextSection)->getBeginSymbol();1044 MCSymbol *EndSymbol = (*TextSection)->getEndSymbol(context);1045 assert(StartSymbol && "StartSymbol must not be NULL");1046 assert(EndSymbol && "EndSymbol must not be NULL");1047 1048 // AT_low_pc, the first address of the default .text section.1049 const MCExpr *Start = MCSymbolRefExpr::create(StartSymbol, context);1050 MCOS->emitValue(Start, AddrSize);1051 1052 // AT_high_pc, the last address of the default .text section.1053 const MCExpr *End = MCSymbolRefExpr::create(EndSymbol, context);1054 MCOS->emitValue(End, AddrSize);1055 }1056 1057 // AT_name, the name of the source file. Reconstruct from the first directory1058 // and file table entries.1059 const SmallVectorImpl<std::string> &MCDwarfDirs = context.getMCDwarfDirs();1060 if (MCDwarfDirs.size() > 0) {1061 MCOS->emitBytes(MCDwarfDirs[0]);1062 MCOS->emitBytes(sys::path::get_separator());1063 }1064 const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles = context.getMCDwarfFiles();1065 // MCDwarfFiles might be empty if we have an empty source file.1066 // If it's not empty, [0] is unused and [1] is the first actual file.1067 assert(MCDwarfFiles.empty() || MCDwarfFiles.size() >= 2);1068 const MCDwarfFile &RootFile =1069 MCDwarfFiles.empty()1070 ? context.getMCDwarfLineTable(/*CUID=*/0).getRootFile()1071 : MCDwarfFiles[1];1072 MCOS->emitBytes(RootFile.Name);1073 MCOS->emitInt8(0); // NULL byte to terminate the string.1074 1075 // AT_comp_dir, the working directory the assembly was done in.1076 if (!context.getCompilationDir().empty()) {1077 MCOS->emitBytes(context.getCompilationDir());1078 MCOS->emitInt8(0); // NULL byte to terminate the string.1079 }1080 1081 // AT_APPLE_flags, the command line arguments of the assembler tool.1082 StringRef DwarfDebugFlags = context.getDwarfDebugFlags();1083 if (!DwarfDebugFlags.empty()){1084 MCOS->emitBytes(DwarfDebugFlags);1085 MCOS->emitInt8(0); // NULL byte to terminate the string.1086 }1087 1088 // AT_producer, the version of the assembler tool.1089 StringRef DwarfDebugProducer = context.getDwarfDebugProducer();1090 if (!DwarfDebugProducer.empty())1091 MCOS->emitBytes(DwarfDebugProducer);1092 else1093 MCOS->emitBytes(StringRef("llvm-mc (based on LLVM " PACKAGE_VERSION ")"));1094 MCOS->emitInt8(0); // NULL byte to terminate the string.1095 1096 // AT_language, a 4 byte value. We use DW_LANG_Mips_Assembler as the dwarf21097 // draft has no standard code for assembler.1098 MCOS->emitInt16(dwarf::DW_LANG_Mips_Assembler);1099 1100 // Third part: the list of label DIEs.1101 1102 // Loop on saved info for dwarf labels and create the DIEs for them.1103 const std::vector<MCGenDwarfLabelEntry> &Entries =1104 MCOS->getContext().getMCGenDwarfLabelEntries();1105 for (const auto &Entry : Entries) {1106 // The DW_TAG_label DIE abbrev (2).1107 MCOS->emitULEB128IntValue(2);1108 1109 // AT_name, of the label without any leading underbar.1110 MCOS->emitBytes(Entry.getName());1111 MCOS->emitInt8(0); // NULL byte to terminate the string.1112 1113 // AT_decl_file, index into the file table.1114 MCOS->emitInt32(Entry.getFileNumber());1115 1116 // AT_decl_line, source line number.1117 MCOS->emitInt32(Entry.getLineNumber());1118 1119 // AT_low_pc, start address of the label.1120 const auto *AT_low_pc = MCSymbolRefExpr::create(Entry.getLabel(), context);1121 MCOS->emitValue(AT_low_pc, AddrSize);1122 }1123 1124 // Add the NULL DIE terminating the Compile Unit DIE's.1125 MCOS->emitInt8(0);1126 1127 // Now set the value of the symbol at the end of the info section.1128 MCOS->emitLabel(InfoEnd);1129}1130 1131// When generating dwarf for assembly source files this emits the data for1132// .debug_ranges section. We only emit one range list, which spans all of the1133// executable sections of this file.1134static MCSymbol *emitGenDwarfRanges(MCStreamer *MCOS) {1135 MCContext &context = MCOS->getContext();1136 auto &Sections = context.getGenDwarfSectionSyms();1137 1138 const MCAsmInfo *AsmInfo = context.getAsmInfo();1139 int AddrSize = AsmInfo->getCodePointerSize();1140 MCSymbol *RangesSymbol;1141 1142 if (MCOS->getContext().getDwarfVersion() >= 5) {1143 MCOS->switchSection(context.getObjectFileInfo()->getDwarfRnglistsSection());1144 MCSymbol *EndSymbol = mcdwarf::emitListsTableHeaderStart(*MCOS);1145 MCOS->AddComment("Offset entry count");1146 MCOS->emitInt32(0);1147 RangesSymbol = context.createTempSymbol("debug_rnglist0_start");1148 MCOS->emitLabel(RangesSymbol);1149 for (MCSection *Sec : Sections) {1150 const MCSymbol *StartSymbol = Sec->getBeginSymbol();1151 const MCSymbol *EndSymbol = Sec->getEndSymbol(context);1152 const MCExpr *SectionStartAddr =1153 MCSymbolRefExpr::create(StartSymbol, context);1154 const MCExpr *SectionSize =1155 makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);1156 MCOS->emitInt8(dwarf::DW_RLE_start_length);1157 MCOS->emitValue(SectionStartAddr, AddrSize);1158 MCOS->emitULEB128Value(SectionSize);1159 }1160 MCOS->emitInt8(dwarf::DW_RLE_end_of_list);1161 MCOS->emitLabel(EndSymbol);1162 } else {1163 MCOS->switchSection(context.getObjectFileInfo()->getDwarfRangesSection());1164 RangesSymbol = context.createTempSymbol("debug_ranges_start");1165 MCOS->emitLabel(RangesSymbol);1166 for (MCSection *Sec : Sections) {1167 const MCSymbol *StartSymbol = Sec->getBeginSymbol();1168 const MCSymbol *EndSymbol = Sec->getEndSymbol(context);1169 1170 // Emit a base address selection entry for the section start.1171 const MCExpr *SectionStartAddr =1172 MCSymbolRefExpr::create(StartSymbol, context);1173 MCOS->emitFill(AddrSize, 0xFF);1174 MCOS->emitValue(SectionStartAddr, AddrSize);1175 1176 // Emit a range list entry spanning this section.1177 const MCExpr *SectionSize =1178 makeEndMinusStartExpr(context, *StartSymbol, *EndSymbol, 0);1179 MCOS->emitIntValue(0, AddrSize);1180 emitAbsValue(*MCOS, SectionSize, AddrSize);1181 }1182 1183 // Emit end of list entry1184 MCOS->emitIntValue(0, AddrSize);1185 MCOS->emitIntValue(0, AddrSize);1186 }1187 1188 return RangesSymbol;1189}1190 1191//1192// When generating dwarf for assembly source files this emits the Dwarf1193// sections.1194//1195void MCGenDwarfInfo::Emit(MCStreamer *MCOS) {1196 MCContext &context = MCOS->getContext();1197 1198 // Create the dwarf sections in this order (.debug_line already created).1199 const MCAsmInfo *AsmInfo = context.getAsmInfo();1200 bool CreateDwarfSectionSymbols =1201 AsmInfo->doesDwarfUseRelocationsAcrossSections();1202 MCSymbol *LineSectionSymbol = nullptr;1203 if (CreateDwarfSectionSymbols)1204 LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0);1205 MCSymbol *AbbrevSectionSymbol = nullptr;1206 MCSymbol *InfoSectionSymbol = nullptr;1207 MCSymbol *RangesSymbol = nullptr;1208 1209 // Create end symbols for each section, and remove empty sections1210 MCOS->getContext().finalizeDwarfSections(*MCOS);1211 1212 // If there are no sections to generate debug info for, we don't need1213 // to do anything1214 if (MCOS->getContext().getGenDwarfSectionSyms().empty())1215 return;1216 1217 // We only use the .debug_ranges section if we have multiple code sections,1218 // and we are emitting a DWARF version which supports it.1219 const bool UseRangesSection =1220 MCOS->getContext().getGenDwarfSectionSyms().size() > 1 &&1221 MCOS->getContext().getDwarfVersion() >= 3;1222 CreateDwarfSectionSymbols |= UseRangesSection;1223 1224 MCOS->switchSection(context.getObjectFileInfo()->getDwarfInfoSection());1225 if (CreateDwarfSectionSymbols) {1226 InfoSectionSymbol = context.createTempSymbol();1227 MCOS->emitLabel(InfoSectionSymbol);1228 }1229 MCOS->switchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());1230 if (CreateDwarfSectionSymbols) {1231 AbbrevSectionSymbol = context.createTempSymbol();1232 MCOS->emitLabel(AbbrevSectionSymbol);1233 }1234 1235 MCOS->switchSection(context.getObjectFileInfo()->getDwarfARangesSection());1236 1237 // Output the data for .debug_aranges section.1238 EmitGenDwarfAranges(MCOS, InfoSectionSymbol);1239 1240 if (UseRangesSection) {1241 RangesSymbol = emitGenDwarfRanges(MCOS);1242 assert(RangesSymbol);1243 }1244 1245 // Output the data for .debug_abbrev section.1246 EmitGenDwarfAbbrev(MCOS);1247 1248 // Output the data for .debug_info section.1249 EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, RangesSymbol);1250}1251 1252//1253// When generating dwarf for assembly source files this is called when symbol1254// for a label is created. If this symbol is not a temporary and is in the1255// section that dwarf is being generated for, save the needed info to create1256// a dwarf label.1257//1258void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS,1259 SourceMgr &SrcMgr, SMLoc &Loc) {1260 // We won't create dwarf labels for temporary symbols.1261 if (Symbol->isTemporary())1262 return;1263 MCContext &context = MCOS->getContext();1264 // We won't create dwarf labels for symbols in sections that we are not1265 // generating debug info for.1266 if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSectionOnly()))1267 return;1268 1269 // The dwarf label's name does not have the symbol name's leading1270 // underbar if any.1271 StringRef Name = Symbol->getName();1272 if (Name.starts_with("_"))1273 Name = Name.substr(1, Name.size()-1);1274 1275 // Get the dwarf file number to be used for the dwarf label.1276 unsigned FileNumber = context.getGenDwarfFileNumber();1277 1278 // Finding the line number is the expensive part which is why we just don't1279 // pass it in as for some symbols we won't create a dwarf label.1280 unsigned CurBuffer = SrcMgr.FindBufferContainingLoc(Loc);1281 unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer);1282 1283 // We create a temporary symbol for use for the AT_high_pc and AT_low_pc1284 // values so that they don't have things like an ARM thumb bit from the1285 // original symbol. So when used they won't get a low bit set after1286 // relocation.1287 MCSymbol *Label = context.createTempSymbol();1288 MCOS->emitLabel(Label);1289 1290 // Create and entry for the info and add it to the other entries.1291 MCOS->getContext().addMCGenDwarfLabelEntry(1292 MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label));1293}1294 1295static int getDataAlignmentFactor(MCStreamer &streamer) {1296 MCContext &context = streamer.getContext();1297 const MCAsmInfo *asmInfo = context.getAsmInfo();1298 int size = asmInfo->getCalleeSaveStackSlotSize();1299 if (asmInfo->isStackGrowthDirectionUp())1300 return size;1301 else1302 return -size;1303}1304 1305static unsigned getSizeForEncoding(MCStreamer &streamer,1306 unsigned symbolEncoding) {1307 MCContext &context = streamer.getContext();1308 unsigned format = symbolEncoding & 0x0f;1309 switch (format) {1310 default: llvm_unreachable("Unknown Encoding");1311 case dwarf::DW_EH_PE_absptr:1312 case dwarf::DW_EH_PE_signed:1313 return context.getAsmInfo()->getCodePointerSize();1314 case dwarf::DW_EH_PE_udata2:1315 case dwarf::DW_EH_PE_sdata2:1316 return 2;1317 case dwarf::DW_EH_PE_udata4:1318 case dwarf::DW_EH_PE_sdata4:1319 return 4;1320 case dwarf::DW_EH_PE_udata8:1321 case dwarf::DW_EH_PE_sdata8:1322 return 8;1323 }1324}1325 1326static void emitFDESymbol(MCObjectStreamer &streamer, const MCSymbol &symbol,1327 unsigned symbolEncoding, bool isEH) {1328 MCContext &context = streamer.getContext();1329 const MCAsmInfo *asmInfo = context.getAsmInfo();1330 const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol,1331 symbolEncoding,1332 streamer);1333 unsigned size = getSizeForEncoding(streamer, symbolEncoding);1334 if (asmInfo->doDwarfFDESymbolsUseAbsDiff() && isEH)1335 emitAbsValue(streamer, v, size);1336 else1337 streamer.emitValue(v, size);1338}1339 1340static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,1341 unsigned symbolEncoding) {1342 MCContext &context = streamer.getContext();1343 const MCAsmInfo *asmInfo = context.getAsmInfo();1344 const MCExpr *v = asmInfo->getExprForPersonalitySymbol(&symbol,1345 symbolEncoding,1346 streamer);1347 unsigned size = getSizeForEncoding(streamer, symbolEncoding);1348 streamer.emitValue(v, size);1349}1350 1351namespace {1352 1353class FrameEmitterImpl {1354 int64_t CFAOffset = 0;1355 int64_t InitialCFAOffset = 0;1356 bool IsEH;1357 MCObjectStreamer &Streamer;1358 1359public:1360 FrameEmitterImpl(bool IsEH, MCObjectStreamer &Streamer)1361 : IsEH(IsEH), Streamer(Streamer) {}1362 1363 /// Emit the unwind information in a compact way.1364 void EmitCompactUnwind(const MCDwarfFrameInfo &frame);1365 1366 const MCSymbol &EmitCIE(const MCDwarfFrameInfo &F);1367 void EmitFDE(const MCSymbol &cieStart, const MCDwarfFrameInfo &frame,1368 bool LastInSection, const MCSymbol &SectionStart);1369 void emitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,1370 MCSymbol *BaseLabel);1371 void emitCFIInstruction(const MCCFIInstruction &Instr);1372};1373 1374} // end anonymous namespace1375 1376static void emitEncodingByte(MCObjectStreamer &Streamer, unsigned Encoding) {1377 Streamer.emitInt8(Encoding);1378}1379 1380void FrameEmitterImpl::emitCFIInstruction(const MCCFIInstruction &Instr) {1381 int dataAlignmentFactor = getDataAlignmentFactor(Streamer);1382 auto *MRI = Streamer.getContext().getRegisterInfo();1383 1384 switch (Instr.getOperation()) {1385 case MCCFIInstruction::OpRegister: {1386 unsigned Reg1 = Instr.getRegister();1387 unsigned Reg2 = Instr.getRegister2();1388 if (!IsEH) {1389 Reg1 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg1);1390 Reg2 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg2);1391 }1392 Streamer.emitInt8(dwarf::DW_CFA_register);1393 Streamer.emitULEB128IntValue(Reg1);1394 Streamer.emitULEB128IntValue(Reg2);1395 return;1396 }1397 case MCCFIInstruction::OpWindowSave:1398 Streamer.emitInt8(dwarf::DW_CFA_GNU_window_save);1399 return;1400 1401 case MCCFIInstruction::OpNegateRAState:1402 Streamer.emitInt8(dwarf::DW_CFA_AARCH64_negate_ra_state);1403 return;1404 1405 case MCCFIInstruction::OpNegateRAStateWithPC:1406 Streamer.emitInt8(dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc);1407 return;1408 1409 case MCCFIInstruction::OpUndefined: {1410 unsigned Reg = Instr.getRegister();1411 Streamer.emitInt8(dwarf::DW_CFA_undefined);1412 Streamer.emitULEB128IntValue(Reg);1413 return;1414 }1415 case MCCFIInstruction::OpAdjustCfaOffset:1416 case MCCFIInstruction::OpDefCfaOffset: {1417 const bool IsRelative =1418 Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset;1419 1420 Streamer.emitInt8(dwarf::DW_CFA_def_cfa_offset);1421 1422 if (IsRelative)1423 CFAOffset += Instr.getOffset();1424 else1425 CFAOffset = Instr.getOffset();1426 1427 Streamer.emitULEB128IntValue(CFAOffset);1428 1429 return;1430 }1431 case MCCFIInstruction::OpDefCfa: {1432 unsigned Reg = Instr.getRegister();1433 if (!IsEH)1434 Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);1435 Streamer.emitInt8(dwarf::DW_CFA_def_cfa);1436 Streamer.emitULEB128IntValue(Reg);1437 CFAOffset = Instr.getOffset();1438 Streamer.emitULEB128IntValue(CFAOffset);1439 1440 return;1441 }1442 case MCCFIInstruction::OpDefCfaRegister: {1443 unsigned Reg = Instr.getRegister();1444 if (!IsEH)1445 Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);1446 Streamer.emitInt8(dwarf::DW_CFA_def_cfa_register);1447 Streamer.emitULEB128IntValue(Reg);1448 1449 return;1450 }1451 // TODO: Implement `_sf` variants if/when they need to be emitted.1452 case MCCFIInstruction::OpLLVMDefAspaceCfa: {1453 unsigned Reg = Instr.getRegister();1454 if (!IsEH)1455 Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);1456 Streamer.emitIntValue(dwarf::DW_CFA_LLVM_def_aspace_cfa, 1);1457 Streamer.emitULEB128IntValue(Reg);1458 CFAOffset = Instr.getOffset();1459 Streamer.emitULEB128IntValue(CFAOffset);1460 Streamer.emitULEB128IntValue(Instr.getAddressSpace());1461 1462 return;1463 }1464 case MCCFIInstruction::OpOffset:1465 case MCCFIInstruction::OpRelOffset: {1466 const bool IsRelative =1467 Instr.getOperation() == MCCFIInstruction::OpRelOffset;1468 1469 unsigned Reg = Instr.getRegister();1470 if (!IsEH)1471 Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);1472 1473 int64_t Offset = Instr.getOffset();1474 if (IsRelative)1475 Offset -= CFAOffset;1476 Offset = Offset / dataAlignmentFactor;1477 1478 if (Offset < 0) {1479 Streamer.emitInt8(dwarf::DW_CFA_offset_extended_sf);1480 Streamer.emitULEB128IntValue(Reg);1481 Streamer.emitSLEB128IntValue(Offset);1482 } else if (Reg < 64) {1483 Streamer.emitInt8(dwarf::DW_CFA_offset + Reg);1484 Streamer.emitULEB128IntValue(Offset);1485 } else {1486 Streamer.emitInt8(dwarf::DW_CFA_offset_extended);1487 Streamer.emitULEB128IntValue(Reg);1488 Streamer.emitULEB128IntValue(Offset);1489 }1490 return;1491 }1492 case MCCFIInstruction::OpRememberState:1493 Streamer.emitInt8(dwarf::DW_CFA_remember_state);1494 return;1495 case MCCFIInstruction::OpRestoreState:1496 Streamer.emitInt8(dwarf::DW_CFA_restore_state);1497 return;1498 case MCCFIInstruction::OpSameValue: {1499 unsigned Reg = Instr.getRegister();1500 Streamer.emitInt8(dwarf::DW_CFA_same_value);1501 Streamer.emitULEB128IntValue(Reg);1502 return;1503 }1504 case MCCFIInstruction::OpRestore: {1505 unsigned Reg = Instr.getRegister();1506 if (!IsEH)1507 Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);1508 if (Reg < 64) {1509 Streamer.emitInt8(dwarf::DW_CFA_restore | Reg);1510 } else {1511 Streamer.emitInt8(dwarf::DW_CFA_restore_extended);1512 Streamer.emitULEB128IntValue(Reg);1513 }1514 return;1515 }1516 case MCCFIInstruction::OpGnuArgsSize:1517 Streamer.emitInt8(dwarf::DW_CFA_GNU_args_size);1518 Streamer.emitULEB128IntValue(Instr.getOffset());1519 return;1520 1521 case MCCFIInstruction::OpEscape:1522 Streamer.emitBytes(Instr.getValues());1523 return;1524 case MCCFIInstruction::OpLabel:1525 Streamer.emitLabel(Instr.getCfiLabel(), Instr.getLoc());1526 return;1527 case MCCFIInstruction::OpValOffset: {1528 unsigned Reg = Instr.getRegister();1529 if (!IsEH)1530 Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);1531 1532 int Offset = Instr.getOffset();1533 Offset = Offset / dataAlignmentFactor;1534 1535 if (Offset < 0) {1536 Streamer.emitInt8(dwarf::DW_CFA_val_offset_sf);1537 Streamer.emitULEB128IntValue(Reg);1538 Streamer.emitSLEB128IntValue(Offset);1539 } else {1540 Streamer.emitInt8(dwarf::DW_CFA_val_offset);1541 Streamer.emitULEB128IntValue(Reg);1542 Streamer.emitULEB128IntValue(Offset);1543 }1544 return;1545 }1546 }1547 llvm_unreachable("Unhandled case in switch");1548}1549 1550/// Emit frame instructions to describe the layout of the frame.1551void FrameEmitterImpl::emitCFIInstructions(ArrayRef<MCCFIInstruction> Instrs,1552 MCSymbol *BaseLabel) {1553 for (const MCCFIInstruction &Instr : Instrs) {1554 MCSymbol *Label = Instr.getLabel();1555 // Throw out move if the label is invalid.1556 if (Label && !Label->isDefined()) continue; // Not emitted, in dead code.1557 1558 // Advance row if new location.1559 if (BaseLabel && Label) {1560 MCSymbol *ThisSym = Label;1561 if (ThisSym != BaseLabel) {1562 Streamer.emitDwarfAdvanceFrameAddr(BaseLabel, ThisSym, Instr.getLoc());1563 BaseLabel = ThisSym;1564 }1565 }1566 1567 emitCFIInstruction(Instr);1568 }1569}1570 1571/// Emit the unwind information in a compact way.1572void FrameEmitterImpl::EmitCompactUnwind(const MCDwarfFrameInfo &Frame) {1573 MCContext &Context = Streamer.getContext();1574 const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();1575 1576 // range-start range-length compact-unwind-enc personality-func lsda1577 // _foo LfooEnd-_foo 0x00000023 0 01578 // _bar LbarEnd-_bar 0x00000025 __gxx_personality except_tab11579 //1580 // .section __LD,__compact_unwind,regular,debug1581 //1582 // # compact unwind for _foo1583 // .quad _foo1584 // .set L1,LfooEnd-_foo1585 // .long L11586 // .long 0x010100011587 // .quad 01588 // .quad 01589 //1590 // # compact unwind for _bar1591 // .quad _bar1592 // .set L2,LbarEnd-_bar1593 // .long L21594 // .long 0x010200111595 // .quad __gxx_personality1596 // .quad except_tab11597 1598 uint32_t Encoding = Frame.CompactUnwindEncoding;1599 if (!Encoding) return;1600 bool DwarfEHFrameOnly = (Encoding == MOFI->getCompactUnwindDwarfEHFrameOnly());1601 1602 // The encoding needs to know we have an LSDA.1603 if (!DwarfEHFrameOnly && Frame.Lsda)1604 Encoding |= 0x40000000;1605 1606 // Range Start1607 unsigned FDEEncoding = MOFI->getFDEEncoding();1608 unsigned Size = getSizeForEncoding(Streamer, FDEEncoding);1609 Streamer.emitSymbolValue(Frame.Begin, Size);1610 1611 // Range Length1612 const MCExpr *Range =1613 makeEndMinusStartExpr(Context, *Frame.Begin, *Frame.End, 0);1614 emitAbsValue(Streamer, Range, 4);1615 1616 // Compact Encoding1617 Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4);1618 Streamer.emitIntValue(Encoding, Size);1619 1620 // Personality Function1621 Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr);1622 if (!DwarfEHFrameOnly && Frame.Personality)1623 Streamer.emitSymbolValue(Frame.Personality, Size);1624 else1625 Streamer.emitIntValue(0, Size); // No personality fn1626 1627 // LSDA1628 Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding);1629 if (!DwarfEHFrameOnly && Frame.Lsda)1630 Streamer.emitSymbolValue(Frame.Lsda, Size);1631 else1632 Streamer.emitIntValue(0, Size); // No LSDA1633}1634 1635static unsigned getCIEVersion(bool IsEH, unsigned DwarfVersion) {1636 if (IsEH)1637 return 1;1638 switch (DwarfVersion) {1639 case 2:1640 return 1;1641 case 3:1642 return 3;1643 case 4:1644 case 5:1645 return 4;1646 }1647 llvm_unreachable("Unknown version");1648}1649 1650const MCSymbol &FrameEmitterImpl::EmitCIE(const MCDwarfFrameInfo &Frame) {1651 MCContext &context = Streamer.getContext();1652 const MCRegisterInfo *MRI = context.getRegisterInfo();1653 const MCObjectFileInfo *MOFI = context.getObjectFileInfo();1654 1655 MCSymbol *sectionStart = context.createTempSymbol();1656 Streamer.emitLabel(sectionStart);1657 1658 MCSymbol *sectionEnd = context.createTempSymbol();1659 1660 dwarf::DwarfFormat Format = IsEH ? dwarf::DWARF32 : context.getDwarfFormat();1661 unsigned UnitLengthBytes = dwarf::getUnitLengthFieldByteSize(Format);1662 unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(Format);1663 bool IsDwarf64 = Format == dwarf::DWARF64;1664 1665 if (IsDwarf64)1666 // DWARF64 mark1667 Streamer.emitInt32(dwarf::DW_LENGTH_DWARF64);1668 1669 // Length1670 const MCExpr *Length = makeEndMinusStartExpr(context, *sectionStart,1671 *sectionEnd, UnitLengthBytes);1672 emitAbsValue(Streamer, Length, OffsetSize);1673 1674 // CIE ID1675 uint64_t CIE_ID =1676 IsEH ? 0 : (IsDwarf64 ? dwarf::DW64_CIE_ID : dwarf::DW_CIE_ID);1677 Streamer.emitIntValue(CIE_ID, OffsetSize);1678 1679 // Version1680 uint8_t CIEVersion = getCIEVersion(IsEH, context.getDwarfVersion());1681 Streamer.emitInt8(CIEVersion);1682 1683 if (IsEH) {1684 SmallString<8> Augmentation;1685 Augmentation += "z";1686 if (Frame.Personality)1687 Augmentation += "P";1688 if (Frame.Lsda)1689 Augmentation += "L";1690 Augmentation += "R";1691 if (Frame.IsSignalFrame)1692 Augmentation += "S";1693 if (Frame.IsBKeyFrame)1694 Augmentation += "B";1695 if (Frame.IsMTETaggedFrame)1696 Augmentation += "G";1697 Streamer.emitBytes(Augmentation);1698 }1699 Streamer.emitInt8(0);1700 1701 if (CIEVersion >= 4) {1702 // Address Size1703 Streamer.emitInt8(context.getAsmInfo()->getCodePointerSize());1704 1705 // Segment Descriptor Size1706 Streamer.emitInt8(0);1707 }1708 1709 // Code Alignment Factor1710 Streamer.emitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment());1711 1712 // Data Alignment Factor1713 Streamer.emitSLEB128IntValue(getDataAlignmentFactor(Streamer));1714 1715 // Return Address Register1716 unsigned RAReg = Frame.RAReg;1717 if (RAReg == static_cast<unsigned>(INT_MAX))1718 RAReg = MRI->getDwarfRegNum(MRI->getRARegister(), IsEH);1719 1720 if (CIEVersion == 1) {1721 assert(RAReg <= 255 &&1722 "DWARF 2 encodes return_address_register in one byte");1723 Streamer.emitInt8(RAReg);1724 } else {1725 Streamer.emitULEB128IntValue(RAReg);1726 }1727 1728 // Augmentation Data Length (optional)1729 unsigned augmentationLength = 0;1730 if (IsEH) {1731 if (Frame.Personality) {1732 // Personality Encoding1733 augmentationLength += 1;1734 // Personality1735 augmentationLength +=1736 getSizeForEncoding(Streamer, Frame.PersonalityEncoding);1737 }1738 if (Frame.Lsda)1739 augmentationLength += 1;1740 // Encoding of the FDE pointers1741 augmentationLength += 1;1742 1743 Streamer.emitULEB128IntValue(augmentationLength);1744 1745 // Augmentation Data (optional)1746 if (Frame.Personality) {1747 // Personality Encoding1748 emitEncodingByte(Streamer, Frame.PersonalityEncoding);1749 // Personality1750 EmitPersonality(Streamer, *Frame.Personality, Frame.PersonalityEncoding);1751 }1752 1753 if (Frame.Lsda)1754 emitEncodingByte(Streamer, Frame.LsdaEncoding);1755 1756 // Encoding of the FDE pointers1757 emitEncodingByte(Streamer, MOFI->getFDEEncoding());1758 }1759 1760 // Initial Instructions1761 1762 const MCAsmInfo *MAI = context.getAsmInfo();1763 if (!Frame.IsSimple) {1764 const std::vector<MCCFIInstruction> &Instructions =1765 MAI->getInitialFrameState();1766 emitCFIInstructions(Instructions, nullptr);1767 }1768 1769 InitialCFAOffset = CFAOffset;1770 1771 // Padding1772 Streamer.emitValueToAlignment(Align(IsEH ? 4 : MAI->getCodePointerSize()));1773 1774 Streamer.emitLabel(sectionEnd);1775 return *sectionStart;1776}1777 1778void FrameEmitterImpl::EmitFDE(const MCSymbol &cieStart,1779 const MCDwarfFrameInfo &frame,1780 bool LastInSection,1781 const MCSymbol &SectionStart) {1782 MCContext &context = Streamer.getContext();1783 MCSymbol *fdeStart = context.createTempSymbol();1784 MCSymbol *fdeEnd = context.createTempSymbol();1785 const MCObjectFileInfo *MOFI = context.getObjectFileInfo();1786 1787 CFAOffset = InitialCFAOffset;1788 1789 dwarf::DwarfFormat Format = IsEH ? dwarf::DWARF32 : context.getDwarfFormat();1790 unsigned OffsetSize = dwarf::getDwarfOffsetByteSize(Format);1791 1792 if (Format == dwarf::DWARF64)1793 // DWARF64 mark1794 Streamer.emitInt32(dwarf::DW_LENGTH_DWARF64);1795 1796 // Length1797 const MCExpr *Length = makeEndMinusStartExpr(context, *fdeStart, *fdeEnd, 0);1798 emitAbsValue(Streamer, Length, OffsetSize);1799 1800 Streamer.emitLabel(fdeStart);1801 1802 // CIE Pointer1803 const MCAsmInfo *asmInfo = context.getAsmInfo();1804 if (IsEH) {1805 const MCExpr *offset =1806 makeEndMinusStartExpr(context, cieStart, *fdeStart, 0);1807 emitAbsValue(Streamer, offset, OffsetSize);1808 } else if (!asmInfo->doesDwarfUseRelocationsAcrossSections()) {1809 const MCExpr *offset =1810 makeEndMinusStartExpr(context, SectionStart, cieStart, 0);1811 emitAbsValue(Streamer, offset, OffsetSize);1812 } else {1813 Streamer.emitSymbolValue(&cieStart, OffsetSize,1814 asmInfo->needsDwarfSectionOffsetDirective());1815 }1816 1817 // PC Begin1818 unsigned PCEncoding =1819 IsEH ? MOFI->getFDEEncoding() : (unsigned)dwarf::DW_EH_PE_absptr;1820 unsigned PCSize = getSizeForEncoding(Streamer, PCEncoding);1821 emitFDESymbol(Streamer, *frame.Begin, PCEncoding, IsEH);1822 1823 // PC Range1824 const MCExpr *Range =1825 makeEndMinusStartExpr(context, *frame.Begin, *frame.End, 0);1826 emitAbsValue(Streamer, Range, PCSize);1827 1828 if (IsEH) {1829 // Augmentation Data Length1830 unsigned augmentationLength = 0;1831 1832 if (frame.Lsda)1833 augmentationLength += getSizeForEncoding(Streamer, frame.LsdaEncoding);1834 1835 Streamer.emitULEB128IntValue(augmentationLength);1836 1837 // Augmentation Data1838 if (frame.Lsda)1839 emitFDESymbol(Streamer, *frame.Lsda, frame.LsdaEncoding, true);1840 }1841 1842 // Call Frame Instructions1843 emitCFIInstructions(frame.Instructions, frame.Begin);1844 1845 // Padding1846 // The size of a .eh_frame section has to be a multiple of the alignment1847 // since a null CIE is interpreted as the end. Old systems overaligned1848 // .eh_frame, so we do too and account for it in the last FDE.1849 unsigned Alignment = LastInSection ? asmInfo->getCodePointerSize() : PCSize;1850 Streamer.emitValueToAlignment(Align(Alignment));1851 1852 Streamer.emitLabel(fdeEnd);1853}1854 1855namespace {1856 1857struct CIEKey {1858 CIEKey() = default;1859 1860 explicit CIEKey(const MCDwarfFrameInfo &Frame)1861 : Personality(Frame.Personality),1862 PersonalityEncoding(Frame.PersonalityEncoding),1863 LsdaEncoding(Frame.LsdaEncoding), IsSignalFrame(Frame.IsSignalFrame),1864 IsSimple(Frame.IsSimple), RAReg(Frame.RAReg),1865 IsBKeyFrame(Frame.IsBKeyFrame),1866 IsMTETaggedFrame(Frame.IsMTETaggedFrame) {}1867 1868 StringRef PersonalityName() const {1869 if (!Personality)1870 return StringRef();1871 return Personality->getName();1872 }1873 1874 bool operator<(const CIEKey &Other) const {1875 return std::make_tuple(PersonalityName(), PersonalityEncoding, LsdaEncoding,1876 IsSignalFrame, IsSimple, RAReg, IsBKeyFrame,1877 IsMTETaggedFrame) <1878 std::make_tuple(Other.PersonalityName(), Other.PersonalityEncoding,1879 Other.LsdaEncoding, Other.IsSignalFrame,1880 Other.IsSimple, Other.RAReg, Other.IsBKeyFrame,1881 Other.IsMTETaggedFrame);1882 }1883 1884 bool operator==(const CIEKey &Other) const {1885 return Personality == Other.Personality &&1886 PersonalityEncoding == Other.PersonalityEncoding &&1887 LsdaEncoding == Other.LsdaEncoding &&1888 IsSignalFrame == Other.IsSignalFrame && IsSimple == Other.IsSimple &&1889 RAReg == Other.RAReg && IsBKeyFrame == Other.IsBKeyFrame &&1890 IsMTETaggedFrame == Other.IsMTETaggedFrame;1891 }1892 bool operator!=(const CIEKey &Other) const { return !(*this == Other); }1893 1894 const MCSymbol *Personality = nullptr;1895 unsigned PersonalityEncoding = 0;1896 unsigned LsdaEncoding = -1;1897 bool IsSignalFrame = false;1898 bool IsSimple = false;1899 unsigned RAReg = UINT_MAX;1900 bool IsBKeyFrame = false;1901 bool IsMTETaggedFrame = false;1902};1903 1904} // end anonymous namespace1905 1906void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB,1907 bool IsEH) {1908 MCContext &Context = Streamer.getContext();1909 const MCObjectFileInfo *MOFI = Context.getObjectFileInfo();1910 const MCAsmInfo *AsmInfo = Context.getAsmInfo();1911 FrameEmitterImpl Emitter(IsEH, Streamer);1912 ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getDwarfFrameInfos();1913 1914 // Emit the compact unwind info if available.1915 bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame();1916 if (IsEH && MOFI->getCompactUnwindSection()) {1917 Streamer.generateCompactUnwindEncodings(MAB);1918 bool SectionEmitted = false;1919 for (const MCDwarfFrameInfo &Frame : FrameArray) {1920 if (Frame.CompactUnwindEncoding == 0) continue;1921 if (!SectionEmitted) {1922 Streamer.switchSection(MOFI->getCompactUnwindSection());1923 Streamer.emitValueToAlignment(Align(AsmInfo->getCodePointerSize()));1924 SectionEmitted = true;1925 }1926 NeedsEHFrameSection |=1927 Frame.CompactUnwindEncoding ==1928 MOFI->getCompactUnwindDwarfEHFrameOnly();1929 Emitter.EmitCompactUnwind(Frame);1930 }1931 }1932 1933 // Compact unwind information can be emitted in the eh_frame section or the1934 // debug_frame section. Skip emitting FDEs and CIEs when the compact unwind1935 // doesn't need an eh_frame section and the emission location is the eh_frame1936 // section.1937 if (!NeedsEHFrameSection && IsEH) return;1938 1939 MCSection &Section =1940 IsEH ? *const_cast<MCObjectFileInfo *>(MOFI)->getEHFrameSection()1941 : *MOFI->getDwarfFrameSection();1942 1943 Streamer.switchSection(&Section);1944 MCSymbol *SectionStart = Context.createTempSymbol();1945 Streamer.emitLabel(SectionStart);1946 1947 bool CanOmitDwarf = MOFI->getOmitDwarfIfHaveCompactUnwind();1948 // Sort the FDEs by their corresponding CIE before we emit them.1949 // This isn't technically necessary according to the DWARF standard,1950 // but the Android libunwindstack rejects eh_frame sections where1951 // an FDE refers to a CIE other than the closest previous CIE.1952 std::vector<MCDwarfFrameInfo> FrameArrayX(FrameArray.begin(), FrameArray.end());1953 llvm::stable_sort(FrameArrayX,1954 [](const MCDwarfFrameInfo &X, const MCDwarfFrameInfo &Y) {1955 return CIEKey(X) < CIEKey(Y);1956 });1957 CIEKey LastKey;1958 const MCSymbol *LastCIEStart = nullptr;1959 for (auto I = FrameArrayX.begin(), E = FrameArrayX.end(); I != E;) {1960 const MCDwarfFrameInfo &Frame = *I;1961 ++I;1962 if (CanOmitDwarf && Frame.CompactUnwindEncoding !=1963 MOFI->getCompactUnwindDwarfEHFrameOnly() && IsEH)1964 // CIEs and FDEs can be emitted in either the eh_frame section or the1965 // debug_frame section, on some platforms (e.g. AArch64) the target object1966 // file supports emitting a compact_unwind section without an associated1967 // eh_frame section. If the eh_frame section is not needed, and the1968 // location where the CIEs and FDEs are to be emitted is the eh_frame1969 // section, do not emit anything.1970 continue;1971 1972 CIEKey Key(Frame);1973 if (!LastCIEStart || (IsEH && Key != LastKey)) {1974 LastKey = Key;1975 LastCIEStart = &Emitter.EmitCIE(Frame);1976 }1977 1978 Emitter.EmitFDE(*LastCIEStart, Frame, I == E, *SectionStart);1979 }1980}1981 1982void MCDwarfFrameEmitter::encodeAdvanceLoc(MCContext &Context,1983 uint64_t AddrDelta,1984 SmallVectorImpl<char> &Out) {1985 // Scale the address delta by the minimum instruction length.1986 AddrDelta = ScaleAddrDelta(Context, AddrDelta);1987 if (AddrDelta == 0)1988 return;1989 1990 llvm::endianness E = Context.getAsmInfo()->isLittleEndian()1991 ? llvm::endianness::little1992 : llvm::endianness::big;1993 1994 if (isUIntN(6, AddrDelta)) {1995 uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;1996 Out.push_back(Opcode);1997 } else if (isUInt<8>(AddrDelta)) {1998 Out.push_back(dwarf::DW_CFA_advance_loc1);1999 Out.push_back(AddrDelta);2000 } else if (isUInt<16>(AddrDelta)) {2001 Out.push_back(dwarf::DW_CFA_advance_loc2);2002 support::endian::write<uint16_t>(Out, AddrDelta, E);2003 } else {2004 assert(isUInt<32>(AddrDelta));2005 Out.push_back(dwarf::DW_CFA_advance_loc4);2006 support::endian::write<uint32_t>(Out, AddrDelta, E);2007 }2008}2009