1// Copyright 2022 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package loong64 6 7import ( 8 "cmd/internal/objabi" 9 "cmd/internal/sys" 10 "cmd/link/internal/ld" 11 "cmd/link/internal/loader" 12 "cmd/link/internal/sym" 13 "debug/elf" 14 "log" 15) 16 17func gentext(ctxt *ld.Link, ldr *loader.Loader) { 18 initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt) 19 if initfunc == nil { 20 return 21 } 22 23 o := func(op uint32) { 24 initfunc.AddUint32(ctxt.Arch, op) 25 } 26 27 // Emit the following function: 28 // 29 // local.dso_init: 30 // la.pcrel $a0, local.moduledata 31 // b runtime.addmoduledata 32 33 // 0000000000000000 <local.dso_init>: 34 // 0: 1a000004 pcalau12i $a0, 0 35 // 0: R_LARCH_PCALA_HI20 local.moduledata 36 o(0x1a000004) 37 rel, _ := initfunc.AddRel(objabi.R_LOONG64_ADDR_HI) 38 rel.SetOff(0) 39 rel.SetSiz(4) 40 rel.SetSym(ctxt.Moduledata) 41 42 // 4: 02c00084 addi.d $a0, $a0, 0 43 // 4: R_LARCH_PCALA_LO12 local.moduledata 44 o(0x02c00084) 45 rel2, _ := initfunc.AddRel(objabi.R_LOONG64_ADDR_LO) 46 rel2.SetOff(4) 47 rel2.SetSiz(4) 48 rel2.SetSym(ctxt.Moduledata) 49 50 // 8: 50000000 b 0 51 // 8: R_LARCH_B26 runtime.addmoduledata 52 o(0x50000000) 53 rel3, _ := initfunc.AddRel(objabi.R_CALLLOONG64) 54 rel3.SetOff(8) 55 rel3.SetSiz(4) 56 rel3.SetSym(addmoduledata) 57} 58 59func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool { 60 log.Fatalf("adddynrel not implemented") 61 return false 62} 63 64func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool { 65 // loong64 ELF relocation (endian neutral) 66 // offset uint64 67 // symreloc uint64 // The high 32-bit is the symbol, the low 32-bit is the relocation type. 68 // addend int64 69 70 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym) 71 switch r.Type { 72 default: 73 return false 74 case objabi.R_ADDR, objabi.R_DWARFSECREF: 75 switch r.Size { 76 case 4: 77 out.Write64(uint64(sectoff)) 78 out.Write64(uint64(elf.R_LARCH_32) | uint64(elfsym)<<32) 79 out.Write64(uint64(r.Xadd)) 80 case 8: 81 out.Write64(uint64(sectoff)) 82 out.Write64(uint64(elf.R_LARCH_64) | uint64(elfsym)<<32) 83 out.Write64(uint64(r.Xadd)) 84 default: 85 return false 86 } 87 case objabi.R_LOONG64_TLS_LE_LO: 88 out.Write64(uint64(sectoff)) 89 out.Write64(uint64(elf.R_LARCH_TLS_LE_LO12) | uint64(elfsym)<<32) 90 out.Write64(uint64(r.Xadd)) 91 92 case objabi.R_LOONG64_TLS_LE_HI: 93 out.Write64(uint64(sectoff)) 94 out.Write64(uint64(elf.R_LARCH_TLS_LE_HI20) | uint64(elfsym)<<32) 95 out.Write64(uint64(r.Xadd)) 96 97 case objabi.R_CALLLOONG64: 98 out.Write64(uint64(sectoff)) 99 out.Write64(uint64(elf.R_LARCH_B26) | uint64(elfsym)<<32) 100 out.Write64(uint64(r.Xadd)) 101 102 case objabi.R_LOONG64_TLS_IE_HI: 103 out.Write64(uint64(sectoff)) 104 out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_HI20) | uint64(elfsym)<<32) 105 out.Write64(uint64(0x0)) 106 107 case objabi.R_LOONG64_TLS_IE_LO: 108 out.Write64(uint64(sectoff)) 109 out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_LO12) | uint64(elfsym)<<32) 110 out.Write64(uint64(0x0)) 111 112 case objabi.R_LOONG64_ADDR_LO: 113 out.Write64(uint64(sectoff)) 114 out.Write64(uint64(elf.R_LARCH_PCALA_LO12) | uint64(elfsym)<<32) 115 out.Write64(uint64(r.Xadd)) 116 117 case objabi.R_LOONG64_ADDR_HI: 118 out.Write64(uint64(sectoff)) 119 out.Write64(uint64(elf.R_LARCH_PCALA_HI20) | uint64(elfsym)<<32) 120 out.Write64(uint64(r.Xadd)) 121 122 case objabi.R_LOONG64_GOT_HI: 123 out.Write64(uint64(sectoff)) 124 out.Write64(uint64(elf.R_LARCH_GOT_PC_HI20) | uint64(elfsym)<<32) 125 out.Write64(uint64(0x0)) 126 127 case objabi.R_LOONG64_GOT_LO: 128 out.Write64(uint64(sectoff)) 129 out.Write64(uint64(elf.R_LARCH_GOT_PC_LO12) | uint64(elfsym)<<32) 130 out.Write64(uint64(0x0)) 131 } 132 133 return true 134} 135 136func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) { 137 return 138} 139 140func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool { 141 return false 142} 143 144func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) { 145 rs := r.Sym() 146 if target.IsExternal() { 147 switch r.Type() { 148 default: 149 return val, 0, false 150 case objabi.R_LOONG64_ADDR_HI, 151 objabi.R_LOONG64_ADDR_LO: 152 // set up addend for eventual relocation via outer symbol. 153 rs, _ := ld.FoldSubSymbolOffset(ldr, rs) 154 rst := ldr.SymType(rs) 155 if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil { 156 ldr.Errorf(s, "missing section for %s", ldr.SymName(rs)) 157 } 158 return val, 1, true 159 case objabi.R_LOONG64_TLS_LE_HI, 160 objabi.R_LOONG64_TLS_LE_LO, 161 objabi.R_CALLLOONG64, 162 objabi.R_JMPLOONG64, 163 objabi.R_LOONG64_TLS_IE_HI, 164 objabi.R_LOONG64_TLS_IE_LO, 165 objabi.R_LOONG64_GOT_HI, 166 objabi.R_LOONG64_GOT_LO: 167 return val, 1, true 168 } 169 } 170 171 const isOk = true 172 const noExtReloc = 0 173 174 switch r.Type() { 175 case objabi.R_CONST: 176 return r.Add(), noExtReloc, isOk 177 case objabi.R_GOTOFF: 178 return ldr.SymValue(r.Sym()) + r.Add() - ldr.SymValue(syms.GOT), noExtReloc, isOk 179 case objabi.R_LOONG64_ADDR_HI, 180 objabi.R_LOONG64_ADDR_LO: 181 pc := ldr.SymValue(s) + int64(r.Off()) 182 t := calculatePCAlignedReloc(r.Type(), ldr.SymAddr(rs)+r.Add(), pc) 183 if r.Type() == objabi.R_LOONG64_ADDR_LO { 184 return int64(val&0xffc003ff | (t << 10)), noExtReloc, isOk 185 } 186 return int64(val&0xfe00001f | (t << 5)), noExtReloc, isOk 187 case objabi.R_LOONG64_TLS_LE_HI, 188 objabi.R_LOONG64_TLS_LE_LO: 189 t := ldr.SymAddr(rs) + r.Add() 190 if r.Type() == objabi.R_LOONG64_TLS_LE_LO { 191 return int64(val&0xffc003ff | ((t & 0xfff) << 10)), noExtReloc, isOk 192 } 193 return int64(val&0xfe00001f | (((t) >> 12 << 5) & 0x1ffffe0)), noExtReloc, isOk 194 case objabi.R_CALLLOONG64, 195 objabi.R_JMPLOONG64: 196 pc := ldr.SymValue(s) + int64(r.Off()) 197 t := ldr.SymAddr(rs) + r.Add() - pc 198 return int64(val&0xfc000000 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x3ff0000) >> 16)), noExtReloc, isOk 199 } 200 201 return val, 0, false 202} 203 204func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 { 205 return -1 206} 207 208func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) { 209 switch r.Type() { 210 case objabi.R_LOONG64_ADDR_HI, 211 objabi.R_LOONG64_ADDR_LO, 212 objabi.R_LOONG64_GOT_HI, 213 objabi.R_LOONG64_GOT_LO: 214 return ld.ExtrelocViaOuterSym(ldr, r, s), true 215 216 case objabi.R_LOONG64_TLS_LE_HI, 217 objabi.R_LOONG64_TLS_LE_LO, 218 objabi.R_CONST, 219 objabi.R_GOTOFF, 220 objabi.R_CALLLOONG64, 221 objabi.R_JMPLOONG64, 222 objabi.R_LOONG64_TLS_IE_HI, 223 objabi.R_LOONG64_TLS_IE_LO: 224 return ld.ExtrelocSimple(ldr, r), true 225 } 226 return loader.ExtReloc{}, false 227} 228 229func isRequestingLowPageBits(t objabi.RelocType) bool { 230 switch t { 231 case objabi.R_LOONG64_ADDR_LO: 232 return true 233 } 234 return false 235} 236 237// Calculates the value to put into the immediate slot, according to the 238// desired relocation type, target and PC. 239// The value to use varies based on the reloc type. Namely, the absolute low 240// bits of the target are to be used for the low part, while the page-aligned 241// offset is to be used for the higher part. A "page" here is not related to 242// the system's actual page size, but rather a fixed 12-bit range (designed to 243// cooperate with ADDI/LD/ST's 12-bit immediates). 244func calculatePCAlignedReloc(t objabi.RelocType, tgt int64, pc int64) int64 { 245 if isRequestingLowPageBits(t) { 246 // corresponding immediate field is 12 bits wide 247 return tgt & 0xfff 248 } 249 250 pageDelta := (tgt >> 12) - (pc >> 12) 251 if tgt&0xfff >= 0x800 { 252 // adjust for sign-extended addition of the low bits 253 pageDelta += 1 254 } 255 // corresponding immediate field is 20 bits wide 256 return pageDelta & 0xfffff 257} 258