rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/cmd/internal/ld/ldelf.go (about)

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