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.
6package loadelf
7
8import (
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/*
24Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c
25https://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
31Permission is hereby granted, free of charge, to any person obtaining a copy
32of this software and associated documentation files (the "Software"), to deal
33in the Software without restriction, including without limitation the rights
34to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35copies of the Software, and to permit persons to whom the Software is
36furnished to do so, subject to the following conditions:
37
38The above copyright notice and this permission notice shall be included in
39all copies or substantial portions of the Software.
40
41THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
44AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47THE SOFTWARE.
48*/
49
50const (
51	SHT_ARM_ATTRIBUTES = 0x70000003
52)
53
54type 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
71type 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
98type 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
109const (
110	TagFile               = 1
111	TagCPUName            = 4
112	TagCPURawName         = 5
113	TagCompatibility      = 32
114	TagNoDefaults         = 64
115	TagAlsoCompatibleWith = 65
116	TagABIVFPArgs         = 28
117)
118
119type elfAttribute struct {
120	tag  uint64
121	sval string
122	ival uint64
123}
124
125type elfAttributeList struct {
126	data []byte
127	err  error
128}
129
130func (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
144func (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.
154func (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
177func (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.
190func 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.
244func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, pkg string, length int64, pn string, initEhdrFlags uint32) (textp []loader.Sym, ehdrFlags uint32, err error) {
245	newSym := func(name string, version int) loader.Sym {
246		return l.CreateStaticSym(name)
247	}
248	lookup := l.LookupOrCreateCgoExport
249	errorf := func(str string, args ...interface{}) ([]loader.Sym, uint32, error) {
250		return nil, 0, fmt.Errorf("loadelf: %s: %v", pn, fmt.Sprintf(str, args...))
251	}
252
253	ehdrFlags = initEhdrFlags
254
255	base := f.Offset()
256
257	var hdrbuf [64]byte
258	if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
259		return errorf("malformed elf file: %v", err)
260	}
261
262	var e binary.ByteOrder
263	switch elf.Data(hdrbuf[elf.EI_DATA]) {
264	case elf.ELFDATA2LSB:
265		e = binary.LittleEndian
266
267	case elf.ELFDATA2MSB:
268		e = binary.BigEndian
269
270	default:
271		return errorf("malformed elf file, unknown header")
272	}
273
274	hdr := new(elf.Header32)
275	binary.Read(bytes.NewReader(hdrbuf[:]), e, hdr)
276
277	if string(hdr.Ident[:elf.EI_CLASS]) != elf.ELFMAG {
278		return errorf("malformed elf file, bad header")
279	}
280
281	// read header
282	elfobj := new(ElfObj)
283
284	elfobj.e = e
285	elfobj.f = f
286	elfobj.base = base
287	elfobj.length = length
288	elfobj.name = pn
289
290	is64 := 0
291	class := elf.Class(hdrbuf[elf.EI_CLASS])
292	if class == elf.ELFCLASS64 {
293		is64 = 1
294		hdr := new(elf.Header64)
295		binary.Read(bytes.NewReader(hdrbuf[:]), e, hdr)
296		elfobj.type_ = uint32(hdr.Type)
297		elfobj.machine = uint32(hdr.Machine)
298		elfobj.version = hdr.Version
299		elfobj.entry = hdr.Entry
300		elfobj.phoff = hdr.Phoff
301		elfobj.shoff = hdr.Shoff
302		elfobj.flags = hdr.Flags
303		elfobj.ehsize = uint32(hdr.Ehsize)
304		elfobj.phentsize = uint32(hdr.Phentsize)
305		elfobj.phnum = uint32(hdr.Phnum)
306		elfobj.shentsize = uint32(hdr.Shentsize)
307		elfobj.shnum = uint32(hdr.Shnum)
308		elfobj.shstrndx = uint32(hdr.Shstrndx)
309	} else {
310		elfobj.type_ = uint32(hdr.Type)
311		elfobj.machine = uint32(hdr.Machine)
312		elfobj.version = hdr.Version
313		elfobj.entry = uint64(hdr.Entry)
314		elfobj.phoff = uint64(hdr.Phoff)
315		elfobj.shoff = uint64(hdr.Shoff)
316		elfobj.flags = hdr.Flags
317		elfobj.ehsize = uint32(hdr.Ehsize)
318		elfobj.phentsize = uint32(hdr.Phentsize)
319		elfobj.phnum = uint32(hdr.Phnum)
320		elfobj.shentsize = uint32(hdr.Shentsize)
321		elfobj.shnum = uint32(hdr.Shnum)
322		elfobj.shstrndx = uint32(hdr.Shstrndx)
323	}
324
325	elfobj.is64 = is64
326
327	if v := uint32(hdrbuf[elf.EI_VERSION]); v != elfobj.version {
328		return errorf("malformed elf version: got %d, want %d", v, elfobj.version)
329	}
330
331	if elf.Type(elfobj.type_) != elf.ET_REL {
332		return errorf("elf but not elf relocatable object")
333	}
334
335	mach := elf.Machine(elfobj.machine)
336	switch arch.Family {
337	default:
338		return errorf("elf %s unimplemented", arch.Name)
339
340	case sys.MIPS:
341		if mach != elf.EM_MIPS || class != elf.ELFCLASS32 {
342			return errorf("elf object but not mips")
343		}
344
345	case sys.MIPS64:
346		if mach != elf.EM_MIPS || class != elf.ELFCLASS64 {
347			return errorf("elf object but not mips64")
348		}
349
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 (%s): ignoring symbol in section %d (type %d)", elfsym.sym, i, elfsym.name, 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, addendSize, 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 addendSize == 2 {
774				rAdd = int64(int16(rAdd))
775			}
776			if addendSize == 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
793func 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
802func 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
821func 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// Return the size of the relocated field, and the size of the addend as the first
949// and second values. Note, the addend may be larger than the relocation field in
950// some cases when a relocated value is split across multiple relocations.
951func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) {
952	// TODO(mdempsky): Replace this with a struct-valued switch statement
953	// once golang.org/issue/15164 is fixed or found to not impair cmd/link
954	// performance.
955
956	const (
957		AMD64   = uint32(sys.AMD64)
958		ARM     = uint32(sys.ARM)
959		ARM64   = uint32(sys.ARM64)
960		I386    = uint32(sys.I386)
961		MIPS    = uint32(sys.MIPS)
962		MIPS64  = uint32(sys.MIPS64)
963		PPC64   = uint32(sys.PPC64)
964		RISCV64 = uint32(sys.RISCV64)
965		S390X   = uint32(sys.S390X)
966	)
967
968	switch uint32(arch.Family) | elftype<<16 {
969	default:
970		return 0, 0, fmt.Errorf("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
971
972	case MIPS | uint32(elf.R_MIPS_HI16)<<16,
973		MIPS | uint32(elf.R_MIPS_LO16)<<16,
974		MIPS | uint32(elf.R_MIPS_GOT16)<<16,
975		MIPS | uint32(elf.R_MIPS_GOT_HI16)<<16,
976		MIPS | uint32(elf.R_MIPS_GOT_LO16)<<16,
977		MIPS | uint32(elf.R_MIPS_GPREL16)<<16,
978		MIPS | uint32(elf.R_MIPS_GOT_PAGE)<<16,
979		MIPS | uint32(elf.R_MIPS_JALR)<<16,
980		MIPS | uint32(elf.R_MIPS_GOT_OFST)<<16,
981		MIPS64 | uint32(elf.R_MIPS_HI16)<<16,
982		MIPS64 | uint32(elf.R_MIPS_LO16)<<16,
983		MIPS64 | uint32(elf.R_MIPS_GOT16)<<16,
984		MIPS64 | uint32(elf.R_MIPS_GOT_HI16)<<16,
985		MIPS64 | uint32(elf.R_MIPS_GOT_LO16)<<16,
986		MIPS64 | uint32(elf.R_MIPS_GPREL16)<<16,
987		MIPS64 | uint32(elf.R_MIPS_GOT_PAGE)<<16,
988		MIPS64 | uint32(elf.R_MIPS_JALR)<<16,
989		MIPS64 | uint32(elf.R_MIPS_GOT_OFST)<<16,
990		MIPS64 | uint32(elf.R_MIPS_CALL16)<<16,
991		MIPS64 | uint32(elf.R_MIPS_GPREL32)<<16,
992		MIPS64 | uint32(elf.R_MIPS_64)<<16,
993		MIPS64 | uint32(elf.R_MIPS_GOT_DISP)<<16:
994		return 4, 4, nil
995
996	case S390X | uint32(elf.R_390_8)<<16:
997		return 1, 1, nil
998
999	case PPC64 | uint32(elf.R_PPC64_TOC16)<<16,
1000		S390X | uint32(elf.R_390_16)<<16,
1001		S390X | uint32(elf.R_390_GOT16)<<16,
1002		S390X | uint32(elf.R_390_PC16)<<16,
1003		S390X | uint32(elf.R_390_PC16DBL)<<16,
1004		S390X | uint32(elf.R_390_PLT16DBL)<<16:
1005		return 2, 2, nil
1006
1007	case ARM | uint32(elf.R_ARM_ABS32)<<16,
1008		ARM | uint32(elf.R_ARM_GOT32)<<16,
1009		ARM | uint32(elf.R_ARM_PLT32)<<16,
1010		ARM | uint32(elf.R_ARM_GOTOFF)<<16,
1011		ARM | uint32(elf.R_ARM_GOTPC)<<16,
1012		ARM | uint32(elf.R_ARM_THM_PC22)<<16,
1013		ARM | uint32(elf.R_ARM_REL32)<<16,
1014		ARM | uint32(elf.R_ARM_CALL)<<16,
1015		ARM | uint32(elf.R_ARM_V4BX)<<16,
1016		ARM | uint32(elf.R_ARM_GOT_PREL)<<16,
1017		ARM | uint32(elf.R_ARM_PC24)<<16,
1018		ARM | uint32(elf.R_ARM_JUMP24)<<16,
1019		ARM64 | uint32(elf.R_AARCH64_CALL26)<<16,
1020		ARM64 | uint32(elf.R_AARCH64_ADR_GOT_PAGE)<<16,
1021		ARM64 | uint32(elf.R_AARCH64_LD64_GOT_LO12_NC)<<16,
1022		ARM64 | uint32(elf.R_AARCH64_ADR_PREL_PG_HI21)<<16,
1023		ARM64 | uint32(elf.R_AARCH64_ADD_ABS_LO12_NC)<<16,
1024		ARM64 | uint32(elf.R_AARCH64_LDST8_ABS_LO12_NC)<<16,
1025		ARM64 | uint32(elf.R_AARCH64_LDST16_ABS_LO12_NC)<<16,
1026		ARM64 | uint32(elf.R_AARCH64_LDST32_ABS_LO12_NC)<<16,
1027		ARM64 | uint32(elf.R_AARCH64_LDST64_ABS_LO12_NC)<<16,
1028		ARM64 | uint32(elf.R_AARCH64_LDST128_ABS_LO12_NC)<<16,
1029		ARM64 | uint32(elf.R_AARCH64_PREL32)<<16,
1030		ARM64 | uint32(elf.R_AARCH64_JUMP26)<<16,
1031		AMD64 | uint32(elf.R_X86_64_PC32)<<16,
1032		AMD64 | uint32(elf.R_X86_64_PLT32)<<16,
1033		AMD64 | uint32(elf.R_X86_64_GOTPCREL)<<16,
1034		AMD64 | uint32(elf.R_X86_64_GOTPCRELX)<<16,
1035		AMD64 | uint32(elf.R_X86_64_REX_GOTPCRELX)<<16,
1036		I386 | uint32(elf.R_386_32)<<16,
1037		I386 | uint32(elf.R_386_PC32)<<16,
1038		I386 | uint32(elf.R_386_GOT32)<<16,
1039		I386 | uint32(elf.R_386_PLT32)<<16,
1040		I386 | uint32(elf.R_386_GOTOFF)<<16,
1041		I386 | uint32(elf.R_386_GOTPC)<<16,
1042		I386 | uint32(elf.R_386_GOT32X)<<16,
1043		PPC64 | uint32(elf.R_PPC64_REL24)<<16,
1044		PPC64 | uint32(elf.R_PPC_REL32)<<16,
1045		S390X | uint32(elf.R_390_32)<<16,
1046		S390X | uint32(elf.R_390_PC32)<<16,
1047		S390X | uint32(elf.R_390_GOT32)<<16,
1048		S390X | uint32(elf.R_390_PLT32)<<16,
1049		S390X | uint32(elf.R_390_PC32DBL)<<16,
1050		S390X | uint32(elf.R_390_PLT32DBL)<<16,
1051		S390X | uint32(elf.R_390_GOTPCDBL)<<16,
1052		S390X | uint32(elf.R_390_GOTENT)<<16:
1053		return 4, 4, nil
1054
1055	case AMD64 | uint32(elf.R_X86_64_64)<<16,
1056		AMD64 | uint32(elf.R_X86_64_PC64)<<16,
1057		ARM64 | uint32(elf.R_AARCH64_ABS64)<<16,
1058		ARM64 | uint32(elf.R_AARCH64_PREL64)<<16,
1059		PPC64 | uint32(elf.R_PPC64_ADDR64)<<16,
1060		S390X | uint32(elf.R_390_GLOB_DAT)<<16,
1061		S390X | uint32(elf.R_390_RELATIVE)<<16,
1062		S390X | uint32(elf.R_390_GOTOFF)<<16,
1063		S390X | uint32(elf.R_390_GOTPC)<<16,
1064		S390X | uint32(elf.R_390_64)<<16,
1065		S390X | uint32(elf.R_390_PC64)<<16,
1066		S390X | uint32(elf.R_390_GOT64)<<16,
1067		S390X | uint32(elf.R_390_PLT64)<<16:
1068		return 8, 8, nil
1069
1070	case RISCV64 | uint32(elf.R_RISCV_RVC_BRANCH)<<16,
1071		RISCV64 | uint32(elf.R_RISCV_RVC_JUMP)<<16:
1072		return 2, 2, nil
1073
1074	case RISCV64 | uint32(elf.R_RISCV_32)<<16,
1075		RISCV64 | uint32(elf.R_RISCV_BRANCH)<<16,
1076		RISCV64 | uint32(elf.R_RISCV_HI20)<<16,
1077		RISCV64 | uint32(elf.R_RISCV_LO12_I)<<16,
1078		RISCV64 | uint32(elf.R_RISCV_LO12_S)<<16,
1079		RISCV64 | uint32(elf.R_RISCV_GOT_HI20)<<16,
1080		RISCV64 | uint32(elf.R_RISCV_PCREL_HI20)<<16,
1081		RISCV64 | uint32(elf.R_RISCV_PCREL_LO12_I)<<16,
1082		RISCV64 | uint32(elf.R_RISCV_PCREL_LO12_S)<<16,
1083		RISCV64 | uint32(elf.R_RISCV_RELAX)<<16:
1084		return 4, 4, nil
1085
1086	case RISCV64 | uint32(elf.R_RISCV_64)<<16,
1087		RISCV64 | uint32(elf.R_RISCV_CALL)<<16,
1088		RISCV64 | uint32(elf.R_RISCV_CALL_PLT)<<16:
1089		return 8, 8, nil
1090
1091	case PPC64 | uint32(elf.R_PPC64_TOC16_LO)<<16,
1092		PPC64 | uint32(elf.R_PPC64_TOC16_HI)<<16,
1093		PPC64 | uint32(elf.R_PPC64_TOC16_HA)<<16,
1094		PPC64 | uint32(elf.R_PPC64_TOC16_DS)<<16,
1095		PPC64 | uint32(elf.R_PPC64_TOC16_LO_DS)<<16,
1096		PPC64 | uint32(elf.R_PPC64_REL16_LO)<<16,
1097		PPC64 | uint32(elf.R_PPC64_REL16_HI)<<16,
1098		PPC64 | uint32(elf.R_PPC64_REL16_HA)<<16:
1099		return 2, 4, nil
1100	}
1101}
1102
1103func cstring(x []byte) string {
1104	i := bytes.IndexByte(x, '\x00')
1105	if i >= 0 {
1106		x = x[:i]
1107	}
1108	return string(x)
1109}
1110