github.com/yukk001/go1.10.8@v0.0.0-20190813125351-6df2d3982e20/src/cmd/link/internal/objfile/objfile.go (about)

     1  // Copyright 2013 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  // Package objfile reads Go object files for the Go linker, cmd/link.
     6  //
     7  // This package is similar to cmd/internal/objfile which also reads
     8  // Go object files.
     9  package objfile
    10  
    11  import (
    12  	"bufio"
    13  	"bytes"
    14  	"cmd/internal/bio"
    15  	"cmd/internal/dwarf"
    16  	"cmd/internal/objabi"
    17  	"cmd/internal/sys"
    18  	"cmd/link/internal/sym"
    19  	"io"
    20  	"log"
    21  	"strconv"
    22  	"strings"
    23  )
    24  
    25  const (
    26  	startmagic = "\x00\x00go19ld"
    27  	endmagic   = "\xff\xffgo19ld"
    28  )
    29  
    30  var emptyPkg = []byte(`"".`)
    31  
    32  // objReader reads Go object files.
    33  type objReader struct {
    34  	rd              *bufio.Reader
    35  	arch            *sys.Arch
    36  	syms            *sym.Symbols
    37  	lib             *sym.Library
    38  	pn              string
    39  	dupSym          *sym.Symbol
    40  	localSymVersion int
    41  
    42  	// rdBuf is used by readString and readSymName as scratch for reading strings.
    43  	rdBuf []byte
    44  
    45  	// List of symbol references for the file being read.
    46  	refs        []*sym.Symbol
    47  	data        []byte
    48  	reloc       []sym.Reloc
    49  	pcdata      []sym.Pcdata
    50  	autom       []sym.Auto
    51  	funcdata    []*sym.Symbol
    52  	funcdataoff []int64
    53  	file        []*sym.Symbol
    54  }
    55  
    56  // Load loads an object file f into library lib.
    57  // The symbols loaded are added to syms.
    58  func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *sym.Library, length int64, pn string) {
    59  	start := f.Offset()
    60  	r := &objReader{
    61  		rd:              f.Reader,
    62  		lib:             lib,
    63  		arch:            arch,
    64  		syms:            syms,
    65  		pn:              pn,
    66  		dupSym:          &sym.Symbol{Name: ".dup"},
    67  		localSymVersion: syms.IncVersion(),
    68  	}
    69  	r.loadObjFile()
    70  	if f.Offset() != start+length {
    71  		log.Fatalf("%s: unexpected end at %d, want %d", pn, f.Offset(), start+length)
    72  	}
    73  }
    74  
    75  func (r *objReader) loadObjFile() {
    76  	// Magic header
    77  	var buf [8]uint8
    78  	r.readFull(buf[:])
    79  	if string(buf[:]) != startmagic {
    80  		log.Fatalf("%s: invalid file start %x %x %x %x %x %x %x %x", r.pn, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])
    81  	}
    82  
    83  	// Version
    84  	c, err := r.rd.ReadByte()
    85  	if err != nil || c != 1 {
    86  		log.Fatalf("%s: invalid file version number %d", r.pn, c)
    87  	}
    88  
    89  	// Autolib
    90  	for {
    91  		lib := r.readString()
    92  		if lib == "" {
    93  			break
    94  		}
    95  		r.lib.ImportStrings = append(r.lib.ImportStrings, lib)
    96  	}
    97  
    98  	// Symbol references
    99  	r.refs = []*sym.Symbol{nil} // zeroth ref is nil
   100  	for {
   101  		c, err := r.rd.Peek(1)
   102  		if err != nil {
   103  			log.Fatalf("%s: peeking: %v", r.pn, err)
   104  		}
   105  		if c[0] == 0xff {
   106  			r.rd.ReadByte()
   107  			break
   108  		}
   109  		r.readRef()
   110  	}
   111  
   112  	// Lengths
   113  	r.readSlices()
   114  
   115  	// Data section
   116  	r.readFull(r.data)
   117  
   118  	// Defined symbols
   119  	for {
   120  		c, err := r.rd.Peek(1)
   121  		if err != nil {
   122  			log.Fatalf("%s: peeking: %v", r.pn, err)
   123  		}
   124  		if c[0] == 0xff {
   125  			break
   126  		}
   127  		r.readSym()
   128  	}
   129  
   130  	// Magic footer
   131  	buf = [8]uint8{}
   132  	r.readFull(buf[:])
   133  	if string(buf[:]) != endmagic {
   134  		log.Fatalf("%s: invalid file end", r.pn)
   135  	}
   136  }
   137  
   138  func (r *objReader) readSlices() {
   139  	n := r.readInt()
   140  	r.data = make([]byte, n)
   141  	n = r.readInt()
   142  	r.reloc = make([]sym.Reloc, n)
   143  	n = r.readInt()
   144  	r.pcdata = make([]sym.Pcdata, n)
   145  	n = r.readInt()
   146  	r.autom = make([]sym.Auto, n)
   147  	n = r.readInt()
   148  	r.funcdata = make([]*sym.Symbol, n)
   149  	r.funcdataoff = make([]int64, n)
   150  	n = r.readInt()
   151  	r.file = make([]*sym.Symbol, n)
   152  }
   153  
   154  // Symbols are prefixed so their content doesn't get confused with the magic footer.
   155  const symPrefix = 0xfe
   156  
   157  func (r *objReader) readSym() {
   158  	var c byte
   159  	var err error
   160  	if c, err = r.rd.ReadByte(); c != symPrefix || err != nil {
   161  		log.Fatalln("readSym out of sync")
   162  	}
   163  	if c, err = r.rd.ReadByte(); err != nil {
   164  		log.Fatalln("error reading input: ", err)
   165  	}
   166  	t := sym.AbiSymKindToSymKind[c]
   167  	s := r.readSymIndex()
   168  	flags := r.readInt()
   169  	dupok := flags&1 != 0
   170  	local := flags&2 != 0
   171  	makeTypelink := flags&4 != 0
   172  	size := r.readInt()
   173  	typ := r.readSymIndex()
   174  	data := r.readData()
   175  	nreloc := r.readInt()
   176  	pkg := objabi.PathToPrefix(r.lib.Pkg)
   177  	isdup := false
   178  
   179  	var dup *sym.Symbol
   180  	if s.Type != 0 && s.Type != sym.SXREF {
   181  		if (t == sym.SDATA || t == sym.SBSS || t == sym.SNOPTRBSS) && len(data) == 0 && nreloc == 0 {
   182  			if s.Size < int64(size) {
   183  				s.Size = int64(size)
   184  			}
   185  			if typ != nil && s.Gotype == nil {
   186  				s.Gotype = typ
   187  			}
   188  			return
   189  		}
   190  
   191  		if (s.Type == sym.SDATA || s.Type == sym.SBSS || s.Type == sym.SNOPTRBSS) && len(s.P) == 0 && len(s.R) == 0 {
   192  			goto overwrite
   193  		}
   194  		if s.Type != sym.SBSS && s.Type != sym.SNOPTRBSS && !dupok && !s.Attr.DuplicateOK() {
   195  			log.Fatalf("duplicate symbol %s (types %d and %d) in %s and %s", s.Name, s.Type, t, s.File, r.pn)
   196  		}
   197  		if len(s.P) > 0 {
   198  			dup = s
   199  			s = r.dupSym
   200  			isdup = true
   201  		}
   202  	}
   203  
   204  overwrite:
   205  	s.File = pkg
   206  	if dupok {
   207  		s.Attr |= sym.AttrDuplicateOK
   208  	}
   209  	if t == sym.SXREF {
   210  		log.Fatalf("bad sxref")
   211  	}
   212  	if t == 0 {
   213  		log.Fatalf("missing type for %s in %s", s.Name, r.pn)
   214  	}
   215  	if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) {
   216  		t = s.Type
   217  	}
   218  	s.Type = t
   219  	if s.Size < int64(size) {
   220  		s.Size = int64(size)
   221  	}
   222  	s.Attr.Set(sym.AttrLocal, local)
   223  	s.Attr.Set(sym.AttrMakeTypelink, makeTypelink)
   224  	if typ != nil {
   225  		s.Gotype = typ
   226  	}
   227  	if isdup && typ != nil { // if bss sym defined multiple times, take type from any one def
   228  		dup.Gotype = typ
   229  	}
   230  	s.P = data
   231  	if nreloc > 0 {
   232  		s.R = r.reloc[:nreloc:nreloc]
   233  		if !isdup {
   234  			r.reloc = r.reloc[nreloc:]
   235  		}
   236  
   237  		for i := 0; i < nreloc; i++ {
   238  			s.R[i] = sym.Reloc{
   239  				Off:  r.readInt32(),
   240  				Siz:  r.readUint8(),
   241  				Type: objabi.RelocType(r.readInt32()),
   242  				Add:  r.readInt64(),
   243  				Sym:  r.readSymIndex(),
   244  			}
   245  		}
   246  	}
   247  
   248  	if s.Type == sym.STEXT {
   249  		s.FuncInfo = new(sym.FuncInfo)
   250  		pc := s.FuncInfo
   251  
   252  		pc.Args = r.readInt32()
   253  		pc.Locals = r.readInt32()
   254  		if r.readUint8() != 0 {
   255  			s.Attr |= sym.AttrNoSplit
   256  		}
   257  		flags := r.readInt()
   258  		if flags&(1<<2) != 0 {
   259  			s.Attr |= sym.AttrReflectMethod
   260  		}
   261  		if flags&(1<<3) != 0 {
   262  			s.Attr |= sym.AttrShared
   263  		}
   264  		n := r.readInt()
   265  		pc.Autom = r.autom[:n:n]
   266  		if !isdup {
   267  			r.autom = r.autom[n:]
   268  		}
   269  
   270  		for i := 0; i < n; i++ {
   271  			pc.Autom[i] = sym.Auto{
   272  				Asym:    r.readSymIndex(),
   273  				Aoffset: r.readInt32(),
   274  				Name:    r.readInt16(),
   275  				Gotype:  r.readSymIndex(),
   276  			}
   277  		}
   278  
   279  		pc.Pcsp.P = r.readData()
   280  		pc.Pcfile.P = r.readData()
   281  		pc.Pcline.P = r.readData()
   282  		pc.Pcinline.P = r.readData()
   283  		n = r.readInt()
   284  		pc.Pcdata = r.pcdata[:n:n]
   285  		if !isdup {
   286  			r.pcdata = r.pcdata[n:]
   287  		}
   288  		for i := 0; i < n; i++ {
   289  			pc.Pcdata[i].P = r.readData()
   290  		}
   291  		n = r.readInt()
   292  		pc.Funcdata = r.funcdata[:n:n]
   293  		pc.Funcdataoff = r.funcdataoff[:n:n]
   294  		if !isdup {
   295  			r.funcdata = r.funcdata[n:]
   296  			r.funcdataoff = r.funcdataoff[n:]
   297  		}
   298  		for i := 0; i < n; i++ {
   299  			pc.Funcdata[i] = r.readSymIndex()
   300  		}
   301  		for i := 0; i < n; i++ {
   302  			pc.Funcdataoff[i] = r.readInt64()
   303  		}
   304  		n = r.readInt()
   305  		pc.File = r.file[:n:n]
   306  		if !isdup {
   307  			r.file = r.file[n:]
   308  		}
   309  		for i := 0; i < n; i++ {
   310  			pc.File[i] = r.readSymIndex()
   311  		}
   312  		n = r.readInt()
   313  		pc.InlTree = make([]sym.InlinedCall, n)
   314  		for i := 0; i < n; i++ {
   315  			pc.InlTree[i].Parent = r.readInt32()
   316  			pc.InlTree[i].File = r.readSymIndex()
   317  			pc.InlTree[i].Line = r.readInt32()
   318  			pc.InlTree[i].Func = r.readSymIndex()
   319  		}
   320  
   321  		s.Lib = r.lib
   322  		if !dupok {
   323  			if s.Attr.OnList() {
   324  				log.Fatalf("symbol %s listed multiple times", s.Name)
   325  			}
   326  			s.Attr |= sym.AttrOnList
   327  			r.lib.Textp = append(r.lib.Textp, s)
   328  		} else {
   329  			// there may ba a dup in another package
   330  			// put into a temp list and add to text later
   331  			if !isdup {
   332  				r.lib.DupTextSyms = append(r.lib.DupTextSyms, s)
   333  			} else {
   334  				r.lib.DupTextSyms = append(r.lib.DupTextSyms, dup)
   335  			}
   336  		}
   337  	}
   338  	if s.Type == sym.SDWARFINFO {
   339  		r.patchDWARFName(s)
   340  	}
   341  }
   342  
   343  func (r *objReader) patchDWARFName(s *sym.Symbol) {
   344  	// This is kind of ugly. Really the package name should not
   345  	// even be included here.
   346  	if s.Size < 1 || s.P[0] != dwarf.DW_ABRV_FUNCTION {
   347  		return
   348  	}
   349  	e := bytes.IndexByte(s.P, 0)
   350  	if e == -1 {
   351  		return
   352  	}
   353  	p := bytes.Index(s.P[:e], emptyPkg)
   354  	if p == -1 {
   355  		return
   356  	}
   357  	pkgprefix := []byte(objabi.PathToPrefix(r.lib.Pkg) + ".")
   358  	patched := bytes.Replace(s.P[:e], emptyPkg, pkgprefix, -1)
   359  
   360  	s.P = append(patched, s.P[e:]...)
   361  	delta := int64(len(s.P)) - s.Size
   362  	s.Size = int64(len(s.P))
   363  	for i := range s.R {
   364  		r := &s.R[i]
   365  		if r.Off > int32(e) {
   366  			r.Off += int32(delta)
   367  		}
   368  	}
   369  }
   370  
   371  func (r *objReader) readFull(b []byte) {
   372  	_, err := io.ReadFull(r.rd, b)
   373  	if err != nil {
   374  		log.Fatalf("%s: error reading %s", r.pn, err)
   375  	}
   376  }
   377  
   378  func (r *objReader) readRef() {
   379  	if c, err := r.rd.ReadByte(); c != symPrefix || err != nil {
   380  		log.Fatalf("readSym out of sync")
   381  	}
   382  	name := r.readSymName()
   383  	v := r.readInt()
   384  	if v != 0 && v != 1 {
   385  		log.Fatalf("invalid symbol version for %q: %d", name, v)
   386  	}
   387  	if v == 1 {
   388  		v = r.localSymVersion
   389  	}
   390  	s := r.syms.Lookup(name, v)
   391  	r.refs = append(r.refs, s)
   392  
   393  	if s == nil || v != 0 {
   394  		return
   395  	}
   396  	if s.Name[0] == '$' && len(s.Name) > 5 && s.Type == 0 && len(s.P) == 0 {
   397  		x, err := strconv.ParseUint(s.Name[5:], 16, 64)
   398  		if err != nil {
   399  			log.Panicf("failed to parse $-symbol %s: %v", s.Name, err)
   400  		}
   401  		s.Type = sym.SRODATA
   402  		s.Attr |= sym.AttrLocal
   403  		switch s.Name[:5] {
   404  		case "$f32.":
   405  			if uint64(uint32(x)) != x {
   406  				log.Panicf("$-symbol %s too large: %d", s.Name, x)
   407  			}
   408  			s.AddUint32(r.arch, uint32(x))
   409  		case "$f64.", "$i64.":
   410  			s.AddUint64(r.arch, x)
   411  		default:
   412  			log.Panicf("unrecognized $-symbol: %s", s.Name)
   413  		}
   414  		s.Attr.Set(sym.AttrReachable, false)
   415  	}
   416  	if strings.HasPrefix(s.Name, "runtime.gcbits.") {
   417  		s.Attr |= sym.AttrLocal
   418  	}
   419  }
   420  
   421  func (r *objReader) readInt64() int64 {
   422  	uv := uint64(0)
   423  	for shift := uint(0); ; shift += 7 {
   424  		if shift >= 64 {
   425  			log.Fatalf("corrupt input")
   426  		}
   427  		c, err := r.rd.ReadByte()
   428  		if err != nil {
   429  			log.Fatalln("error reading input: ", err)
   430  		}
   431  		uv |= uint64(c&0x7F) << shift
   432  		if c&0x80 == 0 {
   433  			break
   434  		}
   435  	}
   436  
   437  	return int64(uv>>1) ^ (int64(uv<<63) >> 63)
   438  }
   439  
   440  func (r *objReader) readInt() int {
   441  	n := r.readInt64()
   442  	if int64(int(n)) != n {
   443  		log.Panicf("%v out of range for int", n)
   444  	}
   445  	return int(n)
   446  }
   447  
   448  func (r *objReader) readInt32() int32 {
   449  	n := r.readInt64()
   450  	if int64(int32(n)) != n {
   451  		log.Panicf("%v out of range for int32", n)
   452  	}
   453  	return int32(n)
   454  }
   455  
   456  func (r *objReader) readInt16() int16 {
   457  	n := r.readInt64()
   458  	if int64(int16(n)) != n {
   459  		log.Panicf("%v out of range for int16", n)
   460  	}
   461  	return int16(n)
   462  }
   463  
   464  func (r *objReader) readUint8() uint8 {
   465  	n := r.readInt64()
   466  	if int64(uint8(n)) != n {
   467  		log.Panicf("%v out of range for uint8", n)
   468  	}
   469  	return uint8(n)
   470  }
   471  
   472  func (r *objReader) readString() string {
   473  	n := r.readInt()
   474  	if cap(r.rdBuf) < n {
   475  		r.rdBuf = make([]byte, 2*n)
   476  	}
   477  	r.readFull(r.rdBuf[:n])
   478  	return string(r.rdBuf[:n])
   479  }
   480  
   481  func (r *objReader) readData() []byte {
   482  	n := r.readInt()
   483  	p := r.data[:n:n]
   484  	r.data = r.data[n:]
   485  	return p
   486  }
   487  
   488  // readSymName reads a symbol name, replacing all "". with pkg.
   489  func (r *objReader) readSymName() string {
   490  	pkg := objabi.PathToPrefix(r.lib.Pkg)
   491  	n := r.readInt()
   492  	if n == 0 {
   493  		r.readInt64()
   494  		return ""
   495  	}
   496  	if cap(r.rdBuf) < n {
   497  		r.rdBuf = make([]byte, 2*n)
   498  	}
   499  	origName, err := r.rd.Peek(n)
   500  	if err == bufio.ErrBufferFull {
   501  		// Long symbol names are rare but exist. One source is type
   502  		// symbols for types with long string forms. See #15104.
   503  		origName = make([]byte, n)
   504  		r.readFull(origName)
   505  	} else if err != nil {
   506  		log.Fatalf("%s: error reading symbol: %v", r.pn, err)
   507  	}
   508  	adjName := r.rdBuf[:0]
   509  	for {
   510  		i := bytes.Index(origName, emptyPkg)
   511  		if i == -1 {
   512  			s := string(append(adjName, origName...))
   513  			// Read past the peeked origName, now that we're done with it,
   514  			// using the rfBuf (also no longer used) as the scratch space.
   515  			// TODO: use bufio.Reader.Discard if available instead?
   516  			if err == nil {
   517  				r.readFull(r.rdBuf[:n])
   518  			}
   519  			r.rdBuf = adjName[:0] // in case 2*n wasn't enough
   520  			return s
   521  		}
   522  		adjName = append(adjName, origName[:i]...)
   523  		adjName = append(adjName, pkg...)
   524  		adjName = append(adjName, '.')
   525  		origName = origName[i+len(emptyPkg):]
   526  	}
   527  }
   528  
   529  // Reads the index of a symbol reference and resolves it to a symbol
   530  func (r *objReader) readSymIndex() *sym.Symbol {
   531  	i := r.readInt()
   532  	return r.refs[i]
   533  }