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