Black Lives Matter. Support the Equal Justice Initiative.

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

Documentation: cmd/link/internal/loadelf

     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  	"cmd/internal/bio"
    11  	"cmd/internal/objabi"
    12  	"cmd/internal/sys"
    13  	"cmd/link/internal/loader"
    14  	"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  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  
    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 := func(name string, version int) loader.Sym {
   249  		return l.LookupOrCreateSym(name, version)
   250  	}
   251  	errorf := func(str string, args ...interface{}) ([]loader.Sym, uint32, error) {
   252  		return nil, 0, fmt.Errorf("loadelf: %s: %v", pn, fmt.Sprintf(str, args...))
   253  	}
   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  
   350  	case sys.ARM:
   351  		if e != binary.LittleEndian || mach != elf.EM_ARM || class != elf.ELFCLASS32 {
   352  			return errorf("elf object but not arm")
   353  		}
   354  
   355  	case sys.AMD64:
   356  		if e != binary.LittleEndian || mach != elf.EM_X86_64 || class != elf.ELFCLASS64 {
   357  			return errorf("elf object but not amd64")
   358  		}
   359  
   360  	case sys.ARM64:
   361  		if e != binary.LittleEndian || mach != elf.EM_AARCH64 || class != elf.ELFCLASS64 {
   362  			return errorf("elf object but not arm64")
   363  		}
   364  
   365  	case sys.I386:
   366  		if e != binary.LittleEndian || mach != elf.EM_386 || class != elf.ELFCLASS32 {
   367  			return errorf("elf object but not 386")
   368  		}
   369  
   370  	case sys.PPC64:
   371  		if mach != elf.EM_PPC64 || class != elf.ELFCLASS64 {
   372  			return errorf("elf object but not ppc64")
   373  		}
   374  
   375  	case sys.RISCV64:
   376  		if mach != elf.EM_RISCV || class != elf.ELFCLASS64 {
   377  			return errorf("elf object but not riscv64")
   378  		}
   379  
   380  	case sys.S390X:
   381  		if mach != elf.EM_S390 || class != elf.ELFCLASS64 {
   382  			return errorf("elf object but not s390x")
   383  		}
   384  	}
   385  
   386  	// load section list into memory.
   387  	elfobj.sect = make([]ElfSect, elfobj.shnum)
   388  
   389  	elfobj.nsect = uint(elfobj.shnum)
   390  	for i := 0; uint(i) < elfobj.nsect; i++ {
   391  		f.MustSeek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0)
   392  		sect := &elfobj.sect[i]
   393  		if is64 != 0 {
   394  			var b elf.Section64
   395  			if err := binary.Read(f, e, &b); err != nil {
   396  				return errorf("malformed elf file: %v", err)
   397  			}
   398  
   399  			sect.nameoff = b.Name
   400  			sect.type_ = elf.SectionType(b.Type)
   401  			sect.flags = elf.SectionFlag(b.Flags)
   402  			sect.addr = b.Addr
   403  			sect.off = b.Off
   404  			sect.size = b.Size
   405  			sect.link = b.Link
   406  			sect.info = b.Info
   407  			sect.align = b.Addralign
   408  			sect.entsize = b.Entsize
   409  		} else {
   410  			var b elf.Section32
   411  
   412  			if err := binary.Read(f, e, &b); err != nil {
   413  				return errorf("malformed elf file: %v", err)
   414  			}
   415  			sect.nameoff = b.Name
   416  			sect.type_ = elf.SectionType(b.Type)
   417  			sect.flags = elf.SectionFlag(b.Flags)
   418  			sect.addr = uint64(b.Addr)
   419  			sect.off = uint64(b.Off)
   420  			sect.size = uint64(b.Size)
   421  			sect.link = b.Link
   422  			sect.info = b.Info
   423  			sect.align = uint64(b.Addralign)
   424  			sect.entsize = uint64(b.Entsize)
   425  		}
   426  	}
   427  
   428  	// read section string table and translate names
   429  	if elfobj.shstrndx >= uint32(elfobj.nsect) {
   430  		return errorf("malformed elf file: shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect)
   431  	}
   432  
   433  	sect := &elfobj.sect[elfobj.shstrndx]
   434  	if err := elfmap(elfobj, sect); err != nil {
   435  		return errorf("malformed elf file: %v", err)
   436  	}
   437  	for i := 0; uint(i) < elfobj.nsect; i++ {
   438  		if elfobj.sect[i].nameoff != 0 {
   439  			elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:])
   440  		}
   441  	}
   442  
   443  	// load string table for symbols into memory.
   444  	elfobj.symtab = section(elfobj, ".symtab")
   445  
   446  	if elfobj.symtab == nil {
   447  		// our work is done here - no symbols means nothing can refer to this file
   448  		return
   449  	}
   450  
   451  	if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) {
   452  		return errorf("elf object has symbol table with invalid string table link")
   453  	}
   454  
   455  	elfobj.symstr = &elfobj.sect[elfobj.symtab.link]
   456  	if is64 != 0 {
   457  		elfobj.nsymtab = int(elfobj.symtab.size / elf.Sym64Size)
   458  	} else {
   459  		elfobj.nsymtab = int(elfobj.symtab.size / elf.Sym32Size)
   460  	}
   461  
   462  	if err := elfmap(elfobj, elfobj.symtab); err != nil {
   463  		return errorf("malformed elf file: %v", err)
   464  	}
   465  	if err := elfmap(elfobj, elfobj.symstr); err != nil {
   466  		return errorf("malformed elf file: %v", err)
   467  	}
   468  
   469  	// load text and data segments into memory.
   470  	// they are not as small as the section lists, but we'll need
   471  	// the memory anyway for the symbol images, so we might
   472  	// as well use one large chunk.
   473  
   474  	// create symbols for elfmapped sections
   475  	sectsymNames := make(map[string]bool)
   476  	counter := 0
   477  	for i := 0; uint(i) < elfobj.nsect; i++ {
   478  		sect = &elfobj.sect[i]
   479  		if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" {
   480  			if err := elfmap(elfobj, sect); err != nil {
   481  				return errorf("%s: malformed elf file: %v", pn, err)
   482  			}
   483  			// We assume the soft-float ABI unless we see a tag indicating otherwise.
   484  			if initEhdrFlags == 0x5000002 {
   485  				ehdrFlags = 0x5000202
   486  			} else {
   487  				ehdrFlags = initEhdrFlags
   488  			}
   489  			found, newEhdrFlags, err := parseArmAttributes(e, sect.base[:sect.size])
   490  			if err != nil {
   491  				// TODO(dfc) should this return an error?
   492  				log.Printf("%s: %v", pn, err)
   493  			}
   494  			if found {
   495  				ehdrFlags = newEhdrFlags
   496  			}
   497  		}
   498  		if (sect.type_ != elf.SHT_PROGBITS && sect.type_ != elf.SHT_NOBITS) || sect.flags&elf.SHF_ALLOC == 0 {
   499  			continue
   500  		}
   501  		if sect.type_ != elf.SHT_NOBITS {
   502  			if err := elfmap(elfobj, sect); err != nil {
   503  				return errorf("%s: malformed elf file: %v", pn, err)
   504  			}
   505  		}
   506  
   507  		name := fmt.Sprintf("%s(%s)", pkg, sect.name)
   508  		for sectsymNames[name] {
   509  			counter++
   510  			name = fmt.Sprintf("%s(%s%d)", pkg, sect.name, counter)
   511  		}
   512  		sectsymNames[name] = true
   513  
   514  		sb := l.MakeSymbolUpdater(lookup(name, localSymVersion))
   515  
   516  		switch sect.flags & (elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_EXECINSTR) {
   517  		default:
   518  			return errorf("%s: unexpected flags for ELF section %s", pn, sect.name)
   519  
   520  		case elf.SHF_ALLOC:
   521  			sb.SetType(sym.SRODATA)
   522  
   523  		case elf.SHF_ALLOC + elf.SHF_WRITE:
   524  			if sect.type_ == elf.SHT_NOBITS {
   525  				sb.SetType(sym.SNOPTRBSS)
   526  			} else {
   527  				sb.SetType(sym.SNOPTRDATA)
   528  			}
   529  
   530  		case elf.SHF_ALLOC + elf.SHF_EXECINSTR:
   531  			sb.SetType(sym.STEXT)
   532  		}
   533  
   534  		if sect.name == ".got" || sect.name == ".toc" {
   535  			sb.SetType(sym.SELFGOT)
   536  		}
   537  		if sect.type_ == elf.SHT_PROGBITS {
   538  			sb.SetData(sect.base[:sect.size])
   539  		}
   540  
   541  		sb.SetSize(int64(sect.size))
   542  		sb.SetAlign(int32(sect.align))
   543  		sb.SetReadOnly(sect.readOnlyMem)
   544  
   545  		sect.sym = sb.Sym()
   546  	}
   547  
   548  	// enter sub-symbols into symbol table.
   549  	// symbol 0 is the null symbol.
   550  	symbols := make([]loader.Sym, elfobj.nsymtab)
   551  
   552  	for i := 1; i < elfobj.nsymtab; i++ {
   553  		var elfsym ElfSym
   554  		if err := readelfsym(newSym, lookup, l, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
   555  			return errorf("%s: malformed elf file: %v", pn, err)
   556  		}
   557  		symbols[i] = elfsym.sym
   558  		if elfsym.type_ != elf.STT_FUNC && elfsym.type_ != elf.STT_OBJECT && elfsym.type_ != elf.STT_NOTYPE && elfsym.type_ != elf.STT_COMMON {
   559  			continue
   560  		}
   561  		if elfsym.shndx == elf.SHN_COMMON || elfsym.type_ == elf.STT_COMMON {
   562  			sb := l.MakeSymbolUpdater(elfsym.sym)
   563  			if uint64(sb.Size()) < elfsym.size {
   564  				sb.SetSize(int64(elfsym.size))
   565  			}
   566  			if sb.Type() == 0 || sb.Type() == sym.SXREF {
   567  				sb.SetType(sym.SNOPTRBSS)
   568  			}
   569  			continue
   570  		}
   571  
   572  		if uint(elfsym.shndx) >= elfobj.nsect || elfsym.shndx == 0 {
   573  			continue
   574  		}
   575  
   576  		// even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
   577  		if elfsym.sym == 0 {
   578  			continue
   579  		}
   580  		sect = &elfobj.sect[elfsym.shndx]
   581  		if sect.sym == 0 {
   582  			if strings.HasPrefix(elfsym.name, ".Linfo_string") { // clang does this
   583  				continue
   584  			}
   585  
   586  			if elfsym.name == "" && elfsym.type_ == 0 && sect.name == ".debug_str" {
   587  				// This reportedly happens with clang 3.7 on ARM.
   588  				// See issue 13139.
   589  				continue
   590  			}
   591  
   592  			if strings.HasPrefix(elfsym.name, "$d") && elfsym.type_ == 0 && sect.name == ".debug_frame" {
   593  				// "$d" is a marker, not a real symbol.
   594  				// This happens with gcc on ARM64.
   595  				// See https://sourceware.org/bugzilla/show_bug.cgi?id=21809
   596  				continue
   597  			}
   598  
   599  			if strings.HasPrefix(elfsym.name, ".LASF") { // gcc on s390x does this
   600  				continue
   601  			}
   602  			return errorf("%v: sym#%d: ignoring symbol in section %d (type %d)", elfsym.sym, i, elfsym.shndx, elfsym.type_)
   603  		}
   604  
   605  		s := elfsym.sym
   606  		if l.OuterSym(s) != 0 {
   607  			if l.AttrDuplicateOK(s) {
   608  				continue
   609  			}
   610  			return errorf("duplicate symbol reference: %s in both %s and %s",
   611  				l.SymName(s), l.SymName(l.OuterSym(s)), l.SymName(sect.sym))
   612  		}
   613  
   614  		sectsb := l.MakeSymbolUpdater(sect.sym)
   615  		sb := l.MakeSymbolUpdater(s)
   616  
   617  		sb.SetType(sectsb.Type())
   618  		sectsb.AddInteriorSym(s)
   619  		if !l.AttrCgoExportDynamic(s) {
   620  			sb.SetDynimplib("") // satisfy dynimport
   621  		}
   622  		sb.SetValue(int64(elfsym.value))
   623  		sb.SetSize(int64(elfsym.size))
   624  		if sectsb.Type() == sym.STEXT {
   625  			if l.AttrExternal(s) && !l.AttrDuplicateOK(s) {
   626  				return errorf("%s: duplicate symbol definition", sb.Name())
   627  			}
   628  			l.SetAttrExternal(s, true)
   629  		}
   630  
   631  		if elf.Machine(elfobj.machine) == elf.EM_PPC64 {
   632  			flag := int(elfsym.other) >> 5
   633  			if 2 <= flag && flag <= 6 {
   634  				l.SetSymLocalentry(s, 1<<uint(flag-2))
   635  			} else if flag == 7 {
   636  				return errorf("%s: invalid sym.other 0x%x", sb.Name(), elfsym.other)
   637  			}
   638  		}
   639  	}
   640  
   641  	// Sort outer lists by address, adding to textp.
   642  	// This keeps textp in increasing address order.
   643  	for i := uint(0); i < elfobj.nsect; i++ {
   644  		s := elfobj.sect[i].sym
   645  		if s == 0 {
   646  			continue
   647  		}
   648  		sb := l.MakeSymbolUpdater(s)
   649  		if l.SubSym(s) != 0 {
   650  			sb.SortSub()
   651  		}
   652  		if sb.Type() == sym.STEXT {
   653  			if l.AttrOnList(s) {
   654  				return errorf("symbol %s listed multiple times",
   655  					l.SymName(s))
   656  			}
   657  			l.SetAttrOnList(s, true)
   658  			textp = append(textp, s)
   659  			for ss := l.SubSym(s); ss != 0; ss = l.SubSym(ss) {
   660  				if l.AttrOnList(ss) {
   661  					return errorf("symbol %s listed multiple times",
   662  						l.SymName(ss))
   663  				}
   664  				l.SetAttrOnList(ss, true)
   665  				textp = append(textp, ss)
   666  			}
   667  		}
   668  	}
   669  
   670  	// load relocations
   671  	for i := uint(0); i < elfobj.nsect; i++ {
   672  		rsect := &elfobj.sect[i]
   673  		if rsect.type_ != elf.SHT_RELA && rsect.type_ != elf.SHT_REL {
   674  			continue
   675  		}
   676  		if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
   677  			continue
   678  		}
   679  		sect = &elfobj.sect[rsect.info]
   680  		if err := elfmap(elfobj, rsect); err != nil {
   681  			return errorf("malformed elf file: %v", err)
   682  		}
   683  		rela := 0
   684  		if rsect.type_ == elf.SHT_RELA {
   685  			rela = 1
   686  		}
   687  		n := int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
   688  		p := rsect.base
   689  		sb := l.MakeSymbolUpdater(sect.sym)
   690  		for j := 0; j < n; j++ {
   691  			var add uint64
   692  			var symIdx int
   693  			var relocType uint64
   694  			var rOff int32
   695  			var rAdd int64
   696  			var rSym loader.Sym
   697  
   698  			if is64 != 0 {
   699  				// 64-bit rel/rela
   700  				rOff = int32(e.Uint64(p))
   701  
   702  				p = p[8:]
   703  				switch arch.Family {
   704  				case sys.MIPS64:
   705  					// https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
   706  					// The doc shows it's different with general Linux ELF
   707  					symIdx = int(e.Uint32(p))
   708  					relocType = uint64(p[7])
   709  				default:
   710  					info := e.Uint64(p)
   711  					relocType = info & 0xffffffff
   712  					symIdx = int(info >> 32)
   713  				}
   714  				p = p[8:]
   715  				if rela != 0 {
   716  					add = e.Uint64(p)
   717  					p = p[8:]
   718  				}
   719  			} else {
   720  				// 32-bit rel/rela
   721  				rOff = int32(e.Uint32(p))
   722  
   723  				p = p[4:]
   724  				info := e.Uint32(p)
   725  				relocType = uint64(info & 0xff)
   726  				symIdx = int(info >> 8)
   727  				p = p[4:]
   728  				if rela != 0 {
   729  					add = uint64(e.Uint32(p))
   730  					p = p[4:]
   731  				}
   732  			}
   733  
   734  			if relocType == 0 { // skip R_*_NONE relocation
   735  				j--
   736  				n--
   737  				continue
   738  			}
   739  
   740  			if symIdx == 0 { // absolute relocation, don't bother reading the null symbol
   741  				rSym = 0
   742  			} else {
   743  				var elfsym ElfSym
   744  				if err := readelfsym(newSym, lookup, l, arch, elfobj, int(symIdx), &elfsym, 0, 0); err != nil {
   745  					return errorf("malformed elf file: %v", err)
   746  				}
   747  				elfsym.sym = symbols[symIdx]
   748  				if elfsym.sym == 0 {
   749  					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_)
   750  				}
   751  
   752  				rSym = elfsym.sym
   753  			}
   754  
   755  			rType := objabi.ElfRelocOffset + objabi.RelocType(relocType)
   756  			rSize, err := relSize(arch, pn, uint32(relocType))
   757  			if err != nil {
   758  				return nil, 0, err
   759  			}
   760  			if rela != 0 {
   761  				rAdd = int64(add)
   762  			} else {
   763  				// load addend from image
   764  				if rSize == 4 {
   765  					rAdd = int64(e.Uint32(sect.base[rOff:]))
   766  				} else if rSize == 8 {
   767  					rAdd = int64(e.Uint64(sect.base[rOff:]))
   768  				} else {
   769  					return errorf("invalid rela size %d", rSize)
   770  				}
   771  			}
   772  
   773  			if rSize == 2 {
   774  				rAdd = int64(int16(rAdd))
   775  			}
   776  			if rSize == 4 {
   777  				rAdd = int64(int32(rAdd))
   778  			}
   779  
   780  			r, _ := sb.AddRel(rType)
   781  			r.SetOff(rOff)
   782  			r.SetSiz(rSize)
   783  			r.SetSym(rSym)
   784  			r.SetAdd(rAdd)
   785  		}
   786  
   787  		sb.SortRelocs() // just in case
   788  	}
   789  
   790  	return textp, ehdrFlags, nil
   791  }
   792  
   793  func section(elfobj *ElfObj, name string) *ElfSect {
   794  	for i := 0; uint(i) < elfobj.nsect; i++ {
   795  		if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
   796  			return &elfobj.sect[i]
   797  		}
   798  	}
   799  	return nil
   800  }
   801  
   802  func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
   803  	if sect.base != nil {
   804  		return nil
   805  	}
   806  
   807  	if sect.off+sect.size > uint64(elfobj.length) {
   808  		err = fmt.Errorf("elf section past end of file")
   809  		return err
   810  	}
   811  
   812  	elfobj.f.MustSeek(int64(uint64(elfobj.base)+sect.off), 0)
   813  	sect.base, sect.readOnlyMem, err = elfobj.f.Slice(uint64(sect.size))
   814  	if err != nil {
   815  		return fmt.Errorf("short read: %v", err)
   816  	}
   817  
   818  	return nil
   819  }
   820  
   821  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) {
   822  	if i >= elfobj.nsymtab || i < 0 {
   823  		err = fmt.Errorf("invalid elf symbol index")
   824  		return err
   825  	}
   826  
   827  	if i == 0 {
   828  		return fmt.Errorf("readym: read null symbol!")
   829  	}
   830  
   831  	if elfobj.is64 != 0 {
   832  		b := new(elf.Sym64)
   833  		binary.Read(bytes.NewReader(elfobj.symtab.base[i*elf.Sym64Size:(i+1)*elf.Sym64Size]), elfobj.e, b)
   834  		elfsym.name = cstring(elfobj.symstr.base[b.Name:])
   835  		elfsym.value = b.Value
   836  		elfsym.size = b.Size
   837  		elfsym.shndx = elf.SectionIndex(b.Shndx)
   838  		elfsym.bind = elf.ST_BIND(b.Info)
   839  		elfsym.type_ = elf.ST_TYPE(b.Info)
   840  		elfsym.other = b.Other
   841  	} else {
   842  		b := new(elf.Sym32)
   843  		binary.Read(bytes.NewReader(elfobj.symtab.base[i*elf.Sym32Size:(i+1)*elf.Sym32Size]), elfobj.e, b)
   844  		elfsym.name = cstring(elfobj.symstr.base[b.Name:])
   845  		elfsym.value = uint64(b.Value)
   846  		elfsym.size = uint64(b.Size)
   847  		elfsym.shndx = elf.SectionIndex(b.Shndx)
   848  		elfsym.bind = elf.ST_BIND(b.Info)
   849  		elfsym.type_ = elf.ST_TYPE(b.Info)
   850  		elfsym.other = b.Other
   851  	}
   852  
   853  	var s loader.Sym
   854  
   855  	if elfsym.name == "_GLOBAL_OFFSET_TABLE_" {
   856  		elfsym.name = ".got"
   857  	}
   858  	if elfsym.name == ".TOC." {
   859  		// Magic symbol on ppc64.  Will be set to this object
   860  		// file's .got+0x8000.
   861  		elfsym.bind = elf.STB_LOCAL
   862  	}
   863  
   864  	switch elfsym.type_ {
   865  	case elf.STT_SECTION:
   866  		s = elfobj.sect[elfsym.shndx].sym
   867  
   868  	case elf.STT_OBJECT, elf.STT_FUNC, elf.STT_NOTYPE, elf.STT_COMMON:
   869  		switch elfsym.bind {
   870  		case elf.STB_GLOBAL:
   871  			if needSym != 0 {
   872  				s = lookup(elfsym.name, 0)
   873  
   874  				// for global scoped hidden symbols we should insert it into
   875  				// symbol hash table, but mark them as hidden.
   876  				// __i686.get_pc_thunk.bx is allowed to be duplicated, to
   877  				// workaround that we set dupok.
   878  				// TODO(minux): correctly handle __i686.get_pc_thunk.bx without
   879  				// set dupok generally. See https://golang.org/cl/5823055
   880  				// comment #5 for details.
   881  				if s != 0 && elfsym.other == 2 {
   882  					if !l.IsExternal(s) {
   883  						l.MakeSymbolUpdater(s)
   884  					}
   885  					l.SetAttrDuplicateOK(s, true)
   886  					l.SetAttrVisibilityHidden(s, true)
   887  				}
   888  			}
   889  
   890  		case elf.STB_LOCAL:
   891  			if (arch.Family == sys.ARM || arch.Family == sys.ARM64) && (strings.HasPrefix(elfsym.name, "$a") || strings.HasPrefix(elfsym.name, "$d") || strings.HasPrefix(elfsym.name, "$x")) {
   892  				// binutils for arm and arm64 generate these mapping
   893  				// symbols, ignore these
   894  				break
   895  			}
   896  
   897  			if elfsym.name == ".TOC." {
   898  				// We need to be able to look this up,
   899  				// so put it in the hash table.
   900  				if needSym != 0 {
   901  					s = lookup(elfsym.name, localSymVersion)
   902  					l.SetAttrVisibilityHidden(s, true)
   903  				}
   904  				break
   905  			}
   906  
   907  			if needSym != 0 {
   908  				// local names and hidden global names are unique
   909  				// and should only be referenced by their index, not name, so we
   910  				// don't bother to add them into the hash table
   911  				// FIXME: pass empty string here for name? This would
   912  				// reduce mem use, but also (possibly) make it harder
   913  				// to debug problems.
   914  				s = newSym(elfsym.name, localSymVersion)
   915  				l.SetAttrVisibilityHidden(s, true)
   916  			}
   917  
   918  		case elf.STB_WEAK:
   919  			if needSym != 0 {
   920  				s = lookup(elfsym.name, 0)
   921  				if elfsym.other == 2 {
   922  					l.SetAttrVisibilityHidden(s, true)
   923  				}
   924  
   925  				// Allow weak symbols to be duplicated when already defined.
   926  				if l.OuterSym(s) != 0 {
   927  					l.SetAttrDuplicateOK(s, true)
   928  				}
   929  			}
   930  
   931  		default:
   932  			err = fmt.Errorf("%s: invalid symbol binding %d", elfsym.name, elfsym.bind)
   933  			return err
   934  		}
   935  	}
   936  
   937  	// TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
   938  	// sense and should be removed when someone has thought about it properly.
   939  	if s != 0 && l.SymType(s) == 0 && !l.AttrVisibilityHidden(s) && elfsym.type_ != elf.STT_SECTION {
   940  		sb := l.MakeSymbolUpdater(s)
   941  		sb.SetType(sym.SXREF)
   942  	}
   943  	elfsym.sym = s
   944  
   945  	return nil
   946  }
   947  
   948  func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, error) {
   949  	// TODO(mdempsky): Replace this with a struct-valued switch statement
   950  	// once golang.org/issue/15164 is fixed or found to not impair cmd/link
   951  	// performance.
   952  
   953  	const (
   954  		AMD64   = uint32(sys.AMD64)
   955  		ARM     = uint32(sys.ARM)
   956  		ARM64   = uint32(sys.ARM64)
   957  		I386    = uint32(sys.I386)
   958  		MIPS    = uint32(sys.MIPS)
   959  		MIPS64  = uint32(sys.MIPS64)
   960  		PPC64   = uint32(sys.PPC64)
   961  		RISCV64 = uint32(sys.RISCV64)
   962  		S390X   = uint32(sys.S390X)
   963  	)
   964  
   965  	switch uint32(arch.Family) | elftype<<16 {
   966  	default:
   967  		return 0, fmt.Errorf("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
   968  
   969  	case MIPS | uint32(elf.R_MIPS_HI16)<<16,
   970  		MIPS | uint32(elf.R_MIPS_LO16)<<16,
   971  		MIPS | uint32(elf.R_MIPS_GOT16)<<16,
   972  		MIPS | uint32(elf.R_MIPS_GOT_HI16)<<16,
   973  		MIPS | uint32(elf.R_MIPS_GOT_LO16)<<16,
   974  		MIPS | uint32(elf.R_MIPS_GPREL16)<<16,
   975  		MIPS | uint32(elf.R_MIPS_GOT_PAGE)<<16,
   976  		MIPS | uint32(elf.R_MIPS_JALR)<<16,
   977  		MIPS | uint32(elf.R_MIPS_GOT_OFST)<<16,
   978  		MIPS64 | uint32(elf.R_MIPS_HI16)<<16,
   979  		MIPS64 | uint32(elf.R_MIPS_LO16)<<16,
   980  		MIPS64 | uint32(elf.R_MIPS_GOT16)<<16,
   981  		MIPS64 | uint32(elf.R_MIPS_GOT_HI16)<<16,
   982  		MIPS64 | uint32(elf.R_MIPS_GOT_LO16)<<16,
   983  		MIPS64 | uint32(elf.R_MIPS_GPREL16)<<16,
   984  		MIPS64 | uint32(elf.R_MIPS_GOT_PAGE)<<16,
   985  		MIPS64 | uint32(elf.R_MIPS_JALR)<<16,
   986  		MIPS64 | uint32(elf.R_MIPS_GOT_OFST)<<16:
   987  		return 4, nil
   988  
   989  	case S390X | uint32(elf.R_390_8)<<16:
   990  		return 1, nil
   991  
   992  	case PPC64 | uint32(elf.R_PPC64_TOC16)<<16,
   993  		PPC64 | uint32(elf.R_PPC64_TOC16_LO)<<16,
   994  		PPC64 | uint32(elf.R_PPC64_TOC16_HI)<<16,
   995  		PPC64 | uint32(elf.R_PPC64_TOC16_HA)<<16,
   996  		PPC64 | uint32(elf.R_PPC64_TOC16_DS)<<16,
   997  		PPC64 | uint32(elf.R_PPC64_TOC16_LO_DS)<<16,
   998  		PPC64 | uint32(elf.R_PPC64_REL16_LO)<<16,
   999  		PPC64 | uint32(elf.R_PPC64_REL16_HI)<<16,
  1000  		PPC64 | uint32(elf.R_PPC64_REL16_HA)<<16,
  1001  		S390X | uint32(elf.R_390_16)<<16,
  1002  		S390X | uint32(elf.R_390_GOT16)<<16,
  1003  		S390X | uint32(elf.R_390_PC16)<<16,
  1004  		S390X | uint32(elf.R_390_PC16DBL)<<16,
  1005  		S390X | uint32(elf.R_390_PLT16DBL)<<16:
  1006  		return 2, nil
  1007  
  1008  	case ARM | uint32(elf.R_ARM_ABS32)<<16,
  1009  		ARM | uint32(elf.R_ARM_GOT32)<<16,
  1010  		ARM | uint32(elf.R_ARM_PLT32)<<16,
  1011  		ARM | uint32(elf.R_ARM_GOTOFF)<<16,
  1012  		ARM | uint32(elf.R_ARM_GOTPC)<<16,
  1013  		ARM | uint32(elf.R_ARM_THM_PC22)<<16,
  1014  		ARM | uint32(elf.R_ARM_REL32)<<16,
  1015  		ARM | uint32(elf.R_ARM_CALL)<<16,
  1016  		ARM | uint32(elf.R_ARM_V4BX)<<16,
  1017  		ARM | uint32(elf.R_ARM_GOT_PREL)<<16,
  1018  		ARM | uint32(elf.R_ARM_PC24)<<16,
  1019  		ARM | uint32(elf.R_ARM_JUMP24)<<16,
  1020  		ARM64 | uint32(elf.R_AARCH64_CALL26)<<16,
  1021  		ARM64 | uint32(elf.R_AARCH64_ADR_GOT_PAGE)<<16,
  1022  		ARM64 | uint32(elf.R_AARCH64_LD64_GOT_LO12_NC)<<16,
  1023  		ARM64 | uint32(elf.R_AARCH64_ADR_PREL_PG_HI21)<<16,
  1024  		ARM64 | uint32(elf.R_AARCH64_ADD_ABS_LO12_NC)<<16,
  1025  		ARM64 | uint32(elf.R_AARCH64_LDST8_ABS_LO12_NC)<<16,
  1026  		ARM64 | uint32(elf.R_AARCH64_LDST16_ABS_LO12_NC)<<16,
  1027  		ARM64 | uint32(elf.R_AARCH64_LDST32_ABS_LO12_NC)<<16,
  1028  		ARM64 | uint32(elf.R_AARCH64_LDST64_ABS_LO12_NC)<<16,
  1029  		ARM64 | uint32(elf.R_AARCH64_LDST128_ABS_LO12_NC)<<16,
  1030  		ARM64 | uint32(elf.R_AARCH64_PREL32)<<16,
  1031  		ARM64 | uint32(elf.R_AARCH64_JUMP26)<<16,
  1032  		AMD64 | uint32(elf.R_X86_64_PC32)<<16,
  1033  		AMD64 | uint32(elf.R_X86_64_PLT32)<<16,
  1034  		AMD64 | uint32(elf.R_X86_64_GOTPCREL)<<16,
  1035  		AMD64 | uint32(elf.R_X86_64_GOTPCRELX)<<16,
  1036  		AMD64 | uint32(elf.R_X86_64_REX_GOTPCRELX)<<16,
  1037  		I386 | uint32(elf.R_386_32)<<16,
  1038  		I386 | uint32(elf.R_386_PC32)<<16,
  1039  		I386 | uint32(elf.R_386_GOT32)<<16,
  1040  		I386 | uint32(elf.R_386_PLT32)<<16,
  1041  		I386 | uint32(elf.R_386_GOTOFF)<<16,
  1042  		I386 | uint32(elf.R_386_GOTPC)<<16,
  1043  		I386 | uint32(elf.R_386_GOT32X)<<16,
  1044  		PPC64 | uint32(elf.R_PPC64_REL24)<<16,
  1045  		PPC64 | uint32(elf.R_PPC_REL32)<<16,
  1046  		S390X | uint32(elf.R_390_32)<<16,
  1047  		S390X | uint32(elf.R_390_PC32)<<16,
  1048  		S390X | uint32(elf.R_390_GOT32)<<16,
  1049  		S390X | uint32(elf.R_390_PLT32)<<16,
  1050  		S390X | uint32(elf.R_390_PC32DBL)<<16,
  1051  		S390X | uint32(elf.R_390_PLT32DBL)<<16,
  1052  		S390X | uint32(elf.R_390_GOTPCDBL)<<16,
  1053  		S390X | uint32(elf.R_390_GOTENT)<<16:
  1054  		return 4, nil
  1055  
  1056  	case AMD64 | uint32(elf.R_X86_64_64)<<16,
  1057  		AMD64 | uint32(elf.R_X86_64_PC64)<<16,
  1058  		ARM64 | uint32(elf.R_AARCH64_ABS64)<<16,
  1059  		ARM64 | uint32(elf.R_AARCH64_PREL64)<<16,
  1060  		PPC64 | uint32(elf.R_PPC64_ADDR64)<<16,
  1061  		S390X | uint32(elf.R_390_GLOB_DAT)<<16,
  1062  		S390X | uint32(elf.R_390_RELATIVE)<<16,
  1063  		S390X | uint32(elf.R_390_GOTOFF)<<16,
  1064  		S390X | uint32(elf.R_390_GOTPC)<<16,
  1065  		S390X | uint32(elf.R_390_64)<<16,
  1066  		S390X | uint32(elf.R_390_PC64)<<16,
  1067  		S390X | uint32(elf.R_390_GOT64)<<16,
  1068  		S390X | uint32(elf.R_390_PLT64)<<16:
  1069  		return 8, nil
  1070  
  1071  	case RISCV64 | uint32(elf.R_RISCV_RVC_BRANCH)<<16,
  1072  		RISCV64 | uint32(elf.R_RISCV_RVC_JUMP)<<16:
  1073  		return 2, nil
  1074  
  1075  	case RISCV64 | uint32(elf.R_RISCV_32)<<16,
  1076  		RISCV64 | uint32(elf.R_RISCV_BRANCH)<<16,
  1077  		RISCV64 | uint32(elf.R_RISCV_HI20)<<16,
  1078  		RISCV64 | uint32(elf.R_RISCV_LO12_I)<<16,
  1079  		RISCV64 | uint32(elf.R_RISCV_LO12_S)<<16,
  1080  		RISCV64 | uint32(elf.R_RISCV_GOT_HI20)<<16,
  1081  		RISCV64 | uint32(elf.R_RISCV_PCREL_HI20)<<16,
  1082  		RISCV64 | uint32(elf.R_RISCV_PCREL_LO12_I)<<16,
  1083  		RISCV64 | uint32(elf.R_RISCV_PCREL_LO12_S)<<16,
  1084  		RISCV64 | uint32(elf.R_RISCV_RELAX)<<16:
  1085  		return 4, nil
  1086  
  1087  	case RISCV64 | uint32(elf.R_RISCV_64)<<16,
  1088  		RISCV64 | uint32(elf.R_RISCV_CALL)<<16,
  1089  		RISCV64 | uint32(elf.R_RISCV_CALL_PLT)<<16:
  1090  		return 8, nil
  1091  	}
  1092  }
  1093  
  1094  func cstring(x []byte) string {
  1095  	i := bytes.IndexByte(x, '\x00')
  1096  	if i >= 0 {
  1097  		x = x[:i]
  1098  	}
  1099  	return string(x)
  1100  }
  1101  

View as plain text