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