1
2
3
4
5 package loong64
6
7 import (
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 "fmt"
15 "log"
16 )
17
18 func gentext(ctxt *ld.Link, ldr *loader.Loader) {
19 initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
20 if initfunc == nil {
21 return
22 }
23
24 o := func(op uint32) {
25 initfunc.AddUint32(ctxt.Arch, op)
26 }
27
28
29
30
31
32
33
34
35
36
37 o(0x1a000004)
38 rel, _ := initfunc.AddRel(objabi.R_LOONG64_ADDR_HI)
39 rel.SetOff(0)
40 rel.SetSiz(4)
41 rel.SetSym(ctxt.Moduledata)
42
43
44
45 o(0x02c00084)
46 rel2, _ := initfunc.AddRel(objabi.R_LOONG64_ADDR_LO)
47 rel2.SetOff(4)
48 rel2.SetSiz(4)
49 rel2.SetSym(ctxt.Moduledata)
50
51
52
53 o(0x50000000)
54 rel3, _ := initfunc.AddRel(objabi.R_CALLLOONG64)
55 rel3.SetOff(8)
56 rel3.SetSiz(4)
57 rel3.SetSym(addmoduledata)
58 }
59
60 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
61 targ := r.Sym()
62 var targType sym.SymKind
63 if targ != 0 {
64 targType = ldr.SymType(targ)
65 }
66
67 switch r.Type() {
68 default:
69 if r.Type() >= objabi.ElfRelocOffset {
70 ldr.Errorf(s, "adddynrel: unexpected reloction type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
71 return false
72 }
73
74 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_64):
75 if targType == sym.SDYNIMPORT {
76 ldr.Errorf(s, "unexpected R_LARCH_64 relocation for dynamic symbol %s", ldr.SymName(targ))
77 }
78 su := ldr.MakeSymbolUpdater(s)
79 su.SetRelocType(rIdx, objabi.R_ADDR)
80 if target.IsPIE() && target.IsInternal() {
81
82
83
84 break
85 }
86 return true
87
88 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B26):
89 if targType == sym.SDYNIMPORT {
90 addpltsym(target, ldr, syms, targ)
91 su := ldr.MakeSymbolUpdater(s)
92 su.SetRelocSym(rIdx, syms.PLT)
93 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
94 }
95 if targType == 0 || targType == sym.SXREF {
96 ldr.Errorf(s, "unknown symbol %s in callloong64", ldr.SymName(targ))
97 }
98 su := ldr.MakeSymbolUpdater(s)
99 su.SetRelocType(rIdx, objabi.R_CALLLOONG64)
100 return true
101
102 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT_PC_HI20),
103 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT_PC_LO12):
104 if targType != sym.SDYNIMPORT {
105
106 }
107
108 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_LARCH_64))
109 su := ldr.MakeSymbolUpdater(s)
110 if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_GOT_PC_HI20) {
111 su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_HI)
112 } else {
113 su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_LO)
114 }
115 su.SetRelocSym(rIdx, syms.GOT)
116 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
117 return true
118
119 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA_HI20),
120 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA_LO12):
121 if targType == sym.SDYNIMPORT {
122 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
123 }
124 if targType == 0 || targType == sym.SXREF {
125 ldr.Errorf(s, "unknown symbol %s", ldr.SymName(targ))
126 }
127
128 su := ldr.MakeSymbolUpdater(s)
129 if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_PCALA_HI20) {
130 su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_HI)
131 } else {
132 su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_LO)
133 }
134 return true
135
136 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_ADD64),
137 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_SUB64):
138 su := ldr.MakeSymbolUpdater(s)
139 if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_ADD64) {
140 su.SetRelocType(rIdx, objabi.R_LOONG64_ADD64)
141 } else {
142 su.SetRelocType(rIdx, objabi.R_LOONG64_SUB64)
143 }
144 return true
145
146 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B16),
147 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B21):
148 if targType == sym.SDYNIMPORT {
149 addpltsym(target, ldr, syms, targ)
150 su := ldr.MakeSymbolUpdater(s)
151 su.SetRelocSym(rIdx, syms.PLT)
152 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
153 }
154 if targType == 0 || targType == sym.SXREF {
155 ldr.Errorf(s, "unknown symbol %s in R_JMPxxLOONG64", ldr.SymName(targ))
156 }
157 su := ldr.MakeSymbolUpdater(s)
158 if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_B16) {
159 su.SetRelocType(rIdx, objabi.R_JMP16LOONG64)
160 } else {
161 su.SetRelocType(rIdx, objabi.R_JMP21LOONG64)
162 }
163 return true
164 }
165
166 relocs := ldr.Relocs(s)
167 r = relocs.At(rIdx)
168
169 switch r.Type() {
170 case objabi.R_CALLLOONG64:
171 if targType != sym.SDYNIMPORT {
172 return true
173 }
174 if target.IsExternal() {
175 return true
176 }
177
178
179 if r.Add() != 0 {
180 ldr.Errorf(s, "PLT call with no-zero addend (%v)", r.Add())
181 }
182
183
184 addpltsym(target, ldr, syms, targ)
185 su := ldr.MakeSymbolUpdater(s)
186 su.SetRelocSym(rIdx, syms.PLT)
187 su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
188 return true
189
190 case objabi.R_ADDR:
191 if ldr.SymType(s) == sym.STEXT && target.IsElf() {
192
193
194
195 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_LARCH_64))
196 su := ldr.MakeSymbolUpdater(s)
197 su.SetRelocSym(rIdx, syms.GOT)
198 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
199 return true
200 }
201
202
203 if target.IsPIE() && target.IsInternal() {
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235 switch ldr.SymName(s) {
236 case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
237 return false
238 }
239 } else {
240
241
242
243
244
245
246 if ldr.SymType(s) != sym.SDATA && ldr.SymType(s) != sym.SRODATA {
247 break
248 }
249 }
250
251 if target.IsElf() {
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 rela := ldr.MakeSymbolUpdater(syms.Rela)
270 rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
271 if r.Siz() == 8 {
272 rela.AddUint64(target.Arch, elf.R_INFO(0, uint32(elf.R_LARCH_RELATIVE)))
273 } else {
274 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
275 }
276 rela.AddAddrPlus(target.Arch, targ, int64(r.Add()))
277 return true
278 }
279
280 case objabi.R_LOONG64_GOT_HI,
281 objabi.R_LOONG64_GOT_LO:
282 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_LARCH_64))
283 su := ldr.MakeSymbolUpdater(s)
284 if r.Type() == objabi.R_LOONG64_GOT_HI {
285 su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_HI)
286 } else {
287 su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_LO)
288 }
289 su.SetRelocSym(rIdx, syms.GOT)
290 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
291 return true
292 }
293 return false
294 }
295
296 func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
297 if plt.Size() == 0 {
298
299 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_LOONG64_ADDR_HI, 4)
300 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x1a00000e)
301
302
303 plt.AddUint32(ctxt.Arch, 0x0011bdad)
304
305
306 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_LOONG64_ADDR_LO, 4)
307 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x28c001cf)
308
309
310 plt.AddUint32(ctxt.Arch, 0x02ff61ad)
311
312
313 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_LOONG64_ADDR_LO, 4)
314 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x2c001cc)
315
316
317 plt.AddUint32(ctxt.Arch, 0x004505ad)
318
319
320 plt.AddUint32(ctxt.Arch, 0x28c0218c)
321
322
323 plt.AddUint32(ctxt.Arch, 0x4c0001e0)
324
325
326 if gotplt.Size() != 0 {
327 ctxt.Errorf(gotplt.Sym(), "got.plt is not empty at the very beginning")
328 }
329
330 gotplt.AddUint64(ctxt.Arch, 0)
331 gotplt.AddUint64(ctxt.Arch, 0)
332 }
333 }
334
335 func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
336 if ldr.SymPlt(s) >= 0 {
337 return
338 }
339
340 ld.Adddynsym(ldr, target, syms, s)
341
342 if target.IsElf() {
343 plt := ldr.MakeSymbolUpdater(syms.PLT)
344 gotplt := ldr.MakeSymbolUpdater(syms.GOTPLT)
345 rela := ldr.MakeSymbolUpdater(syms.RelaPLT)
346 if plt.Size() == 0 {
347 panic("plt is not set up")
348 }
349
350
351 plt.AddAddrPlus4(target.Arch, gotplt.Sym(), gotplt.Size())
352 plt.SetUint32(target.Arch, plt.Size()-4, 0x1a00000f)
353 relocs := plt.Relocs()
354 plt.SetRelocType(relocs.Count()-1, objabi.R_LOONG64_ADDR_HI)
355
356
357 plt.AddAddrPlus4(target.Arch, gotplt.Sym(), gotplt.Size())
358 plt.SetUint32(target.Arch, plt.Size()-4, 0x28c001ef)
359 relocs = plt.Relocs()
360 plt.SetRelocType(relocs.Count()-1, objabi.R_LOONG64_ADDR_LO)
361
362
363 plt.AddUint32(target.Arch, 0x1c00000d)
364
365
366 plt.AddUint32(target.Arch, 0x4c0001e0)
367
368
369 gotplt.AddAddrPlus(target.Arch, plt.Sym(), 0)
370
371
372 rela.AddAddrPlus(target.Arch, gotplt.Sym(), gotplt.Size()-8)
373 sDynid := ldr.SymDynid(s)
374 rela.AddUint64(target.Arch, elf.R_INFO(uint32(sDynid), uint32(elf.R_LARCH_JUMP_SLOT)))
375 rela.AddUint64(target.Arch, 0)
376
377 ldr.SetPlt(s, int32(plt.Size()-16))
378 } else {
379 ldr.Errorf(s, "addpltsym: unsupport binary format")
380 }
381 }
382
383 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
384
385
386
387
388
389 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
390 switch r.Type {
391 default:
392 return false
393 case objabi.R_ADDR, objabi.R_DWARFSECREF:
394 switch r.Size {
395 case 4:
396 out.Write64(uint64(sectoff))
397 out.Write64(uint64(elf.R_LARCH_32) | uint64(elfsym)<<32)
398 out.Write64(uint64(r.Xadd))
399 case 8:
400 out.Write64(uint64(sectoff))
401 out.Write64(uint64(elf.R_LARCH_64) | uint64(elfsym)<<32)
402 out.Write64(uint64(r.Xadd))
403 default:
404 return false
405 }
406 case objabi.R_LOONG64_TLS_LE_LO:
407 out.Write64(uint64(sectoff))
408 out.Write64(uint64(elf.R_LARCH_TLS_LE_LO12) | uint64(elfsym)<<32)
409 out.Write64(uint64(r.Xadd))
410
411 case objabi.R_LOONG64_TLS_LE_HI:
412 out.Write64(uint64(sectoff))
413 out.Write64(uint64(elf.R_LARCH_TLS_LE_HI20) | uint64(elfsym)<<32)
414 out.Write64(uint64(r.Xadd))
415
416 case objabi.R_CALLLOONG64:
417 out.Write64(uint64(sectoff))
418 out.Write64(uint64(elf.R_LARCH_B26) | uint64(elfsym)<<32)
419 out.Write64(uint64(r.Xadd))
420
421 case objabi.R_LOONG64_TLS_IE_HI:
422 out.Write64(uint64(sectoff))
423 out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_HI20) | uint64(elfsym)<<32)
424 out.Write64(uint64(0x0))
425
426 case objabi.R_LOONG64_TLS_IE_LO:
427 out.Write64(uint64(sectoff))
428 out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_LO12) | uint64(elfsym)<<32)
429 out.Write64(uint64(0x0))
430
431 case objabi.R_LOONG64_ADDR_LO:
432 out.Write64(uint64(sectoff))
433 out.Write64(uint64(elf.R_LARCH_PCALA_LO12) | uint64(elfsym)<<32)
434 out.Write64(uint64(r.Xadd))
435
436 case objabi.R_LOONG64_ADDR_HI:
437 out.Write64(uint64(sectoff))
438 out.Write64(uint64(elf.R_LARCH_PCALA_HI20) | uint64(elfsym)<<32)
439 out.Write64(uint64(r.Xadd))
440
441 case objabi.R_LOONG64_GOT_HI:
442 out.Write64(uint64(sectoff))
443 out.Write64(uint64(elf.R_LARCH_GOT_PC_HI20) | uint64(elfsym)<<32)
444 out.Write64(uint64(0x0))
445
446 case objabi.R_LOONG64_GOT_LO:
447 out.Write64(uint64(sectoff))
448 out.Write64(uint64(elf.R_LARCH_GOT_PC_LO12) | uint64(elfsym)<<32)
449 out.Write64(uint64(0x0))
450 }
451
452 return true
453 }
454
455 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
456 return false
457 }
458
459 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) {
460 rs := r.Sym()
461 if target.IsExternal() {
462 switch r.Type() {
463 default:
464 return val, 0, false
465 case objabi.R_LOONG64_ADDR_HI,
466 objabi.R_LOONG64_ADDR_LO:
467
468 rs, _ := ld.FoldSubSymbolOffset(ldr, rs)
469 rst := ldr.SymType(rs)
470 if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil {
471 ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
472 }
473 return val, 1, true
474 case objabi.R_LOONG64_TLS_LE_HI,
475 objabi.R_LOONG64_TLS_LE_LO,
476 objabi.R_CALLLOONG64,
477 objabi.R_JMPLOONG64,
478 objabi.R_LOONG64_TLS_IE_HI,
479 objabi.R_LOONG64_TLS_IE_LO,
480 objabi.R_LOONG64_GOT_HI,
481 objabi.R_LOONG64_GOT_LO:
482 return val, 1, true
483 }
484 }
485
486 const isOk = true
487 const noExtReloc = 0
488
489 switch r.Type() {
490 case objabi.R_CONST:
491 return r.Add(), noExtReloc, isOk
492 case objabi.R_GOTOFF:
493 return ldr.SymValue(r.Sym()) + r.Add() - ldr.SymValue(syms.GOT), noExtReloc, isOk
494 case objabi.R_LOONG64_ADDR_HI,
495 objabi.R_LOONG64_ADDR_LO:
496 pc := ldr.SymValue(s) + int64(r.Off())
497 t := calculatePCAlignedReloc(r.Type(), ldr.SymAddr(rs)+r.Add(), pc)
498 if r.Type() == objabi.R_LOONG64_ADDR_LO {
499 return int64(val&0xffc003ff | (t << 10)), noExtReloc, isOk
500 }
501 return int64(val&0xfe00001f | (t << 5)), noExtReloc, isOk
502 case objabi.R_LOONG64_TLS_LE_HI,
503 objabi.R_LOONG64_TLS_LE_LO:
504 t := ldr.SymAddr(rs) + r.Add()
505 if r.Type() == objabi.R_LOONG64_TLS_LE_LO {
506 return int64(val&0xffc003ff | ((t & 0xfff) << 10)), noExtReloc, isOk
507 }
508 return int64(val&0xfe00001f | (((t) >> 12 << 5) & 0x1ffffe0)), noExtReloc, isOk
509 case objabi.R_CALLLOONG64,
510 objabi.R_JMPLOONG64:
511 pc := ldr.SymValue(s) + int64(r.Off())
512 t := ldr.SymAddr(rs) + r.Add() - pc
513 return int64(val&0xfc000000 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x3ff0000) >> 16)), noExtReloc, isOk
514
515 case objabi.R_JMP16LOONG64,
516 objabi.R_JMP21LOONG64:
517 pc := ldr.SymValue(s) + int64(r.Off())
518 t := ldr.SymAddr(rs) + r.Add() - pc
519 if r.Type() == objabi.R_JMP16LOONG64 {
520 return int64(val&0xfc0003ff | (((t >> 2) & 0xffff) << 10)), noExtReloc, isOk
521 }
522 return int64(val&0xfc0003e0 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x1f0000) >> 16)), noExtReloc, isOk
523
524 case objabi.R_LOONG64_TLS_IE_HI,
525 objabi.R_LOONG64_TLS_IE_LO:
526 if target.IsPIE() && target.IsElf() {
527 if !target.IsLinux() {
528 ldr.Errorf(s, "TLS reloc on unsupported OS %v", target.HeadType)
529 }
530 t := ldr.SymAddr(rs) + r.Add()
531 if r.Type() == objabi.R_LOONG64_TLS_IE_HI {
532
533 return (0x14000000 | (val & 0x1f) | ((t >> 12) << 5)), noExtReloc, isOk
534 }
535
536 return (0x03800000 | (val & 0x3ff) | ((t & 0xfff) << 10)), noExtReloc, isOk
537 } else {
538 log.Fatalf("cannot handle R_LOONG64_TLS_IE_x (sym %s) when linking internally", ldr.SymName(rs))
539 }
540
541 case objabi.R_LOONG64_ADD64, objabi.R_LOONG64_SUB64:
542 if r.Type() == objabi.R_LOONG64_ADD64 {
543 return int64(val + ldr.SymAddr(rs) + r.Add()), noExtReloc, isOk
544 }
545 return int64(val - (ldr.SymAddr(rs) + r.Add())), noExtReloc, isOk
546 }
547
548 return val, 0, false
549 }
550
551 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
552 return -1
553 }
554
555 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
556 switch r.Type() {
557 case objabi.R_LOONG64_ADDR_HI,
558 objabi.R_LOONG64_ADDR_LO,
559 objabi.R_LOONG64_GOT_HI,
560 objabi.R_LOONG64_GOT_LO:
561 return ld.ExtrelocViaOuterSym(ldr, r, s), true
562
563 case objabi.R_LOONG64_TLS_LE_HI,
564 objabi.R_LOONG64_TLS_LE_LO,
565 objabi.R_CONST,
566 objabi.R_GOTOFF,
567 objabi.R_CALLLOONG64,
568 objabi.R_JMPLOONG64,
569 objabi.R_LOONG64_TLS_IE_HI,
570 objabi.R_LOONG64_TLS_IE_LO:
571 return ld.ExtrelocSimple(ldr, r), true
572 }
573 return loader.ExtReloc{}, false
574 }
575
576 func isRequestingLowPageBits(t objabi.RelocType) bool {
577 switch t {
578 case objabi.R_LOONG64_ADDR_LO:
579 return true
580 }
581 return false
582 }
583
584
585
586
587
588
589
590
591 func calculatePCAlignedReloc(t objabi.RelocType, tgt int64, pc int64) int64 {
592 if isRequestingLowPageBits(t) {
593
594 return tgt & 0xfff
595 }
596
597 pageDelta := (tgt >> 12) - (pc >> 12)
598 if tgt&0xfff >= 0x800 {
599
600 pageDelta += 1
601 }
602
603 return pageDelta & 0xfffff
604 }
605
606
607 func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
608 relocs := ldr.Relocs(s)
609 r := relocs.At(ri)
610 switch r.Type() {
611 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B26):
612
613
614
615 case objabi.R_CALLLOONG64:
616 var t int64
617
618
619
620 if ldr.SymValue(rs) != 0 {
621 t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
622 }
623 if t >= 1<<27 || t < -1<<27 || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && (ldr.SymPkg(s) == "" || ldr.SymPkg(s) != ldr.SymPkg(rs))) {
624
625
626
627 var tramp loader.Sym
628 for i := 0; ; i++ {
629 oName := ldr.SymName(rs)
630 name := oName + fmt.Sprintf("%+x-tramp%d", r.Add(), i)
631 tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs)))
632 ldr.SetAttrReachable(tramp, true)
633 if ldr.SymType(tramp) == sym.SDYNIMPORT {
634
635 continue
636 }
637 if oName == "runtime.deferreturn" {
638 ldr.SetIsDeferReturnTramp(tramp, true)
639 }
640 if ldr.SymValue(tramp) == 0 {
641
642
643
644 break
645 }
646
647 t = ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off()))
648 if t >= -1<<27 && t < 1<<27 {
649
650
651 break
652 }
653 }
654 if ldr.SymType(tramp) == 0 {
655
656 trampb := ldr.MakeSymbolUpdater(tramp)
657 ctxt.AddTramp(trampb, ldr.SymType(s))
658 if ldr.SymType(rs) == sym.SDYNIMPORT {
659 if r.Add() != 0 {
660 ctxt.Errorf(s, "nonzero addend for DYNIMPORT call: %v+%d", ldr.SymName(rs), r.Add())
661 }
662 gentrampgot(ctxt, ldr, trampb, rs)
663 } else {
664 gentramp(ctxt, ldr, trampb, rs, r.Add())
665 }
666 }
667
668 sb := ldr.MakeSymbolUpdater(s)
669 relocs := sb.Relocs()
670 r := relocs.At(ri)
671 r.SetSym(tramp)
672 r.SetAdd(0)
673 }
674 default:
675 ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
676 }
677 }
678
679
680 func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
681 tramp.SetSize(12)
682 P := make([]byte, tramp.Size())
683
684 o1 := uint32(0x1a00001e)
685 ctxt.Arch.ByteOrder.PutUint32(P, o1)
686 r1, _ := tramp.AddRel(objabi.R_LOONG64_ADDR_HI)
687 r1.SetOff(0)
688 r1.SetSiz(4)
689 r1.SetSym(target)
690 r1.SetAdd(offset)
691
692 o2 := uint32(0x02c003de)
693 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
694 r2, _ := tramp.AddRel(objabi.R_LOONG64_ADDR_LO)
695 r2.SetOff(4)
696 r2.SetSiz(4)
697 r2.SetSym(target)
698 r2.SetAdd(offset)
699
700 o3 := uint32(0x4c0003c0)
701 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
702
703 tramp.SetData(P)
704 }
705
706 func gentrampgot(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym) {
707 tramp.SetSize(12)
708 P := make([]byte, tramp.Size())
709
710 o1 := uint32(0x1a00001e)
711 ctxt.Arch.ByteOrder.PutUint32(P, o1)
712 r1, _ := tramp.AddRel(objabi.R_LOONG64_GOT_HI)
713 r1.SetOff(0)
714 r1.SetSiz(4)
715 r1.SetSym(target)
716
717 o2 := uint32(0x28c003de)
718 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
719 r2, _ := tramp.AddRel(objabi.R_LOONG64_GOT_LO)
720 r2.SetOff(4)
721 r2.SetSiz(4)
722 r2.SetSym(target)
723
724 o3 := uint32(0x4c0003c0)
725 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
726
727 tramp.SetData(P)
728 }
729
View as plain text