1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package goobj
20
21 import (
22 "bytes"
23 "cmd/internal/bio"
24 "crypto/sha1"
25 "encoding/binary"
26 "errors"
27 "fmt"
28 "internal/unsafeheader"
29 "io"
30 "unsafe"
31 )
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171 const stringRefSize = 8
172
173 type FingerprintType [8]byte
174
175 func (fp FingerprintType) IsZero() bool { return fp == FingerprintType{} }
176
177
178 const (
179 PkgIdxNone = (1<<31 - 1) - iota
180 PkgIdxHashed64
181 PkgIdxHashed
182 PkgIdxBuiltin
183 PkgIdxSelf
184 PkgIdxInvalid = 0
185
186 )
187
188
189 const (
190 BlkAutolib = iota
191 BlkPkgIdx
192 BlkFile
193 BlkSymdef
194 BlkHashed64def
195 BlkHasheddef
196 BlkNonpkgdef
197 BlkNonpkgref
198 BlkRefFlags
199 BlkHash64
200 BlkHash
201 BlkRelocIdx
202 BlkAuxIdx
203 BlkDataIdx
204 BlkReloc
205 BlkAux
206 BlkData
207 BlkPcdata
208 BlkRefName
209 BlkEnd
210 NBlk
211 )
212
213
214
215 type Header struct {
216 Magic string
217 Fingerprint FingerprintType
218 Flags uint32
219 Offsets [NBlk]uint32
220 }
221
222 const Magic = "\x00go117ld"
223
224 func (h *Header) Write(w *Writer) {
225 w.RawString(h.Magic)
226 w.Bytes(h.Fingerprint[:])
227 w.Uint32(h.Flags)
228 for _, x := range h.Offsets {
229 w.Uint32(x)
230 }
231 }
232
233 func (h *Header) Read(r *Reader) error {
234 b := r.BytesAt(0, len(Magic))
235 h.Magic = string(b)
236 if h.Magic != Magic {
237 return errors.New("wrong magic, not a Go object file")
238 }
239 off := uint32(len(h.Magic))
240 copy(h.Fingerprint[:], r.BytesAt(off, len(h.Fingerprint)))
241 off += 8
242 h.Flags = r.uint32At(off)
243 off += 4
244 for i := range h.Offsets {
245 h.Offsets[i] = r.uint32At(off)
246 off += 4
247 }
248 return nil
249 }
250
251 func (h *Header) Size() int {
252 return len(h.Magic) + 4 + 4*len(h.Offsets)
253 }
254
255
256 type ImportedPkg struct {
257 Pkg string
258 Fingerprint FingerprintType
259 }
260
261 const importedPkgSize = stringRefSize + 8
262
263 func (p *ImportedPkg) Write(w *Writer) {
264 w.StringRef(p.Pkg)
265 w.Bytes(p.Fingerprint[:])
266 }
267
268
269
270
271
272
273
274
275
276
277
278
279
280 type Sym [SymSize]byte
281
282 const SymSize = stringRefSize + 2 + 1 + 1 + 1 + 4 + 4
283
284 const SymABIstatic = ^uint16(0)
285
286 const (
287 ObjFlagShared = 1 << iota
288 ObjFlagNeedNameExpansion
289 ObjFlagFromAssembly
290 )
291
292
293 const (
294 SymFlagDupok = 1 << iota
295 SymFlagLocal
296 SymFlagTypelink
297 SymFlagLeaf
298 SymFlagNoSplit
299 SymFlagReflectMethod
300 SymFlagGoType
301 )
302
303
304 const (
305 SymFlagUsedInIface = 1 << iota
306 SymFlagItab
307 )
308
309
310 func (s *Sym) NameLen(r *Reader) int {
311 return int(binary.LittleEndian.Uint32(s[:]))
312 }
313
314 func (s *Sym) Name(r *Reader) string {
315 len := binary.LittleEndian.Uint32(s[:])
316 off := binary.LittleEndian.Uint32(s[4:])
317 return r.StringAt(off, len)
318 }
319
320 func (s *Sym) ABI() uint16 { return binary.LittleEndian.Uint16(s[8:]) }
321 func (s *Sym) Type() uint8 { return s[10] }
322 func (s *Sym) Flag() uint8 { return s[11] }
323 func (s *Sym) Flag2() uint8 { return s[12] }
324 func (s *Sym) Siz() uint32 { return binary.LittleEndian.Uint32(s[13:]) }
325 func (s *Sym) Align() uint32 { return binary.LittleEndian.Uint32(s[17:]) }
326
327 func (s *Sym) Dupok() bool { return s.Flag()&SymFlagDupok != 0 }
328 func (s *Sym) Local() bool { return s.Flag()&SymFlagLocal != 0 }
329 func (s *Sym) Typelink() bool { return s.Flag()&SymFlagTypelink != 0 }
330 func (s *Sym) Leaf() bool { return s.Flag()&SymFlagLeaf != 0 }
331 func (s *Sym) NoSplit() bool { return s.Flag()&SymFlagNoSplit != 0 }
332 func (s *Sym) ReflectMethod() bool { return s.Flag()&SymFlagReflectMethod != 0 }
333 func (s *Sym) IsGoType() bool { return s.Flag()&SymFlagGoType != 0 }
334 func (s *Sym) UsedInIface() bool { return s.Flag2()&SymFlagUsedInIface != 0 }
335 func (s *Sym) IsItab() bool { return s.Flag2()&SymFlagItab != 0 }
336
337 func (s *Sym) SetName(x string, w *Writer) {
338 binary.LittleEndian.PutUint32(s[:], uint32(len(x)))
339 binary.LittleEndian.PutUint32(s[4:], w.stringOff(x))
340 }
341
342 func (s *Sym) SetABI(x uint16) { binary.LittleEndian.PutUint16(s[8:], x) }
343 func (s *Sym) SetType(x uint8) { s[10] = x }
344 func (s *Sym) SetFlag(x uint8) { s[11] = x }
345 func (s *Sym) SetFlag2(x uint8) { s[12] = x }
346 func (s *Sym) SetSiz(x uint32) { binary.LittleEndian.PutUint32(s[13:], x) }
347 func (s *Sym) SetAlign(x uint32) { binary.LittleEndian.PutUint32(s[17:], x) }
348
349 func (s *Sym) Write(w *Writer) { w.Bytes(s[:]) }
350
351
352 func (s *Sym) fromBytes(b []byte) { copy(s[:], b) }
353
354
355 type SymRef struct {
356 PkgIdx uint32
357 SymIdx uint32
358 }
359
360
361 type Hash64Type [Hash64Size]byte
362
363 const Hash64Size = 8
364
365
366 type HashType [HashSize]byte
367
368 const HashSize = sha1.Size
369
370
371
372
373
374
375
376
377
378
379
380 type Reloc [RelocSize]byte
381
382 const RelocSize = 4 + 1 + 2 + 8 + 8
383
384 func (r *Reloc) Off() int32 { return int32(binary.LittleEndian.Uint32(r[:])) }
385 func (r *Reloc) Siz() uint8 { return r[4] }
386 func (r *Reloc) Type() uint16 { return binary.LittleEndian.Uint16(r[5:]) }
387 func (r *Reloc) Add() int64 { return int64(binary.LittleEndian.Uint64(r[7:])) }
388 func (r *Reloc) Sym() SymRef {
389 return SymRef{binary.LittleEndian.Uint32(r[15:]), binary.LittleEndian.Uint32(r[19:])}
390 }
391
392 func (r *Reloc) SetOff(x int32) { binary.LittleEndian.PutUint32(r[:], uint32(x)) }
393 func (r *Reloc) SetSiz(x uint8) { r[4] = x }
394 func (r *Reloc) SetType(x uint16) { binary.LittleEndian.PutUint16(r[5:], x) }
395 func (r *Reloc) SetAdd(x int64) { binary.LittleEndian.PutUint64(r[7:], uint64(x)) }
396 func (r *Reloc) SetSym(x SymRef) {
397 binary.LittleEndian.PutUint32(r[15:], x.PkgIdx)
398 binary.LittleEndian.PutUint32(r[19:], x.SymIdx)
399 }
400
401 func (r *Reloc) Set(off int32, size uint8, typ uint16, add int64, sym SymRef) {
402 r.SetOff(off)
403 r.SetSiz(size)
404 r.SetType(typ)
405 r.SetAdd(add)
406 r.SetSym(sym)
407 }
408
409 func (r *Reloc) Write(w *Writer) { w.Bytes(r[:]) }
410
411
412 func (r *Reloc) fromBytes(b []byte) { copy(r[:], b) }
413
414
415
416
417
418
419
420
421 type Aux [AuxSize]byte
422
423 const AuxSize = 1 + 8
424
425
426 const (
427 AuxGotype = iota
428 AuxFuncInfo
429 AuxFuncdata
430 AuxDwarfInfo
431 AuxDwarfLoc
432 AuxDwarfRanges
433 AuxDwarfLines
434 AuxPcsp
435 AuxPcfile
436 AuxPcline
437 AuxPcinline
438 AuxPcdata
439 )
440
441 func (a *Aux) Type() uint8 { return a[0] }
442 func (a *Aux) Sym() SymRef {
443 return SymRef{binary.LittleEndian.Uint32(a[1:]), binary.LittleEndian.Uint32(a[5:])}
444 }
445
446 func (a *Aux) SetType(x uint8) { a[0] = x }
447 func (a *Aux) SetSym(x SymRef) {
448 binary.LittleEndian.PutUint32(a[1:], x.PkgIdx)
449 binary.LittleEndian.PutUint32(a[5:], x.SymIdx)
450 }
451
452 func (a *Aux) Write(w *Writer) { w.Bytes(a[:]) }
453
454
455 func (a *Aux) fromBytes(b []byte) { copy(a[:], b) }
456
457
458
459
460
461
462
463
464
465 type RefFlags [RefFlagsSize]byte
466
467 const RefFlagsSize = 8 + 1 + 1
468
469 func (r *RefFlags) Sym() SymRef {
470 return SymRef{binary.LittleEndian.Uint32(r[:]), binary.LittleEndian.Uint32(r[4:])}
471 }
472 func (r *RefFlags) Flag() uint8 { return r[8] }
473 func (r *RefFlags) Flag2() uint8 { return r[9] }
474
475 func (r *RefFlags) SetSym(x SymRef) {
476 binary.LittleEndian.PutUint32(r[:], x.PkgIdx)
477 binary.LittleEndian.PutUint32(r[4:], x.SymIdx)
478 }
479 func (r *RefFlags) SetFlag(x uint8) { r[8] = x }
480 func (r *RefFlags) SetFlag2(x uint8) { r[9] = x }
481
482 func (r *RefFlags) Write(w *Writer) { w.Bytes(r[:]) }
483
484
485
486
487 const huge = (1<<31 - 1) / RelocSize
488
489
490
491
492
493
494
495
496 type RefName [RefNameSize]byte
497
498 const RefNameSize = 8 + stringRefSize
499
500 func (n *RefName) Sym() SymRef {
501 return SymRef{binary.LittleEndian.Uint32(n[:]), binary.LittleEndian.Uint32(n[4:])}
502 }
503 func (n *RefName) Name(r *Reader) string {
504 len := binary.LittleEndian.Uint32(n[8:])
505 off := binary.LittleEndian.Uint32(n[12:])
506 return r.StringAt(off, len)
507 }
508
509 func (n *RefName) SetSym(x SymRef) {
510 binary.LittleEndian.PutUint32(n[:], x.PkgIdx)
511 binary.LittleEndian.PutUint32(n[4:], x.SymIdx)
512 }
513 func (n *RefName) SetName(x string, w *Writer) {
514 binary.LittleEndian.PutUint32(n[8:], uint32(len(x)))
515 binary.LittleEndian.PutUint32(n[12:], w.stringOff(x))
516 }
517
518 func (n *RefName) Write(w *Writer) { w.Bytes(n[:]) }
519
520 type Writer struct {
521 wr *bio.Writer
522 stringMap map[string]uint32
523 off uint32
524 }
525
526 func NewWriter(wr *bio.Writer) *Writer {
527 return &Writer{wr: wr, stringMap: make(map[string]uint32)}
528 }
529
530 func (w *Writer) AddString(s string) {
531 if _, ok := w.stringMap[s]; ok {
532 return
533 }
534 w.stringMap[s] = w.off
535 w.RawString(s)
536 }
537
538 func (w *Writer) stringOff(s string) uint32 {
539 off, ok := w.stringMap[s]
540 if !ok {
541 panic(fmt.Sprintf("writeStringRef: string not added: %q", s))
542 }
543 return off
544 }
545
546 func (w *Writer) StringRef(s string) {
547 w.Uint32(uint32(len(s)))
548 w.Uint32(w.stringOff(s))
549 }
550
551 func (w *Writer) RawString(s string) {
552 w.wr.WriteString(s)
553 w.off += uint32(len(s))
554 }
555
556 func (w *Writer) Bytes(s []byte) {
557 w.wr.Write(s)
558 w.off += uint32(len(s))
559 }
560
561 func (w *Writer) Uint64(x uint64) {
562 var b [8]byte
563 binary.LittleEndian.PutUint64(b[:], x)
564 w.wr.Write(b[:])
565 w.off += 8
566 }
567
568 func (w *Writer) Uint32(x uint32) {
569 var b [4]byte
570 binary.LittleEndian.PutUint32(b[:], x)
571 w.wr.Write(b[:])
572 w.off += 4
573 }
574
575 func (w *Writer) Uint16(x uint16) {
576 var b [2]byte
577 binary.LittleEndian.PutUint16(b[:], x)
578 w.wr.Write(b[:])
579 w.off += 2
580 }
581
582 func (w *Writer) Uint8(x uint8) {
583 w.wr.WriteByte(x)
584 w.off++
585 }
586
587 func (w *Writer) Offset() uint32 {
588 return w.off
589 }
590
591 type Reader struct {
592 b []byte
593 readonly bool
594
595 rd io.ReaderAt
596 start uint32
597 h Header
598 }
599
600 func NewReaderFromBytes(b []byte, readonly bool) *Reader {
601 r := &Reader{b: b, readonly: readonly, rd: bytes.NewReader(b), start: 0}
602 err := r.h.Read(r)
603 if err != nil {
604 return nil
605 }
606 return r
607 }
608
609 func (r *Reader) BytesAt(off uint32, len int) []byte {
610 if len == 0 {
611 return nil
612 }
613 end := int(off) + len
614 return r.b[int(off):end:end]
615 }
616
617 func (r *Reader) uint64At(off uint32) uint64 {
618 b := r.BytesAt(off, 8)
619 return binary.LittleEndian.Uint64(b)
620 }
621
622 func (r *Reader) int64At(off uint32) int64 {
623 return int64(r.uint64At(off))
624 }
625
626 func (r *Reader) uint32At(off uint32) uint32 {
627 b := r.BytesAt(off, 4)
628 return binary.LittleEndian.Uint32(b)
629 }
630
631 func (r *Reader) int32At(off uint32) int32 {
632 return int32(r.uint32At(off))
633 }
634
635 func (r *Reader) uint16At(off uint32) uint16 {
636 b := r.BytesAt(off, 2)
637 return binary.LittleEndian.Uint16(b)
638 }
639
640 func (r *Reader) uint8At(off uint32) uint8 {
641 b := r.BytesAt(off, 1)
642 return b[0]
643 }
644
645 func (r *Reader) StringAt(off uint32, len uint32) string {
646 b := r.b[off : off+len]
647 if r.readonly {
648 return toString(b)
649 }
650 return string(b)
651 }
652
653 func toString(b []byte) string {
654 if len(b) == 0 {
655 return ""
656 }
657
658 var s string
659 hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
660 hdr.Data = unsafe.Pointer(&b[0])
661 hdr.Len = len(b)
662
663 return s
664 }
665
666 func (r *Reader) StringRef(off uint32) string {
667 l := r.uint32At(off)
668 return r.StringAt(r.uint32At(off+4), l)
669 }
670
671 func (r *Reader) Fingerprint() FingerprintType {
672 return r.h.Fingerprint
673 }
674
675 func (r *Reader) Autolib() []ImportedPkg {
676 n := (r.h.Offsets[BlkAutolib+1] - r.h.Offsets[BlkAutolib]) / importedPkgSize
677 s := make([]ImportedPkg, n)
678 off := r.h.Offsets[BlkAutolib]
679 for i := range s {
680 s[i].Pkg = r.StringRef(off)
681 copy(s[i].Fingerprint[:], r.BytesAt(off+stringRefSize, len(s[i].Fingerprint)))
682 off += importedPkgSize
683 }
684 return s
685 }
686
687 func (r *Reader) Pkglist() []string {
688 n := (r.h.Offsets[BlkPkgIdx+1] - r.h.Offsets[BlkPkgIdx]) / stringRefSize
689 s := make([]string, n)
690 off := r.h.Offsets[BlkPkgIdx]
691 for i := range s {
692 s[i] = r.StringRef(off)
693 off += stringRefSize
694 }
695 return s
696 }
697
698 func (r *Reader) NPkg() int {
699 return int(r.h.Offsets[BlkPkgIdx+1]-r.h.Offsets[BlkPkgIdx]) / stringRefSize
700 }
701
702 func (r *Reader) Pkg(i int) string {
703 off := r.h.Offsets[BlkPkgIdx] + uint32(i)*stringRefSize
704 return r.StringRef(off)
705 }
706
707 func (r *Reader) NFile() int {
708 return int(r.h.Offsets[BlkFile+1]-r.h.Offsets[BlkFile]) / stringRefSize
709 }
710
711 func (r *Reader) File(i int) string {
712 off := r.h.Offsets[BlkFile] + uint32(i)*stringRefSize
713 return r.StringRef(off)
714 }
715
716 func (r *Reader) NSym() int {
717 return int(r.h.Offsets[BlkSymdef+1]-r.h.Offsets[BlkSymdef]) / SymSize
718 }
719
720 func (r *Reader) NHashed64def() int {
721 return int(r.h.Offsets[BlkHashed64def+1]-r.h.Offsets[BlkHashed64def]) / SymSize
722 }
723
724 func (r *Reader) NHasheddef() int {
725 return int(r.h.Offsets[BlkHasheddef+1]-r.h.Offsets[BlkHasheddef]) / SymSize
726 }
727
728 func (r *Reader) NNonpkgdef() int {
729 return int(r.h.Offsets[BlkNonpkgdef+1]-r.h.Offsets[BlkNonpkgdef]) / SymSize
730 }
731
732 func (r *Reader) NNonpkgref() int {
733 return int(r.h.Offsets[BlkNonpkgref+1]-r.h.Offsets[BlkNonpkgref]) / SymSize
734 }
735
736
737 func (r *Reader) SymOff(i uint32) uint32 {
738 return r.h.Offsets[BlkSymdef] + uint32(i*SymSize)
739 }
740
741
742 func (r *Reader) Sym(i uint32) *Sym {
743 off := r.SymOff(i)
744 return (*Sym)(unsafe.Pointer(&r.b[off]))
745 }
746
747
748 func (r *Reader) NRefFlags() int {
749 return int(r.h.Offsets[BlkRefFlags+1]-r.h.Offsets[BlkRefFlags]) / RefFlagsSize
750 }
751
752
753
754 func (r *Reader) RefFlags(i int) *RefFlags {
755 off := r.h.Offsets[BlkRefFlags] + uint32(i*RefFlagsSize)
756 return (*RefFlags)(unsafe.Pointer(&r.b[off]))
757 }
758
759
760
761
762 func (r *Reader) Hash64(i uint32) uint64 {
763 off := r.h.Offsets[BlkHash64] + uint32(i*Hash64Size)
764 return r.uint64At(off)
765 }
766
767
768
769
770 func (r *Reader) Hash(i uint32) *HashType {
771 off := r.h.Offsets[BlkHash] + uint32(i*HashSize)
772 return (*HashType)(unsafe.Pointer(&r.b[off]))
773 }
774
775
776 func (r *Reader) NReloc(i uint32) int {
777 relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
778 return int(r.uint32At(relocIdxOff+4) - r.uint32At(relocIdxOff))
779 }
780
781
782 func (r *Reader) RelocOff(i uint32, j int) uint32 {
783 relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
784 relocIdx := r.uint32At(relocIdxOff)
785 return r.h.Offsets[BlkReloc] + (relocIdx+uint32(j))*uint32(RelocSize)
786 }
787
788
789 func (r *Reader) Reloc(i uint32, j int) *Reloc {
790 off := r.RelocOff(i, j)
791 return (*Reloc)(unsafe.Pointer(&r.b[off]))
792 }
793
794
795 func (r *Reader) Relocs(i uint32) []Reloc {
796 off := r.RelocOff(i, 0)
797 n := r.NReloc(i)
798 return (*[huge]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n]
799 }
800
801
802 func (r *Reader) NAux(i uint32) int {
803 auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
804 return int(r.uint32At(auxIdxOff+4) - r.uint32At(auxIdxOff))
805 }
806
807
808 func (r *Reader) AuxOff(i uint32, j int) uint32 {
809 auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
810 auxIdx := r.uint32At(auxIdxOff)
811 return r.h.Offsets[BlkAux] + (auxIdx+uint32(j))*uint32(AuxSize)
812 }
813
814
815 func (r *Reader) Aux(i uint32, j int) *Aux {
816 off := r.AuxOff(i, j)
817 return (*Aux)(unsafe.Pointer(&r.b[off]))
818 }
819
820
821 func (r *Reader) Auxs(i uint32) []Aux {
822 off := r.AuxOff(i, 0)
823 n := r.NAux(i)
824 return (*[huge]Aux)(unsafe.Pointer(&r.b[off]))[:n:n]
825 }
826
827
828 func (r *Reader) DataOff(i uint32) uint32 {
829 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
830 return r.h.Offsets[BlkData] + r.uint32At(dataIdxOff)
831 }
832
833
834 func (r *Reader) DataSize(i uint32) int {
835 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
836 return int(r.uint32At(dataIdxOff+4) - r.uint32At(dataIdxOff))
837 }
838
839
840 func (r *Reader) Data(i uint32) []byte {
841 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
842 base := r.h.Offsets[BlkData]
843 off := r.uint32At(dataIdxOff)
844 end := r.uint32At(dataIdxOff + 4)
845 return r.BytesAt(base+off, int(end-off))
846 }
847
848
849 func (r *Reader) NRefName() int {
850 return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize
851 }
852
853
854
855 func (r *Reader) RefName(i int) *RefName {
856 off := r.h.Offsets[BlkRefName] + uint32(i*RefNameSize)
857 return (*RefName)(unsafe.Pointer(&r.b[off]))
858 }
859
860
861 func (r *Reader) ReadOnly() bool {
862 return r.readonly
863 }
864
865
866 func (r *Reader) Flags() uint32 {
867 return r.h.Flags
868 }
869
870 func (r *Reader) Shared() bool { return r.Flags()&ObjFlagShared != 0 }
871 func (r *Reader) NeedNameExpansion() bool { return r.Flags()&ObjFlagNeedNameExpansion != 0 }
872 func (r *Reader) FromAssembly() bool { return r.Flags()&ObjFlagFromAssembly != 0 }
873
View as plain text