]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/internal/goobj/objfile.go
all: implement wasmimport directive
[gostls13.git] / src / cmd / internal / goobj / objfile.go
1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // This package defines the Go object file format, and provide "low-level" functions
6 // for reading and writing object files.
7
8 // The object file is understood by the compiler, assembler, linker, and tools. They
9 // have "high level" code that operates on object files, handling application-specific
10 // logics, and use this package for the actual reading and writing. Specifically, the
11 // code below:
12 //
13 // - cmd/internal/obj/objfile.go (used by cmd/asm and cmd/compile)
14 // - cmd/internal/objfile/goobj.go (used cmd/nm, cmd/objdump)
15 // - cmd/link/internal/loader package (used by cmd/link)
16 //
17 // If the object file format changes, they may (or may not) need to change.
18
19 package goobj
20
21 import (
22         "cmd/internal/bio"
23         "encoding/binary"
24         "errors"
25         "fmt"
26         "internal/unsafeheader"
27         "unsafe"
28 )
29
30 // New object file format.
31 //
32 //    Header struct {
33 //       Magic       [...]byte   // "\x00go120ld"
34 //       Fingerprint [8]byte
35 //       Flags       uint32
36 //       Offsets     [...]uint32 // byte offset of each block below
37 //    }
38 //
39 //    Strings [...]struct {
40 //       Data [...]byte
41 //    }
42 //
43 //    Autolib  [...]struct { // imported packages (for file loading)
44 //       Pkg         string
45 //       Fingerprint [8]byte
46 //    }
47 //
48 //    PkgIndex [...]string // referenced packages by index
49 //
50 //    Files [...]string
51 //
52 //    SymbolDefs [...]struct {
53 //       Name  string
54 //       ABI   uint16
55 //       Type  uint8
56 //       Flag  uint8
57 //       Flag2 uint8
58 //       Size  uint32
59 //    }
60 //    Hashed64Defs [...]struct { // short hashed (content-addressable) symbol definitions
61 //       ... // same as SymbolDefs
62 //    }
63 //    HashedDefs [...]struct { // hashed (content-addressable) symbol definitions
64 //       ... // same as SymbolDefs
65 //    }
66 //    NonPkgDefs [...]struct { // non-pkg symbol definitions
67 //       ... // same as SymbolDefs
68 //    }
69 //    NonPkgRefs [...]struct { // non-pkg symbol references
70 //       ... // same as SymbolDefs
71 //    }
72 //
73 //    RefFlags [...]struct { // referenced symbol flags
74 //       Sym   symRef
75 //       Flag  uint8
76 //       Flag2 uint8
77 //    }
78 //
79 //    Hash64 [...][8]byte
80 //    Hash   [...][N]byte
81 //
82 //    RelocIndex [...]uint32 // index to Relocs
83 //    AuxIndex   [...]uint32 // index to Aux
84 //    DataIndex  [...]uint32 // offset to Data
85 //
86 //    Relocs [...]struct {
87 //       Off  int32
88 //       Size uint8
89 //       Type uint16
90 //       Add  int64
91 //       Sym  symRef
92 //    }
93 //
94 //    Aux [...]struct {
95 //       Type uint8
96 //       Sym  symRef
97 //    }
98 //
99 //    Data   [...]byte
100 //
101 //    // blocks only used by tools (objdump, nm)
102 //
103 //    RefNames [...]struct { // referenced symbol names
104 //       Sym  symRef
105 //       Name string
106 //       // TODO: include ABI version as well?
107 //    }
108 //
109 // string is encoded as is a uint32 length followed by a uint32 offset
110 // that points to the corresponding string bytes.
111 //
112 // symRef is struct { PkgIdx, SymIdx uint32 }.
113 //
114 // Slice type (e.g. []symRef) is encoded as a length prefix (uint32)
115 // followed by that number of elements.
116 //
117 // The types below correspond to the encoded data structure in the
118 // object file.
119
120 // Symbol indexing.
121 //
122 // Each symbol is referenced with a pair of indices, { PkgIdx, SymIdx },
123 // as the symRef struct above.
124 //
125 // PkgIdx is either a predeclared index (see PkgIdxNone below) or
126 // an index of an imported package. For the latter case, PkgIdx is the
127 // index of the package in the PkgIndex array. 0 is an invalid index.
128 //
129 // SymIdx is the index of the symbol in the given package.
130 // - If PkgIdx is PkgIdxSelf, SymIdx is the index of the symbol in the
131 //   SymbolDefs array.
132 // - If PkgIdx is PkgIdxHashed64, SymIdx is the index of the symbol in the
133 //   Hashed64Defs array.
134 // - If PkgIdx is PkgIdxHashed, SymIdx is the index of the symbol in the
135 //   HashedDefs array.
136 // - If PkgIdx is PkgIdxNone, SymIdx is the index of the symbol in the
137 //   NonPkgDefs array (could naturally overflow to NonPkgRefs array).
138 // - Otherwise, SymIdx is the index of the symbol in some other package's
139 //   SymbolDefs array.
140 //
141 // {0, 0} represents a nil symbol. Otherwise PkgIdx should not be 0.
142 //
143 // Hash contains the content hashes of content-addressable symbols, of
144 // which PkgIdx is PkgIdxHashed, in the same order of HashedDefs array.
145 // Hash64 is similar, for PkgIdxHashed64 symbols.
146 //
147 // RelocIndex, AuxIndex, and DataIndex contains indices/offsets to
148 // Relocs/Aux/Data blocks, one element per symbol, first for all the
149 // defined symbols, then all the defined hashed and non-package symbols,
150 // in the same order of SymbolDefs/Hashed64Defs/HashedDefs/NonPkgDefs
151 // arrays. For N total defined symbols, the array is of length N+1. The
152 // last element is the total number of relocations (aux symbols, data
153 // blocks, etc.).
154 //
155 // They can be accessed by index. For the i-th symbol, its relocations
156 // are the RelocIndex[i]-th (inclusive) to RelocIndex[i+1]-th (exclusive)
157 // elements in the Relocs array. Aux/Data are likewise. (The index is
158 // 0-based.)
159
160 // Auxiliary symbols.
161 //
162 // Each symbol may (or may not) be associated with a number of auxiliary
163 // symbols. They are described in the Aux block. See Aux struct below.
164 // Currently a symbol's Gotype, FuncInfo, and associated DWARF symbols
165 // are auxiliary symbols.
166
167 const stringRefSize = 8 // two uint32s
168
169 type FingerprintType [8]byte
170
171 func (fp FingerprintType) IsZero() bool { return fp == FingerprintType{} }
172
173 // Package Index.
174 const (
175         PkgIdxNone     = (1<<31 - 1) - iota // Non-package symbols
176         PkgIdxHashed64                      // Short hashed (content-addressable) symbols
177         PkgIdxHashed                        // Hashed (content-addressable) symbols
178         PkgIdxBuiltin                       // Predefined runtime symbols (ex: runtime.newobject)
179         PkgIdxSelf                          // Symbols defined in the current package
180         PkgIdxSpecial  = PkgIdxSelf         // Indices above it has special meanings
181         PkgIdxInvalid  = 0
182         // The index of other referenced packages starts from 1.
183 )
184
185 // Blocks
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 // File header.
210 // TODO: probably no need to export this.
211 type Header struct {
212         Magic       string
213         Fingerprint FingerprintType
214         Flags       uint32
215         Offsets     [NBlk]uint32
216 }
217
218 const Magic = "\x00go120ld"
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 // Autolib
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 // Symbol definition.
265 //
266 // Serialized format:
267 //
268 //      Sym struct {
269 //         Name  string
270 //         ABI   uint16
271 //         Type  uint8
272 //         Flag  uint8
273 //         Flag2 uint8
274 //         Siz   uint32
275 //         Align uint32
276 //      }
277 type Sym [SymSize]byte
278
279 const SymSize = stringRefSize + 2 + 1 + 1 + 1 + 4 + 4
280
281 const SymABIstatic = ^uint16(0)
282
283 const (
284         ObjFlagShared       = 1 << iota // this object is built with -shared
285         _                               // was ObjFlagNeedNameExpansion
286         ObjFlagFromAssembly             // object is from asm src, not go
287         ObjFlagUnlinkable               // unlinkable package (linker will emit an error)
288 )
289
290 // Sym.Flag
291 const (
292         SymFlagDupok = 1 << iota
293         SymFlagLocal
294         SymFlagTypelink
295         SymFlagLeaf
296         SymFlagNoSplit
297         SymFlagReflectMethod
298         SymFlagGoType
299 )
300
301 // Sym.Flag2
302 const (
303         SymFlagUsedInIface = 1 << iota
304         SymFlagItab
305         SymFlagDict
306         SymFlagPkgInit
307 )
308
309 // Returns the length of the name of the symbol.
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 func (s *Sym) IsDict() bool        { return s.Flag2()&SymFlagDict != 0 }
337 func (s *Sym) IsPkgInit() bool     { return s.Flag2()&SymFlagPkgInit != 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 // for testing
354 func (s *Sym) fromBytes(b []byte) { copy(s[:], b) }
355
356 // Symbol reference.
357 type SymRef struct {
358         PkgIdx uint32
359         SymIdx uint32
360 }
361
362 func (s SymRef) IsZero() bool { return s == SymRef{} }
363
364 // Hash64
365 type Hash64Type [Hash64Size]byte
366
367 const Hash64Size = 8
368
369 // Hash
370 type HashType [HashSize]byte
371
372 const HashSize = 16 // truncated SHA256
373
374 // Relocation.
375 //
376 // Serialized format:
377 //
378 //      Reloc struct {
379 //         Off  int32
380 //         Siz  uint8
381 //         Type uint16
382 //         Add  int64
383 //         Sym  SymRef
384 //      }
385 type Reloc [RelocSize]byte
386
387 const RelocSize = 4 + 1 + 2 + 8 + 8
388
389 func (r *Reloc) Off() int32   { return int32(binary.LittleEndian.Uint32(r[:])) }
390 func (r *Reloc) Siz() uint8   { return r[4] }
391 func (r *Reloc) Type() uint16 { return binary.LittleEndian.Uint16(r[5:]) }
392 func (r *Reloc) Add() int64   { return int64(binary.LittleEndian.Uint64(r[7:])) }
393 func (r *Reloc) Sym() SymRef {
394         return SymRef{binary.LittleEndian.Uint32(r[15:]), binary.LittleEndian.Uint32(r[19:])}
395 }
396
397 func (r *Reloc) SetOff(x int32)   { binary.LittleEndian.PutUint32(r[:], uint32(x)) }
398 func (r *Reloc) SetSiz(x uint8)   { r[4] = x }
399 func (r *Reloc) SetType(x uint16) { binary.LittleEndian.PutUint16(r[5:], x) }
400 func (r *Reloc) SetAdd(x int64)   { binary.LittleEndian.PutUint64(r[7:], uint64(x)) }
401 func (r *Reloc) SetSym(x SymRef) {
402         binary.LittleEndian.PutUint32(r[15:], x.PkgIdx)
403         binary.LittleEndian.PutUint32(r[19:], x.SymIdx)
404 }
405
406 func (r *Reloc) Set(off int32, size uint8, typ uint16, add int64, sym SymRef) {
407         r.SetOff(off)
408         r.SetSiz(size)
409         r.SetType(typ)
410         r.SetAdd(add)
411         r.SetSym(sym)
412 }
413
414 func (r *Reloc) Write(w *Writer) { w.Bytes(r[:]) }
415
416 // for testing
417 func (r *Reloc) fromBytes(b []byte) { copy(r[:], b) }
418
419 // Aux symbol info.
420 //
421 // Serialized format:
422 //
423 //      Aux struct {
424 //         Type uint8
425 //         Sym  SymRef
426 //      }
427 type Aux [AuxSize]byte
428
429 const AuxSize = 1 + 8
430
431 // Aux Type
432 const (
433         AuxGotype = iota
434         AuxFuncInfo
435         AuxFuncdata
436         AuxDwarfInfo
437         AuxDwarfLoc
438         AuxDwarfRanges
439         AuxDwarfLines
440         AuxPcsp
441         AuxPcfile
442         AuxPcline
443         AuxPcinline
444         AuxPcdata
445         AuxWasmImport
446 )
447
448 func (a *Aux) Type() uint8 { return a[0] }
449 func (a *Aux) Sym() SymRef {
450         return SymRef{binary.LittleEndian.Uint32(a[1:]), binary.LittleEndian.Uint32(a[5:])}
451 }
452
453 func (a *Aux) SetType(x uint8) { a[0] = x }
454 func (a *Aux) SetSym(x SymRef) {
455         binary.LittleEndian.PutUint32(a[1:], x.PkgIdx)
456         binary.LittleEndian.PutUint32(a[5:], x.SymIdx)
457 }
458
459 func (a *Aux) Write(w *Writer) { w.Bytes(a[:]) }
460
461 // for testing
462 func (a *Aux) fromBytes(b []byte) { copy(a[:], b) }
463
464 // Referenced symbol flags.
465 //
466 // Serialized format:
467 //
468 //      RefFlags struct {
469 //         Sym   symRef
470 //         Flag  uint8
471 //         Flag2 uint8
472 //      }
473 type RefFlags [RefFlagsSize]byte
474
475 const RefFlagsSize = 8 + 1 + 1
476
477 func (r *RefFlags) Sym() SymRef {
478         return SymRef{binary.LittleEndian.Uint32(r[:]), binary.LittleEndian.Uint32(r[4:])}
479 }
480 func (r *RefFlags) Flag() uint8  { return r[8] }
481 func (r *RefFlags) Flag2() uint8 { return r[9] }
482
483 func (r *RefFlags) SetSym(x SymRef) {
484         binary.LittleEndian.PutUint32(r[:], x.PkgIdx)
485         binary.LittleEndian.PutUint32(r[4:], x.SymIdx)
486 }
487 func (r *RefFlags) SetFlag(x uint8)  { r[8] = x }
488 func (r *RefFlags) SetFlag2(x uint8) { r[9] = x }
489
490 func (r *RefFlags) Write(w *Writer) { w.Bytes(r[:]) }
491
492 // Used to construct an artificially large array type when reading an
493 // item from the object file relocs section or aux sym section (needs
494 // to work on 32-bit as well as 64-bit). See issue 41621.
495 const huge = (1<<31 - 1) / RelocSize
496
497 // Referenced symbol name.
498 //
499 // Serialized format:
500 //
501 //      RefName struct {
502 //         Sym  symRef
503 //         Name string
504 //      }
505 type RefName [RefNameSize]byte
506
507 const RefNameSize = 8 + stringRefSize
508
509 func (n *RefName) Sym() SymRef {
510         return SymRef{binary.LittleEndian.Uint32(n[:]), binary.LittleEndian.Uint32(n[4:])}
511 }
512 func (n *RefName) Name(r *Reader) string {
513         len := binary.LittleEndian.Uint32(n[8:])
514         off := binary.LittleEndian.Uint32(n[12:])
515         return r.StringAt(off, len)
516 }
517
518 func (n *RefName) SetSym(x SymRef) {
519         binary.LittleEndian.PutUint32(n[:], x.PkgIdx)
520         binary.LittleEndian.PutUint32(n[4:], x.SymIdx)
521 }
522 func (n *RefName) SetName(x string, w *Writer) {
523         binary.LittleEndian.PutUint32(n[8:], uint32(len(x)))
524         binary.LittleEndian.PutUint32(n[12:], w.stringOff(x))
525 }
526
527 func (n *RefName) Write(w *Writer) { w.Bytes(n[:]) }
528
529 type Writer struct {
530         wr        *bio.Writer
531         stringMap map[string]uint32
532         off       uint32 // running offset
533
534         b [8]byte // scratch space for writing bytes
535 }
536
537 func NewWriter(wr *bio.Writer) *Writer {
538         return &Writer{wr: wr, stringMap: make(map[string]uint32)}
539 }
540
541 func (w *Writer) AddString(s string) {
542         if _, ok := w.stringMap[s]; ok {
543                 return
544         }
545         w.stringMap[s] = w.off
546         w.RawString(s)
547 }
548
549 func (w *Writer) stringOff(s string) uint32 {
550         off, ok := w.stringMap[s]
551         if !ok {
552                 panic(fmt.Sprintf("writeStringRef: string not added: %q", s))
553         }
554         return off
555 }
556
557 func (w *Writer) StringRef(s string) {
558         w.Uint32(uint32(len(s)))
559         w.Uint32(w.stringOff(s))
560 }
561
562 func (w *Writer) RawString(s string) {
563         w.wr.WriteString(s)
564         w.off += uint32(len(s))
565 }
566
567 func (w *Writer) Bytes(s []byte) {
568         w.wr.Write(s)
569         w.off += uint32(len(s))
570 }
571
572 func (w *Writer) Uint64(x uint64) {
573         binary.LittleEndian.PutUint64(w.b[:], x)
574         w.wr.Write(w.b[:])
575         w.off += 8
576 }
577
578 func (w *Writer) Uint32(x uint32) {
579         binary.LittleEndian.PutUint32(w.b[:4], x)
580         w.wr.Write(w.b[:4])
581         w.off += 4
582 }
583
584 func (w *Writer) Uint16(x uint16) {
585         binary.LittleEndian.PutUint16(w.b[:2], x)
586         w.wr.Write(w.b[:2])
587         w.off += 2
588 }
589
590 func (w *Writer) Uint8(x uint8) {
591         w.wr.WriteByte(x)
592         w.off++
593 }
594
595 func (w *Writer) Offset() uint32 {
596         return w.off
597 }
598
599 type Reader struct {
600         b        []byte // mmapped bytes, if not nil
601         readonly bool   // whether b is backed with read-only memory
602
603         start uint32
604         h     Header // keep block offsets
605 }
606
607 func NewReaderFromBytes(b []byte, readonly bool) *Reader {
608         r := &Reader{b: b, readonly: readonly, start: 0}
609         err := r.h.Read(r)
610         if err != nil {
611                 return nil
612         }
613         return r
614 }
615
616 func (r *Reader) BytesAt(off uint32, len int) []byte {
617         if len == 0 {
618                 return nil
619         }
620         end := int(off) + len
621         return r.b[int(off):end:end]
622 }
623
624 func (r *Reader) uint64At(off uint32) uint64 {
625         b := r.BytesAt(off, 8)
626         return binary.LittleEndian.Uint64(b)
627 }
628
629 func (r *Reader) int64At(off uint32) int64 {
630         return int64(r.uint64At(off))
631 }
632
633 func (r *Reader) uint32At(off uint32) uint32 {
634         b := r.BytesAt(off, 4)
635         return binary.LittleEndian.Uint32(b)
636 }
637
638 func (r *Reader) int32At(off uint32) int32 {
639         return int32(r.uint32At(off))
640 }
641
642 func (r *Reader) uint16At(off uint32) uint16 {
643         b := r.BytesAt(off, 2)
644         return binary.LittleEndian.Uint16(b)
645 }
646
647 func (r *Reader) uint8At(off uint32) uint8 {
648         b := r.BytesAt(off, 1)
649         return b[0]
650 }
651
652 func (r *Reader) StringAt(off uint32, len uint32) string {
653         b := r.b[off : off+len]
654         if r.readonly {
655                 return toString(b) // backed by RO memory, ok to make unsafe string
656         }
657         return string(b)
658 }
659
660 func toString(b []byte) string {
661         if len(b) == 0 {
662                 return ""
663         }
664
665         var s string
666         hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
667         hdr.Data = unsafe.Pointer(&b[0])
668         hdr.Len = len(b)
669
670         return s
671 }
672
673 func (r *Reader) StringRef(off uint32) string {
674         l := r.uint32At(off)
675         return r.StringAt(r.uint32At(off+4), l)
676 }
677
678 func (r *Reader) Fingerprint() FingerprintType {
679         return r.h.Fingerprint
680 }
681
682 func (r *Reader) Autolib() []ImportedPkg {
683         n := (r.h.Offsets[BlkAutolib+1] - r.h.Offsets[BlkAutolib]) / importedPkgSize
684         s := make([]ImportedPkg, n)
685         off := r.h.Offsets[BlkAutolib]
686         for i := range s {
687                 s[i].Pkg = r.StringRef(off)
688                 copy(s[i].Fingerprint[:], r.BytesAt(off+stringRefSize, len(s[i].Fingerprint)))
689                 off += importedPkgSize
690         }
691         return s
692 }
693
694 func (r *Reader) Pkglist() []string {
695         n := (r.h.Offsets[BlkPkgIdx+1] - r.h.Offsets[BlkPkgIdx]) / stringRefSize
696         s := make([]string, n)
697         off := r.h.Offsets[BlkPkgIdx]
698         for i := range s {
699                 s[i] = r.StringRef(off)
700                 off += stringRefSize
701         }
702         return s
703 }
704
705 func (r *Reader) NPkg() int {
706         return int(r.h.Offsets[BlkPkgIdx+1]-r.h.Offsets[BlkPkgIdx]) / stringRefSize
707 }
708
709 func (r *Reader) Pkg(i int) string {
710         off := r.h.Offsets[BlkPkgIdx] + uint32(i)*stringRefSize
711         return r.StringRef(off)
712 }
713
714 func (r *Reader) NFile() int {
715         return int(r.h.Offsets[BlkFile+1]-r.h.Offsets[BlkFile]) / stringRefSize
716 }
717
718 func (r *Reader) File(i int) string {
719         off := r.h.Offsets[BlkFile] + uint32(i)*stringRefSize
720         return r.StringRef(off)
721 }
722
723 func (r *Reader) NSym() int {
724         return int(r.h.Offsets[BlkSymdef+1]-r.h.Offsets[BlkSymdef]) / SymSize
725 }
726
727 func (r *Reader) NHashed64def() int {
728         return int(r.h.Offsets[BlkHashed64def+1]-r.h.Offsets[BlkHashed64def]) / SymSize
729 }
730
731 func (r *Reader) NHasheddef() int {
732         return int(r.h.Offsets[BlkHasheddef+1]-r.h.Offsets[BlkHasheddef]) / SymSize
733 }
734
735 func (r *Reader) NNonpkgdef() int {
736         return int(r.h.Offsets[BlkNonpkgdef+1]-r.h.Offsets[BlkNonpkgdef]) / SymSize
737 }
738
739 func (r *Reader) NNonpkgref() int {
740         return int(r.h.Offsets[BlkNonpkgref+1]-r.h.Offsets[BlkNonpkgref]) / SymSize
741 }
742
743 // SymOff returns the offset of the i-th symbol.
744 func (r *Reader) SymOff(i uint32) uint32 {
745         return r.h.Offsets[BlkSymdef] + uint32(i*SymSize)
746 }
747
748 // Sym returns a pointer to the i-th symbol.
749 func (r *Reader) Sym(i uint32) *Sym {
750         off := r.SymOff(i)
751         return (*Sym)(unsafe.Pointer(&r.b[off]))
752 }
753
754 // NRefFlags returns the number of referenced symbol flags.
755 func (r *Reader) NRefFlags() int {
756         return int(r.h.Offsets[BlkRefFlags+1]-r.h.Offsets[BlkRefFlags]) / RefFlagsSize
757 }
758
759 // RefFlags returns a pointer to the i-th referenced symbol flags.
760 // Note: here i is not a local symbol index, just a counter.
761 func (r *Reader) RefFlags(i int) *RefFlags {
762         off := r.h.Offsets[BlkRefFlags] + uint32(i*RefFlagsSize)
763         return (*RefFlags)(unsafe.Pointer(&r.b[off]))
764 }
765
766 // Hash64 returns the i-th short hashed symbol's hash.
767 // Note: here i is the index of short hashed symbols, not all symbols
768 // (unlike other accessors).
769 func (r *Reader) Hash64(i uint32) uint64 {
770         off := r.h.Offsets[BlkHash64] + uint32(i*Hash64Size)
771         return r.uint64At(off)
772 }
773
774 // Hash returns a pointer to the i-th hashed symbol's hash.
775 // Note: here i is the index of hashed symbols, not all symbols
776 // (unlike other accessors).
777 func (r *Reader) Hash(i uint32) *HashType {
778         off := r.h.Offsets[BlkHash] + uint32(i*HashSize)
779         return (*HashType)(unsafe.Pointer(&r.b[off]))
780 }
781
782 // NReloc returns the number of relocations of the i-th symbol.
783 func (r *Reader) NReloc(i uint32) int {
784         relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
785         return int(r.uint32At(relocIdxOff+4) - r.uint32At(relocIdxOff))
786 }
787
788 // RelocOff returns the offset of the j-th relocation of the i-th symbol.
789 func (r *Reader) RelocOff(i uint32, j int) uint32 {
790         relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
791         relocIdx := r.uint32At(relocIdxOff)
792         return r.h.Offsets[BlkReloc] + (relocIdx+uint32(j))*uint32(RelocSize)
793 }
794
795 // Reloc returns a pointer to the j-th relocation of the i-th symbol.
796 func (r *Reader) Reloc(i uint32, j int) *Reloc {
797         off := r.RelocOff(i, j)
798         return (*Reloc)(unsafe.Pointer(&r.b[off]))
799 }
800
801 // Relocs returns a pointer to the relocations of the i-th symbol.
802 func (r *Reader) Relocs(i uint32) []Reloc {
803         off := r.RelocOff(i, 0)
804         n := r.NReloc(i)
805         return (*[huge]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n]
806 }
807
808 // NAux returns the number of aux symbols of the i-th symbol.
809 func (r *Reader) NAux(i uint32) int {
810         auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
811         return int(r.uint32At(auxIdxOff+4) - r.uint32At(auxIdxOff))
812 }
813
814 // AuxOff returns the offset of the j-th aux symbol of the i-th symbol.
815 func (r *Reader) AuxOff(i uint32, j int) uint32 {
816         auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
817         auxIdx := r.uint32At(auxIdxOff)
818         return r.h.Offsets[BlkAux] + (auxIdx+uint32(j))*uint32(AuxSize)
819 }
820
821 // Aux returns a pointer to the j-th aux symbol of the i-th symbol.
822 func (r *Reader) Aux(i uint32, j int) *Aux {
823         off := r.AuxOff(i, j)
824         return (*Aux)(unsafe.Pointer(&r.b[off]))
825 }
826
827 // Auxs returns the aux symbols of the i-th symbol.
828 func (r *Reader) Auxs(i uint32) []Aux {
829         off := r.AuxOff(i, 0)
830         n := r.NAux(i)
831         return (*[huge]Aux)(unsafe.Pointer(&r.b[off]))[:n:n]
832 }
833
834 // DataOff returns the offset of the i-th symbol's data.
835 func (r *Reader) DataOff(i uint32) uint32 {
836         dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
837         return r.h.Offsets[BlkData] + r.uint32At(dataIdxOff)
838 }
839
840 // DataSize returns the size of the i-th symbol's data.
841 func (r *Reader) DataSize(i uint32) int {
842         dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
843         return int(r.uint32At(dataIdxOff+4) - r.uint32At(dataIdxOff))
844 }
845
846 // Data returns the i-th symbol's data.
847 func (r *Reader) Data(i uint32) []byte {
848         dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
849         base := r.h.Offsets[BlkData]
850         off := r.uint32At(dataIdxOff)
851         end := r.uint32At(dataIdxOff + 4)
852         return r.BytesAt(base+off, int(end-off))
853 }
854
855 // NRefName returns the number of referenced symbol names.
856 func (r *Reader) NRefName() int {
857         return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize
858 }
859
860 // RefName returns a pointer to the i-th referenced symbol name.
861 // Note: here i is not a local symbol index, just a counter.
862 func (r *Reader) RefName(i int) *RefName {
863         off := r.h.Offsets[BlkRefName] + uint32(i*RefNameSize)
864         return (*RefName)(unsafe.Pointer(&r.b[off]))
865 }
866
867 // ReadOnly returns whether r.BytesAt returns read-only bytes.
868 func (r *Reader) ReadOnly() bool {
869         return r.readonly
870 }
871
872 // Flags returns the flag bits read from the object file header.
873 func (r *Reader) Flags() uint32 {
874         return r.h.Flags
875 }
876
877 func (r *Reader) Shared() bool       { return r.Flags()&ObjFlagShared != 0 }
878 func (r *Reader) FromAssembly() bool { return r.Flags()&ObjFlagFromAssembly != 0 }
879 func (r *Reader) Unlinkable() bool   { return r.Flags()&ObjFlagUnlinkable != 0 }