summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/MC/ELFObjectWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/MC/ELFObjectWriter.cpp')
-rw-r--r--contrib/llvm/lib/MC/ELFObjectWriter.cpp146
1 files changed, 68 insertions, 78 deletions
diff --git a/contrib/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm/lib/MC/ELFObjectWriter.cpp
index a8c88dd..c8dd630 100644
--- a/contrib/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/contrib/llvm/lib/MC/ELFObjectWriter.cpp
@@ -11,29 +11,51 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/MC/MCFragment.h"
#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compression.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/SMLoc.h"
#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/SwapByteOrder.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
#include <vector>
using namespace llvm;
@@ -42,7 +64,8 @@ using namespace llvm;
#define DEBUG_TYPE "reloc-info"
namespace {
-typedef DenseMap<const MCSectionELF *, uint32_t> SectionIndexMapTy;
+
+using SectionIndexMapTy = DenseMap<const MCSectionELF *, uint32_t>;
class ELFObjectWriter;
@@ -99,8 +122,7 @@ class ELFObjectWriter : public MCObjectWriter {
DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames;
- llvm::DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>>
- Relocations;
+ DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> Relocations;
/// @}
/// @name Symbol Table Data
@@ -144,6 +166,8 @@ public:
bool IsLittleEndian)
: MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {}
+ ~ELFObjectWriter() override = default;
+
void reset() override {
Renames.clear();
Relocations.clear();
@@ -152,8 +176,6 @@ public:
MCObjectWriter::reset();
}
- ~ELFObjectWriter() override;
-
void WriteWord(uint64_t W) {
if (is64Bit())
write64(W);
@@ -174,8 +196,8 @@ public:
ELFSymbolData &MSD, const MCAsmLayout &Layout);
// Start and end offset of each section
- typedef std::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>>
- SectionOffsetsTy;
+ using SectionOffsetsTy =
+ std::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>>;
bool shouldRelocateWithSymbol(const MCAssembler &Asm,
const MCSymbolRefExpr *RefA,
@@ -184,11 +206,10 @@ public:
void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
- MCValue Target, bool &IsPCRel,
- uint64_t &FixedValue) override;
+ MCValue Target, uint64_t &FixedValue) override;
// Map from a signature symbol to the group section index
- typedef DenseMap<const MCSymbol *, unsigned> RevGroupMapTy;
+ using RevGroupMapTy = DenseMap<const MCSymbol *, unsigned>;
/// Compute the symbol table data
///
@@ -222,18 +243,18 @@ public:
void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec);
+ using MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl;
bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
const MCSymbol &SymA,
const MCFragment &FB, bool InSet,
bool IsPCRel) const override;
- bool isWeak(const MCSymbol &Sym) const override;
-
void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
void writeSection(const SectionIndexMapTy &SectionIndexMap,
uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size,
const MCSectionELF &Section);
};
+
} // end anonymous namespace
void ELFObjectWriter::align(unsigned Alignment) {
@@ -297,9 +318,6 @@ void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,
++NumWritten;
}
-ELFObjectWriter::~ELFObjectWriter()
-{}
-
// Emit the ELF header.
void ELFObjectWriter::writeHeader(const MCAssembler &Asm) {
// ELF Header
@@ -370,22 +388,6 @@ uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym,
void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) {
- // Section symbols are used as definitions for undefined symbols with matching
- // names. If there are multiple sections with the same name, the first one is
- // used.
- for (const MCSection &Sec : Asm) {
- const MCSymbol *Begin = Sec.getBeginSymbol();
- if (!Begin)
- continue;
-
- const MCSymbol *Alias = Asm.getContext().lookupSymbol(Begin->getName());
- if (!Alias || !Alias->isUndefined())
- continue;
-
- Renames.insert(
- std::make_pair(cast<MCSymbolELF>(Alias), cast<MCSymbolELF>(Begin)));
- }
-
// The presence of symbol versions causes undefined symbols and
// versions declared with @@@ to be renamed.
for (const MCSymbol &A : Asm.symbols()) {
@@ -625,16 +627,16 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
const MCFixup &Fixup, MCValue Target,
- bool &IsPCRel, uint64_t &FixedValue) {
+ uint64_t &FixedValue) {
+ MCAsmBackend &Backend = Asm.getBackend();
+ bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
+ MCFixupKindInfo::FKF_IsPCRel;
const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent());
uint64_t C = Target.getConstant();
uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
MCContext &Ctx = Asm.getContext();
if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
- assert(RefB->getKind() == MCSymbolRefExpr::VK_None &&
- "Should not have constructed this");
-
// Let A, B and C being the components of Target and R be the location of
// the fixup. If the fixup is not pcrel, we want to compute (A - B + C).
// If it is pcrel, we want to compute (A - B + C - R).
@@ -900,6 +902,8 @@ void ELFObjectWriter::computeSymbolTable(
StrTabBuilder.finalize();
+ // File symbols are emitted first and handled separately from normal symbols,
+ // i.e. a non-STT_FILE symbol with the same name may appear.
for (const std::string &Name : FileNames)
Writer.writeSymbol(StrTabBuilder.getOffset(Name),
ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT,
@@ -1017,18 +1021,24 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
StringRef SectionName = Section.getSectionName();
+ auto &MC = Asm.getContext();
+ const auto &MAI = MC.getAsmInfo();
+
// Compressing debug_frame requires handling alignment fragments which is
// more work (possibly generalizing MCAssembler.cpp:writeFragment to allow
// for writing to arbitrary buffers) for little benefit.
bool CompressionEnabled =
- Asm.getContext().getAsmInfo()->compressDebugSections() !=
- DebugCompressionType::DCT_None;
+ MAI->compressDebugSections() != DebugCompressionType::None;
if (!CompressionEnabled || !SectionName.startswith(".debug_") ||
SectionName == ".debug_frame") {
Asm.writeSectionData(&Section, Layout);
return;
}
+ assert((MAI->compressDebugSections() == DebugCompressionType::Z ||
+ MAI->compressDebugSections() == DebugCompressionType::GNU) &&
+ "expected zlib or zlib-gnu style compression");
+
SmallVector<char, 128> UncompressedData;
raw_svector_ostream VecOS(UncompressedData);
raw_pwrite_stream &OldStream = getStream();
@@ -1037,16 +1047,15 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
setStream(OldStream);
SmallVector<char, 128> CompressedContents;
- zlib::Status Success = zlib::compress(
- StringRef(UncompressedData.data(), UncompressedData.size()),
- CompressedContents);
- if (Success != zlib::StatusOK) {
+ if (Error E = zlib::compress(
+ StringRef(UncompressedData.data(), UncompressedData.size()),
+ CompressedContents)) {
+ consumeError(std::move(E));
getStream() << UncompressedData;
return;
}
- bool ZlibStyle = Asm.getContext().getAsmInfo()->compressDebugSections() ==
- DebugCompressionType::DCT_Zlib;
+ bool ZlibStyle = MAI->compressDebugSections() == DebugCompressionType::Z;
if (!maybeWriteCompression(UncompressedData.size(), CompressedContents,
ZlibStyle, Sec.getAlignment())) {
getStream() << UncompressedData;
@@ -1058,8 +1067,7 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED);
else
// Add "z" prefix to section name. This is zlib-gnu style.
- Asm.getContext().renameELFSection(&Section,
- (".z" + SectionName.drop_front(1)).str());
+ MC.renameELFSection(&Section, (".z" + SectionName.drop_front(1)).str());
getStream() << CompressedContents;
}
@@ -1151,8 +1159,8 @@ void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
case ELF::SHT_RELA: {
sh_link = SymbolTableIndex;
assert(sh_link && ".symtab not found");
- const MCSectionELF *InfoSection = Section.getAssociatedSection();
- sh_info = SectionIndexMap.lookup(InfoSection);
+ const MCSection *InfoSection = Section.getAssociatedSection();
+ sh_info = SectionIndexMap.lookup(cast<MCSectionELF>(InfoSection));
break;
}
@@ -1172,9 +1180,11 @@ void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
break;
}
- if (TargetObjectWriter->getEMachine() == ELF::EM_ARM &&
- Section.getType() == ELF::SHT_ARM_EXIDX)
- sh_link = SectionIndexMap.lookup(Section.getAssociatedSection());
+ if (Section.getFlags() & ELF::SHF_LINK_ORDER) {
+ const MCSymbol *Sym = Section.getAssociatedSymbol();
+ const MCSectionELF *Sec = cast<MCSectionELF>(&Sym->getSection());
+ sh_link = SectionIndexMap.lookup(Sec);
+ }
WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getSectionName()),
Section.getType(), Section.getFlags(), 0, Offset, Size,
@@ -1298,7 +1308,8 @@ void ELFObjectWriter::writeObject(MCAssembler &Asm,
// Remember the offset into the file for this section.
uint64_t SecStart = getStream().tell();
- writeRelocations(Asm, *RelSection->getAssociatedSection());
+ writeRelocations(Asm,
+ cast<MCSectionELF>(*RelSection->getAssociatedSection()));
uint64_t SecEnd = getStream().tell();
SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd);
@@ -1351,34 +1362,13 @@ bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
const auto &SymA = cast<MCSymbolELF>(SA);
if (IsPCRel) {
assert(!InSet);
- if (::isWeak(SymA))
+ if (isWeak(SymA))
return false;
}
return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
InSet, IsPCRel);
}
-bool ELFObjectWriter::isWeak(const MCSymbol &S) const {
- const auto &Sym = cast<MCSymbolELF>(S);
- if (::isWeak(Sym))
- return true;
-
- // It is invalid to replace a reference to a global in a comdat
- // with a reference to a local since out of comdat references
- // to a local are forbidden.
- // We could try to return false for more cases, like the reference
- // being in the same comdat or Sym being an alias to another global,
- // but it is not clear if it is worth the effort.
- if (Sym.getBinding() != ELF::STB_GLOBAL)
- return false;
-
- if (!Sym.isInSection())
- return false;
-
- const auto &Sec = cast<MCSectionELF>(Sym.getSection());
- return Sec.getGroup();
-}
-
MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW,
raw_pwrite_stream &OS,
bool IsLittleEndian) {
OpenPOWER on IntegriCloud