diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/MC/MCDwarf.cpp | 131 | ||||
-rw-r--r-- | llvm/lib/MC/MCObjectFileInfo.cpp | 14 | ||||
-rw-r--r-- | llvm/lib/MC/StringTableBuilder.cpp | 2 |
3 files changed, 124 insertions, 23 deletions
diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp index 31f731c291c..29c08440f4f 100644 --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -28,6 +28,7 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Endian.h" #include "llvm/Support/EndianStream.h" @@ -45,6 +46,29 @@ using namespace llvm; +/// Manage the .debug_line_str section contents, if we use it. +class llvm::MCDwarfLineStr { + MCSymbol *LineStrLabel = nullptr; + StringTableBuilder LineStrings{StringTableBuilder::DWARF}; + bool UseRelocs = false; + +public: + /// Construct an instance that can emit .debug_line_str (for use in a normal + /// v5 line table). + explicit MCDwarfLineStr(MCContext &Ctx) { + UseRelocs = Ctx.getAsmInfo()->doesDwarfUseRelocationsAcrossSections(); + if (UseRelocs) + LineStrLabel = + Ctx.getObjectFileInfo()->getDwarfLineStrSection()->getBeginSymbol(); + } + + /// Emit a reference to the string. + void emitRef(MCStreamer *MCOS, StringRef Path); + + /// Emit the .debug_line_str section if appropriate. + void emitSection(MCStreamer *MCOS); +}; + static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) { unsigned MinInsnLength = Context.getAsmInfo()->getMinInstAlignment(); if (MinInsnLength == 1) @@ -108,6 +132,18 @@ static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS, } // +// This helper routine returns an expression of Start + IntVal . +// +static inline const MCExpr * +makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) { + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + const MCExpr *LHS = MCSymbolRefExpr::create(&Start, Variant, Ctx); + const MCExpr *RHS = MCConstantExpr::create(IntVal, Ctx); + const MCExpr *Res = MCBinaryExpr::create(MCBinaryExpr::Add, LHS, RHS, Ctx); + return Res; +} + +// // This emits the Dwarf line table for the specified section from the entries // in the LineSection. // @@ -205,22 +241,31 @@ void MCDwarfLineTable::Emit(MCObjectStreamer *MCOS, if (LineTables.empty()) return; + // In a v5 non-split line table, put the strings in a separate section. + Optional<MCDwarfLineStr> LineStr; + if (context.getDwarfVersion() >= 5) + LineStr = MCDwarfLineStr(context); + // Switch to the section where the table will be emitted into. MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); // Handle the rest of the Compile Units. for (const auto &CUIDTablePair : LineTables) - CUIDTablePair.second.EmitCU(MCOS, Params); + CUIDTablePair.second.EmitCU(MCOS, Params, LineStr); + + if (LineStr) + LineStr->emitSection(MCOS); } void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params) const { - MCOS.EmitLabel(Header.Emit(&MCOS, Params, None).second); + Optional<MCDwarfLineStr> NoLineStr(None); + MCOS.EmitLabel(Header.Emit(&MCOS, Params, None, NoLineStr).second); } std::pair<MCSymbol *, MCSymbol *> -MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, - MCDwarfLineTableParams Params) const { +MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, + Optional<MCDwarfLineStr> &LineStr) const { static const char StandardOpcodeLengths[] = { 0, // length of DW_LNS_copy 1, // length of DW_LNS_advance_pc @@ -237,8 +282,10 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, }; assert(array_lengthof(StandardOpcodeLengths) >= (Params.DWARF2LineOpcodeBase - 1U)); - return Emit(MCOS, Params, makeArrayRef(StandardOpcodeLengths, - Params.DWARF2LineOpcodeBase - 1)); + return Emit( + MCOS, Params, + makeArrayRef(StandardOpcodeLengths, Params.DWARF2LineOpcodeBase - 1), + LineStr); } static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) { @@ -257,6 +304,28 @@ static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) { OS.EmitValue(ABS, Size); } +void MCDwarfLineStr::emitSection(MCStreamer *MCOS) { + // Switch to the .debug_line_str section. + MCOS->SwitchSection( + MCOS->getContext().getObjectFileInfo()->getDwarfLineStrSection()); + // Emit the strings without perturbing the offsets we used. + LineStrings.finalizeInOrder(); + SmallString<0> Data; + Data.resize(LineStrings.getSize()); + LineStrings.write((uint8_t *)Data.data()); + MCOS->EmitBinaryData(Data.str()); +} + +void MCDwarfLineStr::emitRef(MCStreamer *MCOS, StringRef Path) { + int RefSize = 4; // FIXME: Support DWARF-64 + size_t Offset = LineStrings.add(Path); + if (UseRelocs) { + MCContext &Ctx = MCOS->getContext(); + MCOS->EmitValue(makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset), RefSize); + } else + MCOS->EmitIntValue(Offset, RefSize); +} + void MCDwarfLineTableHeader::emitV2FileDirTables(MCStreamer *MCOS) const { // First the directory table. for (auto &Dir : MCDwarfDirs) { @@ -277,18 +346,29 @@ void MCDwarfLineTableHeader::emitV2FileDirTables(MCStreamer *MCOS) const { MCOS->EmitIntValue(0, 1); // Terminate the file list. } -void MCDwarfLineTableHeader::emitV5FileDirTables(MCStreamer *MCOS) const { - // The directory format, which is just inline null-terminated strings. +void MCDwarfLineTableHeader::emitV5FileDirTables( + MCStreamer *MCOS, Optional<MCDwarfLineStr> &LineStr) const { + // The directory format, which is just a list of the directory paths. In a + // non-split object, these are references to .debug_line_str; in a split + // object, they are inline strings. MCOS->EmitIntValue(1, 1); MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path); - MCOS->EmitULEB128IntValue(dwarf::DW_FORM_string); - // Then the list of directory paths. CompilationDir comes first. + MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp + : dwarf::DW_FORM_string); MCOS->EmitULEB128IntValue(MCDwarfDirs.size() + 1); - MCOS->EmitBytes(CompilationDir); - MCOS->EmitBytes(StringRef("\0", 1)); - for (auto &Dir : MCDwarfDirs) { - MCOS->EmitBytes(Dir); // The DirectoryName, and... - MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. + if (LineStr) { + // Record path strings, emit references here. + LineStr->emitRef(MCOS, CompilationDir); + for (auto &Dir : MCDwarfDirs) + LineStr->emitRef(MCOS, Dir); + } else { + // The list of directory paths. CompilationDir comes first. + MCOS->EmitBytes(CompilationDir); + MCOS->EmitBytes(StringRef("\0", 1)); + for (auto &Dir : MCDwarfDirs) { + MCOS->EmitBytes(Dir); // The DirectoryName, and... + MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. + } } // The file format, which is the inline null-terminated filename and a @@ -296,7 +376,8 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(MCStreamer *MCOS) const { // in the v5 table. Emit MD5 checksums if we have them. MCOS->EmitIntValue(HasMD5 ? 3 : 2, 1); MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path); - MCOS->EmitULEB128IntValue(dwarf::DW_FORM_string); + MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp + : dwarf::DW_FORM_string); MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_directory_index); MCOS->EmitULEB128IntValue(dwarf::DW_FORM_udata); if (HasMD5) { @@ -307,8 +388,12 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(MCStreamer *MCOS) const { MCOS->EmitULEB128IntValue(MCDwarfFiles.size() - 1); for (unsigned i = 1; i < MCDwarfFiles.size(); ++i) { assert(!MCDwarfFiles[i].Name.empty()); - MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName and... - MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. + if (LineStr) + LineStr->emitRef(MCOS, MCDwarfFiles[i].Name); + else { + MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName and... + MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. + } MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number. if (HasMD5) { MD5::MD5Result *Cksum = MCDwarfFiles[i].Checksum; @@ -321,7 +406,8 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(MCStreamer *MCOS) const { std::pair<MCSymbol *, MCSymbol *> MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, - ArrayRef<char> StandardOpcodeLengths) const { + ArrayRef<char> StandardOpcodeLengths, + Optional<MCDwarfLineStr> &LineStr) const { MCContext &context = MCOS->getContext(); // Create a symbol at the beginning of the line table. @@ -386,7 +472,7 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, // Put out the directory and file tables. The formats vary depending on // the version. if (LineTableVersion >= 5) - emitV5FileDirTables(MCOS); + emitV5FileDirTables(MCOS, LineStr); else emitV2FileDirTables(MCOS); @@ -398,8 +484,9 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, } void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS, - MCDwarfLineTableParams Params) const { - MCSymbol *LineEndSym = Header.Emit(MCOS, Params).second; + MCDwarfLineTableParams Params, + Optional<MCDwarfLineStr> &LineStr) const { + MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; // Put out the line tables. for (const auto &LineSec : MCLineSections.getMCLineEntries()) diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp index f0f4dee8fc1..4eebda6d3ed 100644 --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -228,6 +228,9 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) { DwarfLineSection = Ctx->getMachOSection("__DWARF", "__debug_line", MachO::S_ATTR_DEBUG, SectionKind::getMetadata(), "section_line"); + DwarfLineStrSection = + Ctx->getMachOSection("__DWARF", "__debug_line_str", MachO::S_ATTR_DEBUG, + SectionKind::getMetadata(), "section_line_str"); DwarfFrameSection = Ctx->getMachOSection("__DWARF", "__debug_frame", MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); @@ -527,6 +530,9 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) { Ctx->getELFSection(".debug_abbrev", DebugSecType, 0); DwarfInfoSection = Ctx->getELFSection(".debug_info", DebugSecType, 0); DwarfLineSection = Ctx->getELFSection(".debug_line", DebugSecType, 0); + DwarfLineStrSection = + Ctx->getELFSection(".debug_line_str", DebugSecType, + ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, ""); DwarfFrameSection = Ctx->getELFSection(".debug_frame", DebugSecType, 0); DwarfPubNamesSection = Ctx->getELFSection(".debug_pubnames", DebugSecType, 0); @@ -677,7 +683,11 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) { COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata(), "section_line"); - + DwarfLineStrSection = Ctx->getCOFFSection( + ".debug_line_str", + COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata(), "section_line_str"); DwarfFrameSection = Ctx->getCOFFSection( ".debug_frame", COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | @@ -842,6 +852,8 @@ void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) { // TODO: Set the section types and flags. DwarfLineSection = Ctx->getWasmSection(".debug_line", SectionKind::getMetadata()); + DwarfLineStrSection = + Ctx->getWasmSection(".debug_line_str", SectionKind::getMetadata()); DwarfStrSection = Ctx->getWasmSection(".debug_str", SectionKind::getMetadata()); DwarfLocSection = Ctx->getWasmSection(".debug_loc", SectionKind::getMetadata()); DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", SectionKind::getMetadata(), "section_abbrev"); diff --git a/llvm/lib/MC/StringTableBuilder.cpp b/llvm/lib/MC/StringTableBuilder.cpp index 531bc930c89..de40a7728d3 100644 --- a/llvm/lib/MC/StringTableBuilder.cpp +++ b/llvm/lib/MC/StringTableBuilder.cpp @@ -31,6 +31,7 @@ void StringTableBuilder::initSize() { // correct. switch (K) { case RAW: + case DWARF: Size = 0; break; case MachO: @@ -116,6 +117,7 @@ tailcall: } void StringTableBuilder::finalize() { + assert(K != DWARF); finalizeStringTable(/*Optimize=*/true); } |