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

     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  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  	errorf := func(str string, args ...any) ([]loader.Sym, uint32, error) {
   246  		return nil, 0, fmt.Errorf("loadelf: %s: %v", pn, fmt.Sprintf(str, args...))
   247  	}
   248  
   249  	ehdrFlags = initEhdrFlags
   250  
   251  	base := f.Offset()
   252  
   253  	var hdrbuf [64]byte
   254  	if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
   255  		return errorf("malformed elf file: %v", err)
   256  	}
   257  
   258  	var e binary.ByteOrder
   259  	switch elf.Data(hdrbuf[elf.EI_DATA]) {
   260  	case elf.ELFDATA2LSB:
   261  		e = binary.LittleEndian
   262  
   263  	case elf.ELFDATA2MSB:
   264  		e = binary.BigEndian
   265  
   266  	default:
   267  		return errorf("malformed elf file, unknown header")
   268  	}
   269  
   270  	hdr := new(elf.Header32)
   271  	binary.Read(bytes.NewReader(hdrbuf[:]), e, hdr)
   272  
   273  	if string(hdr.Ident[:elf.EI_CLASS]) != elf.ELFMAG {
   274  		return errorf("malformed elf file, bad header")
   275  	}
   276  
   277  	// read header
   278  	elfobj := new(ElfObj)
   279  
   280  	elfobj.e = e
   281  	elfobj.f = f
   282  	elfobj.base = base
   283  	elfobj.length = length
   284  	elfobj.name = pn
   285  
   286  	is64 := 0
   287  	class := elf.Class(hdrbuf[elf.EI_CLASS])
   288  	if class == elf.ELFCLASS64 {
   289  		is64 = 1
   290  		hdr := new(elf.Header64)
   291  		binary.Read(bytes.NewReader(hdrbuf[:]), e, hdr)
   292  		elfobj.type_ = uint32(hdr.Type)
   293  		elfobj.machine = uint32(hdr.Machine)
   294  		elfobj.version = hdr.Version
   295  		elfobj.entry = hdr.Entry
   296  		elfobj.phoff = hdr.Phoff
   297  		elfobj.shoff = hdr.Shoff
   298  		elfobj.flags = hdr.Flags
   299  		elfobj.ehsize = uint32(hdr.Ehsize)
   300  		elfobj.phentsize = uint32(hdr.Phentsize)
   301  		elfobj.phnum = uint32(hdr.Phnum)
   302  		elfobj.shentsize = uint32(hdr.Shentsize)
   303  		elfobj.shnum = uint32(hdr.Shnum)
   304  		elfobj.shstrndx = uint32(hdr.Shstrndx)
   305  	} else {
   306  		elfobj.type_ = uint32(hdr.Type)
   307  		elfobj.machine = uint32(hdr.Machine)
   308  		elfobj.version = hdr.Version
   309  		elfobj.entry = uint64(hdr.Entry)
   310  		elfobj.phoff = uint64(hdr.Phoff)
   311  		elfobj.shoff = uint64(hdr.Shoff)
   312  		elfobj.flags = hdr.Flags
   313  		elfobj.ehsize = uint32(hdr.Ehsize)
   314  		elfobj.phentsize = uint32(hdr.Phentsize)
   315  		elfobj.phnum = uint32(hdr.Phnum)
   316  		elfobj.shentsize = uint32(hdr.Shentsize)
   317  		elfobj.shnum = uint32(hdr.Shnum)
   318  		elfobj.shstrndx = uint32(hdr.Shstrndx)
   319  	}
   320  
   321  	elfobj.is64 = is64
   322  
   323  	if v := uint32(hdrbuf[elf.EI_VERSION]); v != elfobj.version {
   324  		return errorf("malformed elf version: got %d, want %d", v, elfobj.version)
   325  	}
   326  
   327  	if elf.Type(elfobj.type_) != elf.ET_REL {
   328  		return errorf("elf but not elf relocatable object")
   329  	}
   330  
   331  	mach := elf.Machine(elfobj.machine)
   332  	switch arch.Family {
   333  	default:
   334  		return errorf("elf %s unimplemented", arch.Name)
   335  
   336  	case sys.MIPS:
   337  		if mach != elf.EM_MIPS || class != elf.ELFCLASS32 {
   338  			return errorf("elf object but not mips")
   339  		}
   340  
   341  	case sys.MIPS64:
   342  		if mach != elf.EM_MIPS || class != elf.ELFCLASS64 {
   343  			return errorf("elf object but not mips64")
   344  		}
   345  	case sys.Loong64:
   346  		if mach != elf.EM_LOONGARCH || class != elf.ELFCLASS64 {
   347  			return errorf("elf object but not loong64")
   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(l.LookupOrCreateCgoExport(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  			sb.SetExternal(true)
   540  		}
   541  
   542  		sb.SetSize(int64(sect.size))
   543  		sb.SetAlign(int32(sect.align))
   544  		sb.SetReadOnly(sect.readOnlyMem)
   545  
   546  		sect.sym = sb.Sym()
   547  	}
   548  
   549  	// enter sub-symbols into symbol table.
   550  	// symbol 0 is the null symbol.
   551  	symbols := make([]loader.Sym, elfobj.nsymtab)
   552  
   553  	for i := 1; i < elfobj.nsymtab; i++ {
   554  		var elfsym ElfSym
   555  		if err := readelfsym(l, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
   556  			return errorf("%s: malformed elf file: %v", pn, err)
   557  		}
   558  		symbols[i] = elfsym.sym
   559  		if elfsym.type_ != elf.STT_FUNC && elfsym.type_ != elf.STT_OBJECT && elfsym.type_ != elf.STT_NOTYPE && elfsym.type_ != elf.STT_COMMON {
   560  			continue
   561  		}
   562  		if elfsym.shndx == elf.SHN_COMMON || elfsym.type_ == elf.STT_COMMON {
   563  			sb := l.MakeSymbolUpdater(elfsym.sym)
   564  			if uint64(sb.Size()) < elfsym.size {
   565  				sb.SetSize(int64(elfsym.size))
   566  			}
   567  			if sb.Type() == 0 || sb.Type() == sym.SXREF {
   568  				sb.SetType(sym.SNOPTRBSS)
   569  			}
   570  			continue
   571  		}
   572  
   573  		if uint(elfsym.shndx) >= elfobj.nsect || elfsym.shndx == 0 {
   574  			continue
   575  		}
   576  
   577  		// even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
   578  		if elfsym.sym == 0 {
   579  			continue
   580  		}
   581  		sect = &elfobj.sect[elfsym.shndx]
   582  		if sect.sym == 0 {
   583  			if elfsym.type_ == 0 {
   584  				if strings.HasPrefix(sect.name, ".debug_") && elfsym.name == "" {
   585  					// clang on arm and riscv64.
   586  					// This reportedly happens with clang 3.7 on ARM.
   587  					// See issue 13139.
   588  					continue
   589  				}
   590  				if strings.HasPrefix(elfsym.name, ".Ldebug_") || elfsym.name == ".L0 " {
   591  					// gcc on riscv64.
   592  					continue
   593  				}
   594  				if elfsym.name == ".Lline_table_start0" {
   595  					// clang on riscv64.
   596  					continue
   597  				}
   598  
   599  				if strings.HasPrefix(elfsym.name, "$d") && sect.name == ".debug_frame" {
   600  					// "$d" is a marker, not a real symbol.
   601  					// This happens with gcc on ARM64.
   602  					// See https://sourceware.org/bugzilla/show_bug.cgi?id=21809
   603  					continue
   604  				}
   605  
   606  				if arch.Family == sys.RISCV64 &&
   607  					(strings.HasPrefix(elfsym.name, "$d") || strings.HasPrefix(elfsym.name, "$x")) {
   608  					// Ignore RISC-V mapping symbols, which
   609  					// are similar to ARM64's case.
   610  					// See issue 73591.
   611  					continue
   612  				}
   613  
   614  				if arch.Family == sys.Loong64 && (strings.HasPrefix(elfsym.name, ".L") || elfsym.name == "L0\001") {
   615  					// Symbols generated by the relax feature of gcc and binutils on loong64.
   616  					continue
   617  				}
   618  
   619  				if strings.HasPrefix(elfsym.name, "wm4.") || strings.HasPrefix(elfsym.name, "wm8.") {
   620  					// Symbols generated by GCC as
   621  					// group symbols to eliminate
   622  					// duplicate debug info for
   623  					// preprocessor symbols.
   624  					continue
   625  				}
   626  			}
   627  
   628  			if strings.HasPrefix(elfsym.name, ".Linfo_string") {
   629  				// clang does this
   630  				continue
   631  			}
   632  
   633  			if strings.HasPrefix(elfsym.name, ".LASF") || strings.HasPrefix(elfsym.name, ".LLRL") || strings.HasPrefix(elfsym.name, ".LLST") || strings.HasPrefix(elfsym.name, ".LVUS") {
   634  				// gcc on s390x and riscv64 does this.
   635  				continue
   636  			}
   637  
   638  			return errorf("%v: sym#%d (%q): unrecognized symbol in section %d (%q) (type %d)", elfsym.sym, i, elfsym.name, elfsym.shndx, sect.name, elfsym.type_)
   639  		}
   640  
   641  		s := elfsym.sym
   642  		if l.OuterSym(s) != 0 {
   643  			if l.AttrDuplicateOK(s) {
   644  				continue
   645  			}
   646  			return errorf("duplicate symbol reference: %s in both %s and %s",
   647  				l.SymName(s), l.SymName(l.OuterSym(s)), l.SymName(sect.sym))
   648  		}
   649  
   650  		sectsb := l.MakeSymbolUpdater(sect.sym)
   651  		sb := l.MakeSymbolUpdater(s)
   652  
   653  		sb.SetType(sectsb.Type())
   654  		sectsb.AddInteriorSym(s)
   655  		if !l.AttrCgoExportDynamic(s) {
   656  			sb.SetDynimplib("") // satisfy dynimport
   657  		}
   658  		sb.SetValue(int64(elfsym.value))
   659  		sb.SetSize(int64(elfsym.size))
   660  		if sectsb.Type().IsText() {
   661  			if l.AttrExternal(s) && !l.AttrDuplicateOK(s) {
   662  				return errorf("%s: duplicate symbol definition", sb.Name())
   663  			}
   664  			l.SetAttrExternal(s, true)
   665  		}
   666  
   667  		if elf.Machine(elfobj.machine) == elf.EM_PPC64 {
   668  			flag := int(elfsym.other) >> 5
   669  			switch flag {
   670  			case 0:
   671  				// No local entry. R2 is preserved.
   672  			case 1:
   673  				// This is kind of a hack, but pass the hint about this symbol's
   674  				// usage of R2 (R2 is a caller-save register not a TOC pointer, and
   675  				// this function does not have a distinct local entry) by setting
   676  				// its SymLocalentry to 1.
   677  				l.SetSymLocalentry(s, 1)
   678  			case 7:
   679  				return errorf("%s: invalid sym.other 0x%x", sb.Name(), elfsym.other)
   680  			default:
   681  				// Convert the word sized offset into bytes.
   682  				l.SetSymLocalentry(s, 4<<uint(flag-2))
   683  			}
   684  		}
   685  	}
   686  
   687  	// Sort outer lists by address, adding to textp.
   688  	// This keeps textp in increasing address order.
   689  	for i := uint(0); i < elfobj.nsect; i++ {
   690  		s := elfobj.sect[i].sym
   691  		if s == 0 {
   692  			continue
   693  		}
   694  		sb := l.MakeSymbolUpdater(s)
   695  		if l.SubSym(s) != 0 {
   696  			sb.SortSub()
   697  		}
   698  		if sb.Type().IsText() {
   699  			if l.AttrOnList(s) {
   700  				return errorf("symbol %s listed multiple times",
   701  					l.SymName(s))
   702  			}
   703  			l.SetAttrOnList(s, true)
   704  			textp = append(textp, s)
   705  			for ss := l.SubSym(s); ss != 0; ss = l.SubSym(ss) {
   706  				if arch.Family == sys.Loong64 && (strings.HasPrefix(l.SymName(ss), ".L") || l.SymName(ss) == "L0\001") {
   707  					// Symbols generated by the relax feature of gcc and binutils on loong64.
   708  					// We ignore them here because there are too many symbols of this type,
   709  					// resulting in insufficient space in findfunctable.
   710  					continue
   711  				}
   712  				if l.AttrOnList(ss) {
   713  					return errorf("symbol %s listed multiple times",
   714  						l.SymName(ss))
   715  				}
   716  				l.SetAttrOnList(ss, true)
   717  				textp = append(textp, ss)
   718  			}
   719  		}
   720  	}
   721  
   722  	// load relocations
   723  	for i := uint(0); i < elfobj.nsect; i++ {
   724  		rsect := &elfobj.sect[i]
   725  		if rsect.type_ != elf.SHT_RELA && rsect.type_ != elf.SHT_REL {
   726  			continue
   727  		}
   728  		if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
   729  			continue
   730  		}
   731  		sect = &elfobj.sect[rsect.info]
   732  		if err := elfmap(elfobj, rsect); err != nil {
   733  			return errorf("malformed elf file: %v", err)
   734  		}
   735  		rela := 0
   736  		if rsect.type_ == elf.SHT_RELA {
   737  			rela = 1
   738  		}
   739  		n := int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
   740  		p := rsect.base
   741  		sb := l.MakeSymbolUpdater(sect.sym)
   742  		for j := 0; j < n; j++ {
   743  			var add uint64
   744  			var symIdx int
   745  			var relocType uint64
   746  			var rOff int32
   747  			var rAdd int64
   748  			var rSym loader.Sym
   749  
   750  			if is64 != 0 {
   751  				// 64-bit rel/rela
   752  				rOff = int32(e.Uint64(p))
   753  
   754  				p = p[8:]
   755  				switch arch.Family {
   756  				case sys.MIPS64:
   757  					// https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf
   758  					// The doc shows it's different with general Linux ELF
   759  					symIdx = int(e.Uint32(p))
   760  					relocType = uint64(p[7])
   761  				default:
   762  					info := e.Uint64(p)
   763  					relocType = info & 0xffffffff
   764  					symIdx = int(info >> 32)
   765  				}
   766  				p = p[8:]
   767  				if rela != 0 {
   768  					add = e.Uint64(p)
   769  					p = p[8:]
   770  				}
   771  			} else {
   772  				// 32-bit rel/rela
   773  				rOff = int32(e.Uint32(p))
   774  
   775  				p = p[4:]
   776  				info := e.Uint32(p)
   777  				relocType = uint64(info & 0xff)
   778  				symIdx = int(info >> 8)
   779  				p = p[4:]
   780  				if rela != 0 {
   781  					add = uint64(e.Uint32(p))
   782  					p = p[4:]
   783  				}
   784  			}
   785  
   786  			if relocType == 0 { // skip R_*_NONE relocation
   787  				j--
   788  				n--
   789  				continue
   790  			}
   791  
   792  			if symIdx == 0 { // absolute relocation, don't bother reading the null symbol
   793  				rSym = 0
   794  			} else {
   795  				var elfsym ElfSym
   796  				if err := readelfsym(l, arch, elfobj, symIdx, &elfsym, 0, 0); err != nil {
   797  					return errorf("malformed elf file: %v", err)
   798  				}
   799  				elfsym.sym = symbols[symIdx]
   800  				if elfsym.sym == 0 {
   801  					return errorf("malformed elf file: %s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", l.SymName(sect.sym), j, symIdx, elfsym.name, elfsym.shndx, elfsym.type_)
   802  				}
   803  
   804  				rSym = elfsym.sym
   805  			}
   806  
   807  			rType := objabi.ElfRelocOffset + objabi.RelocType(relocType)
   808  			rSize, addendSize, err := relSize(arch, pn, uint32(relocType))
   809  			if err != nil {
   810  				return nil, 0, err
   811  			}
   812  			if rela != 0 {
   813  				rAdd = int64(add)
   814  			} else {
   815  				// load addend from image
   816  				if rSize == 4 {
   817  					rAdd = int64(e.Uint32(sect.base[rOff:]))
   818  				} else if rSize == 8 {
   819  					rAdd = int64(e.Uint64(sect.base[rOff:]))
   820  				} else {
   821  					return errorf("invalid rela size %d", rSize)
   822  				}
   823  			}
   824  
   825  			if addendSize == 2 {
   826  				rAdd = int64(int16(rAdd))
   827  			}
   828  			if addendSize == 4 {
   829  				rAdd = int64(int32(rAdd))
   830  			}
   831  
   832  			r, _ := sb.AddRel(rType)
   833  			r.SetOff(rOff)
   834  			r.SetSiz(rSize)
   835  			r.SetSym(rSym)
   836  			r.SetAdd(rAdd)
   837  		}
   838  
   839  		sb.SortRelocs() // just in case
   840  	}
   841  
   842  	return textp, ehdrFlags, nil
   843  }
   844  
   845  func section(elfobj *ElfObj, name string) *ElfSect {
   846  	for i := 0; uint(i) < elfobj.nsect; i++ {
   847  		if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
   848  			return &elfobj.sect[i]
   849  		}
   850  	}
   851  	return nil
   852  }
   853  
   854  func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
   855  	if sect.base != nil {
   856  		return nil
   857  	}
   858  
   859  	if sect.off+sect.size > uint64(elfobj.length) {
   860  		err = fmt.Errorf("elf section past end of file")
   861  		return err
   862  	}
   863  
   864  	elfobj.f.MustSeek(int64(uint64(elfobj.base)+sect.off), 0)
   865  	sect.base, sect.readOnlyMem, err = elfobj.f.Slice(sect.size)
   866  	if err != nil {
   867  		return fmt.Errorf("short read: %v", err)
   868  	}
   869  
   870  	return nil
   871  }
   872  
   873  func readelfsym(l *loader.Loader, arch *sys.Arch, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
   874  	if i >= elfobj.nsymtab || i < 0 {
   875  		err = fmt.Errorf("invalid elf symbol index")
   876  		return err
   877  	}
   878  
   879  	if i == 0 {
   880  		return fmt.Errorf("readym: read null symbol!")
   881  	}
   882  
   883  	if elfobj.is64 != 0 {
   884  		b := new(elf.Sym64)
   885  		binary.Read(bytes.NewReader(elfobj.symtab.base[i*elf.Sym64Size:(i+1)*elf.Sym64Size]), elfobj.e, b)
   886  		elfsym.name = cstring(elfobj.symstr.base[b.Name:])
   887  		elfsym.value = b.Value
   888  		elfsym.size = b.Size
   889  		elfsym.shndx = elf.SectionIndex(b.Shndx)
   890  		elfsym.bind = elf.ST_BIND(b.Info)
   891  		elfsym.type_ = elf.ST_TYPE(b.Info)
   892  		elfsym.other = b.Other
   893  	} else {
   894  		b := new(elf.Sym32)
   895  		binary.Read(bytes.NewReader(elfobj.symtab.base[i*elf.Sym32Size:(i+1)*elf.Sym32Size]), elfobj.e, b)
   896  		elfsym.name = cstring(elfobj.symstr.base[b.Name:])
   897  		elfsym.value = uint64(b.Value)
   898  		elfsym.size = uint64(b.Size)
   899  		elfsym.shndx = elf.SectionIndex(b.Shndx)
   900  		elfsym.bind = elf.ST_BIND(b.Info)
   901  		elfsym.type_ = elf.ST_TYPE(b.Info)
   902  		elfsym.other = b.Other
   903  	}
   904  
   905  	var s loader.Sym
   906  
   907  	if elfsym.name == "_GLOBAL_OFFSET_TABLE_" {
   908  		elfsym.name = ".got"
   909  	}
   910  	if elfsym.name == ".TOC." {
   911  		// Magic symbol on ppc64.  Will be set to this object
   912  		// file's .got+0x8000.
   913  		elfsym.bind = elf.STB_LOCAL
   914  	}
   915  
   916  	switch elfsym.type_ {
   917  	case elf.STT_SECTION:
   918  		s = elfobj.sect[elfsym.shndx].sym
   919  
   920  	case elf.STT_OBJECT, elf.STT_FUNC, elf.STT_NOTYPE, elf.STT_COMMON:
   921  		switch elfsym.bind {
   922  		case elf.STB_GLOBAL:
   923  			if needSym != 0 {
   924  				s = l.LookupOrCreateCgoExport(elfsym.name, 0)
   925  
   926  				// for global scoped hidden symbols we should insert it into
   927  				// symbol hash table, but mark them as hidden.
   928  				// __i686.get_pc_thunk.bx is allowed to be duplicated, to
   929  				// workaround that we set dupok.
   930  				// TODO(minux): correctly handle __i686.get_pc_thunk.bx without
   931  				// set dupok generally. See https://golang.org/cl/5823055
   932  				// comment #5 for details.
   933  				if s != 0 && elfsym.other == 2 {
   934  					if !l.IsExternal(s) {
   935  						l.MakeSymbolUpdater(s)
   936  					}
   937  					l.SetAttrDuplicateOK(s, true)
   938  					l.SetAttrVisibilityHidden(s, true)
   939  				}
   940  			}
   941  
   942  		case elf.STB_LOCAL:
   943  			if (arch.Family == sys.ARM || arch.Family == sys.ARM64) && (strings.HasPrefix(elfsym.name, "$a") || strings.HasPrefix(elfsym.name, "$d") || strings.HasPrefix(elfsym.name, "$x")) {
   944  				// binutils for arm and arm64 generate these mapping
   945  				// symbols, ignore these
   946  				break
   947  			}
   948  
   949  			if elfsym.name == ".TOC." {
   950  				// We need to be able to look this up,
   951  				// so put it in the hash table.
   952  				if needSym != 0 {
   953  					s = l.LookupOrCreateCgoExport(elfsym.name, localSymVersion)
   954  					l.SetAttrVisibilityHidden(s, true)
   955  				}
   956  				break
   957  			}
   958  
   959  			if needSym != 0 {
   960  				// local names and hidden global names are unique
   961  				// and should only be referenced by their index, not name, so we
   962  				// don't bother to add them into the hash table
   963  				// FIXME: pass empty string here for name? This would
   964  				// reduce mem use, but also (possibly) make it harder
   965  				// to debug problems.
   966  				s = l.CreateStaticSym(elfsym.name)
   967  				l.SetAttrVisibilityHidden(s, true)
   968  			}
   969  
   970  		case elf.STB_WEAK:
   971  			if needSym != 0 {
   972  				s = l.LookupOrCreateCgoExport(elfsym.name, 0)
   973  				if elfsym.other == 2 {
   974  					l.SetAttrVisibilityHidden(s, true)
   975  				}
   976  
   977  				// Allow weak symbols to be duplicated when already defined.
   978  				if l.OuterSym(s) != 0 {
   979  					l.SetAttrDuplicateOK(s, true)
   980  				}
   981  			}
   982  
   983  		default:
   984  			err = fmt.Errorf("%s: invalid symbol binding %d", elfsym.name, elfsym.bind)
   985  			return err
   986  		}
   987  	}
   988  
   989  	if s != 0 && l.SymType(s) == 0 && elfsym.type_ != elf.STT_SECTION {
   990  		sb := l.MakeSymbolUpdater(s)
   991  		sb.SetType(sym.SXREF)
   992  	}
   993  	elfsym.sym = s
   994  
   995  	return nil
   996  }
   997  
   998  // Return the size of the relocated field, and the size of the addend as the first
   999  // and second values. Note, the addend may be larger than the relocation field in
  1000  // some cases when a relocated value is split across multiple relocations.
  1001  func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) {
  1002  	// TODO(mdempsky): Replace this with a struct-valued switch statement
  1003  	// once golang.org/issue/15164 is fixed or found to not impair cmd/link
  1004  	// performance.
  1005  
  1006  	const (
  1007  		AMD64   = uint32(sys.AMD64)
  1008  		ARM     = uint32(sys.ARM)
  1009  		ARM64   = uint32(sys.ARM64)
  1010  		I386    = uint32(sys.I386)
  1011  		LOONG64 = uint32(sys.Loong64)
  1012  		MIPS    = uint32(sys.MIPS)
  1013  		MIPS64  = uint32(sys.MIPS64)
  1014  		PPC64   = uint32(sys.PPC64)
  1015  		RISCV64 = uint32(sys.RISCV64)
  1016  		S390X   = uint32(sys.S390X)
  1017  	)
  1018  
  1019  	switch uint32(arch.Family) | elftype<<16 {
  1020  	default:
  1021  		return 0, 0, fmt.Errorf("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
  1022  
  1023  	case MIPS | uint32(elf.R_MIPS_HI16)<<16,
  1024  		MIPS | uint32(elf.R_MIPS_LO16)<<16,
  1025  		MIPS | uint32(elf.R_MIPS_GOT16)<<16,
  1026  		MIPS | uint32(elf.R_MIPS_GOT_HI16)<<16,
  1027  		MIPS | uint32(elf.R_MIPS_GOT_LO16)<<16,
  1028  		MIPS | uint32(elf.R_MIPS_GPREL16)<<16,
  1029  		MIPS | uint32(elf.R_MIPS_GOT_PAGE)<<16,
  1030  		MIPS | uint32(elf.R_MIPS_JALR)<<16,
  1031  		MIPS | uint32(elf.R_MIPS_GOT_OFST)<<16,
  1032  		MIPS64 | uint32(elf.R_MIPS_HI16)<<16,
  1033  		MIPS64 | uint32(elf.R_MIPS_LO16)<<16,
  1034  		MIPS64 | uint32(elf.R_MIPS_GOT16)<<16,
  1035  		MIPS64 | uint32(elf.R_MIPS_GOT_HI16)<<16,
  1036  		MIPS64 | uint32(elf.R_MIPS_GOT_LO16)<<16,
  1037  		MIPS64 | uint32(elf.R_MIPS_GPREL16)<<16,
  1038  		MIPS64 | uint32(elf.R_MIPS_GOT_PAGE)<<16,
  1039  		MIPS64 | uint32(elf.R_MIPS_JALR)<<16,
  1040  		MIPS64 | uint32(elf.R_MIPS_GOT_OFST)<<16,
  1041  		MIPS64 | uint32(elf.R_MIPS_CALL16)<<16,
  1042  		MIPS64 | uint32(elf.R_MIPS_GPREL32)<<16,
  1043  		MIPS64 | uint32(elf.R_MIPS_64)<<16,
  1044  		MIPS64 | uint32(elf.R_MIPS_GOT_DISP)<<16,
  1045  		MIPS64 | uint32(elf.R_MIPS_PC32)<<16:
  1046  		return 4, 4, nil
  1047  
  1048  	// These are informational annotations to assist linker optimizations.
  1049  	case LOONG64 | uint32(elf.R_LARCH_ALIGN)<<16,
  1050  		LOONG64 | uint32(elf.R_LARCH_RELAX)<<16:
  1051  		return 0, 0, nil
  1052  
  1053  	case LOONG64 | uint32(elf.R_LARCH_ADD8)<<16,
  1054  		LOONG64 | uint32(elf.R_LARCH_ADD6)<<16,
  1055  		LOONG64 | uint32(elf.R_LARCH_SUB6)<<16,
  1056  		LOONG64 | uint32(elf.R_LARCH_SUB8)<<16:
  1057  		return 1, 1, nil
  1058  
  1059  	case LOONG64 | uint32(elf.R_LARCH_ADD16)<<16,
  1060  		LOONG64 | uint32(elf.R_LARCH_SUB16)<<16:
  1061  		return 2, 2, nil
  1062  
  1063  	case LOONG64 | uint32(elf.R_LARCH_MARK_LA)<<16,
  1064  		LOONG64 | uint32(elf.R_LARCH_MARK_PCREL)<<16,
  1065  		LOONG64 | uint32(elf.R_LARCH_ADD24)<<16,
  1066  		LOONG64 | uint32(elf.R_LARCH_ADD32)<<16,
  1067  		LOONG64 | uint32(elf.R_LARCH_SUB24)<<16,
  1068  		LOONG64 | uint32(elf.R_LARCH_SUB32)<<16,
  1069  		LOONG64 | uint32(elf.R_LARCH_B16)<<16,
  1070  		LOONG64 | uint32(elf.R_LARCH_B21)<<16,
  1071  		LOONG64 | uint32(elf.R_LARCH_B26)<<16,
  1072  		LOONG64 | uint32(elf.R_LARCH_PCALA_HI20)<<16,
  1073  		LOONG64 | uint32(elf.R_LARCH_PCALA_LO12)<<16,
  1074  		LOONG64 | uint32(elf.R_LARCH_GOT_PC_HI20)<<16,
  1075  		LOONG64 | uint32(elf.R_LARCH_GOT_PC_LO12)<<16,
  1076  		LOONG64 | uint32(elf.R_LARCH_32_PCREL)<<16,
  1077  		LOONG64 | uint32(elf.R_LARCH_PCREL20_S2)<<16:
  1078  		return 4, 4, nil
  1079  
  1080  	case LOONG64 | uint32(elf.R_LARCH_64)<<16,
  1081  		LOONG64 | uint32(elf.R_LARCH_ADD64)<<16,
  1082  		LOONG64 | uint32(elf.R_LARCH_SUB64)<<16,
  1083  		LOONG64 | uint32(elf.R_LARCH_64_PCREL)<<16,
  1084  		LOONG64 | uint32(elf.R_LARCH_CALL36)<<16:
  1085  		return 8, 8, nil
  1086  
  1087  	case S390X | uint32(elf.R_390_8)<<16:
  1088  		return 1, 1, nil
  1089  
  1090  	case PPC64 | uint32(elf.R_PPC64_TOC16)<<16,
  1091  		S390X | uint32(elf.R_390_16)<<16,
  1092  		S390X | uint32(elf.R_390_GOT16)<<16,
  1093  		S390X | uint32(elf.R_390_PC16)<<16,
  1094  		S390X | uint32(elf.R_390_PC16DBL)<<16,
  1095  		S390X | uint32(elf.R_390_PLT16DBL)<<16:
  1096  		return 2, 2, nil
  1097  
  1098  	case ARM | uint32(elf.R_ARM_ABS32)<<16,
  1099  		ARM | uint32(elf.R_ARM_GOT32)<<16,
  1100  		ARM | uint32(elf.R_ARM_PLT32)<<16,
  1101  		ARM | uint32(elf.R_ARM_GOTOFF)<<16,
  1102  		ARM | uint32(elf.R_ARM_GOTPC)<<16,
  1103  		ARM | uint32(elf.R_ARM_THM_PC22)<<16,
  1104  		ARM | uint32(elf.R_ARM_REL32)<<16,
  1105  		ARM | uint32(elf.R_ARM_CALL)<<16,
  1106  		ARM | uint32(elf.R_ARM_V4BX)<<16,
  1107  		ARM | uint32(elf.R_ARM_GOT_PREL)<<16,
  1108  		ARM | uint32(elf.R_ARM_PC24)<<16,
  1109  		ARM | uint32(elf.R_ARM_JUMP24)<<16,
  1110  		ARM64 | uint32(elf.R_AARCH64_CALL26)<<16,
  1111  		ARM64 | uint32(elf.R_AARCH64_ADR_GOT_PAGE)<<16,
  1112  		ARM64 | uint32(elf.R_AARCH64_LD64_GOT_LO12_NC)<<16,
  1113  		ARM64 | uint32(elf.R_AARCH64_ADR_PREL_PG_HI21)<<16,
  1114  		ARM64 | uint32(elf.R_AARCH64_ADD_ABS_LO12_NC)<<16,
  1115  		ARM64 | uint32(elf.R_AARCH64_LDST8_ABS_LO12_NC)<<16,
  1116  		ARM64 | uint32(elf.R_AARCH64_LDST16_ABS_LO12_NC)<<16,
  1117  		ARM64 | uint32(elf.R_AARCH64_LDST32_ABS_LO12_NC)<<16,
  1118  		ARM64 | uint32(elf.R_AARCH64_LDST64_ABS_LO12_NC)<<16,
  1119  		ARM64 | uint32(elf.R_AARCH64_LDST128_ABS_LO12_NC)<<16,
  1120  		ARM64 | uint32(elf.R_AARCH64_PREL32)<<16,
  1121  		ARM64 | uint32(elf.R_AARCH64_JUMP26)<<16,
  1122  		AMD64 | uint32(elf.R_X86_64_PC32)<<16,
  1123  		AMD64 | uint32(elf.R_X86_64_PLT32)<<16,
  1124  		AMD64 | uint32(elf.R_X86_64_GOTPCREL)<<16,
  1125  		AMD64 | uint32(elf.R_X86_64_GOTPCRELX)<<16,
  1126  		AMD64 | uint32(elf.R_X86_64_REX_GOTPCRELX)<<16,
  1127  		I386 | uint32(elf.R_386_32)<<16,
  1128  		I386 | uint32(elf.R_386_PC32)<<16,
  1129  		I386 | uint32(elf.R_386_GOT32)<<16,
  1130  		I386 | uint32(elf.R_386_PLT32)<<16,
  1131  		I386 | uint32(elf.R_386_GOTOFF)<<16,
  1132  		I386 | uint32(elf.R_386_GOTPC)<<16,
  1133  		I386 | uint32(elf.R_386_GOT32X)<<16,
  1134  		PPC64 | uint32(elf.R_PPC64_REL24)<<16,
  1135  		PPC64 | uint32(elf.R_PPC64_REL24_NOTOC)<<16,
  1136  		PPC64 | uint32(elf.R_PPC64_REL24_P9NOTOC)<<16,
  1137  		PPC64 | uint32(elf.R_PPC_REL32)<<16,
  1138  		S390X | uint32(elf.R_390_32)<<16,
  1139  		S390X | uint32(elf.R_390_PC32)<<16,
  1140  		S390X | uint32(elf.R_390_GOT32)<<16,
  1141  		S390X | uint32(elf.R_390_PLT32)<<16,
  1142  		S390X | uint32(elf.R_390_PC32DBL)<<16,
  1143  		S390X | uint32(elf.R_390_PLT32DBL)<<16,
  1144  		S390X | uint32(elf.R_390_GOTPCDBL)<<16,
  1145  		S390X | uint32(elf.R_390_GOTENT)<<16:
  1146  		return 4, 4, nil
  1147  
  1148  	case AMD64 | uint32(elf.R_X86_64_64)<<16,
  1149  		AMD64 | uint32(elf.R_X86_64_PC64)<<16,
  1150  		ARM64 | uint32(elf.R_AARCH64_ABS64)<<16,
  1151  		ARM64 | uint32(elf.R_AARCH64_PREL64)<<16,
  1152  		PPC64 | uint32(elf.R_PPC64_ADDR64)<<16,
  1153  		PPC64 | uint32(elf.R_PPC64_PCREL34)<<16,
  1154  		PPC64 | uint32(elf.R_PPC64_GOT_PCREL34)<<16,
  1155  		PPC64 | uint32(elf.R_PPC64_PLT_PCREL34_NOTOC)<<16,
  1156  		S390X | uint32(elf.R_390_GLOB_DAT)<<16,
  1157  		S390X | uint32(elf.R_390_RELATIVE)<<16,
  1158  		S390X | uint32(elf.R_390_GOTOFF)<<16,
  1159  		S390X | uint32(elf.R_390_GOTPC)<<16,
  1160  		S390X | uint32(elf.R_390_64)<<16,
  1161  		S390X | uint32(elf.R_390_PC64)<<16,
  1162  		S390X | uint32(elf.R_390_GOT64)<<16,
  1163  		S390X | uint32(elf.R_390_PLT64)<<16:
  1164  		return 8, 8, nil
  1165  
  1166  	case RISCV64 | uint32(elf.R_RISCV_SET6)<<16,
  1167  		RISCV64 | uint32(elf.R_RISCV_SUB6)<<16,
  1168  		RISCV64 | uint32(elf.R_RISCV_SET8)<<16,
  1169  		RISCV64 | uint32(elf.R_RISCV_SUB8)<<16:
  1170  		return 1, 1, nil
  1171  
  1172  	case RISCV64 | uint32(elf.R_RISCV_RVC_BRANCH)<<16,
  1173  		RISCV64 | uint32(elf.R_RISCV_RVC_JUMP)<<16,
  1174  		RISCV64 | uint32(elf.R_RISCV_SET16)<<16,
  1175  		RISCV64 | uint32(elf.R_RISCV_SUB16)<<16:
  1176  		return 2, 2, nil
  1177  
  1178  	case RISCV64 | uint32(elf.R_RISCV_32)<<16,
  1179  		RISCV64 | uint32(elf.R_RISCV_BRANCH)<<16,
  1180  		RISCV64 | uint32(elf.R_RISCV_HI20)<<16,
  1181  		RISCV64 | uint32(elf.R_RISCV_LO12_I)<<16,
  1182  		RISCV64 | uint32(elf.R_RISCV_LO12_S)<<16,
  1183  		RISCV64 | uint32(elf.R_RISCV_GOT_HI20)<<16,
  1184  		RISCV64 | uint32(elf.R_RISCV_PCREL_HI20)<<16,
  1185  		RISCV64 | uint32(elf.R_RISCV_PCREL_LO12_I)<<16,
  1186  		RISCV64 | uint32(elf.R_RISCV_PCREL_LO12_S)<<16,
  1187  		RISCV64 | uint32(elf.R_RISCV_ADD32)<<16,
  1188  		RISCV64 | uint32(elf.R_RISCV_SET32)<<16,
  1189  		RISCV64 | uint32(elf.R_RISCV_SUB32)<<16,
  1190  		RISCV64 | uint32(elf.R_RISCV_32_PCREL)<<16,
  1191  		RISCV64 | uint32(elf.R_RISCV_JAL)<<16,
  1192  		RISCV64 | uint32(elf.R_RISCV_RELAX)<<16:
  1193  		return 4, 4, nil
  1194  
  1195  	case RISCV64 | uint32(elf.R_RISCV_64)<<16,
  1196  		RISCV64 | uint32(elf.R_RISCV_CALL)<<16,
  1197  		RISCV64 | uint32(elf.R_RISCV_CALL_PLT)<<16:
  1198  		return 8, 8, nil
  1199  
  1200  	case PPC64 | uint32(elf.R_PPC64_TOC16_LO)<<16,
  1201  		PPC64 | uint32(elf.R_PPC64_TOC16_HI)<<16,
  1202  		PPC64 | uint32(elf.R_PPC64_TOC16_HA)<<16,
  1203  		PPC64 | uint32(elf.R_PPC64_TOC16_DS)<<16,
  1204  		PPC64 | uint32(elf.R_PPC64_TOC16_LO_DS)<<16,
  1205  		PPC64 | uint32(elf.R_PPC64_REL16_LO)<<16,
  1206  		PPC64 | uint32(elf.R_PPC64_REL16_HI)<<16,
  1207  		PPC64 | uint32(elf.R_PPC64_REL16_HA)<<16,
  1208  		PPC64 | uint32(elf.R_PPC64_PLT16_HA)<<16,
  1209  		PPC64 | uint32(elf.R_PPC64_PLT16_LO_DS)<<16:
  1210  		return 2, 4, nil
  1211  
  1212  	// PPC64 inline PLT sequence hint relocations (-fno-plt)
  1213  	// These are informational annotations to assist linker optimizations.
  1214  	case PPC64 | uint32(elf.R_PPC64_PLTSEQ)<<16,
  1215  		PPC64 | uint32(elf.R_PPC64_PLTCALL)<<16,
  1216  		PPC64 | uint32(elf.R_PPC64_PLTCALL_NOTOC)<<16,
  1217  		PPC64 | uint32(elf.R_PPC64_PLTSEQ_NOTOC)<<16:
  1218  		return 0, 0, nil
  1219  
  1220  	}
  1221  }
  1222  
  1223  func cstring(x []byte) string {
  1224  	i := bytes.IndexByte(x, '\x00')
  1225  	if i >= 0 {
  1226  		x = x[:i]
  1227  	}
  1228  	return string(x)
  1229  }
  1230  

View as plain text