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