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