...

Source file src/pkg/cmd/link/internal/objfile/objfile.go

     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		"fmt"
    21		"io"
    22		"log"
    23		"os"
    24		"strconv"
    25		"strings"
    26		"unsafe"
    27	)
    28	
    29	const (
    30		startmagic = "\x00go112ld"
    31		endmagic   = "\xffgo112ld"
    32	)
    33	
    34	var emptyPkg = []byte(`"".`)
    35	
    36	// objReader reads Go object files.
    37	type objReader struct {
    38		rd              *bio.Reader
    39		arch            *sys.Arch
    40		syms            *sym.Symbols
    41		lib             *sym.Library
    42		pn              string
    43		dupSym          *sym.Symbol
    44		localSymVersion int
    45		flags           int
    46		strictDupMsgs   int
    47		dataSize        int
    48	
    49		// rdBuf is used by readString and readSymName as scratch for reading strings.
    50		rdBuf []byte
    51	
    52		// List of symbol references for the file being read.
    53		refs        []*sym.Symbol
    54		data        []byte
    55		reloc       []sym.Reloc
    56		pcdata      []sym.Pcdata
    57		autom       []sym.Auto
    58		funcdata    []*sym.Symbol
    59		funcdataoff []int64
    60		file        []*sym.Symbol
    61		pkgpref     string // objabi.PathToPrefix(r.lib.Pkg) + "."
    62	
    63		roObject []byte // from read-only mmap of object file (may be nil)
    64		roOffset int64  // offset into readonly object data examined so far
    65	
    66		dataReadOnly bool // whether data is backed by read-only memory
    67	}
    68	
    69	// Flags to enable optional behavior during object loading/reading.
    70	
    71	const (
    72		NoFlag int = iota
    73	
    74		// Sanity-check duplicate symbol contents, issuing warning
    75		// when duplicates have different lengths or contents.
    76		StrictDupsWarnFlag
    77	
    78		// Similar to StrictDupsWarnFlag, but issue fatal error.
    79		StrictDupsErrFlag
    80	)
    81	
    82	// Load loads an object file f into library lib.
    83	// The symbols loaded are added to syms.
    84	func Load(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *sym.Library, length int64, pn string, flags int) int {
    85		start := f.Offset()
    86		roObject := f.SliceRO(uint64(length))
    87		if roObject != nil {
    88			f.MustSeek(int64(-length), os.SEEK_CUR)
    89		}
    90		r := &objReader{
    91			rd:              f,
    92			lib:             lib,
    93			arch:            arch,
    94			syms:            syms,
    95			pn:              pn,
    96			dupSym:          &sym.Symbol{Name: ".dup"},
    97			localSymVersion: syms.IncVersion(),
    98			flags:           flags,
    99			roObject:        roObject,
   100			pkgpref:         objabi.PathToPrefix(lib.Pkg) + ".",
   101		}
   102		r.loadObjFile()
   103		if roObject != nil {
   104			if r.roOffset != length {
   105				log.Fatalf("%s: unexpected end at %d, want %d", pn, r.roOffset, start+length)
   106			}
   107			r.rd.MustSeek(int64(length), os.SEEK_CUR)
   108		} else if f.Offset() != start+length {
   109			log.Fatalf("%s: unexpected end at %d, want %d", pn, f.Offset(), start+length)
   110		}
   111		return r.strictDupMsgs
   112	}
   113	
   114	func (r *objReader) loadObjFile() {
   115		// Magic header
   116		var buf [8]uint8
   117		r.readFull(buf[:])
   118		if string(buf[:]) != startmagic {
   119			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])
   120		}
   121	
   122		// Version
   123		c, err := r.readByte()
   124		if err != nil || c != 1 {
   125			log.Fatalf("%s: invalid file version number %d", r.pn, c)
   126		}
   127	
   128		// Autolib
   129		for {
   130			lib := r.readString()
   131			if lib == "" {
   132				break
   133			}
   134			r.lib.ImportStrings = append(r.lib.ImportStrings, lib)
   135		}
   136	
   137		// Symbol references
   138		r.refs = []*sym.Symbol{nil} // zeroth ref is nil
   139		for {
   140			c, err := r.peek(1)
   141			if err != nil {
   142				log.Fatalf("%s: peeking: %v", r.pn, err)
   143			}
   144			if c[0] == 0xff {
   145				r.readByte()
   146				break
   147			}
   148			r.readRef()
   149		}
   150	
   151		// Lengths
   152		r.readSlices()
   153	
   154		// Data section
   155		err = r.readDataSection()
   156		if err != nil {
   157			log.Fatalf("%s: error reading %s", r.pn, err)
   158		}
   159	
   160		// Defined symbols
   161		for {
   162			c, err := r.peek(1)
   163			if err != nil {
   164				log.Fatalf("%s: peeking: %v", r.pn, err)
   165			}
   166			if c[0] == 0xff {
   167				break
   168			}
   169			r.readSym()
   170		}
   171	
   172		// Magic footer
   173		buf = [8]uint8{}
   174		r.readFull(buf[:])
   175		if string(buf[:]) != endmagic {
   176			log.Fatalf("%s: invalid file end", r.pn)
   177		}
   178	}
   179	
   180	func (r *objReader) readSlices() {
   181		r.dataSize = r.readInt()
   182		n := r.readInt()
   183		r.reloc = make([]sym.Reloc, n)
   184		n = r.readInt()
   185		r.pcdata = make([]sym.Pcdata, n)
   186		n = r.readInt()
   187		r.autom = make([]sym.Auto, n)
   188		n = r.readInt()
   189		r.funcdata = make([]*sym.Symbol, n)
   190		r.funcdataoff = make([]int64, n)
   191		n = r.readInt()
   192		r.file = make([]*sym.Symbol, n)
   193	}
   194	
   195	func (r *objReader) readDataSection() (err error) {
   196		if r.roObject != nil {
   197			r.data, r.dataReadOnly, err =
   198				r.roObject[r.roOffset:r.roOffset+int64(r.dataSize)], true, nil
   199			r.roOffset += int64(r.dataSize)
   200			return
   201		}
   202		r.data, r.dataReadOnly, err = r.rd.Slice(uint64(r.dataSize))
   203		return
   204	}
   205	
   206	// Symbols are prefixed so their content doesn't get confused with the magic footer.
   207	const symPrefix = 0xfe
   208	
   209	func (r *objReader) readSym() {
   210		var c byte
   211		var err error
   212		if c, err = r.readByte(); c != symPrefix || err != nil {
   213			log.Fatalln("readSym out of sync")
   214		}
   215		if c, err = r.readByte(); err != nil {
   216			log.Fatalln("error reading input: ", err)
   217		}
   218		t := sym.AbiSymKindToSymKind[c]
   219		s := r.readSymIndex()
   220		flags := r.readInt()
   221		dupok := flags&1 != 0
   222		local := flags&2 != 0
   223		makeTypelink := flags&4 != 0
   224		size := r.readInt()
   225		typ := r.readSymIndex()
   226		data := r.readData()
   227		nreloc := r.readInt()
   228		isdup := false
   229	
   230		var dup *sym.Symbol
   231		if s.Type != 0 && s.Type != sym.SXREF {
   232			if (t == sym.SDATA || t == sym.SBSS || t == sym.SNOPTRBSS) && len(data) == 0 && nreloc == 0 {
   233				if s.Size < int64(size) {
   234					s.Size = int64(size)
   235				}
   236				if typ != nil && s.Gotype == nil {
   237					s.Gotype = typ
   238				}
   239				return
   240			}
   241	
   242			if (s.Type == sym.SDATA || s.Type == sym.SBSS || s.Type == sym.SNOPTRBSS) && len(s.P) == 0 && len(s.R) == 0 {
   243				goto overwrite
   244			}
   245			if s.Type != sym.SBSS && s.Type != sym.SNOPTRBSS && !dupok && !s.Attr.DuplicateOK() {
   246				log.Fatalf("duplicate symbol %s (types %d and %d) in %s and %s", s.Name, s.Type, t, s.File, r.pn)
   247			}
   248			if len(s.P) > 0 {
   249				dup = s
   250				s = r.dupSym
   251				isdup = true
   252			}
   253		}
   254	
   255	overwrite:
   256		s.File = r.pkgpref[:len(r.pkgpref)-1]
   257		s.Lib = r.lib
   258		if dupok {
   259			s.Attr |= sym.AttrDuplicateOK
   260		}
   261		if t == sym.SXREF {
   262			log.Fatalf("bad sxref")
   263		}
   264		if t == 0 {
   265			log.Fatalf("missing type for %s in %s", s.Name, r.pn)
   266		}
   267		if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) {
   268			t = s.Type
   269		}
   270		s.Type = t
   271		if s.Size < int64(size) {
   272			s.Size = int64(size)
   273		}
   274		s.Attr.Set(sym.AttrLocal, local)
   275		s.Attr.Set(sym.AttrMakeTypelink, makeTypelink)
   276		if typ != nil {
   277			s.Gotype = typ
   278		}
   279		if isdup && typ != nil { // if bss sym defined multiple times, take type from any one def
   280			dup.Gotype = typ
   281		}
   282		s.P = data
   283		s.Attr.Set(sym.AttrReadOnly, r.dataReadOnly)
   284		if nreloc > 0 {
   285			s.R = r.reloc[:nreloc:nreloc]
   286			if !isdup {
   287				r.reloc = r.reloc[nreloc:]
   288			}
   289	
   290			for i := 0; i < nreloc; i++ {
   291				s.R[i] = sym.Reloc{
   292					Off:  r.readInt32(),
   293					Siz:  r.readUint8(),
   294					Type: objabi.RelocType(r.readInt32()),
   295					Add:  r.readInt64(),
   296					Sym:  r.readSymIndex(),
   297				}
   298			}
   299		}
   300	
   301		if s.Type == sym.STEXT {
   302			s.FuncInfo = new(sym.FuncInfo)
   303			pc := s.FuncInfo
   304	
   305			pc.Args = r.readInt32()
   306			pc.Locals = r.readInt32()
   307			if r.readUint8() != 0 {
   308				s.Attr |= sym.AttrNoSplit
   309			}
   310			flags := r.readInt()
   311			if flags&(1<<2) != 0 {
   312				s.Attr |= sym.AttrReflectMethod
   313			}
   314			if flags&(1<<3) != 0 {
   315				s.Attr |= sym.AttrShared
   316			}
   317			if flags&(1<<4) != 0 {
   318				s.Attr |= sym.AttrTopFrame
   319			}
   320			n := r.readInt()
   321			pc.Autom = r.autom[:n:n]
   322			if !isdup {
   323				r.autom = r.autom[n:]
   324			}
   325	
   326			for i := 0; i < n; i++ {
   327				pc.Autom[i] = sym.Auto{
   328					Asym:    r.readSymIndex(),
   329					Aoffset: r.readInt32(),
   330					Name:    r.readInt16(),
   331					Gotype:  r.readSymIndex(),
   332				}
   333			}
   334	
   335			pc.Pcsp.P = r.readData()
   336			pc.Pcfile.P = r.readData()
   337			pc.Pcline.P = r.readData()
   338			pc.Pcinline.P = r.readData()
   339			n = r.readInt()
   340			pc.Pcdata = r.pcdata[:n:n]
   341			if !isdup {
   342				r.pcdata = r.pcdata[n:]
   343			}
   344			for i := 0; i < n; i++ {
   345				pc.Pcdata[i].P = r.readData()
   346			}
   347			n = r.readInt()
   348			pc.Funcdata = r.funcdata[:n:n]
   349			pc.Funcdataoff = r.funcdataoff[:n:n]
   350			if !isdup {
   351				r.funcdata = r.funcdata[n:]
   352				r.funcdataoff = r.funcdataoff[n:]
   353			}
   354			for i := 0; i < n; i++ {
   355				pc.Funcdata[i] = r.readSymIndex()
   356			}
   357			for i := 0; i < n; i++ {
   358				pc.Funcdataoff[i] = r.readInt64()
   359			}
   360			n = r.readInt()
   361			pc.File = r.file[:n:n]
   362			if !isdup {
   363				r.file = r.file[n:]
   364			}
   365			for i := 0; i < n; i++ {
   366				pc.File[i] = r.readSymIndex()
   367			}
   368			n = r.readInt()
   369			pc.InlTree = make([]sym.InlinedCall, n)
   370			for i := 0; i < n; i++ {
   371				pc.InlTree[i].Parent = r.readInt32()
   372				pc.InlTree[i].File = r.readSymIndex()
   373				pc.InlTree[i].Line = r.readInt32()
   374				pc.InlTree[i].Func = r.readSymIndex()
   375				pc.InlTree[i].ParentPC = r.readInt32()
   376			}
   377	
   378			if !dupok {
   379				if s.Attr.OnList() {
   380					log.Fatalf("symbol %s listed multiple times", s.Name)
   381				}
   382				s.Attr |= sym.AttrOnList
   383				r.lib.Textp = append(r.lib.Textp, s)
   384			} else {
   385				// there may ba a dup in another package
   386				// put into a temp list and add to text later
   387				if !isdup {
   388					r.lib.DupTextSyms = append(r.lib.DupTextSyms, s)
   389				} else {
   390					r.lib.DupTextSyms = append(r.lib.DupTextSyms, dup)
   391				}
   392			}
   393		}
   394		if s.Type == sym.SDWARFINFO {
   395			r.patchDWARFName(s)
   396		}
   397	
   398		if isdup && r.flags&(StrictDupsWarnFlag|StrictDupsErrFlag) != 0 {
   399			// Compare the just-read symbol with the previously read
   400			// symbol of the same name, verifying that they have the same
   401			// payload. If not, issue a warning and possibly an error.
   402			if !bytes.Equal(s.P, dup.P) {
   403				reason := "same length but different contents"
   404				if len(s.P) != len(dup.P) {
   405					reason = fmt.Sprintf("new length %d != old length %d",
   406						len(data), len(dup.P))
   407				}
   408				fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.lib, dup, dup.Lib, reason)
   409	
   410				// For the moment, whitelist DWARF subprogram DIEs for
   411				// auto-generated wrapper functions. What seems to happen
   412				// here is that we get different line numbers on formal
   413				// params; I am guessing that the pos is being inherited
   414				// from the spot where the wrapper is needed.
   415				whitelist := (strings.HasPrefix(dup.Name, "go.info.go.interface") ||
   416					strings.HasPrefix(dup.Name, "go.info.go.builtin") ||
   417					strings.HasPrefix(dup.Name, "go.isstmt.go.builtin"))
   418				if !whitelist {
   419					r.strictDupMsgs++
   420				}
   421			}
   422		}
   423	}
   424	
   425	func (r *objReader) patchDWARFName(s *sym.Symbol) {
   426		// This is kind of ugly. Really the package name should not
   427		// even be included here.
   428		if s.Size < 1 || s.P[0] != dwarf.DW_ABRV_FUNCTION {
   429			return
   430		}
   431		e := bytes.IndexByte(s.P, 0)
   432		if e == -1 {
   433			return
   434		}
   435		p := bytes.Index(s.P[:e], emptyPkg)
   436		if p == -1 {
   437			return
   438		}
   439		pkgprefix := []byte(r.pkgpref)
   440		patched := bytes.Replace(s.P[:e], emptyPkg, pkgprefix, -1)
   441	
   442		s.P = append(patched, s.P[e:]...)
   443		delta := int64(len(s.P)) - s.Size
   444		s.Size = int64(len(s.P))
   445		for i := range s.R {
   446			r := &s.R[i]
   447			if r.Off > int32(e) {
   448				r.Off += int32(delta)
   449			}
   450		}
   451	}
   452	
   453	func (r *objReader) readFull(b []byte) {
   454		if r.roObject != nil {
   455			copy(b, r.roObject[r.roOffset:])
   456			r.roOffset += int64(len(b))
   457			return
   458		}
   459		_, err := io.ReadFull(r.rd, b)
   460		if err != nil {
   461			log.Fatalf("%s: error reading %s", r.pn, err)
   462		}
   463	}
   464	
   465	func (r *objReader) readByte() (byte, error) {
   466		if r.roObject != nil {
   467			b := r.roObject[r.roOffset]
   468			r.roOffset++
   469			return b, nil
   470		}
   471		return r.rd.ReadByte()
   472	}
   473	
   474	func (r *objReader) peek(n int) ([]byte, error) {
   475		if r.roObject != nil {
   476			return r.roObject[r.roOffset : r.roOffset+int64(n)], nil
   477		}
   478		return r.rd.Peek(n)
   479	}
   480	
   481	func (r *objReader) readRef() {
   482		if c, err := r.readByte(); c != symPrefix || err != nil {
   483			log.Fatalf("readSym out of sync")
   484		}
   485		name := r.readSymName()
   486		var v int
   487		if abi := r.readInt(); abi == -1 {
   488			// Static
   489			v = r.localSymVersion
   490		} else if abiver := sym.ABIToVersion(obj.ABI(abi)); abiver != -1 {
   491			// Note that data symbols are "ABI0", which maps to version 0.
   492			v = abiver
   493		} else {
   494			log.Fatalf("invalid symbol ABI for %q: %d", name, abi)
   495		}
   496		s := r.syms.Lookup(name, v)
   497		r.refs = append(r.refs, s)
   498	
   499		if s == nil || v == r.localSymVersion {
   500			return
   501		}
   502		if s.Name[0] == '$' && len(s.Name) > 5 && s.Type == 0 && len(s.P) == 0 {
   503			x, err := strconv.ParseUint(s.Name[5:], 16, 64)
   504			if err != nil {
   505				log.Panicf("failed to parse $-symbol %s: %v", s.Name, err)
   506			}
   507			s.Type = sym.SRODATA
   508			s.Attr |= sym.AttrLocal
   509			switch s.Name[:5] {
   510			case "$f32.":
   511				if uint64(uint32(x)) != x {
   512					log.Panicf("$-symbol %s too large: %d", s.Name, x)
   513				}
   514				s.AddUint32(r.arch, uint32(x))
   515			case "$f64.", "$i64.":
   516				s.AddUint64(r.arch, x)
   517			default:
   518				log.Panicf("unrecognized $-symbol: %s", s.Name)
   519			}
   520			s.Attr.Set(sym.AttrReachable, false)
   521		}
   522		if strings.HasPrefix(s.Name, "runtime.gcbits.") {
   523			s.Attr |= sym.AttrLocal
   524		}
   525	}
   526	
   527	func (r *objReader) readInt64() int64 {
   528		uv := uint64(0)
   529		for shift := uint(0); ; shift += 7 {
   530			if shift >= 64 {
   531				log.Fatalf("corrupt input")
   532			}
   533			c, err := r.readByte()
   534			if err != nil {
   535				log.Fatalln("error reading input: ", err)
   536			}
   537			uv |= uint64(c&0x7F) << shift
   538			if c&0x80 == 0 {
   539				break
   540			}
   541		}
   542	
   543		return int64(uv>>1) ^ (int64(uv<<63) >> 63)
   544	}
   545	
   546	func (r *objReader) readInt() int {
   547		n := r.readInt64()
   548		if int64(int(n)) != n {
   549			log.Panicf("%v out of range for int", n)
   550		}
   551		return int(n)
   552	}
   553	
   554	func (r *objReader) readInt32() int32 {
   555		n := r.readInt64()
   556		if int64(int32(n)) != n {
   557			log.Panicf("%v out of range for int32", n)
   558		}
   559		return int32(n)
   560	}
   561	
   562	func (r *objReader) readInt16() int16 {
   563		n := r.readInt64()
   564		if int64(int16(n)) != n {
   565			log.Panicf("%v out of range for int16", n)
   566		}
   567		return int16(n)
   568	}
   569	
   570	func (r *objReader) readUint8() uint8 {
   571		n := r.readInt64()
   572		if int64(uint8(n)) != n {
   573			log.Panicf("%v out of range for uint8", n)
   574		}
   575		return uint8(n)
   576	}
   577	
   578	func (r *objReader) readString() string {
   579		n := r.readInt()
   580		if cap(r.rdBuf) < n {
   581			r.rdBuf = make([]byte, 2*n)
   582		}
   583		r.readFull(r.rdBuf[:n])
   584		return string(r.rdBuf[:n])
   585	}
   586	
   587	func (r *objReader) readData() []byte {
   588		n := r.readInt()
   589		p := r.data[:n:n]
   590		r.data = r.data[n:]
   591		return p
   592	}
   593	
   594	type stringHeader struct {
   595		str unsafe.Pointer
   596		len int
   597	}
   598	
   599	func mkROString(rodata []byte) string {
   600		if len(rodata) == 0 {
   601			return ""
   602		}
   603		ss := stringHeader{str: unsafe.Pointer(&rodata[0]), len: len(rodata)}
   604		s := *(*string)(unsafe.Pointer(&ss))
   605		return s
   606	}
   607	
   608	// readSymName reads a symbol name, replacing all "". with pkg.
   609	func (r *objReader) readSymName() string {
   610		n := r.readInt()
   611		if n == 0 {
   612			r.readInt64()
   613			return ""
   614		}
   615		if cap(r.rdBuf) < n {
   616			r.rdBuf = make([]byte, 2*n)
   617		}
   618		sOffset := r.roOffset
   619		origName, err := r.peek(n)
   620		if err == bufio.ErrBufferFull {
   621			// Long symbol names are rare but exist. One source is type
   622			// symbols for types with long string forms. See #15104.
   623			origName = make([]byte, n)
   624			r.readFull(origName)
   625		} else if err != nil {
   626			log.Fatalf("%s: error reading symbol: %v", r.pn, err)
   627		}
   628		adjName := r.rdBuf[:0]
   629		nPkgRefs := 0
   630		for {
   631			i := bytes.Index(origName, emptyPkg)
   632			if i == -1 {
   633				var s string
   634				if r.roObject != nil && nPkgRefs == 0 {
   635					s = mkROString(r.roObject[sOffset : sOffset+int64(n)])
   636				} else {
   637					s = string(append(adjName, origName...))
   638				}
   639				// Read past the peeked origName, now that we're done with it,
   640				// using the rfBuf (also no longer used) as the scratch space.
   641				// TODO: use bufio.Reader.Discard if available instead?
   642				if err == nil {
   643					r.readFull(r.rdBuf[:n])
   644				}
   645				r.rdBuf = adjName[:0] // in case 2*n wasn't enough
   646				return s
   647			}
   648			nPkgRefs++
   649			adjName = append(adjName, origName[:i]...)
   650			adjName = append(adjName, r.pkgpref[:len(r.pkgpref)-1]...)
   651			adjName = append(adjName, '.')
   652			origName = origName[i+len(emptyPkg):]
   653		}
   654	}
   655	
   656	// Reads the index of a symbol reference and resolves it to a symbol
   657	func (r *objReader) readSymIndex() *sym.Symbol {
   658		i := r.readInt()
   659		return r.refs[i]
   660	}
   661	

View as plain text