github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/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 '5':
   555  		if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 {
   556  			Diag("%s: elf object but not arm", pn)
   557  			return
   558  		}
   559  
   560  	case '6':
   561  		if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 {
   562  			Diag("%s: elf object but not amd64", pn)
   563  			return
   564  		}
   565  
   566  	case '7':
   567  		if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 {
   568  			Diag("%s: elf object but not arm64", pn)
   569  			return
   570  		}
   571  
   572  	case '8':
   573  		if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 {
   574  			Diag("%s: elf object but not 386", pn)
   575  			return
   576  		}
   577  
   578  	case '9':
   579  		if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 {
   580  			Diag("%s: elf object but not ppc64", pn)
   581  			return
   582  		}
   583  	}
   584  
   585  	// load section list into memory.
   586  	elfobj.sect = make([]ElfSect, elfobj.shnum)
   587  
   588  	elfobj.nsect = uint(elfobj.shnum)
   589  	for i := 0; uint(i) < elfobj.nsect; i++ {
   590  		if obj.Bseek(f, int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 {
   591  			goto bad
   592  		}
   593  		sect = &elfobj.sect[i]
   594  		if is64 != 0 {
   595  			var b ElfSectBytes64
   596  
   597  			if err = binary.Read(f, e, &b); err != nil {
   598  				goto bad
   599  			}
   600  
   601  			sect.nameoff = uint32(e.Uint32(b.Name[:]))
   602  			sect.type_ = e.Uint32(b.Type[:])
   603  			sect.flags = e.Uint64(b.Flags[:])
   604  			sect.addr = e.Uint64(b.Addr[:])
   605  			sect.off = e.Uint64(b.Off[:])
   606  			sect.size = e.Uint64(b.Size[:])
   607  			sect.link = e.Uint32(b.Link[:])
   608  			sect.info = e.Uint32(b.Info[:])
   609  			sect.align = e.Uint64(b.Align[:])
   610  			sect.entsize = e.Uint64(b.Entsize[:])
   611  		} else {
   612  			var b ElfSectBytes
   613  
   614  			if err = binary.Read(f, e, &b); err != nil {
   615  				goto bad
   616  			}
   617  
   618  			sect.nameoff = uint32(e.Uint32(b.Name[:]))
   619  			sect.type_ = e.Uint32(b.Type[:])
   620  			sect.flags = uint64(e.Uint32(b.Flags[:]))
   621  			sect.addr = uint64(e.Uint32(b.Addr[:]))
   622  			sect.off = uint64(e.Uint32(b.Off[:]))
   623  			sect.size = uint64(e.Uint32(b.Size[:]))
   624  			sect.link = e.Uint32(b.Link[:])
   625  			sect.info = e.Uint32(b.Info[:])
   626  			sect.align = uint64(e.Uint32(b.Align[:]))
   627  			sect.entsize = uint64(e.Uint32(b.Entsize[:]))
   628  		}
   629  	}
   630  
   631  	// read section string table and translate names
   632  	if elfobj.shstrndx >= uint32(elfobj.nsect) {
   633  		err = fmt.Errorf("shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect)
   634  		goto bad
   635  	}
   636  
   637  	sect = &elfobj.sect[elfobj.shstrndx]
   638  	if err = elfmap(elfobj, sect); err != nil {
   639  		goto bad
   640  	}
   641  	for i := 0; uint(i) < elfobj.nsect; i++ {
   642  		if elfobj.sect[i].nameoff != 0 {
   643  			elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:])
   644  		}
   645  	}
   646  
   647  	// load string table for symbols into memory.
   648  	elfobj.symtab = section(elfobj, ".symtab")
   649  
   650  	if elfobj.symtab == nil {
   651  		// our work is done here - no symbols means nothing can refer to this file
   652  		return
   653  	}
   654  
   655  	if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) {
   656  		Diag("%s: elf object has symbol table with invalid string table link", pn)
   657  		return
   658  	}
   659  
   660  	elfobj.symstr = &elfobj.sect[elfobj.symtab.link]
   661  	if is64 != 0 {
   662  		elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE)
   663  	} else {
   664  		elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE)
   665  	}
   666  
   667  	if err = elfmap(elfobj, elfobj.symtab); err != nil {
   668  		goto bad
   669  	}
   670  	if err = elfmap(elfobj, elfobj.symstr); err != nil {
   671  		goto bad
   672  	}
   673  
   674  	// load text and data segments into memory.
   675  	// they are not as small as the section lists, but we'll need
   676  	// the memory anyway for the symbol images, so we might
   677  	// as well use one large chunk.
   678  
   679  	// create symbols for elfmapped sections
   680  	for i := 0; uint(i) < elfobj.nsect; i++ {
   681  		sect = &elfobj.sect[i]
   682  		if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" {
   683  			if err = elfmap(elfobj, sect); err != nil {
   684  				goto bad
   685  			}
   686  			parseArmAttributes(e, sect.base[:sect.size])
   687  		}
   688  		if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 {
   689  			continue
   690  		}
   691  		if sect.type_ != ElfSectNobits {
   692  			if err = elfmap(elfobj, sect); err != nil {
   693  				goto bad
   694  			}
   695  		}
   696  
   697  		name = fmt.Sprintf("%s(%s)", pkg, sect.name)
   698  		s = Linklookup(Ctxt, name, Ctxt.Version)
   699  
   700  		switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) {
   701  		default:
   702  			err = fmt.Errorf("unexpected flags for ELF section %s", sect.name)
   703  			goto bad
   704  
   705  		case ElfSectFlagAlloc:
   706  			s.Type = obj.SRODATA
   707  
   708  		case ElfSectFlagAlloc + ElfSectFlagWrite:
   709  			if sect.type_ == ElfSectNobits {
   710  				s.Type = obj.SNOPTRBSS
   711  			} else {
   712  				s.Type = obj.SNOPTRDATA
   713  			}
   714  
   715  		case ElfSectFlagAlloc + ElfSectFlagExec:
   716  			s.Type = obj.STEXT
   717  		}
   718  
   719  		if sect.name == ".got" || sect.name == ".toc" {
   720  			s.Type = obj.SELFGOT
   721  		}
   722  		if sect.type_ == ElfSectProgbits {
   723  			s.P = sect.base
   724  			s.P = s.P[:sect.size]
   725  		}
   726  
   727  		s.Size = int64(sect.size)
   728  		s.Align = int32(sect.align)
   729  		sect.sym = s
   730  	}
   731  
   732  	// enter sub-symbols into symbol table.
   733  	// symbol 0 is the null symbol.
   734  	symbols = make([]*LSym, elfobj.nsymtab)
   735  
   736  	for i := 1; i < elfobj.nsymtab; i++ {
   737  		if err = readelfsym(elfobj, i, &sym, 1); err != nil {
   738  			goto bad
   739  		}
   740  		symbols[i] = sym.sym
   741  		if sym.type_ != ElfSymTypeFunc && sym.type_ != ElfSymTypeObject && sym.type_ != ElfSymTypeNone {
   742  			continue
   743  		}
   744  		if sym.shndx == ElfSymShnCommon {
   745  			s = sym.sym
   746  			if uint64(s.Size) < sym.size {
   747  				s.Size = int64(sym.size)
   748  			}
   749  			if s.Type == 0 || s.Type == obj.SXREF {
   750  				s.Type = obj.SNOPTRBSS
   751  			}
   752  			continue
   753  		}
   754  
   755  		if uint(sym.shndx) >= elfobj.nsect || sym.shndx == 0 {
   756  			continue
   757  		}
   758  
   759  		// even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
   760  		if sym.sym == nil {
   761  			continue
   762  		}
   763  		sect = &elfobj.sect[sym.shndx:][0]
   764  		if sect.sym == nil {
   765  			if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this
   766  				continue
   767  			}
   768  			Diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type_)
   769  			continue
   770  		}
   771  
   772  		s = sym.sym
   773  		if s.Outer != nil {
   774  			if s.Dupok != 0 {
   775  				continue
   776  			}
   777  			Exitf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sect.sym.Name)
   778  		}
   779  
   780  		s.Sub = sect.sym.Sub
   781  		sect.sym.Sub = s
   782  		s.Type = sect.sym.Type | s.Type&^obj.SMASK | obj.SSUB
   783  		if s.Cgoexport&CgoExportDynamic == 0 {
   784  			s.Dynimplib = "" // satisfy dynimport
   785  		}
   786  		s.Value = int64(sym.value)
   787  		s.Size = int64(sym.size)
   788  		s.Outer = sect.sym
   789  		if sect.sym.Type == obj.STEXT {
   790  			if s.External != 0 && s.Dupok == 0 {
   791  				Diag("%s: duplicate definition of %s", pn, s.Name)
   792  			}
   793  			s.External = 1
   794  		}
   795  
   796  		if elfobj.machine == ElfMachPower64 {
   797  			flag = int(sym.other) >> 5
   798  			if 2 <= flag && flag <= 6 {
   799  				s.Localentry = 1 << uint(flag-2)
   800  			} else if flag == 7 {
   801  				Diag("%s: invalid sym.other 0x%x for %s", pn, sym.other, s.Name)
   802  			}
   803  		}
   804  	}
   805  
   806  	// Sort outer lists by address, adding to textp.
   807  	// This keeps textp in increasing address order.
   808  	for i := 0; uint(i) < elfobj.nsect; i++ {
   809  		s = elfobj.sect[i].sym
   810  		if s == nil {
   811  			continue
   812  		}
   813  		if s.Sub != nil {
   814  			s.Sub = listsort(s.Sub, valuecmp, listsubp)
   815  		}
   816  		if s.Type == obj.STEXT {
   817  			if s.Onlist != 0 {
   818  				log.Fatalf("symbol %s listed multiple times", s.Name)
   819  			}
   820  			s.Onlist = 1
   821  			if Ctxt.Etextp != nil {
   822  				Ctxt.Etextp.Next = s
   823  			} else {
   824  				Ctxt.Textp = s
   825  			}
   826  			Ctxt.Etextp = s
   827  			for s = s.Sub; s != nil; s = s.Sub {
   828  				if s.Onlist != 0 {
   829  					log.Fatalf("symbol %s listed multiple times", s.Name)
   830  				}
   831  				s.Onlist = 1
   832  				Ctxt.Etextp.Next = s
   833  				Ctxt.Etextp = s
   834  			}
   835  		}
   836  	}
   837  
   838  	// load relocations
   839  	for i := 0; uint(i) < elfobj.nsect; i++ {
   840  		rsect = &elfobj.sect[i]
   841  		if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel {
   842  			continue
   843  		}
   844  		if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
   845  			continue
   846  		}
   847  		sect = &elfobj.sect[rsect.info]
   848  		if err = elfmap(elfobj, rsect); err != nil {
   849  			goto bad
   850  		}
   851  		rela = 0
   852  		if rsect.type_ == ElfSectRela {
   853  			rela = 1
   854  		}
   855  		n = int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
   856  		r = make([]Reloc, n)
   857  		p = rsect.base
   858  		for j = 0; j < n; j++ {
   859  			add = 0
   860  			rp = &r[j]
   861  			if is64 != 0 {
   862  				// 64-bit rel/rela
   863  				rp.Off = int32(e.Uint64(p))
   864  
   865  				p = p[8:]
   866  				info = e.Uint64(p)
   867  				p = p[8:]
   868  				if rela != 0 {
   869  					add = e.Uint64(p)
   870  					p = p[8:]
   871  				}
   872  			} else {
   873  				// 32-bit rel/rela
   874  				rp.Off = int32(e.Uint32(p))
   875  
   876  				p = p[4:]
   877  				info = uint64(e.Uint32(p))
   878  				info = info>>8<<32 | info&0xff // convert to 64-bit info
   879  				p = p[4:]
   880  				if rela != 0 {
   881  					add = uint64(e.Uint32(p))
   882  					p = p[4:]
   883  				}
   884  			}
   885  
   886  			if info&0xffffffff == 0 { // skip R_*_NONE relocation
   887  				j--
   888  				n--
   889  				continue
   890  			}
   891  
   892  			if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol
   893  				rp.Sym = nil
   894  			} else {
   895  				if err = readelfsym(elfobj, int(info>>32), &sym, 0); err != nil {
   896  					goto bad
   897  				}
   898  				sym.sym = symbols[info>>32]
   899  				if sym.sym == nil {
   900  					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_)
   901  					goto bad
   902  				}
   903  
   904  				rp.Sym = sym.sym
   905  			}
   906  
   907  			rp.Type = int32(reltype(pn, int(uint32(info)), &rp.Siz))
   908  			if rela != 0 {
   909  				rp.Add = int64(add)
   910  			} else {
   911  				// load addend from image
   912  				if rp.Siz == 4 {
   913  					rp.Add = int64(e.Uint32(sect.base[rp.Off:]))
   914  				} else if rp.Siz == 8 {
   915  					rp.Add = int64(e.Uint64(sect.base[rp.Off:]))
   916  				} else {
   917  					Diag("invalid rela size %d", rp.Siz)
   918  				}
   919  			}
   920  
   921  			if rp.Siz == 2 {
   922  				rp.Add = int64(int16(rp.Add))
   923  			}
   924  			if rp.Siz == 4 {
   925  				rp.Add = int64(int32(rp.Add))
   926  			}
   927  		}
   928  
   929  		//print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add);
   930  		sort.Sort(rbyoff(r[:n]))
   931  		// just in case
   932  
   933  		s = sect.sym
   934  		s.R = r
   935  		s.R = s.R[:n]
   936  	}
   937  
   938  	return
   939  
   940  bad:
   941  	Diag("%s: malformed elf file: %v", pn, err)
   942  }
   943  
   944  func section(elfobj *ElfObj, name string) *ElfSect {
   945  	for i := 0; uint(i) < elfobj.nsect; i++ {
   946  		if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
   947  			return &elfobj.sect[i]
   948  		}
   949  	}
   950  	return nil
   951  }
   952  
   953  func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
   954  	if sect.base != nil {
   955  		return nil
   956  	}
   957  
   958  	if sect.off+sect.size > uint64(elfobj.length) {
   959  		err = fmt.Errorf("elf section past end of file")
   960  		return err
   961  	}
   962  
   963  	sect.base = make([]byte, sect.size)
   964  	err = fmt.Errorf("short read")
   965  	if obj.Bseek(elfobj.f, int64(uint64(elfobj.base)+sect.off), 0) < 0 || obj.Bread(elfobj.f, sect.base) != len(sect.base) {
   966  		return err
   967  	}
   968  
   969  	return nil
   970  }
   971  
   972  func readelfsym(elfobj *ElfObj, i int, sym *ElfSym, needSym int) (err error) {
   973  	if i >= elfobj.nsymtab || i < 0 {
   974  		err = fmt.Errorf("invalid elf symbol index")
   975  		return err
   976  	}
   977  
   978  	if i == 0 {
   979  		Diag("readym: read null symbol!")
   980  	}
   981  
   982  	if elfobj.is64 != 0 {
   983  		b := new(ElfSymBytes64)
   984  		binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b)
   985  		sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
   986  		sym.value = elfobj.e.Uint64(b.Value[:])
   987  		sym.size = elfobj.e.Uint64(b.Size[:])
   988  		sym.shndx = elfobj.e.Uint16(b.Shndx[:])
   989  		sym.bind = b.Info >> 4
   990  		sym.type_ = b.Info & 0xf
   991  		sym.other = b.Other
   992  	} else {
   993  		b := new(ElfSymBytes)
   994  		binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b)
   995  		sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
   996  		sym.value = uint64(elfobj.e.Uint32(b.Value[:]))
   997  		sym.size = uint64(elfobj.e.Uint32(b.Size[:]))
   998  		sym.shndx = elfobj.e.Uint16(b.Shndx[:])
   999  		sym.bind = b.Info >> 4
  1000  		sym.type_ = b.Info & 0xf
  1001  		sym.other = b.Other
  1002  	}
  1003  
  1004  	var s *LSym
  1005  	if sym.name == "_GLOBAL_OFFSET_TABLE_" {
  1006  		sym.name = ".got"
  1007  	}
  1008  	if sym.name == ".TOC." {
  1009  		// Magic symbol on ppc64.  Will be set to this object
  1010  		// file's .got+0x8000.
  1011  		sym.bind = ElfSymBindLocal
  1012  	}
  1013  
  1014  	switch sym.type_ {
  1015  	case ElfSymTypeSection:
  1016  		s = elfobj.sect[sym.shndx].sym
  1017  
  1018  	case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone:
  1019  		switch sym.bind {
  1020  		case ElfSymBindGlobal:
  1021  			if needSym != 0 {
  1022  				s = Linklookup(Ctxt, sym.name, 0)
  1023  
  1024  				// for global scoped hidden symbols we should insert it into
  1025  				// symbol hash table, but mark them as hidden.
  1026  				// __i686.get_pc_thunk.bx is allowed to be duplicated, to
  1027  				// workaround that we set dupok.
  1028  				// TODO(minux): correctly handle __i686.get_pc_thunk.bx without
  1029  				// set dupok generally. See http://codereview.appspot.com/5823055/
  1030  				// comment #5 for details.
  1031  				if s != nil && sym.other == 2 {
  1032  					s.Type |= obj.SHIDDEN
  1033  					s.Dupok = 1
  1034  				}
  1035  			}
  1036  
  1037  		case ElfSymBindLocal:
  1038  			if Thearch.Thechar == '5' && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) {
  1039  				// binutils for arm generate these mapping
  1040  				// symbols, ignore these
  1041  				break
  1042  			}
  1043  
  1044  			if sym.name == ".TOC." {
  1045  				// We need to be able to look this up,
  1046  				// so put it in the hash table.
  1047  				if needSym != 0 {
  1048  					s = Linklookup(Ctxt, sym.name, Ctxt.Version)
  1049  					s.Type |= obj.SHIDDEN
  1050  				}
  1051  
  1052  				break
  1053  			}
  1054  
  1055  			if needSym != 0 {
  1056  				// local names and hidden visiblity global names are unique
  1057  				// and should only reference by its index, not name, so we
  1058  				// don't bother to add them into hash table
  1059  				s = linknewsym(Ctxt, sym.name, Ctxt.Version)
  1060  
  1061  				s.Type |= obj.SHIDDEN
  1062  			}
  1063  
  1064  		case ElfSymBindWeak:
  1065  			if needSym != 0 {
  1066  				s = linknewsym(Ctxt, sym.name, 0)
  1067  				if sym.other == 2 {
  1068  					s.Type |= obj.SHIDDEN
  1069  				}
  1070  			}
  1071  
  1072  		default:
  1073  			err = fmt.Errorf("%s: invalid symbol binding %d", sym.name, sym.bind)
  1074  			return err
  1075  		}
  1076  	}
  1077  
  1078  	if s != nil && s.Type == 0 && sym.type_ != ElfSymTypeSection {
  1079  		s.Type = obj.SXREF
  1080  	}
  1081  	sym.sym = s
  1082  
  1083  	return nil
  1084  }
  1085  
  1086  type rbyoff []Reloc
  1087  
  1088  func (x rbyoff) Len() int {
  1089  	return len(x)
  1090  }
  1091  
  1092  func (x rbyoff) Swap(i, j int) {
  1093  	x[i], x[j] = x[j], x[i]
  1094  }
  1095  
  1096  func (x rbyoff) Less(i, j int) bool {
  1097  	a := &x[i]
  1098  	b := &x[j]
  1099  	if a.Off < b.Off {
  1100  		return true
  1101  	}
  1102  	if a.Off > b.Off {
  1103  		return false
  1104  	}
  1105  	return false
  1106  }
  1107  
  1108  func reltype(pn string, elftype int, siz *uint8) int {
  1109  	switch uint32(Thearch.Thechar) | uint32(elftype)<<24 {
  1110  	default:
  1111  		Diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
  1112  		fallthrough
  1113  
  1114  	case '9' | R_PPC64_TOC16<<24,
  1115  		'9' | R_PPC64_TOC16_LO<<24,
  1116  		'9' | R_PPC64_TOC16_HI<<24,
  1117  		'9' | R_PPC64_TOC16_HA<<24,
  1118  		'9' | R_PPC64_TOC16_DS<<24,
  1119  		'9' | R_PPC64_TOC16_LO_DS<<24,
  1120  		'9' | R_PPC64_REL16_LO<<24,
  1121  		'9' | R_PPC64_REL16_HI<<24,
  1122  		'9' | R_PPC64_REL16_HA<<24:
  1123  		*siz = 2
  1124  
  1125  	case '5' | R_ARM_ABS32<<24,
  1126  		'5' | R_ARM_GOT32<<24,
  1127  		'5' | R_ARM_PLT32<<24,
  1128  		'5' | R_ARM_GOTOFF<<24,
  1129  		'5' | R_ARM_GOTPC<<24,
  1130  		'5' | R_ARM_THM_PC22<<24,
  1131  		'5' | R_ARM_REL32<<24,
  1132  		'5' | R_ARM_CALL<<24,
  1133  		'5' | R_ARM_V4BX<<24,
  1134  		'5' | R_ARM_GOT_PREL<<24,
  1135  		'5' | R_ARM_PC24<<24,
  1136  		'5' | R_ARM_JUMP24<<24,
  1137  		'6' | R_X86_64_PC32<<24,
  1138  		'6' | R_X86_64_PLT32<<24,
  1139  		'6' | R_X86_64_GOTPCREL<<24,
  1140  		'6' | R_X86_64_GOTPCRELX<<24,
  1141  		'6' | R_X86_64_REX_GOTPCRELX<<24,
  1142  		'8' | R_386_32<<24,
  1143  		'8' | R_386_PC32<<24,
  1144  		'8' | R_386_GOT32<<24,
  1145  		'8' | R_386_PLT32<<24,
  1146  		'8' | R_386_GOTOFF<<24,
  1147  		'8' | R_386_GOTPC<<24,
  1148  		'8' | R_386_GOT32X<<24,
  1149  		'9' | R_PPC64_REL24<<24:
  1150  		*siz = 4
  1151  
  1152  	case '6' | R_X86_64_64<<24,
  1153  		'9' | R_PPC64_ADDR64<<24:
  1154  		*siz = 8
  1155  	}
  1156  
  1157  	return 256 + elftype
  1158  }