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