1320541Sdim//===- SPARCV9.cpp --------------------------------------------------------===// 2320541Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6320541Sdim// 7320541Sdim//===----------------------------------------------------------------------===// 8320541Sdim 9320541Sdim#include "InputFiles.h" 10320541Sdim#include "Symbols.h" 11320541Sdim#include "SyntheticSections.h" 12320541Sdim#include "Target.h" 13327952Sdim#include "lld/Common/ErrorHandler.h" 14320541Sdim#include "llvm/Support/Endian.h" 15320541Sdim 16320541Sdimusing namespace llvm; 17320541Sdimusing namespace llvm::support::endian; 18320541Sdimusing namespace llvm::ELF; 19320541Sdim 20360784Sdimnamespace lld { 21360784Sdimnamespace elf { 22360784Sdim 23320541Sdimnamespace { 24320541Sdimclass SPARCV9 final : public TargetInfo { 25320541Sdimpublic: 26320541Sdim SPARCV9(); 27353358Sdim RelExpr getRelExpr(RelType type, const Symbol &s, 28353358Sdim const uint8_t *loc) const override; 29360784Sdim void writePlt(uint8_t *buf, const Symbol &sym, 30360784Sdim uint64_t pltEntryAddr) const override; 31353358Sdim void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; 32320541Sdim}; 33320541Sdim} // namespace 34320541Sdim 35320541SdimSPARCV9::SPARCV9() { 36353358Sdim copyRel = R_SPARC_COPY; 37353358Sdim gotRel = R_SPARC_GLOB_DAT; 38353358Sdim noneRel = R_SPARC_NONE; 39353358Sdim pltRel = R_SPARC_JMP_SLOT; 40353358Sdim relativeRel = R_SPARC_RELATIVE; 41353358Sdim symbolicRel = R_SPARC_64; 42353358Sdim pltEntrySize = 32; 43353358Sdim pltHeaderSize = 4 * pltEntrySize; 44320541Sdim 45353358Sdim defaultCommonPageSize = 8192; 46353358Sdim defaultMaxPageSize = 0x100000; 47353358Sdim defaultImageBase = 0x100000; 48320541Sdim} 49320541Sdim 50353358SdimRelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s, 51353358Sdim const uint8_t *loc) const { 52353358Sdim switch (type) { 53320541Sdim case R_SPARC_32: 54320541Sdim case R_SPARC_UA32: 55320541Sdim case R_SPARC_64: 56320541Sdim case R_SPARC_UA64: 57320541Sdim return R_ABS; 58320541Sdim case R_SPARC_PC10: 59320541Sdim case R_SPARC_PC22: 60320541Sdim case R_SPARC_DISP32: 61320541Sdim case R_SPARC_WDISP30: 62320541Sdim return R_PC; 63320541Sdim case R_SPARC_GOT10: 64320541Sdim return R_GOT_OFF; 65320541Sdim case R_SPARC_GOT22: 66320541Sdim return R_GOT_OFF; 67320541Sdim case R_SPARC_WPLT30: 68320541Sdim return R_PLT_PC; 69320541Sdim case R_SPARC_NONE: 70320541Sdim return R_NONE; 71320541Sdim default: 72353358Sdim error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + 73353358Sdim ") against symbol " + toString(s)); 74353358Sdim return R_NONE; 75320541Sdim } 76320541Sdim} 77320541Sdim 78353358Sdimvoid SPARCV9::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { 79353358Sdim switch (type) { 80320541Sdim case R_SPARC_32: 81320541Sdim case R_SPARC_UA32: 82320541Sdim // V-word32 83353358Sdim checkUInt(loc, val, 32, type); 84353358Sdim write32be(loc, val); 85320541Sdim break; 86320541Sdim case R_SPARC_DISP32: 87320541Sdim // V-disp32 88353358Sdim checkInt(loc, val, 32, type); 89353358Sdim write32be(loc, val); 90320541Sdim break; 91320541Sdim case R_SPARC_WDISP30: 92320541Sdim case R_SPARC_WPLT30: 93320541Sdim // V-disp30 94353358Sdim checkInt(loc, val, 32, type); 95353358Sdim write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff)); 96320541Sdim break; 97320541Sdim case R_SPARC_22: 98320541Sdim // V-imm22 99353358Sdim checkUInt(loc, val, 22, type); 100353358Sdim write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff)); 101320541Sdim break; 102320541Sdim case R_SPARC_GOT22: 103320541Sdim case R_SPARC_PC22: 104320541Sdim // T-imm22 105353358Sdim write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff)); 106320541Sdim break; 107320541Sdim case R_SPARC_WDISP19: 108320541Sdim // V-disp19 109353358Sdim checkInt(loc, val, 21, type); 110353358Sdim write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff)); 111320541Sdim break; 112320541Sdim case R_SPARC_GOT10: 113320541Sdim case R_SPARC_PC10: 114320541Sdim // T-simm10 115353358Sdim write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff)); 116320541Sdim break; 117320541Sdim case R_SPARC_64: 118320541Sdim case R_SPARC_UA64: 119320541Sdim // V-xword64 120353358Sdim write64be(loc, val); 121320541Sdim break; 122320541Sdim default: 123353358Sdim llvm_unreachable("unknown relocation"); 124320541Sdim } 125320541Sdim} 126320541Sdim 127360784Sdimvoid SPARCV9::writePlt(uint8_t *buf, const Symbol & /*sym*/, 128360784Sdim uint64_t pltEntryAddr) const { 129353358Sdim const uint8_t pltData[] = { 130320541Sdim 0x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g1 131320541Sdim 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1 132320541Sdim 0x01, 0x00, 0x00, 0x00, // nop 133320541Sdim 0x01, 0x00, 0x00, 0x00, // nop 134320541Sdim 0x01, 0x00, 0x00, 0x00, // nop 135320541Sdim 0x01, 0x00, 0x00, 0x00, // nop 136320541Sdim 0x01, 0x00, 0x00, 0x00, // nop 137320541Sdim 0x01, 0x00, 0x00, 0x00 // nop 138320541Sdim }; 139353358Sdim memcpy(buf, pltData, sizeof(pltData)); 140320541Sdim 141360784Sdim uint64_t off = pltEntryAddr - in.plt->getVA(); 142353358Sdim relocateOne(buf, R_SPARC_22, off); 143353358Sdim relocateOne(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize)); 144320541Sdim} 145320541Sdim 146360784SdimTargetInfo *getSPARCV9TargetInfo() { 147353358Sdim static SPARCV9 target; 148353358Sdim return ⌖ 149320541Sdim} 150360784Sdim 151360784Sdim} // namespace elf 152360784Sdim} // namespace lld 153