github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/cmd/link/internal/ld/ldelf.go (about)

     1  package ld
     2  
     3  import (
     4  	"bytes"
     5  	"cmd/internal/obj"
     6  	"encoding/binary"
     7  	"fmt"
     8  	"io"
     9  	"log"
    10  	"sort"
    11  	"strings"
    12  )
    13  
    14  /*
    15  Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c
    16  http://code.swtch.com/plan9port/src/tip/src/libmach/
    17  
    18  	Copyright © 2004 Russ Cox.
    19  	Portions Copyright © 2008-2010 Google Inc.
    20  	Portions Copyright © 2010 The Go Authors.
    21  
    22  Permission is hereby granted, free of charge, to any person obtaining a copy
    23  of this software and associated documentation files (the "Software"), to deal
    24  in the Software without restriction, including without limitation the rights
    25  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    26  copies of the Software, and to permit persons to whom the Software is
    27  furnished to do so, subject to the following conditions:
    28  
    29  The above copyright notice and this permission notice shall be included in
    30  all copies or substantial portions of the Software.
    31  
    32  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    33  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    34  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    35  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    36  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    37  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    38  THE SOFTWARE.
    39  */
    40  const (
    41  	ElfClassNone = 0
    42  	ElfClass32   = 1
    43  	ElfClass64   = 2
    44  )
    45  
    46  const (
    47  	ElfDataNone = 0
    48  	ElfDataLsb  = 1
    49  	ElfDataMsb  = 2
    50  )
    51  
    52  const (
    53  	ElfTypeNone         = 0
    54  	ElfTypeRelocatable  = 1
    55  	ElfTypeExecutable   = 2
    56  	ElfTypeSharedObject = 3
    57  	ElfTypeCore         = 4
    58  )
    59  
    60  const (
    61  	ElfMachNone        = 0
    62  	ElfMach32100       = 1
    63  	ElfMachSparc       = 2
    64  	ElfMach386         = 3
    65  	ElfMach68000       = 4
    66  	ElfMach88000       = 5
    67  	ElfMach486         = 6
    68  	ElfMach860         = 7
    69  	ElfMachMips        = 8
    70  	ElfMachS370        = 9
    71  	ElfMachMipsLe      = 10
    72  	ElfMachParisc      = 15
    73  	ElfMachVpp500      = 17
    74  	ElfMachSparc32Plus = 18
    75  	ElfMach960         = 19
    76  	ElfMachPower       = 20
    77  	ElfMachPower64     = 21
    78  	ElfMachS390        = 22
    79  	ElfMachV800        = 36
    80  	ElfMachFr20        = 37
    81  	ElfMachRh32        = 38
    82  	ElfMachRce         = 39
    83  	ElfMachArm         = 40
    84  	ElfMachAlpha       = 41
    85  	ElfMachSH          = 42
    86  	ElfMachSparc9      = 43
    87  	ElfMachAmd64       = 62
    88  	ElfMachArm64       = 183
    89  )
    90  
    91  const (
    92  	ElfAbiNone     = 0
    93  	ElfAbiSystemV  = 0
    94  	ElfAbiHPUX     = 1
    95  	ElfAbiNetBSD   = 2
    96  	ElfAbiLinux    = 3
    97  	ElfAbiSolaris  = 6
    98  	ElfAbiAix      = 7
    99  	ElfAbiIrix     = 8
   100  	ElfAbiFreeBSD  = 9
   101  	ElfAbiTru64    = 10
   102  	ElfAbiModesto  = 11
   103  	ElfAbiOpenBSD  = 12
   104  	ElfAbiARM      = 97
   105  	ElfAbiEmbedded = 255
   106  )
   107  
   108  const (
   109  	ElfSectNone      = 0
   110  	ElfSectProgbits  = 1
   111  	ElfSectSymtab    = 2
   112  	ElfSectStrtab    = 3
   113  	ElfSectRela      = 4
   114  	ElfSectHash      = 5
   115  	ElfSectDynamic   = 6
   116  	ElfSectNote      = 7
   117  	ElfSectNobits    = 8
   118  	ElfSectRel       = 9
   119  	ElfSectShlib     = 10
   120  	ElfSectDynsym    = 11
   121  	ElfSectFlagWrite = 0x1
   122  	ElfSectFlagAlloc = 0x2
   123  	ElfSectFlagExec  = 0x4
   124  )
   125  
   126  const (
   127  	ElfSymBindLocal  = 0
   128  	ElfSymBindGlobal = 1
   129  	ElfSymBindWeak   = 2
   130  )
   131  
   132  const (
   133  	ElfSymTypeNone    = 0
   134  	ElfSymTypeObject  = 1
   135  	ElfSymTypeFunc    = 2
   136  	ElfSymTypeSection = 3
   137  	ElfSymTypeFile    = 4
   138  )
   139  
   140  const (
   141  	ElfSymShnNone   = 0
   142  	ElfSymShnAbs    = 0xFFF1
   143  	ElfSymShnCommon = 0xFFF2
   144  )
   145  
   146  const (
   147  	ElfProgNone      = 0
   148  	ElfProgLoad      = 1
   149  	ElfProgDynamic   = 2
   150  	ElfProgInterp    = 3
   151  	ElfProgNote      = 4
   152  	ElfProgShlib     = 5
   153  	ElfProgPhdr      = 6
   154  	ElfProgFlagExec  = 0x1
   155  	ElfProgFlagWrite = 0x2
   156  	ElfProgFlagRead  = 0x4
   157  )
   158  
   159  const (
   160  	ElfNotePrStatus     = 1
   161  	ElfNotePrFpreg      = 2
   162  	ElfNotePrPsinfo     = 3
   163  	ElfNotePrTaskstruct = 4
   164  	ElfNotePrAuxv       = 6
   165  	ElfNotePrXfpreg     = 0x46e62b7f
   166  )
   167  
   168  type ElfHdrBytes struct {
   169  	Ident     [16]uint8
   170  	Type      [2]uint8
   171  	Machine   [2]uint8
   172  	Version   [4]uint8
   173  	Entry     [4]uint8
   174  	Phoff     [4]uint8
   175  	Shoff     [4]uint8
   176  	Flags     [4]uint8
   177  	Ehsize    [2]uint8
   178  	Phentsize [2]uint8
   179  	Phnum     [2]uint8
   180  	Shentsize [2]uint8
   181  	Shnum     [2]uint8
   182  	Shstrndx  [2]uint8
   183  }
   184  
   185  type ElfSectBytes struct {
   186  	Name    [4]uint8
   187  	Type    [4]uint8
   188  	Flags   [4]uint8
   189  	Addr    [4]uint8
   190  	Off     [4]uint8
   191  	Size    [4]uint8
   192  	Link    [4]uint8
   193  	Info    [4]uint8
   194  	Align   [4]uint8
   195  	Entsize [4]uint8
   196  }
   197  
   198  type ElfProgBytes struct {
   199  }
   200  
   201  type ElfSymBytes struct {
   202  	Name  [4]uint8
   203  	Value [4]uint8
   204  	Size  [4]uint8
   205  	Info  uint8
   206  	Other uint8
   207  	Shndx [2]uint8
   208  }
   209  
   210  type ElfHdrBytes64 struct {
   211  	Ident     [16]uint8
   212  	Type      [2]uint8
   213  	Machine   [2]uint8
   214  	Version   [4]uint8
   215  	Entry     [8]uint8
   216  	Phoff     [8]uint8
   217  	Shoff     [8]uint8
   218  	Flags     [4]uint8
   219  	Ehsize    [2]uint8
   220  	Phentsize [2]uint8
   221  	Phnum     [2]uint8
   222  	Shentsize [2]uint8
   223  	Shnum     [2]uint8
   224  	Shstrndx  [2]uint8
   225  }
   226  
   227  type ElfSectBytes64 struct {
   228  	Name    [4]uint8
   229  	Type    [4]uint8
   230  	Flags   [8]uint8
   231  	Addr    [8]uint8
   232  	Off     [8]uint8
   233  	Size    [8]uint8
   234  	Link    [4]uint8
   235  	Info    [4]uint8
   236  	Align   [8]uint8
   237  	Entsize [8]uint8
   238  }
   239  
   240  type ElfProgBytes64 struct {
   241  }
   242  
   243  type ElfSymBytes64 struct {
   244  	Name  [4]uint8
   245  	Info  uint8
   246  	Other uint8
   247  	Shndx [2]uint8
   248  	Value [8]uint8
   249  	Size  [8]uint8
   250  }
   251  
   252  type ElfSect struct {
   253  	name    string
   254  	nameoff uint32
   255  	type_   uint32
   256  	flags   uint64
   257  	addr    uint64
   258  	off     uint64
   259  	size    uint64
   260  	link    uint32
   261  	info    uint32
   262  	align   uint64
   263  	entsize uint64
   264  	base    []byte
   265  	sym     *LSym
   266  }
   267  
   268  type ElfObj struct {
   269  	f         *obj.Biobuf
   270  	base      int64 // offset in f where ELF begins
   271  	length    int64 // length of ELF
   272  	is64      int
   273  	name      string
   274  	e         binary.ByteOrder
   275  	sect      []ElfSect
   276  	nsect     uint
   277  	shstrtab  string
   278  	nsymtab   int
   279  	symtab    *ElfSect
   280  	symstr    *ElfSect
   281  	type_     uint32
   282  	machine   uint32
   283  	version   uint32
   284  	entry     uint64
   285  	phoff     uint64
   286  	shoff     uint64
   287  	flags     uint32
   288  	ehsize    uint32
   289  	phentsize uint32
   290  	phnum     uint32
   291  	shentsize uint32
   292  	shnum     uint32
   293  	shstrndx  uint32
   294  }
   295  
   296  type ElfSym struct {
   297  	name  string
   298  	value uint64
   299  	size  uint64
   300  	bind  uint8
   301  	type_ uint8
   302  	other uint8
   303  	shndx uint16
   304  	sym   *LSym
   305  }
   306  
   307  var ElfMagic = [4]uint8{0x7F, 'E', 'L', 'F'}
   308  
   309  func valuecmp(a *LSym, b *LSym) int {
   310  	if a.Value < b.Value {
   311  		return -1
   312  	}
   313  	if a.Value > b.Value {
   314  		return +1
   315  	}
   316  	return 0
   317  }
   318  
   319  const (
   320  	Tag_file                 = 1
   321  	Tag_CPU_name             = 4
   322  	Tag_CPU_raw_name         = 5
   323  	Tag_compatibility        = 32
   324  	Tag_nodefaults           = 64
   325  	Tag_also_compatible_with = 65
   326  	Tag_ABI_VFP_args         = 28
   327  )
   328  
   329  type elfAttribute struct {
   330  	tag  uint64
   331  	sval string
   332  	ival uint64
   333  }
   334  
   335  type elfAttributeList struct {
   336  	data []byte
   337  	err  error
   338  }
   339  
   340  func (a *elfAttributeList) string() string {
   341  	if a.err != nil {
   342  		return ""
   343  	}
   344  	nul := bytes.IndexByte(a.data, 0)
   345  	if nul < 0 {
   346  		a.err = io.EOF
   347  		return ""
   348  	}
   349  	s := string(a.data[:nul])
   350  	a.data = a.data[nul+1:]
   351  	return s
   352  }
   353  
   354  func (a *elfAttributeList) uleb128() uint64 {
   355  	if a.err != nil {
   356  		return 0
   357  	}
   358  	v, size := binary.Uvarint(a.data)
   359  	a.data = a.data[size:]
   360  	return v
   361  }
   362  
   363  // Read an elfAttribute from the list following the rules used on ARM systems.
   364  func (a *elfAttributeList) armAttr() elfAttribute {
   365  	attr := elfAttribute{tag: a.uleb128()}
   366  	switch {
   367  	case attr.tag == Tag_compatibility:
   368  		attr.ival = a.uleb128()
   369  		attr.sval = a.string()
   370  
   371  	case attr.tag == 64: // Tag_nodefaults has no argument
   372  
   373  	case attr.tag == 65: // Tag_also_compatible_with
   374  		// Not really, but we don't actually care about this tag.
   375  		attr.sval = a.string()
   376  
   377  	// Tag with string argument
   378  	case attr.tag == Tag_CPU_name || attr.tag == Tag_CPU_raw_name || (attr.tag >= 32 && attr.tag&1 != 0):
   379  		attr.sval = a.string()
   380  
   381  	default: // Tag with integer argument
   382  		attr.ival = a.uleb128()
   383  	}
   384  	return attr
   385  }
   386  
   387  func (a *elfAttributeList) done() bool {
   388  	if a.err != nil || len(a.data) == 0 {
   389  		return true
   390  	}
   391  	return false
   392  }
   393  
   394  // Look for the attribute that indicates the object uses the hard-float ABI (a
   395  // file-level attribute with tag Tag_VFP_arch and value 1). Unfortunately the
   396  // format used means that we have to parse all of the file-level attributes to
   397  // find the one we are looking for. This format is slightly documented in "ELF
   398  // for the ARM Architecture" but mostly this is derived from reading the source
   399  // to gold and readelf.
   400  func parseArmAttributes(e binary.ByteOrder, data []byte) {
   401  	// We assume the soft-float ABI unless we see a tag indicating otherwise.
   402  	if ehdr.flags == 0x5000002 {
   403  		ehdr.flags = 0x5000202
   404  	}
   405  	if data[0] != 'A' {
   406  		fmt.Fprintf(&Bso, ".ARM.attributes has unexpected format %c\n", data[0])
   407  		return
   408  	}
   409  	data = data[1:]
   410  	for len(data) != 0 {
   411  		sectionlength := e.Uint32(data)
   412  		sectiondata := data[4:sectionlength]
   413  		data = data[sectionlength:]
   414  
   415  		nulIndex := bytes.IndexByte(sectiondata, 0)
   416  		if nulIndex < 0 {
   417  			fmt.Fprintf(&Bso, "corrupt .ARM.attributes (section name not NUL-terminated)\n")
   418  			return
   419  		}
   420  		name := string(sectiondata[:nulIndex])
   421  		sectiondata = sectiondata[nulIndex+1:]
   422  
   423  		if name != "aeabi" {
   424  			continue
   425  		}
   426  		for len(sectiondata) != 0 {
   427  			subsectiontag, sz := binary.Uvarint(sectiondata)
   428  			subsectionsize := e.Uint32(sectiondata[sz:])
   429  			subsectiondata := sectiondata[sz+4 : subsectionsize]
   430  			sectiondata = sectiondata[subsectionsize:]
   431  
   432  			if subsectiontag == Tag_file {
   433  				attrList := elfAttributeList{data: subsectiondata}
   434  				for !attrList.done() {
   435  					attr := attrList.armAttr()
   436  					if attr.tag == Tag_ABI_VFP_args && attr.ival == 1 {
   437  						ehdr.flags = 0x5000402 // has entry point, Version5 EABI, hard-float ABI
   438  					}
   439  				}
   440  				if attrList.err != nil {
   441  					fmt.Fprintf(&Bso, "could not parse .ARM.attributes\n")
   442  				}
   443  			}
   444  		}
   445  	}
   446  }
   447  
   448  func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
   449  	if Debug['v'] != 0 {
   450  		fmt.Fprintf(&Bso, "%5.2f ldelf %s\n", obj.Cputime(), pn)
   451  	}
   452  
   453  	Ctxt.Version++
   454  	base := int32(obj.Boffset(f))
   455  
   456  	var add uint64
   457  	var e binary.ByteOrder
   458  	var elfobj *ElfObj
   459  	var err error
   460  	var flag int
   461  	var hdr *ElfHdrBytes
   462  	var hdrbuf [64]uint8
   463  	var info uint64
   464  	var is64 int
   465  	var j int
   466  	var n int
   467  	var name string
   468  	var p []byte
   469  	var r []Reloc
   470  	var rela int
   471  	var rp *Reloc
   472  	var rsect *ElfSect
   473  	var s *LSym
   474  	var sect *ElfSect
   475  	var sym ElfSym
   476  	var symbols []*LSym
   477  	if obj.Bread(f, hdrbuf[:]) != len(hdrbuf) {
   478  		goto bad
   479  	}
   480  	hdr = new(ElfHdrBytes)
   481  	binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
   482  	if string(hdr.Ident[:4]) != "\x7FELF" {
   483  		goto bad
   484  	}
   485  	switch hdr.Ident[5] {
   486  	case ElfDataLsb:
   487  		e = binary.LittleEndian
   488  
   489  	case ElfDataMsb:
   490  		e = binary.BigEndian
   491  
   492  	default:
   493  		goto bad
   494  	}
   495  
   496  	// read header
   497  	elfobj = new(ElfObj)
   498  
   499  	elfobj.e = e
   500  	elfobj.f = f
   501  	elfobj.base = int64(base)
   502  	elfobj.length = length
   503  	elfobj.name = pn
   504  
   505  	is64 = 0
   506  	if hdr.Ident[4] == ElfClass64 {
   507  		is64 = 1
   508  		hdr := new(ElfHdrBytes64)
   509  		binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
   510  		elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
   511  		elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
   512  		elfobj.version = e.Uint32(hdr.Version[:])
   513  		elfobj.phoff = e.Uint64(hdr.Phoff[:])
   514  		elfobj.shoff = e.Uint64(hdr.Shoff[:])
   515  		elfobj.flags = e.Uint32(hdr.Flags[:])
   516  		elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
   517  		elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
   518  		elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
   519  		elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
   520  		elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
   521  		elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
   522  	} else {
   523  		elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
   524  		elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
   525  		elfobj.version = e.Uint32(hdr.Version[:])
   526  		elfobj.entry = uint64(e.Uint32(hdr.Entry[:]))
   527  		elfobj.phoff = uint64(e.Uint32(hdr.Phoff[:]))
   528  		elfobj.shoff = uint64(e.Uint32(hdr.Shoff[:]))
   529  		elfobj.flags = e.Uint32(hdr.Flags[:])
   530  		elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
   531  		elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
   532  		elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
   533  		elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
   534  		elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
   535  		elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
   536  	}
   537  
   538  	elfobj.is64 = is64
   539  
   540  	if uint32(hdr.Ident[6]) != elfobj.version {
   541  		goto bad
   542  	}
   543  
   544  	if e.Uint16(hdr.Type[:]) != ElfTypeRelocatable {
   545  		Diag("%s: elf but not elf relocatable object", pn)
   546  		return
   547  	}
   548  
   549  	switch Thearch.Thechar {
   550  	default:
   551  		Diag("%s: elf %s unimplemented", pn, Thestring)
   552  		return
   553  
   554  	case '0':
   555  		if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 {
   556  			Diag("%s: elf object but not mips64", pn)
   557  			return
   558  		}
   559  
   560  	case '5':
   561  		if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 {
   562  			Diag("%s: elf object but not arm", pn)
   563  			return
   564  		}
   565  
   566  	case '6':
   567  		if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 {
   568  			Diag("%s: elf object but not amd64", pn)
   569  			return
   570  		}
   571  
   572  	case '7':
   573  		if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 {
   574  			Diag("%s: elf object but not arm64", pn)
   575  			return
   576  		}
   577  
   578  	case '8':
   579  		if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 {
   580  			Diag("%s: elf object but not 386", pn)
   581  			return
   582  		}
   583  
   584  	case '9':
   585  		if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 {
   586  			Diag("%s: elf object but not ppc64", pn)
   587  			return
   588  		}
   589  	}
   590  
   591  	// load section list into memory.
   592  	elfobj.sect = make([]ElfSect, elfobj.shnum)
   593  
   594  	elfobj.nsect = uint(elfobj.shnum)
   595  	for i := 0; uint(i) < elfobj.nsect; i++ {
   596  		if obj.Bseek(f, int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 {
   597  			goto bad
   598  		}
   599  		sect = &elfobj.sect[i]
   600  		if is64 != 0 {
   601  			var b ElfSectBytes64
   602  
   603  			if err = binary.Read(f, e, &b); err != nil {
   604  				goto bad
   605  			}
   606  
   607  			sect.nameoff = uint32(e.Uint32(b.Name[:]))
   608  			sect.type_ = e.Uint32(b.Type[:])
   609  			sect.flags = e.Uint64(b.Flags[:])
   610  			sect.addr = e.Uint64(b.Addr[:])
   611  			sect.off = e.Uint64(b.Off[:])
   612  			sect.size = e.Uint64(b.Size[:])
   613  			sect.link = e.Uint32(b.Link[:])
   614  			sect.info = e.Uint32(b.Info[:])
   615  			sect.align = e.Uint64(b.Align[:])
   616  			sect.entsize = e.Uint64(b.Entsize[:])
   617  		} else {
   618  			var b ElfSectBytes
   619  
   620  			if err = binary.Read(f, e, &b); err != nil {
   621  				goto bad
   622  			}
   623  
   624  			sect.nameoff = uint32(e.Uint32(b.Name[:]))
   625  			sect.type_ = e.Uint32(b.Type[:])
   626  			sect.flags = uint64(e.Uint32(b.Flags[:]))
   627  			sect.addr = uint64(e.Uint32(b.Addr[:]))
   628  			sect.off = uint64(e.Uint32(b.Off[:]))
   629  			sect.size = uint64(e.Uint32(b.Size[:]))
   630  			sect.link = e.Uint32(b.Link[:])
   631  			sect.info = e.Uint32(b.Info[:])
   632  			sect.align = uint64(e.Uint32(b.Align[:]))
   633  			sect.entsize = uint64(e.Uint32(b.Entsize[:]))
   634  		}
   635  	}
   636  
   637  	// read section string table and translate names
   638  	if elfobj.shstrndx >= uint32(elfobj.nsect) {
   639  		err = fmt.Errorf("shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect)
   640  		goto bad
   641  	}
   642  
   643  	sect = &elfobj.sect[elfobj.shstrndx]
   644  	if err = elfmap(elfobj, sect); err != nil {
   645  		goto bad
   646  	}
   647  	for i := 0; uint(i) < elfobj.nsect; i++ {
   648  		if elfobj.sect[i].nameoff != 0 {
   649  			elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:])
   650  		}
   651  	}
   652  
   653  	// load string table for symbols into memory.
   654  	elfobj.symtab = section(elfobj, ".symtab")
   655  
   656  	if elfobj.symtab == nil {
   657  		// our work is done here - no symbols means nothing can refer to this file
   658  		return
   659  	}
   660  
   661  	if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) {
   662  		Diag("%s: elf object has symbol table with invalid string table link", pn)
   663  		return
   664  	}
   665  
   666  	elfobj.symstr = &elfobj.sect[elfobj.symtab.link]
   667  	if is64 != 0 {
   668  		elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE)
   669  	} else {
   670  		elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE)
   671  	}
   672  
   673  	if err = elfmap(elfobj, elfobj.symtab); err != nil {
   674  		goto bad
   675  	}
   676  	if err = elfmap(elfobj, elfobj.symstr); err != nil {
   677  		goto bad
   678  	}
   679  
   680  	// load text and data segments into memory.
   681  	// they are not as small as the section lists, but we'll need
   682  	// the memory anyway for the symbol images, so we might
   683  	// as well use one large chunk.
   684  
   685  	// create symbols for elfmapped sections
   686  	for i := 0; uint(i) < elfobj.nsect; i++ {
   687  		sect = &elfobj.sect[i]
   688  		if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" {
   689  			if err = elfmap(elfobj, sect); err != nil {
   690  				goto bad
   691  			}
   692  			parseArmAttributes(e, sect.base[:sect.size])
   693  		}
   694  		if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 {
   695  			continue
   696  		}
   697  		if sect.type_ != ElfSectNobits {
   698  			if err = elfmap(elfobj, sect); err != nil {
   699  				goto bad
   700  			}
   701  		}
   702  
   703  		name = fmt.Sprintf("%s(%s)", pkg, sect.name)
   704  		s = Linklookup(Ctxt, name, Ctxt.Version)
   705  
   706  		switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) {
   707  		default:
   708  			err = fmt.Errorf("unexpected flags for ELF section %s", sect.name)
   709  			goto bad
   710  
   711  		case ElfSectFlagAlloc:
   712  			s.Type = obj.SRODATA
   713  
   714  		case ElfSectFlagAlloc + ElfSectFlagWrite:
   715  			if sect.type_ == ElfSectNobits {
   716  				s.Type = obj.SNOPTRBSS
   717  			} else {
   718  				s.Type = obj.SNOPTRDATA
   719  			}
   720  
   721  		case ElfSectFlagAlloc + ElfSectFlagExec:
   722  			s.Type = obj.STEXT
   723  		}
   724  
   725  		if sect.name == ".got" || sect.name == ".toc" {
   726  			s.Type = obj.SELFGOT
   727  		}
   728  		if sect.type_ == ElfSectProgbits {
   729  			s.P = sect.base
   730  			s.P = s.P[:sect.size]
   731  		}
   732  
   733  		s.Size = int64(sect.size)
   734  		s.Align = int32(sect.align)
   735  		sect.sym = s
   736  	}
   737  
   738  	// enter sub-symbols into symbol table.
   739  	// symbol 0 is the null symbol.
   740  	symbols = make([]*LSym, elfobj.nsymtab)
   741  
   742  	for i := 1; i < elfobj.nsymtab; i++ {
   743  		if err = readelfsym(elfobj, i, &sym, 1); err != nil {
   744  			goto bad
   745  		}
   746  		symbols[i] = sym.sym
   747  		if sym.type_ != ElfSymTypeFunc && sym.type_ != ElfSymTypeObject && sym.type_ != ElfSymTypeNone {
   748  			continue
   749  		}
   750  		if sym.shndx == ElfSymShnCommon {
   751  			s = sym.sym
   752  			if uint64(s.Size) < sym.size {
   753  				s.Size = int64(sym.size)
   754  			}
   755  			if s.Type == 0 || s.Type == obj.SXREF {
   756  				s.Type = obj.SNOPTRBSS
   757  			}
   758  			continue
   759  		}
   760  
   761  		if uint(sym.shndx) >= elfobj.nsect || sym.shndx == 0 {
   762  			continue
   763  		}
   764  
   765  		// even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
   766  		if sym.sym == nil {
   767  			continue
   768  		}
   769  		sect = &elfobj.sect[sym.shndx:][0]
   770  		if sect.sym == nil {
   771  			if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this
   772  				continue
   773  			}
   774  
   775  			if sym.name == "" && sym.type_ == 0 && sect.name == ".debug_str" {
   776  				// This reportedly happens with clang 3.7 on ARM.
   777  				// See issue 13139.
   778  				continue
   779  			}
   780  
   781  			Diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type_)
   782  			continue
   783  		}
   784  
   785  		s = sym.sym
   786  		if s.Outer != nil {
   787  			if s.Dupok != 0 {
   788  				continue
   789  			}
   790  			Exitf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sect.sym.Name)
   791  		}
   792  
   793  		s.Sub = sect.sym.Sub
   794  		sect.sym.Sub = s
   795  		s.Type = sect.sym.Type | s.Type&^obj.SMASK | obj.SSUB
   796  		if s.Cgoexport&CgoExportDynamic == 0 {
   797  			s.Dynimplib = "" // satisfy dynimport
   798  		}
   799  		s.Value = int64(sym.value)
   800  		s.Size = int64(sym.size)
   801  		s.Outer = sect.sym
   802  		if sect.sym.Type == obj.STEXT {
   803  			if s.External != 0 && s.Dupok == 0 {
   804  				Diag("%s: duplicate definition of %s", pn, s.Name)
   805  			}
   806  			s.External = 1
   807  		}
   808  
   809  		if elfobj.machine == ElfMachPower64 {
   810  			flag = int(sym.other) >> 5
   811  			if 2 <= flag && flag <= 6 {
   812  				s.Localentry = 1 << uint(flag-2)
   813  			} else if flag == 7 {
   814  				Diag("%s: invalid sym.other 0x%x for %s", pn, sym.other, s.Name)
   815  			}
   816  		}
   817  	}
   818  
   819  	// Sort outer lists by address, adding to textp.
   820  	// This keeps textp in increasing address order.
   821  	for i := 0; uint(i) < elfobj.nsect; i++ {
   822  		s = elfobj.sect[i].sym
   823  		if s == nil {
   824  			continue
   825  		}
   826  		if s.Sub != nil {
   827  			s.Sub = listsort(s.Sub, valuecmp, listsubp)
   828  		}
   829  		if s.Type == obj.STEXT {
   830  			if s.Onlist != 0 {
   831  				log.Fatalf("symbol %s listed multiple times", s.Name)
   832  			}
   833  			s.Onlist = 1
   834  			if Ctxt.Etextp != nil {
   835  				Ctxt.Etextp.Next = s
   836  			} else {
   837  				Ctxt.Textp = s
   838  			}
   839  			Ctxt.Etextp = s
   840  			for s = s.Sub; s != nil; s = s.Sub {
   841  				if s.Onlist != 0 {
   842  					log.Fatalf("symbol %s listed multiple times", s.Name)
   843  				}
   844  				s.Onlist = 1
   845  				Ctxt.Etextp.Next = s
   846  				Ctxt.Etextp = s
   847  			}
   848  		}
   849  	}
   850  
   851  	// load relocations
   852  	for i := 0; uint(i) < elfobj.nsect; i++ {
   853  		rsect = &elfobj.sect[i]
   854  		if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel {
   855  			continue
   856  		}
   857  		if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
   858  			continue
   859  		}
   860  		sect = &elfobj.sect[rsect.info]
   861  		if err = elfmap(elfobj, rsect); err != nil {
   862  			goto bad
   863  		}
   864  		rela = 0
   865  		if rsect.type_ == ElfSectRela {
   866  			rela = 1
   867  		}
   868  		n = int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
   869  		r = make([]Reloc, n)
   870  		p = rsect.base
   871  		for j = 0; j < n; j++ {
   872  			add = 0
   873  			rp = &r[j]
   874  			if is64 != 0 {
   875  				// 64-bit rel/rela
   876  				rp.Off = int32(e.Uint64(p))
   877  
   878  				p = p[8:]
   879  				info = e.Uint64(p)
   880  				p = p[8:]
   881  				if rela != 0 {
   882  					add = e.Uint64(p)
   883  					p = p[8:]
   884  				}
   885  			} else {
   886  				// 32-bit rel/rela
   887  				rp.Off = int32(e.Uint32(p))
   888  
   889  				p = p[4:]
   890  				info = uint64(e.Uint32(p))
   891  				info = info>>8<<32 | info&0xff // convert to 64-bit info
   892  				p = p[4:]
   893  				if rela != 0 {
   894  					add = uint64(e.Uint32(p))
   895  					p = p[4:]
   896  				}
   897  			}
   898  
   899  			if info&0xffffffff == 0 { // skip R_*_NONE relocation
   900  				j--
   901  				n--
   902  				continue
   903  			}
   904  
   905  			if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol
   906  				rp.Sym = nil
   907  			} else {
   908  				if err = readelfsym(elfobj, int(info>>32), &sym, 0); err != nil {
   909  					goto bad
   910  				}
   911  				sym.sym = symbols[info>>32]
   912  				if sym.sym == nil {
   913  					err = fmt.Errorf("%s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", sect.sym.Name, j, int(info>>32), sym.name, sym.shndx, sym.type_)
   914  					goto bad
   915  				}
   916  
   917  				rp.Sym = sym.sym
   918  			}
   919  
   920  			rp.Type = int32(reltype(pn, int(uint32(info)), &rp.Siz))
   921  			if rela != 0 {
   922  				rp.Add = int64(add)
   923  			} else {
   924  				// load addend from image
   925  				if rp.Siz == 4 {
   926  					rp.Add = int64(e.Uint32(sect.base[rp.Off:]))
   927  				} else if rp.Siz == 8 {
   928  					rp.Add = int64(e.Uint64(sect.base[rp.Off:]))
   929  				} else {
   930  					Diag("invalid rela size %d", rp.Siz)
   931  				}
   932  			}
   933  
   934  			if rp.Siz == 2 {
   935  				rp.Add = int64(int16(rp.Add))
   936  			}
   937  			if rp.Siz == 4 {
   938  				rp.Add = int64(int32(rp.Add))
   939  			}
   940  		}
   941  
   942  		//print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add);
   943  		sort.Sort(rbyoff(r[:n]))
   944  		// just in case
   945  
   946  		s = sect.sym
   947  		s.R = r
   948  		s.R = s.R[:n]
   949  	}
   950  
   951  	return
   952  
   953  bad:
   954  	Diag("%s: malformed elf file: %v", pn, err)
   955  }
   956  
   957  func section(elfobj *ElfObj, name string) *ElfSect {
   958  	for i := 0; uint(i) < elfobj.nsect; i++ {
   959  		if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
   960  			return &elfobj.sect[i]
   961  		}
   962  	}
   963  	return nil
   964  }
   965  
   966  func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
   967  	if sect.base != nil {
   968  		return nil
   969  	}
   970  
   971  	if sect.off+sect.size > uint64(elfobj.length) {
   972  		err = fmt.Errorf("elf section past end of file")
   973  		return err
   974  	}
   975  
   976  	sect.base = make([]byte, sect.size)
   977  	err = fmt.Errorf("short read")
   978  	if obj.Bseek(elfobj.f, int64(uint64(elfobj.base)+sect.off), 0) < 0 || obj.Bread(elfobj.f, sect.base) != len(sect.base) {
   979  		return err
   980  	}
   981  
   982  	return nil
   983  }
   984  
   985  func readelfsym(elfobj *ElfObj, i int, sym *ElfSym, needSym int) (err error) {
   986  	if i >= elfobj.nsymtab || i < 0 {
   987  		err = fmt.Errorf("invalid elf symbol index")
   988  		return err
   989  	}
   990  
   991  	if i == 0 {
   992  		Diag("readym: read null symbol!")
   993  	}
   994  
   995  	if elfobj.is64 != 0 {
   996  		b := new(ElfSymBytes64)
   997  		binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b)
   998  		sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
   999  		sym.value = elfobj.e.Uint64(b.Value[:])
  1000  		sym.size = elfobj.e.Uint64(b.Size[:])
  1001  		sym.shndx = elfobj.e.Uint16(b.Shndx[:])
  1002  		sym.bind = b.Info >> 4
  1003  		sym.type_ = b.Info & 0xf
  1004  		sym.other = b.Other
  1005  	} else {
  1006  		b := new(ElfSymBytes)
  1007  		binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b)
  1008  		sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
  1009  		sym.value = uint64(elfobj.e.Uint32(b.Value[:]))
  1010  		sym.size = uint64(elfobj.e.Uint32(b.Size[:]))
  1011  		sym.shndx = elfobj.e.Uint16(b.Shndx[:])
  1012  		sym.bind = b.Info >> 4
  1013  		sym.type_ = b.Info & 0xf
  1014  		sym.other = b.Other
  1015  	}
  1016  
  1017  	var s *LSym
  1018  	if sym.name == "_GLOBAL_OFFSET_TABLE_" {
  1019  		sym.name = ".got"
  1020  	}
  1021  	if sym.name == ".TOC." {
  1022  		// Magic symbol on ppc64.  Will be set to this object
  1023  		// file's .got+0x8000.
  1024  		sym.bind = ElfSymBindLocal
  1025  	}
  1026  
  1027  	switch sym.type_ {
  1028  	case ElfSymTypeSection:
  1029  		s = elfobj.sect[sym.shndx].sym
  1030  
  1031  	case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone:
  1032  		switch sym.bind {
  1033  		case ElfSymBindGlobal:
  1034  			if needSym != 0 {
  1035  				s = Linklookup(Ctxt, sym.name, 0)
  1036  
  1037  				// for global scoped hidden symbols we should insert it into
  1038  				// symbol hash table, but mark them as hidden.
  1039  				// __i686.get_pc_thunk.bx is allowed to be duplicated, to
  1040  				// workaround that we set dupok.
  1041  				// TODO(minux): correctly handle __i686.get_pc_thunk.bx without
  1042  				// set dupok generally. See http://codereview.appspot.com/5823055/
  1043  				// comment #5 for details.
  1044  				if s != nil && sym.other == 2 {
  1045  					s.Type |= obj.SHIDDEN
  1046  					s.Dupok = 1
  1047  				}
  1048  			}
  1049  
  1050  		case ElfSymBindLocal:
  1051  			if Thearch.Thechar == '5' && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) {
  1052  				// binutils for arm generate these mapping
  1053  				// symbols, ignore these
  1054  				break
  1055  			}
  1056  
  1057  			if sym.name == ".TOC." {
  1058  				// We need to be able to look this up,
  1059  				// so put it in the hash table.
  1060  				if needSym != 0 {
  1061  					s = Linklookup(Ctxt, sym.name, Ctxt.Version)
  1062  					s.Type |= obj.SHIDDEN
  1063  				}
  1064  
  1065  				break
  1066  			}
  1067  
  1068  			if needSym != 0 {
  1069  				// local names and hidden visiblity global names are unique
  1070  				// and should only reference by its index, not name, so we
  1071  				// don't bother to add them into hash table
  1072  				s = linknewsym(Ctxt, sym.name, Ctxt.Version)
  1073  
  1074  				s.Type |= obj.SHIDDEN
  1075  			}
  1076  
  1077  		case ElfSymBindWeak:
  1078  			if needSym != 0 {
  1079  				s = Linklookup(Ctxt, sym.name, 0)
  1080  				if sym.other == 2 {
  1081  					s.Type |= obj.SHIDDEN
  1082  				}
  1083  			}
  1084  
  1085  		default:
  1086  			err = fmt.Errorf("%s: invalid symbol binding %d", sym.name, sym.bind)
  1087  			return err
  1088  		}
  1089  	}
  1090  
  1091  	if s != nil && s.Type == 0 && sym.type_ != ElfSymTypeSection {
  1092  		s.Type = obj.SXREF
  1093  	}
  1094  	sym.sym = s
  1095  
  1096  	return nil
  1097  }
  1098  
  1099  type rbyoff []Reloc
  1100  
  1101  func (x rbyoff) Len() int {
  1102  	return len(x)
  1103  }
  1104  
  1105  func (x rbyoff) Swap(i, j int) {
  1106  	x[i], x[j] = x[j], x[i]
  1107  }
  1108  
  1109  func (x rbyoff) Less(i, j int) bool {
  1110  	a := &x[i]
  1111  	b := &x[j]
  1112  	if a.Off < b.Off {
  1113  		return true
  1114  	}
  1115  	if a.Off > b.Off {
  1116  		return false
  1117  	}
  1118  	return false
  1119  }
  1120  
  1121  func reltype(pn string, elftype int, siz *uint8) int {
  1122  	switch uint32(Thearch.Thechar) | uint32(elftype)<<24 {
  1123  	default:
  1124  		Diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
  1125  		fallthrough
  1126  
  1127  	case '9' | R_PPC64_TOC16<<24,
  1128  		'9' | R_PPC64_TOC16_LO<<24,
  1129  		'9' | R_PPC64_TOC16_HI<<24,
  1130  		'9' | R_PPC64_TOC16_HA<<24,
  1131  		'9' | R_PPC64_TOC16_DS<<24,
  1132  		'9' | R_PPC64_TOC16_LO_DS<<24,
  1133  		'9' | R_PPC64_REL16_LO<<24,
  1134  		'9' | R_PPC64_REL16_HI<<24,
  1135  		'9' | R_PPC64_REL16_HA<<24:
  1136  		*siz = 2
  1137  
  1138  	case '5' | R_ARM_ABS32<<24,
  1139  		'5' | R_ARM_GOT32<<24,
  1140  		'5' | R_ARM_PLT32<<24,
  1141  		'5' | R_ARM_GOTOFF<<24,
  1142  		'5' | R_ARM_GOTPC<<24,
  1143  		'5' | R_ARM_THM_PC22<<24,
  1144  		'5' | R_ARM_REL32<<24,
  1145  		'5' | R_ARM_CALL<<24,
  1146  		'5' | R_ARM_V4BX<<24,
  1147  		'5' | R_ARM_GOT_PREL<<24,
  1148  		'5' | R_ARM_PC24<<24,
  1149  		'5' | R_ARM_JUMP24<<24,
  1150  		'6' | R_X86_64_PC32<<24,
  1151  		'6' | R_X86_64_PLT32<<24,
  1152  		'6' | R_X86_64_GOTPCREL<<24,
  1153  		'6' | R_X86_64_GOTPCRELX<<24,
  1154  		'6' | R_X86_64_REX_GOTPCRELX<<24,
  1155  		'8' | R_386_32<<24,
  1156  		'8' | R_386_PC32<<24,
  1157  		'8' | R_386_GOT32<<24,
  1158  		'8' | R_386_PLT32<<24,
  1159  		'8' | R_386_GOTOFF<<24,
  1160  		'8' | R_386_GOTPC<<24,
  1161  		'8' | R_386_GOT32X<<24,
  1162  		'9' | R_PPC64_REL24<<24,
  1163  		'9' | R_PPC_REL32<<24:
  1164  		*siz = 4
  1165  
  1166  	case '6' | R_X86_64_64<<24,
  1167  		'9' | R_PPC64_ADDR64<<24:
  1168  		*siz = 8
  1169  	}
  1170  
  1171  	return 256 + elftype
  1172  }