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