[llvm] r332875 - MC: Introduce an ELF dwo object writer and teach llvm-mc about it.
Peter Collingbourne via llvm-commits
llvm-commits at lists.llvm.org
Mon May 21 12:44:54 PDT 2018
Author: pcc
Date: Mon May 21 12:44:54 2018
New Revision: 332875
URL: http://llvm.org/viewvc/llvm-project?rev=332875&view=rev
Log:
MC: Introduce an ELF dwo object writer and teach llvm-mc about it.
Part of PR37466.
Differential Revision: https://reviews.llvm.org/D47051
Added:
llvm/trunk/test/MC/ELF/dwo-restrict-relocs.s
llvm/trunk/test/MC/ELF/dwo-sections.s
Modified:
llvm/trunk/include/llvm/MC/MCAsmBackend.h
llvm/trunk/include/llvm/MC/MCELFObjectWriter.h
llvm/trunk/lib/MC/ELFObjectWriter.cpp
llvm/trunk/lib/MC/MCAsmBackend.cpp
llvm/trunk/tools/llvm-mc/llvm-mc.cpp
Modified: llvm/trunk/include/llvm/MC/MCAsmBackend.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAsmBackend.h?rev=332875&r1=332874&r2=332875&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCAsmBackend.h (original)
+++ llvm/trunk/include/llvm/MC/MCAsmBackend.h Mon May 21 12:44:54 2018
@@ -60,6 +60,12 @@ public:
std::unique_ptr<MCObjectWriter>
createObjectWriter(raw_pwrite_stream &OS) const;
+ /// Create an MCObjectWriter that writes two object files: a .o file which is
+ /// linked into the final program and a .dwo file which is used by debuggers.
+ /// This function is only supported with ELF targets.
+ std::unique_ptr<MCObjectWriter>
+ createDwoObjectWriter(raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS) const;
+
virtual std::unique_ptr<MCObjectTargetWriter>
createObjectTargetWriter() const = 0;
Modified: llvm/trunk/include/llvm/MC/MCELFObjectWriter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCELFObjectWriter.h?rev=332875&r1=332874&r2=332875&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCELFObjectWriter.h (original)
+++ llvm/trunk/include/llvm/MC/MCELFObjectWriter.h Mon May 21 12:44:54 2018
@@ -147,6 +147,11 @@ std::unique_ptr<MCObjectWriter>
createELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS, bool IsLittleEndian);
+std::unique_ptr<MCObjectWriter>
+createELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS,
+ bool IsLittleEndian);
+
} // end namespace llvm
#endif // LLVM_MC_MCELFOBJECTWRITER_H
Modified: llvm/trunk/lib/MC/ELFObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/ELFObjectWriter.cpp?rev=332875&r1=332874&r2=332875&view=diff
==============================================================================
--- llvm/trunk/lib/MC/ELFObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/ELFObjectWriter.cpp Mon May 21 12:44:54 2018
@@ -70,6 +70,10 @@ using SectionIndexMapTy = DenseMap<const
class ELFObjectWriter;
struct ELFWriter;
+bool isDwoSection(const MCSectionELF &Sec) {
+ return Sec.getSectionName().endswith(".dwo");
+}
+
class SymbolTableWriter {
ELFWriter &EWriter;
bool Is64Bit;
@@ -97,6 +101,12 @@ struct ELFWriter {
ELFObjectWriter &OWriter;
support::endian::Writer W;
+ enum DwoMode {
+ AllSections,
+ NonDwoOnly,
+ DwoOnly,
+ } Mode;
+
static uint64_t SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout);
static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol,
bool Used, bool Renamed);
@@ -152,9 +162,9 @@ struct ELFWriter {
public:
ELFWriter(ELFObjectWriter &OWriter, raw_pwrite_stream &OS,
- bool IsLittleEndian)
+ bool IsLittleEndian, DwoMode Mode)
: OWriter(OWriter),
- W(OS, IsLittleEndian ? support::little : support::big) {}
+ W(OS, IsLittleEndian ? support::little : support::big), Mode(Mode) {}
void WriteWord(uint64_t Word) {
if (is64Bit())
@@ -244,6 +254,12 @@ public:
const MCFragment &FB, bool InSet,
bool IsPCRel) const override;
+ virtual bool checkRelocation(MCContext &Ctx, SMLoc Loc,
+ const MCSectionELF *From,
+ const MCSectionELF *To) {
+ return true;
+ }
+
void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, uint64_t &FixedValue) override;
@@ -265,7 +281,44 @@ public:
IsLittleEndian(IsLittleEndian) {}
uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override {
- return ELFWriter(*this, OS, IsLittleEndian).writeObject(Asm, Layout);
+ return ELFWriter(*this, OS, IsLittleEndian, ELFWriter::AllSections)
+ .writeObject(Asm, Layout);
+ }
+
+ friend struct ELFWriter;
+};
+
+class ELFDwoObjectWriter : public ELFObjectWriter {
+ raw_pwrite_stream &OS, &DwoOS;
+ bool IsLittleEndian;
+
+public:
+ ELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS,
+ bool IsLittleEndian)
+ : ELFObjectWriter(std::move(MOTW)), OS(OS), DwoOS(DwoOS),
+ IsLittleEndian(IsLittleEndian) {}
+
+ virtual bool checkRelocation(MCContext &Ctx, SMLoc Loc,
+ const MCSectionELF *From,
+ const MCSectionELF *To) override {
+ if (isDwoSection(*From)) {
+ Ctx.reportError(Loc, "A dwo section may not contain relocations");
+ return false;
+ }
+ if (To && isDwoSection(*To)) {
+ Ctx.reportError(Loc, "A relocation may not refer to a dwo section");
+ return false;
+ }
+ return true;
+ }
+
+ uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override {
+ uint64_t Size = ELFWriter(*this, OS, IsLittleEndian, ELFWriter::NonDwoOnly)
+ .writeObject(Asm, Layout);
+ Size += ELFWriter(*this, DwoOS, IsLittleEndian, ELFWriter::DwoOnly)
+ .writeObject(Asm, Layout);
+ return Size;
}
};
@@ -604,6 +657,8 @@ void ELFWriter::computeSymbolTable(
} else {
const MCSectionELF &Section =
static_cast<const MCSectionELF &>(Symbol.getSection());
+ if (Mode == NonDwoOnly && isDwoSection(Section))
+ continue;
MSD.SectionIndex = SectionIndexMap.lookup(&Section);
assert(MSD.SectionIndex && "Invalid section index!");
if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
@@ -995,6 +1050,10 @@ uint64_t ELFWriter::writeObject(MCAssemb
std::vector<MCSectionELF *> Relocations;
for (MCSection &Sec : Asm) {
MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
+ if (Mode == NonDwoOnly && isDwoSection(Section))
+ continue;
+ if (Mode == DwoOnly && !isDwoSection(Section))
+ continue;
align(Section.getAlignment());
@@ -1050,20 +1109,27 @@ uint64_t ELFWriter::writeObject(MCAssemb
SectionOffsets[Group] = std::make_pair(SecStart, SecEnd);
}
- // Compute symbol table information.
- computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, SectionOffsets);
+ if (Mode == DwoOnly) {
+ // dwo files don't have symbol tables or relocations, but they do have
+ // string tables.
+ StrTabBuilder.finalize();
+ } else {
+ // Compute symbol table information.
+ computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap,
+ SectionOffsets);
- for (MCSectionELF *RelSection : Relocations) {
- align(RelSection->getAlignment());
+ for (MCSectionELF *RelSection : Relocations) {
+ align(RelSection->getAlignment());
- // Remember the offset into the file for this section.
- uint64_t SecStart = W.OS.tell();
+ // Remember the offset into the file for this section.
+ uint64_t SecStart = W.OS.tell();
- writeRelocations(Asm,
- cast<MCSectionELF>(*RelSection->getAssociatedSection()));
+ writeRelocations(Asm,
+ cast<MCSectionELF>(*RelSection->getAssociatedSection()));
- uint64_t SecEnd = W.OS.tell();
- SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
+ uint64_t SecEnd = W.OS.tell();
+ SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
+ }
}
{
@@ -1336,9 +1402,13 @@ void ELFObjectWriter::recordRelocation(M
FixedValue = C;
+ const MCSectionELF *SecA = (SymA && SymA->isInSection())
+ ? cast<MCSectionELF>(&SymA->getSection())
+ : nullptr;
+ if (!checkRelocation(Ctx, Fixup.getLoc(), &FixupSection, SecA))
+ return;
+
if (!RelocateWithSymbol) {
- const MCSection *SecA =
- (SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr;
const auto *SectionSymbol =
SecA ? cast<MCSymbolELF>(SecA->getBeginSymbol()) : nullptr;
if (SectionSymbol)
@@ -1383,3 +1453,11 @@ llvm::createELFObjectWriter(std::unique_
return llvm::make_unique<ELFSingleObjectWriter>(std::move(MOTW), OS,
IsLittleEndian);
}
+
+std::unique_ptr<MCObjectWriter>
+llvm::createELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
+ raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS,
+ bool IsLittleEndian) {
+ return llvm::make_unique<ELFDwoObjectWriter>(std::move(MOTW), OS, DwoOS,
+ IsLittleEndian);
+}
Modified: llvm/trunk/lib/MC/MCAsmBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmBackend.cpp?rev=332875&r1=332874&r2=332875&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAsmBackend.cpp (original)
+++ llvm/trunk/lib/MC/MCAsmBackend.cpp Mon May 21 12:44:54 2018
@@ -49,6 +49,16 @@ MCAsmBackend::createObjectWriter(raw_pwr
}
}
+std::unique_ptr<MCObjectWriter>
+MCAsmBackend::createDwoObjectWriter(raw_pwrite_stream &OS,
+ raw_pwrite_stream &DwoOS) const {
+ auto TW = createObjectTargetWriter();
+ if (TW->getFormat() != Triple::ELF)
+ report_fatal_error("dwo only supported with ELF");
+ return createELFDwoObjectWriter(cast<MCELFObjectTargetWriter>(std::move(TW)),
+ OS, DwoOS, Endian == support::little);
+}
+
Optional<MCFixupKind> MCAsmBackend::getFixupKind(StringRef Name) const {
return None;
}
Added: llvm/trunk/test/MC/ELF/dwo-restrict-relocs.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/dwo-restrict-relocs.s?rev=332875&view=auto
==============================================================================
--- llvm/trunk/test/MC/ELF/dwo-restrict-relocs.s (added)
+++ llvm/trunk/test/MC/ELF/dwo-restrict-relocs.s Mon May 21 12:44:54 2018
@@ -0,0 +1,10 @@
+// RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t1 -split-dwarf-file %t2 2>&1 | FileCheck %s
+
+// CHECK: error: A relocation may not refer to a dwo section
+.quad .foo.dwo
+
+.section .foo.dwo
+// CHECK: error: A dwo section may not contain relocations
+.quad .text
+// CHECK: error: A dwo section may not contain relocations
+.quad .foo.dwo
Added: llvm/trunk/test/MC/ELF/dwo-sections.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/dwo-sections.s?rev=332875&view=auto
==============================================================================
--- llvm/trunk/test/MC/ELF/dwo-sections.s (added)
+++ llvm/trunk/test/MC/ELF/dwo-sections.s Mon May 21 12:44:54 2018
@@ -0,0 +1,25 @@
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t1 -split-dwarf-file %t2
+// RUN: llvm-objdump -s %t1 | FileCheck --check-prefix=O %s
+// RUN: llvm-objdump -s %t2 | FileCheck --check-prefix=DWO %s
+
+// O-NOT: Contents of section
+// O: Contents of section .strtab:
+// O-NOT: Contents of section
+// O: Contents of section .text:
+// O-NEXT: 0000 c3
+// O-NEXT: Contents of section .symtab:
+// O-NOT: Contents of section
+.globl main
+main:
+.Ltmp1:
+ret
+.Ltmp2:
+
+// DWO-NOT: Contents of section
+// DWO: Contents of section .strtab:
+// DWO-NOT: Contents of section
+// DWO: Contents of section .foo.dwo:
+// DWO-NEXT: 0000 01000000
+// DWO-NOT: Contents of section
+.section .foo.dwo
+.long .Ltmp2-.Ltmp1
Modified: llvm/trunk/tools/llvm-mc/llvm-mc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mc/llvm-mc.cpp?rev=332875&r1=332874&r2=332875&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mc/llvm-mc.cpp (original)
+++ llvm/trunk/tools/llvm-mc/llvm-mc.cpp Mon May 21 12:44:54 2018
@@ -45,9 +45,13 @@ using namespace llvm;
static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
-static cl::opt<std::string>
-OutputFilename("o", cl::desc("Output filename"),
- cl::value_desc("filename"));
+static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
+ cl::value_desc("filename"),
+ cl::init("-"));
+
+static cl::opt<std::string> SplitDwarfFile("split-dwarf-file",
+ cl::desc("DWO output filename"),
+ cl::value_desc("filename"));
static cl::opt<bool>
ShowEncoding("show-encoding", cl::desc("Show instruction encodings"));
@@ -197,13 +201,9 @@ static const Target *GetTarget(const cha
return TheTarget;
}
-static std::unique_ptr<ToolOutputFile> GetOutputStream() {
- if (OutputFilename == "")
- OutputFilename = "-";
-
+static std::unique_ptr<ToolOutputFile> GetOutputStream(StringRef Path) {
std::error_code EC;
- auto Out =
- llvm::make_unique<ToolOutputFile>(OutputFilename, EC, sys::fs::F_None);
+ auto Out = llvm::make_unique<ToolOutputFile>(Path, EC, sys::fs::F_None);
if (EC) {
WithColor::error() << EC.message() << '\n';
return nullptr;
@@ -411,10 +411,21 @@ int main(int argc, char **argv) {
FeaturesStr = Features.getString();
}
- std::unique_ptr<ToolOutputFile> Out = GetOutputStream();
+ std::unique_ptr<ToolOutputFile> Out = GetOutputStream(OutputFilename);
if (!Out)
return 1;
+ std::unique_ptr<ToolOutputFile> DwoOut;
+ if (!SplitDwarfFile.empty()) {
+ if (FileType != OFT_ObjectFile) {
+ WithColor::error() << "dwo output only supported with object files\n";
+ return 1;
+ }
+ DwoOut = GetOutputStream(SplitDwarfFile);
+ if (!DwoOut)
+ return 1;
+ }
+
std::unique_ptr<buffer_ostream> BOS;
raw_pwrite_stream *OS = &Out->os();
std::unique_ptr<MCStreamer> Str;
@@ -469,8 +480,10 @@ int main(int argc, char **argv) {
MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions);
Str.reset(TheTarget->createMCObjectStreamer(
TheTriple, Ctx, std::unique_ptr<MCAsmBackend>(MAB),
- MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(CE), *STI,
- MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
+ DwoOut ? MAB->createDwoObjectWriter(*OS, DwoOut->os())
+ : MAB->createObjectWriter(*OS),
+ std::unique_ptr<MCCodeEmitter>(CE), *STI, MCOptions.MCRelaxAll,
+ MCOptions.MCIncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ false));
if (NoExecStack)
Str->InitSections(true);
@@ -503,6 +516,10 @@ int main(int argc, char **argv) {
*Buffer, SrcMgr, Out->os());
// Keep output if no errors.
- if (Res == 0) Out->keep();
+ if (Res == 0) {
+ Out->keep();
+ if (DwoOut)
+ DwoOut->keep();
+ }
return Res;
}
More information about the llvm-commits
mailing list