Path: blob/main/contrib/llvm-project/lld/ELF/Arch/SPARCV9.cpp
34878 views
//===- SPARCV9.cpp --------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "Symbols.h"9#include "SyntheticSections.h"10#include "Target.h"11#include "lld/Common/ErrorHandler.h"12#include "llvm/Support/Endian.h"1314using namespace llvm;15using namespace llvm::support::endian;16using namespace llvm::ELF;17using namespace lld;18using namespace lld::elf;1920namespace {21class SPARCV9 final : public TargetInfo {22public:23SPARCV9();24RelExpr getRelExpr(RelType type, const Symbol &s,25const uint8_t *loc) const override;26void writePlt(uint8_t *buf, const Symbol &sym,27uint64_t pltEntryAddr) const override;28void relocate(uint8_t *loc, const Relocation &rel,29uint64_t val) const override;30};31} // namespace3233SPARCV9::SPARCV9() {34copyRel = R_SPARC_COPY;35gotRel = R_SPARC_GLOB_DAT;36pltRel = R_SPARC_JMP_SLOT;37relativeRel = R_SPARC_RELATIVE;38symbolicRel = R_SPARC_64;39pltEntrySize = 32;40pltHeaderSize = 4 * pltEntrySize;4142defaultCommonPageSize = 8192;43defaultMaxPageSize = 0x100000;44defaultImageBase = 0x100000;45}4647RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s,48const uint8_t *loc) const {49switch (type) {50case R_SPARC_32:51case R_SPARC_UA32:52case R_SPARC_64:53case R_SPARC_UA64:54case R_SPARC_H44:55case R_SPARC_M44:56case R_SPARC_L44:57case R_SPARC_HH22:58case R_SPARC_HM10:59case R_SPARC_LM22:60case R_SPARC_HI22:61case R_SPARC_LO10:62return R_ABS;63case R_SPARC_PC10:64case R_SPARC_PC22:65case R_SPARC_DISP32:66case R_SPARC_WDISP30:67return R_PC;68case R_SPARC_GOT10:69return R_GOT_OFF;70case R_SPARC_GOT22:71return R_GOT_OFF;72case R_SPARC_WPLT30:73return R_PLT_PC;74case R_SPARC_NONE:75return R_NONE;76case R_SPARC_TLS_LE_HIX22:77case R_SPARC_TLS_LE_LOX10:78return R_TPREL;79default:80error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +81") against symbol " + toString(s));82return R_NONE;83}84}8586void SPARCV9::relocate(uint8_t *loc, const Relocation &rel,87uint64_t val) const {88switch (rel.type) {89case R_SPARC_32:90case R_SPARC_UA32:91// V-word3292checkUInt(loc, val, 32, rel);93write32be(loc, val);94break;95case R_SPARC_DISP32:96// V-disp3297checkInt(loc, val, 32, rel);98write32be(loc, val);99break;100case R_SPARC_WDISP30:101case R_SPARC_WPLT30:102// V-disp30103checkInt(loc, val, 32, rel);104write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff));105break;106case R_SPARC_22:107// V-imm22108checkUInt(loc, val, 22, rel);109write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff));110break;111case R_SPARC_GOT22:112case R_SPARC_PC22:113case R_SPARC_LM22:114// T-imm22115write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));116break;117case R_SPARC_HI22:118// V-imm22119checkUInt(loc, val >> 10, 22, rel);120write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));121break;122case R_SPARC_WDISP19:123// V-disp19124checkInt(loc, val, 21, rel);125write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff));126break;127case R_SPARC_GOT10:128case R_SPARC_PC10:129// T-simm10130write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff));131break;132case R_SPARC_LO10:133// T-simm13134write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff));135break;136case R_SPARC_64:137case R_SPARC_UA64:138// V-xword64139write64be(loc, val);140break;141case R_SPARC_HH22:142// V-imm22143checkUInt(loc, val >> 42, 22, rel);144write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 42) & 0x003fffff));145break;146case R_SPARC_HM10:147// T-simm13148write32be(loc, (read32be(loc) & ~0x00001fff) | ((val >> 32) & 0x000003ff));149break;150case R_SPARC_H44:151// V-imm22152checkUInt(loc, val >> 22, 22, rel);153write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 22) & 0x003fffff));154break;155case R_SPARC_M44:156// T-imm10157write32be(loc, (read32be(loc) & ~0x000003ff) | ((val >> 12) & 0x000003ff));158break;159case R_SPARC_L44:160// T-imm13161write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x00000fff));162break;163case R_SPARC_TLS_LE_HIX22:164// T-imm22165write32be(loc, (read32be(loc) & ~0x003fffff) | ((~val >> 10) & 0x003fffff));166break;167case R_SPARC_TLS_LE_LOX10:168// T-simm13169write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff) | 0x1C00);170break;171default:172llvm_unreachable("unknown relocation");173}174}175176void SPARCV9::writePlt(uint8_t *buf, const Symbol & /*sym*/,177uint64_t pltEntryAddr) const {178const uint8_t pltData[] = {1790x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g11800x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT11810x01, 0x00, 0x00, 0x00, // nop1820x01, 0x00, 0x00, 0x00, // nop1830x01, 0x00, 0x00, 0x00, // nop1840x01, 0x00, 0x00, 0x00, // nop1850x01, 0x00, 0x00, 0x00, // nop1860x01, 0x00, 0x00, 0x00 // nop187};188memcpy(buf, pltData, sizeof(pltData));189190uint64_t off = pltEntryAddr - in.plt->getVA();191relocateNoSym(buf, R_SPARC_22, off);192relocateNoSym(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize));193}194195TargetInfo *elf::getSPARCV9TargetInfo() {196static SPARCV9 target;197return ⌖198}199200201