github.com/bir3/gocompiler@v0.9.2202/src/cmd/link/internal/s390x/asm.go (about) 1 // Inferno utils/5l/asm.c 2 // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 package s390x 32 33 import ( 34 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 35 "github.com/bir3/gocompiler/src/cmd/internal/sys" 36 "github.com/bir3/gocompiler/src/cmd/link/internal/ld" 37 "github.com/bir3/gocompiler/src/cmd/link/internal/loader" 38 "github.com/bir3/gocompiler/src/cmd/link/internal/sym" 39 "debug/elf" 40 ) 41 42 // gentext generates assembly to append the local moduledata to the global 43 // moduledata linked list at initialization time. This is only done if the runtime 44 // is in a different module. 45 // 46 // <go.link.addmoduledata>: 47 // larl %r2, <local.moduledata> 48 // jg <runtime.addmoduledata@plt> 49 // undef 50 // 51 // The job of appending the moduledata is delegated to runtime.addmoduledata. 52 func gentext(ctxt *ld.Link, ldr *loader.Loader) { 53 initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt) 54 if initfunc == nil { 55 return 56 } 57 58 // larl %r2, <local.moduledata> 59 initfunc.AddUint8(0xc0) 60 initfunc.AddUint8(0x20) 61 initfunc.AddSymRef(ctxt.Arch, ctxt.Moduledata, 6, objabi.R_PCREL, 4) 62 r1 := initfunc.Relocs() 63 ldr.SetRelocVariant(initfunc.Sym(), r1.Count()-1, sym.RV_390_DBL) 64 65 // jg <runtime.addmoduledata[@plt]> 66 initfunc.AddUint8(0xc0) 67 initfunc.AddUint8(0xf4) 68 initfunc.AddSymRef(ctxt.Arch, addmoduledata, 6, objabi.R_CALL, 4) 69 r2 := initfunc.Relocs() 70 ldr.SetRelocVariant(initfunc.Sym(), r2.Count()-1, sym.RV_390_DBL) 71 72 // undef (for debugging) 73 initfunc.AddUint32(ctxt.Arch, 0) 74 } 75 76 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool { 77 targ := r.Sym() 78 var targType sym.SymKind 79 if targ != 0 { 80 targType = ldr.SymType(targ) 81 } 82 83 switch r.Type() { 84 default: 85 if r.Type() >= objabi.ElfRelocOffset { 86 ldr.Errorf(s, "unexpected relocation type %d", r.Type()) 87 return false 88 } 89 90 // Handle relocations found in ELF object files. 91 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_12), 92 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT12): 93 ldr.Errorf(s, "s390x 12-bit relocations have not been implemented (relocation type %d)", r.Type()-objabi.ElfRelocOffset) 94 return false 95 96 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_8), 97 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_16), 98 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_32), 99 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_64): 100 if targType == sym.SDYNIMPORT { 101 ldr.Errorf(s, "unexpected R_390_nn relocation for dynamic symbol %s", ldr.SymName(targ)) 102 } 103 104 su := ldr.MakeSymbolUpdater(s) 105 su.SetRelocType(rIdx, objabi.R_ADDR) 106 return true 107 108 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC16), 109 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC32), 110 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC64): 111 if targType == sym.SDYNIMPORT { 112 ldr.Errorf(s, "unexpected R_390_PCnn relocation for dynamic symbol %s", ldr.SymName(targ)) 113 } 114 if targType == 0 || targType == sym.SXREF { 115 ldr.Errorf(s, "unknown symbol %s in pcrel", ldr.SymName(targ)) 116 } 117 su := ldr.MakeSymbolUpdater(s) 118 su.SetRelocType(rIdx, objabi.R_PCREL) 119 su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz())) 120 return true 121 122 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT16), 123 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT32), 124 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT64): 125 ldr.Errorf(s, "unimplemented S390x relocation: %v", r.Type()-objabi.ElfRelocOffset) 126 return true 127 128 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT16DBL), 129 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT32DBL): 130 su := ldr.MakeSymbolUpdater(s) 131 su.SetRelocType(rIdx, objabi.R_PCREL) 132 ldr.SetRelocVariant(s, rIdx, sym.RV_390_DBL) 133 su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz())) 134 if targType == sym.SDYNIMPORT { 135 addpltsym(target, ldr, syms, targ) 136 r.SetSym(syms.PLT) 137 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ))) 138 } 139 return true 140 141 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT32), 142 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT64): 143 su := ldr.MakeSymbolUpdater(s) 144 su.SetRelocType(rIdx, objabi.R_PCREL) 145 su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz())) 146 if targType == sym.SDYNIMPORT { 147 addpltsym(target, ldr, syms, targ) 148 r.SetSym(syms.PLT) 149 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ))) 150 } 151 return true 152 153 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_COPY): 154 ldr.Errorf(s, "unimplemented S390x relocation: %v", r.Type()-objabi.ElfRelocOffset) 155 return false 156 157 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GLOB_DAT): 158 ldr.Errorf(s, "unimplemented S390x relocation: %v", r.Type()-objabi.ElfRelocOffset) 159 return false 160 161 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_JMP_SLOT): 162 ldr.Errorf(s, "unimplemented S390x relocation: %v", r.Type()-objabi.ElfRelocOffset) 163 return false 164 165 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_RELATIVE): 166 ldr.Errorf(s, "unimplemented S390x relocation: %v", r.Type()-objabi.ElfRelocOffset) 167 return false 168 169 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTOFF): 170 if targType == sym.SDYNIMPORT { 171 ldr.Errorf(s, "unexpected R_390_GOTOFF relocation for dynamic symbol %s", ldr.SymName(targ)) 172 } 173 su := ldr.MakeSymbolUpdater(s) 174 su.SetRelocType(rIdx, objabi.R_GOTOFF) 175 return true 176 177 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTPC): 178 su := ldr.MakeSymbolUpdater(s) 179 su.SetRelocType(rIdx, objabi.R_PCREL) 180 r.SetSym(syms.GOT) 181 su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz())) 182 return true 183 184 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC16DBL), 185 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC32DBL): 186 su := ldr.MakeSymbolUpdater(s) 187 su.SetRelocType(rIdx, objabi.R_PCREL) 188 ldr.SetRelocVariant(s, rIdx, sym.RV_390_DBL) 189 su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz())) 190 if targType == sym.SDYNIMPORT { 191 ldr.Errorf(s, "unexpected R_390_PCnnDBL relocation for dynamic symbol %s", ldr.SymName(targ)) 192 } 193 return true 194 195 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTPCDBL): 196 su := ldr.MakeSymbolUpdater(s) 197 su.SetRelocType(rIdx, objabi.R_PCREL) 198 ldr.SetRelocVariant(s, rIdx, sym.RV_390_DBL) 199 r.SetSym(syms.GOT) 200 su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz())) 201 return true 202 203 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTENT): 204 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_390_GLOB_DAT)) 205 su := ldr.MakeSymbolUpdater(s) 206 su.SetRelocType(rIdx, objabi.R_PCREL) 207 ldr.SetRelocVariant(s, rIdx, sym.RV_390_DBL) 208 r.SetSym(syms.GOT) 209 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ))+int64(r.Siz())) 210 return true 211 } 212 // Handle references to ELF symbols from our own object files. 213 return targType != sym.SDYNIMPORT 214 } 215 216 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool { 217 out.Write64(uint64(sectoff)) 218 219 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym) 220 siz := r.Size 221 switch r.Type { 222 default: 223 return false 224 case objabi.R_TLS_LE: 225 switch siz { 226 default: 227 return false 228 case 4: 229 // WARNING - silently ignored by linker in ELF64 230 out.Write64(uint64(elf.R_390_TLS_LE32) | uint64(elfsym)<<32) 231 case 8: 232 // WARNING - silently ignored by linker in ELF32 233 out.Write64(uint64(elf.R_390_TLS_LE64) | uint64(elfsym)<<32) 234 } 235 case objabi.R_TLS_IE: 236 switch siz { 237 default: 238 return false 239 case 4: 240 out.Write64(uint64(elf.R_390_TLS_IEENT) | uint64(elfsym)<<32) 241 } 242 case objabi.R_ADDR, objabi.R_DWARFSECREF: 243 switch siz { 244 default: 245 return false 246 case 4: 247 out.Write64(uint64(elf.R_390_32) | uint64(elfsym)<<32) 248 case 8: 249 out.Write64(uint64(elf.R_390_64) | uint64(elfsym)<<32) 250 } 251 case objabi.R_GOTPCREL: 252 if siz == 4 { 253 out.Write64(uint64(elf.R_390_GOTENT) | uint64(elfsym)<<32) 254 } else { 255 return false 256 } 257 case objabi.R_PCREL, objabi.R_PCRELDBL, objabi.R_CALL: 258 elfrel := elf.R_390_NONE 259 rVariant := ldr.RelocVariant(s, ri) 260 isdbl := rVariant&sym.RV_TYPE_MASK == sym.RV_390_DBL 261 // TODO(mundaym): all DBL style relocations should be 262 // signalled using the variant - see issue 14218. 263 switch r.Type { 264 case objabi.R_PCRELDBL, objabi.R_CALL: 265 isdbl = true 266 } 267 if ldr.SymType(r.Xsym) == sym.SDYNIMPORT && (ldr.SymElfType(r.Xsym) == elf.STT_FUNC || r.Type == objabi.R_CALL) { 268 if isdbl { 269 switch siz { 270 case 2: 271 elfrel = elf.R_390_PLT16DBL 272 case 4: 273 elfrel = elf.R_390_PLT32DBL 274 } 275 } else { 276 switch siz { 277 case 4: 278 elfrel = elf.R_390_PLT32 279 case 8: 280 elfrel = elf.R_390_PLT64 281 } 282 } 283 } else { 284 if isdbl { 285 switch siz { 286 case 2: 287 elfrel = elf.R_390_PC16DBL 288 case 4: 289 elfrel = elf.R_390_PC32DBL 290 } 291 } else { 292 switch siz { 293 case 2: 294 elfrel = elf.R_390_PC16 295 case 4: 296 elfrel = elf.R_390_PC32 297 case 8: 298 elfrel = elf.R_390_PC64 299 } 300 } 301 } 302 if elfrel == elf.R_390_NONE { 303 return false // unsupported size/dbl combination 304 } 305 out.Write64(uint64(elfrel) | uint64(elfsym)<<32) 306 } 307 308 out.Write64(uint64(r.Xadd)) 309 return true 310 } 311 312 func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, got *loader.SymbolBuilder, dynamic loader.Sym) { 313 if plt.Size() == 0 { 314 // stg %r1,56(%r15) 315 plt.AddUint8(0xe3) 316 plt.AddUint8(0x10) 317 plt.AddUint8(0xf0) 318 plt.AddUint8(0x38) 319 plt.AddUint8(0x00) 320 plt.AddUint8(0x24) 321 // larl %r1,_GLOBAL_OFFSET_TABLE_ 322 plt.AddUint8(0xc0) 323 plt.AddUint8(0x10) 324 plt.AddSymRef(ctxt.Arch, got.Sym(), 6, objabi.R_PCRELDBL, 4) 325 // mvc 48(8,%r15),8(%r1) 326 plt.AddUint8(0xd2) 327 plt.AddUint8(0x07) 328 plt.AddUint8(0xf0) 329 plt.AddUint8(0x30) 330 plt.AddUint8(0x10) 331 plt.AddUint8(0x08) 332 // lg %r1,16(%r1) 333 plt.AddUint8(0xe3) 334 plt.AddUint8(0x10) 335 plt.AddUint8(0x10) 336 plt.AddUint8(0x10) 337 plt.AddUint8(0x00) 338 plt.AddUint8(0x04) 339 // br %r1 340 plt.AddUint8(0x07) 341 plt.AddUint8(0xf1) 342 // nopr %r0 343 plt.AddUint8(0x07) 344 plt.AddUint8(0x00) 345 // nopr %r0 346 plt.AddUint8(0x07) 347 plt.AddUint8(0x00) 348 // nopr %r0 349 plt.AddUint8(0x07) 350 plt.AddUint8(0x00) 351 352 // assume got->size == 0 too 353 got.AddAddrPlus(ctxt.Arch, dynamic, 0) 354 355 got.AddUint64(ctxt.Arch, 0) 356 got.AddUint64(ctxt.Arch, 0) 357 } 358 } 359 360 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool { 361 return false 362 } 363 364 func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) { 365 return val, 0, false 366 } 367 368 func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc, rv sym.RelocVariant, s loader.Sym, t int64, p []byte) int64 { 369 switch rv & sym.RV_TYPE_MASK { 370 default: 371 ldr.Errorf(s, "unexpected relocation variant %d", rv) 372 return t 373 374 case sym.RV_NONE: 375 return t 376 377 case sym.RV_390_DBL: 378 if t&1 != 0 { 379 ldr.Errorf(s, "%s+%v is not 2-byte aligned", ldr.SymName(r.Sym()), ldr.SymValue(r.Sym())) 380 } 381 return t >> 1 382 } 383 } 384 385 func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) { 386 if ldr.SymPlt(s) >= 0 { 387 return 388 } 389 390 ld.Adddynsym(ldr, target, syms, s) 391 392 if target.IsElf() { 393 plt := ldr.MakeSymbolUpdater(syms.PLT) 394 got := ldr.MakeSymbolUpdater(syms.GOT) 395 rela := ldr.MakeSymbolUpdater(syms.RelaPLT) 396 if plt.Size() == 0 { 397 panic("plt is not set up") 398 } 399 // larl %r1,_GLOBAL_OFFSET_TABLE_+index 400 401 plt.AddUint8(0xc0) 402 plt.AddUint8(0x10) 403 plt.AddPCRelPlus(target.Arch, got.Sym(), got.Size()+6) 404 pltrelocs := plt.Relocs() 405 ldr.SetRelocVariant(plt.Sym(), pltrelocs.Count()-1, sym.RV_390_DBL) 406 407 // add to got: pointer to current pos in plt 408 got.AddAddrPlus(target.Arch, plt.Sym(), plt.Size()+8) // weird but correct 409 // lg %r1,0(%r1) 410 plt.AddUint8(0xe3) 411 plt.AddUint8(0x10) 412 plt.AddUint8(0x10) 413 plt.AddUint8(0x00) 414 plt.AddUint8(0x00) 415 plt.AddUint8(0x04) 416 // br %r1 417 plt.AddUint8(0x07) 418 plt.AddUint8(0xf1) 419 // basr %r1,%r0 420 plt.AddUint8(0x0d) 421 plt.AddUint8(0x10) 422 // lgf %r1,12(%r1) 423 plt.AddUint8(0xe3) 424 plt.AddUint8(0x10) 425 plt.AddUint8(0x10) 426 plt.AddUint8(0x0c) 427 plt.AddUint8(0x00) 428 plt.AddUint8(0x14) 429 // jg .plt 430 plt.AddUint8(0xc0) 431 plt.AddUint8(0xf4) 432 433 plt.AddUint32(target.Arch, uint32(-((plt.Size() - 2) >> 1))) // roll-your-own relocation 434 //.plt index 435 plt.AddUint32(target.Arch, uint32(rela.Size())) // rela size before current entry 436 437 // rela 438 rela.AddAddrPlus(target.Arch, got.Sym(), got.Size()-8) 439 440 sDynid := ldr.SymDynid(s) 441 rela.AddUint64(target.Arch, elf.R_INFO(uint32(sDynid), uint32(elf.R_390_JMP_SLOT))) 442 rela.AddUint64(target.Arch, 0) 443 444 ldr.SetPlt(s, int32(plt.Size()-32)) 445 446 } else { 447 ldr.Errorf(s, "addpltsym: unsupported binary format") 448 } 449 }