1218885Sdim//===-- llvm/MC/MCELFObjectWriter.h - ELF Object Writer ---------*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim 10218885Sdim#ifndef LLVM_MC_MCELFOBJECTWRITER_H 11218885Sdim#define LLVM_MC_MCELFOBJECTWRITER_H 12218885Sdim 13234353Sdim#include "llvm/ADT/Triple.h" 14218885Sdim#include "llvm/Support/DataTypes.h" 15234353Sdim#include "llvm/Support/ELF.h" 16234353Sdim#include <vector> 17218885Sdim 18218885Sdimnamespace llvm { 19234353Sdimclass MCAssembler; 20234353Sdimclass MCFixup; 21234353Sdimclass MCFragment; 22234353Sdimclass MCObjectWriter; 23234353Sdimclass MCSymbol; 24234353Sdimclass MCValue; 25234353Sdim 26234353Sdim/// @name Relocation Data 27234353Sdim/// @{ 28234353Sdim 29234353Sdimstruct ELFRelocationEntry { 30234353Sdim // Make these big enough for both 32-bit and 64-bit 31234353Sdim uint64_t r_offset; 32234353Sdim int Index; 33234353Sdim unsigned Type; 34234353Sdim const MCSymbol *Symbol; 35234353Sdim uint64_t r_addend; 36234353Sdim const MCFixup *Fixup; 37234353Sdim 38234353Sdim ELFRelocationEntry() 39234353Sdim : r_offset(0), Index(0), Type(0), Symbol(0), r_addend(0), Fixup(0) {} 40234353Sdim 41234353Sdim ELFRelocationEntry(uint64_t RelocOffset, int Idx, unsigned RelType, 42234353Sdim const MCSymbol *Sym, uint64_t Addend, const MCFixup &Fixup) 43234353Sdim : r_offset(RelocOffset), Index(Idx), Type(RelType), Symbol(Sym), 44234353Sdim r_addend(Addend), Fixup(&Fixup) {} 45234353Sdim}; 46234353Sdim 47218885Sdimclass MCELFObjectTargetWriter { 48234353Sdim const uint8_t OSABI; 49218885Sdim const uint16_t EMachine; 50218885Sdim const unsigned HasRelocationAddend : 1; 51218885Sdim const unsigned Is64Bit : 1; 52239462Sdim const unsigned IsN64 : 1; 53234353Sdim 54218885Sdimprotected: 55234353Sdim 56234353Sdim MCELFObjectTargetWriter(bool Is64Bit_, uint8_t OSABI_, 57239462Sdim uint16_t EMachine_, bool HasRelocationAddend, 58239462Sdim bool IsN64=false); 59218885Sdim 60218885Sdimpublic: 61234353Sdim static uint8_t getOSABI(Triple::OSType OSType) { 62234353Sdim switch (OSType) { 63234353Sdim case Triple::FreeBSD: 64234353Sdim return ELF::ELFOSABI_FREEBSD; 65234353Sdim case Triple::Linux: 66234353Sdim return ELF::ELFOSABI_LINUX; 67234353Sdim default: 68234353Sdim return ELF::ELFOSABI_NONE; 69234353Sdim } 70234353Sdim } 71218885Sdim 72234353Sdim virtual ~MCELFObjectTargetWriter() {} 73234353Sdim 74234353Sdim virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 75234353Sdim bool IsPCRel, bool IsRelocWithSymbol, 76234353Sdim int64_t Addend) const = 0; 77234353Sdim virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, 78234353Sdim const MCValue &Target, 79234353Sdim const MCFragment &F, 80234353Sdim const MCFixup &Fixup, 81234353Sdim bool IsPCRel) const; 82243830Sdim virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, 83243830Sdim const MCFixup &Fixup, 84243830Sdim bool IsPCRel) const; 85234353Sdim 86234353Sdim virtual void sortRelocs(const MCAssembler &Asm, 87234353Sdim std::vector<ELFRelocationEntry> &Relocs); 88234353Sdim 89218885Sdim /// @name Accessors 90218885Sdim /// @{ 91243830Sdim uint8_t getOSABI() const { return OSABI; } 92243830Sdim uint16_t getEMachine() const { return EMachine; } 93243830Sdim bool hasRelocationAddend() const { return HasRelocationAddend; } 94234353Sdim bool is64Bit() const { return Is64Bit; } 95239462Sdim bool isN64() const { return IsN64; } 96218885Sdim /// @} 97239462Sdim 98239462Sdim // Instead of changing everyone's API we pack the N64 Type fields 99239462Sdim // into the existing 32 bit data unsigned. 100239462Sdim#define R_TYPE_SHIFT 0 101239462Sdim#define R_TYPE_MASK 0xffffff00 102239462Sdim#define R_TYPE2_SHIFT 8 103239462Sdim#define R_TYPE2_MASK 0xffff00ff 104239462Sdim#define R_TYPE3_SHIFT 16 105239462Sdim#define R_TYPE3_MASK 0xff00ffff 106239462Sdim#define R_SSYM_SHIFT 24 107239462Sdim#define R_SSYM_MASK 0x00ffffff 108239462Sdim 109239462Sdim // N64 relocation type accessors 110239462Sdim unsigned getRType(uint32_t Type) const { 111239462Sdim return (unsigned)((Type >> R_TYPE_SHIFT) & 0xff); 112239462Sdim } 113239462Sdim unsigned getRType2(uint32_t Type) const { 114239462Sdim return (unsigned)((Type >> R_TYPE2_SHIFT) & 0xff); 115239462Sdim } 116239462Sdim unsigned getRType3(uint32_t Type) const { 117239462Sdim return (unsigned)((Type >> R_TYPE3_SHIFT) & 0xff); 118239462Sdim } 119239462Sdim unsigned getRSsym(uint32_t Type) const { 120239462Sdim return (unsigned)((Type >> R_SSYM_SHIFT) & 0xff); 121239462Sdim } 122239462Sdim 123239462Sdim // N64 relocation type setting 124239462Sdim unsigned setRType(unsigned Value, unsigned Type) const { 125239462Sdim return ((Type & R_TYPE_MASK) | ((Value & 0xff) << R_TYPE_SHIFT)); 126239462Sdim } 127239462Sdim unsigned setRType2(unsigned Value, unsigned Type) const { 128239462Sdim return (Type & R_TYPE2_MASK) | ((Value & 0xff) << R_TYPE2_SHIFT); 129239462Sdim } 130239462Sdim unsigned setRType3(unsigned Value, unsigned Type) const { 131239462Sdim return (Type & R_TYPE3_MASK) | ((Value & 0xff) << R_TYPE3_SHIFT); 132239462Sdim } 133239462Sdim unsigned setRSsym(unsigned Value, unsigned Type) const { 134239462Sdim return (Type & R_SSYM_MASK) | ((Value & 0xff) << R_SSYM_SHIFT); 135239462Sdim } 136218885Sdim}; 137218885Sdim 138218885Sdim/// \brief Construct a new ELF writer instance. 139218885Sdim/// 140218885Sdim/// \param MOTW - The target specific ELF writer subclass. 141218885Sdim/// \param OS - The stream to write to. 142218885Sdim/// \returns The constructed object writer. 143218885SdimMCObjectWriter *createELFObjectWriter(MCELFObjectTargetWriter *MOTW, 144218885Sdim raw_ostream &OS, bool IsLittleEndian); 145218885Sdim} // End llvm namespace 146218885Sdim 147218885Sdim#endif 148