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