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