1 //===- PPC.cpp ------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Symbols.h" 10 #include "Target.h" 11 #include "lld/Common/ErrorHandler.h" 12 #include "llvm/Support/Endian.h" 13 14 using namespace llvm; 15 using namespace llvm::support::endian; 16 using namespace llvm::ELF; 17 using namespace lld; 18 using namespace lld::elf; 19 20 namespace { 21 class PPC final : public TargetInfo { 22 public: 23 PPC(); 24 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; 25 RelExpr getRelExpr(RelType Type, const Symbol &S, 26 const uint8_t *Loc) const override; 27 }; 28 } // namespace 29 30 PPC::PPC() { 31 NoneRel = R_PPC_NONE; 32 GotBaseSymInGotPlt = false; 33 } 34 35 RelExpr PPC::getRelExpr(RelType Type, const Symbol &S, 36 const uint8_t *Loc) const { 37 switch (Type) { 38 case R_PPC_REL14: 39 case R_PPC_REL24: 40 case R_PPC_REL32: 41 return R_PC; 42 case R_PPC_PLTREL24: 43 return R_PLT_PC; 44 default: 45 return R_ABS; 46 } 47 } 48 49 void PPC::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { 50 switch (Type) { 51 case R_PPC_ADDR16_HA: 52 write16be(Loc, (Val + 0x8000) >> 16); 53 break; 54 case R_PPC_ADDR16_HI: 55 write16be(Loc, Val >> 16); 56 break; 57 case R_PPC_ADDR16_LO: 58 write16be(Loc, Val); 59 break; 60 case R_PPC_ADDR32: 61 case R_PPC_REL32: 62 write32be(Loc, Val); 63 break; 64 case R_PPC_REL14: 65 write32be(Loc, read32be(Loc) | (Val & 0xFFFC)); 66 break; 67 case R_PPC_PLTREL24: 68 case R_PPC_REL24: 69 write32be(Loc, read32be(Loc) | (Val & 0x3FFFFFC)); 70 break; 71 default: 72 error(getErrorLocation(Loc) + "unrecognized relocation " + toString(Type)); 73 } 74 } 75 76 TargetInfo *elf::getPPCTargetInfo() { 77 static PPC Target; 78 return &Target; 79 } 80