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