1 //===- PPC.cpp ------------------------------------------------------------===// 2 // 3 // The LLVM Linker 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 "Symbols.h" 11 #include "Target.h" 12 #include "lld/Common/ErrorHandler.h" 13 #include "llvm/Support/Endian.h" 14 15 using namespace llvm; 16 using namespace llvm::support::endian; 17 using namespace llvm::ELF; 18 using namespace lld; 19 using namespace lld::elf; 20 21 namespace { 22 class PPC final : public TargetInfo { 23 public: 24 PPC(); 25 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; 26 RelExpr getRelExpr(RelType Type, const Symbol &S, 27 const uint8_t *Loc) const override; 28 }; 29 } // namespace 30 31 PPC::PPC() { 32 NoneRel = R_PPC_NONE; 33 GotBaseSymOff = 0x8000; 34 GotBaseSymInGotPlt = false; 35 } 36 37 RelExpr PPC::getRelExpr(RelType Type, const Symbol &S, 38 const uint8_t *Loc) const { 39 switch (Type) { 40 case R_PPC_REL14: 41 case R_PPC_REL24: 42 case R_PPC_REL32: 43 return R_PC; 44 case R_PPC_PLTREL24: 45 return R_PLT_PC; 46 default: 47 return R_ABS; 48 } 49 } 50 51 void PPC::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { 52 switch (Type) { 53 case R_PPC_ADDR16_HA: 54 write16be(Loc, (Val + 0x8000) >> 16); 55 break; 56 case R_PPC_ADDR16_HI: 57 write16be(Loc, Val >> 16); 58 break; 59 case R_PPC_ADDR16_LO: 60 write16be(Loc, Val); 61 break; 62 case R_PPC_ADDR32: 63 case R_PPC_REL32: 64 write32be(Loc, Val); 65 break; 66 case R_PPC_REL14: 67 write32be(Loc, read32be(Loc) | (Val & 0xFFFC)); 68 break; 69 case R_PPC_PLTREL24: 70 case R_PPC_REL24: 71 write32be(Loc, read32be(Loc) | (Val & 0x3FFFFFC)); 72 break; 73 default: 74 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); 75 } 76 } 77 78 TargetInfo *elf::getPPCTargetInfo() { 79 static PPC Target; 80 return &Target; 81 } 82