1321369Sdim//===- llvm/MC/MCELFObjectWriter.h - ELF Object Writer ----------*- C++ -*-===// 2218885Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6218885Sdim// 7218885Sdim//===----------------------------------------------------------------------===// 8218885Sdim 9218885Sdim#ifndef LLVM_MC_MCELFOBJECTWRITER_H 10218885Sdim#define LLVM_MC_MCELFOBJECTWRITER_H 11218885Sdim 12234353Sdim#include "llvm/ADT/Triple.h" 13321369Sdim#include "llvm/BinaryFormat/ELF.h" 14341825Sdim#include "llvm/MC/MCObjectWriter.h" 15344779Sdim#include "llvm/MC/MCSectionELF.h" 16321369Sdim#include "llvm/Support/Casting.h" 17309124Sdim#include "llvm/Support/raw_ostream.h" 18321369Sdim#include <cstdint> 19234353Sdim#include <vector> 20218885Sdim 21218885Sdimnamespace llvm { 22321369Sdim 23234353Sdimclass MCAssembler; 24309124Sdimclass MCContext; 25234353Sdimclass MCFixup; 26234353Sdimclass MCObjectWriter; 27234353Sdimclass MCSymbol; 28288943Sdimclass MCSymbolELF; 29234353Sdimclass MCValue; 30234353Sdim 31288943Sdimstruct ELFRelocationEntry { 32288943Sdim uint64_t Offset; // Where is the relocation. 33288943Sdim const MCSymbolELF *Symbol; // The symbol to relocate with. 34288943Sdim unsigned Type; // The type of the relocation. 35288943Sdim uint64_t Addend; // The addend to use. 36309124Sdim const MCSymbolELF *OriginalSymbol; // The original value of Symbol if we changed it. 37309124Sdim uint64_t OriginalAddend; // The original value of addend. 38288943Sdim 39288943Sdim ELFRelocationEntry(uint64_t Offset, const MCSymbolELF *Symbol, unsigned Type, 40309124Sdim uint64_t Addend, const MCSymbolELF *OriginalSymbol, 41309124Sdim uint64_t OriginalAddend) 42309124Sdim : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend), 43309124Sdim OriginalSymbol(OriginalSymbol), OriginalAddend(OriginalAddend) {} 44309124Sdim 45309124Sdim void print(raw_ostream &Out) const { 46309124Sdim Out << "Off=" << Offset << ", Sym=" << Symbol << ", Type=" << Type 47309124Sdim << ", Addend=" << Addend << ", OriginalSymbol=" << OriginalSymbol 48309124Sdim << ", OriginalAddend=" << OriginalAddend; 49309124Sdim } 50321369Sdim 51309124Sdim void dump() const { print(errs()); } 52288943Sdim}; 53288943Sdim 54341825Sdimclass MCELFObjectTargetWriter : public MCObjectTargetWriter { 55234353Sdim const uint8_t OSABI; 56353358Sdim const uint8_t ABIVersion; 57218885Sdim const uint16_t EMachine; 58218885Sdim const unsigned HasRelocationAddend : 1; 59218885Sdim const unsigned Is64Bit : 1; 60234353Sdim 61218885Sdimprotected: 62321369Sdim MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_, uint16_t EMachine_, 63353358Sdim bool HasRelocationAddend_, uint8_t ABIVersion_ = 0); 64234353Sdim 65321369Sdimpublic: 66321369Sdim virtual ~MCELFObjectTargetWriter() = default; 67218885Sdim 68341825Sdim virtual Triple::ObjectFormatType getFormat() const { return Triple::ELF; } 69341825Sdim static bool classof(const MCObjectTargetWriter *W) { 70341825Sdim return W->getFormat() == Triple::ELF; 71341825Sdim } 72341825Sdim 73234353Sdim static uint8_t getOSABI(Triple::OSType OSType) { 74234353Sdim switch (OSType) { 75288943Sdim case Triple::CloudABI: 76288943Sdim return ELF::ELFOSABI_CLOUDABI; 77344779Sdim case Triple::HermitCore: 78344779Sdim return ELF::ELFOSABI_STANDALONE; 79288943Sdim case Triple::PS4: 80234353Sdim case Triple::FreeBSD: 81234353Sdim return ELF::ELFOSABI_FREEBSD; 82234353Sdim default: 83234353Sdim return ELF::ELFOSABI_NONE; 84234353Sdim } 85234353Sdim } 86218885Sdim 87309124Sdim virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target, 88309124Sdim const MCFixup &Fixup, bool IsPCRel) const = 0; 89234353Sdim 90288943Sdim virtual bool needsRelocateWithSymbol(const MCSymbol &Sym, 91276479Sdim unsigned Type) const; 92234353Sdim 93288943Sdim virtual void sortRelocs(const MCAssembler &Asm, 94288943Sdim std::vector<ELFRelocationEntry> &Relocs); 95288943Sdim 96344779Sdim virtual void addTargetSectionFlags(MCContext &Ctx, MCSectionELF &Sec); 97344779Sdim 98288943Sdim /// \name Accessors 99218885Sdim /// @{ 100243830Sdim uint8_t getOSABI() const { return OSABI; } 101353358Sdim uint8_t getABIVersion() const { return ABIVersion; } 102243830Sdim uint16_t getEMachine() const { return EMachine; } 103243830Sdim bool hasRelocationAddend() const { return HasRelocationAddend; } 104234353Sdim bool is64Bit() const { return Is64Bit; } 105218885Sdim /// @} 106239462Sdim 107239462Sdim // Instead of changing everyone's API we pack the N64 Type fields 108239462Sdim // into the existing 32 bit data unsigned. 109239462Sdim#define R_TYPE_SHIFT 0 110239462Sdim#define R_TYPE_MASK 0xffffff00 111239462Sdim#define R_TYPE2_SHIFT 8 112239462Sdim#define R_TYPE2_MASK 0xffff00ff 113239462Sdim#define R_TYPE3_SHIFT 16 114239462Sdim#define R_TYPE3_MASK 0xff00ffff 115239462Sdim#define R_SSYM_SHIFT 24 116239462Sdim#define R_SSYM_MASK 0x00ffffff 117239462Sdim 118239462Sdim // N64 relocation type accessors 119276479Sdim uint8_t getRType(uint32_t Type) const { 120239462Sdim return (unsigned)((Type >> R_TYPE_SHIFT) & 0xff); 121239462Sdim } 122276479Sdim uint8_t getRType2(uint32_t Type) const { 123239462Sdim return (unsigned)((Type >> R_TYPE2_SHIFT) & 0xff); 124239462Sdim } 125276479Sdim uint8_t getRType3(uint32_t Type) const { 126239462Sdim return (unsigned)((Type >> R_TYPE3_SHIFT) & 0xff); 127239462Sdim } 128276479Sdim uint8_t getRSsym(uint32_t Type) const { 129239462Sdim return (unsigned)((Type >> R_SSYM_SHIFT) & 0xff); 130239462Sdim } 131239462Sdim 132239462Sdim // N64 relocation type setting 133239462Sdim unsigned setRType(unsigned Value, unsigned Type) const { 134239462Sdim return ((Type & R_TYPE_MASK) | ((Value & 0xff) << R_TYPE_SHIFT)); 135239462Sdim } 136239462Sdim unsigned setRType2(unsigned Value, unsigned Type) const { 137239462Sdim return (Type & R_TYPE2_MASK) | ((Value & 0xff) << R_TYPE2_SHIFT); 138239462Sdim } 139239462Sdim unsigned setRType3(unsigned Value, unsigned Type) const { 140239462Sdim return (Type & R_TYPE3_MASK) | ((Value & 0xff) << R_TYPE3_SHIFT); 141239462Sdim } 142239462Sdim unsigned setRSsym(unsigned Value, unsigned Type) const { 143239462Sdim return (Type & R_SSYM_MASK) | ((Value & 0xff) << R_SSYM_SHIFT); 144239462Sdim } 145218885Sdim}; 146218885Sdim 147341825Sdim/// Construct a new ELF writer instance. 148218885Sdim/// 149218885Sdim/// \param MOTW - The target specific ELF writer subclass. 150218885Sdim/// \param OS - The stream to write to. 151218885Sdim/// \returns The constructed object writer. 152327952Sdimstd::unique_ptr<MCObjectWriter> 153327952SdimcreateELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW, 154327952Sdim raw_pwrite_stream &OS, bool IsLittleEndian); 155218885Sdim 156341825Sdimstd::unique_ptr<MCObjectWriter> 157341825SdimcreateELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW, 158341825Sdim raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS, 159341825Sdim bool IsLittleEndian); 160341825Sdim 161321369Sdim} // end namespace llvm 162321369Sdim 163321369Sdim#endif // LLVM_MC_MCELFOBJECTWRITER_H 164