github.com/huandu/go@v0.0.0-20151114150818-04e615e41150/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  	"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         *obj.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 *obj.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(obj.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 obj.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 obj.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 = obj.SRODATA
   571  
   572  		case ElfSectFlagAlloc + ElfSectFlagWrite:
   573  			if sect.type_ == ElfSectNobits {
   574  				s.Type = obj.SNOPTRBSS
   575  			} else {
   576  				s.Type = obj.SNOPTRDATA
   577  			}
   578  
   579  		case ElfSectFlagAlloc + ElfSectFlagExec:
   580  			s.Type = obj.STEXT
   581  		}
   582  
   583  		if sect.name == ".got" || sect.name == ".toc" {
   584  			s.Type = obj.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  	for i := 1; i < elfobj.nsymtab; i++ {
   601  		if err = readelfsym(elfobj, i, &sym, 1); err != nil {
   602  			goto bad
   603  		}
   604  		symbols[i] = sym.sym
   605  		if sym.type_ != ElfSymTypeFunc && sym.type_ != ElfSymTypeObject && sym.type_ != ElfSymTypeNone {
   606  			continue
   607  		}
   608  		if sym.shndx == ElfSymShnCommon {
   609  			s = sym.sym
   610  			if uint64(s.Size) < sym.size {
   611  				s.Size = int64(sym.size)
   612  			}
   613  			if s.Type == 0 || s.Type == obj.SXREF {
   614  				s.Type = obj.SNOPTRBSS
   615  			}
   616  			continue
   617  		}
   618  
   619  		if uint(sym.shndx) >= elfobj.nsect || sym.shndx == 0 {
   620  			continue
   621  		}
   622  
   623  		// even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
   624  		if sym.sym == nil {
   625  			continue
   626  		}
   627  		sect = &elfobj.sect[sym.shndx:][0]
   628  		if sect.sym == nil {
   629  			if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this
   630  				continue
   631  			}
   632  			Diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type_)
   633  			continue
   634  		}
   635  
   636  		s = sym.sym
   637  		if s.Outer != nil {
   638  			if s.Dupok != 0 {
   639  				continue
   640  			}
   641  			Exitf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sect.sym.Name)
   642  		}
   643  
   644  		s.Sub = sect.sym.Sub
   645  		sect.sym.Sub = s
   646  		s.Type = sect.sym.Type | s.Type&^obj.SMASK | obj.SSUB
   647  		if s.Cgoexport&CgoExportDynamic == 0 {
   648  			s.Dynimplib = "" // satisfy dynimport
   649  		}
   650  		s.Value = int64(sym.value)
   651  		s.Size = int64(sym.size)
   652  		s.Outer = sect.sym
   653  		if sect.sym.Type == obj.STEXT {
   654  			if s.External != 0 && s.Dupok == 0 {
   655  				Diag("%s: duplicate definition of %s", pn, s.Name)
   656  			}
   657  			s.External = 1
   658  		}
   659  
   660  		if elfobj.machine == ElfMachPower64 {
   661  			flag = int(sym.other) >> 5
   662  			if 2 <= flag && flag <= 6 {
   663  				s.Localentry = 1 << uint(flag-2)
   664  			} else if flag == 7 {
   665  				Diag("%s: invalid sym.other 0x%x for %s", pn, sym.other, s.Name)
   666  			}
   667  		}
   668  	}
   669  
   670  	// Sort outer lists by address, adding to textp.
   671  	// This keeps textp in increasing address order.
   672  	for i := 0; uint(i) < elfobj.nsect; i++ {
   673  		s = elfobj.sect[i].sym
   674  		if s == nil {
   675  			continue
   676  		}
   677  		if s.Sub != nil {
   678  			s.Sub = listsort(s.Sub, valuecmp, listsubp)
   679  		}
   680  		if s.Type == obj.STEXT {
   681  			if s.Onlist != 0 {
   682  				log.Fatalf("symbol %s listed multiple times", s.Name)
   683  			}
   684  			s.Onlist = 1
   685  			if Ctxt.Etextp != nil {
   686  				Ctxt.Etextp.Next = s
   687  			} else {
   688  				Ctxt.Textp = s
   689  			}
   690  			Ctxt.Etextp = s
   691  			for s = s.Sub; s != nil; s = s.Sub {
   692  				if s.Onlist != 0 {
   693  					log.Fatalf("symbol %s listed multiple times", s.Name)
   694  				}
   695  				s.Onlist = 1
   696  				Ctxt.Etextp.Next = s
   697  				Ctxt.Etextp = s
   698  			}
   699  		}
   700  	}
   701  
   702  	// load relocations
   703  	for i := 0; uint(i) < elfobj.nsect; i++ {
   704  		rsect = &elfobj.sect[i]
   705  		if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel {
   706  			continue
   707  		}
   708  		if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
   709  			continue
   710  		}
   711  		sect = &elfobj.sect[rsect.info]
   712  		if err = elfmap(elfobj, rsect); err != nil {
   713  			goto bad
   714  		}
   715  		rela = 0
   716  		if rsect.type_ == ElfSectRela {
   717  			rela = 1
   718  		}
   719  		n = int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
   720  		r = make([]Reloc, n)
   721  		p = rsect.base
   722  		for j = 0; j < n; j++ {
   723  			add = 0
   724  			rp = &r[j]
   725  			if is64 != 0 {
   726  				// 64-bit rel/rela
   727  				rp.Off = int32(e.Uint64(p))
   728  
   729  				p = p[8:]
   730  				info = e.Uint64(p)
   731  				p = p[8:]
   732  				if rela != 0 {
   733  					add = e.Uint64(p)
   734  					p = p[8:]
   735  				}
   736  			} else {
   737  				// 32-bit rel/rela
   738  				rp.Off = int32(e.Uint32(p))
   739  
   740  				p = p[4:]
   741  				info = uint64(e.Uint32(p))
   742  				info = info>>8<<32 | info&0xff // convert to 64-bit info
   743  				p = p[4:]
   744  				if rela != 0 {
   745  					add = uint64(e.Uint32(p))
   746  					p = p[4:]
   747  				}
   748  			}
   749  
   750  			if info&0xffffffff == 0 { // skip R_*_NONE relocation
   751  				j--
   752  				n--
   753  				continue
   754  			}
   755  
   756  			if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol
   757  				rp.Sym = nil
   758  			} else {
   759  				if err = readelfsym(elfobj, int(info>>32), &sym, 0); err != nil {
   760  					goto bad
   761  				}
   762  				sym.sym = symbols[info>>32]
   763  				if sym.sym == nil {
   764  					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_)
   765  					goto bad
   766  				}
   767  
   768  				rp.Sym = sym.sym
   769  			}
   770  
   771  			rp.Type = int32(reltype(pn, int(uint32(info)), &rp.Siz))
   772  			if rela != 0 {
   773  				rp.Add = int64(add)
   774  			} else {
   775  				// load addend from image
   776  				if rp.Siz == 4 {
   777  					rp.Add = int64(e.Uint32(sect.base[rp.Off:]))
   778  				} else if rp.Siz == 8 {
   779  					rp.Add = int64(e.Uint64(sect.base[rp.Off:]))
   780  				} else {
   781  					Diag("invalid rela size %d", rp.Siz)
   782  				}
   783  			}
   784  
   785  			if rp.Siz == 2 {
   786  				rp.Add = int64(int16(rp.Add))
   787  			}
   788  			if rp.Siz == 4 {
   789  				rp.Add = int64(int32(rp.Add))
   790  			}
   791  		}
   792  
   793  		//print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add);
   794  		sort.Sort(rbyoff(r[:n]))
   795  		// just in case
   796  
   797  		s = sect.sym
   798  		s.R = r
   799  		s.R = s.R[:n]
   800  	}
   801  
   802  	return
   803  
   804  bad:
   805  	Diag("%s: malformed elf file: %v", pn, err)
   806  }
   807  
   808  func section(elfobj *ElfObj, name string) *ElfSect {
   809  	for i := 0; uint(i) < elfobj.nsect; i++ {
   810  		if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
   811  			return &elfobj.sect[i]
   812  		}
   813  	}
   814  	return nil
   815  }
   816  
   817  func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
   818  	if sect.base != nil {
   819  		return nil
   820  	}
   821  
   822  	if sect.off+sect.size > uint64(elfobj.length) {
   823  		err = fmt.Errorf("elf section past end of file")
   824  		return err
   825  	}
   826  
   827  	sect.base = make([]byte, sect.size)
   828  	err = fmt.Errorf("short read")
   829  	if obj.Bseek(elfobj.f, int64(uint64(elfobj.base)+sect.off), 0) < 0 || obj.Bread(elfobj.f, sect.base) != len(sect.base) {
   830  		return err
   831  	}
   832  
   833  	return nil
   834  }
   835  
   836  func readelfsym(elfobj *ElfObj, i int, sym *ElfSym, needSym int) (err error) {
   837  	if i >= elfobj.nsymtab || i < 0 {
   838  		err = fmt.Errorf("invalid elf symbol index")
   839  		return err
   840  	}
   841  
   842  	if i == 0 {
   843  		Diag("readym: read null symbol!")
   844  	}
   845  
   846  	if elfobj.is64 != 0 {
   847  		b := new(ElfSymBytes64)
   848  		binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b)
   849  		sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
   850  		sym.value = elfobj.e.Uint64(b.Value[:])
   851  		sym.size = elfobj.e.Uint64(b.Size[:])
   852  		sym.shndx = elfobj.e.Uint16(b.Shndx[:])
   853  		sym.bind = b.Info >> 4
   854  		sym.type_ = b.Info & 0xf
   855  		sym.other = b.Other
   856  	} else {
   857  		b := new(ElfSymBytes)
   858  		binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b)
   859  		sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
   860  		sym.value = uint64(elfobj.e.Uint32(b.Value[:]))
   861  		sym.size = uint64(elfobj.e.Uint32(b.Size[:]))
   862  		sym.shndx = elfobj.e.Uint16(b.Shndx[:])
   863  		sym.bind = b.Info >> 4
   864  		sym.type_ = b.Info & 0xf
   865  		sym.other = b.Other
   866  	}
   867  
   868  	var s *LSym
   869  	if sym.name == "_GLOBAL_OFFSET_TABLE_" {
   870  		sym.name = ".got"
   871  	}
   872  	if sym.name == ".TOC." {
   873  		// Magic symbol on ppc64.  Will be set to this object
   874  		// file's .got+0x8000.
   875  		sym.bind = ElfSymBindLocal
   876  	}
   877  
   878  	switch sym.type_ {
   879  	case ElfSymTypeSection:
   880  		s = elfobj.sect[sym.shndx].sym
   881  
   882  	case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone:
   883  		switch sym.bind {
   884  		case ElfSymBindGlobal:
   885  			if needSym != 0 {
   886  				s = Linklookup(Ctxt, sym.name, 0)
   887  
   888  				// for global scoped hidden symbols we should insert it into
   889  				// symbol hash table, but mark them as hidden.
   890  				// __i686.get_pc_thunk.bx is allowed to be duplicated, to
   891  				// workaround that we set dupok.
   892  				// TODO(minux): correctly handle __i686.get_pc_thunk.bx without
   893  				// set dupok generally. See http://codereview.appspot.com/5823055/
   894  				// comment #5 for details.
   895  				if s != nil && sym.other == 2 {
   896  					s.Type |= obj.SHIDDEN
   897  					s.Dupok = 1
   898  				}
   899  			}
   900  
   901  		case ElfSymBindLocal:
   902  			if Thearch.Thechar == '5' && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) {
   903  				// binutils for arm generate these mapping
   904  				// symbols, ignore these
   905  				break
   906  			}
   907  
   908  			if sym.name == ".TOC." {
   909  				// We need to be able to look this up,
   910  				// so put it in the hash table.
   911  				if needSym != 0 {
   912  					s = Linklookup(Ctxt, sym.name, Ctxt.Version)
   913  					s.Type |= obj.SHIDDEN
   914  				}
   915  
   916  				break
   917  			}
   918  
   919  			if needSym != 0 {
   920  				// local names and hidden visiblity global names are unique
   921  				// and should only reference by its index, not name, so we
   922  				// don't bother to add them into hash table
   923  				s = linknewsym(Ctxt, sym.name, Ctxt.Version)
   924  
   925  				s.Type |= obj.SHIDDEN
   926  			}
   927  
   928  		case ElfSymBindWeak:
   929  			if needSym != 0 {
   930  				s = linknewsym(Ctxt, sym.name, 0)
   931  				if sym.other == 2 {
   932  					s.Type |= obj.SHIDDEN
   933  				}
   934  			}
   935  
   936  		default:
   937  			err = fmt.Errorf("%s: invalid symbol binding %d", sym.name, sym.bind)
   938  			return err
   939  		}
   940  	}
   941  
   942  	if s != nil && s.Type == 0 && sym.type_ != ElfSymTypeSection {
   943  		s.Type = obj.SXREF
   944  	}
   945  	sym.sym = s
   946  
   947  	return nil
   948  }
   949  
   950  type rbyoff []Reloc
   951  
   952  func (x rbyoff) Len() int {
   953  	return len(x)
   954  }
   955  
   956  func (x rbyoff) Swap(i, j int) {
   957  	x[i], x[j] = x[j], x[i]
   958  }
   959  
   960  func (x rbyoff) Less(i, j int) bool {
   961  	a := &x[i]
   962  	b := &x[j]
   963  	if a.Off < b.Off {
   964  		return true
   965  	}
   966  	if a.Off > b.Off {
   967  		return false
   968  	}
   969  	return false
   970  }
   971  
   972  func reltype(pn string, elftype int, siz *uint8) int {
   973  	switch uint32(Thearch.Thechar) | uint32(elftype)<<24 {
   974  	default:
   975  		Diag("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
   976  		fallthrough
   977  
   978  	case '9' | R_PPC64_TOC16<<24,
   979  		'9' | R_PPC64_TOC16_LO<<24,
   980  		'9' | R_PPC64_TOC16_HI<<24,
   981  		'9' | R_PPC64_TOC16_HA<<24,
   982  		'9' | R_PPC64_TOC16_DS<<24,
   983  		'9' | R_PPC64_TOC16_LO_DS<<24,
   984  		'9' | R_PPC64_REL16_LO<<24,
   985  		'9' | R_PPC64_REL16_HI<<24,
   986  		'9' | R_PPC64_REL16_HA<<24:
   987  		*siz = 2
   988  
   989  	case '5' | R_ARM_ABS32<<24,
   990  		'5' | R_ARM_GOT32<<24,
   991  		'5' | R_ARM_PLT32<<24,
   992  		'5' | R_ARM_GOTOFF<<24,
   993  		'5' | R_ARM_GOTPC<<24,
   994  		'5' | R_ARM_THM_PC22<<24,
   995  		'5' | R_ARM_REL32<<24,
   996  		'5' | R_ARM_CALL<<24,
   997  		'5' | R_ARM_V4BX<<24,
   998  		'5' | R_ARM_GOT_PREL<<24,
   999  		'5' | R_ARM_PC24<<24,
  1000  		'5' | R_ARM_JUMP24<<24,
  1001  		'6' | R_X86_64_PC32<<24,
  1002  		'6' | R_X86_64_PLT32<<24,
  1003  		'6' | R_X86_64_GOTPCREL<<24,
  1004  		'8' | R_386_32<<24,
  1005  		'8' | R_386_PC32<<24,
  1006  		'8' | R_386_GOT32<<24,
  1007  		'8' | R_386_PLT32<<24,
  1008  		'8' | R_386_GOTOFF<<24,
  1009  		'8' | R_386_GOTPC<<24,
  1010  		'9' | R_PPC64_REL24<<24:
  1011  		*siz = 4
  1012  
  1013  	case '6' | R_X86_64_64<<24,
  1014  		'9' | R_PPC64_ADDR64<<24:
  1015  		*siz = 8
  1016  	}
  1017  
  1018  	return 256 + elftype
  1019  }