Source file src/pkg/cmd/link/internal/arm64/asm.go
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/sym"
38 "debug/elf"
39 "encoding/binary"
40 "fmt"
41 "log"
42 )
43
44 func gentext(ctxt *ld.Link) {
45 if !ctxt.DynlinkingGo() {
46 return
47 }
48 addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
49 if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
50
51
52 return
53 }
54 addmoduledata.Attr |= sym.AttrReachable
55 initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
56 initfunc.Type = sym.STEXT
57 initfunc.Attr |= sym.AttrLocal
58 initfunc.Attr |= sym.AttrReachable
59 o := func(op uint32) {
60 initfunc.AddUint32(ctxt.Arch, op)
61 }
62
63
64
65
66
67 o(0x90000000)
68 o(0x91000000)
69 rel := initfunc.AddRel()
70 rel.Off = 0
71 rel.Siz = 8
72 rel.Sym = ctxt.Moduledata
73 rel.Type = objabi.R_ADDRARM64
74
75
76
77 o(0x14000000)
78 rel = initfunc.AddRel()
79 rel.Off = 8
80 rel.Siz = 4
81 rel.Sym = ctxt.Syms.Lookup("runtime.addmoduledata", 0)
82 rel.Type = objabi.R_CALLARM64
83
84 if ctxt.BuildMode == ld.BuildModePlugin {
85 ctxt.Textp = append(ctxt.Textp, addmoduledata)
86 }
87 ctxt.Textp = append(ctxt.Textp, initfunc)
88 initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
89 initarray_entry.Attr |= sym.AttrReachable
90 initarray_entry.Attr |= sym.AttrLocal
91 initarray_entry.Type = sym.SINITARR
92 initarray_entry.AddAddr(ctxt.Arch, initfunc)
93 }
94
95 func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
96 targ := r.Sym
97
98 switch r.Type {
99 default:
100 if r.Type >= objabi.ElfRelocOffset {
101 ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
102 return false
103 }
104
105
106 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_PREL32):
107 if targ.Type == sym.SDYNIMPORT {
108 ld.Errorf(s, "unexpected R_AARCH64_PREL32 relocation for dynamic symbol %s", targ.Name)
109 }
110
111
112 if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
113 ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
114 }
115 r.Type = objabi.R_PCREL
116 r.Add += 4
117 return true
118
119 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_PREL64):
120 if targ.Type == sym.SDYNIMPORT {
121 ld.Errorf(s, "unexpected R_AARCH64_PREL64 relocation for dynamic symbol %s", targ.Name)
122 }
123 if targ.Type == 0 || targ.Type == sym.SXREF {
124 ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
125 }
126 r.Type = objabi.R_PCREL
127 r.Add += 8
128 return true
129
130 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_CALL26),
131 objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_JUMP26):
132 if targ.Type == sym.SDYNIMPORT {
133 addpltsym(ctxt, targ)
134 r.Sym = ctxt.Syms.Lookup(".plt", 0)
135 r.Add += int64(targ.Plt())
136 }
137 if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
138 ld.Errorf(s, "unknown symbol %s in callarm64", targ.Name)
139 }
140 r.Type = objabi.R_CALLARM64
141 return true
142
143 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADR_GOT_PAGE),
144 objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LD64_GOT_LO12_NC):
145 if targ.Type != sym.SDYNIMPORT {
146
147
148 }
149
150
151
152 addgotsym(ctxt, targ)
153
154 r.Type = objabi.R_ARM64_GOT
155 r.Sym = ctxt.Syms.Lookup(".got", 0)
156 r.Add += int64(targ.Got())
157 return true
158
159 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADR_PREL_PG_HI21),
160 objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ADD_ABS_LO12_NC):
161 if targ.Type == sym.SDYNIMPORT {
162 ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
163 }
164 if targ.Type == 0 || targ.Type == sym.SXREF {
165 ld.Errorf(s, "unknown symbol %s", targ.Name)
166 }
167 r.Type = objabi.R_ARM64_PCREL
168 return true
169
170 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_ABS64):
171 if targ.Type == sym.SDYNIMPORT {
172 ld.Errorf(s, "unexpected R_AARCH64_ABS64 relocation for dynamic symbol %s", targ.Name)
173 }
174 r.Type = objabi.R_ADDR
175 return true
176
177 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST8_ABS_LO12_NC):
178 if targ.Type == sym.SDYNIMPORT {
179 ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
180 }
181 r.Type = objabi.R_ARM64_LDST8
182 return true
183
184 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST32_ABS_LO12_NC):
185 if targ.Type == sym.SDYNIMPORT {
186 ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
187 }
188 r.Type = objabi.R_ARM64_LDST32
189 return true
190
191 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST64_ABS_LO12_NC):
192 if targ.Type == sym.SDYNIMPORT {
193 ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
194 }
195 r.Type = objabi.R_ARM64_LDST64
196 return true
197
198 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_AARCH64_LDST128_ABS_LO12_NC):
199 if targ.Type == sym.SDYNIMPORT {
200 ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
201 }
202 r.Type = objabi.R_ARM64_LDST128
203 return true
204 }
205
206 switch r.Type {
207 case objabi.R_CALL,
208 objabi.R_PCREL,
209 objabi.R_CALLARM64:
210 if targ.Type != sym.SDYNIMPORT {
211
212 return true
213 }
214 if ctxt.LinkMode == ld.LinkExternal {
215
216 return true
217 }
218
219 case objabi.R_ADDR:
220 if s.Type == sym.STEXT && ctxt.IsELF {
221
222
223
224 addgotsym(ctxt, targ)
225
226 r.Sym = ctxt.Syms.Lookup(".got", 0)
227 r.Add += int64(targ.Got())
228 return true
229 }
230
231
232 if ctxt.BuildMode == ld.BuildModePIE && ctxt.LinkMode == ld.LinkInternal {
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264 switch s.Name {
265 case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
266 return false
267 }
268 } else {
269
270
271
272
273
274
275 if s.Type != sym.SDATA && s.Type != sym.SRODATA {
276 break
277 }
278 }
279
280 if ctxt.IsELF {
281
282
283
284 ld.Adddynsym(ctxt, targ)
285 rela := ctxt.Syms.Lookup(".rela", 0)
286 rela.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
287 if r.Siz == 8 {
288 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(targ.Dynid), uint32(elf.R_AARCH64_ABS64)))
289 } else {
290 ld.Errorf(s, "unexpected relocation for dynamic symbol %s", targ.Name)
291 }
292 rela.AddUint64(ctxt.Arch, uint64(r.Add))
293 r.Type = objabi.ElfRelocOffset
294 return true
295 }
296 }
297 return false
298 }
299
300 func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
301 ctxt.Out.Write64(uint64(sectoff))
302
303 elfsym := r.Xsym.ElfsymForReloc()
304 switch r.Type {
305 default:
306 return false
307 case objabi.R_ADDR:
308 switch r.Siz {
309 case 4:
310 ctxt.Out.Write64(uint64(elf.R_AARCH64_ABS32) | uint64(elfsym)<<32)
311 case 8:
312 ctxt.Out.Write64(uint64(elf.R_AARCH64_ABS64) | uint64(elfsym)<<32)
313 default:
314 return false
315 }
316 case objabi.R_ADDRARM64:
317
318 ctxt.Out.Write64(uint64(elf.R_AARCH64_ADR_PREL_PG_HI21) | uint64(elfsym)<<32)
319 ctxt.Out.Write64(uint64(r.Xadd))
320 ctxt.Out.Write64(uint64(sectoff + 4))
321 ctxt.Out.Write64(uint64(elf.R_AARCH64_ADD_ABS_LO12_NC) | uint64(elfsym)<<32)
322 case objabi.R_ARM64_TLS_LE:
323 ctxt.Out.Write64(uint64(elf.R_AARCH64_TLSLE_MOVW_TPREL_G0) | uint64(elfsym)<<32)
324 case objabi.R_ARM64_TLS_IE:
325 ctxt.Out.Write64(uint64(elf.R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) | uint64(elfsym)<<32)
326 ctxt.Out.Write64(uint64(r.Xadd))
327 ctxt.Out.Write64(uint64(sectoff + 4))
328 ctxt.Out.Write64(uint64(elf.R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) | uint64(elfsym)<<32)
329 case objabi.R_ARM64_GOTPCREL:
330 ctxt.Out.Write64(uint64(elf.R_AARCH64_ADR_GOT_PAGE) | uint64(elfsym)<<32)
331 ctxt.Out.Write64(uint64(r.Xadd))
332 ctxt.Out.Write64(uint64(sectoff + 4))
333 ctxt.Out.Write64(uint64(elf.R_AARCH64_LD64_GOT_LO12_NC) | uint64(elfsym)<<32)
334 case objabi.R_CALLARM64:
335 if r.Siz != 4 {
336 return false
337 }
338 ctxt.Out.Write64(uint64(elf.R_AARCH64_CALL26) | uint64(elfsym)<<32)
339
340 }
341 ctxt.Out.Write64(uint64(r.Xadd))
342
343 return true
344 }
345
346 func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
347 var v uint32
348
349 rs := r.Xsym
350
351 if rs.Type == sym.SHOSTOBJ || r.Type == objabi.R_CALLARM64 || r.Type == objabi.R_ADDRARM64 {
352 if rs.Dynid < 0 {
353 ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
354 return false
355 }
356
357 v = uint32(rs.Dynid)
358 v |= 1 << 27
359 } else {
360 v = uint32(rs.Sect.Extnum)
361 if v == 0 {
362 ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type)
363 return false
364 }
365 }
366
367 switch r.Type {
368 default:
369 return false
370 case objabi.R_ADDR:
371 v |= ld.MACHO_ARM64_RELOC_UNSIGNED << 28
372 case objabi.R_CALLARM64:
373 if r.Xadd != 0 {
374 ld.Errorf(s, "ld64 doesn't allow BR26 reloc with non-zero addend: %s+%d", rs.Name, r.Xadd)
375 }
376
377 v |= 1 << 24
378 v |= ld.MACHO_ARM64_RELOC_BRANCH26 << 28
379 case objabi.R_ADDRARM64:
380 r.Siz = 4
381
382
383 if r.Xadd != 0 {
384 out.Write32(uint32(sectoff + 4))
385 out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(r.Xadd&0xffffff))
386 }
387 out.Write32(uint32(sectoff + 4))
388 out.Write32(v | (ld.MACHO_ARM64_RELOC_PAGEOFF12 << 28) | (2 << 25))
389 if r.Xadd != 0 {
390 out.Write32(uint32(sectoff))
391 out.Write32((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(r.Xadd&0xffffff))
392 }
393 v |= 1 << 24
394 v |= ld.MACHO_ARM64_RELOC_PAGE21 << 28
395 }
396
397 switch r.Siz {
398 default:
399 return false
400 case 1:
401 v |= 0 << 25
402 case 2:
403 v |= 1 << 25
404 case 4:
405 v |= 2 << 25
406 case 8:
407 v |= 3 << 25
408 }
409
410 out.Write32(uint32(sectoff))
411 out.Write32(v)
412 return true
413 }
414
415 func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
416 if ctxt.LinkMode == ld.LinkExternal {
417 switch r.Type {
418 default:
419 return val, false
420 case objabi.R_ARM64_GOTPCREL:
421 var o1, o2 uint32
422 if ctxt.Arch.ByteOrder == binary.BigEndian {
423 o1 = uint32(val >> 32)
424 o2 = uint32(val)
425 } else {
426 o1 = uint32(val)
427 o2 = uint32(val >> 32)
428 }
429
430
431
432
433
434
435
436
437 if !(r.Sym.IsFileLocal() || r.Sym.Attr.VisibilityHidden() || r.Sym.Attr.Local()) && r.Sym.Type == sym.STEXT && ctxt.DynlinkingGo() {
438 if o2&0xffc00000 != 0xf9400000 {
439 ld.Errorf(s, "R_ARM64_GOTPCREL against unexpected instruction %x", o2)
440 }
441 o2 = 0x91000000 | (o2 & 0x000003ff)
442 r.Type = objabi.R_ADDRARM64
443 }
444 if ctxt.Arch.ByteOrder == binary.BigEndian {
445 val = int64(o1)<<32 | int64(o2)
446 } else {
447 val = int64(o2)<<32 | int64(o1)
448 }
449 fallthrough
450 case objabi.R_ADDRARM64:
451 r.Done = false
452
453
454 rs := r.Sym
455 r.Xadd = r.Add
456 for rs.Outer != nil {
457 r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
458 rs = rs.Outer
459 }
460
461 if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
462 ld.Errorf(s, "missing section for %s", rs.Name)
463 }
464 r.Xsym = rs
465
466
467
468
469
470
471 if false && ctxt.HeadType == objabi.Hdarwin {
472 var o0, o1 uint32
473
474 if ctxt.Arch.ByteOrder == binary.BigEndian {
475 o0 = uint32(val >> 32)
476 o1 = uint32(val)
477 } else {
478 o0 = uint32(val)
479 o1 = uint32(val >> 32)
480 }
481
482
483
484
485
486 o0 |= (uint32((r.Xadd>>12)&3) << 29) | (uint32((r.Xadd>>12>>2)&0x7ffff) << 5)
487 o1 |= uint32(r.Xadd&0xfff) << 10
488 r.Xadd = 0
489
490
491 if ctxt.Arch.ByteOrder == binary.BigEndian {
492 val = int64(o0)<<32 | int64(o1)
493 } else {
494 val = int64(o1)<<32 | int64(o0)
495 }
496 }
497
498 return val, true
499 case objabi.R_CALLARM64,
500 objabi.R_ARM64_TLS_LE,
501 objabi.R_ARM64_TLS_IE:
502 r.Done = false
503 r.Xsym = r.Sym
504 r.Xadd = r.Add
505 return val, true
506 }
507 }
508
509 switch r.Type {
510 case objabi.R_CONST:
511 return r.Add, true
512
513 case objabi.R_GOTOFF:
514 return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
515
516 case objabi.R_ADDRARM64:
517 t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
518 if t >= 1<<32 || t < -1<<32 {
519 ld.Errorf(s, "program too large, address relocation distance = %d", t)
520 }
521
522 var o0, o1 uint32
523
524 if ctxt.Arch.ByteOrder == binary.BigEndian {
525 o0 = uint32(val >> 32)
526 o1 = uint32(val)
527 } else {
528 o0 = uint32(val)
529 o1 = uint32(val >> 32)
530 }
531
532 o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
533 o1 |= uint32(t&0xfff) << 10
534
535
536 if ctxt.Arch.ByteOrder == binary.BigEndian {
537 return int64(o0)<<32 | int64(o1), true
538 }
539 return int64(o1)<<32 | int64(o0), true
540
541 case objabi.R_ARM64_TLS_LE:
542 r.Done = false
543 if ctxt.HeadType == objabi.Hdarwin {
544 ld.Errorf(s, "TLS reloc on unsupported OS %v", ctxt.HeadType)
545 }
546
547
548 v := r.Sym.Value + int64(2*ctxt.Arch.PtrSize)
549 if v < 0 || v >= 32678 {
550 ld.Errorf(s, "TLS offset out of range %d", v)
551 }
552 return val | (v << 5), true
553
554 case objabi.R_ARM64_TLS_IE:
555 if ctxt.BuildMode == ld.BuildModePIE && ctxt.IsELF {
556
557
558 r.Done = false
559 if ctxt.HeadType != objabi.Hlinux {
560 ld.Errorf(s, "TLS reloc on unsupported OS %v", ctxt.HeadType)
561 }
562
563
564
565 v := ld.Symaddr(r.Sym) + int64(2*ctxt.Arch.PtrSize) + r.Add
566 if v < 0 || v >= 32678 {
567 ld.Errorf(s, "TLS offset out of range %d", v)
568 }
569
570 var o0, o1 uint32
571 if ctxt.Arch.ByteOrder == binary.BigEndian {
572 o0 = uint32(val >> 32)
573 o1 = uint32(val)
574 } else {
575 o0 = uint32(val)
576 o1 = uint32(val >> 32)
577 }
578
579
580
581 o0 = 0xd2a00000 | uint32(o0&0x1f) | (uint32((v>>16)&0xffff) << 5)
582
583
584 if v&3 != 0 {
585 ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC", v)
586 }
587 o1 = 0xf2800000 | uint32(o1&0x1f) | (uint32(v&0xffff) << 5)
588
589
590 if ctxt.Arch.ByteOrder == binary.BigEndian {
591 return int64(o0)<<32 | int64(o1), true
592 }
593 return int64(o1)<<32 | int64(o0), true
594 } else {
595 log.Fatalf("cannot handle R_ARM64_TLS_IE (sym %s) when linking internally", s.Name)
596 }
597
598 case objabi.R_CALLARM64:
599 var t int64
600 if r.Sym.Type == sym.SDYNIMPORT {
601 t = (ld.Symaddr(ctxt.Syms.Lookup(".plt", 0)) + r.Add) - (s.Value + int64(r.Off))
602 } else {
603 t = (ld.Symaddr(r.Sym) + r.Add) - (s.Value + int64(r.Off))
604 }
605 if t >= 1<<27 || t < -1<<27 {
606 ld.Errorf(s, "program too large, call relocation distance = %d", t)
607 }
608 return val | ((t >> 2) & 0x03ffffff), true
609
610 case objabi.R_ARM64_GOT:
611 if s.P[r.Off+3]&0x9f == 0x90 {
612
613
614 t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
615 if t >= 1<<32 || t < -1<<32 {
616 ld.Errorf(s, "program too large, address relocation distance = %d", t)
617 }
618 var o0 uint32
619 o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
620 return val | int64(o0), true
621 } else if s.P[r.Off+3] == 0xf9 {
622
623
624 t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
625 if t&7 != 0 {
626 ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LD64_GOT_LO12_NC", t)
627 }
628 var o1 uint32
629 o1 |= uint32(t&0xfff) << (10 - 3)
630 return val | int64(uint64(o1)), true
631 } else {
632 ld.Errorf(s, "unsupported instruction for %v R_GOTARM64", s.P[r.Off:r.Off+4])
633 }
634
635 case objabi.R_ARM64_PCREL:
636 if s.P[r.Off+3]&0x9f == 0x90 {
637
638
639 t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
640 if t >= 1<<32 || t < -1<<32 {
641 ld.Errorf(s, "program too large, address relocation distance = %d", t)
642 }
643 o0 := (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
644 return val | int64(o0), true
645 } else if s.P[r.Off+3]&0x91 == 0x91 {
646
647
648 t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
649 o1 := uint32(t&0xfff) << 10
650 return val | int64(o1), true
651 } else {
652 ld.Errorf(s, "unsupported instruction for %v R_PCRELARM64", s.P[r.Off:r.Off+4])
653 }
654
655 case objabi.R_ARM64_LDST8:
656 t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
657 o0 := uint32(t&0xfff) << 10
658 return val | int64(o0), true
659
660 case objabi.R_ARM64_LDST32:
661 t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
662 if t&3 != 0 {
663 ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST32_ABS_LO12_NC", t)
664 }
665 o0 := (uint32(t&0xfff) >> 2) << 10
666 return val | int64(o0), true
667
668 case objabi.R_ARM64_LDST64:
669 t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
670 if t&7 != 0 {
671 ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST64_ABS_LO12_NC", t)
672 }
673 o0 := (uint32(t&0xfff) >> 3) << 10
674 return val | int64(o0), true
675
676 case objabi.R_ARM64_LDST128:
677 t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
678 if t&15 != 0 {
679 ld.Errorf(s, "invalid address: %x for relocation type: R_AARCH64_LDST128_ABS_LO12_NC", t)
680 }
681 o0 := (uint32(t&0xfff) >> 4) << 10
682 return val | int64(o0), true
683 }
684
685 return val, false
686 }
687
688 func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
689 log.Fatalf("unexpected relocation variant")
690 return -1
691 }
692
693 func elfsetupplt(ctxt *ld.Link) {
694 plt := ctxt.Syms.Lookup(".plt", 0)
695 gotplt := ctxt.Syms.Lookup(".got.plt", 0)
696 if plt.Size == 0 {
697
698
699 plt.AddUint32(ctxt.Arch, 0xa9bf7bf0)
700
701
702
703 plt.AddAddrPlus4(gotplt, 16)
704 plt.SetUint32(ctxt.Arch, plt.Size-4, 0x90000010)
705 plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT
706
707
708
709 plt.AddAddrPlus4(gotplt, 16)
710 plt.SetUint32(ctxt.Arch, plt.Size-4, 0xf9400211)
711 plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT
712
713
714 plt.AddAddrPlus4(gotplt, 16)
715 plt.SetUint32(ctxt.Arch, plt.Size-4, 0x91000210)
716 plt.R[len(plt.R)-1].Type = objabi.R_ARM64_PCREL
717
718
719 plt.AddUint32(ctxt.Arch, 0xd61f0220)
720
721
722 plt.AddUint32(ctxt.Arch, 0xd503201f)
723 plt.AddUint32(ctxt.Arch, 0xd503201f)
724 plt.AddUint32(ctxt.Arch, 0xd503201f)
725
726
727 if gotplt.Size != 0 {
728 ld.Errorf(gotplt, "got.plt is not empty at the very beginning")
729 }
730 gotplt.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0)
731
732 gotplt.AddUint64(ctxt.Arch, 0)
733 gotplt.AddUint64(ctxt.Arch, 0)
734 }
735 }
736
737 func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
738 if s.Plt() >= 0 {
739 return
740 }
741
742 ld.Adddynsym(ctxt, s)
743
744 if ctxt.IsELF {
745 plt := ctxt.Syms.Lookup(".plt", 0)
746 gotplt := ctxt.Syms.Lookup(".got.plt", 0)
747 rela := ctxt.Syms.Lookup(".rela.plt", 0)
748 if plt.Size == 0 {
749 elfsetupplt(ctxt)
750 }
751
752
753 plt.AddAddrPlus4(gotplt, gotplt.Size)
754 plt.SetUint32(ctxt.Arch, plt.Size-4, 0x90000010)
755 plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT
756
757
758
759 plt.AddAddrPlus4(gotplt, gotplt.Size)
760 plt.SetUint32(ctxt.Arch, plt.Size-4, 0xf9400211)
761 plt.R[len(plt.R)-1].Type = objabi.R_ARM64_GOT
762
763
764 plt.AddAddrPlus4(gotplt, gotplt.Size)
765 plt.SetUint32(ctxt.Arch, plt.Size-4, 0x91000210)
766 plt.R[len(plt.R)-1].Type = objabi.R_ARM64_PCREL
767
768
769 plt.AddUint32(ctxt.Arch, 0xd61f0220)
770
771
772 gotplt.AddAddrPlus(ctxt.Arch, plt, 0)
773
774
775 rela.AddAddrPlus(ctxt.Arch, gotplt, gotplt.Size-8)
776 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_AARCH64_JUMP_SLOT)))
777 rela.AddUint64(ctxt.Arch, 0)
778
779 s.SetPlt(int32(plt.Size - 16))
780 } else {
781 ld.Errorf(s, "addpltsym: unsupported binary format")
782 }
783 }
784
785 func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
786 if s.Got() >= 0 {
787 return
788 }
789
790 ld.Adddynsym(ctxt, s)
791 got := ctxt.Syms.Lookup(".got", 0)
792 s.SetGot(int32(got.Size))
793 got.AddUint64(ctxt.Arch, 0)
794
795 if ctxt.IsELF {
796 rela := ctxt.Syms.Lookup(".rela", 0)
797 rela.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
798 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_AARCH64_GLOB_DAT)))
799 rela.AddUint64(ctxt.Arch, 0)
800 } else {
801 ld.Errorf(s, "addgotsym: unsupported binary format")
802 }
803 }
804
805 func asmb(ctxt *ld.Link) {
806 if ctxt.Debugvlog != 0 {
807 ctxt.Logf("%5.2f asmb\n", ld.Cputime())
808 }
809
810 if ctxt.IsELF {
811 ld.Asmbelfsetup()
812 }
813
814 sect := ld.Segtext.Sections[0]
815 ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
816 ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
817 for _, sect = range ld.Segtext.Sections[1:] {
818 ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
819 ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
820 }
821
822 if ld.Segrodata.Filelen > 0 {
823 if ctxt.Debugvlog != 0 {
824 ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
825 }
826 ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
827 ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
828 }
829 if ld.Segrelrodata.Filelen > 0 {
830 if ctxt.Debugvlog != 0 {
831 ctxt.Logf("%5.2f relrodatblk\n", ld.Cputime())
832 }
833 ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
834 ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
835 }
836
837 if ctxt.Debugvlog != 0 {
838 ctxt.Logf("%5.2f datblk\n", ld.Cputime())
839 }
840
841 ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
842 ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
843
844 ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
845 ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
846 }
847
848 func asmb2(ctxt *ld.Link) {
849 machlink := uint32(0)
850 if ctxt.HeadType == objabi.Hdarwin {
851 machlink = uint32(ld.Domacholink(ctxt))
852 }
853
854
855 ld.Symsize = 0
856
857 ld.Lcsize = 0
858 symo := uint32(0)
859 if !*ld.FlagS {
860
861 if ctxt.Debugvlog != 0 {
862 ctxt.Logf("%5.2f sym\n", ld.Cputime())
863 }
864 switch ctxt.HeadType {
865 default:
866 if ctxt.IsELF {
867 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
868 symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
869 }
870
871 case objabi.Hplan9:
872 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
873
874 case objabi.Hdarwin:
875 symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink))
876 }
877
878 ctxt.Out.SeekSet(int64(symo))
879 switch ctxt.HeadType {
880 default:
881 if ctxt.IsELF {
882 if ctxt.Debugvlog != 0 {
883 ctxt.Logf("%5.2f elfsym\n", ld.Cputime())
884 }
885 ld.Asmelfsym(ctxt)
886 ctxt.Out.Flush()
887 ctxt.Out.Write(ld.Elfstrdat)
888
889 if ctxt.LinkMode == ld.LinkExternal {
890 ld.Elfemitreloc(ctxt)
891 }
892 }
893
894 case objabi.Hplan9:
895 ld.Asmplan9sym(ctxt)
896 ctxt.Out.Flush()
897
898 sym := ctxt.Syms.Lookup("pclntab", 0)
899 if sym != nil {
900 ld.Lcsize = int32(len(sym.P))
901 ctxt.Out.Write(sym.P)
902 ctxt.Out.Flush()
903 }
904
905 case objabi.Hdarwin:
906 if ctxt.LinkMode == ld.LinkExternal {
907 ld.Machoemitreloc(ctxt)
908 }
909 }
910 }
911
912 if ctxt.Debugvlog != 0 {
913 ctxt.Logf("%5.2f header\n", ld.Cputime())
914 }
915 ctxt.Out.SeekSet(0)
916 switch ctxt.HeadType {
917 default:
918 case objabi.Hplan9:
919 ctxt.Out.Write32(0x647)
920 ctxt.Out.Write32(uint32(ld.Segtext.Filelen))
921 ctxt.Out.Write32(uint32(ld.Segdata.Filelen))
922 ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
923 ctxt.Out.Write32(uint32(ld.Symsize))
924 ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt)))
925 ctxt.Out.Write32(0)
926 ctxt.Out.Write32(uint32(ld.Lcsize))
927
928 case objabi.Hlinux,
929 objabi.Hfreebsd,
930 objabi.Hnetbsd,
931 objabi.Hopenbsd,
932 objabi.Hnacl:
933 ld.Asmbelf(ctxt, int64(symo))
934
935 case objabi.Hdarwin:
936 ld.Asmbmacho(ctxt)
937 }
938
939 ctxt.Out.Flush()
940 if *ld.FlagC {
941 fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
942 fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
943 fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
944 fmt.Printf("symsize=%d\n", ld.Symsize)
945 fmt.Printf("lcsize=%d\n", ld.Lcsize)
946 fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
947 }
948 }
949
View as plain text