1
2
3
4
5 package riscv64
6
7 import (
8 "cmd/internal/obj/riscv"
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 "sort"
18 )
19
20
21 const fakeLabelName = ".L0 "
22
23 func gentext(ctxt *ld.Link, ldr *loader.Loader) {}
24
25 func findHI20Reloc(ldr *loader.Loader, s loader.Sym, val int64) *loader.Reloc {
26 outer := ldr.OuterSym(s)
27 if outer == 0 {
28 return nil
29 }
30 relocs := ldr.Relocs(outer)
31 start := sort.Search(relocs.Count(), func(i int) bool { return ldr.SymValue(outer)+int64(relocs.At(i).Off()) >= val })
32 for idx := start; idx < relocs.Count(); idx++ {
33 r := relocs.At(idx)
34 if ldr.SymValue(outer)+int64(r.Off()) != val {
35 break
36 }
37 if r.Type() == objabi.R_RISCV_GOT_HI20 || r.Type() == objabi.R_RISCV_PCREL_HI20 {
38 return &r
39 }
40 }
41 return nil
42 }
43
44 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
45 targ := r.Sym()
46
47 var targType sym.SymKind
48 if targ != 0 {
49 targType = ldr.SymType(targ)
50 }
51
52 switch r.Type() {
53 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_CALL),
54 objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_CALL_PLT):
55
56 if targType == sym.SDYNIMPORT {
57 addpltsym(target, ldr, syms, targ)
58 su := ldr.MakeSymbolUpdater(s)
59 su.SetRelocSym(rIdx, syms.PLT)
60 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
61 }
62 if targType == 0 || targType == sym.SXREF {
63 ldr.Errorf(s, "unknown symbol %s in RISCV call", ldr.SymName(targ))
64 }
65 su := ldr.MakeSymbolUpdater(s)
66 su.SetRelocType(rIdx, objabi.R_RISCV_CALL)
67 return true
68
69 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_GOT_HI20):
70 if targType != sym.SDYNIMPORT {
71
72 }
73
74 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_RISCV_64))
75 su := ldr.MakeSymbolUpdater(s)
76 su.SetRelocType(rIdx, objabi.R_RISCV_GOT_HI20)
77 su.SetRelocSym(rIdx, syms.GOT)
78 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
79 return true
80
81 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_PCREL_HI20):
82 su := ldr.MakeSymbolUpdater(s)
83 su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_HI20)
84 return true
85
86 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_PCREL_LO12_I):
87 if r.Add() != 0 {
88 ldr.Errorf(s, "R_RISCV_PCREL_LO12_I with non-zero addend")
89 }
90 su := ldr.MakeSymbolUpdater(s)
91 su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_LO12_I)
92 return true
93
94 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_PCREL_LO12_S):
95 if r.Add() != 0 {
96 ldr.Errorf(s, "R_RISCV_PCREL_LO12_S with non-zero addend")
97 }
98 su := ldr.MakeSymbolUpdater(s)
99 su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_LO12_S)
100 return true
101
102 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_RVC_BRANCH):
103 su := ldr.MakeSymbolUpdater(s)
104 su.SetRelocType(rIdx, objabi.R_RISCV_RVC_BRANCH)
105 return true
106
107 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_RVC_JUMP):
108 su := ldr.MakeSymbolUpdater(s)
109 su.SetRelocType(rIdx, objabi.R_RISCV_RVC_JUMP)
110 return true
111
112 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_BRANCH):
113 su := ldr.MakeSymbolUpdater(s)
114 su.SetRelocType(rIdx, objabi.R_RISCV_BRANCH)
115 return true
116
117 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_RELAX):
118
119 return true
120
121 default:
122 if r.Type() >= objabi.ElfRelocOffset {
123 ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
124 return false
125 }
126 }
127
128
129 relocs := ldr.Relocs(s)
130 r = relocs.At(rIdx)
131
132 switch r.Type() {
133 case objabi.R_RISCV_CALL:
134 if targType != sym.SDYNIMPORT {
135
136 return true
137 }
138 if target.IsExternal() {
139
140 return true
141 }
142
143 if r.Add() != 0 {
144 ldr.Errorf(s, "PLT reference with non-zero addend (%v)", r.Add())
145 }
146
147 addpltsym(target, ldr, syms, targ)
148 su := ldr.MakeSymbolUpdater(s)
149 su.SetRelocSym(rIdx, syms.PLT)
150 su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
151
152 return true
153 }
154
155 return false
156 }
157
158 func genSymsLate(ctxt *ld.Link, ldr *loader.Loader) {
159 if ctxt.LinkMode != ld.LinkExternal {
160 return
161 }
162
163
164
165 if ctxt.Textp == nil {
166 log.Fatal("genSymsLate called before Textp has been assigned")
167 }
168 var hi20Syms []loader.Sym
169 for _, s := range ctxt.Textp {
170 relocs := ldr.Relocs(s)
171 for ri := 0; ri < relocs.Count(); ri++ {
172 r := relocs.At(ri)
173 if r.Type() != objabi.R_RISCV_CALL && r.Type() != objabi.R_RISCV_PCREL_ITYPE &&
174 r.Type() != objabi.R_RISCV_PCREL_STYPE && r.Type() != objabi.R_RISCV_TLS_IE {
175 continue
176 }
177 if r.Off() == 0 && ldr.SymType(s).IsText() {
178
179
180 continue
181 }
182
183
184
185
186
187 sb := ldr.MakeSymbolBuilder(fakeLabelName)
188 sb.SetType(sym.STEXT)
189 sb.SetValue(ldr.SymValue(s) + int64(r.Off()))
190 sb.SetLocal(true)
191 sb.SetReachable(true)
192 sb.SetVisibilityHidden(true)
193 sb.SetSect(ldr.SymSect(s))
194 if outer := ldr.OuterSym(s); outer != 0 {
195 ldr.AddInteriorSym(outer, sb.Sym())
196 }
197 hi20Syms = append(hi20Syms, sb.Sym())
198 }
199 }
200 ctxt.Textp = append(ctxt.Textp, hi20Syms...)
201 ldr.SortSyms(ctxt.Textp)
202 }
203
204 func findHI20Symbol(ctxt *ld.Link, ldr *loader.Loader, val int64) loader.Sym {
205 idx := sort.Search(len(ctxt.Textp), func(i int) bool { return ldr.SymValue(ctxt.Textp[i]) >= val })
206 if idx >= len(ctxt.Textp) {
207 return 0
208 }
209 if s := ctxt.Textp[idx]; ldr.SymValue(s) == val && ldr.SymType(s).IsText() {
210 return s
211 }
212 return 0
213 }
214
215 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
216 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
217 switch r.Type {
218 case objabi.R_ADDR, objabi.R_DWARFSECREF:
219 out.Write64(uint64(sectoff))
220 switch r.Size {
221 case 4:
222 out.Write64(uint64(elf.R_RISCV_32) | uint64(elfsym)<<32)
223 case 8:
224 out.Write64(uint64(elf.R_RISCV_64) | uint64(elfsym)<<32)
225 default:
226 ld.Errorf("unknown size %d for %v relocation", r.Size, r.Type)
227 return false
228 }
229 out.Write64(uint64(r.Xadd))
230
231 case objabi.R_RISCV_JAL, objabi.R_RISCV_JAL_TRAMP:
232 out.Write64(uint64(sectoff))
233 out.Write64(uint64(elf.R_RISCV_JAL) | uint64(elfsym)<<32)
234 out.Write64(uint64(r.Xadd))
235
236 case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE:
237
238
239 relocs := ldr.Relocs(s)
240 offset := int64(relocs.At(ri).Off())
241 hi20Sym := findHI20Symbol(ctxt, ldr, ldr.SymValue(s)+offset)
242 if hi20Sym == 0 {
243 ld.Errorf("failed to find text symbol for HI20 relocation at %d (%x)", sectoff, ldr.SymValue(s)+offset)
244 return false
245 }
246 hi20ElfSym := ld.ElfSymForReloc(ctxt, hi20Sym)
247
248
249
250
251
252
253
254
255
256
257 var hiRel, loRel elf.R_RISCV
258 switch r.Type {
259 case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE:
260 hiRel, loRel = elf.R_RISCV_PCREL_HI20, elf.R_RISCV_PCREL_LO12_I
261 case objabi.R_RISCV_PCREL_STYPE:
262 hiRel, loRel = elf.R_RISCV_PCREL_HI20, elf.R_RISCV_PCREL_LO12_S
263 case objabi.R_RISCV_TLS_IE:
264 hiRel, loRel = elf.R_RISCV_TLS_GOT_HI20, elf.R_RISCV_PCREL_LO12_I
265 }
266 out.Write64(uint64(sectoff))
267 out.Write64(uint64(hiRel) | uint64(elfsym)<<32)
268 out.Write64(uint64(r.Xadd))
269 out.Write64(uint64(sectoff + 4))
270 out.Write64(uint64(loRel) | uint64(hi20ElfSym)<<32)
271 out.Write64(uint64(0))
272
273 case objabi.R_RISCV_TLS_LE:
274 out.Write64(uint64(sectoff))
275 out.Write64(uint64(elf.R_RISCV_TPREL_HI20) | uint64(elfsym)<<32)
276 out.Write64(uint64(r.Xadd))
277 out.Write64(uint64(sectoff + 4))
278 out.Write64(uint64(elf.R_RISCV_TPREL_LO12_I) | uint64(elfsym)<<32)
279 out.Write64(uint64(r.Xadd))
280
281 default:
282 return false
283 }
284
285 return true
286 }
287
288 func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
289 if plt.Size() != 0 {
290 return
291 }
292 if gotplt.Size() != 0 {
293 ctxt.Errorf(gotplt.Sym(), "got.plt is not empty")
294 }
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_RISCV_PCREL_HI20, 4)
310 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x00000397)
311
312 sb := ldr.MakeSymbolBuilder(fakeLabelName)
313 sb.SetType(sym.STEXT)
314 sb.SetValue(ldr.SymValue(plt.Sym()) + plt.Size() - 4)
315 sb.SetLocal(true)
316 sb.SetReachable(true)
317 sb.SetVisibilityHidden(true)
318 plt.AddInteriorSym(sb.Sym())
319
320 plt.AddUint32(ctxt.Arch, 0x41c30333)
321
322 plt.AddSymRef(ctxt.Arch, sb.Sym(), 0, objabi.R_RISCV_PCREL_LO12_I, 4)
323 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x0003be03)
324
325 plt.AddUint32(ctxt.Arch, 0xfd430313)
326
327 plt.AddSymRef(ctxt.Arch, sb.Sym(), 0, objabi.R_RISCV_PCREL_LO12_I, 4)
328 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x00038293)
329
330 plt.AddUint32(ctxt.Arch, 0x00135313)
331 plt.AddUint32(ctxt.Arch, 0x0082b283)
332 plt.AddUint32(ctxt.Arch, 0x00008e02)
333
334 gotplt.AddAddrPlus(ctxt.Arch, dynamic, 0)
335 gotplt.AddUint64(ctxt.Arch, 0)
336 }
337
338 func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
339 if ldr.SymPlt(s) >= 0 {
340 return
341 }
342
343 ld.Adddynsym(ldr, target, syms, s)
344
345 plt := ldr.MakeSymbolUpdater(syms.PLT)
346 gotplt := ldr.MakeSymbolUpdater(syms.GOTPLT)
347 rela := ldr.MakeSymbolUpdater(syms.RelaPLT)
348 if plt.Size() == 0 {
349 panic("plt is not set up")
350 }
351
352
353
354
355
356
357
358
359
360
361 plt.AddSymRef(target.Arch, gotplt.Sym(), gotplt.Size(), objabi.R_RISCV_PCREL_HI20, 4)
362 plt.SetUint32(target.Arch, plt.Size()-4, 0x00000e17)
363
364 sb := ldr.MakeSymbolBuilder(fakeLabelName)
365 sb.SetType(sym.STEXT)
366 sb.SetValue(ldr.SymValue(plt.Sym()) + plt.Size() - 4)
367 sb.SetLocal(true)
368 sb.SetReachable(true)
369 sb.SetVisibilityHidden(true)
370 plt.AddInteriorSym(sb.Sym())
371
372 plt.AddSymRef(target.Arch, sb.Sym(), 0, objabi.R_RISCV_PCREL_LO12_I, 4)
373 plt.SetUint32(target.Arch, plt.Size()-4, 0x000e3e03)
374 plt.AddUint32(target.Arch, 0x000e0367)
375 plt.AddUint32(target.Arch, 0x00000001)
376
377 ldr.SetPlt(s, int32(plt.Size()-16))
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
386 rela.AddUint64(target.Arch, elf.R_INFO(uint32(sDynid), uint32(elf.R_RISCV_JUMP_SLOT)))
387 rela.AddUint64(target.Arch, 0)
388 }
389
390 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
391 log.Fatalf("machoreloc1 not implemented")
392 return false
393 }
394
395 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) {
396 rs := r.Sym()
397 pc := ldr.SymValue(s) + int64(r.Off())
398
399
400
401
402 if r.Type() == objabi.R_RISCV_JAL_TRAMP {
403 relocs := ldr.Relocs(rs)
404 if relocs.Count() != 1 {
405 ldr.Errorf(s, "trampoline %v has %d relocations", ldr.SymName(rs), relocs.Count())
406 }
407 tr := relocs.At(0)
408 if tr.Type() != objabi.R_RISCV_CALL {
409 ldr.Errorf(s, "trampoline %v has unexpected relocation %v", ldr.SymName(rs), tr.Type())
410 }
411 trs := tr.Sym()
412 if ldr.SymValue(trs) != 0 && ldr.SymType(trs) != sym.SDYNIMPORT && ldr.SymType(trs) != sym.SUNDEFEXT {
413 trsOff := ldr.SymValue(trs) + tr.Add() - pc
414 if trsOff >= -(1<<20) && trsOff < (1<<20) {
415 r.SetType(objabi.R_RISCV_JAL)
416 r.SetSym(trs)
417 r.SetAdd(tr.Add())
418 rs = trs
419 }
420 }
421
422 }
423
424 if target.IsExternal() {
425 switch r.Type() {
426 case objabi.R_RISCV_JAL, objabi.R_RISCV_JAL_TRAMP:
427 return val, 1, true
428
429 case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE, objabi.R_RISCV_TLS_LE:
430 return val, 2, true
431 }
432
433 return val, 0, false
434 }
435
436 off := ldr.SymValue(rs) + r.Add() - pc
437
438 switch r.Type() {
439 case objabi.R_RISCV_JAL, objabi.R_RISCV_JAL_TRAMP:
440
441 imm, err := riscv.EncodeJImmediate(off)
442 if err != nil {
443 ldr.Errorf(s, "cannot encode J-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
444 }
445 immMask := int64(riscv.JTypeImmMask)
446
447 val = (val &^ immMask) | int64(imm)
448
449 return val, 0, true
450
451 case objabi.R_RISCV_TLS_IE:
452 log.Fatalf("cannot handle R_RISCV_TLS_IE (sym %s) when linking internally", ldr.SymName(s))
453 return val, 0, false
454
455 case objabi.R_RISCV_TLS_LE:
456
457 off := r.Add()
458
459 low, high, err := riscv.Split32BitImmediate(off)
460 if err != nil {
461 ldr.Errorf(s, "relocation does not fit in 32-bits: %d", off)
462 }
463
464 luiImm, err := riscv.EncodeUImmediate(high)
465 if err != nil {
466 ldr.Errorf(s, "cannot encode R_RISCV_TLS_LE LUI relocation offset for %s: %v", ldr.SymName(rs), err)
467 }
468
469 addiwImm, err := riscv.EncodeIImmediate(low)
470 if err != nil {
471 ldr.Errorf(s, "cannot encode R_RISCV_TLS_LE I-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
472 }
473
474 lui := int64(uint32(val))
475 addiw := int64(uint32(val >> 32))
476
477 lui = (lui &^ riscv.UTypeImmMask) | int64(uint32(luiImm))
478 addiw = (addiw &^ riscv.ITypeImmMask) | int64(uint32(addiwImm))
479
480 return addiw<<32 | lui, 0, true
481
482 case objabi.R_RISCV_BRANCH:
483 pc := ldr.SymValue(s) + int64(r.Off())
484 off := ldr.SymValue(rs) + r.Add() - pc
485
486 imm, err := riscv.EncodeBImmediate(off)
487 if err != nil {
488 ldr.Errorf(s, "cannot encode B-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
489 }
490 ins := (int64(uint32(val)) &^ riscv.BTypeImmMask) | int64(uint32(imm))
491
492 return ins, 0, true
493
494 case objabi.R_RISCV_RVC_BRANCH, objabi.R_RISCV_RVC_JUMP:
495 pc := ldr.SymValue(s) + int64(r.Off())
496 off := ldr.SymValue(rs) + r.Add() - pc
497
498 var err error
499 var imm, immMask int64
500 switch r.Type() {
501 case objabi.R_RISCV_RVC_BRANCH:
502 immMask = riscv.CBTypeImmMask
503 imm, err = riscv.EncodeCBImmediate(off)
504 if err != nil {
505 ldr.Errorf(s, "cannot encode CB-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
506 }
507 case objabi.R_RISCV_RVC_JUMP:
508 immMask = riscv.CJTypeImmMask
509 imm, err = riscv.EncodeCJImmediate(off)
510 if err != nil {
511 ldr.Errorf(s, "cannot encode CJ-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
512 }
513 default:
514 panic(fmt.Sprintf("unknown relocation type: %v", r.Type()))
515 }
516
517 ins := (int64(uint16(val)) &^ immMask) | int64(uint16(imm))
518
519 return ins, 0, true
520
521 case objabi.R_RISCV_GOT_HI20, objabi.R_RISCV_PCREL_HI20:
522 pc := ldr.SymValue(s) + int64(r.Off())
523 off := ldr.SymValue(rs) + r.Add() - pc
524
525
526 _, high, err := riscv.Split32BitImmediate(off)
527 if err != nil {
528 ldr.Errorf(s, "relocation does not fit in 32-bits: %d", off)
529 }
530
531 auipcImm, err := riscv.EncodeUImmediate(high)
532 if err != nil {
533 ldr.Errorf(s, "cannot encode R_RISCV_PCREL_ AUIPC relocation offset for %s: %v", ldr.SymName(rs), err)
534 }
535
536 auipc := int64(uint32(val))
537 auipc = (auipc &^ riscv.UTypeImmMask) | int64(uint32(auipcImm))
538
539 return auipc, 0, true
540
541 case objabi.R_RISCV_PCREL_LO12_I, objabi.R_RISCV_PCREL_LO12_S:
542 hi20Reloc := findHI20Reloc(ldr, rs, ldr.SymValue(rs))
543 if hi20Reloc == nil {
544 ldr.Errorf(s, "missing HI20 relocation for LO12 relocation with %s (%d)", ldr.SymName(rs), rs)
545 }
546
547 pc := ldr.SymValue(s) + int64(hi20Reloc.Off())
548 off := ldr.SymValue(hi20Reloc.Sym()) + hi20Reloc.Add() - pc
549
550 low, _, err := riscv.Split32BitImmediate(off)
551 if err != nil {
552 ldr.Errorf(s, "relocation does not fit in 32-bits: %d", off)
553 }
554
555 var imm, immMask int64
556 switch r.Type() {
557 case objabi.R_RISCV_PCREL_LO12_I:
558 immMask = riscv.ITypeImmMask
559 imm, err = riscv.EncodeIImmediate(low)
560 if err != nil {
561 ldr.Errorf(s, "cannot encode objabi.R_RISCV_PCREL_LO12_I I-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
562 }
563 case objabi.R_RISCV_PCREL_LO12_S:
564 immMask = riscv.STypeImmMask
565 imm, err = riscv.EncodeSImmediate(low)
566 if err != nil {
567 ldr.Errorf(s, "cannot encode R_RISCV_PCREL_LO12_S S-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
568 }
569 default:
570 panic(fmt.Sprintf("unknown relocation type: %v", r.Type()))
571 }
572
573 ins := int64(uint32(val))
574 ins = (ins &^ immMask) | int64(uint32(imm))
575 return ins, 0, true
576
577 case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE:
578
579 low, high, err := riscv.Split32BitImmediate(off)
580 if err != nil {
581 ldr.Errorf(s, "pc-relative relocation does not fit in 32 bits: %d", off)
582 }
583
584 auipcImm, err := riscv.EncodeUImmediate(high)
585 if err != nil {
586 ldr.Errorf(s, "cannot encode AUIPC relocation offset for %s: %v", ldr.SymName(rs), err)
587 }
588
589 var secondImm, secondImmMask int64
590 switch r.Type() {
591 case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE:
592 secondImmMask = riscv.ITypeImmMask
593 secondImm, err = riscv.EncodeIImmediate(low)
594 if err != nil {
595 ldr.Errorf(s, "cannot encode I-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
596 }
597 case objabi.R_RISCV_PCREL_STYPE:
598 secondImmMask = riscv.STypeImmMask
599 secondImm, err = riscv.EncodeSImmediate(low)
600 if err != nil {
601 ldr.Errorf(s, "cannot encode S-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
602 }
603 default:
604 panic(fmt.Sprintf("unknown relocation type: %v", r.Type()))
605 }
606
607 auipc := int64(uint32(val))
608 second := int64(uint32(val >> 32))
609
610 auipc = (auipc &^ riscv.UTypeImmMask) | int64(uint32(auipcImm))
611 second = (second &^ secondImmMask) | int64(uint32(secondImm))
612
613 return second<<32 | auipc, 0, true
614 }
615
616 return val, 0, false
617 }
618
619 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
620 log.Fatalf("archrelocvariant")
621 return -1
622 }
623
624 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
625 switch r.Type() {
626 case objabi.R_RISCV_JAL, objabi.R_RISCV_JAL_TRAMP:
627 return ld.ExtrelocSimple(ldr, r), true
628
629 case objabi.R_RISCV_CALL, objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE, objabi.R_RISCV_TLS_LE:
630 return ld.ExtrelocViaOuterSym(ldr, r, s), true
631 }
632 return loader.ExtReloc{}, false
633 }
634
635 func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
636 relocs := ldr.Relocs(s)
637 r := relocs.At(ri)
638
639 switch r.Type() {
640 case objabi.R_RISCV_JAL:
641 pc := ldr.SymValue(s) + int64(r.Off())
642 off := ldr.SymValue(rs) + r.Add() - pc
643
644
645
646 if ldr.SymValue(rs) != 0 && off >= -(1<<20) && off < (1<<20) && (*ld.FlagDebugTramp <= 1 || ldr.SymPkg(s) == ldr.SymPkg(rs)) {
647 break
648 }
649
650
651
652
653
654 var tramp loader.Sym
655 for i := 0; ; i++ {
656 oName := ldr.SymName(rs)
657 name := fmt.Sprintf("%s-tramp%d", oName, i)
658 if r.Add() != 0 {
659 name = fmt.Sprintf("%s%+x-tramp%d", oName, r.Add(), i)
660 }
661 tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs)))
662 ldr.SetAttrReachable(tramp, true)
663 if ldr.SymType(tramp) == sym.SDYNIMPORT {
664
665 continue
666 }
667 if oName == "runtime.deferreturn" {
668 ldr.SetIsDeferReturnTramp(tramp, true)
669 }
670 if ldr.SymValue(tramp) == 0 {
671
672
673
674 break
675 }
676
677 trampOff := ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off()))
678 if trampOff >= -(1<<20) && trampOff < (1<<20) {
679
680 break
681 }
682 }
683 if ldr.SymType(tramp) == 0 {
684 trampb := ldr.MakeSymbolUpdater(tramp)
685 ctxt.AddTramp(trampb, ldr.SymType(s))
686 genCallTramp(ctxt.Arch, ctxt.LinkMode, ldr, trampb, rs, int64(r.Add()))
687 }
688 sb := ldr.MakeSymbolUpdater(s)
689 if ldr.SymValue(rs) == 0 {
690
691
692
693
694 sb.SetRelocType(ri, objabi.R_RISCV_JAL_TRAMP)
695 }
696 relocs := sb.Relocs()
697 r := relocs.At(ri)
698 r.SetSym(tramp)
699 r.SetAdd(0)
700
701 case objabi.R_RISCV_CALL:
702
703
704 default:
705 ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
706 }
707 }
708
709 func genCallTramp(arch *sys.Arch, linkmode ld.LinkMode, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
710 tramp.AddUint32(arch, 0x00000f97)
711 tramp.AddUint32(arch, 0x000f8067)
712
713 r, _ := tramp.AddRel(objabi.R_RISCV_CALL)
714 r.SetSiz(8)
715 r.SetSym(target)
716 r.SetAdd(offset)
717 }
718
View as plain text