1
2
3
4
5 package loong64
6
7 import (
8 . "cmd/internal/obj/loong64"
9 "cmd/internal/objabi"
10 "cmd/internal/sys"
11 "cmd/link/internal/ld"
12 "cmd/link/internal/loader"
13 "cmd/link/internal/sym"
14 "debug/elf"
15 "fmt"
16 "log"
17 )
18
19 func gentext(ctxt *ld.Link, ldr *loader.Loader) {
20 initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
21 if initfunc == nil {
22 return
23 }
24
25 o := func(op uint32) {
26 initfunc.AddUint32(ctxt.Arch, op)
27 }
28
29
30
31
32
33
34
35
36
37
38 o(OP_IR(OpCodeIR(APCALAU12I), 0, REG_R4))
39 rel, _ := initfunc.AddRel(objabi.R_LOONG64_ADDR_HI)
40 rel.SetOff(0)
41 rel.SetSiz(4)
42 rel.SetSym(ctxt.Moduledata)
43
44
45
46 o(OP_12IRR(OpCodeIRR(AADDV), 0, REG_R4, REG_R4))
47 rel2, _ := initfunc.AddRel(objabi.R_LOONG64_ADDR_LO)
48 rel2.SetOff(4)
49 rel2.SetSiz(4)
50 rel2.SetSym(ctxt.Moduledata)
51
52
53
54 o(OP_B_BL(OpCodeIRR(AJMP), 0))
55 rel3, _ := initfunc.AddRel(objabi.R_CALLLOONG64)
56 rel3.SetOff(8)
57 rel3.SetSiz(4)
58 rel3.SetSym(addmoduledata)
59 }
60
61 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
62 targ := r.Sym()
63 var targType sym.SymKind
64 if targ != 0 {
65 targType = ldr.SymType(targ)
66 }
67
68 switch r.Type() {
69 default:
70 if r.Type() >= objabi.ElfRelocOffset {
71 ldr.Errorf(s, "adddynrel: unexpected reloction type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
72 return false
73 }
74
75 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_64):
76 if targType == sym.SDYNIMPORT {
77 ldr.Errorf(s, "unexpected R_LARCH_64 relocation for dynamic symbol %s", ldr.SymName(targ))
78 }
79 su := ldr.MakeSymbolUpdater(s)
80 su.SetRelocType(rIdx, objabi.R_ADDR)
81 if target.IsPIE() && target.IsInternal() {
82
83
84
85 break
86 }
87 return true
88
89 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B26),
90 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_CALL36):
91 if targType == sym.SDYNIMPORT {
92 addpltsym(target, ldr, syms, targ)
93 su := ldr.MakeSymbolUpdater(s)
94 su.SetRelocSym(rIdx, syms.PLT)
95 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
96 }
97 if targType == 0 || targType == sym.SXREF {
98 ldr.Errorf(s, "unknown symbol %s in callloong64", ldr.SymName(targ))
99 }
100 relocType := objabi.R_CALLLOONG64
101 if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_CALL36) {
102 relocType = objabi.R_LOONG64_CALL36
103 }
104 su := ldr.MakeSymbolUpdater(s)
105 su.SetRelocType(rIdx, relocType)
106 return true
107
108 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT_PC_HI20),
109 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT_PC_LO12),
110 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT64_PC_HI12),
111 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT64_PC_LO20):
112 if targType != sym.SDYNIMPORT {
113
114 }
115
116 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_LARCH_64))
117 su := ldr.MakeSymbolUpdater(s)
118
119 var relocType objabi.RelocType
120 switch r.Type() - objabi.ElfRelocOffset {
121 case objabi.RelocType(elf.R_LARCH_GOT_PC_HI20):
122 relocType = objabi.R_LOONG64_ADDR_HI
123 case objabi.RelocType(elf.R_LARCH_GOT_PC_LO12):
124 relocType = objabi.R_LOONG64_ADDR_LO
125 case objabi.RelocType(elf.R_LARCH_GOT64_PC_HI12):
126 relocType = objabi.R_LOONG64_ADDR64_HI
127 case objabi.RelocType(elf.R_LARCH_GOT64_PC_LO20):
128 relocType = objabi.R_LOONG64_ADDR64_LO
129 }
130
131 su.SetRelocType(rIdx, relocType)
132 su.SetRelocSym(rIdx, syms.GOT)
133 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
134 return true
135
136 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA_HI20),
137 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA_LO12),
138 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA64_HI12),
139 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA64_LO20),
140 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCREL20_S2):
141 if targType == sym.SDYNIMPORT {
142 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
143 }
144 if targType == 0 || targType == sym.SXREF {
145 ldr.Errorf(s, "unknown symbol %s", ldr.SymName(targ))
146 }
147
148 var relocType objabi.RelocType
149 switch r.Type() - objabi.ElfRelocOffset {
150 case objabi.RelocType(elf.R_LARCH_PCALA_HI20):
151 relocType = objabi.R_LOONG64_ADDR_HI
152 case objabi.RelocType(elf.R_LARCH_PCALA_LO12):
153 relocType = objabi.R_LOONG64_ADDR_LO
154 case objabi.RelocType(elf.R_LARCH_PCALA64_HI12):
155 relocType = objabi.R_LOONG64_ADDR64_HI
156 case objabi.RelocType(elf.R_LARCH_PCALA64_LO20):
157 relocType = objabi.R_LOONG64_ADDR64_LO
158 case objabi.RelocType(elf.R_LARCH_PCREL20_S2):
159 relocType = objabi.R_LOONG64_ADDR_PCREL20_S2
160 }
161
162 su := ldr.MakeSymbolUpdater(s)
163 su.SetRelocType(rIdx, relocType)
164 return true
165
166 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_ADD64),
167 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_SUB64):
168 su := ldr.MakeSymbolUpdater(s)
169 if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_ADD64) {
170 su.SetRelocType(rIdx, objabi.R_LOONG64_ADD64)
171 } else {
172 su.SetRelocType(rIdx, objabi.R_LOONG64_SUB64)
173 }
174 return true
175
176 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B16),
177 objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B21):
178 if targType == sym.SDYNIMPORT {
179 addpltsym(target, ldr, syms, targ)
180 su := ldr.MakeSymbolUpdater(s)
181 su.SetRelocSym(rIdx, syms.PLT)
182 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
183 }
184 if targType == 0 || targType == sym.SXREF {
185 ldr.Errorf(s, "unknown symbol %s in R_JMPxxLOONG64", ldr.SymName(targ))
186 }
187 su := ldr.MakeSymbolUpdater(s)
188 if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_B16) {
189 su.SetRelocType(rIdx, objabi.R_JMP16LOONG64)
190 } else {
191 su.SetRelocType(rIdx, objabi.R_JMP21LOONG64)
192 }
193 return true
194 }
195
196 relocs := ldr.Relocs(s)
197 r = relocs.At(rIdx)
198
199 switch r.Type() {
200 case objabi.R_CALLLOONG64:
201 if targType != sym.SDYNIMPORT {
202 return true
203 }
204 if target.IsExternal() {
205 return true
206 }
207
208
209 if r.Add() != 0 {
210 ldr.Errorf(s, "PLT call with no-zero addend (%v)", r.Add())
211 }
212
213
214 addpltsym(target, ldr, syms, targ)
215 su := ldr.MakeSymbolUpdater(s)
216 su.SetRelocSym(rIdx, syms.PLT)
217 su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
218 return true
219
220 case objabi.R_ADDR:
221 if ldr.SymType(s) == sym.STEXT && target.IsElf() {
222
223
224
225 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_LARCH_64))
226 su := ldr.MakeSymbolUpdater(s)
227 su.SetRelocSym(rIdx, syms.GOT)
228 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
229 return true
230 }
231
232
233 if target.IsPIE() && target.IsInternal() {
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265 switch ldr.SymName(s) {
266 case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
267 return false
268 }
269 } else {
270
271
272
273
274
275
276 if ldr.SymType(s) != sym.SDATA && ldr.SymType(s) != sym.SRODATA {
277 break
278 }
279 }
280
281 if target.IsElf() {
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299 rela := ldr.MakeSymbolUpdater(syms.Rela)
300 rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
301 if r.Siz() == 8 {
302 rela.AddUint64(target.Arch, elf.R_INFO(0, uint32(elf.R_LARCH_RELATIVE)))
303 } else {
304 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
305 }
306 rela.AddAddrPlus(target.Arch, targ, r.Add())
307 return true
308 }
309
310 case objabi.R_LOONG64_GOT_HI,
311 objabi.R_LOONG64_GOT_LO,
312 objabi.R_LOONG64_GOT64_HI,
313 objabi.R_LOONG64_GOT64_LO:
314 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_LARCH_64))
315 su := ldr.MakeSymbolUpdater(s)
316
317 var relocType objabi.RelocType
318 switch r.Type() {
319 case objabi.R_LOONG64_GOT_HI:
320 relocType = objabi.R_LOONG64_ADDR_HI
321 case objabi.R_LOONG64_GOT_LO:
322 relocType = objabi.R_LOONG64_ADDR_LO
323 case objabi.R_LOONG64_GOT64_HI:
324 relocType = objabi.R_LOONG64_ADDR64_HI
325 case objabi.R_LOONG64_GOT64_LO:
326 relocType = objabi.R_LOONG64_ADDR64_LO
327 }
328
329 su.SetRelocType(rIdx, relocType)
330 su.SetRelocSym(rIdx, syms.GOT)
331 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
332 return true
333 }
334 return false
335 }
336
337 func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
338 if plt.Size() == 0 {
339 var t uint32
340
341
342 t = OP_IR(OpCodeIR(APCALAU12I), 0, REG_R14)
343 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_LOONG64_ADDR_HI, 4)
344 plt.SetUint32(ctxt.Arch, plt.Size()-4, t)
345
346
347 t = OP_RRR(OpCodeRRR(ASUBV), REG_R15, REG_R13, REG_R13)
348 plt.AddUint32(ctxt.Arch, t)
349
350
351 t = OP_12IRR(OpCodeIRR(-AMOVV), 0, REG_R14, REG_R15)
352 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_LOONG64_ADDR_LO, 4)
353 plt.SetUint32(ctxt.Arch, plt.Size()-4, t)
354
355
356 t = OP_12IRR(OpCodeIRR(AADDV), uint32(0xfd8), REG_R13, REG_R13)
357 plt.AddUint32(ctxt.Arch, t)
358
359
360 t = OP_12IRR(OpCodeIRR(AADDV), 0, REG_R14, REG_R12)
361 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_LOONG64_ADDR_LO, 4)
362 plt.SetUint32(ctxt.Arch, plt.Size()-4, t)
363
364
365 t = OP_6IRR(OpCodeIRR(ASRLV), 1, REG_R13, REG_R13)
366 plt.AddUint32(ctxt.Arch, t)
367
368
369 t = OP_12IRR(OpCodeIRR(-AMOVV), 8, REG_R12, REG_R12)
370 plt.AddUint32(ctxt.Arch, t)
371
372
373 t = OP_16IRR(OpCodeIRR(AJIRL), 0, REG_R15, REG_R0)
374 plt.AddUint32(ctxt.Arch, t)
375
376
377 if gotplt.Size() != 0 {
378 ctxt.Errorf(gotplt.Sym(), "got.plt is not empty at the very beginning")
379 }
380
381 gotplt.AddUint64(ctxt.Arch, 0)
382 gotplt.AddUint64(ctxt.Arch, 0)
383 }
384 }
385
386 func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
387 if ldr.SymPlt(s) >= 0 {
388 return
389 }
390
391 ld.Adddynsym(ldr, target, syms, s)
392
393 if target.IsElf() {
394 var t uint32
395 plt := ldr.MakeSymbolUpdater(syms.PLT)
396 gotplt := ldr.MakeSymbolUpdater(syms.GOTPLT)
397 rela := ldr.MakeSymbolUpdater(syms.RelaPLT)
398 if plt.Size() == 0 {
399 panic("plt is not set up")
400 }
401
402
403 t = OP_IR(OpCodeIR(APCALAU12I), 0, REG_R15)
404 plt.AddAddrPlus4(target.Arch, gotplt.Sym(), gotplt.Size())
405 plt.SetUint32(target.Arch, plt.Size()-4, t)
406 relocs := plt.Relocs()
407 plt.SetRelocType(relocs.Count()-1, objabi.R_LOONG64_ADDR_HI)
408
409
410 t = OP_12IRR(OpCodeIRR(-AMOVV), 0, REG_R15, REG_R15)
411 plt.AddAddrPlus4(target.Arch, gotplt.Sym(), gotplt.Size())
412 plt.SetUint32(target.Arch, plt.Size()-4, t)
413 relocs = plt.Relocs()
414 plt.SetRelocType(relocs.Count()-1, objabi.R_LOONG64_ADDR_LO)
415
416
417 t = OP_IR(OpCodeIR(APCADDU12I), 0, REG_R13)
418 plt.AddUint32(target.Arch, t)
419
420
421 t = OP_16IRR(OpCodeIRR(AJIRL), 0, REG_R15, REG_R0)
422 plt.AddUint32(target.Arch, t)
423
424
425 gotplt.AddAddrPlus(target.Arch, plt.Sym(), 0)
426
427
428 rela.AddAddrPlus(target.Arch, gotplt.Sym(), gotplt.Size()-8)
429 sDynid := ldr.SymDynid(s)
430 rela.AddUint64(target.Arch, elf.R_INFO(uint32(sDynid), uint32(elf.R_LARCH_JUMP_SLOT)))
431 rela.AddUint64(target.Arch, 0)
432
433 ldr.SetPlt(s, int32(plt.Size()-16))
434 } else {
435 ldr.Errorf(s, "addpltsym: unsupport binary format")
436 }
437 }
438
439 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
440
441
442
443
444
445 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
446 switch r.Type {
447 default:
448 return false
449 case objabi.R_ADDR, objabi.R_DWARFSECREF:
450 switch r.Size {
451 case 4:
452 out.Write64(uint64(sectoff))
453 out.Write64(uint64(elf.R_LARCH_32) | uint64(elfsym)<<32)
454 out.Write64(uint64(r.Xadd))
455 case 8:
456 out.Write64(uint64(sectoff))
457 out.Write64(uint64(elf.R_LARCH_64) | uint64(elfsym)<<32)
458 out.Write64(uint64(r.Xadd))
459 default:
460 return false
461 }
462 case objabi.R_LOONG64_TLS_LE_LO:
463 out.Write64(uint64(sectoff))
464 out.Write64(uint64(elf.R_LARCH_TLS_LE_LO12) | uint64(elfsym)<<32)
465 out.Write64(uint64(r.Xadd))
466
467 case objabi.R_LOONG64_TLS_LE_HI:
468 out.Write64(uint64(sectoff))
469 out.Write64(uint64(elf.R_LARCH_TLS_LE_HI20) | uint64(elfsym)<<32)
470 out.Write64(uint64(r.Xadd))
471
472 case objabi.R_CALLLOONG64:
473 out.Write64(uint64(sectoff))
474 out.Write64(uint64(elf.R_LARCH_B26) | uint64(elfsym)<<32)
475 out.Write64(uint64(r.Xadd))
476
477 case objabi.R_LOONG64_CALL36:
478 out.Write64(uint64(sectoff))
479 out.Write64(uint64(elf.R_LARCH_CALL36) | uint64(elfsym)<<32)
480 out.Write64(uint64(r.Xadd))
481
482 case objabi.R_LOONG64_TLS_IE_HI:
483 out.Write64(uint64(sectoff))
484 out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_HI20) | uint64(elfsym)<<32)
485 out.Write64(uint64(0x0))
486
487 case objabi.R_LOONG64_TLS_IE_LO:
488 out.Write64(uint64(sectoff))
489 out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_LO12) | uint64(elfsym)<<32)
490 out.Write64(uint64(0x0))
491
492 case objabi.R_LOONG64_ADDR_LO:
493 out.Write64(uint64(sectoff))
494 out.Write64(uint64(elf.R_LARCH_PCALA_LO12) | uint64(elfsym)<<32)
495 out.Write64(uint64(r.Xadd))
496
497 case objabi.R_LOONG64_ADDR_HI:
498 out.Write64(uint64(sectoff))
499 out.Write64(uint64(elf.R_LARCH_PCALA_HI20) | uint64(elfsym)<<32)
500 out.Write64(uint64(r.Xadd))
501
502 case objabi.R_LOONG64_ADDR64_LO:
503 out.Write64(uint64(sectoff))
504 out.Write64(uint64(elf.R_LARCH_PCALA64_LO20) | uint64(elfsym)<<32)
505 out.Write64(uint64(r.Xadd))
506
507 case objabi.R_LOONG64_ADDR64_HI:
508 out.Write64(uint64(sectoff))
509 out.Write64(uint64(elf.R_LARCH_PCALA64_HI12) | uint64(elfsym)<<32)
510 out.Write64(uint64(r.Xadd))
511
512 case objabi.R_LOONG64_ADDR_PCREL20_S2:
513 out.Write64(uint64(sectoff))
514 out.Write64(uint64(elf.R_LARCH_PCREL20_S2) | uint64(elfsym)<<32)
515 out.Write64(uint64(r.Xadd))
516
517 case objabi.R_LOONG64_GOT_HI:
518 out.Write64(uint64(sectoff))
519 out.Write64(uint64(elf.R_LARCH_GOT_PC_HI20) | uint64(elfsym)<<32)
520 out.Write64(uint64(0x0))
521
522 case objabi.R_LOONG64_GOT_LO:
523 out.Write64(uint64(sectoff))
524 out.Write64(uint64(elf.R_LARCH_GOT_PC_LO12) | uint64(elfsym)<<32)
525 out.Write64(uint64(0x0))
526
527 case objabi.R_LOONG64_GOT64_HI:
528 out.Write64(uint64(sectoff))
529 out.Write64(uint64(elf.R_LARCH_GOT64_PC_HI12) | uint64(elfsym)<<32)
530 out.Write64(uint64(0x0))
531
532 case objabi.R_LOONG64_GOT64_LO:
533 out.Write64(uint64(sectoff))
534 out.Write64(uint64(elf.R_LARCH_GOT64_PC_LO20) | uint64(elfsym)<<32)
535 out.Write64(uint64(0x0))
536 }
537
538 return true
539 }
540
541 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
542 return false
543 }
544
545 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) {
546 rs := r.Sym()
547 if target.IsExternal() {
548 switch r.Type() {
549 default:
550 return val, 0, false
551 case objabi.R_LOONG64_ADDR_HI,
552 objabi.R_LOONG64_ADDR_LO,
553 objabi.R_LOONG64_ADDR64_HI,
554 objabi.R_LOONG64_ADDR64_LO,
555 objabi.R_LOONG64_ADDR_PCREL20_S2:
556
557 rs, _ := ld.FoldSubSymbolOffset(ldr, rs)
558 rst := ldr.SymType(rs)
559 if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil {
560 ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
561 }
562 return val, 1, true
563
564 case objabi.R_LOONG64_TLS_LE_HI,
565 objabi.R_LOONG64_TLS_LE_LO,
566 objabi.R_CALLLOONG64,
567 objabi.R_LOONG64_CALL36,
568 objabi.R_LOONG64_TLS_IE_HI,
569 objabi.R_LOONG64_TLS_IE_LO,
570 objabi.R_LOONG64_GOT_HI,
571 objabi.R_LOONG64_GOT_LO,
572 objabi.R_LOONG64_GOT64_HI,
573 objabi.R_LOONG64_GOT64_LO:
574 return val, 1, true
575 }
576 }
577
578 const isOk = true
579 const noExtReloc = 0
580
581 switch r.Type() {
582 case objabi.R_LOONG64_ADDR_HI,
583 objabi.R_LOONG64_ADDR_LO,
584 objabi.R_LOONG64_ADDR64_HI,
585 objabi.R_LOONG64_ADDR64_LO:
586 pc := ldr.SymValue(s) + int64(r.Off())
587 var t int64
588
589 switch r.Type() {
590 case objabi.R_LOONG64_ADDR_LO:
591
592 t = pc32RelocBits(r.Type(), ldr.SymAddr(rs)+r.Add(), pc)
593 o = val&0xffc003ff | (t << 10)
594 case objabi.R_LOONG64_ADDR_HI:
595
596 t = pc32RelocBits(r.Type(), ldr.SymAddr(rs)+r.Add(), pc)
597 o = val&0xfe00001f | (t << 5)
598 case objabi.R_LOONG64_ADDR64_LO:
599
600 t = pc64RelocBits(r.Type(), ldr.SymAddr(rs)+r.Add(), pc-8)
601 o = val&0xfe00001f | (t << 5)
602 case objabi.R_LOONG64_ADDR64_HI:
603
604 t = pc64RelocBits(r.Type(), ldr.SymAddr(rs)+r.Add(), pc-12)
605 o = val&0xffc003ff | (t << 10)
606 }
607
608 return o, noExtReloc, isOk
609
610 case objabi.R_LOONG64_ADDR_PCREL20_S2:
611 pc := ldr.SymValue(s) + int64(r.Off())
612 t := (ldr.SymAddr(rs) + r.Add() - pc) >> 2
613 if t < -1<<21 || t >= 1<<21 {
614 ldr.Errorf(s, "reloc: R_LOONG64_ADDR_PCREL20_S2, offset out of range %d", t)
615 }
616
617 return val&0xfe00001f | ((t & 0xfffff) << 5), noExtReloc, isOk
618
619 case objabi.R_LOONG64_TLS_LE_HI,
620 objabi.R_LOONG64_TLS_LE_LO:
621 t := ldr.SymAddr(rs) + r.Add()
622 if t < -1<<31 || t >= 1<<31 {
623 ldr.Errorf(s, "reloc: R_LOONG64_TLS_LE_HI/LO, TLS offset out of range %d", t)
624 }
625 if r.Type() == objabi.R_LOONG64_TLS_LE_LO {
626
627 return val&0xffc003ff | ((t & 0xfff) << 10), noExtReloc, isOk
628 }
629
630 return val&0xfe00001f | (((t) >> 12 << 5) & 0x1ffffe0), noExtReloc, isOk
631
632 case objabi.R_CALLLOONG64:
633 pc := ldr.SymValue(s) + int64(r.Off())
634 t := ldr.SymAddr(rs) + r.Add() - pc
635 if t < -1<<27 || t >= 1<<27 {
636 ldr.Errorf(s, "reloc: R_CALLLOONG64, program too large, call relocation distance = %d", t)
637 }
638
639 return val&0xfc000000 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x3ff0000) >> 16), noExtReloc, isOk
640
641 case objabi.R_LOONG64_CALL36:
642 pc := ldr.SymValue(s) + int64(r.Off())
643 t := (ldr.SymAddr(rs) + r.Add() - pc) >> 2
644 if t < -1<<37 || t >= 1<<37 {
645 ldr.Errorf(s, "reloc: R_LOONG64_CALL36, program too large, call relocation distance = %d", t)
646 }
647
648 pcaddu18i := (val & 0xfe00001f) | (((t + 0x8000) >> 16) << 5)
649 jirl := ((val >> 32) & 0xfc0003ff) | ((t & 0xffff) << 10)
650 return pcaddu18i | (jirl << 32), noExtReloc, isOk
651
652 case objabi.R_JMP16LOONG64,
653 objabi.R_JMP21LOONG64:
654 pc := ldr.SymValue(s) + int64(r.Off())
655 t := ldr.SymAddr(rs) + r.Add() - pc
656 if r.Type() == objabi.R_JMP16LOONG64 {
657 if t < -1<<17 || t >= 1<<17 {
658 ldr.Errorf(s, "reloc: R_JMP16LOONG64, program too large, jmp relocation distance = %d", t)
659 }
660
661 return val&0xfc0003ff | (((t >> 2) & 0xffff) << 10), noExtReloc, isOk
662 }
663 if t < -1<<22 || t >= 1<<22 {
664 ldr.Errorf(s, "reloc: R_JMP21LOONG64, program too large, call relocation distance = %d", t)
665 }
666
667 return val&0xfc0003e0 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x1f0000) >> 16), noExtReloc, isOk
668
669 case objabi.R_LOONG64_TLS_IE_HI,
670 objabi.R_LOONG64_TLS_IE_LO:
671 if target.IsPIE() && target.IsElf() {
672 if !target.IsLinux() {
673 ldr.Errorf(s, "TLS reloc on unsupported OS %v", target.HeadType)
674 }
675 t := ldr.SymAddr(rs) + r.Add()
676 if t < -1<<31 || t >= 1<<31 {
677 ldr.Errorf(s, "reloc: R_LOONG64_TLS_IE_HI/LO, TLS offset out of range %d", t)
678 }
679 if r.Type() == objabi.R_LOONG64_TLS_IE_HI {
680
681 return (0x14000000 | (val & 0x1f) | ((t >> 12) << 5)), noExtReloc, isOk
682 }
683
684 return (0x03800000 | (val & 0x3ff) | ((t & 0xfff) << 10)), noExtReloc, isOk
685 } else {
686 log.Fatalf("cannot handle R_LOONG64_TLS_IE_x (sym %s) when linking internally", ldr.SymName(rs))
687 }
688
689 case objabi.R_LOONG64_ADD64, objabi.R_LOONG64_SUB64:
690 if r.Type() == objabi.R_LOONG64_ADD64 {
691 return val + ldr.SymAddr(rs) + r.Add(), noExtReloc, isOk
692 }
693 return val - (ldr.SymAddr(rs) + r.Add()), noExtReloc, isOk
694 }
695
696 return val, 0, false
697 }
698
699 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
700 return -1
701 }
702
703 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
704 switch r.Type() {
705 case objabi.R_LOONG64_ADDR_HI,
706 objabi.R_LOONG64_ADDR_LO,
707 objabi.R_LOONG64_ADDR64_HI,
708 objabi.R_LOONG64_ADDR64_LO,
709 objabi.R_LOONG64_GOT_HI,
710 objabi.R_LOONG64_GOT_LO,
711 objabi.R_LOONG64_GOT64_HI,
712 objabi.R_LOONG64_GOT64_LO:
713 return ld.ExtrelocViaOuterSym(ldr, r, s), true
714
715 case objabi.R_LOONG64_TLS_LE_HI,
716 objabi.R_LOONG64_TLS_LE_LO,
717 objabi.R_CALLLOONG64,
718 objabi.R_LOONG64_TLS_IE_HI,
719 objabi.R_LOONG64_TLS_IE_LO:
720 return ld.ExtrelocSimple(ldr, r), true
721 }
722 return loader.ExtReloc{}, false
723 }
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757 func pc32RelocBits(reloc objabi.RelocType, tgt int64, pc int64) int64 {
758 lo12 := tgt & 0xfff
759 if reloc == objabi.R_LOONG64_ADDR_LO {
760 return lo12
761 }
762
763 off := (tgt & ^0xfff) - (pc & ^0xfff)
764 if lo12 >= 0x800 {
765 off += 0x1000
766 }
767
768
769 return (off >> 12) & 0xfffff
770 }
771
772 func pc64RelocBits(reloc objabi.RelocType, tgt int64, pc int64) int64 {
773 lo12 := tgt & 0xfff
774 off := (tgt & ^0xfff) - (pc & ^0xfff)
775
776 if lo12 >= 0x800 {
777 off += (0x1000 - 0x100000000)
778 }
779
780 if (off & 0x80000000) != 0 {
781 off += 0x100000000
782 }
783
784 if reloc == objabi.R_LOONG64_ADDR64_LO {
785 return (off >> 32) & 0xfffff
786 }
787
788
789 return (off >> 52) & 0xfff
790 }
791
792
793 func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
794 relocs := ldr.Relocs(s)
795 r := relocs.At(ri)
796 switch r.Type() {
797 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B26), objabi.R_CALLLOONG64:
798 var t int64
799
800
801
802 if ldr.SymValue(rs) != 0 {
803 t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
804 }
805 if t >= 1<<27 || t < -1<<27 || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && (ldr.SymPkg(s) == "" || ldr.SymPkg(s) != ldr.SymPkg(rs))) {
806
807
808
809 var tramp loader.Sym
810 for i := 0; ; i++ {
811 oName := ldr.SymName(rs)
812 name := oName + fmt.Sprintf("%+x-tramp%d", r.Add(), i)
813 tramp = ldr.LookupOrCreateSym(name, ldr.SymVersion(rs))
814 ldr.SetAttrReachable(tramp, true)
815 if ldr.SymType(tramp) == sym.SDYNIMPORT {
816
817 continue
818 }
819 if oName == "runtime.deferreturn" {
820 ldr.SetIsDeferReturnTramp(tramp, true)
821 }
822 if ldr.SymValue(tramp) == 0 {
823
824
825
826 break
827 }
828
829 t = ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off()))
830 if t >= -1<<27 && t < 1<<27 {
831
832
833 break
834 }
835 }
836 if ldr.SymType(tramp) == 0 {
837
838 trampb := ldr.MakeSymbolUpdater(tramp)
839 ctxt.AddTramp(trampb, ldr.SymType(s))
840 if ldr.SymType(rs) == sym.SDYNIMPORT {
841 if r.Add() != 0 {
842 ctxt.Errorf(s, "nonzero addend for DYNIMPORT call: %v+%d", ldr.SymName(rs), r.Add())
843 }
844 gentrampgot(ctxt, ldr, trampb, rs)
845 } else {
846 gentramp(ctxt, ldr, trampb, rs, r.Add())
847 }
848 }
849
850 sb := ldr.MakeSymbolUpdater(s)
851 relocs := sb.Relocs()
852 r := relocs.At(ri)
853 r.SetSym(tramp)
854 r.SetAdd(0)
855 }
856 default:
857 ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
858 }
859 }
860
861
862 func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
863 tramp.SetSize(12)
864 P := make([]byte, tramp.Size())
865
866 o1 := OP_IR(OpCodeIR(APCALAU12I), 0, REGRT1)
867 ctxt.Arch.ByteOrder.PutUint32(P, o1)
868 r1, _ := tramp.AddRel(objabi.R_LOONG64_ADDR_HI)
869 r1.SetOff(0)
870 r1.SetSiz(4)
871 r1.SetSym(target)
872 r1.SetAdd(offset)
873
874 o2 := OP_12IRR(OpCodeIRR(AADDV), 0, REGRT1, REGRT1)
875 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
876 r2, _ := tramp.AddRel(objabi.R_LOONG64_ADDR_LO)
877 r2.SetOff(4)
878 r2.SetSiz(4)
879 r2.SetSym(target)
880 r2.SetAdd(offset)
881
882 o3 := OP_16IRR(OpCodeIRR(AJIRL), 0, REGRT1, REG_R0)
883 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
884
885 tramp.SetData(P)
886 }
887
888 func gentrampgot(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym) {
889 tramp.SetSize(12)
890 P := make([]byte, tramp.Size())
891
892 o1 := OP_IR(OpCodeIR(APCALAU12I), 0, REGRT1)
893 ctxt.Arch.ByteOrder.PutUint32(P, o1)
894 r1, _ := tramp.AddRel(objabi.R_LOONG64_GOT_HI)
895 r1.SetOff(0)
896 r1.SetSiz(4)
897 r1.SetSym(target)
898
899 o2 := OP_12IRR(OpCodeIRR(-AMOVV), 0, REGRT1, REGRT1)
900 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
901 r2, _ := tramp.AddRel(objabi.R_LOONG64_GOT_LO)
902 r2.SetOff(4)
903 r2.SetSiz(4)
904 r2.SetSym(target)
905
906 o3 := OP_16IRR(OpCodeIRR(AJIRL), 0, REGRT1, REG_R0)
907 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
908
909 tramp.SetData(P)
910 }
911
View as plain text