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 "cmd/internal/bio"
23 "crypto/sha1"
24 "encoding/binary"
25 "errors"
26 "fmt"
27 "internal/unsafeheader"
28 "unsafe"
29 )
30
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 const stringRefSize = 8
169
170 type FingerprintType [8]byte
171
172 func (fp FingerprintType) IsZero() bool { return fp == FingerprintType{} }
173
174
175 const (
176 PkgIdxNone = (1<<31 - 1) - iota
177 PkgIdxHashed64
178 PkgIdxHashed
179 PkgIdxBuiltin
180 PkgIdxSelf
181 PkgIdxInvalid = 0
182
183 )
184
185
186 const (
187 BlkAutolib = iota
188 BlkPkgIdx
189 BlkFile
190 BlkSymdef
191 BlkHashed64def
192 BlkHasheddef
193 BlkNonpkgdef
194 BlkNonpkgref
195 BlkRefFlags
196 BlkHash64
197 BlkHash
198 BlkRelocIdx
199 BlkAuxIdx
200 BlkDataIdx
201 BlkReloc
202 BlkAux
203 BlkData
204 BlkRefName
205 BlkEnd
206 NBlk
207 )
208
209
210
211 type Header struct {
212 Magic string
213 Fingerprint FingerprintType
214 Flags uint32
215 Offsets [NBlk]uint32
216 }
217
218 const Magic = "\x00go118ld"
219
220 func (h *Header) Write(w *Writer) {
221 w.RawString(h.Magic)
222 w.Bytes(h.Fingerprint[:])
223 w.Uint32(h.Flags)
224 for _, x := range h.Offsets {
225 w.Uint32(x)
226 }
227 }
228
229 func (h *Header) Read(r *Reader) error {
230 b := r.BytesAt(0, len(Magic))
231 h.Magic = string(b)
232 if h.Magic != Magic {
233 return errors.New("wrong magic, not a Go object file")
234 }
235 off := uint32(len(h.Magic))
236 copy(h.Fingerprint[:], r.BytesAt(off, len(h.Fingerprint)))
237 off += 8
238 h.Flags = r.uint32At(off)
239 off += 4
240 for i := range h.Offsets {
241 h.Offsets[i] = r.uint32At(off)
242 off += 4
243 }
244 return nil
245 }
246
247 func (h *Header) Size() int {
248 return len(h.Magic) + 4 + 4*len(h.Offsets)
249 }
250
251
252 type ImportedPkg struct {
253 Pkg string
254 Fingerprint FingerprintType
255 }
256
257 const importedPkgSize = stringRefSize + 8
258
259 func (p *ImportedPkg) Write(w *Writer) {
260 w.StringRef(p.Pkg)
261 w.Bytes(p.Fingerprint[:])
262 }
263
264
265
266
267
268
269
270
271
272
273
274
275
276 type Sym [SymSize]byte
277
278 const SymSize = stringRefSize + 2 + 1 + 1 + 1 + 4 + 4
279
280 const SymABIstatic = ^uint16(0)
281
282 const (
283 ObjFlagShared = 1 << iota
284 ObjFlagNeedNameExpansion
285 ObjFlagFromAssembly
286 )
287
288
289 const (
290 SymFlagDupok = 1 << iota
291 SymFlagLocal
292 SymFlagTypelink
293 SymFlagLeaf
294 SymFlagNoSplit
295 SymFlagReflectMethod
296 SymFlagGoType
297 )
298
299
300 const (
301 SymFlagUsedInIface = 1 << iota
302 SymFlagItab
303 SymFlagDict
304 )
305
306
307 func (s *Sym) NameLen(r *Reader) int {
308 return int(binary.LittleEndian.Uint32(s[:]))
309 }
310
311 func (s *Sym) Name(r *Reader) string {
312 len := binary.LittleEndian.Uint32(s[:])
313 off := binary.LittleEndian.Uint32(s[4:])
314 return r.StringAt(off, len)
315 }
316
317 func (s *Sym) ABI() uint16 { return binary.LittleEndian.Uint16(s[8:]) }
318 func (s *Sym) Type() uint8 { return s[10] }
319 func (s *Sym) Flag() uint8 { return s[11] }
320 func (s *Sym) Flag2() uint8 { return s[12] }
321 func (s *Sym) Siz() uint32 { return binary.LittleEndian.Uint32(s[13:]) }
322 func (s *Sym) Align() uint32 { return binary.LittleEndian.Uint32(s[17:]) }
323
324 func (s *Sym) Dupok() bool { return s.Flag()&SymFlagDupok != 0 }
325 func (s *Sym) Local() bool { return s.Flag()&SymFlagLocal != 0 }
326 func (s *Sym) Typelink() bool { return s.Flag()&SymFlagTypelink != 0 }
327 func (s *Sym) Leaf() bool { return s.Flag()&SymFlagLeaf != 0 }
328 func (s *Sym) NoSplit() bool { return s.Flag()&SymFlagNoSplit != 0 }
329 func (s *Sym) ReflectMethod() bool { return s.Flag()&SymFlagReflectMethod != 0 }
330 func (s *Sym) IsGoType() bool { return s.Flag()&SymFlagGoType != 0 }
331 func (s *Sym) UsedInIface() bool { return s.Flag2()&SymFlagUsedInIface != 0 }
332 func (s *Sym) IsItab() bool { return s.Flag2()&SymFlagItab != 0 }
333 func (s *Sym) IsDict() bool { return s.Flag2()&SymFlagDict != 0 }
334
335 func (s *Sym) SetName(x string, w *Writer) {
336 binary.LittleEndian.PutUint32(s[:], uint32(len(x)))
337 binary.LittleEndian.PutUint32(s[4:], w.stringOff(x))
338 }
339
340 func (s *Sym) SetABI(x uint16) { binary.LittleEndian.PutUint16(s[8:], x) }
341 func (s *Sym) SetType(x uint8) { s[10] = x }
342 func (s *Sym) SetFlag(x uint8) { s[11] = x }
343 func (s *Sym) SetFlag2(x uint8) { s[12] = x }
344 func (s *Sym) SetSiz(x uint32) { binary.LittleEndian.PutUint32(s[13:], x) }
345 func (s *Sym) SetAlign(x uint32) { binary.LittleEndian.PutUint32(s[17:], x) }
346
347 func (s *Sym) Write(w *Writer) { w.Bytes(s[:]) }
348
349
350 func (s *Sym) fromBytes(b []byte) { copy(s[:], b) }
351
352
353 type SymRef struct {
354 PkgIdx uint32
355 SymIdx uint32
356 }
357
358 func (s SymRef) IsZero() bool { return s == SymRef{} }
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 start uint32
596 h Header
597 }
598
599 func NewReaderFromBytes(b []byte, readonly bool) *Reader {
600 r := &Reader{b: b, readonly: readonly, start: 0}
601 err := r.h.Read(r)
602 if err != nil {
603 return nil
604 }
605 return r
606 }
607
608 func (r *Reader) BytesAt(off uint32, len int) []byte {
609 if len == 0 {
610 return nil
611 }
612 end := int(off) + len
613 return r.b[int(off):end:end]
614 }
615
616 func (r *Reader) uint64At(off uint32) uint64 {
617 b := r.BytesAt(off, 8)
618 return binary.LittleEndian.Uint64(b)
619 }
620
621 func (r *Reader) int64At(off uint32) int64 {
622 return int64(r.uint64At(off))
623 }
624
625 func (r *Reader) uint32At(off uint32) uint32 {
626 b := r.BytesAt(off, 4)
627 return binary.LittleEndian.Uint32(b)
628 }
629
630 func (r *Reader) int32At(off uint32) int32 {
631 return int32(r.uint32At(off))
632 }
633
634 func (r *Reader) uint16At(off uint32) uint16 {
635 b := r.BytesAt(off, 2)
636 return binary.LittleEndian.Uint16(b)
637 }
638
639 func (r *Reader) uint8At(off uint32) uint8 {
640 b := r.BytesAt(off, 1)
641 return b[0]
642 }
643
644 func (r *Reader) StringAt(off uint32, len uint32) string {
645 b := r.b[off : off+len]
646 if r.readonly {
647 return toString(b)
648 }
649 return string(b)
650 }
651
652 func toString(b []byte) string {
653 if len(b) == 0 {
654 return ""
655 }
656
657 var s string
658 hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
659 hdr.Data = unsafe.Pointer(&b[0])
660 hdr.Len = len(b)
661
662 return s
663 }
664
665 func (r *Reader) StringRef(off uint32) string {
666 l := r.uint32At(off)
667 return r.StringAt(r.uint32At(off+4), l)
668 }
669
670 func (r *Reader) Fingerprint() FingerprintType {
671 return r.h.Fingerprint
672 }
673
674 func (r *Reader) Autolib() []ImportedPkg {
675 n := (r.h.Offsets[BlkAutolib+1] - r.h.Offsets[BlkAutolib]) / importedPkgSize
676 s := make([]ImportedPkg, n)
677 off := r.h.Offsets[BlkAutolib]
678 for i := range s {
679 s[i].Pkg = r.StringRef(off)
680 copy(s[i].Fingerprint[:], r.BytesAt(off+stringRefSize, len(s[i].Fingerprint)))
681 off += importedPkgSize
682 }
683 return s
684 }
685
686 func (r *Reader) Pkglist() []string {
687 n := (r.h.Offsets[BlkPkgIdx+1] - r.h.Offsets[BlkPkgIdx]) / stringRefSize
688 s := make([]string, n)
689 off := r.h.Offsets[BlkPkgIdx]
690 for i := range s {
691 s[i] = r.StringRef(off)
692 off += stringRefSize
693 }
694 return s
695 }
696
697 func (r *Reader) NPkg() int {
698 return int(r.h.Offsets[BlkPkgIdx+1]-r.h.Offsets[BlkPkgIdx]) / stringRefSize
699 }
700
701 func (r *Reader) Pkg(i int) string {
702 off := r.h.Offsets[BlkPkgIdx] + uint32(i)*stringRefSize
703 return r.StringRef(off)
704 }
705
706 func (r *Reader) NFile() int {
707 return int(r.h.Offsets[BlkFile+1]-r.h.Offsets[BlkFile]) / stringRefSize
708 }
709
710 func (r *Reader) File(i int) string {
711 off := r.h.Offsets[BlkFile] + uint32(i)*stringRefSize
712 return r.StringRef(off)
713 }
714
715 func (r *Reader) NSym() int {
716 return int(r.h.Offsets[BlkSymdef+1]-r.h.Offsets[BlkSymdef]) / SymSize
717 }
718
719 func (r *Reader) NHashed64def() int {
720 return int(r.h.Offsets[BlkHashed64def+1]-r.h.Offsets[BlkHashed64def]) / SymSize
721 }
722
723 func (r *Reader) NHasheddef() int {
724 return int(r.h.Offsets[BlkHasheddef+1]-r.h.Offsets[BlkHasheddef]) / SymSize
725 }
726
727 func (r *Reader) NNonpkgdef() int {
728 return int(r.h.Offsets[BlkNonpkgdef+1]-r.h.Offsets[BlkNonpkgdef]) / SymSize
729 }
730
731 func (r *Reader) NNonpkgref() int {
732 return int(r.h.Offsets[BlkNonpkgref+1]-r.h.Offsets[BlkNonpkgref]) / SymSize
733 }
734
735
736 func (r *Reader) SymOff(i uint32) uint32 {
737 return r.h.Offsets[BlkSymdef] + uint32(i*SymSize)
738 }
739
740
741 func (r *Reader) Sym(i uint32) *Sym {
742 off := r.SymOff(i)
743 return (*Sym)(unsafe.Pointer(&r.b[off]))
744 }
745
746
747 func (r *Reader) NRefFlags() int {
748 return int(r.h.Offsets[BlkRefFlags+1]-r.h.Offsets[BlkRefFlags]) / RefFlagsSize
749 }
750
751
752
753 func (r *Reader) RefFlags(i int) *RefFlags {
754 off := r.h.Offsets[BlkRefFlags] + uint32(i*RefFlagsSize)
755 return (*RefFlags)(unsafe.Pointer(&r.b[off]))
756 }
757
758
759
760
761 func (r *Reader) Hash64(i uint32) uint64 {
762 off := r.h.Offsets[BlkHash64] + uint32(i*Hash64Size)
763 return r.uint64At(off)
764 }
765
766
767
768
769 func (r *Reader) Hash(i uint32) *HashType {
770 off := r.h.Offsets[BlkHash] + uint32(i*HashSize)
771 return (*HashType)(unsafe.Pointer(&r.b[off]))
772 }
773
774
775 func (r *Reader) NReloc(i uint32) int {
776 relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
777 return int(r.uint32At(relocIdxOff+4) - r.uint32At(relocIdxOff))
778 }
779
780
781 func (r *Reader) RelocOff(i uint32, j int) uint32 {
782 relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
783 relocIdx := r.uint32At(relocIdxOff)
784 return r.h.Offsets[BlkReloc] + (relocIdx+uint32(j))*uint32(RelocSize)
785 }
786
787
788 func (r *Reader) Reloc(i uint32, j int) *Reloc {
789 off := r.RelocOff(i, j)
790 return (*Reloc)(unsafe.Pointer(&r.b[off]))
791 }
792
793
794 func (r *Reader) Relocs(i uint32) []Reloc {
795 off := r.RelocOff(i, 0)
796 n := r.NReloc(i)
797 return (*[huge]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n]
798 }
799
800
801 func (r *Reader) NAux(i uint32) int {
802 auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
803 return int(r.uint32At(auxIdxOff+4) - r.uint32At(auxIdxOff))
804 }
805
806
807 func (r *Reader) AuxOff(i uint32, j int) uint32 {
808 auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
809 auxIdx := r.uint32At(auxIdxOff)
810 return r.h.Offsets[BlkAux] + (auxIdx+uint32(j))*uint32(AuxSize)
811 }
812
813
814 func (r *Reader) Aux(i uint32, j int) *Aux {
815 off := r.AuxOff(i, j)
816 return (*Aux)(unsafe.Pointer(&r.b[off]))
817 }
818
819
820 func (r *Reader) Auxs(i uint32) []Aux {
821 off := r.AuxOff(i, 0)
822 n := r.NAux(i)
823 return (*[huge]Aux)(unsafe.Pointer(&r.b[off]))[:n:n]
824 }
825
826
827 func (r *Reader) DataOff(i uint32) uint32 {
828 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
829 return r.h.Offsets[BlkData] + r.uint32At(dataIdxOff)
830 }
831
832
833 func (r *Reader) DataSize(i uint32) int {
834 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
835 return int(r.uint32At(dataIdxOff+4) - r.uint32At(dataIdxOff))
836 }
837
838
839 func (r *Reader) Data(i uint32) []byte {
840 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
841 base := r.h.Offsets[BlkData]
842 off := r.uint32At(dataIdxOff)
843 end := r.uint32At(dataIdxOff + 4)
844 return r.BytesAt(base+off, int(end-off))
845 }
846
847
848 func (r *Reader) NRefName() int {
849 return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize
850 }
851
852
853
854 func (r *Reader) RefName(i int) *RefName {
855 off := r.h.Offsets[BlkRefName] + uint32(i*RefNameSize)
856 return (*RefName)(unsafe.Pointer(&r.b[off]))
857 }
858
859
860 func (r *Reader) ReadOnly() bool {
861 return r.readonly
862 }
863
864
865 func (r *Reader) Flags() uint32 {
866 return r.h.Flags
867 }
868
869 func (r *Reader) Shared() bool { return r.Flags()&ObjFlagShared != 0 }
870 func (r *Reader) NeedNameExpansion() bool { return r.Flags()&ObjFlagNeedNameExpansion != 0 }
871 func (r *Reader) FromAssembly() bool { return r.Flags()&ObjFlagFromAssembly != 0 }
872
View as plain text