github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/ld/ldelf.go (about)

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