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
PPC()31 PPC::PPC() {
32 NoneRel = R_PPC_NONE;
33 GotBaseSymOff = 0x8000;
34 GotBaseSymInGotPlt = false;
35 }
36
getRelExpr(RelType Type,const Symbol & S,const uint8_t * Loc) const37 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
relocateOne(uint8_t * Loc,RelType Type,uint64_t Val) const51 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
getPPCTargetInfo()78 TargetInfo *elf::getPPCTargetInfo() {
79 static PPC Target;
80 return &Target;
81 }
82