github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/link/internal/loadelf/ldelf.go (about)

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