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 "github.com/twitchyliquid64/golang-asm/bio"
24 "crypto/sha1"
25 "encoding/binary"
26 "errors"
27 "fmt"
28 "github.com/twitchyliquid64/golang-asm/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 = "\x00go116ld"
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 SymFlagTopFrame
302 )
303
304
305 const (
306 SymFlagUsedInIface = 1 << iota
307 SymFlagItab
308 )
309
310
311 func (s *Sym) NameLen(r *Reader) int {
312 return int(binary.LittleEndian.Uint32(s[:]))
313 }
314
315 func (s *Sym) Name(r *Reader) string {
316 len := binary.LittleEndian.Uint32(s[:])
317 off := binary.LittleEndian.Uint32(s[4:])
318 return r.StringAt(off, len)
319 }
320
321 func (s *Sym) ABI() uint16 { return binary.LittleEndian.Uint16(s[8:]) }
322 func (s *Sym) Type() uint8 { return s[10] }
323 func (s *Sym) Flag() uint8 { return s[11] }
324 func (s *Sym) Flag2() uint8 { return s[12] }
325 func (s *Sym) Siz() uint32 { return binary.LittleEndian.Uint32(s[13:]) }
326 func (s *Sym) Align() uint32 { return binary.LittleEndian.Uint32(s[17:]) }
327
328 func (s *Sym) Dupok() bool { return s.Flag()&SymFlagDupok != 0 }
329 func (s *Sym) Local() bool { return s.Flag()&SymFlagLocal != 0 }
330 func (s *Sym) Typelink() bool { return s.Flag()&SymFlagTypelink != 0 }
331 func (s *Sym) Leaf() bool { return s.Flag()&SymFlagLeaf != 0 }
332 func (s *Sym) NoSplit() bool { return s.Flag()&SymFlagNoSplit != 0 }
333 func (s *Sym) ReflectMethod() bool { return s.Flag()&SymFlagReflectMethod != 0 }
334 func (s *Sym) IsGoType() bool { return s.Flag()&SymFlagGoType != 0 }
335 func (s *Sym) TopFrame() bool { return s.Flag()&SymFlagTopFrame != 0 }
336 func (s *Sym) UsedInIface() bool { return s.Flag2()&SymFlagUsedInIface != 0 }
337 func (s *Sym) IsItab() bool { return s.Flag2()&SymFlagItab != 0 }
338
339 func (s *Sym) SetName(x string, w *Writer) {
340 binary.LittleEndian.PutUint32(s[:], uint32(len(x)))
341 binary.LittleEndian.PutUint32(s[4:], w.stringOff(x))
342 }
343
344 func (s *Sym) SetABI(x uint16) { binary.LittleEndian.PutUint16(s[8:], x) }
345 func (s *Sym) SetType(x uint8) { s[10] = x }
346 func (s *Sym) SetFlag(x uint8) { s[11] = x }
347 func (s *Sym) SetFlag2(x uint8) { s[12] = x }
348 func (s *Sym) SetSiz(x uint32) { binary.LittleEndian.PutUint32(s[13:], x) }
349 func (s *Sym) SetAlign(x uint32) { binary.LittleEndian.PutUint32(s[17:], x) }
350
351 func (s *Sym) Write(w *Writer) { w.Bytes(s[:]) }
352
353
354 func (s *Sym) fromBytes(b []byte) { copy(s[:], b) }
355
356
357 type SymRef struct {
358 PkgIdx uint32
359 SymIdx uint32
360 }
361
362
363 type Hash64Type [Hash64Size]byte
364
365 const Hash64Size = 8
366
367
368 type HashType [HashSize]byte
369
370 const HashSize = sha1.Size
371
372
373
374
375
376
377
378
379
380
381
382 type Reloc [RelocSize]byte
383
384 const RelocSize = 4 + 1 + 1 + 8 + 8
385
386 func (r *Reloc) Off() int32 { return int32(binary.LittleEndian.Uint32(r[:])) }
387 func (r *Reloc) Siz() uint8 { return r[4] }
388 func (r *Reloc) Type() uint8 { return r[5] }
389 func (r *Reloc) Add() int64 { return int64(binary.LittleEndian.Uint64(r[6:])) }
390 func (r *Reloc) Sym() SymRef {
391 return SymRef{binary.LittleEndian.Uint32(r[14:]), binary.LittleEndian.Uint32(r[18:])}
392 }
393
394 func (r *Reloc) SetOff(x int32) { binary.LittleEndian.PutUint32(r[:], uint32(x)) }
395 func (r *Reloc) SetSiz(x uint8) { r[4] = x }
396 func (r *Reloc) SetType(x uint8) { r[5] = x }
397 func (r *Reloc) SetAdd(x int64) { binary.LittleEndian.PutUint64(r[6:], uint64(x)) }
398 func (r *Reloc) SetSym(x SymRef) {
399 binary.LittleEndian.PutUint32(r[14:], x.PkgIdx)
400 binary.LittleEndian.PutUint32(r[18:], x.SymIdx)
401 }
402
403 func (r *Reloc) Set(off int32, size uint8, typ uint8, add int64, sym SymRef) {
404 r.SetOff(off)
405 r.SetSiz(size)
406 r.SetType(typ)
407 r.SetAdd(add)
408 r.SetSym(sym)
409 }
410
411 func (r *Reloc) Write(w *Writer) { w.Bytes(r[:]) }
412
413
414 func (r *Reloc) fromBytes(b []byte) { copy(r[:], b) }
415
416
417
418
419
420
421
422
423 type Aux [AuxSize]byte
424
425 const AuxSize = 1 + 8
426
427
428 const (
429 AuxGotype = iota
430 AuxFuncInfo
431 AuxFuncdata
432 AuxDwarfInfo
433 AuxDwarfLoc
434 AuxDwarfRanges
435 AuxDwarfLines
436
437
438 )
439
440 func (a *Aux) Type() uint8 { return a[0] }
441 func (a *Aux) Sym() SymRef {
442 return SymRef{binary.LittleEndian.Uint32(a[1:]), binary.LittleEndian.Uint32(a[5:])}
443 }
444
445 func (a *Aux) SetType(x uint8) { a[0] = x }
446 func (a *Aux) SetSym(x SymRef) {
447 binary.LittleEndian.PutUint32(a[1:], x.PkgIdx)
448 binary.LittleEndian.PutUint32(a[5:], x.SymIdx)
449 }
450
451 func (a *Aux) Write(w *Writer) { w.Bytes(a[:]) }
452
453
454 func (a *Aux) fromBytes(b []byte) { copy(a[:], b) }
455
456
457
458
459
460
461
462
463
464 type RefFlags [RefFlagsSize]byte
465
466 const RefFlagsSize = 8 + 1 + 1
467
468 func (r *RefFlags) Sym() SymRef {
469 return SymRef{binary.LittleEndian.Uint32(r[:]), binary.LittleEndian.Uint32(r[4:])}
470 }
471 func (r *RefFlags) Flag() uint8 { return r[8] }
472 func (r *RefFlags) Flag2() uint8 { return r[9] }
473
474 func (r *RefFlags) SetSym(x SymRef) {
475 binary.LittleEndian.PutUint32(r[:], x.PkgIdx)
476 binary.LittleEndian.PutUint32(r[4:], x.SymIdx)
477 }
478 func (r *RefFlags) SetFlag(x uint8) { r[8] = x }
479 func (r *RefFlags) SetFlag2(x uint8) { r[9] = x }
480
481 func (r *RefFlags) Write(w *Writer) { w.Bytes(r[:]) }
482
483
484
485
486
487
488
489
490 type RefName [RefNameSize]byte
491
492 const RefNameSize = 8 + stringRefSize
493
494 func (n *RefName) Sym() SymRef {
495 return SymRef{binary.LittleEndian.Uint32(n[:]), binary.LittleEndian.Uint32(n[4:])}
496 }
497 func (n *RefName) Name(r *Reader) string {
498 len := binary.LittleEndian.Uint32(n[8:])
499 off := binary.LittleEndian.Uint32(n[12:])
500 return r.StringAt(off, len)
501 }
502
503 func (n *RefName) SetSym(x SymRef) {
504 binary.LittleEndian.PutUint32(n[:], x.PkgIdx)
505 binary.LittleEndian.PutUint32(n[4:], x.SymIdx)
506 }
507 func (n *RefName) SetName(x string, w *Writer) {
508 binary.LittleEndian.PutUint32(n[8:], uint32(len(x)))
509 binary.LittleEndian.PutUint32(n[12:], w.stringOff(x))
510 }
511
512 func (n *RefName) Write(w *Writer) { w.Bytes(n[:]) }
513
514 type Writer struct {
515 wr *bio.Writer
516 stringMap map[string]uint32
517 off uint32
518 }
519
520 func NewWriter(wr *bio.Writer) *Writer {
521 return &Writer{wr: wr, stringMap: make(map[string]uint32)}
522 }
523
524 func (w *Writer) AddString(s string) {
525 if _, ok := w.stringMap[s]; ok {
526 return
527 }
528 w.stringMap[s] = w.off
529 w.RawString(s)
530 }
531
532 func (w *Writer) stringOff(s string) uint32 {
533 off, ok := w.stringMap[s]
534 if !ok {
535 panic(fmt.Sprintf("writeStringRef: string not added: %q", s))
536 }
537 return off
538 }
539
540 func (w *Writer) StringRef(s string) {
541 w.Uint32(uint32(len(s)))
542 w.Uint32(w.stringOff(s))
543 }
544
545 func (w *Writer) RawString(s string) {
546 w.wr.WriteString(s)
547 w.off += uint32(len(s))
548 }
549
550 func (w *Writer) Bytes(s []byte) {
551 w.wr.Write(s)
552 w.off += uint32(len(s))
553 }
554
555 func (w *Writer) Uint64(x uint64) {
556 var b [8]byte
557 binary.LittleEndian.PutUint64(b[:], x)
558 w.wr.Write(b[:])
559 w.off += 8
560 }
561
562 func (w *Writer) Uint32(x uint32) {
563 var b [4]byte
564 binary.LittleEndian.PutUint32(b[:], x)
565 w.wr.Write(b[:])
566 w.off += 4
567 }
568
569 func (w *Writer) Uint16(x uint16) {
570 var b [2]byte
571 binary.LittleEndian.PutUint16(b[:], x)
572 w.wr.Write(b[:])
573 w.off += 2
574 }
575
576 func (w *Writer) Uint8(x uint8) {
577 w.wr.WriteByte(x)
578 w.off++
579 }
580
581 func (w *Writer) Offset() uint32 {
582 return w.off
583 }
584
585 type Reader struct {
586 b []byte
587 readonly bool
588
589 rd io.ReaderAt
590 start uint32
591 h Header
592 }
593
594 func NewReaderFromBytes(b []byte, readonly bool) *Reader {
595 r := &Reader{b: b, readonly: readonly, rd: bytes.NewReader(b), start: 0}
596 err := r.h.Read(r)
597 if err != nil {
598 return nil
599 }
600 return r
601 }
602
603 func (r *Reader) BytesAt(off uint32, len int) []byte {
604 if len == 0 {
605 return nil
606 }
607 end := int(off) + len
608 return r.b[int(off):end:end]
609 }
610
611 func (r *Reader) uint64At(off uint32) uint64 {
612 b := r.BytesAt(off, 8)
613 return binary.LittleEndian.Uint64(b)
614 }
615
616 func (r *Reader) int64At(off uint32) int64 {
617 return int64(r.uint64At(off))
618 }
619
620 func (r *Reader) uint32At(off uint32) uint32 {
621 b := r.BytesAt(off, 4)
622 return binary.LittleEndian.Uint32(b)
623 }
624
625 func (r *Reader) int32At(off uint32) int32 {
626 return int32(r.uint32At(off))
627 }
628
629 func (r *Reader) uint16At(off uint32) uint16 {
630 b := r.BytesAt(off, 2)
631 return binary.LittleEndian.Uint16(b)
632 }
633
634 func (r *Reader) uint8At(off uint32) uint8 {
635 b := r.BytesAt(off, 1)
636 return b[0]
637 }
638
639 func (r *Reader) StringAt(off uint32, len uint32) string {
640 b := r.b[off : off+len]
641 if r.readonly {
642 return toString(b)
643 }
644 return string(b)
645 }
646
647 func toString(b []byte) string {
648 if len(b) == 0 {
649 return ""
650 }
651
652 var s string
653 hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
654 hdr.Data = unsafe.Pointer(&b[0])
655 hdr.Len = len(b)
656
657 return s
658 }
659
660 func (r *Reader) StringRef(off uint32) string {
661 l := r.uint32At(off)
662 return r.StringAt(r.uint32At(off+4), l)
663 }
664
665 func (r *Reader) Fingerprint() FingerprintType {
666 return r.h.Fingerprint
667 }
668
669 func (r *Reader) Autolib() []ImportedPkg {
670 n := (r.h.Offsets[BlkAutolib+1] - r.h.Offsets[BlkAutolib]) / importedPkgSize
671 s := make([]ImportedPkg, n)
672 off := r.h.Offsets[BlkAutolib]
673 for i := range s {
674 s[i].Pkg = r.StringRef(off)
675 copy(s[i].Fingerprint[:], r.BytesAt(off+stringRefSize, len(s[i].Fingerprint)))
676 off += importedPkgSize
677 }
678 return s
679 }
680
681 func (r *Reader) Pkglist() []string {
682 n := (r.h.Offsets[BlkPkgIdx+1] - r.h.Offsets[BlkPkgIdx]) / stringRefSize
683 s := make([]string, n)
684 off := r.h.Offsets[BlkPkgIdx]
685 for i := range s {
686 s[i] = r.StringRef(off)
687 off += stringRefSize
688 }
689 return s
690 }
691
692 func (r *Reader) NPkg() int {
693 return int(r.h.Offsets[BlkPkgIdx+1]-r.h.Offsets[BlkPkgIdx]) / stringRefSize
694 }
695
696 func (r *Reader) Pkg(i int) string {
697 off := r.h.Offsets[BlkPkgIdx] + uint32(i)*stringRefSize
698 return r.StringRef(off)
699 }
700
701 func (r *Reader) NFile() int {
702 return int(r.h.Offsets[BlkFile+1]-r.h.Offsets[BlkFile]) / stringRefSize
703 }
704
705 func (r *Reader) File(i int) string {
706 off := r.h.Offsets[BlkFile] + uint32(i)*stringRefSize
707 return r.StringRef(off)
708 }
709
710 func (r *Reader) NSym() int {
711 return int(r.h.Offsets[BlkSymdef+1]-r.h.Offsets[BlkSymdef]) / SymSize
712 }
713
714 func (r *Reader) NHashed64def() int {
715 return int(r.h.Offsets[BlkHashed64def+1]-r.h.Offsets[BlkHashed64def]) / SymSize
716 }
717
718 func (r *Reader) NHasheddef() int {
719 return int(r.h.Offsets[BlkHasheddef+1]-r.h.Offsets[BlkHasheddef]) / SymSize
720 }
721
722 func (r *Reader) NNonpkgdef() int {
723 return int(r.h.Offsets[BlkNonpkgdef+1]-r.h.Offsets[BlkNonpkgdef]) / SymSize
724 }
725
726 func (r *Reader) NNonpkgref() int {
727 return int(r.h.Offsets[BlkNonpkgref+1]-r.h.Offsets[BlkNonpkgref]) / SymSize
728 }
729
730
731 func (r *Reader) SymOff(i uint32) uint32 {
732 return r.h.Offsets[BlkSymdef] + uint32(i*SymSize)
733 }
734
735
736 func (r *Reader) Sym(i uint32) *Sym {
737 off := r.SymOff(i)
738 return (*Sym)(unsafe.Pointer(&r.b[off]))
739 }
740
741
742 func (r *Reader) NRefFlags() int {
743 return int(r.h.Offsets[BlkRefFlags+1]-r.h.Offsets[BlkRefFlags]) / RefFlagsSize
744 }
745
746
747
748 func (r *Reader) RefFlags(i int) *RefFlags {
749 off := r.h.Offsets[BlkRefFlags] + uint32(i*RefFlagsSize)
750 return (*RefFlags)(unsafe.Pointer(&r.b[off]))
751 }
752
753
754
755
756 func (r *Reader) Hash64(i uint32) uint64 {
757 off := r.h.Offsets[BlkHash64] + uint32(i*Hash64Size)
758 return r.uint64At(off)
759 }
760
761
762
763
764 func (r *Reader) Hash(i uint32) *HashType {
765 off := r.h.Offsets[BlkHash] + uint32(i*HashSize)
766 return (*HashType)(unsafe.Pointer(&r.b[off]))
767 }
768
769
770 func (r *Reader) NReloc(i uint32) int {
771 relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
772 return int(r.uint32At(relocIdxOff+4) - r.uint32At(relocIdxOff))
773 }
774
775
776 func (r *Reader) RelocOff(i uint32, j int) uint32 {
777 relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
778 relocIdx := r.uint32At(relocIdxOff)
779 return r.h.Offsets[BlkReloc] + (relocIdx+uint32(j))*uint32(RelocSize)
780 }
781
782
783 func (r *Reader) Reloc(i uint32, j int) *Reloc {
784 off := r.RelocOff(i, j)
785 return (*Reloc)(unsafe.Pointer(&r.b[off]))
786 }
787
788
789 func (r *Reader) Relocs(i uint32) []Reloc {
790 off := r.RelocOff(i, 0)
791 n := r.NReloc(i)
792 return (*[1 << 20]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n]
793 }
794
795
796 func (r *Reader) NAux(i uint32) int {
797 auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
798 return int(r.uint32At(auxIdxOff+4) - r.uint32At(auxIdxOff))
799 }
800
801
802 func (r *Reader) AuxOff(i uint32, j int) uint32 {
803 auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
804 auxIdx := r.uint32At(auxIdxOff)
805 return r.h.Offsets[BlkAux] + (auxIdx+uint32(j))*uint32(AuxSize)
806 }
807
808
809 func (r *Reader) Aux(i uint32, j int) *Aux {
810 off := r.AuxOff(i, j)
811 return (*Aux)(unsafe.Pointer(&r.b[off]))
812 }
813
814
815 func (r *Reader) Auxs(i uint32) []Aux {
816 off := r.AuxOff(i, 0)
817 n := r.NAux(i)
818 return (*[1 << 20]Aux)(unsafe.Pointer(&r.b[off]))[:n:n]
819 }
820
821
822 func (r *Reader) DataOff(i uint32) uint32 {
823 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
824 return r.h.Offsets[BlkData] + r.uint32At(dataIdxOff)
825 }
826
827
828 func (r *Reader) DataSize(i uint32) int {
829 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
830 return int(r.uint32At(dataIdxOff+4) - r.uint32At(dataIdxOff))
831 }
832
833
834 func (r *Reader) Data(i uint32) []byte {
835 dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
836 base := r.h.Offsets[BlkData]
837 off := r.uint32At(dataIdxOff)
838 end := r.uint32At(dataIdxOff + 4)
839 return r.BytesAt(base+off, int(end-off))
840 }
841
842
843 func (r *Reader) PcdataBase() uint32 {
844 return r.h.Offsets[BlkPcdata]
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