1 //===- PPC64.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 "Error.h" 11 #include "Symbols.h" 12 #include "SyntheticSections.h" 13 #include "Target.h" 14 #include "llvm/Support/Endian.h" 15 16 using namespace llvm; 17 using namespace llvm::support::endian; 18 using namespace llvm::ELF; 19 using namespace lld; 20 using namespace lld::elf; 21 22 static uint64_t PPC64TocOffset = 0x8000; 23 24 uint64_t elf::getPPC64TocBase() { 25 // The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The 26 // TOC starts where the first of these sections starts. We always create a 27 // .got when we see a relocation that uses it, so for us the start is always 28 // the .got. 29 uint64_t TocVA = InX::Got->getVA(); 30 31 // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000 32 // thus permitting a full 64 Kbytes segment. Note that the glibc startup 33 // code (crt1.o) assumes that you can get from the TOC base to the 34 // start of the .toc section with only a single (signed) 16-bit relocation. 35 return TocVA + PPC64TocOffset; 36 } 37 38 namespace { 39 class PPC64 final : public TargetInfo { 40 public: 41 PPC64(); 42 RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, 43 const uint8_t *Loc) const override; 44 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, 45 int32_t Index, unsigned RelOff) const override; 46 void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; 47 }; 48 } // namespace 49 50 // Relocation masks following the #lo(value), #hi(value), #ha(value), 51 // #higher(value), #highera(value), #highest(value), and #highesta(value) 52 // macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi 53 // document. 54 static uint16_t applyPPCLo(uint64_t V) { return V; } 55 static uint16_t applyPPCHi(uint64_t V) { return V >> 16; } 56 static uint16_t applyPPCHa(uint64_t V) { return (V + 0x8000) >> 16; } 57 static uint16_t applyPPCHigher(uint64_t V) { return V >> 32; } 58 static uint16_t applyPPCHighera(uint64_t V) { return (V + 0x8000) >> 32; } 59 static uint16_t applyPPCHighest(uint64_t V) { return V >> 48; } 60 static uint16_t applyPPCHighesta(uint64_t V) { return (V + 0x8000) >> 48; } 61 62 PPC64::PPC64() { 63 PltRel = GotRel = R_PPC64_GLOB_DAT; 64 RelativeRel = R_PPC64_RELATIVE; 65 GotEntrySize = 8; 66 GotPltEntrySize = 8; 67 PltEntrySize = 32; 68 PltHeaderSize = 0; 69 70 // We need 64K pages (at least under glibc/Linux, the loader won't 71 // set different permissions on a finer granularity than that). 72 DefaultMaxPageSize = 65536; 73 74 // The PPC64 ELF ABI v1 spec, says: 75 // 76 // It is normally desirable to put segments with different characteristics 77 // in separate 256 Mbyte portions of the address space, to give the 78 // operating system full paging flexibility in the 64-bit address space. 79 // 80 // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers 81 // use 0x10000000 as the starting address. 82 DefaultImageBase = 0x10000000; 83 } 84 85 RelExpr PPC64::getRelExpr(uint32_t Type, const SymbolBody &S, 86 const uint8_t *Loc) const { 87 switch (Type) { 88 default: 89 return R_ABS; 90 case R_PPC64_TOC16: 91 case R_PPC64_TOC16_DS: 92 case R_PPC64_TOC16_HA: 93 case R_PPC64_TOC16_HI: 94 case R_PPC64_TOC16_LO: 95 case R_PPC64_TOC16_LO_DS: 96 return R_GOTREL; 97 case R_PPC64_TOC: 98 return R_PPC_TOC; 99 case R_PPC64_REL24: 100 return R_PPC_PLT_OPD; 101 } 102 } 103 104 void PPC64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, 105 uint64_t PltEntryAddr, int32_t Index, 106 unsigned RelOff) const { 107 uint64_t Off = GotPltEntryAddr - getPPC64TocBase(); 108 109 // FIXME: What we should do, in theory, is get the offset of the function 110 // descriptor in the .opd section, and use that as the offset from %r2 (the 111 // TOC-base pointer). Instead, we have the GOT-entry offset, and that will 112 // be a pointer to the function descriptor in the .opd section. Using 113 // this scheme is simpler, but requires an extra indirection per PLT dispatch. 114 115 write32be(Buf, 0xf8410028); // std %r2, 40(%r1) 116 write32be(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha 117 write32be(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11) 118 write32be(Buf + 12, 0xe96c0000); // ld %r11,0(%r12) 119 write32be(Buf + 16, 0x7d6903a6); // mtctr %r11 120 write32be(Buf + 20, 0xe84c0008); // ld %r2,8(%r12) 121 write32be(Buf + 24, 0xe96c0010); // ld %r11,16(%r12) 122 write32be(Buf + 28, 0x4e800420); // bctr 123 } 124 125 static std::pair<uint32_t, uint64_t> toAddr16Rel(uint32_t Type, uint64_t Val) { 126 uint64_t V = Val - PPC64TocOffset; 127 switch (Type) { 128 case R_PPC64_TOC16: 129 return {R_PPC64_ADDR16, V}; 130 case R_PPC64_TOC16_DS: 131 return {R_PPC64_ADDR16_DS, V}; 132 case R_PPC64_TOC16_HA: 133 return {R_PPC64_ADDR16_HA, V}; 134 case R_PPC64_TOC16_HI: 135 return {R_PPC64_ADDR16_HI, V}; 136 case R_PPC64_TOC16_LO: 137 return {R_PPC64_ADDR16_LO, V}; 138 case R_PPC64_TOC16_LO_DS: 139 return {R_PPC64_ADDR16_LO_DS, V}; 140 default: 141 return {Type, Val}; 142 } 143 } 144 145 void PPC64::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { 146 // For a TOC-relative relocation, proceed in terms of the corresponding 147 // ADDR16 relocation type. 148 std::tie(Type, Val) = toAddr16Rel(Type, Val); 149 150 switch (Type) { 151 case R_PPC64_ADDR14: { 152 checkAlignment<4>(Loc, Val, Type); 153 // Preserve the AA/LK bits in the branch instruction 154 uint8_t AALK = Loc[3]; 155 write16be(Loc + 2, (AALK & 3) | (Val & 0xfffc)); 156 break; 157 } 158 case R_PPC64_ADDR16: 159 checkInt<16>(Loc, Val, Type); 160 write16be(Loc, Val); 161 break; 162 case R_PPC64_ADDR16_DS: 163 checkInt<16>(Loc, Val, Type); 164 write16be(Loc, (read16be(Loc) & 3) | (Val & ~3)); 165 break; 166 case R_PPC64_ADDR16_HA: 167 case R_PPC64_REL16_HA: 168 write16be(Loc, applyPPCHa(Val)); 169 break; 170 case R_PPC64_ADDR16_HI: 171 case R_PPC64_REL16_HI: 172 write16be(Loc, applyPPCHi(Val)); 173 break; 174 case R_PPC64_ADDR16_HIGHER: 175 write16be(Loc, applyPPCHigher(Val)); 176 break; 177 case R_PPC64_ADDR16_HIGHERA: 178 write16be(Loc, applyPPCHighera(Val)); 179 break; 180 case R_PPC64_ADDR16_HIGHEST: 181 write16be(Loc, applyPPCHighest(Val)); 182 break; 183 case R_PPC64_ADDR16_HIGHESTA: 184 write16be(Loc, applyPPCHighesta(Val)); 185 break; 186 case R_PPC64_ADDR16_LO: 187 write16be(Loc, applyPPCLo(Val)); 188 break; 189 case R_PPC64_ADDR16_LO_DS: 190 case R_PPC64_REL16_LO: 191 write16be(Loc, (read16be(Loc) & 3) | (applyPPCLo(Val) & ~3)); 192 break; 193 case R_PPC64_ADDR32: 194 case R_PPC64_REL32: 195 checkInt<32>(Loc, Val, Type); 196 write32be(Loc, Val); 197 break; 198 case R_PPC64_ADDR64: 199 case R_PPC64_REL64: 200 case R_PPC64_TOC: 201 write64be(Loc, Val); 202 break; 203 case R_PPC64_REL24: { 204 uint32_t Mask = 0x03FFFFFC; 205 checkInt<24>(Loc, Val, Type); 206 write32be(Loc, (read32be(Loc) & ~Mask) | (Val & Mask)); 207 break; 208 } 209 default: 210 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); 211 } 212 } 213 214 TargetInfo *elf::getPPC64TargetInfo() { 215 static PPC64 Target; 216 return &Target; 217 } 218