summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r--llvm/lib/MC/MCDwarf.cpp131
-rw-r--r--llvm/lib/MC/MCObjectFileInfo.cpp14
-rw-r--r--llvm/lib/MC/StringTableBuilder.cpp2
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);
}
OpenPOWER on IntegriCloud