123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871 |
- // Copyright 2019 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // This package defines the Go object file format, and provide "low-level" functions
- // for reading and writing object files.
- // The object file is understood by the compiler, assembler, linker, and tools. They
- // have "high level" code that operates on object files, handling application-specific
- // logics, and use this package for the actual reading and writing. Specifically, the
- // code below:
- //
- // - cmd/internal/obj/objfile.go (used by cmd/asm and cmd/compile)
- // - cmd/internal/objfile/goobj.go (used cmd/nm, cmd/objdump)
- // - cmd/link/internal/loader package (used by cmd/link)
- //
- // If the object file format changes, they may (or may not) need to change.
- package goobj
- import (
- "bytes"
- "github.com/twitchyliquid64/golang-asm/bio"
- "crypto/sha1"
- "encoding/binary"
- "errors"
- "fmt"
- "github.com/twitchyliquid64/golang-asm/unsafeheader"
- "io"
- "unsafe"
- )
- // New object file format.
- //
- // Header struct {
- // Magic [...]byte // "\x00go116ld"
- // Fingerprint [8]byte
- // Flags uint32
- // Offsets [...]uint32 // byte offset of each block below
- // }
- //
- // Strings [...]struct {
- // Data [...]byte
- // }
- //
- // Autolib [...]struct { // imported packages (for file loading)
- // Pkg string
- // Fingerprint [8]byte
- // }
- //
- // PkgIndex [...]string // referenced packages by index
- //
- // Files [...]string
- //
- // SymbolDefs [...]struct {
- // Name string
- // ABI uint16
- // Type uint8
- // Flag uint8
- // Flag2 uint8
- // Size uint32
- // }
- // Hashed64Defs [...]struct { // short hashed (content-addressable) symbol definitions
- // ... // same as SymbolDefs
- // }
- // HashedDefs [...]struct { // hashed (content-addressable) symbol definitions
- // ... // same as SymbolDefs
- // }
- // NonPkgDefs [...]struct { // non-pkg symbol definitions
- // ... // same as SymbolDefs
- // }
- // NonPkgRefs [...]struct { // non-pkg symbol references
- // ... // same as SymbolDefs
- // }
- //
- // RefFlags [...]struct { // referenced symbol flags
- // Sym symRef
- // Flag uint8
- // Flag2 uint8
- // }
- //
- // Hash64 [...][8]byte
- // Hash [...][N]byte
- //
- // RelocIndex [...]uint32 // index to Relocs
- // AuxIndex [...]uint32 // index to Aux
- // DataIndex [...]uint32 // offset to Data
- //
- // Relocs [...]struct {
- // Off int32
- // Size uint8
- // Type uint8
- // Add int64
- // Sym symRef
- // }
- //
- // Aux [...]struct {
- // Type uint8
- // Sym symRef
- // }
- //
- // Data [...]byte
- // Pcdata [...]byte
- //
- // // blocks only used by tools (objdump, nm)
- //
- // RefNames [...]struct { // referenced symbol names
- // Sym symRef
- // Name string
- // // TODO: include ABI version as well?
- // }
- //
- // string is encoded as is a uint32 length followed by a uint32 offset
- // that points to the corresponding string bytes.
- //
- // symRef is struct { PkgIdx, SymIdx uint32 }.
- //
- // Slice type (e.g. []symRef) is encoded as a length prefix (uint32)
- // followed by that number of elements.
- //
- // The types below correspond to the encoded data structure in the
- // object file.
- // Symbol indexing.
- //
- // Each symbol is referenced with a pair of indices, { PkgIdx, SymIdx },
- // as the symRef struct above.
- //
- // PkgIdx is either a predeclared index (see PkgIdxNone below) or
- // an index of an imported package. For the latter case, PkgIdx is the
- // index of the package in the PkgIndex array. 0 is an invalid index.
- //
- // SymIdx is the index of the symbol in the given package.
- // - If PkgIdx is PkgIdxSelf, SymIdx is the index of the symbol in the
- // SymbolDefs array.
- // - If PkgIdx is PkgIdxHashed64, SymIdx is the index of the symbol in the
- // Hashed64Defs array.
- // - If PkgIdx is PkgIdxHashed, SymIdx is the index of the symbol in the
- // HashedDefs array.
- // - If PkgIdx is PkgIdxNone, SymIdx is the index of the symbol in the
- // NonPkgDefs array (could natually overflow to NonPkgRefs array).
- // - Otherwise, SymIdx is the index of the symbol in some other package's
- // SymbolDefs array.
- //
- // {0, 0} represents a nil symbol. Otherwise PkgIdx should not be 0.
- //
- // Hash contains the content hashes of content-addressable symbols, of
- // which PkgIdx is PkgIdxHashed, in the same order of HashedDefs array.
- // Hash64 is similar, for PkgIdxHashed64 symbols.
- //
- // RelocIndex, AuxIndex, and DataIndex contains indices/offsets to
- // Relocs/Aux/Data blocks, one element per symbol, first for all the
- // defined symbols, then all the defined hashed and non-package symbols,
- // in the same order of SymbolDefs/Hashed64Defs/HashedDefs/NonPkgDefs
- // arrays. For N total defined symbols, the array is of length N+1. The
- // last element is the total number of relocations (aux symbols, data
- // blocks, etc.).
- //
- // They can be accessed by index. For the i-th symbol, its relocations
- // are the RelocIndex[i]-th (inclusive) to RelocIndex[i+1]-th (exclusive)
- // elements in the Relocs array. Aux/Data are likewise. (The index is
- // 0-based.)
- // Auxiliary symbols.
- //
- // Each symbol may (or may not) be associated with a number of auxiliary
- // symbols. They are described in the Aux block. See Aux struct below.
- // Currently a symbol's Gotype, FuncInfo, and associated DWARF symbols
- // are auxiliary symbols.
- const stringRefSize = 8 // two uint32s
- type FingerprintType [8]byte
- func (fp FingerprintType) IsZero() bool { return fp == FingerprintType{} }
- // Package Index.
- const (
- PkgIdxNone = (1<<31 - 1) - iota // Non-package symbols
- PkgIdxHashed64 // Short hashed (content-addressable) symbols
- PkgIdxHashed // Hashed (content-addressable) symbols
- PkgIdxBuiltin // Predefined runtime symbols (ex: runtime.newobject)
- PkgIdxSelf // Symbols defined in the current package
- PkgIdxInvalid = 0
- // The index of other referenced packages starts from 1.
- )
- // Blocks
- const (
- BlkAutolib = iota
- BlkPkgIdx
- BlkFile
- BlkSymdef
- BlkHashed64def
- BlkHasheddef
- BlkNonpkgdef
- BlkNonpkgref
- BlkRefFlags
- BlkHash64
- BlkHash
- BlkRelocIdx
- BlkAuxIdx
- BlkDataIdx
- BlkReloc
- BlkAux
- BlkData
- BlkPcdata
- BlkRefName
- BlkEnd
- NBlk
- )
- // File header.
- // TODO: probably no need to export this.
- type Header struct {
- Magic string
- Fingerprint FingerprintType
- Flags uint32
- Offsets [NBlk]uint32
- }
- const Magic = "\x00go116ld"
- func (h *Header) Write(w *Writer) {
- w.RawString(h.Magic)
- w.Bytes(h.Fingerprint[:])
- w.Uint32(h.Flags)
- for _, x := range h.Offsets {
- w.Uint32(x)
- }
- }
- func (h *Header) Read(r *Reader) error {
- b := r.BytesAt(0, len(Magic))
- h.Magic = string(b)
- if h.Magic != Magic {
- return errors.New("wrong magic, not a Go object file")
- }
- off := uint32(len(h.Magic))
- copy(h.Fingerprint[:], r.BytesAt(off, len(h.Fingerprint)))
- off += 8
- h.Flags = r.uint32At(off)
- off += 4
- for i := range h.Offsets {
- h.Offsets[i] = r.uint32At(off)
- off += 4
- }
- return nil
- }
- func (h *Header) Size() int {
- return len(h.Magic) + 4 + 4*len(h.Offsets)
- }
- // Autolib
- type ImportedPkg struct {
- Pkg string
- Fingerprint FingerprintType
- }
- const importedPkgSize = stringRefSize + 8
- func (p *ImportedPkg) Write(w *Writer) {
- w.StringRef(p.Pkg)
- w.Bytes(p.Fingerprint[:])
- }
- // Symbol definition.
- //
- // Serialized format:
- // Sym struct {
- // Name string
- // ABI uint16
- // Type uint8
- // Flag uint8
- // Flag2 uint8
- // Siz uint32
- // Align uint32
- // }
- type Sym [SymSize]byte
- const SymSize = stringRefSize + 2 + 1 + 1 + 1 + 4 + 4
- const SymABIstatic = ^uint16(0)
- const (
- ObjFlagShared = 1 << iota // this object is built with -shared
- ObjFlagNeedNameExpansion // the linker needs to expand `"".` to package path in symbol names
- ObjFlagFromAssembly // object is from asm src, not go
- )
- // Sym.Flag
- const (
- SymFlagDupok = 1 << iota
- SymFlagLocal
- SymFlagTypelink
- SymFlagLeaf
- SymFlagNoSplit
- SymFlagReflectMethod
- SymFlagGoType
- SymFlagTopFrame
- )
- // Sym.Flag2
- const (
- SymFlagUsedInIface = 1 << iota
- SymFlagItab
- )
- // Returns the length of the name of the symbol.
- func (s *Sym) NameLen(r *Reader) int {
- return int(binary.LittleEndian.Uint32(s[:]))
- }
- func (s *Sym) Name(r *Reader) string {
- len := binary.LittleEndian.Uint32(s[:])
- off := binary.LittleEndian.Uint32(s[4:])
- return r.StringAt(off, len)
- }
- func (s *Sym) ABI() uint16 { return binary.LittleEndian.Uint16(s[8:]) }
- func (s *Sym) Type() uint8 { return s[10] }
- func (s *Sym) Flag() uint8 { return s[11] }
- func (s *Sym) Flag2() uint8 { return s[12] }
- func (s *Sym) Siz() uint32 { return binary.LittleEndian.Uint32(s[13:]) }
- func (s *Sym) Align() uint32 { return binary.LittleEndian.Uint32(s[17:]) }
- func (s *Sym) Dupok() bool { return s.Flag()&SymFlagDupok != 0 }
- func (s *Sym) Local() bool { return s.Flag()&SymFlagLocal != 0 }
- func (s *Sym) Typelink() bool { return s.Flag()&SymFlagTypelink != 0 }
- func (s *Sym) Leaf() bool { return s.Flag()&SymFlagLeaf != 0 }
- func (s *Sym) NoSplit() bool { return s.Flag()&SymFlagNoSplit != 0 }
- func (s *Sym) ReflectMethod() bool { return s.Flag()&SymFlagReflectMethod != 0 }
- func (s *Sym) IsGoType() bool { return s.Flag()&SymFlagGoType != 0 }
- func (s *Sym) TopFrame() bool { return s.Flag()&SymFlagTopFrame != 0 }
- func (s *Sym) UsedInIface() bool { return s.Flag2()&SymFlagUsedInIface != 0 }
- func (s *Sym) IsItab() bool { return s.Flag2()&SymFlagItab != 0 }
- func (s *Sym) SetName(x string, w *Writer) {
- binary.LittleEndian.PutUint32(s[:], uint32(len(x)))
- binary.LittleEndian.PutUint32(s[4:], w.stringOff(x))
- }
- func (s *Sym) SetABI(x uint16) { binary.LittleEndian.PutUint16(s[8:], x) }
- func (s *Sym) SetType(x uint8) { s[10] = x }
- func (s *Sym) SetFlag(x uint8) { s[11] = x }
- func (s *Sym) SetFlag2(x uint8) { s[12] = x }
- func (s *Sym) SetSiz(x uint32) { binary.LittleEndian.PutUint32(s[13:], x) }
- func (s *Sym) SetAlign(x uint32) { binary.LittleEndian.PutUint32(s[17:], x) }
- func (s *Sym) Write(w *Writer) { w.Bytes(s[:]) }
- // for testing
- func (s *Sym) fromBytes(b []byte) { copy(s[:], b) }
- // Symbol reference.
- type SymRef struct {
- PkgIdx uint32
- SymIdx uint32
- }
- // Hash64
- type Hash64Type [Hash64Size]byte
- const Hash64Size = 8
- // Hash
- type HashType [HashSize]byte
- const HashSize = sha1.Size
- // Relocation.
- //
- // Serialized format:
- // Reloc struct {
- // Off int32
- // Siz uint8
- // Type uint8
- // Add int64
- // Sym SymRef
- // }
- type Reloc [RelocSize]byte
- const RelocSize = 4 + 1 + 1 + 8 + 8
- func (r *Reloc) Off() int32 { return int32(binary.LittleEndian.Uint32(r[:])) }
- func (r *Reloc) Siz() uint8 { return r[4] }
- func (r *Reloc) Type() uint8 { return r[5] }
- func (r *Reloc) Add() int64 { return int64(binary.LittleEndian.Uint64(r[6:])) }
- func (r *Reloc) Sym() SymRef {
- return SymRef{binary.LittleEndian.Uint32(r[14:]), binary.LittleEndian.Uint32(r[18:])}
- }
- func (r *Reloc) SetOff(x int32) { binary.LittleEndian.PutUint32(r[:], uint32(x)) }
- func (r *Reloc) SetSiz(x uint8) { r[4] = x }
- func (r *Reloc) SetType(x uint8) { r[5] = x }
- func (r *Reloc) SetAdd(x int64) { binary.LittleEndian.PutUint64(r[6:], uint64(x)) }
- func (r *Reloc) SetSym(x SymRef) {
- binary.LittleEndian.PutUint32(r[14:], x.PkgIdx)
- binary.LittleEndian.PutUint32(r[18:], x.SymIdx)
- }
- func (r *Reloc) Set(off int32, size uint8, typ uint8, add int64, sym SymRef) {
- r.SetOff(off)
- r.SetSiz(size)
- r.SetType(typ)
- r.SetAdd(add)
- r.SetSym(sym)
- }
- func (r *Reloc) Write(w *Writer) { w.Bytes(r[:]) }
- // for testing
- func (r *Reloc) fromBytes(b []byte) { copy(r[:], b) }
- // Aux symbol info.
- //
- // Serialized format:
- // Aux struct {
- // Type uint8
- // Sym SymRef
- // }
- type Aux [AuxSize]byte
- const AuxSize = 1 + 8
- // Aux Type
- const (
- AuxGotype = iota
- AuxFuncInfo
- AuxFuncdata
- AuxDwarfInfo
- AuxDwarfLoc
- AuxDwarfRanges
- AuxDwarfLines
- // TODO: more. Pcdata?
- )
- func (a *Aux) Type() uint8 { return a[0] }
- func (a *Aux) Sym() SymRef {
- return SymRef{binary.LittleEndian.Uint32(a[1:]), binary.LittleEndian.Uint32(a[5:])}
- }
- func (a *Aux) SetType(x uint8) { a[0] = x }
- func (a *Aux) SetSym(x SymRef) {
- binary.LittleEndian.PutUint32(a[1:], x.PkgIdx)
- binary.LittleEndian.PutUint32(a[5:], x.SymIdx)
- }
- func (a *Aux) Write(w *Writer) { w.Bytes(a[:]) }
- // for testing
- func (a *Aux) fromBytes(b []byte) { copy(a[:], b) }
- // Referenced symbol flags.
- //
- // Serialized format:
- // RefFlags struct {
- // Sym symRef
- // Flag uint8
- // Flag2 uint8
- // }
- type RefFlags [RefFlagsSize]byte
- const RefFlagsSize = 8 + 1 + 1
- func (r *RefFlags) Sym() SymRef {
- return SymRef{binary.LittleEndian.Uint32(r[:]), binary.LittleEndian.Uint32(r[4:])}
- }
- func (r *RefFlags) Flag() uint8 { return r[8] }
- func (r *RefFlags) Flag2() uint8 { return r[9] }
- func (r *RefFlags) SetSym(x SymRef) {
- binary.LittleEndian.PutUint32(r[:], x.PkgIdx)
- binary.LittleEndian.PutUint32(r[4:], x.SymIdx)
- }
- func (r *RefFlags) SetFlag(x uint8) { r[8] = x }
- func (r *RefFlags) SetFlag2(x uint8) { r[9] = x }
- func (r *RefFlags) Write(w *Writer) { w.Bytes(r[:]) }
- // Referenced symbol name.
- //
- // Serialized format:
- // RefName struct {
- // Sym symRef
- // Name string
- // }
- type RefName [RefNameSize]byte
- const RefNameSize = 8 + stringRefSize
- func (n *RefName) Sym() SymRef {
- return SymRef{binary.LittleEndian.Uint32(n[:]), binary.LittleEndian.Uint32(n[4:])}
- }
- func (n *RefName) Name(r *Reader) string {
- len := binary.LittleEndian.Uint32(n[8:])
- off := binary.LittleEndian.Uint32(n[12:])
- return r.StringAt(off, len)
- }
- func (n *RefName) SetSym(x SymRef) {
- binary.LittleEndian.PutUint32(n[:], x.PkgIdx)
- binary.LittleEndian.PutUint32(n[4:], x.SymIdx)
- }
- func (n *RefName) SetName(x string, w *Writer) {
- binary.LittleEndian.PutUint32(n[8:], uint32(len(x)))
- binary.LittleEndian.PutUint32(n[12:], w.stringOff(x))
- }
- func (n *RefName) Write(w *Writer) { w.Bytes(n[:]) }
- type Writer struct {
- wr *bio.Writer
- stringMap map[string]uint32
- off uint32 // running offset
- }
- func NewWriter(wr *bio.Writer) *Writer {
- return &Writer{wr: wr, stringMap: make(map[string]uint32)}
- }
- func (w *Writer) AddString(s string) {
- if _, ok := w.stringMap[s]; ok {
- return
- }
- w.stringMap[s] = w.off
- w.RawString(s)
- }
- func (w *Writer) stringOff(s string) uint32 {
- off, ok := w.stringMap[s]
- if !ok {
- panic(fmt.Sprintf("writeStringRef: string not added: %q", s))
- }
- return off
- }
- func (w *Writer) StringRef(s string) {
- w.Uint32(uint32(len(s)))
- w.Uint32(w.stringOff(s))
- }
- func (w *Writer) RawString(s string) {
- w.wr.WriteString(s)
- w.off += uint32(len(s))
- }
- func (w *Writer) Bytes(s []byte) {
- w.wr.Write(s)
- w.off += uint32(len(s))
- }
- func (w *Writer) Uint64(x uint64) {
- var b [8]byte
- binary.LittleEndian.PutUint64(b[:], x)
- w.wr.Write(b[:])
- w.off += 8
- }
- func (w *Writer) Uint32(x uint32) {
- var b [4]byte
- binary.LittleEndian.PutUint32(b[:], x)
- w.wr.Write(b[:])
- w.off += 4
- }
- func (w *Writer) Uint16(x uint16) {
- var b [2]byte
- binary.LittleEndian.PutUint16(b[:], x)
- w.wr.Write(b[:])
- w.off += 2
- }
- func (w *Writer) Uint8(x uint8) {
- w.wr.WriteByte(x)
- w.off++
- }
- func (w *Writer) Offset() uint32 {
- return w.off
- }
- type Reader struct {
- b []byte // mmapped bytes, if not nil
- readonly bool // whether b is backed with read-only memory
- rd io.ReaderAt
- start uint32
- h Header // keep block offsets
- }
- func NewReaderFromBytes(b []byte, readonly bool) *Reader {
- r := &Reader{b: b, readonly: readonly, rd: bytes.NewReader(b), start: 0}
- err := r.h.Read(r)
- if err != nil {
- return nil
- }
- return r
- }
- func (r *Reader) BytesAt(off uint32, len int) []byte {
- if len == 0 {
- return nil
- }
- end := int(off) + len
- return r.b[int(off):end:end]
- }
- func (r *Reader) uint64At(off uint32) uint64 {
- b := r.BytesAt(off, 8)
- return binary.LittleEndian.Uint64(b)
- }
- func (r *Reader) int64At(off uint32) int64 {
- return int64(r.uint64At(off))
- }
- func (r *Reader) uint32At(off uint32) uint32 {
- b := r.BytesAt(off, 4)
- return binary.LittleEndian.Uint32(b)
- }
- func (r *Reader) int32At(off uint32) int32 {
- return int32(r.uint32At(off))
- }
- func (r *Reader) uint16At(off uint32) uint16 {
- b := r.BytesAt(off, 2)
- return binary.LittleEndian.Uint16(b)
- }
- func (r *Reader) uint8At(off uint32) uint8 {
- b := r.BytesAt(off, 1)
- return b[0]
- }
- func (r *Reader) StringAt(off uint32, len uint32) string {
- b := r.b[off : off+len]
- if r.readonly {
- return toString(b) // backed by RO memory, ok to make unsafe string
- }
- return string(b)
- }
- func toString(b []byte) string {
- if len(b) == 0 {
- return ""
- }
- var s string
- hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
- hdr.Data = unsafe.Pointer(&b[0])
- hdr.Len = len(b)
- return s
- }
- func (r *Reader) StringRef(off uint32) string {
- l := r.uint32At(off)
- return r.StringAt(r.uint32At(off+4), l)
- }
- func (r *Reader) Fingerprint() FingerprintType {
- return r.h.Fingerprint
- }
- func (r *Reader) Autolib() []ImportedPkg {
- n := (r.h.Offsets[BlkAutolib+1] - r.h.Offsets[BlkAutolib]) / importedPkgSize
- s := make([]ImportedPkg, n)
- off := r.h.Offsets[BlkAutolib]
- for i := range s {
- s[i].Pkg = r.StringRef(off)
- copy(s[i].Fingerprint[:], r.BytesAt(off+stringRefSize, len(s[i].Fingerprint)))
- off += importedPkgSize
- }
- return s
- }
- func (r *Reader) Pkglist() []string {
- n := (r.h.Offsets[BlkPkgIdx+1] - r.h.Offsets[BlkPkgIdx]) / stringRefSize
- s := make([]string, n)
- off := r.h.Offsets[BlkPkgIdx]
- for i := range s {
- s[i] = r.StringRef(off)
- off += stringRefSize
- }
- return s
- }
- func (r *Reader) NPkg() int {
- return int(r.h.Offsets[BlkPkgIdx+1]-r.h.Offsets[BlkPkgIdx]) / stringRefSize
- }
- func (r *Reader) Pkg(i int) string {
- off := r.h.Offsets[BlkPkgIdx] + uint32(i)*stringRefSize
- return r.StringRef(off)
- }
- func (r *Reader) NFile() int {
- return int(r.h.Offsets[BlkFile+1]-r.h.Offsets[BlkFile]) / stringRefSize
- }
- func (r *Reader) File(i int) string {
- off := r.h.Offsets[BlkFile] + uint32(i)*stringRefSize
- return r.StringRef(off)
- }
- func (r *Reader) NSym() int {
- return int(r.h.Offsets[BlkSymdef+1]-r.h.Offsets[BlkSymdef]) / SymSize
- }
- func (r *Reader) NHashed64def() int {
- return int(r.h.Offsets[BlkHashed64def+1]-r.h.Offsets[BlkHashed64def]) / SymSize
- }
- func (r *Reader) NHasheddef() int {
- return int(r.h.Offsets[BlkHasheddef+1]-r.h.Offsets[BlkHasheddef]) / SymSize
- }
- func (r *Reader) NNonpkgdef() int {
- return int(r.h.Offsets[BlkNonpkgdef+1]-r.h.Offsets[BlkNonpkgdef]) / SymSize
- }
- func (r *Reader) NNonpkgref() int {
- return int(r.h.Offsets[BlkNonpkgref+1]-r.h.Offsets[BlkNonpkgref]) / SymSize
- }
- // SymOff returns the offset of the i-th symbol.
- func (r *Reader) SymOff(i uint32) uint32 {
- return r.h.Offsets[BlkSymdef] + uint32(i*SymSize)
- }
- // Sym returns a pointer to the i-th symbol.
- func (r *Reader) Sym(i uint32) *Sym {
- off := r.SymOff(i)
- return (*Sym)(unsafe.Pointer(&r.b[off]))
- }
- // NRefFlags returns the number of referenced symbol flags.
- func (r *Reader) NRefFlags() int {
- return int(r.h.Offsets[BlkRefFlags+1]-r.h.Offsets[BlkRefFlags]) / RefFlagsSize
- }
- // RefFlags returns a pointer to the i-th referenced symbol flags.
- // Note: here i is not a local symbol index, just a counter.
- func (r *Reader) RefFlags(i int) *RefFlags {
- off := r.h.Offsets[BlkRefFlags] + uint32(i*RefFlagsSize)
- return (*RefFlags)(unsafe.Pointer(&r.b[off]))
- }
- // Hash64 returns the i-th short hashed symbol's hash.
- // Note: here i is the index of short hashed symbols, not all symbols
- // (unlike other accessors).
- func (r *Reader) Hash64(i uint32) uint64 {
- off := r.h.Offsets[BlkHash64] + uint32(i*Hash64Size)
- return r.uint64At(off)
- }
- // Hash returns a pointer to the i-th hashed symbol's hash.
- // Note: here i is the index of hashed symbols, not all symbols
- // (unlike other accessors).
- func (r *Reader) Hash(i uint32) *HashType {
- off := r.h.Offsets[BlkHash] + uint32(i*HashSize)
- return (*HashType)(unsafe.Pointer(&r.b[off]))
- }
- // NReloc returns the number of relocations of the i-th symbol.
- func (r *Reader) NReloc(i uint32) int {
- relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
- return int(r.uint32At(relocIdxOff+4) - r.uint32At(relocIdxOff))
- }
- // RelocOff returns the offset of the j-th relocation of the i-th symbol.
- func (r *Reader) RelocOff(i uint32, j int) uint32 {
- relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
- relocIdx := r.uint32At(relocIdxOff)
- return r.h.Offsets[BlkReloc] + (relocIdx+uint32(j))*uint32(RelocSize)
- }
- // Reloc returns a pointer to the j-th relocation of the i-th symbol.
- func (r *Reader) Reloc(i uint32, j int) *Reloc {
- off := r.RelocOff(i, j)
- return (*Reloc)(unsafe.Pointer(&r.b[off]))
- }
- // Relocs returns a pointer to the relocations of the i-th symbol.
- func (r *Reader) Relocs(i uint32) []Reloc {
- off := r.RelocOff(i, 0)
- n := r.NReloc(i)
- return (*[1 << 20]Reloc)(unsafe.Pointer(&r.b[off]))[:n:n]
- }
- // NAux returns the number of aux symbols of the i-th symbol.
- func (r *Reader) NAux(i uint32) int {
- auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
- return int(r.uint32At(auxIdxOff+4) - r.uint32At(auxIdxOff))
- }
- // AuxOff returns the offset of the j-th aux symbol of the i-th symbol.
- func (r *Reader) AuxOff(i uint32, j int) uint32 {
- auxIdxOff := r.h.Offsets[BlkAuxIdx] + i*4
- auxIdx := r.uint32At(auxIdxOff)
- return r.h.Offsets[BlkAux] + (auxIdx+uint32(j))*uint32(AuxSize)
- }
- // Aux returns a pointer to the j-th aux symbol of the i-th symbol.
- func (r *Reader) Aux(i uint32, j int) *Aux {
- off := r.AuxOff(i, j)
- return (*Aux)(unsafe.Pointer(&r.b[off]))
- }
- // Auxs returns the aux symbols of the i-th symbol.
- func (r *Reader) Auxs(i uint32) []Aux {
- off := r.AuxOff(i, 0)
- n := r.NAux(i)
- return (*[1 << 20]Aux)(unsafe.Pointer(&r.b[off]))[:n:n]
- }
- // DataOff returns the offset of the i-th symbol's data.
- func (r *Reader) DataOff(i uint32) uint32 {
- dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
- return r.h.Offsets[BlkData] + r.uint32At(dataIdxOff)
- }
- // DataSize returns the size of the i-th symbol's data.
- func (r *Reader) DataSize(i uint32) int {
- dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
- return int(r.uint32At(dataIdxOff+4) - r.uint32At(dataIdxOff))
- }
- // Data returns the i-th symbol's data.
- func (r *Reader) Data(i uint32) []byte {
- dataIdxOff := r.h.Offsets[BlkDataIdx] + i*4
- base := r.h.Offsets[BlkData]
- off := r.uint32At(dataIdxOff)
- end := r.uint32At(dataIdxOff + 4)
- return r.BytesAt(base+off, int(end-off))
- }
- // AuxDataBase returns the base offset of the aux data block.
- func (r *Reader) PcdataBase() uint32 {
- return r.h.Offsets[BlkPcdata]
- }
- // NRefName returns the number of referenced symbol names.
- func (r *Reader) NRefName() int {
- return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize
- }
- // RefName returns a pointer to the i-th referenced symbol name.
- // Note: here i is not a local symbol index, just a counter.
- func (r *Reader) RefName(i int) *RefName {
- off := r.h.Offsets[BlkRefName] + uint32(i*RefNameSize)
- return (*RefName)(unsafe.Pointer(&r.b[off]))
- }
- // ReadOnly returns whether r.BytesAt returns read-only bytes.
- func (r *Reader) ReadOnly() bool {
- return r.readonly
- }
- // Flags returns the flag bits read from the object file header.
- func (r *Reader) Flags() uint32 {
- return r.h.Flags
- }
- func (r *Reader) Shared() bool { return r.Flags()&ObjFlagShared != 0 }
- func (r *Reader) NeedNameExpansion() bool { return r.Flags()&ObjFlagNeedNameExpansion != 0 }
- func (r *Reader) FromAssembly() bool { return r.Flags()&ObjFlagFromAssembly != 0 }
|