...

Source file src/pkg/cmd/link/internal/loadelf/ldelf.go

     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 returned 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			f.MustSeek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0)
   594			sect := &elfobj.sect[i]
   595			if is64 != 0 {
   596				var b ElfSectBytes64
   597	
   598				if err := binary.Read(f, e, &b); err != nil {
   599					return errorf("malformed elf file: %v", err)
   600				}
   601	
   602				sect.nameoff = e.Uint32(b.Name[:])
   603				sect.type_ = e.Uint32(b.Type[:])
   604				sect.flags = e.Uint64(b.Flags[:])
   605				sect.addr = e.Uint64(b.Addr[:])
   606				sect.off = e.Uint64(b.Off[:])
   607				sect.size = e.Uint64(b.Size[:])
   608				sect.link = e.Uint32(b.Link[:])
   609				sect.info = e.Uint32(b.Info[:])
   610				sect.align = e.Uint64(b.Align[:])
   611				sect.entsize = e.Uint64(b.Entsize[:])
   612			} else {
   613				var b ElfSectBytes
   614	
   615				if err := binary.Read(f, e, &b); err != nil {
   616					return errorf("malformed elf file: %v", err)
   617				}
   618	
   619				sect.nameoff = e.Uint32(b.Name[:])
   620				sect.type_ = e.Uint32(b.Type[:])
   621				sect.flags = uint64(e.Uint32(b.Flags[:]))
   622				sect.addr = uint64(e.Uint32(b.Addr[:]))
   623				sect.off = uint64(e.Uint32(b.Off[:]))
   624				sect.size = uint64(e.Uint32(b.Size[:]))
   625				sect.link = e.Uint32(b.Link[:])
   626				sect.info = e.Uint32(b.Info[:])
   627				sect.align = uint64(e.Uint32(b.Align[:]))
   628				sect.entsize = uint64(e.Uint32(b.Entsize[:]))
   629			}
   630		}
   631	
   632		// read section string table and translate names
   633		if elfobj.shstrndx >= uint32(elfobj.nsect) {
   634			return errorf("malformed elf file: shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect)
   635		}
   636	
   637		sect := &elfobj.sect[elfobj.shstrndx]
   638		if err := elfmap(elfobj, sect); err != nil {
   639			return errorf("malformed elf file: %v", err)
   640		}
   641		for i := 0; uint(i) < elfobj.nsect; i++ {
   642			if elfobj.sect[i].nameoff != 0 {
   643				elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:])
   644			}
   645		}
   646	
   647		// load string table for symbols into memory.
   648		elfobj.symtab = section(elfobj, ".symtab")
   649	
   650		if elfobj.symtab == nil {
   651			// our work is done here - no symbols means nothing can refer to this file
   652			return
   653		}
   654	
   655		if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) {
   656			return errorf("elf object has symbol table with invalid string table link")
   657		}
   658	
   659		elfobj.symstr = &elfobj.sect[elfobj.symtab.link]
   660		if is64 != 0 {
   661			elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE)
   662		} else {
   663			elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE)
   664		}
   665	
   666		if err := elfmap(elfobj, elfobj.symtab); err != nil {
   667			return errorf("malformed elf file: %v", err)
   668		}
   669		if err := elfmap(elfobj, elfobj.symstr); err != nil {
   670			return errorf("malformed elf file: %v", err)
   671		}
   672	
   673		// load text and data segments into memory.
   674		// they are not as small as the section lists, but we'll need
   675		// the memory anyway for the symbol images, so we might
   676		// as well use one large chunk.
   677	
   678		// create symbols for elfmapped sections
   679		sectsymNames := make(map[string]bool)
   680		counter := 0
   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			for sectsymNames[name] {
   713				counter++
   714				name = fmt.Sprintf("%s(%s%d)", pkg, sect.name, counter)
   715			}
   716			sectsymNames[name] = true
   717	
   718			s := syms.Lookup(name, localSymVersion)
   719	
   720			switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) {
   721			default:
   722				return errorf("%s: unexpected flags for ELF section %s", pn, sect.name)
   723	
   724			case ElfSectFlagAlloc:
   725				s.Type = sym.SRODATA
   726	
   727			case ElfSectFlagAlloc + ElfSectFlagWrite:
   728				if sect.type_ == ElfSectNobits {
   729					s.Type = sym.SNOPTRBSS
   730				} else {
   731					s.Type = sym.SNOPTRDATA
   732				}
   733	
   734			case ElfSectFlagAlloc + ElfSectFlagExec:
   735				s.Type = sym.STEXT
   736			}
   737	
   738			if sect.name == ".got" || sect.name == ".toc" {
   739				s.Type = sym.SELFGOT
   740			}
   741			if sect.type_ == ElfSectProgbits {
   742				s.P = sect.base
   743				s.P = s.P[:sect.size]
   744			}
   745	
   746			s.Size = int64(sect.size)
   747			s.Align = int32(sect.align)
   748			sect.sym = s
   749		}
   750	
   751		// enter sub-symbols into symbol table.
   752		// symbol 0 is the null symbol.
   753		symbols := make([]*sym.Symbol, elfobj.nsymtab)
   754	
   755		for i := 1; i < elfobj.nsymtab; i++ {
   756			var elfsym ElfSym
   757			if err := readelfsym(arch, syms, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
   758				return errorf("%s: malformed elf file: %v", pn, err)
   759			}
   760			symbols[i] = elfsym.sym
   761			if elfsym.type_ != ElfSymTypeFunc && elfsym.type_ != ElfSymTypeObject && elfsym.type_ != ElfSymTypeNone && elfsym.type_ != ElfSymTypeCommon {
   762				continue
   763			}
   764			if elfsym.shndx == ElfSymShnCommon || elfsym.type_ == ElfSymTypeCommon {
   765				s := elfsym.sym
   766				if uint64(s.Size) < elfsym.size {
   767					s.Size = int64(elfsym.size)
   768				}
   769				if s.Type == 0 || s.Type == sym.SXREF {
   770					s.Type = sym.SNOPTRBSS
   771				}
   772				continue
   773			}
   774	
   775			if uint(elfsym.shndx) >= elfobj.nsect || elfsym.shndx == 0 {
   776				continue
   777			}
   778	
   779			// even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
   780			if elfsym.sym == nil {
   781				continue
   782			}
   783			sect = &elfobj.sect[elfsym.shndx]
   784			if sect.sym == nil {
   785				if strings.HasPrefix(elfsym.name, ".Linfo_string") { // clang does this
   786					continue
   787				}
   788	
   789				if elfsym.name == "" && elfsym.type_ == 0 && sect.name == ".debug_str" {
   790					// This reportedly happens with clang 3.7 on ARM.
   791					// See issue 13139.
   792					continue
   793				}
   794	
   795				if strings.HasPrefix(elfsym.name, "$d") && elfsym.type_ == 0 && sect.name == ".debug_frame" {
   796					// "$d" is a marker, not a real symbol.
   797					// This happens with gcc on ARM64.
   798					// See https://sourceware.org/bugzilla/show_bug.cgi?id=21809
   799					continue
   800				}
   801	
   802				if strings.HasPrefix(elfsym.name, ".LASF") { // gcc on s390x does this
   803					continue
   804				}
   805				return errorf("%v: sym#%d: ignoring symbol in section %d (type %d)", elfsym.sym, i, elfsym.shndx, elfsym.type_)
   806			}
   807	
   808			s := elfsym.sym
   809			if s.Outer != nil {
   810				if s.Attr.DuplicateOK() {
   811					continue
   812				}
   813				return errorf("duplicate symbol reference: %s in both %s and %s", s.Name, s.Outer.Name, sect.sym.Name)
   814			}
   815	
   816			s.Sub = sect.sym.Sub
   817			sect.sym.Sub = s
   818			s.Type = sect.sym.Type
   819			s.Attr |= sym.AttrSubSymbol
   820			if !s.Attr.CgoExportDynamic() {
   821				s.SetDynimplib("") // satisfy dynimport
   822			}
   823			s.Value = int64(elfsym.value)
   824			s.Size = int64(elfsym.size)
   825			s.Outer = sect.sym
   826			if sect.sym.Type == sym.STEXT {
   827				if s.Attr.External() && !s.Attr.DuplicateOK() {
   828					return errorf("%v: duplicate symbol definition", s)
   829				}
   830				s.Attr |= sym.AttrExternal
   831			}
   832	
   833			if elfobj.machine == ElfMachPower64 {
   834				flag := int(elfsym.other) >> 5
   835				if 2 <= flag && flag <= 6 {
   836					s.SetLocalentry(1 << uint(flag-2))
   837				} else if flag == 7 {
   838					return errorf("%v: invalid sym.other 0x%x", s, elfsym.other)
   839				}
   840			}
   841		}
   842	
   843		// Sort outer lists by address, adding to textp.
   844		// This keeps textp in increasing address order.
   845		for i := uint(0); i < elfobj.nsect; i++ {
   846			s := elfobj.sect[i].sym
   847			if s == nil {
   848				continue
   849			}
   850			if s.Sub != nil {
   851				s.Sub = sym.SortSub(s.Sub)
   852			}
   853			if s.Type == sym.STEXT {
   854				if s.Attr.OnList() {
   855					return errorf("symbol %s listed multiple times", s.Name)
   856				}
   857				s.Attr |= sym.AttrOnList
   858				textp = append(textp, s)
   859				for s = s.Sub; s != nil; s = s.Sub {
   860					if s.Attr.OnList() {
   861						return errorf("symbol %s listed multiple times", s.Name)
   862					}
   863					s.Attr |= sym.AttrOnList
   864					textp = append(textp, s)
   865				}
   866			}
   867		}
   868	
   869		// load relocations
   870		for i := uint(0); i < elfobj.nsect; i++ {
   871			rsect := &elfobj.sect[i]
   872			if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel {
   873				continue
   874			}
   875			if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
   876				continue
   877			}
   878			sect = &elfobj.sect[rsect.info]
   879			if err := elfmap(elfobj, rsect); err != nil {
   880				return errorf("malformed elf file: %v", err)
   881			}
   882			rela := 0
   883			if rsect.type_ == ElfSectRela {
   884				rela = 1
   885			}
   886			n := int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
   887			r := make([]sym.Reloc, n)
   888			p := rsect.base
   889			for j := 0; j < n; j++ {
   890				var add uint64
   891				rp := &r[j]
   892				var info uint64
   893				if is64 != 0 {
   894					// 64-bit rel/rela
   895					rp.Off = int32(e.Uint64(p))
   896	
   897					p = p[8:]
   898					info = e.Uint64(p)
   899					p = p[8:]
   900					if rela != 0 {
   901						add = e.Uint64(p)
   902						p = p[8:]
   903					}
   904				} else {
   905					// 32-bit rel/rela
   906					rp.Off = int32(e.Uint32(p))
   907	
   908					p = p[4:]
   909					info = uint64(e.Uint32(p))
   910					info = info>>8<<32 | info&0xff // convert to 64-bit info
   911					p = p[4:]
   912					if rela != 0 {
   913						add = uint64(e.Uint32(p))
   914						p = p[4:]
   915					}
   916				}
   917	
   918				if info&0xffffffff == 0 { // skip R_*_NONE relocation
   919					j--
   920					n--
   921					continue
   922				}
   923	
   924				if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol
   925					rp.Sym = nil
   926				} else {
   927					var elfsym ElfSym
   928					if err := readelfsym(arch, syms, elfobj, int(info>>32), &elfsym, 0, 0); err != nil {
   929						return errorf("malformed elf file: %v", err)
   930					}
   931					elfsym.sym = symbols[info>>32]
   932					if elfsym.sym == nil {
   933						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_)
   934					}
   935	
   936					rp.Sym = elfsym.sym
   937				}
   938	
   939				rp.Type = objabi.ElfRelocOffset + objabi.RelocType(info)
   940				rp.Siz, err = relSize(arch, pn, uint32(info))
   941				if err != nil {
   942					return nil, 0, err
   943				}
   944				if rela != 0 {
   945					rp.Add = int64(add)
   946				} else {
   947					// load addend from image
   948					if rp.Siz == 4 {
   949						rp.Add = int64(e.Uint32(sect.base[rp.Off:]))
   950					} else if rp.Siz == 8 {
   951						rp.Add = int64(e.Uint64(sect.base[rp.Off:]))
   952					} else {
   953						return errorf("invalid rela size %d", rp.Siz)
   954					}
   955				}
   956	
   957				if rp.Siz == 2 {
   958					rp.Add = int64(int16(rp.Add))
   959				}
   960				if rp.Siz == 4 {
   961					rp.Add = int64(int32(rp.Add))
   962				}
   963			}
   964	
   965			//print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add);
   966			sort.Sort(sym.RelocByOff(r[:n]))
   967			// just in case
   968	
   969			s := sect.sym
   970			s.R = r
   971			s.R = s.R[:n]
   972		}
   973	
   974		return textp, ehdrFlags, nil
   975	}
   976	
   977	func section(elfobj *ElfObj, name string) *ElfSect {
   978		for i := 0; uint(i) < elfobj.nsect; i++ {
   979			if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
   980				return &elfobj.sect[i]
   981			}
   982		}
   983		return nil
   984	}
   985	
   986	func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
   987		if sect.base != nil {
   988			return nil
   989		}
   990	
   991		if sect.off+sect.size > uint64(elfobj.length) {
   992			err = fmt.Errorf("elf section past end of file")
   993			return err
   994		}
   995	
   996		sect.base = make([]byte, sect.size)
   997		elfobj.f.MustSeek(int64(uint64(elfobj.base)+sect.off), 0)
   998		if _, err := io.ReadFull(elfobj.f, sect.base); err != nil {
   999			return fmt.Errorf("short read: %v", err)
  1000		}
  1001	
  1002		return nil
  1003	}
  1004	
  1005	func readelfsym(arch *sys.Arch, syms *sym.Symbols, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
  1006		if i >= elfobj.nsymtab || i < 0 {
  1007			err = fmt.Errorf("invalid elf symbol index")
  1008			return err
  1009		}
  1010	
  1011		if i == 0 {
  1012			return fmt.Errorf("readym: read null symbol!")
  1013		}
  1014	
  1015		if elfobj.is64 != 0 {
  1016			b := new(ElfSymBytes64)
  1017			binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b)
  1018			elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
  1019			elfsym.value = elfobj.e.Uint64(b.Value[:])
  1020			elfsym.size = elfobj.e.Uint64(b.Size[:])
  1021			elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
  1022			elfsym.bind = b.Info >> 4
  1023			elfsym.type_ = b.Info & 0xf
  1024			elfsym.other = b.Other
  1025		} else {
  1026			b := new(ElfSymBytes)
  1027			binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b)
  1028			elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
  1029			elfsym.value = uint64(elfobj.e.Uint32(b.Value[:]))
  1030			elfsym.size = uint64(elfobj.e.Uint32(b.Size[:]))
  1031			elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
  1032			elfsym.bind = b.Info >> 4
  1033			elfsym.type_ = b.Info & 0xf
  1034			elfsym.other = b.Other
  1035		}
  1036	
  1037		var s *sym.Symbol
  1038		if elfsym.name == "_GLOBAL_OFFSET_TABLE_" {
  1039			elfsym.name = ".got"
  1040		}
  1041		if elfsym.name == ".TOC." {
  1042			// Magic symbol on ppc64.  Will be set to this object
  1043			// file's .got+0x8000.
  1044			elfsym.bind = ElfSymBindLocal
  1045		}
  1046	
  1047		switch elfsym.type_ {
  1048		case ElfSymTypeSection:
  1049			s = elfobj.sect[elfsym.shndx].sym
  1050	
  1051		case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone, ElfSymTypeCommon:
  1052			switch elfsym.bind {
  1053			case ElfSymBindGlobal:
  1054				if needSym != 0 {
  1055					s = syms.Lookup(elfsym.name, 0)
  1056	
  1057					// for global scoped hidden symbols we should insert it into
  1058					// symbol hash table, but mark them as hidden.
  1059					// __i686.get_pc_thunk.bx is allowed to be duplicated, to
  1060					// workaround that we set dupok.
  1061					// TODO(minux): correctly handle __i686.get_pc_thunk.bx without
  1062					// set dupok generally. See https://golang.org/cl/5823055
  1063					// comment #5 for details.
  1064					if s != nil && elfsym.other == 2 {
  1065						s.Attr |= sym.AttrDuplicateOK | sym.AttrVisibilityHidden
  1066					}
  1067				}
  1068	
  1069			case ElfSymBindLocal:
  1070				if (arch.Family == sys.ARM || arch.Family == sys.ARM64) && (strings.HasPrefix(elfsym.name, "$a") || strings.HasPrefix(elfsym.name, "$d") || strings.HasPrefix(elfsym.name, "$x")) {
  1071					// binutils for arm and arm64 generate these mapping
  1072					// symbols, ignore these
  1073					break
  1074				}
  1075	
  1076				if elfsym.name == ".TOC." {
  1077					// We need to be able to look this up,
  1078					// so put it in the hash table.
  1079					if needSym != 0 {
  1080						s = syms.Lookup(elfsym.name, localSymVersion)
  1081						s.Attr |= sym.AttrVisibilityHidden
  1082					}
  1083	
  1084					break
  1085				}
  1086	
  1087				if needSym != 0 {
  1088					// local names and hidden global names are unique
  1089					// and should only be referenced by their index, not name, so we
  1090					// don't bother to add them into the hash table
  1091					s = syms.Newsym(elfsym.name, localSymVersion)
  1092	
  1093					s.Attr |= sym.AttrVisibilityHidden
  1094				}
  1095	
  1096			case ElfSymBindWeak:
  1097				if needSym != 0 {
  1098					s = syms.Lookup(elfsym.name, 0)
  1099					if elfsym.other == 2 {
  1100						s.Attr |= sym.AttrVisibilityHidden
  1101					}
  1102	
  1103					// Allow weak symbols to be duplicated when already defined.
  1104					if s.Outer != nil {
  1105						s.Attr |= sym.AttrDuplicateOK
  1106					}
  1107				}
  1108	
  1109			default:
  1110				err = fmt.Errorf("%s: invalid symbol binding %d", elfsym.name, elfsym.bind)
  1111				return err
  1112			}
  1113		}
  1114	
  1115		// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
  1116		// sense and should be removed when someone has thought about it properly.
  1117		if s != nil && s.Type == 0 && !s.Attr.VisibilityHidden() && elfsym.type_ != ElfSymTypeSection {
  1118			s.Type = sym.SXREF
  1119		}
  1120		elfsym.sym = s
  1121	
  1122		return nil
  1123	}
  1124	
  1125	func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, error) {
  1126		// TODO(mdempsky): Replace this with a struct-valued switch statement
  1127		// once golang.org/issue/15164 is fixed or found to not impair cmd/link
  1128		// performance.
  1129	
  1130		const (
  1131			AMD64 = uint32(sys.AMD64)
  1132			ARM   = uint32(sys.ARM)
  1133			ARM64 = uint32(sys.ARM64)
  1134			I386  = uint32(sys.I386)
  1135			PPC64 = uint32(sys.PPC64)
  1136			S390X = uint32(sys.S390X)
  1137		)
  1138	
  1139		switch uint32(arch.Family) | elftype<<16 {
  1140		default:
  1141			return 0, fmt.Errorf("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
  1142	
  1143		case S390X | uint32(elf.R_390_8)<<16:
  1144			return 1, nil
  1145	
  1146		case PPC64 | uint32(elf.R_PPC64_TOC16)<<16,
  1147			PPC64 | uint32(elf.R_PPC64_TOC16_LO)<<16,
  1148			PPC64 | uint32(elf.R_PPC64_TOC16_HI)<<16,
  1149			PPC64 | uint32(elf.R_PPC64_TOC16_HA)<<16,
  1150			PPC64 | uint32(elf.R_PPC64_TOC16_DS)<<16,
  1151			PPC64 | uint32(elf.R_PPC64_TOC16_LO_DS)<<16,
  1152			PPC64 | uint32(elf.R_PPC64_REL16_LO)<<16,
  1153			PPC64 | uint32(elf.R_PPC64_REL16_HI)<<16,
  1154			PPC64 | uint32(elf.R_PPC64_REL16_HA)<<16,
  1155			S390X | uint32(elf.R_390_16)<<16,
  1156			S390X | uint32(elf.R_390_GOT16)<<16,
  1157			S390X | uint32(elf.R_390_PC16)<<16,
  1158			S390X | uint32(elf.R_390_PC16DBL)<<16,
  1159			S390X | uint32(elf.R_390_PLT16DBL)<<16:
  1160			return 2, nil
  1161	
  1162		case ARM | uint32(elf.R_ARM_ABS32)<<16,
  1163			ARM | uint32(elf.R_ARM_GOT32)<<16,
  1164			ARM | uint32(elf.R_ARM_PLT32)<<16,
  1165			ARM | uint32(elf.R_ARM_GOTOFF)<<16,
  1166			ARM | uint32(elf.R_ARM_GOTPC)<<16,
  1167			ARM | uint32(elf.R_ARM_THM_PC22)<<16,
  1168			ARM | uint32(elf.R_ARM_REL32)<<16,
  1169			ARM | uint32(elf.R_ARM_CALL)<<16,
  1170			ARM | uint32(elf.R_ARM_V4BX)<<16,
  1171			ARM | uint32(elf.R_ARM_GOT_PREL)<<16,
  1172			ARM | uint32(elf.R_ARM_PC24)<<16,
  1173			ARM | uint32(elf.R_ARM_JUMP24)<<16,
  1174			ARM64 | uint32(elf.R_AARCH64_CALL26)<<16,
  1175			ARM64 | uint32(elf.R_AARCH64_ADR_GOT_PAGE)<<16,
  1176			ARM64 | uint32(elf.R_AARCH64_LD64_GOT_LO12_NC)<<16,
  1177			ARM64 | uint32(elf.R_AARCH64_ADR_PREL_PG_HI21)<<16,
  1178			ARM64 | uint32(elf.R_AARCH64_ADD_ABS_LO12_NC)<<16,
  1179			ARM64 | uint32(elf.R_AARCH64_LDST8_ABS_LO12_NC)<<16,
  1180			ARM64 | uint32(elf.R_AARCH64_LDST32_ABS_LO12_NC)<<16,
  1181			ARM64 | uint32(elf.R_AARCH64_LDST64_ABS_LO12_NC)<<16,
  1182			ARM64 | uint32(elf.R_AARCH64_LDST128_ABS_LO12_NC)<<16,
  1183			ARM64 | uint32(elf.R_AARCH64_PREL32)<<16,
  1184			ARM64 | uint32(elf.R_AARCH64_JUMP26)<<16,
  1185			AMD64 | uint32(elf.R_X86_64_PC32)<<16,
  1186			AMD64 | uint32(elf.R_X86_64_PLT32)<<16,
  1187			AMD64 | uint32(elf.R_X86_64_GOTPCREL)<<16,
  1188			AMD64 | uint32(elf.R_X86_64_GOTPCRELX)<<16,
  1189			AMD64 | uint32(elf.R_X86_64_REX_GOTPCRELX)<<16,
  1190			I386 | uint32(elf.R_386_32)<<16,
  1191			I386 | uint32(elf.R_386_PC32)<<16,
  1192			I386 | uint32(elf.R_386_GOT32)<<16,
  1193			I386 | uint32(elf.R_386_PLT32)<<16,
  1194			I386 | uint32(elf.R_386_GOTOFF)<<16,
  1195			I386 | uint32(elf.R_386_GOTPC)<<16,
  1196			I386 | uint32(elf.R_386_GOT32X)<<16,
  1197			PPC64 | uint32(elf.R_PPC64_REL24)<<16,
  1198			PPC64 | uint32(elf.R_PPC_REL32)<<16,
  1199			S390X | uint32(elf.R_390_32)<<16,
  1200			S390X | uint32(elf.R_390_PC32)<<16,
  1201			S390X | uint32(elf.R_390_GOT32)<<16,
  1202			S390X | uint32(elf.R_390_PLT32)<<16,
  1203			S390X | uint32(elf.R_390_PC32DBL)<<16,
  1204			S390X | uint32(elf.R_390_PLT32DBL)<<16,
  1205			S390X | uint32(elf.R_390_GOTPCDBL)<<16,
  1206			S390X | uint32(elf.R_390_GOTENT)<<16:
  1207			return 4, nil
  1208	
  1209		case AMD64 | uint32(elf.R_X86_64_64)<<16,
  1210			AMD64 | uint32(elf.R_X86_64_PC64)<<16,
  1211			ARM64 | uint32(elf.R_AARCH64_ABS64)<<16,
  1212			ARM64 | uint32(elf.R_AARCH64_PREL64)<<16,
  1213			PPC64 | uint32(elf.R_PPC64_ADDR64)<<16,
  1214			S390X | uint32(elf.R_390_GLOB_DAT)<<16,
  1215			S390X | uint32(elf.R_390_RELATIVE)<<16,
  1216			S390X | uint32(elf.R_390_GOTOFF)<<16,
  1217			S390X | uint32(elf.R_390_GOTPC)<<16,
  1218			S390X | uint32(elf.R_390_64)<<16,
  1219			S390X | uint32(elf.R_390_PC64)<<16,
  1220			S390X | uint32(elf.R_390_GOT64)<<16,
  1221			S390X | uint32(elf.R_390_PLT64)<<16:
  1222			return 8, nil
  1223		}
  1224	}
  1225	
  1226	func cstring(x []byte) string {
  1227		i := bytes.IndexByte(x, '\x00')
  1228		if i >= 0 {
  1229			x = x[:i]
  1230		}
  1231		return string(x)
  1232	}
  1233	

View as plain text