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.
5 // This package defines the Go object file format, and provide "low-level" functions
6 // for reading and writing object files.
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
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)
17 // If the object file format changes, they may (or may not) need to change.
26 "internal/unsafeheader"
30 // New object file format.
33 // Magic [...]byte // "\x00go120ld"
34 // Fingerprint [8]byte
36 // Offsets [...]uint32 // byte offset of each block below
39 // Strings [...]struct {
43 // Autolib [...]struct { // imported packages (for file loading)
45 // Fingerprint [8]byte
48 // PkgIndex [...]string // referenced packages by index
52 // SymbolDefs [...]struct {
60 // Hashed64Defs [...]struct { // short hashed (content-addressable) symbol definitions
61 // ... // same as SymbolDefs
63 // HashedDefs [...]struct { // hashed (content-addressable) symbol definitions
64 // ... // same as SymbolDefs
66 // NonPkgDefs [...]struct { // non-pkg symbol definitions
67 // ... // same as SymbolDefs
69 // NonPkgRefs [...]struct { // non-pkg symbol references
70 // ... // same as SymbolDefs
73 // RefFlags [...]struct { // referenced symbol flags
79 // Hash64 [...][8]byte
82 // RelocIndex [...]uint32 // index to Relocs
83 // AuxIndex [...]uint32 // index to Aux
84 // DataIndex [...]uint32 // offset to Data
86 // Relocs [...]struct {
101 // // blocks only used by tools (objdump, nm)
103 // RefNames [...]struct { // referenced symbol names
106 // // TODO: include ABI version as well?
109 // string is encoded as is a uint32 length followed by a uint32 offset
110 // that points to the corresponding string bytes.
112 // symRef is struct { PkgIdx, SymIdx uint32 }.
114 // Slice type (e.g. []symRef) is encoded as a length prefix (uint32)
115 // followed by that number of elements.
117 // The types below correspond to the encoded data structure in the
122 // Each symbol is referenced with a pair of indices, { PkgIdx, SymIdx },
123 // as the symRef struct above.
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.
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
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
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
141 // {0, 0} represents a nil symbol. Otherwise PkgIdx should not be 0.
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.
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
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
160 // Auxiliary symbols.
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.
167 const stringRefSize = 8 // two uint32s
169 type FingerprintType [8]byte
171 func (fp FingerprintType) IsZero() bool { return fp == FingerprintType{} }
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
182 // The index of other referenced packages starts from 1.
210 // TODO: probably no need to export this.
213 Fingerprint FingerprintType
218 const Magic = "\x00go120ld"
220 func (h *Header) Write(w *Writer) {
222 w.Bytes(h.Fingerprint[:])
224 for _, x := range h.Offsets {
229 func (h *Header) Read(r *Reader) error {
230 b := r.BytesAt(0, len(Magic))
232 if h.Magic != Magic {
233 return errors.New("wrong magic, not a Go object file")
235 off := uint32(len(h.Magic))
236 copy(h.Fingerprint[:], r.BytesAt(off, len(h.Fingerprint)))
238 h.Flags = r.uint32At(off)
240 for i := range h.Offsets {
241 h.Offsets[i] = r.uint32At(off)
247 func (h *Header) Size() int {
248 return len(h.Magic) + 4 + 4*len(h.Offsets)
252 type ImportedPkg struct {
254 Fingerprint FingerprintType
257 const importedPkgSize = stringRefSize + 8
259 func (p *ImportedPkg) Write(w *Writer) {
261 w.Bytes(p.Fingerprint[:])
264 // Symbol definition.
266 // Serialized format:
277 type Sym [SymSize]byte
279 const SymSize = stringRefSize + 2 + 1 + 1 + 1 + 4 + 4
281 const SymABIstatic = ^uint16(0)
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)
292 SymFlagDupok = 1 << iota
303 SymFlagUsedInIface = 1 << iota
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[:]))
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)
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:]) }
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 }
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))
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) }
351 func (s *Sym) Write(w *Writer) { w.Bytes(s[:]) }
354 func (s *Sym) fromBytes(b []byte) { copy(s[:], b) }
362 func (s SymRef) IsZero() bool { return s == SymRef{} }
365 type Hash64Type [Hash64Size]byte
370 type HashType [HashSize]byte
372 const HashSize = 16 // truncated SHA256
376 // Serialized format:
385 type Reloc [RelocSize]byte
387 const RelocSize = 4 + 1 + 2 + 8 + 8
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:])}
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)
406 func (r *Reloc) Set(off int32, size uint8, typ uint16, add int64, sym SymRef) {
414 func (r *Reloc) Write(w *Writer) { w.Bytes(r[:]) }
417 func (r *Reloc) fromBytes(b []byte) { copy(r[:], b) }
421 // Serialized format:
427 type Aux [AuxSize]byte
429 const AuxSize = 1 + 8
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:])}
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)
459 func (a *Aux) Write(w *Writer) { w.Bytes(a[:]) }
462 func (a *Aux) fromBytes(b []byte) { copy(a[:], b) }
464 // Referenced symbol flags.
466 // Serialized format:
473 type RefFlags [RefFlagsSize]byte
475 const RefFlagsSize = 8 + 1 + 1
477 func (r *RefFlags) Sym() SymRef {
478 return SymRef{binary.LittleEndian.Uint32(r[:]), binary.LittleEndian.Uint32(r[4:])}
480 func (r *RefFlags) Flag() uint8 { return r[8] }
481 func (r *RefFlags) Flag2() uint8 { return r[9] }
483 func (r *RefFlags) SetSym(x SymRef) {
484 binary.LittleEndian.PutUint32(r[:], x.PkgIdx)
485 binary.LittleEndian.PutUint32(r[4:], x.SymIdx)
487 func (r *RefFlags) SetFlag(x uint8) { r[8] = x }
488 func (r *RefFlags) SetFlag2(x uint8) { r[9] = x }
490 func (r *RefFlags) Write(w *Writer) { w.Bytes(r[:]) }
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
497 // Referenced symbol name.
499 // Serialized format:
505 type RefName [RefNameSize]byte
507 const RefNameSize = 8 + stringRefSize
509 func (n *RefName) Sym() SymRef {
510 return SymRef{binary.LittleEndian.Uint32(n[:]), binary.LittleEndian.Uint32(n[4:])}
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)
518 func (n *RefName) SetSym(x SymRef) {
519 binary.LittleEndian.PutUint32(n[:], x.PkgIdx)
520 binary.LittleEndian.PutUint32(n[4:], x.SymIdx)
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))
527 func (n *RefName) Write(w *Writer) { w.Bytes(n[:]) }
531 stringMap map[string]uint32
532 off uint32 // running offset
534 b [8]byte // scratch space for writing bytes
537 func NewWriter(wr *bio.Writer) *Writer {
538 return &Writer{wr: wr, stringMap: make(map[string]uint32)}
541 func (w *Writer) AddString(s string) {
542 if _, ok := w.stringMap[s]; ok {
545 w.stringMap[s] = w.off
549 func (w *Writer) stringOff(s string) uint32 {
550 off, ok := w.stringMap[s]
552 panic(fmt.Sprintf("writeStringRef: string not added: %q", s))
557 func (w *Writer) StringRef(s string) {
558 w.Uint32(uint32(len(s)))
559 w.Uint32(w.stringOff(s))
562 func (w *Writer) RawString(s string) {
564 w.off += uint32(len(s))
567 func (w *Writer) Bytes(s []byte) {
569 w.off += uint32(len(s))
572 func (w *Writer) Uint64(x uint64) {
573 binary.LittleEndian.PutUint64(w.b[:], x)
578 func (w *Writer) Uint32(x uint32) {
579 binary.LittleEndian.PutUint32(w.b[:4], x)
584 func (w *Writer) Uint16(x uint16) {
585 binary.LittleEndian.PutUint16(w.b[:2], x)
590 func (w *Writer) Uint8(x uint8) {
595 func (w *Writer) Offset() uint32 {
600 b []byte // mmapped bytes, if not nil
601 readonly bool // whether b is backed with read-only memory
604 h Header // keep block offsets
607 func NewReaderFromBytes(b []byte, readonly bool) *Reader {
608 r := &Reader{b: b, readonly: readonly, start: 0}
616 func (r *Reader) BytesAt(off uint32, len int) []byte {
620 end := int(off) + len
621 return r.b[int(off):end:end]
624 func (r *Reader) uint64At(off uint32) uint64 {
625 b := r.BytesAt(off, 8)
626 return binary.LittleEndian.Uint64(b)
629 func (r *Reader) int64At(off uint32) int64 {
630 return int64(r.uint64At(off))
633 func (r *Reader) uint32At(off uint32) uint32 {
634 b := r.BytesAt(off, 4)
635 return binary.LittleEndian.Uint32(b)
638 func (r *Reader) int32At(off uint32) int32 {
639 return int32(r.uint32At(off))
642 func (r *Reader) uint16At(off uint32) uint16 {
643 b := r.BytesAt(off, 2)
644 return binary.LittleEndian.Uint16(b)
647 func (r *Reader) uint8At(off uint32) uint8 {
648 b := r.BytesAt(off, 1)
652 func (r *Reader) StringAt(off uint32, len uint32) string {
653 b := r.b[off : off+len]
655 return toString(b) // backed by RO memory, ok to make unsafe string
660 func toString(b []byte) string {
666 hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
667 hdr.Data = unsafe.Pointer(&b[0])
673 func (r *Reader) StringRef(off uint32) string {
675 return r.StringAt(r.uint32At(off+4), l)
678 func (r *Reader) Fingerprint() FingerprintType {
679 return r.h.Fingerprint
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]
687 s[i].Pkg = r.StringRef(off)
688 copy(s[i].Fingerprint[:], r.BytesAt(off+stringRefSize, len(s[i].Fingerprint)))
689 off += importedPkgSize
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]
699 s[i] = r.StringRef(off)
705 func (r *Reader) NPkg() int {
706 return int(r.h.Offsets[BlkPkgIdx+1]-r.h.Offsets[BlkPkgIdx]) / stringRefSize
709 func (r *Reader) Pkg(i int) string {
710 off := r.h.Offsets[BlkPkgIdx] + uint32(i)*stringRefSize
711 return r.StringRef(off)
714 func (r *Reader) NFile() int {
715 return int(r.h.Offsets[BlkFile+1]-r.h.Offsets[BlkFile]) / stringRefSize
718 func (r *Reader) File(i int) string {
719 off := r.h.Offsets[BlkFile] + uint32(i)*stringRefSize
720 return r.StringRef(off)
723 func (r *Reader) NSym() int {
724 return int(r.h.Offsets[BlkSymdef+1]-r.h.Offsets[BlkSymdef]) / SymSize
727 func (r *Reader) NHashed64def() int {
728 return int(r.h.Offsets[BlkHashed64def+1]-r.h.Offsets[BlkHashed64def]) / SymSize
731 func (r *Reader) NHasheddef() int {
732 return int(r.h.Offsets[BlkHasheddef+1]-r.h.Offsets[BlkHasheddef]) / SymSize
735 func (r *Reader) NNonpkgdef() int {
736 return int(r.h.Offsets[BlkNonpkgdef+1]-r.h.Offsets[BlkNonpkgdef]) / SymSize
739 func (r *Reader) NNonpkgref() int {
740 return int(r.h.Offsets[BlkNonpkgref+1]-r.h.Offsets[BlkNonpkgref]) / SymSize
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)
748 // Sym returns a pointer to the i-th symbol.
749 func (r *Reader) Sym(i uint32) *Sym {
751 return (*Sym)(unsafe.Pointer(&r.b[off]))
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
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]))
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)
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]))
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))
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)
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]))
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)
805 return (*[huge]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n]
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))
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)
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]))
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)
831 return (*[huge]Aux)(unsafe.Pointer(&r.b[off]))[:n:n]
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)
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))
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))
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
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]))
867 // ReadOnly returns whether r.BytesAt returns read-only bytes.
868 func (r *Reader) ReadOnly() bool {
872 // Flags returns the flag bits read from the object file header.
873 func (r *Reader) Flags() uint32 {
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 }