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