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.
5 // Package loadelf implements an ELF file reader.
13 "cmd/link/internal/loader"
14 "cmd/link/internal/sym"
25 Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c
26 http://code.swtch.com/plan9port/src/tip/src/libmach/
28 Copyright © 2004 Russ Cox.
29 Portions Copyright © 2008-2010 Google Inc.
30 Portions Copyright © 2010 The Go Authors.
32 Permission is hereby granted, free of charge, to any person obtaining a copy
33 of this software and associated documentation files (the "Software"), to deal
34 in the Software without restriction, including without limitation the rights
35 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
36 copies of the Software, and to permit persons to whom the Software is
37 furnished to do so, subject to the following conditions:
39 The above copyright notice and this permission notice shall be included in
40 all copies or substantial portions of the Software.
42 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
47 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
64 ElfTypeRelocatable = 1
66 ElfTypeSharedObject = 3
84 ElfMachSparc32Plus = 18
131 ElfSectFlagWrite = 0x1
132 ElfSectFlagAlloc = 0x2
133 ElfSectFlagExec = 0x4
146 ElfSymTypeSection = 3
154 ElfSymShnAbs = 0xFFF1
155 ElfSymShnCommon = 0xFFF2
166 ElfProgFlagExec = 0x1
167 ElfProgFlagWrite = 0x2
168 ElfProgFlagRead = 0x4
175 ElfNotePrTaskstruct = 4
177 ElfNotePrXfpreg = 0x46e62b7f
180 // TODO(crawshaw): de-duplicate with cmd/link/internal/ld/elf.go.
185 SHT_ARM_ATTRIBUTES = 0x70000003
188 type ElfHdrBytes struct {
205 type ElfSectBytes struct {
218 type ElfProgBytes struct {
221 type ElfSymBytes struct {
230 type ElfHdrBytes64 struct {
247 type ElfSectBytes64 struct {
260 type ElfProgBytes64 struct {
263 type ElfSymBytes64 struct {
272 type ElfSect struct {
290 base int64 // offset in f where ELF begins
291 length int64 // length of ELF
326 var ElfMagic = [4]uint8{0x7F, 'E', 'L', 'F'}
332 TagCompatibility = 32
334 TagAlsoCompatibleWith = 65
338 type elfAttribute struct {
344 type elfAttributeList struct {
349 func (a *elfAttributeList) string() string {
353 nul := bytes.IndexByte(a.data, 0)
358 s := string(a.data[:nul])
359 a.data = a.data[nul+1:]
363 func (a *elfAttributeList) uleb128() uint64 {
367 v, size := binary.Uvarint(a.data)
368 a.data = a.data[size:]
372 // Read an elfAttribute from the list following the rules used on ARM systems.
373 func (a *elfAttributeList) armAttr() elfAttribute {
374 attr := elfAttribute{tag: a.uleb128()}
376 case attr.tag == TagCompatibility:
377 attr.ival = a.uleb128()
378 attr.sval = a.string()
380 case attr.tag == 64: // Tag_nodefaults has no argument
382 case attr.tag == 65: // Tag_also_compatible_with
383 // Not really, but we don't actually care about this tag.
384 attr.sval = a.string()
386 // Tag with string argument
387 case attr.tag == TagCPUName || attr.tag == TagCPURawName || (attr.tag >= 32 && attr.tag&1 != 0):
388 attr.sval = a.string()
390 default: // Tag with integer argument
391 attr.ival = a.uleb128()
396 func (a *elfAttributeList) done() bool {
397 if a.err != nil || len(a.data) == 0 {
403 // Look for the attribute that indicates the object uses the hard-float ABI (a
404 // file-level attribute with tag Tag_VFP_arch and value 1). Unfortunately the
405 // format used means that we have to parse all of the file-level attributes to
406 // find the one we are looking for. This format is slightly documented in "ELF
407 // for the ARM Architecture" but mostly this is derived from reading the source
408 // to gold and readelf.
409 func parseArmAttributes(e binary.ByteOrder, data []byte) (found bool, ehdrFlags uint32, err error) {
412 return false, 0, fmt.Errorf(".ARM.attributes has unexpected format %c\n", data[0])
416 sectionlength := e.Uint32(data)
417 sectiondata := data[4:sectionlength]
418 data = data[sectionlength:]
420 nulIndex := bytes.IndexByte(sectiondata, 0)
422 return false, 0, fmt.Errorf("corrupt .ARM.attributes (section name not NUL-terminated)\n")
424 name := string(sectiondata[:nulIndex])
425 sectiondata = sectiondata[nulIndex+1:]
430 for len(sectiondata) != 0 {
431 subsectiontag, sz := binary.Uvarint(sectiondata)
432 subsectionsize := e.Uint32(sectiondata[sz:])
433 subsectiondata := sectiondata[sz+4 : subsectionsize]
434 sectiondata = sectiondata[subsectionsize:]
436 if subsectiontag != TagFile {
439 attrList := elfAttributeList{data: subsectiondata}
440 for !attrList.done() {
441 attr := attrList.armAttr()
442 if attr.tag == TagABIVFPArgs && attr.ival == 1 {
444 ehdrFlags = 0x5000402 // has entry point, Version5 EABI, hard-float ABI
447 if attrList.err != nil {
448 return false, 0, fmt.Errorf("could not parse .ARM.attributes\n")
452 return found, ehdrFlags, nil
455 // Load loads the ELF file pn from f.
456 // Symbols are installed into the loader, and a slice of the text symbols is returned.
458 // On ARM systems, Load will attempt to determine what ELF header flags to
459 // emit by scanning the attributes in the ELF file being loaded. The
460 // parameter initEhdrFlags contains the current header flags for the output
461 // object, and the returned ehdrFlags contains what this Load function computes.
462 // TODO: find a better place for this logic.
463 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) {
464 newSym := func(name string, version int) loader.Sym {
465 return l.CreateExtSym(name)
467 lookup := func(name string, version int) loader.Sym {
468 return l.LookupOrCreateSym(name, version)
470 errorf := func(str string, args ...interface{}) ([]loader.Sym, uint32, error) {
471 return nil, 0, fmt.Errorf("loadelf: %s: %v", pn, fmt.Sprintf(str, args...))
477 if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
478 return errorf("malformed elf file: %v", err)
480 hdr := new(ElfHdrBytes)
481 binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
482 if string(hdr.Ident[:4]) != "\x7FELF" {
483 return errorf("malformed elf file, bad header")
485 var e binary.ByteOrder
486 switch hdr.Ident[5] {
488 e = binary.LittleEndian
494 return errorf("malformed elf file, unknown header")
498 elfobj := new(ElfObj)
503 elfobj.length = length
507 if hdr.Ident[4] == ElfClass64 {
509 hdr := new(ElfHdrBytes64)
510 binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
511 elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
512 elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
513 elfobj.version = e.Uint32(hdr.Version[:])
514 elfobj.phoff = e.Uint64(hdr.Phoff[:])
515 elfobj.shoff = e.Uint64(hdr.Shoff[:])
516 elfobj.flags = e.Uint32(hdr.Flags[:])
517 elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
518 elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
519 elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
520 elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
521 elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
522 elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
524 elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
525 elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
526 elfobj.version = e.Uint32(hdr.Version[:])
527 elfobj.entry = uint64(e.Uint32(hdr.Entry[:]))
528 elfobj.phoff = uint64(e.Uint32(hdr.Phoff[:]))
529 elfobj.shoff = uint64(e.Uint32(hdr.Shoff[:]))
530 elfobj.flags = e.Uint32(hdr.Flags[:])
531 elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
532 elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
533 elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
534 elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
535 elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
536 elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
541 if v := uint32(hdr.Ident[6]); v != elfobj.version {
542 return errorf("malformed elf version: got %d, want %d", v, elfobj.version)
545 if e.Uint16(hdr.Type[:]) != ElfTypeRelocatable {
546 return errorf("elf but not elf relocatable object")
551 return errorf("elf %s unimplemented", arch.Name)
554 if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass32 {
555 return errorf("elf object but not mips")
559 if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 {
560 return errorf("elf object but not mips64")
564 if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 {
565 return errorf("elf object but not arm")
569 if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 {
570 return errorf("elf object but not amd64")
574 if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 {
575 return errorf("elf object but not arm64")
579 if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 {
580 return errorf("elf object but not 386")
584 if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 {
585 return errorf("elf object but not ppc64")
589 if elfobj.machine != ElfMachS390 || hdr.Ident[4] != ElfClass64 {
590 return errorf("elf object but not s390x")
594 // load section list into memory.
595 elfobj.sect = make([]ElfSect, elfobj.shnum)
597 elfobj.nsect = uint(elfobj.shnum)
598 for i := 0; uint(i) < elfobj.nsect; i++ {
599 f.MustSeek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0)
600 sect := &elfobj.sect[i]
604 if err := binary.Read(f, e, &b); err != nil {
605 return errorf("malformed elf file: %v", err)
608 sect.nameoff = e.Uint32(b.Name[:])
609 sect.type_ = e.Uint32(b.Type[:])
610 sect.flags = e.Uint64(b.Flags[:])
611 sect.addr = e.Uint64(b.Addr[:])
612 sect.off = e.Uint64(b.Off[:])
613 sect.size = e.Uint64(b.Size[:])
614 sect.link = e.Uint32(b.Link[:])
615 sect.info = e.Uint32(b.Info[:])
616 sect.align = e.Uint64(b.Align[:])
617 sect.entsize = e.Uint64(b.Entsize[:])
621 if err := binary.Read(f, e, &b); err != nil {
622 return errorf("malformed elf file: %v", err)
625 sect.nameoff = e.Uint32(b.Name[:])
626 sect.type_ = e.Uint32(b.Type[:])
627 sect.flags = uint64(e.Uint32(b.Flags[:]))
628 sect.addr = uint64(e.Uint32(b.Addr[:]))
629 sect.off = uint64(e.Uint32(b.Off[:]))
630 sect.size = uint64(e.Uint32(b.Size[:]))
631 sect.link = e.Uint32(b.Link[:])
632 sect.info = e.Uint32(b.Info[:])
633 sect.align = uint64(e.Uint32(b.Align[:]))
634 sect.entsize = uint64(e.Uint32(b.Entsize[:]))
638 // read section string table and translate names
639 if elfobj.shstrndx >= uint32(elfobj.nsect) {
640 return errorf("malformed elf file: shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect)
643 sect := &elfobj.sect[elfobj.shstrndx]
644 if err := elfmap(elfobj, sect); err != nil {
645 return errorf("malformed elf file: %v", err)
647 for i := 0; uint(i) < elfobj.nsect; i++ {
648 if elfobj.sect[i].nameoff != 0 {
649 elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:])
653 // load string table for symbols into memory.
654 elfobj.symtab = section(elfobj, ".symtab")
656 if elfobj.symtab == nil {
657 // our work is done here - no symbols means nothing can refer to this file
661 if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) {
662 return errorf("elf object has symbol table with invalid string table link")
665 elfobj.symstr = &elfobj.sect[elfobj.symtab.link]
667 elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE)
669 elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE)
672 if err := elfmap(elfobj, elfobj.symtab); err != nil {
673 return errorf("malformed elf file: %v", err)
675 if err := elfmap(elfobj, elfobj.symstr); err != nil {
676 return errorf("malformed elf file: %v", err)
679 // load text and data segments into memory.
680 // they are not as small as the section lists, but we'll need
681 // the memory anyway for the symbol images, so we might
682 // as well use one large chunk.
684 // create symbols for elfmapped sections
685 sectsymNames := make(map[string]bool)
687 for i := 0; uint(i) < elfobj.nsect; i++ {
688 sect = &elfobj.sect[i]
689 if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" {
690 if err := elfmap(elfobj, sect); err != nil {
691 return errorf("%s: malformed elf file: %v", pn, err)
693 // We assume the soft-float ABI unless we see a tag indicating otherwise.
694 if initEhdrFlags == 0x5000002 {
695 ehdrFlags = 0x5000202
697 ehdrFlags = initEhdrFlags
699 found, newEhdrFlags, err := parseArmAttributes(e, sect.base[:sect.size])
701 // TODO(dfc) should this return an error?
702 log.Printf("%s: %v", pn, err)
705 ehdrFlags = newEhdrFlags
708 if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 {
711 if sect.type_ != ElfSectNobits {
712 if err := elfmap(elfobj, sect); err != nil {
713 return errorf("%s: malformed elf file: %v", pn, err)
717 name := fmt.Sprintf("%s(%s)", pkg, sect.name)
718 for sectsymNames[name] {
720 name = fmt.Sprintf("%s(%s%d)", pkg, sect.name, counter)
722 sectsymNames[name] = true
724 sb, _ := l.MakeSymbolUpdater(lookup(name, localSymVersion))
726 switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) {
728 return errorf("%s: unexpected flags for ELF section %s", pn, sect.name)
730 case ElfSectFlagAlloc:
731 sb.SetType(sym.SRODATA)
733 case ElfSectFlagAlloc + ElfSectFlagWrite:
734 if sect.type_ == ElfSectNobits {
735 sb.SetType(sym.SNOPTRBSS)
737 sb.SetType(sym.SNOPTRDATA)
740 case ElfSectFlagAlloc + ElfSectFlagExec:
741 sb.SetType(sym.STEXT)
744 if sect.name == ".got" || sect.name == ".toc" {
745 sb.SetType(sym.SELFGOT)
747 if sect.type_ == ElfSectProgbits {
748 sb.SetData(sect.base[:sect.size])
751 sb.SetSize(int64(sect.size))
752 sb.SetAlign(int32(sect.align))
757 // enter sub-symbols into symbol table.
758 // symbol 0 is the null symbol.
759 symbols := make([]loader.Sym, elfobj.nsymtab)
761 for i := 1; i < elfobj.nsymtab; i++ {
763 if err := readelfsym(newSym, lookup, l, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
764 return errorf("%s: malformed elf file: %v", pn, err)
766 symbols[i] = elfsym.sym
767 if elfsym.type_ != ElfSymTypeFunc && elfsym.type_ != ElfSymTypeObject && elfsym.type_ != ElfSymTypeNone && elfsym.type_ != ElfSymTypeCommon {
770 if elfsym.shndx == ElfSymShnCommon || elfsym.type_ == ElfSymTypeCommon {
771 sb, ns := l.MakeSymbolUpdater(elfsym.sym)
772 if uint64(sb.Size()) < elfsym.size {
773 sb.SetSize(int64(elfsym.size))
775 if sb.Type() == 0 || sb.Type() == sym.SXREF {
776 sb.SetType(sym.SNOPTRBSS)
783 if uint(elfsym.shndx) >= elfobj.nsect || elfsym.shndx == 0 {
787 // even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
791 sect = &elfobj.sect[elfsym.shndx]
793 if strings.HasPrefix(elfsym.name, ".Linfo_string") { // clang does this
797 if elfsym.name == "" && elfsym.type_ == 0 && sect.name == ".debug_str" {
798 // This reportedly happens with clang 3.7 on ARM.
803 if strings.HasPrefix(elfsym.name, "$d") && elfsym.type_ == 0 && sect.name == ".debug_frame" {
804 // "$d" is a marker, not a real symbol.
805 // This happens with gcc on ARM64.
806 // See https://sourceware.org/bugzilla/show_bug.cgi?id=21809
810 if strings.HasPrefix(elfsym.name, ".LASF") { // gcc on s390x does this
813 return errorf("%v: sym#%d: ignoring symbol in section %d (type %d)", elfsym.sym, i, elfsym.shndx, elfsym.type_)
817 if l.OuterSym(s) != 0 {
818 if l.AttrDuplicateOK(s) {
821 return errorf("duplicate symbol reference: %s in both %s and %s",
822 l.SymName(s), l.SymName(l.OuterSym(s)), l.SymName(sect.sym))
825 sectsb, _ := l.MakeSymbolUpdater(sect.sym)
826 sb, _ := l.MakeSymbolUpdater(s)
828 sb.SetType(sectsb.Type())
830 if !l.AttrCgoExportDynamic(s) {
831 sb.SetDynimplib("") // satisfy dynimport
833 sb.SetValue(int64(elfsym.value))
834 sb.SetSize(int64(elfsym.size))
835 if sectsb.Type() == sym.STEXT {
836 if l.AttrExternal(s) && !l.AttrDuplicateOK(s) {
837 return errorf("%s: duplicate symbol definition", sb.Name())
839 l.SetAttrExternal(s, true)
842 if elfobj.machine == ElfMachPower64 {
843 flag := int(elfsym.other) >> 5
844 if 2 <= flag && flag <= 6 {
845 l.SetSymLocalentry(s, 1<<uint(flag-2))
846 } else if flag == 7 {
847 return errorf("%s: invalid sym.other 0x%x", sb.Name(), elfsym.other)
852 // Sort outer lists by address, adding to textp.
853 // This keeps textp in increasing address order.
854 for i := uint(0); i < elfobj.nsect; i++ {
855 s := elfobj.sect[i].sym
859 sb, _ := l.MakeSymbolUpdater(s)
861 if l.SubSym(s) != 0 {
864 if sb.Type() == sym.STEXT {
866 return errorf("symbol %s listed multiple times",
869 l.SetAttrOnList(s, true)
870 textp = append(textp, s)
871 for ss := l.SubSym(s); ss != 0; ss = l.SubSym(ss) {
872 if l.AttrOnList(ss) {
873 return errorf("symbol %s listed multiple times",
876 l.SetAttrOnList(ss, true)
877 textp = append(textp, ss)
883 for i := uint(0); i < elfobj.nsect; i++ {
884 rsect := &elfobj.sect[i]
885 if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel {
888 if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
891 sect = &elfobj.sect[rsect.info]
892 if err := elfmap(elfobj, rsect); err != nil {
893 return errorf("malformed elf file: %v", err)
896 if rsect.type_ == ElfSectRela {
899 n := int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
900 r := make([]loader.Reloc, n)
902 for j := 0; j < n; j++ {
908 rp.Off = int32(e.Uint64(p))
919 rp.Off = int32(e.Uint32(p))
922 info = uint64(e.Uint32(p))
923 info = info>>8<<32 | info&0xff // convert to 64-bit info
926 add = uint64(e.Uint32(p))
931 if info&0xffffffff == 0 { // skip R_*_NONE relocation
937 if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol
941 if err := readelfsym(newSym, lookup, l, arch, elfobj, int(info>>32), &elfsym, 0, 0); err != nil {
942 return errorf("malformed elf file: %v", err)
944 elfsym.sym = symbols[info>>32]
946 return errorf("malformed elf file: %s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", l.SymName(sect.sym), j, int(info>>32), elfsym.name, elfsym.shndx, elfsym.type_)
952 rp.Type = objabi.ElfRelocOffset + objabi.RelocType(info)
953 rp.Size, err = relSize(arch, pn, uint32(info))
960 // load addend from image
962 rp.Add = int64(e.Uint32(sect.base[rp.Off:]))
963 } else if rp.Size == 8 {
964 rp.Add = int64(e.Uint64(sect.base[rp.Off:]))
966 return errorf("invalid rela size %d", rp.Size)
971 rp.Add = int64(int16(rp.Add))
974 rp.Add = int64(int32(rp.Add))
978 //print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add);
979 sort.Sort(loader.RelocByOff(r[:n]))
982 sb, _ := l.MakeSymbolUpdater(sect.sym)
987 return textp, ehdrFlags, nil
990 func section(elfobj *ElfObj, name string) *ElfSect {
991 for i := 0; uint(i) < elfobj.nsect; i++ {
992 if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
993 return &elfobj.sect[i]
999 func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
1000 if sect.base != nil {
1004 if sect.off+sect.size > uint64(elfobj.length) {
1005 err = fmt.Errorf("elf section past end of file")
1009 sect.base = make([]byte, sect.size)
1010 elfobj.f.MustSeek(int64(uint64(elfobj.base)+sect.off), 0)
1011 if _, err := io.ReadFull(elfobj.f, sect.base); err != nil {
1012 return fmt.Errorf("short read: %v", err)
1018 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) {
1019 if i >= elfobj.nsymtab || i < 0 {
1020 err = fmt.Errorf("invalid elf symbol index")
1025 return fmt.Errorf("readym: read null symbol!")
1028 if elfobj.is64 != 0 {
1029 b := new(ElfSymBytes64)
1030 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b)
1031 elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
1032 elfsym.value = elfobj.e.Uint64(b.Value[:])
1033 elfsym.size = elfobj.e.Uint64(b.Size[:])
1034 elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
1035 elfsym.bind = b.Info >> 4
1036 elfsym.type_ = b.Info & 0xf
1037 elfsym.other = b.Other
1039 b := new(ElfSymBytes)
1040 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b)
1041 elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
1042 elfsym.value = uint64(elfobj.e.Uint32(b.Value[:]))
1043 elfsym.size = uint64(elfobj.e.Uint32(b.Size[:]))
1044 elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
1045 elfsym.bind = b.Info >> 4
1046 elfsym.type_ = b.Info & 0xf
1047 elfsym.other = b.Other
1052 if elfsym.name == "_GLOBAL_OFFSET_TABLE_" {
1053 elfsym.name = ".got"
1055 if elfsym.name == ".TOC." {
1056 // Magic symbol on ppc64. Will be set to this object
1057 // file's .got+0x8000.
1058 elfsym.bind = ElfSymBindLocal
1061 switch elfsym.type_ {
1062 case ElfSymTypeSection:
1063 s = elfobj.sect[elfsym.shndx].sym
1065 case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone, ElfSymTypeCommon:
1066 switch elfsym.bind {
1067 case ElfSymBindGlobal:
1069 s = lookup(elfsym.name, 0)
1071 // for global scoped hidden symbols we should insert it into
1072 // symbol hash table, but mark them as hidden.
1073 // __i686.get_pc_thunk.bx is allowed to be duplicated, to
1074 // workaround that we set dupok.
1075 // TODO(minux): correctly handle __i686.get_pc_thunk.bx without
1076 // set dupok generally. See https://golang.org/cl/5823055
1077 // comment #5 for details.
1078 if s != 0 && elfsym.other == 2 {
1079 if !l.IsExternal(s) {
1080 _, s = l.MakeSymbolUpdater(s)
1082 l.SetAttrDuplicateOK(s, true)
1083 l.SetAttrVisibilityHidden(s, true)
1087 case ElfSymBindLocal:
1088 if (arch.Family == sys.ARM || arch.Family == sys.ARM64) && (strings.HasPrefix(elfsym.name, "$a") || strings.HasPrefix(elfsym.name, "$d") || strings.HasPrefix(elfsym.name, "$x")) {
1089 // binutils for arm and arm64 generate these mapping
1090 // symbols, ignore these
1094 if elfsym.name == ".TOC." {
1095 // We need to be able to look this up,
1096 // so put it in the hash table.
1098 s = lookup(elfsym.name, localSymVersion)
1099 l.SetAttrVisibilityHidden(s, true)
1105 // local names and hidden global names are unique
1106 // and should only be referenced by their index, not name, so we
1107 // don't bother to add them into the hash table
1108 // FIXME: pass empty string here for name? This would
1109 // reduce mem use, but also (possibly) make it harder
1110 // to debug problems.
1111 s = newSym(elfsym.name, localSymVersion)
1112 l.SetAttrVisibilityHidden(s, true)
1115 case ElfSymBindWeak:
1117 s = lookup(elfsym.name, 0)
1118 if elfsym.other == 2 {
1119 l.SetAttrVisibilityHidden(s, true)
1122 // Allow weak symbols to be duplicated when already defined.
1123 if l.OuterSym(s) != 0 {
1124 l.SetAttrDuplicateOK(s, true)
1129 err = fmt.Errorf("%s: invalid symbol binding %d", elfsym.name, elfsym.bind)
1134 // TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
1135 // sense and should be removed when someone has thought about it properly.
1136 if s != 0 && l.SymType(s) == 0 && !l.AttrVisibilityHidden(s) && elfsym.type_ != ElfSymTypeSection {
1137 sb, _ := l.MakeSymbolUpdater(s)
1138 sb.SetType(sym.SXREF)
1145 func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, error) {
1146 // TODO(mdempsky): Replace this with a struct-valued switch statement
1147 // once golang.org/issue/15164 is fixed or found to not impair cmd/link
1151 AMD64 = uint32(sys.AMD64)
1152 ARM = uint32(sys.ARM)
1153 ARM64 = uint32(sys.ARM64)
1154 I386 = uint32(sys.I386)
1155 PPC64 = uint32(sys.PPC64)
1156 S390X = uint32(sys.S390X)
1159 switch uint32(arch.Family) | elftype<<16 {
1161 return 0, fmt.Errorf("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
1163 case S390X | uint32(elf.R_390_8)<<16:
1166 case PPC64 | uint32(elf.R_PPC64_TOC16)<<16,
1167 PPC64 | uint32(elf.R_PPC64_TOC16_LO)<<16,
1168 PPC64 | uint32(elf.R_PPC64_TOC16_HI)<<16,
1169 PPC64 | uint32(elf.R_PPC64_TOC16_HA)<<16,
1170 PPC64 | uint32(elf.R_PPC64_TOC16_DS)<<16,
1171 PPC64 | uint32(elf.R_PPC64_TOC16_LO_DS)<<16,
1172 PPC64 | uint32(elf.R_PPC64_REL16_LO)<<16,
1173 PPC64 | uint32(elf.R_PPC64_REL16_HI)<<16,
1174 PPC64 | uint32(elf.R_PPC64_REL16_HA)<<16,
1175 S390X | uint32(elf.R_390_16)<<16,
1176 S390X | uint32(elf.R_390_GOT16)<<16,
1177 S390X | uint32(elf.R_390_PC16)<<16,
1178 S390X | uint32(elf.R_390_PC16DBL)<<16,
1179 S390X | uint32(elf.R_390_PLT16DBL)<<16:
1182 case ARM | uint32(elf.R_ARM_ABS32)<<16,
1183 ARM | uint32(elf.R_ARM_GOT32)<<16,
1184 ARM | uint32(elf.R_ARM_PLT32)<<16,
1185 ARM | uint32(elf.R_ARM_GOTOFF)<<16,
1186 ARM | uint32(elf.R_ARM_GOTPC)<<16,
1187 ARM | uint32(elf.R_ARM_THM_PC22)<<16,
1188 ARM | uint32(elf.R_ARM_REL32)<<16,
1189 ARM | uint32(elf.R_ARM_CALL)<<16,
1190 ARM | uint32(elf.R_ARM_V4BX)<<16,
1191 ARM | uint32(elf.R_ARM_GOT_PREL)<<16,
1192 ARM | uint32(elf.R_ARM_PC24)<<16,
1193 ARM | uint32(elf.R_ARM_JUMP24)<<16,
1194 ARM64 | uint32(elf.R_AARCH64_CALL26)<<16,
1195 ARM64 | uint32(elf.R_AARCH64_ADR_GOT_PAGE)<<16,
1196 ARM64 | uint32(elf.R_AARCH64_LD64_GOT_LO12_NC)<<16,
1197 ARM64 | uint32(elf.R_AARCH64_ADR_PREL_PG_HI21)<<16,
1198 ARM64 | uint32(elf.R_AARCH64_ADD_ABS_LO12_NC)<<16,
1199 ARM64 | uint32(elf.R_AARCH64_LDST8_ABS_LO12_NC)<<16,
1200 ARM64 | uint32(elf.R_AARCH64_LDST32_ABS_LO12_NC)<<16,
1201 ARM64 | uint32(elf.R_AARCH64_LDST64_ABS_LO12_NC)<<16,
1202 ARM64 | uint32(elf.R_AARCH64_LDST128_ABS_LO12_NC)<<16,
1203 ARM64 | uint32(elf.R_AARCH64_PREL32)<<16,
1204 ARM64 | uint32(elf.R_AARCH64_JUMP26)<<16,
1205 AMD64 | uint32(elf.R_X86_64_PC32)<<16,
1206 AMD64 | uint32(elf.R_X86_64_PLT32)<<16,
1207 AMD64 | uint32(elf.R_X86_64_GOTPCREL)<<16,
1208 AMD64 | uint32(elf.R_X86_64_GOTPCRELX)<<16,
1209 AMD64 | uint32(elf.R_X86_64_REX_GOTPCRELX)<<16,
1210 I386 | uint32(elf.R_386_32)<<16,
1211 I386 | uint32(elf.R_386_PC32)<<16,
1212 I386 | uint32(elf.R_386_GOT32)<<16,
1213 I386 | uint32(elf.R_386_PLT32)<<16,
1214 I386 | uint32(elf.R_386_GOTOFF)<<16,
1215 I386 | uint32(elf.R_386_GOTPC)<<16,
1216 I386 | uint32(elf.R_386_GOT32X)<<16,
1217 PPC64 | uint32(elf.R_PPC64_REL24)<<16,
1218 PPC64 | uint32(elf.R_PPC_REL32)<<16,
1219 S390X | uint32(elf.R_390_32)<<16,
1220 S390X | uint32(elf.R_390_PC32)<<16,
1221 S390X | uint32(elf.R_390_GOT32)<<16,
1222 S390X | uint32(elf.R_390_PLT32)<<16,
1223 S390X | uint32(elf.R_390_PC32DBL)<<16,
1224 S390X | uint32(elf.R_390_PLT32DBL)<<16,
1225 S390X | uint32(elf.R_390_GOTPCDBL)<<16,
1226 S390X | uint32(elf.R_390_GOTENT)<<16:
1229 case AMD64 | uint32(elf.R_X86_64_64)<<16,
1230 AMD64 | uint32(elf.R_X86_64_PC64)<<16,
1231 ARM64 | uint32(elf.R_AARCH64_ABS64)<<16,
1232 ARM64 | uint32(elf.R_AARCH64_PREL64)<<16,
1233 PPC64 | uint32(elf.R_PPC64_ADDR64)<<16,
1234 S390X | uint32(elf.R_390_GLOB_DAT)<<16,
1235 S390X | uint32(elf.R_390_RELATIVE)<<16,
1236 S390X | uint32(elf.R_390_GOTOFF)<<16,
1237 S390X | uint32(elf.R_390_GOTPC)<<16,
1238 S390X | uint32(elf.R_390_64)<<16,
1239 S390X | uint32(elf.R_390_PC64)<<16,
1240 S390X | uint32(elf.R_390_GOT64)<<16,
1241 S390X | uint32(elf.R_390_PLT64)<<16:
1246 func cstring(x []byte) string {
1247 i := bytes.IndexByte(x, '\x00')