1 //===- AMDGPU.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 "InputFiles.h" 10 #include "Symbols.h" 11 #include "Target.h" 12 #include "lld/Common/ErrorHandler.h" 13 #include "llvm/Object/ELF.h" 14 #include "llvm/Support/Endian.h" 15 16 using namespace llvm; 17 using namespace llvm::object; 18 using namespace llvm::support::endian; 19 using namespace llvm::ELF; 20 21 namespace lld { 22 namespace elf { 23 24 namespace { 25 class AMDGPU final : public TargetInfo { 26 public: 27 AMDGPU(); 28 uint32_t calcEFlags() const override; 29 void relocate(uint8_t *loc, const Relocation &rel, 30 uint64_t val) const override; 31 RelExpr getRelExpr(RelType type, const Symbol &s, 32 const uint8_t *loc) const override; 33 RelType getDynRel(RelType type) const override; 34 }; 35 } // namespace 36 37 AMDGPU::AMDGPU() { 38 relativeRel = R_AMDGPU_RELATIVE64; 39 gotRel = R_AMDGPU_ABS64; 40 noneRel = R_AMDGPU_NONE; 41 symbolicRel = R_AMDGPU_ABS64; 42 } 43 44 static uint32_t getEFlags(InputFile *file) { 45 return cast<ObjFile<ELF64LE>>(file)->getObj().getHeader()->e_flags; 46 } 47 48 uint32_t AMDGPU::calcEFlags() const { 49 assert(!objectFiles.empty()); 50 uint32_t ret = getEFlags(objectFiles[0]); 51 52 // Verify that all input files have the same e_flags. 53 for (InputFile *f : makeArrayRef(objectFiles).slice(1)) { 54 if (ret == getEFlags(f)) 55 continue; 56 error("incompatible e_flags: " + toString(f)); 57 return 0; 58 } 59 return ret; 60 } 61 62 void AMDGPU::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { 63 switch (rel.type) { 64 case R_AMDGPU_ABS32: 65 case R_AMDGPU_GOTPCREL: 66 case R_AMDGPU_GOTPCREL32_LO: 67 case R_AMDGPU_REL32: 68 case R_AMDGPU_REL32_LO: 69 write32le(loc, val); 70 break; 71 case R_AMDGPU_ABS64: 72 case R_AMDGPU_REL64: 73 write64le(loc, val); 74 break; 75 case R_AMDGPU_GOTPCREL32_HI: 76 case R_AMDGPU_REL32_HI: 77 write32le(loc, val >> 32); 78 break; 79 default: 80 llvm_unreachable("unknown relocation"); 81 } 82 } 83 84 RelExpr AMDGPU::getRelExpr(RelType type, const Symbol &s, 85 const uint8_t *loc) const { 86 switch (type) { 87 case R_AMDGPU_ABS32: 88 case R_AMDGPU_ABS64: 89 return R_ABS; 90 case R_AMDGPU_REL32: 91 case R_AMDGPU_REL32_LO: 92 case R_AMDGPU_REL32_HI: 93 case R_AMDGPU_REL64: 94 return R_PC; 95 case R_AMDGPU_GOTPCREL: 96 case R_AMDGPU_GOTPCREL32_LO: 97 case R_AMDGPU_GOTPCREL32_HI: 98 return R_GOT_PC; 99 default: 100 error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + 101 ") against symbol " + toString(s)); 102 return R_NONE; 103 } 104 } 105 106 RelType AMDGPU::getDynRel(RelType type) const { 107 if (type == R_AMDGPU_ABS64) 108 return type; 109 return R_AMDGPU_NONE; 110 } 111 112 TargetInfo *getAMDGPUTargetInfo() { 113 static AMDGPU target; 114 return ⌖ 115 } 116 117 } // namespace elf 118 } // namespace lld 119