Source file src/cmd/link/internal/loadmacho/ldmacho.go
1
2
3
4
5
6 package loadmacho
7
8 import (
9 "bytes"
10 "cmd/internal/bio"
11 "cmd/internal/objabi"
12 "cmd/internal/sys"
13 "cmd/link/internal/sym"
14 "encoding/binary"
15 "fmt"
16 "io"
17 "sort"
18 )
19
20
46
47
48 const (
49 MACHO_X86_64_RELOC_UNSIGNED = 0
50 MACHO_X86_64_RELOC_SIGNED = 1
51 MACHO_FAKE_GOTPCREL = 100
52 )
53
54 type ldMachoObj struct {
55 f *bio.Reader
56 base int64
57 length int64
58 is64 bool
59 name string
60 e binary.ByteOrder
61 cputype uint
62 subcputype uint
63 filetype uint32
64 flags uint32
65 cmd []ldMachoCmd
66 ncmd uint
67 }
68
69 type ldMachoCmd struct {
70 type_ int
71 off uint32
72 size uint32
73 seg ldMachoSeg
74 sym ldMachoSymtab
75 dsym ldMachoDysymtab
76 }
77
78 type ldMachoSeg struct {
79 name string
80 vmaddr uint64
81 vmsize uint64
82 fileoff uint32
83 filesz uint32
84 maxprot uint32
85 initprot uint32
86 nsect uint32
87 flags uint32
88 sect []ldMachoSect
89 }
90
91 type ldMachoSect struct {
92 name string
93 segname string
94 addr uint64
95 size uint64
96 off uint32
97 align uint32
98 reloff uint32
99 nreloc uint32
100 flags uint32
101 res1 uint32
102 res2 uint32
103 sym *sym.Symbol
104 rel []ldMachoRel
105 }
106
107 type ldMachoRel struct {
108 addr uint32
109 symnum uint32
110 pcrel uint8
111 length uint8
112 extrn uint8
113 type_ uint8
114 scattered uint8
115 value uint32
116 }
117
118 type ldMachoSymtab struct {
119 symoff uint32
120 nsym uint32
121 stroff uint32
122 strsize uint32
123 str []byte
124 sym []ldMachoSym
125 }
126
127 type ldMachoSym struct {
128 name string
129 type_ uint8
130 sectnum uint8
131 desc uint16
132 kind int8
133 value uint64
134 sym *sym.Symbol
135 }
136
137 type ldMachoDysymtab struct {
138 ilocalsym uint32
139 nlocalsym uint32
140 iextdefsym uint32
141 nextdefsym uint32
142 iundefsym uint32
143 nundefsym uint32
144 tocoff uint32
145 ntoc uint32
146 modtaboff uint32
147 nmodtab uint32
148 extrefsymoff uint32
149 nextrefsyms uint32
150 indirectsymoff uint32
151 nindirectsyms uint32
152 extreloff uint32
153 nextrel uint32
154 locreloff uint32
155 nlocrel uint32
156 indir []uint32
157 }
158
159
160 const (
161 N_EXT = 0x01
162 N_TYPE = 0x1e
163 N_STAB = 0xe0
164 )
165
166
167 const (
168 N_WEAK_REF = 0x40
169 N_WEAK_DEF = 0x80
170 )
171
172 const (
173 LdMachoCpuVax = 1
174 LdMachoCpu68000 = 6
175 LdMachoCpu386 = 7
176 LdMachoCpuAmd64 = 0x1000007
177 LdMachoCpuMips = 8
178 LdMachoCpu98000 = 10
179 LdMachoCpuHppa = 11
180 LdMachoCpuArm = 12
181 LdMachoCpu88000 = 13
182 LdMachoCpuSparc = 14
183 LdMachoCpu860 = 15
184 LdMachoCpuAlpha = 16
185 LdMachoCpuPower = 18
186 LdMachoCmdSegment = 1
187 LdMachoCmdSymtab = 2
188 LdMachoCmdSymseg = 3
189 LdMachoCmdThread = 4
190 LdMachoCmdDysymtab = 11
191 LdMachoCmdSegment64 = 25
192 LdMachoFileObject = 1
193 LdMachoFileExecutable = 2
194 LdMachoFileFvmlib = 3
195 LdMachoFileCore = 4
196 LdMachoFilePreload = 5
197 )
198
199 func unpackcmd(p []byte, m *ldMachoObj, c *ldMachoCmd, type_ uint, sz uint) int {
200 e4 := m.e.Uint32
201 e8 := m.e.Uint64
202
203 c.type_ = int(type_)
204 c.size = uint32(sz)
205 switch type_ {
206 default:
207 return -1
208
209 case LdMachoCmdSegment:
210 if sz < 56 {
211 return -1
212 }
213 c.seg.name = cstring(p[8:24])
214 c.seg.vmaddr = uint64(e4(p[24:]))
215 c.seg.vmsize = uint64(e4(p[28:]))
216 c.seg.fileoff = e4(p[32:])
217 c.seg.filesz = e4(p[36:])
218 c.seg.maxprot = e4(p[40:])
219 c.seg.initprot = e4(p[44:])
220 c.seg.nsect = e4(p[48:])
221 c.seg.flags = e4(p[52:])
222 c.seg.sect = make([]ldMachoSect, c.seg.nsect)
223 if uint32(sz) < 56+c.seg.nsect*68 {
224 return -1
225 }
226 p = p[56:]
227 var s *ldMachoSect
228 for i := 0; uint32(i) < c.seg.nsect; i++ {
229 s = &c.seg.sect[i]
230 s.name = cstring(p[0:16])
231 s.segname = cstring(p[16:32])
232 s.addr = uint64(e4(p[32:]))
233 s.size = uint64(e4(p[36:]))
234 s.off = e4(p[40:])
235 s.align = e4(p[44:])
236 s.reloff = e4(p[48:])
237 s.nreloc = e4(p[52:])
238 s.flags = e4(p[56:])
239 s.res1 = e4(p[60:])
240 s.res2 = e4(p[64:])
241 p = p[68:]
242 }
243
244 case LdMachoCmdSegment64:
245 if sz < 72 {
246 return -1
247 }
248 c.seg.name = cstring(p[8:24])
249 c.seg.vmaddr = e8(p[24:])
250 c.seg.vmsize = e8(p[32:])
251 c.seg.fileoff = uint32(e8(p[40:]))
252 c.seg.filesz = uint32(e8(p[48:]))
253 c.seg.maxprot = e4(p[56:])
254 c.seg.initprot = e4(p[60:])
255 c.seg.nsect = e4(p[64:])
256 c.seg.flags = e4(p[68:])
257 c.seg.sect = make([]ldMachoSect, c.seg.nsect)
258 if uint32(sz) < 72+c.seg.nsect*80 {
259 return -1
260 }
261 p = p[72:]
262 var s *ldMachoSect
263 for i := 0; uint32(i) < c.seg.nsect; i++ {
264 s = &c.seg.sect[i]
265 s.name = cstring(p[0:16])
266 s.segname = cstring(p[16:32])
267 s.addr = e8(p[32:])
268 s.size = e8(p[40:])
269 s.off = e4(p[48:])
270 s.align = e4(p[52:])
271 s.reloff = e4(p[56:])
272 s.nreloc = e4(p[60:])
273 s.flags = e4(p[64:])
274 s.res1 = e4(p[68:])
275 s.res2 = e4(p[72:])
276
277
278 p = p[80:]
279 }
280
281 case LdMachoCmdSymtab:
282 if sz < 24 {
283 return -1
284 }
285 c.sym.symoff = e4(p[8:])
286 c.sym.nsym = e4(p[12:])
287 c.sym.stroff = e4(p[16:])
288 c.sym.strsize = e4(p[20:])
289
290 case LdMachoCmdDysymtab:
291 if sz < 80 {
292 return -1
293 }
294 c.dsym.ilocalsym = e4(p[8:])
295 c.dsym.nlocalsym = e4(p[12:])
296 c.dsym.iextdefsym = e4(p[16:])
297 c.dsym.nextdefsym = e4(p[20:])
298 c.dsym.iundefsym = e4(p[24:])
299 c.dsym.nundefsym = e4(p[28:])
300 c.dsym.tocoff = e4(p[32:])
301 c.dsym.ntoc = e4(p[36:])
302 c.dsym.modtaboff = e4(p[40:])
303 c.dsym.nmodtab = e4(p[44:])
304 c.dsym.extrefsymoff = e4(p[48:])
305 c.dsym.nextrefsyms = e4(p[52:])
306 c.dsym.indirectsymoff = e4(p[56:])
307 c.dsym.nindirectsyms = e4(p[60:])
308 c.dsym.extreloff = e4(p[64:])
309 c.dsym.nextrel = e4(p[68:])
310 c.dsym.locreloff = e4(p[72:])
311 c.dsym.nlocrel = e4(p[76:])
312 }
313
314 return 0
315 }
316
317 func macholoadrel(m *ldMachoObj, sect *ldMachoSect) int {
318 if sect.rel != nil || sect.nreloc == 0 {
319 return 0
320 }
321 rel := make([]ldMachoRel, sect.nreloc)
322 n := int(sect.nreloc * 8)
323 buf := make([]byte, n)
324 m.f.MustSeek(m.base+int64(sect.reloff), 0)
325 if _, err := io.ReadFull(m.f, buf); err != nil {
326 return -1
327 }
328 for i := uint32(0); i < sect.nreloc; i++ {
329 r := &rel[i]
330 p := buf[i*8:]
331 r.addr = m.e.Uint32(p)
332
333
334 if r.addr&0x80000000 != 0 {
335
336 r.scattered = 1
337
338 v := r.addr >> 24
339 r.addr &= 0xFFFFFF
340 r.type_ = uint8(v & 0xF)
341 v >>= 4
342 r.length = 1 << (v & 3)
343 v >>= 2
344 r.pcrel = uint8(v & 1)
345 r.value = m.e.Uint32(p[4:])
346 } else {
347 v := m.e.Uint32(p[4:])
348 r.symnum = v & 0xFFFFFF
349 v >>= 24
350 r.pcrel = uint8(v & 1)
351 v >>= 1
352 r.length = 1 << (v & 3)
353 v >>= 2
354 r.extrn = uint8(v & 1)
355 v >>= 1
356 r.type_ = uint8(v)
357 }
358 }
359
360 sect.rel = rel
361 return 0
362 }
363
364 func macholoaddsym(m *ldMachoObj, d *ldMachoDysymtab) int {
365 n := int(d.nindirectsyms)
366
367 p := make([]byte, n*4)
368 m.f.MustSeek(m.base+int64(d.indirectsymoff), 0)
369 if _, err := io.ReadFull(m.f, p); err != nil {
370 return -1
371 }
372
373 d.indir = make([]uint32, n)
374 for i := 0; i < n; i++ {
375 d.indir[i] = m.e.Uint32(p[4*i:])
376 }
377 return 0
378 }
379
380 func macholoadsym(m *ldMachoObj, symtab *ldMachoSymtab) int {
381 if symtab.sym != nil {
382 return 0
383 }
384
385 strbuf := make([]byte, symtab.strsize)
386 m.f.MustSeek(m.base+int64(symtab.stroff), 0)
387 if _, err := io.ReadFull(m.f, strbuf); err != nil {
388 return -1
389 }
390
391 symsize := 12
392 if m.is64 {
393 symsize = 16
394 }
395 n := int(symtab.nsym * uint32(symsize))
396 symbuf := make([]byte, n)
397 m.f.MustSeek(m.base+int64(symtab.symoff), 0)
398 if _, err := io.ReadFull(m.f, symbuf); err != nil {
399 return -1
400 }
401 sym := make([]ldMachoSym, symtab.nsym)
402 p := symbuf
403 for i := uint32(0); i < symtab.nsym; i++ {
404 s := &sym[i]
405 v := m.e.Uint32(p)
406 if v >= symtab.strsize {
407 return -1
408 }
409 s.name = cstring(strbuf[v:])
410 s.type_ = p[4]
411 s.sectnum = p[5]
412 s.desc = m.e.Uint16(p[6:])
413 if m.is64 {
414 s.value = m.e.Uint64(p[8:])
415 } else {
416 s.value = uint64(m.e.Uint32(p[8:]))
417 }
418 p = p[symsize:]
419 }
420
421 symtab.str = strbuf
422 symtab.sym = sym
423 return 0
424 }
425
426
427
428 func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, err error) {
429 errorf := func(str string, args ...interface{}) ([]*sym.Symbol, error) {
430 return nil, fmt.Errorf("loadmacho: %v: %v", pn, fmt.Sprintf(str, args...))
431 }
432
433 localSymVersion := syms.IncVersion()
434 base := f.Offset()
435
436 var hdr [7 * 4]uint8
437 if _, err := io.ReadFull(f, hdr[:]); err != nil {
438 return errorf("reading hdr: %v", err)
439 }
440
441 var e binary.ByteOrder
442 if binary.BigEndian.Uint32(hdr[:])&^1 == 0xFEEDFACE {
443 e = binary.BigEndian
444 } else if binary.LittleEndian.Uint32(hdr[:])&^1 == 0xFEEDFACE {
445 e = binary.LittleEndian
446 } else {
447 return errorf("bad magic - not mach-o file")
448 }
449
450 is64 := e.Uint32(hdr[:]) == 0xFEEDFACF
451 ncmd := e.Uint32(hdr[4*4:])
452 cmdsz := e.Uint32(hdr[5*4:])
453 if ncmd > 0x10000 || cmdsz >= 0x01000000 {
454 return errorf("implausible mach-o header ncmd=%d cmdsz=%d", ncmd, cmdsz)
455 }
456
457 if is64 {
458 f.MustSeek(4, 1)
459 }
460
461 m := &ldMachoObj{
462 f: f,
463 e: e,
464 cputype: uint(e.Uint32(hdr[1*4:])),
465 subcputype: uint(e.Uint32(hdr[2*4:])),
466 filetype: e.Uint32(hdr[3*4:]),
467 ncmd: uint(ncmd),
468 flags: e.Uint32(hdr[6*4:]),
469 is64: is64,
470 base: base,
471 length: length,
472 name: pn,
473 }
474
475 switch arch.Family {
476 default:
477 return errorf("mach-o %s unimplemented", arch.Name)
478
479 case sys.AMD64:
480 if e != binary.LittleEndian || m.cputype != LdMachoCpuAmd64 {
481 return errorf("mach-o object but not amd64")
482 }
483
484 case sys.I386:
485 if e != binary.LittleEndian || m.cputype != LdMachoCpu386 {
486 return errorf("mach-o object but not 386")
487 }
488 }
489
490 m.cmd = make([]ldMachoCmd, ncmd)
491 cmdp := make([]byte, cmdsz)
492 if _, err := io.ReadFull(f, cmdp); err != nil {
493 return errorf("reading cmds: %v", err)
494 }
495
496
497 var c *ldMachoCmd
498
499 var symtab *ldMachoSymtab
500 var dsymtab *ldMachoDysymtab
501
502 off := uint32(len(hdr))
503 for i := uint32(0); i < ncmd; i++ {
504 ty := e.Uint32(cmdp)
505 sz := e.Uint32(cmdp[4:])
506 m.cmd[i].off = off
507 unpackcmd(cmdp, m, &m.cmd[i], uint(ty), uint(sz))
508 cmdp = cmdp[sz:]
509 off += sz
510 if ty == LdMachoCmdSymtab {
511 if symtab != nil {
512 return errorf("multiple symbol tables")
513 }
514
515 symtab = &m.cmd[i].sym
516 macholoadsym(m, symtab)
517 }
518
519 if ty == LdMachoCmdDysymtab {
520 dsymtab = &m.cmd[i].dsym
521 macholoaddsym(m, dsymtab)
522 }
523
524 if (is64 && ty == LdMachoCmdSegment64) || (!is64 && ty == LdMachoCmdSegment) {
525 if c != nil {
526 return errorf("multiple load commands")
527 }
528
529 c = &m.cmd[i]
530 }
531 }
532
533
534
535
536
537 if c == nil {
538 return errorf("no load command")
539 }
540
541 if symtab == nil {
542
543 return
544 }
545
546 if int64(c.seg.fileoff+c.seg.filesz) >= length {
547 return errorf("load segment out of range")
548 }
549
550 f.MustSeek(m.base+int64(c.seg.fileoff), 0)
551 dat := make([]byte, c.seg.filesz)
552 if _, err := io.ReadFull(f, dat); err != nil {
553 return errorf("cannot load object data: %v", err)
554 }
555
556 for i := uint32(0); i < c.seg.nsect; i++ {
557 sect := &c.seg.sect[i]
558 if sect.segname != "__TEXT" && sect.segname != "__DATA" {
559 continue
560 }
561 if sect.name == "__eh_frame" {
562 continue
563 }
564 name := fmt.Sprintf("%s(%s/%s)", pkg, sect.segname, sect.name)
565 s := syms.Lookup(name, localSymVersion)
566 if s.Type != 0 {
567 return errorf("duplicate %s/%s", sect.segname, sect.name)
568 }
569
570 if sect.flags&0xff == 1 {
571 s.P = make([]byte, sect.size)
572 } else {
573 s.P = dat[sect.addr-c.seg.vmaddr:][:sect.size]
574 }
575 s.Size = int64(len(s.P))
576
577 if sect.segname == "__TEXT" {
578 if sect.name == "__text" {
579 s.Type = sym.STEXT
580 } else {
581 s.Type = sym.SRODATA
582 }
583 } else {
584 if sect.name == "__bss" {
585 s.Type = sym.SNOPTRBSS
586 s.P = s.P[:0]
587 } else {
588 s.Type = sym.SNOPTRDATA
589 }
590 }
591
592 sect.sym = s
593 }
594
595
596
597 for i := uint32(0); i < symtab.nsym; i++ {
598 machsym := &symtab.sym[i]
599 if machsym.type_&N_STAB != 0 {
600 continue
601 }
602
603
604 name := machsym.name
605
606 if name[0] == '_' && name[1] != '\x00' {
607 name = name[1:]
608 }
609 v := 0
610 if machsym.type_&N_EXT == 0 {
611 v = localSymVersion
612 }
613 s := syms.Lookup(name, v)
614 if machsym.type_&N_EXT == 0 {
615 s.Attr |= sym.AttrDuplicateOK
616 }
617 if machsym.desc&(N_WEAK_REF|N_WEAK_DEF) != 0 {
618 s.Attr |= sym.AttrDuplicateOK
619 }
620 machsym.sym = s
621 if machsym.sectnum == 0 {
622 continue
623 }
624 if uint32(machsym.sectnum) > c.seg.nsect {
625 return errorf("reference to invalid section %d", machsym.sectnum)
626 }
627
628 sect := &c.seg.sect[machsym.sectnum-1]
629 outer := sect.sym
630 if outer == nil {
631 continue
632 }
633
634 if s.Outer != nil {
635 if s.Attr.DuplicateOK() {
636 continue
637 }
638 return errorf("duplicate symbol reference: %s in both %s and %s", s.Name, s.Outer.Name, sect.sym.Name)
639 }
640
641 s.Type = outer.Type
642 s.Attr |= sym.AttrSubSymbol
643 s.Sub = outer.Sub
644 outer.Sub = s
645 s.Outer = outer
646 s.Value = int64(machsym.value - sect.addr)
647 if !s.Attr.CgoExportDynamic() {
648 s.SetDynimplib("")
649 }
650 if outer.Type == sym.STEXT {
651 if s.Attr.External() && !s.Attr.DuplicateOK() {
652 return errorf("%v: duplicate symbol definition", s)
653 }
654 s.Attr |= sym.AttrExternal
655 }
656
657 machsym.sym = s
658 }
659
660
661
662 for i := 0; uint32(i) < c.seg.nsect; i++ {
663 sect := &c.seg.sect[i]
664 s := sect.sym
665 if s == nil {
666 continue
667 }
668 if s.Sub != nil {
669 s.Sub = sym.SortSub(s.Sub)
670
671
672 for s1 := s.Sub; s1 != nil; s1 = s1.Sub {
673 if s1.Sub != nil {
674 s1.Size = s1.Sub.Value - s1.Value
675 } else {
676 s1.Size = s.Value + s.Size - s1.Value
677 }
678 }
679 }
680
681 if s.Type == sym.STEXT {
682 if s.Attr.OnList() {
683 return errorf("symbol %s listed multiple times", s.Name)
684 }
685 s.Attr |= sym.AttrOnList
686 textp = append(textp, s)
687 for s1 := s.Sub; s1 != nil; s1 = s1.Sub {
688 if s1.Attr.OnList() {
689 return errorf("symbol %s listed multiple times", s1.Name)
690 }
691 s1.Attr |= sym.AttrOnList
692 textp = append(textp, s1)
693 }
694 }
695 }
696
697
698 for i := 0; uint32(i) < c.seg.nsect; i++ {
699 sect := &c.seg.sect[i]
700 s := sect.sym
701 if s == nil {
702 continue
703 }
704 macholoadrel(m, sect)
705 if sect.rel == nil {
706 continue
707 }
708 r := make([]sym.Reloc, sect.nreloc)
709 rpi := 0
710 Reloc:
711 for j := uint32(0); j < sect.nreloc; j++ {
712 rp := &r[rpi]
713 rel := §.rel[j]
714 if rel.scattered != 0 {
715 if arch.Family != sys.I386 {
716
717 return errorf("%v: unexpected scattered relocation", s)
718 }
719
720
721
722
723
724
725 if j+1 >= sect.nreloc {
726 return errorf("unsupported scattered relocation %d", int(rel.type_))
727 }
728
729 if sect.rel[j+1].scattered == 0 || sect.rel[j+1].type_ != 1 || (rel.type_ != 4 && rel.type_ != 2) || uint64(sect.rel[j+1].value) < sect.addr || uint64(sect.rel[j+1].value) >= sect.addr+sect.size {
730 return errorf("unsupported scattered relocation %d/%d", int(rel.type_), int(sect.rel[j+1].type_))
731 }
732
733 rp.Siz = rel.length
734 rp.Off = int32(rel.addr)
735
736
737
738
739
740
741
742
743 rp.Add = 0
744
745
746
747
748 rp.Type = objabi.R_PCREL
749
750 rp.Add += int64(uint64(int64(rp.Off)+4) - (uint64(sect.rel[j+1].value) - sect.addr))
751
752
753
754 for k := 0; uint32(k) < c.seg.nsect; k++ {
755 ks := &c.seg.sect[k]
756 if ks.addr <= uint64(rel.value) && uint64(rel.value) < ks.addr+ks.size {
757 if ks.sym != nil {
758 rp.Sym = ks.sym
759 rp.Add += int64(uint64(rel.value) - ks.addr)
760 } else if ks.segname == "__IMPORT" && ks.name == "__pointers" {
761
762
763
764 rp.Type = objabi.MachoRelocOffset + MACHO_FAKE_GOTPCREL
765
766
767 k = int(uint64(ks.res1) + (uint64(rel.value)-ks.addr)/4)
768
769
770
771 if dsymtab == nil || k < 0 || uint32(k) >= dsymtab.nindirectsyms || dsymtab.indir == nil {
772 return errorf("invalid scattered relocation: indirect symbol reference out of range")
773 }
774
775 k = int(dsymtab.indir[k])
776 if k < 0 || uint32(k) >= symtab.nsym {
777 return errorf("invalid scattered relocation: symbol reference out of range")
778 }
779
780 rp.Sym = symtab.sym[k].sym
781 } else {
782 return errorf("unsupported scattered relocation: reference to %s/%s", ks.segname, ks.name)
783 }
784
785 rpi++
786
787
788 j++
789
790 continue Reloc
791 }
792 }
793
794 return errorf("unsupported scattered relocation: invalid address %#x", rel.addr)
795 }
796
797 rp.Siz = rel.length
798 rp.Type = objabi.MachoRelocOffset + (objabi.RelocType(rel.type_) << 1) + objabi.RelocType(rel.pcrel)
799 rp.Off = int32(rel.addr)
800
801
802 if arch.Family == sys.AMD64 && rel.extrn == 0 && rel.type_ == MACHO_X86_64_RELOC_SIGNED {
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818 secaddr := c.seg.sect[rel.symnum-1].addr
819
820 rp.Add = int64(uint64(int64(int32(e.Uint32(s.P[rp.Off:])))+int64(rp.Off)+4) - secaddr)
821 } else {
822 rp.Add = int64(int32(e.Uint32(s.P[rp.Off:])))
823 }
824
825
826
827 if arch.Family == sys.AMD64 && rel.extrn == 0 && rel.type_ == MACHO_X86_64_RELOC_UNSIGNED {
828 secaddr := c.seg.sect[rel.symnum-1].addr
829 rp.Add -= int64(secaddr)
830 }
831
832
833
834
835 if rel.pcrel != 0 && arch.Family == sys.I386 {
836 rp.Add += int64(rp.Off) + int64(rp.Siz)
837 }
838 if rel.extrn == 0 {
839 if rel.symnum < 1 || rel.symnum > c.seg.nsect {
840 return errorf("invalid relocation: section reference out of range %d vs %d", rel.symnum, c.seg.nsect)
841 }
842
843 rp.Sym = c.seg.sect[rel.symnum-1].sym
844 if rp.Sym == nil {
845 return errorf("invalid relocation: %s", c.seg.sect[rel.symnum-1].name)
846 }
847
848
849
850
851
852 if arch.Family == sys.I386 {
853 rp.Add -= int64(c.seg.sect[rel.symnum-1].addr)
854 }
855 } else {
856 if rel.symnum >= symtab.nsym {
857 return errorf("invalid relocation: symbol reference out of range")
858 }
859
860 rp.Sym = symtab.sym[rel.symnum].sym
861 }
862
863 rpi++
864 }
865
866 sort.Sort(sym.RelocByOff(r[:rpi]))
867 s.R = r
868 s.R = s.R[:rpi]
869 }
870
871 return textp, nil
872 }
873
874 func cstring(x []byte) string {
875 i := bytes.IndexByte(x, '\x00')
876 if i >= 0 {
877 x = x[:i]
878 }
879 return string(x)
880 }
881
View as plain text