File indexing completed on 2026-05-10 08:44:13
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_MC_MCELFOBJECTWRITER_H
0010 #define LLVM_MC_MCELFOBJECTWRITER_H
0011
0012 #include "llvm/ADT/DenseMap.h"
0013 #include "llvm/ADT/SmallVector.h"
0014 #include "llvm/BinaryFormat/ELF.h"
0015 #include "llvm/MC/MCObjectWriter.h"
0016 #include "llvm/MC/MCSectionELF.h"
0017 #include "llvm/Support/Casting.h"
0018 #include "llvm/Support/raw_ostream.h"
0019 #include "llvm/TargetParser/Triple.h"
0020 #include <cstdint>
0021 #include <memory>
0022 #include <optional>
0023 #include <vector>
0024
0025 namespace llvm {
0026
0027 class MCAssembler;
0028 class MCContext;
0029 class MCFixup;
0030 class MCSymbol;
0031 class MCSymbolELF;
0032 class MCTargetOptions;
0033 class MCValue;
0034
0035 struct ELFRelocationEntry {
0036 uint64_t Offset;
0037 const MCSymbolELF *Symbol;
0038 unsigned Type;
0039 uint64_t Addend;
0040
0041 ELFRelocationEntry(uint64_t Offset, const MCSymbolELF *Symbol, unsigned Type,
0042 uint64_t Addend)
0043 : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {}
0044
0045 void print(raw_ostream &Out) const {
0046 Out << "Off=" << Offset << ", Sym=" << Symbol << ", Type=" << Type
0047 << ", Addend=" << Addend;
0048 }
0049
0050 LLVM_DUMP_METHOD void dump() const { print(errs()); }
0051 };
0052
0053 class MCELFObjectTargetWriter : public MCObjectTargetWriter {
0054 const uint8_t OSABI;
0055 const uint8_t ABIVersion;
0056 const uint16_t EMachine;
0057 const unsigned HasRelocationAddend : 1;
0058 const unsigned Is64Bit : 1;
0059
0060 protected:
0061 MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_, uint16_t EMachine_,
0062 bool HasRelocationAddend_, uint8_t ABIVersion_ = 0);
0063
0064 public:
0065 virtual ~MCELFObjectTargetWriter() = default;
0066
0067 Triple::ObjectFormatType getFormat() const override { return Triple::ELF; }
0068 static bool classof(const MCObjectTargetWriter *W) {
0069 return W->getFormat() == Triple::ELF;
0070 }
0071
0072 static uint8_t getOSABI(Triple::OSType OSType) {
0073 switch (OSType) {
0074 case Triple::HermitCore:
0075 return ELF::ELFOSABI_STANDALONE;
0076 case Triple::PS4:
0077 case Triple::FreeBSD:
0078 return ELF::ELFOSABI_FREEBSD;
0079 case Triple::Solaris:
0080 return ELF::ELFOSABI_SOLARIS;
0081 case Triple::OpenBSD:
0082 return ELF::ELFOSABI_OPENBSD;
0083 default:
0084 return ELF::ELFOSABI_NONE;
0085 }
0086 }
0087
0088 virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
0089 const MCFixup &Fixup, bool IsPCRel) const = 0;
0090
0091 virtual bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym,
0092 unsigned Type) const;
0093
0094 virtual void sortRelocs(const MCAssembler &Asm,
0095 std::vector<ELFRelocationEntry> &Relocs);
0096
0097
0098
0099 uint8_t getOSABI() const { return OSABI; }
0100 uint8_t getABIVersion() const { return ABIVersion; }
0101 uint16_t getEMachine() const { return EMachine; }
0102 bool hasRelocationAddend() const { return HasRelocationAddend; }
0103 bool is64Bit() const { return Is64Bit; }
0104
0105
0106
0107
0108 #define R_TYPE_SHIFT 0
0109 #define R_TYPE_MASK 0xffffff00
0110 #define R_TYPE2_SHIFT 8
0111 #define R_TYPE2_MASK 0xffff00ff
0112 #define R_TYPE3_SHIFT 16
0113 #define R_TYPE3_MASK 0xff00ffff
0114 #define R_SSYM_SHIFT 24
0115 #define R_SSYM_MASK 0x00ffffff
0116
0117
0118 uint8_t getRType(uint32_t Type) const {
0119 return (unsigned)((Type >> R_TYPE_SHIFT) & 0xff);
0120 }
0121 uint8_t getRType2(uint32_t Type) const {
0122 return (unsigned)((Type >> R_TYPE2_SHIFT) & 0xff);
0123 }
0124 uint8_t getRType3(uint32_t Type) const {
0125 return (unsigned)((Type >> R_TYPE3_SHIFT) & 0xff);
0126 }
0127 uint8_t getRSsym(uint32_t Type) const {
0128 return (unsigned)((Type >> R_SSYM_SHIFT) & 0xff);
0129 }
0130
0131
0132 static unsigned setRTypes(unsigned Value1, unsigned Value2, unsigned Value3) {
0133 return ((Value1 & 0xff) << R_TYPE_SHIFT) |
0134 ((Value2 & 0xff) << R_TYPE2_SHIFT) |
0135 ((Value3 & 0xff) << R_TYPE3_SHIFT);
0136 }
0137 unsigned setRSsym(unsigned Value, unsigned Type) const {
0138 return (Type & R_SSYM_MASK) | ((Value & 0xff) << R_SSYM_SHIFT);
0139 }
0140 };
0141
0142 class ELFObjectWriter final : public MCObjectWriter {
0143 unsigned ELFHeaderEFlags = 0;
0144
0145 public:
0146 std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter;
0147 raw_pwrite_stream &OS;
0148 raw_pwrite_stream *DwoOS = nullptr;
0149
0150 DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> Relocations;
0151 DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames;
0152 bool IsLittleEndian = false;
0153 bool SeenGnuAbi = false;
0154 std::optional<uint8_t> OverrideABIVersion;
0155
0156 struct Symver {
0157 SMLoc Loc;
0158 const MCSymbol *Sym;
0159 StringRef Name;
0160
0161 bool KeepOriginalSym;
0162 };
0163 SmallVector<Symver, 0> Symvers;
0164
0165 ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
0166 raw_pwrite_stream &OS, bool IsLittleEndian);
0167 ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
0168 raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS,
0169 bool IsLittleEndian);
0170
0171 void reset() override;
0172 void executePostLayoutBinding(MCAssembler &Asm) override;
0173 void recordRelocation(MCAssembler &Asm, const MCFragment *Fragment,
0174 const MCFixup &Fixup, MCValue Target,
0175 uint64_t &FixedValue) override;
0176 bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
0177 const MCSymbol &SymA,
0178 const MCFragment &FB, bool InSet,
0179 bool IsPCRel) const override;
0180 uint64_t writeObject(MCAssembler &Asm) override;
0181
0182 bool hasRelocationAddend() const;
0183 bool usesRela(const MCTargetOptions *TO, const MCSectionELF &Sec) const;
0184
0185 bool shouldRelocateWithSymbol(const MCAssembler &Asm, const MCValue &Val,
0186 const MCSymbolELF *Sym, uint64_t C,
0187 unsigned Type) const;
0188
0189 bool checkRelocation(MCContext &Ctx, SMLoc Loc, const MCSectionELF *From,
0190 const MCSectionELF *To);
0191
0192 unsigned getELFHeaderEFlags() const { return ELFHeaderEFlags; }
0193 void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags; }
0194
0195
0196 void markGnuAbi() { SeenGnuAbi = true; }
0197 bool seenGnuAbi() const { return SeenGnuAbi; }
0198
0199
0200 void setOverrideABIVersion(uint8_t V) { OverrideABIVersion = V; }
0201 };
0202 }
0203
0204 #endif