1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package arm64
32
33 import (
34 "cmd/internal/objabi"
35 "cmd/internal/sys"
36 "cmd/link/internal/ld"
37 "cmd/link/internal/loader"
38 "cmd/link/internal/sym"
39 "debug/elf"
40 "fmt"
41 "log"
42 )
43
44 func gentext(ctxt *ld.Link, ldr *loader.Loader) {
45 initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
46 if initfunc == nil {
47 return
48 }
49
50 o := func(op uint32) {
51 initfunc.AddUint32(ctxt.Arch, op)
52 }
53
54
55
56
57
58 o(0x90000000)
59 o(0x91000000)
60 rel, _ := initfunc.AddRel(objabi.R_ADDRARM64)
61 rel.SetOff(0)
62 rel.SetSiz(8)
63 rel.SetSym(ctxt.Moduledata)
64
65
66
67 o(0x14000000)
68 rel2, _ := initfunc.AddRel(objabi.R_CALLARM64)
69 rel2.SetOff(8)
70 rel2.SetSiz(4)
71 rel2.SetSym(addmoduledata)
72 }
73
74 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
75 targ := r.Sym()
76 var targType sym.SymKind
77 if targ != 0 {
78 targType = ldr.SymType(targ)
79 }
80
81 const pcrel = 1
82 switch r.Type() {
83 default:
84 if r.Type() >= objabi.ElfRelocOffset {
85 ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
86 return false
87 }
88
89
90 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_PREL32):
91 if targType == sym.SDYNIMPORT {
92 ldr.Errorf(s, "unexpected R_AARCH64_PREL32 relocation for dynamic symbol %s", ldr.SymName(targ))
93 }
94
95
96 if (targType == 0 || targType == sym.SXREF) && !ldr.AttrVisibilityHidden(targ) {
97 ldr.Errorf(s, "unknown symbol %s in pcrel", ldr.SymName(targ))
98 }
99 su := ldr.MakeSymbolUpdater(s)
100 su.SetRelocType(rIdx, objabi.R_PCREL)
101 su.SetRelocAdd(rIdx, r.Add()+4)
102 return true
103
104 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_PREL64):
105 if targType == sym.SDYNIMPORT {
106 ldr.Errorf(s, "unexpected R_AARCH64_PREL64 relocation for dynamic symbol %s", ldr.SymName(targ))
107 }
108 if targType == 0 || targType == sym.SXREF {
109 ldr.Errorf(s, "unknown symbol %s in pcrel", ldr.SymName(targ))
110 }
111 su := ldr.MakeSymbolUpdater(s)
112 su.SetRelocType(rIdx, objabi.R_PCREL)
113 su.SetRelocAdd(rIdx, r.Add()+8)
114 return true
115
116 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_CALL26),
117 objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_JUMP26):
118 if targType == sym.SDYNIMPORT {
119 addpltsym(target, ldr, syms, targ)
120 su := ldr.MakeSymbolUpdater(s)
121 su.SetRelocSym(rIdx, syms.PLT)
122 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
123 }
124 if (targType == 0 || targType == sym.SXREF) && !ldr.AttrVisibilityHidden(targ) {
125 ldr.Errorf(s, "unknown symbol %s in callarm64", ldr.SymName(targ))
126 }
127 su := ldr.MakeSymbolUpdater(s)
128 su.SetRelocType(rIdx, objabi.R_CALLARM64)
129 return true
130
131 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADR_GOT_PAGE),
132 objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LD64_GOT_LO12_NC):
133 if targType != sym.SDYNIMPORT {
134
135
136 }
137
138
139
140 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_AARCH64_GLOB_DAT))
141 su := ldr.MakeSymbolUpdater(s)
142 su.SetRelocType(rIdx, objabi.R_ARM64_GOT)
143 su.SetRelocSym(rIdx, syms.GOT)
144 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
145 return true
146
147 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADR_PREL_PG_HI21),
148 objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADD_ABS_LO12_NC):
149 if targType == sym.SDYNIMPORT {
150 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
151 }
152 if targType == 0 || targType == sym.SXREF {
153 ldr.Errorf(s, "unknown symbol %s", ldr.SymName(targ))
154 }
155 su := ldr.MakeSymbolUpdater(s)
156 su.SetRelocType(rIdx, objabi.R_ARM64_PCREL)
157 return true
158
159 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ABS64):
160 if targType == sym.SDYNIMPORT {
161 ldr.Errorf(s, "unexpected R_AARCH64_ABS64 relocation for dynamic symbol %s", ldr.SymName(targ))
162 }
163 su := ldr.MakeSymbolUpdater(s)
164 su.SetRelocType(rIdx, objabi.R_ADDR)
165 if target.IsPIE() && target.IsInternal() {
166
167
168
169 break
170 }
171 return true
172
173 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST8_ABS_LO12_NC):
174 if targType == sym.SDYNIMPORT {
175 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
176 }
177 su := ldr.MakeSymbolUpdater(s)
178 su.SetRelocType(rIdx, objabi.R_ARM64_LDST8)
179 return true
180
181 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST16_ABS_LO12_NC):
182 if targType == sym.SDYNIMPORT {
183 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
184 }
185 su := ldr.MakeSymbolUpdater(s)
186 su.SetRelocType(rIdx, objabi.R_ARM64_LDST16)
187 return true
188
189 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST32_ABS_LO12_NC):
190 if targType == sym.SDYNIMPORT {
191 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
192 }
193 su := ldr.MakeSymbolUpdater(s)
194 su.SetRelocType(rIdx, objabi.R_ARM64_LDST32)
195 return true
196
197 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST64_ABS_LO12_NC):
198 if targType == sym.SDYNIMPORT {
199 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
200 }
201 su := ldr.MakeSymbolUpdater(s)
202 su.SetRelocType(rIdx, objabi.R_ARM64_LDST64)
203
204 return true
205
206 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST128_ABS_LO12_NC):
207 if targType == sym.SDYNIMPORT {
208 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
209 }
210 su := ldr.MakeSymbolUpdater(s)
211 su.SetRelocType(rIdx, objabi.R_ARM64_LDST128)
212 return true
213
214
215 case objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_UNSIGNED*2:
216 if targType == sym.SDYNIMPORT {
217 ldr.Errorf(s, "unexpected reloc for dynamic symbol %s", ldr.SymName(targ))
218 }
219 su := ldr.MakeSymbolUpdater(s)
220 su.SetRelocType(rIdx, objabi.R_ADDR)
221 if target.IsPIE() && target.IsInternal() {
222
223
224
225 break
226 }
227 return true
228
229 case objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_BRANCH26*2 + pcrel:
230 su := ldr.MakeSymbolUpdater(s)
231 su.SetRelocType(rIdx, objabi.R_CALLARM64)
232 if targType == sym.SDYNIMPORT {
233 addpltsym(target, ldr, syms, targ)
234 su.SetRelocSym(rIdx, syms.PLT)
235 su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
236 }
237 return true
238
239 case objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_PAGE21*2 + pcrel,
240 objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_PAGEOFF12*2:
241 if targType == sym.SDYNIMPORT {
242 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
243 }
244 su := ldr.MakeSymbolUpdater(s)
245 su.SetRelocType(rIdx, objabi.R_ARM64_PCREL)
246 return true
247
248 case objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_GOT_LOAD_PAGE21*2 + pcrel,
249 objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_GOT_LOAD_PAGEOFF12*2:
250 if targType != sym.SDYNIMPORT {
251
252
253 data := ldr.Data(s)
254 off := r.Off()
255 if int(off+3) >= len(data) {
256 ldr.Errorf(s, "unexpected GOT_LOAD reloc for non-dynamic symbol %s", ldr.SymName(targ))
257 return false
258 }
259 o := target.Arch.ByteOrder.Uint32(data[off:])
260 su := ldr.MakeSymbolUpdater(s)
261 switch {
262 case (o>>24)&0x9f == 0x90:
263
264 case o>>24 == 0xf9:
265
266 o = (0x91 << 24) | (o & (1<<22 - 1))
267 su.MakeWritable()
268 su.SetUint32(target.Arch, int64(off), o)
269 default:
270 ldr.Errorf(s, "unexpected GOT_LOAD reloc for non-dynamic symbol %s", ldr.SymName(targ))
271 return false
272 }
273 su.SetRelocType(rIdx, objabi.R_ARM64_PCREL)
274 return true
275 }
276 ld.AddGotSym(target, ldr, syms, targ, 0)
277 su := ldr.MakeSymbolUpdater(s)
278 su.SetRelocType(rIdx, objabi.R_ARM64_GOT)
279 su.SetRelocSym(rIdx, syms.GOT)
280 su.SetRelocAdd(rIdx, int64(ldr.SymGot(targ)))
281 return true
282 }
283
284
285 relocs := ldr.Relocs(s)
286 r = relocs.At(rIdx)
287
288 switch r.Type() {
289 case objabi.R_CALL,
290 objabi.R_PCREL,
291 objabi.R_CALLARM64:
292 if targType != sym.SDYNIMPORT {
293
294 return true
295 }
296 if target.IsExternal() {
297
298 return true
299 }
300
301 if r.Add() != 0 {
302 ldr.Errorf(s, "PLT call with non-zero addend (%v)", r.Add())
303 }
304
305 addpltsym(target, ldr, syms, targ)
306 su := ldr.MakeSymbolUpdater(s)
307 su.SetRelocSym(rIdx, syms.PLT)
308 su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
309 return true
310
311 case objabi.R_ADDR:
312 if ldr.SymType(s) == sym.STEXT && target.IsElf() {
313
314
315
316 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_AARCH64_GLOB_DAT))
317 su := ldr.MakeSymbolUpdater(s)
318 su.SetRelocSym(rIdx, syms.GOT)
319 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
320 return true
321 }
322
323
324 if target.IsPIE() && target.IsInternal() {
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356 switch ldr.SymName(s) {
357 case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
358 return false
359 }
360 } else {
361
362
363
364
365
366
367 if ldr.SymType(s) != sym.SDATA && ldr.SymType(s) != sym.SRODATA {
368 break
369 }
370 }
371
372 if target.IsElf() {
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390 rela := ldr.MakeSymbolUpdater(syms.Rela)
391 rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
392 if r.Siz() == 8 {
393 rela.AddUint64(target.Arch, elf.R_INFO(0, uint32(elf.R_AARCH64_RELATIVE)))
394 } else {
395 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
396 }
397 rela.AddAddrPlus(target.Arch, targ, int64(r.Add()))
398
399
400
401
402 return true
403 }
404
405 if target.IsDarwin() {
406
407
408
409 ld.MachoAddRebase(s, int64(r.Off()))
410
411
412
413
414 return true
415 }
416
417 case objabi.R_ARM64_GOTPCREL:
418 if target.IsExternal() {
419
420 return true
421 }
422 if targType != sym.SDYNIMPORT {
423 ldr.Errorf(s, "R_ARM64_GOTPCREL target is not SDYNIMPORT symbol: %v", ldr.SymName(targ))
424 }
425 if r.Add() != 0 {
426 ldr.Errorf(s, "R_ARM64_GOTPCREL with non-zero addend (%v)", r.Add())
427 }
428 if target.IsElf() {
429 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_AARCH64_GLOB_DAT))
430 } else {
431 ld.AddGotSym(target, ldr, syms, targ, 0)
432 }
433
434 su := ldr.MakeSymbolUpdater(s)
435 r.SetType(objabi.R_ARM64_GOT)
436 r.SetSiz(4)
437 r.SetSym(syms.GOT)
438 r.SetAdd(int64(ldr.SymGot(targ)))
439 r2, _ := su.AddRel(objabi.R_ARM64_GOT)
440 r2.SetSiz(4)
441 r2.SetOff(r.Off() + 4)
442 r2.SetSym(syms.GOT)
443 r2.SetAdd(int64(ldr.SymGot(targ)))
444 return true
445 }
446 return false
447 }
448
449 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
450 out.Write64(uint64(sectoff))
451
452 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
453 siz := r.Size
454 switch r.Type {
455 default:
456 return false
457 case objabi.R_ADDR, objabi.R_DWARFSECREF:
458 switch siz {
459 case 4:
460 out.Write64(uint64(elf.R_AARCH64_ABS32) | uint64(elfsym)<<32)
461 case 8:
462 out.Write64(uint64(elf.R_AARCH64_ABS64) | uint64(elfsym)<<32)
463 default:
464 return false
465 }
466 case objabi.R_ADDRARM64:
467
468 out.Write64(uint64(elf.R_AARCH64_ADR_PREL_PG_HI21) | uint64(elfsym)<<32)
469 out.Write64(uint64(r.Xadd))
470 out.Write64(uint64(sectoff + 4))
471 out.Write64(uint64(elf.R_AARCH64_ADD_ABS_LO12_NC) | uint64(elfsym)<<32)
472 case objabi.R_ARM64_TLS_LE:
473 out.Write64(uint64(elf.R_AARCH64_TLSLE_MOVW_TPREL_G0) | uint64(elfsym)<<32)
474 case objabi.R_ARM64_TLS_IE:
475 out.Write64(uint64(elf.R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) | uint64(elfsym)<<32)
476 out.Write64(uint64(r.Xadd))
477 out.Write64(uint64(sectoff + 4))
478 out.Write64(uint64(elf.R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) | uint64(elfsym)<<32)
479 case objabi.R_ARM64_GOTPCREL:
480 out.Write64(uint64(elf.R_AARCH64_ADR_GOT_PAGE) | uint64(elfsym)<<32)
481 out.Write64(uint64(r.Xadd))
482 out.Write64(uint64(sectoff + 4))
483 out.Write64(uint64(elf.R_AARCH64_LD64_GOT_LO12_NC) | uint64(elfsym)<<32)
484 case objabi.R_CALLARM64:
485 if siz != 4 {
486 return false
487 }
488 out.Write64(uint64(elf.R_AARCH64_CALL26) | uint64(elfsym)<<32)
489
490 }
491 out.Write64(uint64(r.Xadd))
492
493 return true
494 }
495
496
497 func signext21(x int64) int64 { return x << (64 - 21) >> (64 - 21) }
498 func signext24(x int64) int64 { return x << (64 - 24) >> (64 - 24) }
499
500 func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, sectoff int64) bool {
501 var v uint32
502
503 rs := r.Xsym
504 rt := r.Type
505 siz := r.Size
506 xadd := r.Xadd
507
508 if xadd != signext24(xadd) {
509
510
511 label := ldr.Lookup(offsetLabelName(ldr, rs, xadd/machoRelocLimit*machoRelocLimit), ldr.SymVersion(rs))
512 if label != 0 {
513 xadd = ldr.SymValue(rs) + xadd - ldr.SymValue(label)
514 rs = label
515 }
516 if xadd != signext24(xadd) {
517 ldr.Errorf(s, "internal error: relocation addend overflow: %s+0x%x", ldr.SymName(rs), xadd)
518 }
519 }
520
521 if ldr.SymType(rs) == sym.SHOSTOBJ || rt == objabi.R_CALLARM64 || rt == objabi.R_ADDRARM64 || rt == objabi.R_ARM64_GOTPCREL {
522 if ldr.SymDynid(rs) < 0 {
523 ldr.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs))
524 return false
525 }
526
527 v = uint32(ldr.SymDynid(rs))
528 v |= 1 << 27
529 } else {
530 v = uint32(ldr.SymSect(rs).Extnum)
531 if v == 0 {
532 ldr.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymSect(rs).Name, ldr.SymType(rs), ldr.SymType(rs))
533 return false
534 }
535 }
536
537 switch rt {
538 default:
539 return false
540 case objabi.R_ADDR:
541 v |= ld.MACHO_ARM64_RELOC_UNSIGNED << 28
542 case objabi.R_CALLARM64:
543 if xadd != 0 {
544 ldr.Errorf(s, "ld64 doesn't allow BR26 reloc with non-zero addend: %s+%d", ldr.SymName(rs), xadd)
545 }
546
547 v |= 1 << 24
548 v |= ld.MACHO_ARM64_RELOC_BRANCH26 << 28
549 case objabi.R_ADDRARM64:
550 siz = 4
551
552
553 if r.Xadd != 0 {
554 out.Write32(uint32(sectoff + 4))
555 out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(xadd&0xffffff))
556 }
557 out.Write32(uint32(sectoff + 4))
558 out.Write32(v | (ld.MACHO_ARM64_RELOC_PAGEOFF12 << 28) | (2 << 25))
559 if r.Xadd != 0 {
560 out.Write32(uint32(sectoff))
561 out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(xadd&0xffffff))
562 }
563 v |= 1 << 24
564 v |= ld.MACHO_ARM64_RELOC_PAGE21 << 28
565 case objabi.R_ARM64_GOTPCREL:
566 siz = 4
567
568
569 if r.Xadd != 0 {
570 out.Write32(uint32(sectoff + 4))
571 out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(xadd&0xffffff))
572 }
573 out.Write32(uint32(sectoff + 4))
574 out.Write32(v | (ld.MACHO_ARM64_RELOC_GOT_LOAD_PAGEOFF12 << 28) | (2 << 25))
575 if r.Xadd != 0 {
576 out.Write32(uint32(sectoff))
577 out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(xadd&0xffffff))
578 }
579 v |= 1 << 24
580 v |= ld.MACHO_ARM64_RELOC_GOT_LOAD_PAGE21 << 28
581 }
582
583 switch siz {
584 default:
585 return false
586 case 1:
587 v |= 0 << 25
588 case 2:
589 v |= 1 << 25
590 case 4:
591 v |= 2 << 25
592 case 8:
593 v |= 3 << 25
594 }
595
596 out.Write32(uint32(sectoff))
597 out.Write32(v)
598 return true
599 }
600
601 func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, sectoff int64) bool {
602 rs := r.Xsym
603 rt := r.Type
604
605 if r.Xadd != signext21(r.Xadd) {
606
607
608 label := ldr.Lookup(offsetLabelName(ldr, rs, r.Xadd/peRelocLimit*peRelocLimit), ldr.SymVersion(rs))
609 if label == 0 {
610 ldr.Errorf(s, "invalid relocation: %v %s+0x%x", rt, ldr.SymName(rs), r.Xadd)
611 return false
612 }
613 rs = label
614 }
615 if rt == objabi.R_CALLARM64 && r.Xadd != 0 {
616 label := ldr.Lookup(offsetLabelName(ldr, rs, r.Xadd), ldr.SymVersion(rs))
617 if label == 0 {
618 ldr.Errorf(s, "invalid relocation: %v %s+0x%x", rt, ldr.SymName(rs), r.Xadd)
619 return false
620 }
621 rs = label
622 }
623 symdynid := ldr.SymDynid(rs)
624 if symdynid < 0 {
625 ldr.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs))
626 return false
627 }
628
629 switch rt {
630 default:
631 return false
632
633 case objabi.R_DWARFSECREF:
634 out.Write32(uint32(sectoff))
635 out.Write32(uint32(symdynid))
636 out.Write16(ld.IMAGE_REL_ARM64_SECREL)
637
638 case objabi.R_ADDR:
639 out.Write32(uint32(sectoff))
640 out.Write32(uint32(symdynid))
641 if r.Size == 8 {
642 out.Write16(ld.IMAGE_REL_ARM64_ADDR64)
643 } else {
644 out.Write16(ld.IMAGE_REL_ARM64_ADDR32)
645 }
646
647 case objabi.R_ADDRARM64:
648
649 out.Write32(uint32(sectoff))
650 out.Write32(uint32(symdynid))
651 out.Write16(ld.IMAGE_REL_ARM64_PAGEBASE_REL21)
652
653 out.Write32(uint32(sectoff + 4))
654 out.Write32(uint32(symdynid))
655 out.Write16(ld.IMAGE_REL_ARM64_PAGEOFFSET_12A)
656
657 case objabi.R_CALLARM64:
658
659 out.Write32(uint32(sectoff))
660 out.Write32(uint32(symdynid))
661 out.Write16(ld.IMAGE_REL_ARM64_BRANCH26)
662 }
663
664 return true
665 }
666
667 func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (int64, int, bool) {
668 const noExtReloc = 0
669 const isOk = true
670
671 rs := ldr.ResolveABIAlias(r.Sym())
672
673 if target.IsExternal() {
674 nExtReloc := 0
675 switch rt := r.Type(); rt {
676 default:
677 case objabi.R_ARM64_GOTPCREL,
678 objabi.R_ADDRARM64:
679
680
681 rs, off := ld.FoldSubSymbolOffset(ldr, rs)
682 xadd := r.Add() + off
683 rst := ldr.SymType(rs)
684 if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil {
685 ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
686 }
687
688 nExtReloc = 2
689 if target.IsDarwin() && xadd != 0 {
690 nExtReloc = 4
691 }
692
693 if target.IsWindows() {
694 var o0, o1 uint32
695 if target.IsBigEndian() {
696 o0 = uint32(val >> 32)
697 o1 = uint32(val)
698 } else {
699 o0 = uint32(val)
700 o1 = uint32(val >> 32)
701 }
702
703
704
705
706
707
708
709
710
711
712 xadd := uint32(xadd)
713 o0 |= (xadd&3)<<29 | (xadd&0xffffc)<<3
714 o1 |= (xadd & 0xfff) << 10
715
716 if target.IsBigEndian() {
717 val = int64(o0)<<32 | int64(o1)
718 } else {
719 val = int64(o1)<<32 | int64(o0)
720 }
721 }
722
723 return val, nExtReloc, isOk
724 case objabi.R_CALLARM64,
725 objabi.R_ARM64_TLS_LE,
726 objabi.R_ARM64_TLS_IE:
727 nExtReloc = 1
728 if rt == objabi.R_ARM64_TLS_IE {
729 nExtReloc = 2
730 }
731 return val, nExtReloc, isOk
732
733 case objabi.R_ADDR:
734 if target.IsWindows() && r.Add() != 0 {
735 if r.Siz() == 8 {
736 val = r.Add()
737 } else if target.IsBigEndian() {
738 val = int64(uint32(val)) | int64(r.Add())<<32
739 } else {
740 val = val>>32<<32 | int64(uint32(r.Add()))
741 }
742 return val, 1, true
743 }
744 }
745 }
746
747 switch r.Type() {
748 case objabi.R_ADDRARM64:
749 t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
750 if t >= 1<<32 || t < -1<<32 {
751 ldr.Errorf(s, "program too large, address relocation distance = %d", t)
752 }
753
754 var o0, o1 uint32
755
756 if target.IsBigEndian() {
757 o0 = uint32(val >> 32)
758 o1 = uint32(val)
759 } else {
760 o0 = uint32(val)
761 o1 = uint32(val >> 32)
762 }
763
764 o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
765 o1 |= uint32(t&0xfff) << 10
766
767
768 if target.IsBigEndian() {
769 return int64(o0)<<32 | int64(o1), noExtReloc, true
770 }
771 return int64(o1)<<32 | int64(o0), noExtReloc, true
772
773 case objabi.R_ARM64_TLS_LE:
774 if target.IsDarwin() {
775 ldr.Errorf(s, "TLS reloc on unsupported OS %v", target.HeadType)
776 }
777
778
779 v := ldr.SymValue(rs) + int64(2*target.Arch.PtrSize)
780 if v < 0 || v >= 32678 {
781 ldr.Errorf(s, "TLS offset out of range %d", v)
782 }
783 return val | (v << 5), noExtReloc, true
784
785 case objabi.R_ARM64_TLS_IE:
786 if target.IsPIE() && target.IsElf() {
787
788
789
790 if !target.IsLinux() {
791 ldr.Errorf(s, "TLS reloc on unsupported OS %v", target.HeadType)
792 }
793
794
795
796 v := ldr.SymAddr(rs) + int64(2*target.Arch.PtrSize) + r.Add()
797 if v < 0 || v >= 32678 {
798 ldr.Errorf(s, "TLS offset out of range %d", v)
799 }
800
801 var o0, o1 uint32
802 if target.IsBigEndian() {
803 o0 = uint32(val >> 32)
804 o1 = uint32(val)
805 } else {
806 o0 = uint32(val)
807 o1 = uint32(val >> 32)
808 }
809
810
811
812 o0 = 0xd2a00000 | uint32(o0&0x1f) | (uint32((v>>16)&0xffff) << 5)
813
814
815 if v&3 != 0 {
816 ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC", v)
817 }
818 o1 = 0xf2800000 | uint32(o1&0x1f) | (uint32(v&0xffff) << 5)
819
820
821 if target.IsBigEndian() {
822 return int64(o0)<<32 | int64(o1), noExtReloc, isOk
823 }
824 return int64(o1)<<32 | int64(o0), noExtReloc, isOk
825 } else {
826 log.Fatalf("cannot handle R_ARM64_TLS_IE (sym %s) when linking internally", ldr.SymName(s))
827 }
828
829 case objabi.R_CALLARM64:
830 var t int64
831 if ldr.SymType(rs) == sym.SDYNIMPORT {
832 t = (ldr.SymAddr(syms.PLT) + r.Add()) - (ldr.SymValue(s) + int64(r.Off()))
833 } else {
834 t = (ldr.SymAddr(rs) + r.Add()) - (ldr.SymValue(s) + int64(r.Off()))
835 }
836 if t >= 1<<27 || t < -1<<27 {
837 ldr.Errorf(s, "program too large, call relocation distance = %d", t)
838 }
839 return val | ((t >> 2) & 0x03ffffff), noExtReloc, true
840
841 case objabi.R_ARM64_GOT:
842 if (val>>24)&0x9f == 0x90 {
843
844
845 t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
846 if t >= 1<<32 || t < -1<<32 {
847 ldr.Errorf(s, "program too large, address relocation distance = %d", t)
848 }
849 var o0 uint32
850 o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
851 return val | int64(o0), noExtReloc, isOk
852 } else if val>>24 == 0xf9 {
853
854
855 t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
856 if t&7 != 0 {
857 ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LD64_GOT_LO12_NC", t)
858 }
859 var o1 uint32
860 o1 |= uint32(t&0xfff) << (10 - 3)
861 return val | int64(uint64(o1)), noExtReloc, isOk
862 } else {
863 ldr.Errorf(s, "unsupported instruction for %x R_GOTARM64", val)
864 }
865
866 case objabi.R_ARM64_PCREL:
867 if (val>>24)&0x9f == 0x90 {
868
869
870 t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
871 if t >= 1<<32 || t < -1<<32 {
872 ldr.Errorf(s, "program too large, address relocation distance = %d", t)
873 }
874 o0 := (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
875 return val | int64(o0), noExtReloc, isOk
876 } else if (val>>24)&0x9f == 0x91 {
877
878
879 t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
880 o1 := uint32(t&0xfff) << 10
881 return val | int64(o1), noExtReloc, isOk
882 } else if (val>>24)&0x3b == 0x39 {
883
884
885
886 shift := uint32(val) >> 30
887 if shift == 0 && (val>>20)&0x048 == 0x048 {
888 shift = 4
889 }
890 t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
891 if t&(1<<shift-1) != 0 {
892 ldr.Errorf(s, "invalid address: %x for relocation type: ARM64_RELOC_PAGEOFF12", t)
893 }
894 o1 := (uint32(t&0xfff) >> shift) << 10
895 return val | int64(o1), noExtReloc, isOk
896 } else {
897 ldr.Errorf(s, "unsupported instruction for %x R_ARM64_PCREL", val)
898 }
899
900 case objabi.R_ARM64_LDST8:
901 t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
902 o0 := uint32(t&0xfff) << 10
903 return val | int64(o0), noExtReloc, true
904
905 case objabi.R_ARM64_LDST16:
906 t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
907 if t&1 != 0 {
908 ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST16_ABS_LO12_NC", t)
909 }
910 o0 := (uint32(t&0xfff) >> 1) << 10
911 return val | int64(o0), noExtReloc, true
912
913 case objabi.R_ARM64_LDST32:
914 t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
915 if t&3 != 0 {
916 ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST32_ABS_LO12_NC", t)
917 }
918 o0 := (uint32(t&0xfff) >> 2) << 10
919 return val | int64(o0), noExtReloc, true
920
921 case objabi.R_ARM64_LDST64:
922 t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
923 if t&7 != 0 {
924 ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST64_ABS_LO12_NC", t)
925 }
926 o0 := (uint32(t&0xfff) >> 3) << 10
927 return val | int64(o0), noExtReloc, true
928
929 case objabi.R_ARM64_LDST128:
930 t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff)
931 if t&15 != 0 {
932 ldr.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST128_ABS_LO12_NC", t)
933 }
934 o0 := (uint32(t&0xfff) >> 4) << 10
935 return val | int64(o0), noExtReloc, true
936 }
937
938 return val, 0, false
939 }
940
941 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
942 log.Fatalf("unexpected relocation variant")
943 return -1
944 }
945
946 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
947 switch rt := r.Type(); rt {
948 case objabi.R_ARM64_GOTPCREL,
949 objabi.R_ADDRARM64:
950 rr := ld.ExtrelocViaOuterSym(ldr, r, s)
951
952
953
954
955
956
957 if false && target.IsDarwin() {
958
959
960
961
962
963 rr.Xadd = 0
964 }
965 return rr, true
966 case objabi.R_CALLARM64,
967 objabi.R_ARM64_TLS_LE,
968 objabi.R_ARM64_TLS_IE:
969 return ld.ExtrelocSimple(ldr, r), true
970 }
971 return loader.ExtReloc{}, false
972 }
973
974 func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
975 if plt.Size() == 0 {
976
977
978 plt.AddUint32(ctxt.Arch, 0xa9bf7bf0)
979
980
981
982 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 16, objabi.R_ARM64_GOT, 4)
983 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x90000010)
984
985
986
987 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 16, objabi.R_ARM64_GOT, 4)
988 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0xf9400211)
989
990
991 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 16, objabi.R_ARM64_PCREL, 4)
992 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x91000210)
993
994
995 plt.AddUint32(ctxt.Arch, 0xd61f0220)
996
997
998 plt.AddUint32(ctxt.Arch, 0xd503201f)
999 plt.AddUint32(ctxt.Arch, 0xd503201f)
1000 plt.AddUint32(ctxt.Arch, 0xd503201f)
1001
1002
1003 if gotplt.Size() != 0 {
1004 ctxt.Errorf(gotplt.Sym(), "got.plt is not empty at the very beginning")
1005 }
1006 gotplt.AddAddrPlus(ctxt.Arch, dynamic, 0)
1007
1008 gotplt.AddUint64(ctxt.Arch, 0)
1009 gotplt.AddUint64(ctxt.Arch, 0)
1010 }
1011 }
1012
1013 func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
1014 if ldr.SymPlt(s) >= 0 {
1015 return
1016 }
1017
1018 ld.Adddynsym(ldr, target, syms, s)
1019
1020 if target.IsElf() {
1021 plt := ldr.MakeSymbolUpdater(syms.PLT)
1022 gotplt := ldr.MakeSymbolUpdater(syms.GOTPLT)
1023 rela := ldr.MakeSymbolUpdater(syms.RelaPLT)
1024 if plt.Size() == 0 {
1025 panic("plt is not set up")
1026 }
1027
1028
1029 plt.AddAddrPlus4(target.Arch, gotplt.Sym(), gotplt.Size())
1030 plt.SetUint32(target.Arch, plt.Size()-4, 0x90000010)
1031 relocs := plt.Relocs()
1032 plt.SetRelocType(relocs.Count()-1, objabi.R_ARM64_GOT)
1033
1034
1035
1036 plt.AddAddrPlus4(target.Arch, gotplt.Sym(), gotplt.Size())
1037 plt.SetUint32(target.Arch, plt.Size()-4, 0xf9400211)
1038 relocs = plt.Relocs()
1039 plt.SetRelocType(relocs.Count()-1, objabi.R_ARM64_GOT)
1040
1041
1042 plt.AddAddrPlus4(target.Arch, gotplt.Sym(), gotplt.Size())
1043 plt.SetUint32(target.Arch, plt.Size()-4, 0x91000210)
1044 relocs = plt.Relocs()
1045 plt.SetRelocType(relocs.Count()-1, objabi.R_ARM64_PCREL)
1046
1047
1048 plt.AddUint32(target.Arch, 0xd61f0220)
1049
1050
1051 gotplt.AddAddrPlus(target.Arch, plt.Sym(), 0)
1052
1053
1054 rela.AddAddrPlus(target.Arch, gotplt.Sym(), gotplt.Size()-8)
1055 sDynid := ldr.SymDynid(s)
1056
1057 rela.AddUint64(target.Arch, elf.R_INFO(uint32(sDynid), uint32(elf.R_AARCH64_JUMP_SLOT)))
1058 rela.AddUint64(target.Arch, 0)
1059
1060 ldr.SetPlt(s, int32(plt.Size()-16))
1061 } else if target.IsDarwin() {
1062 ld.AddGotSym(target, ldr, syms, s, 0)
1063
1064 sDynid := ldr.SymDynid(s)
1065 lep := ldr.MakeSymbolUpdater(syms.LinkEditPLT)
1066 lep.AddUint32(target.Arch, uint32(sDynid))
1067
1068 plt := ldr.MakeSymbolUpdater(syms.PLT)
1069 ldr.SetPlt(s, int32(plt.Size()))
1070
1071
1072 plt.AddUint32(target.Arch, 0x90000010)
1073 r, _ := plt.AddRel(objabi.R_ARM64_GOT)
1074 r.SetOff(int32(plt.Size() - 4))
1075 r.SetSiz(4)
1076 r.SetSym(syms.GOT)
1077 r.SetAdd(int64(ldr.SymGot(s)))
1078
1079
1080 plt.AddUint32(target.Arch, 0xf9400211)
1081 r, _ = plt.AddRel(objabi.R_ARM64_GOT)
1082 r.SetOff(int32(plt.Size() - 4))
1083 r.SetSiz(4)
1084 r.SetSym(syms.GOT)
1085 r.SetAdd(int64(ldr.SymGot(s)))
1086
1087
1088 plt.AddUint32(target.Arch, 0xd61f0220)
1089 } else {
1090 ldr.Errorf(s, "addpltsym: unsupported binary format")
1091 }
1092 }
1093
1094 const (
1095 machoRelocLimit = 1 << 23
1096 peRelocLimit = 1 << 20
1097 )
1098
1099 func gensymlate(ctxt *ld.Link, ldr *loader.Loader) {
1100
1101
1102
1103
1104 if !ctxt.IsDarwin() && !ctxt.IsWindows() || !ctxt.IsExternal() {
1105 return
1106 }
1107
1108 limit := int64(machoRelocLimit)
1109 if ctxt.IsWindows() {
1110 limit = peRelocLimit
1111 }
1112
1113 if ctxt.IsDarwin() {
1114 big := false
1115 for _, seg := range ld.Segments {
1116 if seg.Length >= machoRelocLimit {
1117 big = true
1118 break
1119 }
1120 }
1121 if !big {
1122 return
1123 }
1124 }
1125
1126
1127 addLabelSyms := func(s loader.Sym, limit, sz int64) {
1128 v := ldr.SymValue(s)
1129 for off := limit; off < sz; off += limit {
1130 p := ldr.LookupOrCreateSym(offsetLabelName(ldr, s, off), ldr.SymVersion(s))
1131 ldr.SetAttrReachable(p, true)
1132 ldr.SetSymValue(p, v+off)
1133 ldr.SetSymSect(p, ldr.SymSect(s))
1134 if ctxt.IsDarwin() {
1135 ld.AddMachoSym(ldr, p)
1136 } else if ctxt.IsWindows() {
1137 ld.AddPELabelSym(ldr, p)
1138 } else {
1139 panic("missing case in gensymlate")
1140 }
1141
1142 }
1143 }
1144
1145 for s, n := loader.Sym(1), loader.Sym(ldr.NSym()); s < n; s++ {
1146 if !ldr.AttrReachable(s) {
1147 continue
1148 }
1149 if ldr.SymType(s) == sym.STEXT {
1150 if ctxt.IsDarwin() || ctxt.IsWindows() {
1151
1152
1153 switch ldr.SymName(s) {
1154 case "runtime.duffcopy":
1155 addLabelSyms(s, 8, 8*64)
1156 case "runtime.duffzero":
1157 addLabelSyms(s, 4, 4*64)
1158 }
1159 }
1160 continue
1161 }
1162 sz := ldr.SymSize(s)
1163 if sz <= limit {
1164 continue
1165 }
1166 addLabelSyms(s, limit, sz)
1167 }
1168
1169
1170 for _, ss := range ld.CarrierSymByType {
1171 if ss.Sym != 0 && ss.Size > limit {
1172 addLabelSyms(ss.Sym, limit, ss.Size)
1173 }
1174 }
1175 }
1176
1177
1178
1179
1180 func offsetLabelName(ldr *loader.Loader, s loader.Sym, off int64) string {
1181 if off>>20<<20 == off {
1182 return fmt.Sprintf("%s+%dMB", ldr.SymExtname(s), off>>20)
1183 }
1184 return fmt.Sprintf("%s+%d", ldr.SymExtname(s), off)
1185 }
1186
1187
1188 func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
1189 relocs := ldr.Relocs(s)
1190 r := relocs.At(ri)
1191 const pcrel = 1
1192 switch r.Type() {
1193 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_CALL26),
1194 objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_JUMP26),
1195 objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_BRANCH26*2 + pcrel:
1196
1197
1198 fallthrough
1199 case objabi.R_CALLARM64:
1200 var t int64
1201
1202
1203
1204 if ldr.SymValue(rs) != 0 {
1205 t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
1206 }
1207 if t >= 1<<27 || t < -1<<27 || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && (ldr.SymPkg(s) == "" || ldr.SymPkg(s) != ldr.SymPkg(rs))) {
1208
1209
1210
1211 var tramp loader.Sym
1212 for i := 0; ; i++ {
1213 oName := ldr.SymName(rs)
1214 name := oName + fmt.Sprintf("%+x-tramp%d", r.Add(), i)
1215 tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs)))
1216 ldr.SetAttrReachable(tramp, true)
1217 if ldr.SymType(tramp) == sym.SDYNIMPORT {
1218
1219 continue
1220 }
1221 if oName == "runtime.deferreturn" {
1222 ldr.SetIsDeferReturnTramp(tramp, true)
1223 }
1224 if ldr.SymValue(tramp) == 0 {
1225
1226
1227
1228 break
1229 }
1230
1231 t = ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off()))
1232 if t >= -1<<27 && t < 1<<27 {
1233
1234
1235 break
1236 }
1237 }
1238 if ldr.SymType(tramp) == 0 {
1239
1240 trampb := ldr.MakeSymbolUpdater(tramp)
1241 ctxt.AddTramp(trampb)
1242 if ldr.SymType(rs) == sym.SDYNIMPORT {
1243 if r.Add() != 0 {
1244 ctxt.Errorf(s, "nonzero addend for DYNIMPORT call: %v+%d", ldr.SymName(rs), r.Add())
1245 }
1246 gentrampgot(ctxt, ldr, trampb, rs)
1247 } else {
1248 gentramp(ctxt, ldr, trampb, rs, r.Add())
1249 }
1250 }
1251
1252 sb := ldr.MakeSymbolUpdater(s)
1253 relocs := sb.Relocs()
1254 r := relocs.At(ri)
1255 r.SetSym(tramp)
1256 r.SetAdd(0)
1257 }
1258 default:
1259 ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
1260 }
1261 }
1262
1263
1264 func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
1265 tramp.SetSize(12)
1266 P := make([]byte, tramp.Size())
1267 o1 := uint32(0x90000010)
1268 o2 := uint32(0x91000210)
1269 o3 := uint32(0xd61f0200)
1270 ctxt.Arch.ByteOrder.PutUint32(P, o1)
1271 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
1272 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
1273 tramp.SetData(P)
1274
1275 r, _ := tramp.AddRel(objabi.R_ADDRARM64)
1276 r.SetSiz(8)
1277 r.SetSym(target)
1278 r.SetAdd(offset)
1279 }
1280
1281
1282 func gentrampgot(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym) {
1283 tramp.SetSize(12)
1284 P := make([]byte, tramp.Size())
1285 o1 := uint32(0x90000010)
1286 o2 := uint32(0xf9400210)
1287 o3 := uint32(0xd61f0200)
1288 ctxt.Arch.ByteOrder.PutUint32(P, o1)
1289 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
1290 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
1291 tramp.SetData(P)
1292
1293 r, _ := tramp.AddRel(objabi.R_ARM64_GOTPCREL)
1294 r.SetSiz(8)
1295 r.SetSym(target)
1296 }
1297
View as plain text