github.com/bir3/gocompiler@v0.9.2202/src/cmd/link/internal/loadelf/ldelf.go (about)

     1  // Copyright 2019 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/bir3/gocompiler/src/cmd/internal/bio"
    11  	"github.com/bir3/gocompiler/src/cmd/internal/objabi"
    12  	"github.com/bir3/gocompiler/src/cmd/internal/sys"
    13  	"github.com/bir3/gocompiler/src/cmd/link/internal/loader"
    14  	"github.com/bir3/gocompiler/src/cmd/link/internal/sym"
    15  	"debug/elf"
    16  	"encoding/binary"
    17  	"fmt"
    18  	"io"
    19  	"log"
    20  	"strings"
    21  )
    22  
    23  /*
    24  Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c
    25  https://github.com/9fans/plan9port/tree/master/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  
    50  const (
    51  	SHT_ARM_ATTRIBUTES = 0x70000003
    52  )
    53  
    54  type ElfSect struct {
    55  	name		string
    56  	nameoff		uint32
    57  	type_		elf.SectionType
    58  	flags		elf.SectionFlag
    59  	addr		uint64
    60  	off		uint64
    61  	size		uint64
    62  	link		uint32
    63  	info		uint32
    64  	align		uint64
    65  	entsize		uint64
    66  	base		[]byte
    67  	readOnlyMem	bool	// Is this section in readonly memory?
    68  	sym		loader.Sym
    69  }
    70  
    71  type ElfObj struct {
    72  	f		*bio.Reader
    73  	base		int64	// offset in f where ELF begins
    74  	length		int64	// length of ELF
    75  	is64		int
    76  	name		string
    77  	e		binary.ByteOrder
    78  	sect		[]ElfSect
    79  	nsect		uint
    80  	nsymtab		int
    81  	symtab		*ElfSect
    82  	symstr		*ElfSect
    83  	type_		uint32
    84  	machine		uint32
    85  	version		uint32
    86  	entry		uint64
    87  	phoff		uint64
    88  	shoff		uint64
    89  	flags		uint32
    90  	ehsize		uint32
    91  	phentsize	uint32
    92  	phnum		uint32
    93  	shentsize	uint32
    94  	shnum		uint32
    95  	shstrndx	uint32
    96  }
    97  
    98  type ElfSym struct {
    99  	name	string
   100  	value	uint64
   101  	size	uint64
   102  	bind	elf.SymBind
   103  	type_	elf.SymType
   104  	other	uint8
   105  	shndx	elf.SectionIndex
   106  	sym	loader.Sym
   107  }
   108  
   109  const (
   110  	TagFile			= 1
   111  	TagCPUName		= 4
   112  	TagCPURawName		= 5
   113  	TagCompatibility	= 32
   114  	TagNoDefaults		= 64
   115  	TagAlsoCompatibleWith	= 65
   116  	TagABIVFPArgs		= 28
   117  )
   118  
   119  type elfAttribute struct {
   120  	tag	uint64
   121  	sval	string
   122  	ival	uint64
   123  }
   124  
   125  type elfAttributeList struct {
   126  	data	[]byte
   127  	err	error
   128  }
   129  
   130  func (a *elfAttributeList) string() string {
   131  	if a.err != nil {
   132  		return ""
   133  	}
   134  	nul := bytes.IndexByte(a.data, 0)
   135  	if nul < 0 {
   136  		a.err = io.EOF
   137  		return ""
   138  	}
   139  	s := string(a.data[:nul])
   140  	a.data = a.data[nul+1:]
   141  	return s
   142  }
   143  
   144  func (a *elfAttributeList) uleb128() uint64 {
   145  	if a.err != nil {
   146  		return 0
   147  	}
   148  	v, size := binary.Uvarint(a.data)
   149  	a.data = a.data[size:]
   150  	return v
   151  }
   152  
   153  // Read an elfAttribute from the list following the rules used on ARM systems.
   154  func (a *elfAttributeList) armAttr() elfAttribute {
   155  	attr := elfAttribute{tag: a.uleb128()}
   156  	switch {
   157  	case attr.tag == TagCompatibility:
   158  		attr.ival = a.uleb128()
   159  		attr.sval = a.string()
   160  
   161  	case attr.tag == TagNoDefaults:	// Tag_nodefaults has no argument
   162  
   163  	case attr.tag == TagAlsoCompatibleWith:
   164  		// Not really, but we don't actually care about this tag.
   165  		attr.sval = a.string()
   166  
   167  	// Tag with string argument
   168  	case attr.tag == TagCPUName || attr.tag == TagCPURawName || (attr.tag >= 32 && attr.tag&1 != 0):
   169  		attr.sval = a.string()
   170  
   171  	default:	// Tag with integer argument
   172  		attr.ival = a.uleb128()
   173  	}
   174  	return attr
   175  }
   176  
   177  func (a *elfAttributeList) done() bool {
   178  	if a.err != nil || len(a.data) == 0 {
   179  		return true
   180  	}
   181  	return false
   182  }
   183  
   184  // Look for the attribute that indicates the object uses the hard-float ABI (a
   185  // file-level attribute with tag Tag_VFP_arch and value 1). Unfortunately the
   186  // format used means that we have to parse all of the file-level attributes to
   187  // find the one we are looking for. This format is slightly documented in "ELF
   188  // for the ARM Architecture" but mostly this is derived from reading the source
   189  // to gold and readelf.
   190  func parseArmAttributes(e binary.ByteOrder, data []byte) (found bool, ehdrFlags uint32, err error) {
   191  	found = false
   192  	if data[0] != 'A' {
   193  		return false, 0, fmt.Errorf(".ARM.attributes has unexpected format %c\n", data[0])
   194  	}
   195  	data = data[1:]
   196  	for len(data) != 0 {
   197  		sectionlength := e.Uint32(data)
   198  		sectiondata := data[4:sectionlength]
   199  		data = data[sectionlength:]
   200  
   201  		nulIndex := bytes.IndexByte(sectiondata, 0)
   202  		if nulIndex < 0 {
   203  			return false, 0, fmt.Errorf("corrupt .ARM.attributes (section name not NUL-terminated)\n")
   204  		}
   205  		name := string(sectiondata[:nulIndex])
   206  		sectiondata = sectiondata[nulIndex+1:]
   207  
   208  		if name != "aeabi" {
   209  			continue
   210  		}
   211  		for len(sectiondata) != 0 {
   212  			subsectiontag, sz := binary.Uvarint(sectiondata)
   213  			subsectionsize := e.Uint32(sectiondata[sz:])
   214  			subsectiondata := sectiondata[sz+4 : subsectionsize]
   215  			sectiondata = sectiondata[subsectionsize:]
   216  
   217  			if subsectiontag != TagFile {
   218  				continue
   219  			}
   220  			attrList := elfAttributeList{data: subsectiondata}
   221  			for !attrList.done() {
   222  				attr := attrList.armAttr()
   223  				if attr.tag == TagABIVFPArgs && attr.ival == 1 {
   224  					found = true
   225  					ehdrFlags = 0x5000402	// has entry point, Version5 EABI, hard-float ABI
   226  				}
   227  			}
   228  			if attrList.err != nil {
   229  				return false, 0, fmt.Errorf("could not parse .ARM.attributes\n")
   230  			}
   231  		}
   232  	}
   233  	return found, ehdrFlags, nil
   234  }
   235  
   236  // Load loads the ELF file pn from f.
   237  // Symbols are installed into the loader, and a slice of the text symbols is returned.
   238  //
   239  // On ARM systems, Load will attempt to determine what ELF header flags to
   240  // emit by scanning the attributes in the ELF file being loaded. The
   241  // parameter initEhdrFlags contains the current header flags for the output
   242  // object, and the returned ehdrFlags contains what this Load function computes.
   243  // TODO: find a better place for this logic.
   244  func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, pkg string, length int64, pn string, initEhdrFlags uint32) (textp []loader.Sym, ehdrFlags uint32, err error) {
   245  	newSym := func(name string, version int) loader.Sym {
   246  		return l.CreateStaticSym(name)
   247  	}
   248  	lookup := l.LookupOrCreateCgoExport
   249  	errorf := func(str string, args ...interface{}) ([]loader.Sym, uint32, error) {
   250  		return nil, 0, fmt.Errorf("loadelf: %s: %v", pn, fmt.Sprintf(str, args...))
   251  	}
   252  
   253  	ehdrFlags = initEhdrFlags
   254  
   255  	base := f.Offset()
   256  
   257  	var hdrbuf [64]byte
   258  	if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
   259  		return errorf("malformed elf file: %v", err)
   260  	}
   261  
   262  	var e binary.ByteOrder
   263  	switch elf.Data(hdrbuf[elf.EI_DATA]) {
   264  	case elf.ELFDATA2LSB:
   265  		e = binary.LittleEndian
   266  
   267  	case elf.ELFDATA2MSB:
   268  		e = binary.BigEndian
   269  
   270  	default:
   271  		return errorf("malformed elf file, unknown header")
   272  	}
   273  
   274  	hdr := new(elf.Header32)
   275  	binary.Read(bytes.NewReader(hdrbuf[:]), e, hdr)
   276  
   277  	if string(hdr.Ident[:elf.EI_CLASS]) != elf.ELFMAG {
   278  		return errorf("malformed elf file, bad header")
   279  	}
   280  
   281  	// read header
   282  	elfobj := new(ElfObj)
   283  
   284  	elfobj.e = e
   285  	elfobj.f = f
   286  	elfobj.base = base
   287  	elfobj.length = length
   288  	elfobj.name = pn
   289  
   290  	is64 := 0
   291  	class := elf.Class(hdrbuf[elf.EI_CLASS])
   292  	if class == elf.ELFCLASS64 {
   293  		is64 = 1
   294  		hdr := new(elf.Header64)
   295  		binary.Read(bytes.NewReader(hdrbuf[:]), e, hdr)
   296  		elfobj.type_ = uint32(hdr.Type)
   297  		elfobj.machine = uint32(hdr.Machine)
   298  		elfobj.version = hdr.Version
   299  		elfobj.entry = hdr.Entry
   300  		elfobj.phoff = hdr.Phoff
   301  		elfobj.shoff = hdr.Shoff
   302  		elfobj.flags = hdr.Flags
   303  		elfobj.ehsize = uint32(hdr.Ehsize)
   304  		elfobj.phentsize = uint32(hdr.Phentsize)
   305  		elfobj.phnum = uint32(hdr.Phnum)
   306  		elfobj.shentsize = uint32(hdr.Shentsize)
   307  		elfobj.shnum = uint32(hdr.Shnum)
   308  		elfobj.shstrndx = uint32(hdr.Shstrndx)
   309  	} else {
   310  		elfobj.type_ = uint32(hdr.Type)
   311  		elfobj.machine = uint32(hdr.Machine)
   312  		elfobj.version = hdr.Version
   313  		elfobj.entry = uint64(hdr.Entry)
   314  		elfobj.phoff = uint64(hdr.Phoff)
   315  		elfobj.shoff = uint64(hdr.Shoff)
   316  		elfobj.flags = hdr.Flags
   317  		elfobj.ehsize = uint32(hdr.Ehsize)
   318  		elfobj.phentsize = uint32(hdr.Phentsize)
   319  		elfobj.phnum = uint32(hdr.Phnum)
   320  		elfobj.shentsize = uint32(hdr.Shentsize)
   321  		elfobj.shnum = uint32(hdr.Shnum)
   322  		elfobj.shstrndx = uint32(hdr.Shstrndx)
   323  	}
   324  
   325  	elfobj.is64 = is64
   326  
   327  	if v := uint32(hdrbuf[elf.EI_VERSION]); v != elfobj.version {
   328  		return errorf("malformed elf version: got %d, want %d", v, elfobj.version)
   329  	}
   330  
   331  	if elf.Type(elfobj.type_) != elf.ET_REL {
   332  		return errorf("elf but not elf relocatable object")
   333  	}
   334  
   335  	mach := elf.Machine(elfobj.machine)
   336  	switch arch.Family {
   337  	default:
   338  		return errorf("elf %s unimplemented", arch.Name)
   339  
   340  	case sys.MIPS:
   341  		if mach != elf.EM_MIPS || class != elf.ELFCLASS32 {
   342  			return errorf("elf object but not mips")
   343  		}
   344  
   345  	case sys.MIPS64:
   346  		if mach != elf.EM_MIPS || class != elf.ELFCLASS64 {
   347  			return errorf("elf object but not mips64")
   348  		}
   349  	case sys.Loong64:
   350  		if mach != elf.EM_LOONGARCH || class != elf.ELFCLASS64 {
   351  			return errorf("elf object but not loong64")
   352  		}
   353  
   354  	case sys.ARM:
   355  		if e != binary.LittleEndian || mach != elf.EM_ARM || class != elf.ELFCLASS32 {
   356  			return errorf("elf object but not arm")
   357  		}
   358  
   359  	case sys.AMD64:
   360  		if e != binary.LittleEndian || mach != elf.EM_X86_64 || class != elf.ELFCLASS64 {
   361  			return errorf("elf object but not amd64")
   362  		}
   363  
   364  	case sys.ARM64:
   365  		if e != binary.LittleEndian || mach != elf.EM_AARCH64 || class != elf.ELFCLASS64 {
   366  			return errorf("elf object but not arm64")
   367  		}
   368  
   369  	case sys.I386:
   370  		if e != binary.LittleEndian || mach != elf.EM_386 || class != elf.ELFCLASS32 {
   371  			return errorf("elf object but not 386")
   372  		}
   373  
   374  	case sys.PPC64:
   375  		if mach != elf.EM_PPC64 || class != elf.ELFCLASS64 {
   376  			return errorf("elf object but not ppc64")
   377  		}
   378  
   379  	case sys.RISCV64:
   380  		if mach != elf.EM_RISCV || class != elf.ELFCLASS64 {
   381  			return errorf("elf object but not riscv64")
   382  		}
   383  
   384  	case sys.S390X:
   385  		if mach != elf.EM_S390 || class != elf.ELFCLASS64 {
   386  			return errorf("elf object but not s390x")
   387  		}
   388  	}
   389  
   390  	// load section list into memory.
   391  	elfobj.sect = make([]ElfSect, elfobj.shnum)
   392  
   393  	elfobj.nsect = uint(elfobj.shnum)
   394  	for i := 0; uint(i) < elfobj.nsect; i++ {
   395  		f.MustSeek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0)
   396  		sect := &elfobj.sect[i]
   397  		if is64 != 0 {
   398  			var b elf.Section64
   399  			if err := binary.Read(f, e, &b); err != nil {
   400  				return errorf("malformed elf file: %v", err)
   401  			}
   402  
   403  			sect.nameoff = b.Name
   404  			sect.type_ = elf.SectionType(b.Type)
   405  			sect.flags = elf.SectionFlag(b.Flags)
   406  			sect.addr = b.Addr
   407  			sect.off = b.Off
   408  			sect.size = b.Size
   409  			sect.link = b.Link
   410  			sect.info = b.Info
   411  			sect.align = b.Addralign
   412  			sect.entsize = b.Entsize
   413  		} else {
   414  			var b elf.Section32
   415  
   416  			if err := binary.Read(f, e, &b); err != nil {
   417  				return errorf("malformed elf file: %v", err)
   418  			}
   419  			sect.nameoff = b.Name
   420  			sect.type_ = elf.SectionType(b.Type)
   421  			sect.flags = elf.SectionFlag(b.Flags)
   422  			sect.addr = uint64(b.Addr)
   423  			sect.off = uint64(b.Off)
   424  			sect.size = uint64(b.Size)
   425  			sect.link = b.Link
   426  			sect.info = b.Info
   427  			sect.align = uint64(b.Addralign)
   428  			sect.entsize = uint64(b.Entsize)
   429  		}
   430  	}
   431  
   432  	// read section string table and translate names
   433  	if elfobj.shstrndx >= uint32(elfobj.nsect) {
   434  		return errorf("malformed elf file: shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect)
   435  	}
   436  
   437  	sect := &elfobj.sect[elfobj.shstrndx]
   438  	if err := elfmap(elfobj, sect); err != nil {
   439  		return errorf("malformed elf file: %v", err)
   440  	}
   441  	for i := 0; uint(i) < elfobj.nsect; i++ {
   442  		if elfobj.sect[i].nameoff != 0 {
   443  			elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:])
   444  		}
   445  	}
   446  
   447  	// load string table for symbols into memory.
   448  	elfobj.symtab = section(elfobj, ".symtab")
   449  
   450  	if elfobj.symtab == nil {
   451  		// our work is done here - no symbols means nothing can refer to this file
   452  		return
   453  	}
   454  
   455  	if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) {
   456  		return errorf("elf object has symbol table with invalid string table link")
   457  	}
   458  
   459  	elfobj.symstr = &elfobj.sect[elfobj.symtab.link]
   460  	if is64 != 0 {
   461  		elfobj.nsymtab = int(elfobj.symtab.size / elf.Sym64Size)
   462  	} else {
   463  		elfobj.nsymtab = int(elfobj.symtab.size / elf.Sym32Size)
   464  	}
   465  
   466  	if err := elfmap(elfobj, elfobj.symtab); err != nil {
   467  		return errorf("malformed elf file: %v", err)
   468  	}
   469  	if err := elfmap(elfobj, elfobj.symstr); err != nil {
   470  		return errorf("malformed elf file: %v", err)
   471  	}
   472  
   473  	// load text and data segments into memory.
   474  	// they are not as small as the section lists, but we'll need
   475  	// the memory anyway for the symbol images, so we might
   476  	// as well use one large chunk.
   477  
   478  	// create symbols for elfmapped sections
   479  	sectsymNames := make(map[string]bool)
   480  	counter := 0
   481  	for i := 0; uint(i) < elfobj.nsect; i++ {
   482  		sect = &elfobj.sect[i]
   483  		if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" {
   484  			if err := elfmap(elfobj, sect); err != nil {
   485  				return errorf("%s: malformed elf file: %v", pn, err)
   486  			}
   487  			// We assume the soft-float ABI unless we see a tag indicating otherwise.
   488  			if initEhdrFlags == 0x5000002 {
   489  				ehdrFlags = 0x5000202
   490  			} else {
   491  				ehdrFlags = initEhdrFlags
   492  			}
   493  			found, newEhdrFlags, err := parseArmAttributes(e, sect.base[:sect.size])
   494  			if err != nil {
   495  				// TODO(dfc) should this return an error?
   496  				log.Printf("%s: %v", pn, err)
   497  			}
   498  			if found {
   499  				ehdrFlags = newEhdrFlags
   500  			}
   501  		}
   502  		if (sect.type_ != elf.SHT_PROGBITS && sect.type_ != elf.SHT_NOBITS) || sect.flags&elf.SHF_ALLOC == 0 {
   503  			continue
   504  		}
   505  		if sect.type_ != elf.SHT_NOBITS {
   506  			if err := elfmap(elfobj, sect); err != nil {
   507  				return errorf("%s: malformed elf file: %v", pn, err)
   508  			}
   509  		}
   510  
   511  		name := fmt.Sprintf("%s(%s)", pkg, sect.name)
   512  		for sectsymNames[name] {
   513  			counter++
   514  			name = fmt.Sprintf("%s(%s%d)", pkg, sect.name, counter)
   515  		}
   516  		sectsymNames[name] = true
   517  
   518  		sb := l.MakeSymbolUpdater(lookup(name, localSymVersion))
   519  
   520  		switch sect.flags & (elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_EXECINSTR) {
   521  		default:
   522  			return errorf("%s: unexpected flags for ELF section %s", pn, sect.name)
   523  
   524  		case elf.SHF_ALLOC:
   525  			sb.SetType(sym.SRODATA)
   526  
   527  		case elf.SHF_ALLOC + elf.SHF_WRITE:
   528  			if sect.type_ == elf.SHT_NOBITS {
   529  				sb.SetType(sym.SNOPTRBSS)
   530  			} else {
   531  				sb.SetType(sym.SNOPTRDATA)
   532  			}
   533  
   534  		case elf.SHF_ALLOC + elf.SHF_EXECINSTR:
   535  			sb.SetType(sym.STEXT)
   536  		}
   537  
   538  		if sect.name == ".got" || sect.name == ".toc" {
   539  			sb.SetType(sym.SELFGOT)
   540  		}
   541  		if sect.type_ == elf.SHT_PROGBITS {
   542  			sb.SetData(sect.base[:sect.size])
   543  			sb.SetExternal(true)
   544  		}
   545  
   546  		sb.SetSize(int64(sect.size))
   547  		sb.SetAlign(int32(sect.align))
   548  		sb.SetReadOnly(sect.readOnlyMem)
   549  
   550  		sect.sym = sb.Sym()
   551  	}
   552  
   553  	// enter sub-symbols into symbol table.
   554  	// symbol 0 is the null symbol.
   555  	symbols := make([]loader.Sym, elfobj.nsymtab)
   556  
   557  	for i := 1; i < elfobj.nsymtab; i++ {
   558  		var elfsym ElfSym
   559  		if err := readelfsym(newSym, lookup, l, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
   560  			return errorf("%s: malformed elf file: %v", pn, err)
   561  		}
   562  		symbols[i] = elfsym.sym
   563  		if elfsym.type_ != elf.STT_FUNC && elfsym.type_ != elf.STT_OBJECT && elfsym.type_ != elf.STT_NOTYPE && elfsym.type_ != elf.STT_COMMON {
   564  			continue
   565  		}
   566  		if elfsym.shndx == elf.SHN_COMMON || elfsym.type_ == elf.STT_COMMON {
   567  			sb := l.MakeSymbolUpdater(elfsym.sym)
   568  			if uint64(sb.Size()) < elfsym.size {
   569  				sb.SetSize(int64(elfsym.size))
   570  			}
   571  			if sb.Type() == 0 || sb.Type() == sym.SXREF {
   572  				sb.SetType(sym.SNOPTRBSS)
   573  			}
   574  			continue
   575  		}
   576  
   577  		if uint(elfsym.shndx) >= elfobj.nsect || elfsym.shndx == 0 {
   578  			continue
   579  		}
   580  
   581  		// even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
   582  		if elfsym.sym == 0 {
   583  			continue
   584  		}
   585  		sect = &elfobj.sect[elfsym.shndx]
   586  		if sect.sym == 0 {
   587  			if elfsym.type_ == 0 {
   588  				if strings.HasPrefix(sect.name, ".debug_") && elfsym.name == "" {
   589  					// clang on arm and riscv64.
   590  					// This reportedly happens with clang 3.7 on ARM.
   591  					// See issue 13139.
   592  					continue
   593  				}
   594  				if strings.HasPrefix(elfsym.name, ".Ldebug_") || elfsym.name == ".L0 " {
   595  					// gcc on riscv64.
   596  					continue
   597  				}
   598  				if elfsym.name == ".Lline_table_start0" {
   599  					// clang on riscv64.
   600  					continue
   601  				}
   602  
   603  				if strings.HasPrefix(elfsym.name, "$d") && sect.name == ".debug_frame" {
   604  					// "$d" is a marker, not a real symbol.
   605  					// This happens with gcc on ARM64.
   606  					// See https://sourceware.org/bugzilla/show_bug.cgi?id=21809
   607  					continue
   608  				}
   609  			}
   610  
   611  			if strings.HasPrefix(elfsym.name, ".Linfo_string") {
   612  				// clang does this
   613  				continue
   614  			}
   615  
   616  			if strings.HasPrefix(elfsym.name, ".LASF") || strings.HasPrefix(elfsym.name, ".LLRL") || strings.HasPrefix(elfsym.name, ".LLST") {
   617  				// gcc on s390x and riscv64 does this.
   618  				continue
   619  			}
   620  
   621  			return errorf("%v: sym#%d (%q): ignoring symbol in section %d (%q) (type %d)", elfsym.sym, i, elfsym.name, elfsym.shndx, sect.name, elfsym.type_)
   622  		}
   623  
   624  		s := elfsym.sym
   625  		if l.OuterSym(s) != 0 {
   626  			if l.AttrDuplicateOK(s) {
   627  				continue
   628  			}
   629  			return errorf("duplicate symbol reference: %s in both %s and %s",
   630  				l.SymName(s), l.SymName(l.OuterSym(s)), l.SymName(sect.sym))
   631  		}
   632  
   633  		sectsb := l.MakeSymbolUpdater(sect.sym)
   634  		sb := l.MakeSymbolUpdater(s)
   635  
   636  		sb.SetType(sectsb.Type())
   637  		sectsb.AddInteriorSym(s)
   638  		if !l.AttrCgoExportDynamic(s) {
   639  			sb.SetDynimplib("")	// satisfy dynimport
   640  		}
   641  		sb.SetValue(int64(elfsym.value))
   642  		sb.SetSize(int64(elfsym.size))
   643  		if sectsb.Type() == sym.STEXT {
   644  			if l.AttrExternal(s) && !l.AttrDuplicateOK(s) {
   645  				return errorf("%s: duplicate symbol definition", sb.Name())
   646  			}
   647  			l.SetAttrExternal(s, true)
   648  		}
   649  
   650  		if elf.Machine(elfobj.machine) == elf.EM_PPC64 {
   651  			flag := int(elfsym.other) >> 5
   652  			switch flag {
   653  			case 0:
   654  				// No local entry. R2 is preserved.
   655  			case 1:
   656  				// This is kind of a hack, but pass the hint about this symbol's
   657  				// usage of R2 (R2 is a caller-save register not a TOC pointer, and
   658  				// this function does not have a distinct local entry) by setting
   659  				// its SymLocalentry to 1.
   660  				l.SetSymLocalentry(s, 1)
   661  			case 7:
   662  				return errorf("%s: invalid sym.other 0x%x", sb.Name(), elfsym.other)
   663  			default:
   664  				// Convert the word sized offset into bytes.
   665  				l.SetSymLocalentry(s, 4<<uint(flag-2))
   666  			}
   667  		}
   668  	}
   669  
   670  	// Sort outer lists by address, adding to textp.
   671  	// This keeps textp in increasing address order.
   672  	for i := uint(0); i < elfobj.nsect; i++ {
   673  		s := elfobj.sect[i].sym
   674  		if s == 0 {
   675  			continue
   676  		}
   677  		sb := l.MakeSymbolUpdater(s)
   678  		if l.SubSym(s) != 0 {
   679  			sb.SortSub()
   680  		}
   681  		if sb.Type() == sym.STEXT {
   682  			if l.AttrOnList(s) {
   683  				return errorf("symbol %s listed multiple times",
   684  					l.SymName(s))
   685  			}
   686  			l.SetAttrOnList(s, true)
   687  			textp = append(textp, s)
   688  			for ss := l.SubSym(s); ss != 0; ss = l.SubSym(ss) {
   689  				if l.AttrOnList(ss) {
   690  					return errorf("symbol %s listed multiple times",
   691  						l.SymName(ss))
   692  				}
   693  				l.SetAttrOnList(ss, true)
   694  				textp = append(textp, ss)
   695  			}
   696  		}
   697  	}
   698  
   699  	// load relocations
   700  	for i := uint(0); i < elfobj.nsect; i++ {
   701  		rsect := &elfobj.sect[i]
   702  		if rsect.type_ != elf.SHT_RELA && rsect.type_ != elf.SHT_REL {
   703  			continue
   704  		}
   705  		if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
   706  			continue
   707  		}
   708  		sect = &elfobj.sect[rsect.info]
   709  		if err := elfmap(elfobj, rsect); err != nil {
   710  			return errorf("malformed elf file: %v", err)
   711  		}
   712  		rela := 0
   713  		if rsect.type_ == elf.SHT_RELA {
   714  			rela = 1
   715  		}
   716  		n := int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
   717  		p := rsect.base
   718  		sb := l.MakeSymbolUpdater(sect.sym)
   719  		for j := 0; j < n; j++ {
   720  			var add uint64
   721  			var symIdx int
   722  			var relocType uint64
   723  			var rOff int32
   724  			var rAdd int64
   725  			var rSym loader.Sym
   726  
   727  			if is64 != 0 {
   728  				// 64-bit rel/rela
   729  				rOff = int32(e.Uint64(p))
   730  
   731  				p = p[8:]
   732  				switch arch.Family {
   733  				case sys.MIPS64:
   734  					// https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
   735  					// The doc shows it's different with general Linux ELF
   736  					symIdx = int(e.Uint32(p))
   737  					relocType = uint64(p[7])
   738  				default:
   739  					info := e.Uint64(p)
   740  					relocType = info & 0xffffffff
   741  					symIdx = int(info >> 32)
   742  				}
   743  				p = p[8:]
   744  				if rela != 0 {
   745  					add = e.Uint64(p)
   746  					p = p[8:]
   747  				}
   748  			} else {
   749  				// 32-bit rel/rela
   750  				rOff = int32(e.Uint32(p))
   751  
   752  				p = p[4:]
   753  				info := e.Uint32(p)
   754  				relocType = uint64(info & 0xff)
   755  				symIdx = int(info >> 8)
   756  				p = p[4:]
   757  				if rela != 0 {
   758  					add = uint64(e.Uint32(p))
   759  					p = p[4:]
   760  				}
   761  			}
   762  
   763  			if relocType == 0 {	// skip R_*_NONE relocation
   764  				j--
   765  				n--
   766  				continue
   767  			}
   768  
   769  			if symIdx == 0 {	// absolute relocation, don't bother reading the null symbol
   770  				rSym = 0
   771  			} else {
   772  				var elfsym ElfSym
   773  				if err := readelfsym(newSym, lookup, l, arch, elfobj, int(symIdx), &elfsym, 0, 0); err != nil {
   774  					return errorf("malformed elf file: %v", err)
   775  				}
   776  				elfsym.sym = symbols[symIdx]
   777  				if elfsym.sym == 0 {
   778  					return errorf("malformed elf file: %s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", l.SymName(sect.sym), j, int(symIdx), elfsym.name, elfsym.shndx, elfsym.type_)
   779  				}
   780  
   781  				rSym = elfsym.sym
   782  			}
   783  
   784  			rType := objabi.ElfRelocOffset + objabi.RelocType(relocType)
   785  			rSize, addendSize, err := relSize(arch, pn, uint32(relocType))
   786  			if err != nil {
   787  				return nil, 0, err
   788  			}
   789  			if rela != 0 {
   790  				rAdd = int64(add)
   791  			} else {
   792  				// load addend from image
   793  				if rSize == 4 {
   794  					rAdd = int64(e.Uint32(sect.base[rOff:]))
   795  				} else if rSize == 8 {
   796  					rAdd = int64(e.Uint64(sect.base[rOff:]))
   797  				} else {
   798  					return errorf("invalid rela size %d", rSize)
   799  				}
   800  			}
   801  
   802  			if addendSize == 2 {
   803  				rAdd = int64(int16(rAdd))
   804  			}
   805  			if addendSize == 4 {
   806  				rAdd = int64(int32(rAdd))
   807  			}
   808  
   809  			r, _ := sb.AddRel(rType)
   810  			r.SetOff(rOff)
   811  			r.SetSiz(rSize)
   812  			r.SetSym(rSym)
   813  			r.SetAdd(rAdd)
   814  		}
   815  
   816  		sb.SortRelocs()	// just in case
   817  	}
   818  
   819  	return textp, ehdrFlags, nil
   820  }
   821  
   822  func section(elfobj *ElfObj, name string) *ElfSect {
   823  	for i := 0; uint(i) < elfobj.nsect; i++ {
   824  		if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
   825  			return &elfobj.sect[i]
   826  		}
   827  	}
   828  	return nil
   829  }
   830  
   831  func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
   832  	if sect.base != nil {
   833  		return nil
   834  	}
   835  
   836  	if sect.off+sect.size > uint64(elfobj.length) {
   837  		err = fmt.Errorf("elf section past end of file")
   838  		return err
   839  	}
   840  
   841  	elfobj.f.MustSeek(int64(uint64(elfobj.base)+sect.off), 0)
   842  	sect.base, sect.readOnlyMem, err = elfobj.f.Slice(uint64(sect.size))
   843  	if err != nil {
   844  		return fmt.Errorf("short read: %v", err)
   845  	}
   846  
   847  	return nil
   848  }
   849  
   850  func readelfsym(newSym, lookup func(string, int) loader.Sym, l *loader.Loader, arch *sys.Arch, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
   851  	if i >= elfobj.nsymtab || i < 0 {
   852  		err = fmt.Errorf("invalid elf symbol index")
   853  		return err
   854  	}
   855  
   856  	if i == 0 {
   857  		return fmt.Errorf("readym: read null symbol!")
   858  	}
   859  
   860  	if elfobj.is64 != 0 {
   861  		b := new(elf.Sym64)
   862  		binary.Read(bytes.NewReader(elfobj.symtab.base[i*elf.Sym64Size:(i+1)*elf.Sym64Size]), elfobj.e, b)
   863  		elfsym.name = cstring(elfobj.symstr.base[b.Name:])
   864  		elfsym.value = b.Value
   865  		elfsym.size = b.Size
   866  		elfsym.shndx = elf.SectionIndex(b.Shndx)
   867  		elfsym.bind = elf.ST_BIND(b.Info)
   868  		elfsym.type_ = elf.ST_TYPE(b.Info)
   869  		elfsym.other = b.Other
   870  	} else {
   871  		b := new(elf.Sym32)
   872  		binary.Read(bytes.NewReader(elfobj.symtab.base[i*elf.Sym32Size:(i+1)*elf.Sym32Size]), elfobj.e, b)
   873  		elfsym.name = cstring(elfobj.symstr.base[b.Name:])
   874  		elfsym.value = uint64(b.Value)
   875  		elfsym.size = uint64(b.Size)
   876  		elfsym.shndx = elf.SectionIndex(b.Shndx)
   877  		elfsym.bind = elf.ST_BIND(b.Info)
   878  		elfsym.type_ = elf.ST_TYPE(b.Info)
   879  		elfsym.other = b.Other
   880  	}
   881  
   882  	var s loader.Sym
   883  
   884  	if elfsym.name == "_GLOBAL_OFFSET_TABLE_" {
   885  		elfsym.name = ".got"
   886  	}
   887  	if elfsym.name == ".TOC." {
   888  		// Magic symbol on ppc64.  Will be set to this object
   889  		// file's .got+0x8000.
   890  		elfsym.bind = elf.STB_LOCAL
   891  	}
   892  
   893  	switch elfsym.type_ {
   894  	case elf.STT_SECTION:
   895  		s = elfobj.sect[elfsym.shndx].sym
   896  
   897  	case elf.STT_OBJECT, elf.STT_FUNC, elf.STT_NOTYPE, elf.STT_COMMON:
   898  		switch elfsym.bind {
   899  		case elf.STB_GLOBAL:
   900  			if needSym != 0 {
   901  				s = lookup(elfsym.name, 0)
   902  
   903  				// for global scoped hidden symbols we should insert it into
   904  				// symbol hash table, but mark them as hidden.
   905  				// __i686.get_pc_thunk.bx is allowed to be duplicated, to
   906  				// workaround that we set dupok.
   907  				// TODO(minux): correctly handle __i686.get_pc_thunk.bx without
   908  				// set dupok generally. See https://golang.org/cl/5823055
   909  				// comment #5 for details.
   910  				if s != 0 && elfsym.other == 2 {
   911  					if !l.IsExternal(s) {
   912  						l.MakeSymbolUpdater(s)
   913  					}
   914  					l.SetAttrDuplicateOK(s, true)
   915  					l.SetAttrVisibilityHidden(s, true)
   916  				}
   917  			}
   918  
   919  		case elf.STB_LOCAL:
   920  			if (arch.Family == sys.ARM || arch.Family == sys.ARM64) && (strings.HasPrefix(elfsym.name, "$a") || strings.HasPrefix(elfsym.name, "$d") || strings.HasPrefix(elfsym.name, "$x")) {
   921  				// binutils for arm and arm64 generate these mapping
   922  				// symbols, ignore these
   923  				break
   924  			}
   925  
   926  			if elfsym.name == ".TOC." {
   927  				// We need to be able to look this up,
   928  				// so put it in the hash table.
   929  				if needSym != 0 {
   930  					s = lookup(elfsym.name, localSymVersion)
   931  					l.SetAttrVisibilityHidden(s, true)
   932  				}
   933  				break
   934  			}
   935  
   936  			if needSym != 0 {
   937  				// local names and hidden global names are unique
   938  				// and should only be referenced by their index, not name, so we
   939  				// don't bother to add them into the hash table
   940  				// FIXME: pass empty string here for name? This would
   941  				// reduce mem use, but also (possibly) make it harder
   942  				// to debug problems.
   943  				s = newSym(elfsym.name, localSymVersion)
   944  				l.SetAttrVisibilityHidden(s, true)
   945  			}
   946  
   947  		case elf.STB_WEAK:
   948  			if needSym != 0 {
   949  				s = lookup(elfsym.name, 0)
   950  				if elfsym.other == 2 {
   951  					l.SetAttrVisibilityHidden(s, true)
   952  				}
   953  
   954  				// Allow weak symbols to be duplicated when already defined.
   955  				if l.OuterSym(s) != 0 {
   956  					l.SetAttrDuplicateOK(s, true)
   957  				}
   958  			}
   959  
   960  		default:
   961  			err = fmt.Errorf("%s: invalid symbol binding %d", elfsym.name, elfsym.bind)
   962  			return err
   963  		}
   964  	}
   965  
   966  	if s != 0 && l.SymType(s) == 0 && elfsym.type_ != elf.STT_SECTION {
   967  		sb := l.MakeSymbolUpdater(s)
   968  		sb.SetType(sym.SXREF)
   969  	}
   970  	elfsym.sym = s
   971  
   972  	return nil
   973  }
   974  
   975  // Return the size of the relocated field, and the size of the addend as the first
   976  // and second values. Note, the addend may be larger than the relocation field in
   977  // some cases when a relocated value is split across multiple relocations.
   978  func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) {
   979  	// TODO(mdempsky): Replace this with a struct-valued switch statement
   980  	// once golang.org/issue/15164 is fixed or found to not impair cmd/link
   981  	// performance.
   982  
   983  	const (
   984  		AMD64	= uint32(sys.AMD64)
   985  		ARM	= uint32(sys.ARM)
   986  		ARM64	= uint32(sys.ARM64)
   987  		I386	= uint32(sys.I386)
   988  		LOONG64	= uint32(sys.Loong64)
   989  		MIPS	= uint32(sys.MIPS)
   990  		MIPS64	= uint32(sys.MIPS64)
   991  		PPC64	= uint32(sys.PPC64)
   992  		RISCV64	= uint32(sys.RISCV64)
   993  		S390X	= uint32(sys.S390X)
   994  	)
   995  
   996  	switch uint32(arch.Family) | elftype<<16 {
   997  	default:
   998  		return 0, 0, fmt.Errorf("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
   999  
  1000  	case MIPS | uint32(elf.R_MIPS_HI16)<<16,
  1001  		MIPS | uint32(elf.R_MIPS_LO16)<<16,
  1002  		MIPS | uint32(elf.R_MIPS_GOT16)<<16,
  1003  		MIPS | uint32(elf.R_MIPS_GOT_HI16)<<16,
  1004  		MIPS | uint32(elf.R_MIPS_GOT_LO16)<<16,
  1005  		MIPS | uint32(elf.R_MIPS_GPREL16)<<16,
  1006  		MIPS | uint32(elf.R_MIPS_GOT_PAGE)<<16,
  1007  		MIPS | uint32(elf.R_MIPS_JALR)<<16,
  1008  		MIPS | uint32(elf.R_MIPS_GOT_OFST)<<16,
  1009  		MIPS64 | uint32(elf.R_MIPS_HI16)<<16,
  1010  		MIPS64 | uint32(elf.R_MIPS_LO16)<<16,
  1011  		MIPS64 | uint32(elf.R_MIPS_GOT16)<<16,
  1012  		MIPS64 | uint32(elf.R_MIPS_GOT_HI16)<<16,
  1013  		MIPS64 | uint32(elf.R_MIPS_GOT_LO16)<<16,
  1014  		MIPS64 | uint32(elf.R_MIPS_GPREL16)<<16,
  1015  		MIPS64 | uint32(elf.R_MIPS_GOT_PAGE)<<16,
  1016  		MIPS64 | uint32(elf.R_MIPS_JALR)<<16,
  1017  		MIPS64 | uint32(elf.R_MIPS_GOT_OFST)<<16,
  1018  		MIPS64 | uint32(elf.R_MIPS_CALL16)<<16,
  1019  		MIPS64 | uint32(elf.R_MIPS_GPREL32)<<16,
  1020  		MIPS64 | uint32(elf.R_MIPS_64)<<16,
  1021  		MIPS64 | uint32(elf.R_MIPS_GOT_DISP)<<16,
  1022  		MIPS64 | uint32(elf.R_MIPS_PC32)<<16:
  1023  		return 4, 4, nil
  1024  
  1025  	case LOONG64 | uint32(elf.R_LARCH_ADD8)<<16,
  1026  		LOONG64 | uint32(elf.R_LARCH_SUB8)<<16:
  1027  		return 1, 1, nil
  1028  
  1029  	case LOONG64 | uint32(elf.R_LARCH_ADD16)<<16,
  1030  		LOONG64 | uint32(elf.R_LARCH_SUB16)<<16:
  1031  		return 2, 2, nil
  1032  
  1033  	case LOONG64 | uint32(elf.R_LARCH_SOP_PUSH_PCREL)<<16,
  1034  		LOONG64 | uint32(elf.R_LARCH_SOP_PUSH_GPREL)<<16,
  1035  		LOONG64 | uint32(elf.R_LARCH_SOP_PUSH_ABSOLUTE)<<16,
  1036  		LOONG64 | uint32(elf.R_LARCH_MARK_LA)<<16,
  1037  		LOONG64 | uint32(elf.R_LARCH_SOP_POP_32_S_0_10_10_16_S2)<<16,
  1038  		LOONG64 | uint32(elf.R_LARCH_MARK_PCREL)<<16,
  1039  		LOONG64 | uint32(elf.R_LARCH_ADD24)<<16,
  1040  		LOONG64 | uint32(elf.R_LARCH_ADD32)<<16,
  1041  		LOONG64 | uint32(elf.R_LARCH_SUB24)<<16,
  1042  		LOONG64 | uint32(elf.R_LARCH_SUB32)<<16,
  1043  		LOONG64 | uint32(elf.R_LARCH_B26)<<16,
  1044  		LOONG64 | uint32(elf.R_LARCH_32_PCREL)<<16:
  1045  		return 4, 4, nil
  1046  
  1047  	case LOONG64 | uint32(elf.R_LARCH_64)<<16,
  1048  		LOONG64 | uint32(elf.R_LARCH_ADD64)<<16,
  1049  		LOONG64 | uint32(elf.R_LARCH_SUB64)<<16,
  1050  		LOONG64 | uint32(elf.R_LARCH_64_PCREL)<<16:
  1051  		return 8, 8, nil
  1052  
  1053  	case S390X | uint32(elf.R_390_8)<<16:
  1054  		return 1, 1, nil
  1055  
  1056  	case PPC64 | uint32(elf.R_PPC64_TOC16)<<16,
  1057  		S390X | uint32(elf.R_390_16)<<16,
  1058  		S390X | uint32(elf.R_390_GOT16)<<16,
  1059  		S390X | uint32(elf.R_390_PC16)<<16,
  1060  		S390X | uint32(elf.R_390_PC16DBL)<<16,
  1061  		S390X | uint32(elf.R_390_PLT16DBL)<<16:
  1062  		return 2, 2, nil
  1063  
  1064  	case ARM | uint32(elf.R_ARM_ABS32)<<16,
  1065  		ARM | uint32(elf.R_ARM_GOT32)<<16,
  1066  		ARM | uint32(elf.R_ARM_PLT32)<<16,
  1067  		ARM | uint32(elf.R_ARM_GOTOFF)<<16,
  1068  		ARM | uint32(elf.R_ARM_GOTPC)<<16,
  1069  		ARM | uint32(elf.R_ARM_THM_PC22)<<16,
  1070  		ARM | uint32(elf.R_ARM_REL32)<<16,
  1071  		ARM | uint32(elf.R_ARM_CALL)<<16,
  1072  		ARM | uint32(elf.R_ARM_V4BX)<<16,
  1073  		ARM | uint32(elf.R_ARM_GOT_PREL)<<16,
  1074  		ARM | uint32(elf.R_ARM_PC24)<<16,
  1075  		ARM | uint32(elf.R_ARM_JUMP24)<<16,
  1076  		ARM64 | uint32(elf.R_AARCH64_CALL26)<<16,
  1077  		ARM64 | uint32(elf.R_AARCH64_ADR_GOT_PAGE)<<16,
  1078  		ARM64 | uint32(elf.R_AARCH64_LD64_GOT_LO12_NC)<<16,
  1079  		ARM64 | uint32(elf.R_AARCH64_ADR_PREL_PG_HI21)<<16,
  1080  		ARM64 | uint32(elf.R_AARCH64_ADD_ABS_LO12_NC)<<16,
  1081  		ARM64 | uint32(elf.R_AARCH64_LDST8_ABS_LO12_NC)<<16,
  1082  		ARM64 | uint32(elf.R_AARCH64_LDST16_ABS_LO12_NC)<<16,
  1083  		ARM64 | uint32(elf.R_AARCH64_LDST32_ABS_LO12_NC)<<16,
  1084  		ARM64 | uint32(elf.R_AARCH64_LDST64_ABS_LO12_NC)<<16,
  1085  		ARM64 | uint32(elf.R_AARCH64_LDST128_ABS_LO12_NC)<<16,
  1086  		ARM64 | uint32(elf.R_AARCH64_PREL32)<<16,
  1087  		ARM64 | uint32(elf.R_AARCH64_JUMP26)<<16,
  1088  		AMD64 | uint32(elf.R_X86_64_PC32)<<16,
  1089  		AMD64 | uint32(elf.R_X86_64_PLT32)<<16,
  1090  		AMD64 | uint32(elf.R_X86_64_GOTPCREL)<<16,
  1091  		AMD64 | uint32(elf.R_X86_64_GOTPCRELX)<<16,
  1092  		AMD64 | uint32(elf.R_X86_64_REX_GOTPCRELX)<<16,
  1093  		I386 | uint32(elf.R_386_32)<<16,
  1094  		I386 | uint32(elf.R_386_PC32)<<16,
  1095  		I386 | uint32(elf.R_386_GOT32)<<16,
  1096  		I386 | uint32(elf.R_386_PLT32)<<16,
  1097  		I386 | uint32(elf.R_386_GOTOFF)<<16,
  1098  		I386 | uint32(elf.R_386_GOTPC)<<16,
  1099  		I386 | uint32(elf.R_386_GOT32X)<<16,
  1100  		PPC64 | uint32(elf.R_PPC64_REL24)<<16,
  1101  		PPC64 | uint32(elf.R_PPC64_REL24_NOTOC)<<16,
  1102  		PPC64 | uint32(elf.R_PPC64_REL24_P9NOTOC)<<16,
  1103  		PPC64 | uint32(elf.R_PPC_REL32)<<16,
  1104  		S390X | uint32(elf.R_390_32)<<16,
  1105  		S390X | uint32(elf.R_390_PC32)<<16,
  1106  		S390X | uint32(elf.R_390_GOT32)<<16,
  1107  		S390X | uint32(elf.R_390_PLT32)<<16,
  1108  		S390X | uint32(elf.R_390_PC32DBL)<<16,
  1109  		S390X | uint32(elf.R_390_PLT32DBL)<<16,
  1110  		S390X | uint32(elf.R_390_GOTPCDBL)<<16,
  1111  		S390X | uint32(elf.R_390_GOTENT)<<16:
  1112  		return 4, 4, nil
  1113  
  1114  	case AMD64 | uint32(elf.R_X86_64_64)<<16,
  1115  		AMD64 | uint32(elf.R_X86_64_PC64)<<16,
  1116  		ARM64 | uint32(elf.R_AARCH64_ABS64)<<16,
  1117  		ARM64 | uint32(elf.R_AARCH64_PREL64)<<16,
  1118  		PPC64 | uint32(elf.R_PPC64_ADDR64)<<16,
  1119  		PPC64 | uint32(elf.R_PPC64_PCREL34)<<16,
  1120  		PPC64 | uint32(elf.R_PPC64_GOT_PCREL34)<<16,
  1121  		PPC64 | uint32(elf.R_PPC64_PLT_PCREL34_NOTOC)<<16,
  1122  		S390X | uint32(elf.R_390_GLOB_DAT)<<16,
  1123  		S390X | uint32(elf.R_390_RELATIVE)<<16,
  1124  		S390X | uint32(elf.R_390_GOTOFF)<<16,
  1125  		S390X | uint32(elf.R_390_GOTPC)<<16,
  1126  		S390X | uint32(elf.R_390_64)<<16,
  1127  		S390X | uint32(elf.R_390_PC64)<<16,
  1128  		S390X | uint32(elf.R_390_GOT64)<<16,
  1129  		S390X | uint32(elf.R_390_PLT64)<<16:
  1130  		return 8, 8, nil
  1131  
  1132  	case RISCV64 | uint32(elf.R_RISCV_SET6)<<16,
  1133  		RISCV64 | uint32(elf.R_RISCV_SUB6)<<16,
  1134  		RISCV64 | uint32(elf.R_RISCV_SET8)<<16,
  1135  		RISCV64 | uint32(elf.R_RISCV_SUB8)<<16:
  1136  		return 1, 1, nil
  1137  
  1138  	case RISCV64 | uint32(elf.R_RISCV_RVC_BRANCH)<<16,
  1139  		RISCV64 | uint32(elf.R_RISCV_RVC_JUMP)<<16,
  1140  		RISCV64 | uint32(elf.R_RISCV_SET16)<<16,
  1141  		RISCV64 | uint32(elf.R_RISCV_SUB16)<<16:
  1142  		return 2, 2, nil
  1143  
  1144  	case RISCV64 | uint32(elf.R_RISCV_32)<<16,
  1145  		RISCV64 | uint32(elf.R_RISCV_BRANCH)<<16,
  1146  		RISCV64 | uint32(elf.R_RISCV_HI20)<<16,
  1147  		RISCV64 | uint32(elf.R_RISCV_LO12_I)<<16,
  1148  		RISCV64 | uint32(elf.R_RISCV_LO12_S)<<16,
  1149  		RISCV64 | uint32(elf.R_RISCV_GOT_HI20)<<16,
  1150  		RISCV64 | uint32(elf.R_RISCV_PCREL_HI20)<<16,
  1151  		RISCV64 | uint32(elf.R_RISCV_PCREL_LO12_I)<<16,
  1152  		RISCV64 | uint32(elf.R_RISCV_PCREL_LO12_S)<<16,
  1153  		RISCV64 | uint32(elf.R_RISCV_ADD32)<<16,
  1154  		RISCV64 | uint32(elf.R_RISCV_SET32)<<16,
  1155  		RISCV64 | uint32(elf.R_RISCV_SUB32)<<16,
  1156  		RISCV64 | uint32(elf.R_RISCV_32_PCREL)<<16,
  1157  		RISCV64 | uint32(elf.R_RISCV_RELAX)<<16:
  1158  		return 4, 4, nil
  1159  
  1160  	case RISCV64 | uint32(elf.R_RISCV_64)<<16,
  1161  		RISCV64 | uint32(elf.R_RISCV_CALL)<<16,
  1162  		RISCV64 | uint32(elf.R_RISCV_CALL_PLT)<<16:
  1163  		return 8, 8, nil
  1164  
  1165  	case PPC64 | uint32(elf.R_PPC64_TOC16_LO)<<16,
  1166  		PPC64 | uint32(elf.R_PPC64_TOC16_HI)<<16,
  1167  		PPC64 | uint32(elf.R_PPC64_TOC16_HA)<<16,
  1168  		PPC64 | uint32(elf.R_PPC64_TOC16_DS)<<16,
  1169  		PPC64 | uint32(elf.R_PPC64_TOC16_LO_DS)<<16,
  1170  		PPC64 | uint32(elf.R_PPC64_REL16_LO)<<16,
  1171  		PPC64 | uint32(elf.R_PPC64_REL16_HI)<<16,
  1172  		PPC64 | uint32(elf.R_PPC64_REL16_HA)<<16,
  1173  		PPC64 | uint32(elf.R_PPC64_PLT16_HA)<<16,
  1174  		PPC64 | uint32(elf.R_PPC64_PLT16_LO_DS)<<16:
  1175  		return 2, 4, nil
  1176  
  1177  	// PPC64 inline PLT sequence hint relocations (-fno-plt)
  1178  	// These are informational annotations to assist linker optimizations.
  1179  	case PPC64 | uint32(elf.R_PPC64_PLTSEQ)<<16,
  1180  		PPC64 | uint32(elf.R_PPC64_PLTCALL)<<16,
  1181  		PPC64 | uint32(elf.R_PPC64_PLTCALL_NOTOC)<<16,
  1182  		PPC64 | uint32(elf.R_PPC64_PLTSEQ_NOTOC)<<16:
  1183  		return 0, 0, nil
  1184  
  1185  	}
  1186  }
  1187  
  1188  func cstring(x []byte) string {
  1189  	i := bytes.IndexByte(x, '\x00')
  1190  	if i >= 0 {
  1191  		x = x[:i]
  1192  	}
  1193  	return string(x)
  1194  }