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