1 //===-- PPCELFObjectWriter.cpp - PPC ELF Writer ---------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "MCTargetDesc/PPCFixupKinds.h" 11 #include "MCTargetDesc/PPCMCTargetDesc.h" 12 #include "llvm/MC/MCELFObjectWriter.h" 13 #include "llvm/Support/ErrorHandling.h" 14 15 using namespace llvm; 16 17 namespace { 18 class PPCELFObjectWriter : public MCELFObjectTargetWriter { 19 public: 20 PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI); 21 22 virtual ~PPCELFObjectWriter(); 23 protected: 24 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 25 bool IsPCRel, bool IsRelocWithSymbol, 26 int64_t Addend) const; 27 virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset); 28 }; 29 } 30 31 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) 32 : MCELFObjectTargetWriter(Is64Bit, OSABI, 33 Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC, 34 /*HasRelocationAddend*/ true) {} 35 36 PPCELFObjectWriter::~PPCELFObjectWriter() { 37 } 38 39 unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target, 40 const MCFixup &Fixup, 41 bool IsPCRel, 42 bool IsRelocWithSymbol, 43 int64_t Addend) const { 44 // determine the type of the relocation 45 unsigned Type; 46 if (IsPCRel) { 47 switch ((unsigned)Fixup.getKind()) { 48 default: 49 llvm_unreachable("Unimplemented"); 50 case PPC::fixup_ppc_br24: 51 Type = ELF::R_PPC_REL24; 52 break; 53 case FK_PCRel_4: 54 Type = ELF::R_PPC_REL32; 55 break; 56 } 57 } else { 58 switch ((unsigned)Fixup.getKind()) { 59 default: llvm_unreachable("invalid fixup kind!"); 60 case PPC::fixup_ppc_br24: 61 Type = ELF::R_PPC_ADDR24; 62 break; 63 case PPC::fixup_ppc_brcond14: 64 Type = ELF::R_PPC_ADDR14_BRTAKEN; // XXX: or BRNTAKEN?_ 65 break; 66 case PPC::fixup_ppc_ha16: 67 Type = ELF::R_PPC_ADDR16_HA; 68 break; 69 case PPC::fixup_ppc_lo16: 70 Type = ELF::R_PPC_ADDR16_LO; 71 break; 72 case PPC::fixup_ppc_lo14: 73 Type = ELF::R_PPC_ADDR14; 74 break; 75 case FK_Data_4: 76 Type = ELF::R_PPC_ADDR32; 77 break; 78 case FK_Data_2: 79 Type = ELF::R_PPC_ADDR16; 80 break; 81 } 82 } 83 return Type; 84 } 85 86 void PPCELFObjectWriter:: 87 adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) { 88 switch ((unsigned)Fixup.getKind()) { 89 case PPC::fixup_ppc_ha16: 90 case PPC::fixup_ppc_lo16: 91 RelocOffset += 2; 92 break; 93 default: 94 break; 95 } 96 } 97 98 MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS, 99 bool Is64Bit, 100 uint8_t OSABI) { 101 MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI); 102 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false); 103 } 104