1 // Copyright 2017 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 func Load(l *loader.Loader, arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string, flags uint32) ([]*sym.Symbol, uint32, error) {
456 newSym := func(name string, version int) *sym.Symbol {
457 return l.Create(name, syms)
459 lookup := func(name string, version int) *sym.Symbol {
460 return l.LookupOrCreate(name, version, syms)
462 return load(arch, syms.IncVersion(), newSym, lookup, f, pkg, length, pn, flags)
465 func LoadOld(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string, flags uint32) ([]*sym.Symbol, uint32, error) {
466 return load(arch, syms.IncVersion(), syms.Newsym, syms.Lookup, f, pkg, length, pn, flags)
469 type lookupFunc func(string, int) *sym.Symbol
471 // load loads the ELF file pn from f.
472 // Symbols are written into syms, and a slice of the text symbols is returned.
474 // On ARM systems, Load will attempt to determine what ELF header flags to
475 // emit by scanning the attributes in the ELF file being loaded. The
476 // parameter initEhdrFlags contains the current header flags for the output
477 // object, and the returned ehdrFlags contains what this Load function computes.
478 // TODO: find a better place for this logic.
479 func load(arch *sys.Arch, localSymVersion int, newSym, lookup lookupFunc, f *bio.Reader, pkg string, length int64, pn string, initEhdrFlags uint32) (textp []*sym.Symbol, ehdrFlags uint32, err error) {
480 errorf := func(str string, args ...interface{}) ([]*sym.Symbol, uint32, error) {
481 return nil, 0, fmt.Errorf("loadelf: %s: %v", pn, fmt.Sprintf(str, args...))
487 if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
488 return errorf("malformed elf file: %v", err)
490 hdr := new(ElfHdrBytes)
491 binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
492 if string(hdr.Ident[:4]) != "\x7FELF" {
493 return errorf("malformed elf file, bad header")
495 var e binary.ByteOrder
496 switch hdr.Ident[5] {
498 e = binary.LittleEndian
504 return errorf("malformed elf file, unknown header")
508 elfobj := new(ElfObj)
513 elfobj.length = length
517 if hdr.Ident[4] == ElfClass64 {
519 hdr := new(ElfHdrBytes64)
520 binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
521 elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
522 elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
523 elfobj.version = e.Uint32(hdr.Version[:])
524 elfobj.phoff = e.Uint64(hdr.Phoff[:])
525 elfobj.shoff = e.Uint64(hdr.Shoff[:])
526 elfobj.flags = e.Uint32(hdr.Flags[:])
527 elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
528 elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
529 elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
530 elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
531 elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
532 elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
534 elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
535 elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
536 elfobj.version = e.Uint32(hdr.Version[:])
537 elfobj.entry = uint64(e.Uint32(hdr.Entry[:]))
538 elfobj.phoff = uint64(e.Uint32(hdr.Phoff[:]))
539 elfobj.shoff = uint64(e.Uint32(hdr.Shoff[:]))
540 elfobj.flags = e.Uint32(hdr.Flags[:])
541 elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
542 elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
543 elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
544 elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
545 elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
546 elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
551 if v := uint32(hdr.Ident[6]); v != elfobj.version {
552 return errorf("malformed elf version: got %d, want %d", v, elfobj.version)
555 if e.Uint16(hdr.Type[:]) != ElfTypeRelocatable {
556 return errorf("elf but not elf relocatable object")
561 return errorf("elf %s unimplemented", arch.Name)
564 if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass32 {
565 return errorf("elf object but not mips")
569 if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 {
570 return errorf("elf object but not mips64")
574 if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 {
575 return errorf("elf object but not arm")
579 if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 {
580 return errorf("elf object but not amd64")
584 if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 {
585 return errorf("elf object but not arm64")
589 if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 {
590 return errorf("elf object but not 386")
594 if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 {
595 return errorf("elf object but not ppc64")
599 if elfobj.machine != ElfMachS390 || hdr.Ident[4] != ElfClass64 {
600 return errorf("elf object but not s390x")
604 // load section list into memory.
605 elfobj.sect = make([]ElfSect, elfobj.shnum)
607 elfobj.nsect = uint(elfobj.shnum)
608 for i := 0; uint(i) < elfobj.nsect; i++ {
609 f.MustSeek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0)
610 sect := &elfobj.sect[i]
614 if err := binary.Read(f, e, &b); err != nil {
615 return errorf("malformed elf file: %v", err)
618 sect.nameoff = e.Uint32(b.Name[:])
619 sect.type_ = e.Uint32(b.Type[:])
620 sect.flags = e.Uint64(b.Flags[:])
621 sect.addr = e.Uint64(b.Addr[:])
622 sect.off = e.Uint64(b.Off[:])
623 sect.size = e.Uint64(b.Size[:])
624 sect.link = e.Uint32(b.Link[:])
625 sect.info = e.Uint32(b.Info[:])
626 sect.align = e.Uint64(b.Align[:])
627 sect.entsize = e.Uint64(b.Entsize[:])
631 if err := binary.Read(f, e, &b); err != nil {
632 return errorf("malformed elf file: %v", err)
635 sect.nameoff = e.Uint32(b.Name[:])
636 sect.type_ = e.Uint32(b.Type[:])
637 sect.flags = uint64(e.Uint32(b.Flags[:]))
638 sect.addr = uint64(e.Uint32(b.Addr[:]))
639 sect.off = uint64(e.Uint32(b.Off[:]))
640 sect.size = uint64(e.Uint32(b.Size[:]))
641 sect.link = e.Uint32(b.Link[:])
642 sect.info = e.Uint32(b.Info[:])
643 sect.align = uint64(e.Uint32(b.Align[:]))
644 sect.entsize = uint64(e.Uint32(b.Entsize[:]))
648 // read section string table and translate names
649 if elfobj.shstrndx >= uint32(elfobj.nsect) {
650 return errorf("malformed elf file: shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect)
653 sect := &elfobj.sect[elfobj.shstrndx]
654 if err := elfmap(elfobj, sect); err != nil {
655 return errorf("malformed elf file: %v", err)
657 for i := 0; uint(i) < elfobj.nsect; i++ {
658 if elfobj.sect[i].nameoff != 0 {
659 elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:])
663 // load string table for symbols into memory.
664 elfobj.symtab = section(elfobj, ".symtab")
666 if elfobj.symtab == nil {
667 // our work is done here - no symbols means nothing can refer to this file
671 if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) {
672 return errorf("elf object has symbol table with invalid string table link")
675 elfobj.symstr = &elfobj.sect[elfobj.symtab.link]
677 elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE)
679 elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE)
682 if err := elfmap(elfobj, elfobj.symtab); err != nil {
683 return errorf("malformed elf file: %v", err)
685 if err := elfmap(elfobj, elfobj.symstr); err != nil {
686 return errorf("malformed elf file: %v", err)
689 // load text and data segments into memory.
690 // they are not as small as the section lists, but we'll need
691 // the memory anyway for the symbol images, so we might
692 // as well use one large chunk.
694 // create symbols for elfmapped sections
695 sectsymNames := make(map[string]bool)
697 for i := 0; uint(i) < elfobj.nsect; i++ {
698 sect = &elfobj.sect[i]
699 if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" {
700 if err := elfmap(elfobj, sect); err != nil {
701 return errorf("%s: malformed elf file: %v", pn, err)
703 // We assume the soft-float ABI unless we see a tag indicating otherwise.
704 if initEhdrFlags == 0x5000002 {
705 ehdrFlags = 0x5000202
707 ehdrFlags = initEhdrFlags
709 found, newEhdrFlags, err := parseArmAttributes(e, sect.base[:sect.size])
711 // TODO(dfc) should this return an error?
712 log.Printf("%s: %v", pn, err)
715 ehdrFlags = newEhdrFlags
718 if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 {
721 if sect.type_ != ElfSectNobits {
722 if err := elfmap(elfobj, sect); err != nil {
723 return errorf("%s: malformed elf file: %v", pn, err)
727 name := fmt.Sprintf("%s(%s)", pkg, sect.name)
728 for sectsymNames[name] {
730 name = fmt.Sprintf("%s(%s%d)", pkg, sect.name, counter)
732 sectsymNames[name] = true
734 s := lookup(name, localSymVersion)
736 switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) {
738 return errorf("%s: unexpected flags for ELF section %s", pn, sect.name)
740 case ElfSectFlagAlloc:
743 case ElfSectFlagAlloc + ElfSectFlagWrite:
744 if sect.type_ == ElfSectNobits {
745 s.Type = sym.SNOPTRBSS
747 s.Type = sym.SNOPTRDATA
750 case ElfSectFlagAlloc + ElfSectFlagExec:
754 if sect.name == ".got" || sect.name == ".toc" {
757 if sect.type_ == ElfSectProgbits {
759 s.P = s.P[:sect.size]
762 s.Size = int64(sect.size)
763 s.Align = int32(sect.align)
767 // enter sub-symbols into symbol table.
768 // symbol 0 is the null symbol.
769 symbols := make([]*sym.Symbol, elfobj.nsymtab)
771 for i := 1; i < elfobj.nsymtab; i++ {
773 if err := readelfsym(newSym, lookup, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
774 return errorf("%s: malformed elf file: %v", pn, err)
776 symbols[i] = elfsym.sym
777 if elfsym.type_ != ElfSymTypeFunc && elfsym.type_ != ElfSymTypeObject && elfsym.type_ != ElfSymTypeNone && elfsym.type_ != ElfSymTypeCommon {
780 if elfsym.shndx == ElfSymShnCommon || elfsym.type_ == ElfSymTypeCommon {
782 if uint64(s.Size) < elfsym.size {
783 s.Size = int64(elfsym.size)
785 if s.Type == 0 || s.Type == sym.SXREF {
786 s.Type = sym.SNOPTRBSS
791 if uint(elfsym.shndx) >= elfobj.nsect || elfsym.shndx == 0 {
795 // even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
796 if elfsym.sym == nil {
799 sect = &elfobj.sect[elfsym.shndx]
801 if strings.HasPrefix(elfsym.name, ".Linfo_string") { // clang does this
805 if elfsym.name == "" && elfsym.type_ == 0 && sect.name == ".debug_str" {
806 // This reportedly happens with clang 3.7 on ARM.
811 if strings.HasPrefix(elfsym.name, "$d") && elfsym.type_ == 0 && sect.name == ".debug_frame" {
812 // "$d" is a marker, not a real symbol.
813 // This happens with gcc on ARM64.
814 // See https://sourceware.org/bugzilla/show_bug.cgi?id=21809
818 if strings.HasPrefix(elfsym.name, ".LASF") { // gcc on s390x does this
821 return errorf("%v: sym#%d: ignoring symbol in section %d (type %d)", elfsym.sym, i, elfsym.shndx, elfsym.type_)
826 if s.Attr.DuplicateOK() {
829 return errorf("duplicate symbol reference: %s in both %s and %s", s.Name, s.Outer.Name, sect.sym.Name)
834 s.Type = sect.sym.Type
835 s.Attr |= sym.AttrSubSymbol
836 if !s.Attr.CgoExportDynamic() {
837 s.SetDynimplib("") // satisfy dynimport
839 s.Value = int64(elfsym.value)
840 s.Size = int64(elfsym.size)
842 if sect.sym.Type == sym.STEXT {
843 if s.Attr.External() && !s.Attr.DuplicateOK() {
844 return errorf("%v: duplicate symbol definition", s)
846 s.Attr |= sym.AttrExternal
849 if elfobj.machine == ElfMachPower64 {
850 flag := int(elfsym.other) >> 5
851 if 2 <= flag && flag <= 6 {
852 s.SetLocalentry(1 << uint(flag-2))
853 } else if flag == 7 {
854 return errorf("%v: invalid sym.other 0x%x", s, elfsym.other)
859 // Sort outer lists by address, adding to textp.
860 // This keeps textp in increasing address order.
861 for i := uint(0); i < elfobj.nsect; i++ {
862 s := elfobj.sect[i].sym
867 s.Sub = sym.SortSub(s.Sub)
869 if s.Type == sym.STEXT {
871 return errorf("symbol %s listed multiple times", s.Name)
873 s.Attr |= sym.AttrOnList
874 textp = append(textp, s)
875 for s = s.Sub; s != nil; s = s.Sub {
877 return errorf("symbol %s listed multiple times", s.Name)
879 s.Attr |= sym.AttrOnList
880 textp = append(textp, s)
886 for i := uint(0); i < elfobj.nsect; i++ {
887 rsect := &elfobj.sect[i]
888 if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel {
891 if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
894 sect = &elfobj.sect[rsect.info]
895 if err := elfmap(elfobj, rsect); err != nil {
896 return errorf("malformed elf file: %v", err)
899 if rsect.type_ == ElfSectRela {
902 n := int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
903 r := make([]sym.Reloc, n)
905 for j := 0; j < n; j++ {
911 rp.Off = int32(e.Uint64(p))
922 rp.Off = int32(e.Uint32(p))
925 info = uint64(e.Uint32(p))
926 info = info>>8<<32 | info&0xff // convert to 64-bit info
929 add = uint64(e.Uint32(p))
934 if info&0xffffffff == 0 { // skip R_*_NONE relocation
940 if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol
944 if err := readelfsym(newSym, lookup, arch, elfobj, int(info>>32), &elfsym, 0, 0); err != nil {
945 return errorf("malformed elf file: %v", err)
947 elfsym.sym = symbols[info>>32]
948 if elfsym.sym == nil {
949 return errorf("malformed elf file: %s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", sect.sym.Name, j, int(info>>32), elfsym.name, elfsym.shndx, elfsym.type_)
955 rp.Type = objabi.ElfRelocOffset + objabi.RelocType(info)
956 rp.Siz, err = relSize(arch, pn, uint32(info))
963 // load addend from image
965 rp.Add = int64(e.Uint32(sect.base[rp.Off:]))
966 } else if rp.Siz == 8 {
967 rp.Add = int64(e.Uint64(sect.base[rp.Off:]))
969 return errorf("invalid rela size %d", rp.Siz)
974 rp.Add = int64(int16(rp.Add))
977 rp.Add = int64(int32(rp.Add))
981 //print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add);
982 sort.Sort(sym.RelocByOff(r[:n]))
990 return textp, ehdrFlags, nil
993 func section(elfobj *ElfObj, name string) *ElfSect {
994 for i := 0; uint(i) < elfobj.nsect; i++ {
995 if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
996 return &elfobj.sect[i]
1002 func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
1003 if sect.base != nil {
1007 if sect.off+sect.size > uint64(elfobj.length) {
1008 err = fmt.Errorf("elf section past end of file")
1012 sect.base = make([]byte, sect.size)
1013 elfobj.f.MustSeek(int64(uint64(elfobj.base)+sect.off), 0)
1014 if _, err := io.ReadFull(elfobj.f, sect.base); err != nil {
1015 return fmt.Errorf("short read: %v", err)
1021 func readelfsym(newSym, lookup lookupFunc, arch *sys.Arch, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
1022 if i >= elfobj.nsymtab || i < 0 {
1023 err = fmt.Errorf("invalid elf symbol index")
1028 return fmt.Errorf("readym: read null symbol!")
1031 if elfobj.is64 != 0 {
1032 b := new(ElfSymBytes64)
1033 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b)
1034 elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
1035 elfsym.value = elfobj.e.Uint64(b.Value[:])
1036 elfsym.size = elfobj.e.Uint64(b.Size[:])
1037 elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
1038 elfsym.bind = b.Info >> 4
1039 elfsym.type_ = b.Info & 0xf
1040 elfsym.other = b.Other
1042 b := new(ElfSymBytes)
1043 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b)
1044 elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
1045 elfsym.value = uint64(elfobj.e.Uint32(b.Value[:]))
1046 elfsym.size = uint64(elfobj.e.Uint32(b.Size[:]))
1047 elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
1048 elfsym.bind = b.Info >> 4
1049 elfsym.type_ = b.Info & 0xf
1050 elfsym.other = b.Other
1054 if elfsym.name == "_GLOBAL_OFFSET_TABLE_" {
1055 elfsym.name = ".got"
1057 if elfsym.name == ".TOC." {
1058 // Magic symbol on ppc64. Will be set to this object
1059 // file's .got+0x8000.
1060 elfsym.bind = ElfSymBindLocal
1063 switch elfsym.type_ {
1064 case ElfSymTypeSection:
1065 s = elfobj.sect[elfsym.shndx].sym
1067 case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone, ElfSymTypeCommon:
1068 switch elfsym.bind {
1069 case ElfSymBindGlobal:
1071 s = lookup(elfsym.name, 0)
1073 // for global scoped hidden symbols we should insert it into
1074 // symbol hash table, but mark them as hidden.
1075 // __i686.get_pc_thunk.bx is allowed to be duplicated, to
1076 // workaround that we set dupok.
1077 // TODO(minux): correctly handle __i686.get_pc_thunk.bx without
1078 // set dupok generally. See https://golang.org/cl/5823055
1079 // comment #5 for details.
1080 if s != nil && elfsym.other == 2 {
1081 s.Attr |= sym.AttrDuplicateOK | sym.AttrVisibilityHidden
1085 case ElfSymBindLocal:
1086 if (arch.Family == sys.ARM || arch.Family == sys.ARM64) && (strings.HasPrefix(elfsym.name, "$a") || strings.HasPrefix(elfsym.name, "$d") || strings.HasPrefix(elfsym.name, "$x")) {
1087 // binutils for arm and arm64 generate these mapping
1088 // symbols, ignore these
1092 if elfsym.name == ".TOC." {
1093 // We need to be able to look this up,
1094 // so put it in the hash table.
1096 s = lookup(elfsym.name, localSymVersion)
1097 s.Attr |= sym.AttrVisibilityHidden
1104 // local names and hidden global names are unique
1105 // and should only be referenced by their index, not name, so we
1106 // don't bother to add them into the hash table
1107 // FIXME: pass empty string here for name? This would
1108 // reduce mem use, but also (possibly) make it harder
1109 // to debug problems.
1110 s = newSym(elfsym.name, localSymVersion)
1112 s.Attr |= sym.AttrVisibilityHidden
1115 case ElfSymBindWeak:
1117 s = lookup(elfsym.name, 0)
1118 if elfsym.other == 2 {
1119 s.Attr |= sym.AttrVisibilityHidden
1122 // Allow weak symbols to be duplicated when already defined.
1124 s.Attr |= sym.AttrDuplicateOK
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 != nil && s.Type == 0 && !s.Attr.VisibilityHidden() && elfsym.type_ != ElfSymTypeSection {
1144 func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, error) {
1145 // TODO(mdempsky): Replace this with a struct-valued switch statement
1146 // once golang.org/issue/15164 is fixed or found to not impair cmd/link
1150 AMD64 = uint32(sys.AMD64)
1151 ARM = uint32(sys.ARM)
1152 ARM64 = uint32(sys.ARM64)
1153 I386 = uint32(sys.I386)
1154 PPC64 = uint32(sys.PPC64)
1155 S390X = uint32(sys.S390X)
1158 switch uint32(arch.Family) | elftype<<16 {
1160 return 0, fmt.Errorf("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
1162 case S390X | uint32(elf.R_390_8)<<16:
1165 case PPC64 | uint32(elf.R_PPC64_TOC16)<<16,
1166 PPC64 | uint32(elf.R_PPC64_TOC16_LO)<<16,
1167 PPC64 | uint32(elf.R_PPC64_TOC16_HI)<<16,
1168 PPC64 | uint32(elf.R_PPC64_TOC16_HA)<<16,
1169 PPC64 | uint32(elf.R_PPC64_TOC16_DS)<<16,
1170 PPC64 | uint32(elf.R_PPC64_TOC16_LO_DS)<<16,
1171 PPC64 | uint32(elf.R_PPC64_REL16_LO)<<16,
1172 PPC64 | uint32(elf.R_PPC64_REL16_HI)<<16,
1173 PPC64 | uint32(elf.R_PPC64_REL16_HA)<<16,
1174 S390X | uint32(elf.R_390_16)<<16,
1175 S390X | uint32(elf.R_390_GOT16)<<16,
1176 S390X | uint32(elf.R_390_PC16)<<16,
1177 S390X | uint32(elf.R_390_PC16DBL)<<16,
1178 S390X | uint32(elf.R_390_PLT16DBL)<<16:
1181 case ARM | uint32(elf.R_ARM_ABS32)<<16,
1182 ARM | uint32(elf.R_ARM_GOT32)<<16,
1183 ARM | uint32(elf.R_ARM_PLT32)<<16,
1184 ARM | uint32(elf.R_ARM_GOTOFF)<<16,
1185 ARM | uint32(elf.R_ARM_GOTPC)<<16,
1186 ARM | uint32(elf.R_ARM_THM_PC22)<<16,
1187 ARM | uint32(elf.R_ARM_REL32)<<16,
1188 ARM | uint32(elf.R_ARM_CALL)<<16,
1189 ARM | uint32(elf.R_ARM_V4BX)<<16,
1190 ARM | uint32(elf.R_ARM_GOT_PREL)<<16,
1191 ARM | uint32(elf.R_ARM_PC24)<<16,
1192 ARM | uint32(elf.R_ARM_JUMP24)<<16,
1193 ARM64 | uint32(elf.R_AARCH64_CALL26)<<16,
1194 ARM64 | uint32(elf.R_AARCH64_ADR_GOT_PAGE)<<16,
1195 ARM64 | uint32(elf.R_AARCH64_LD64_GOT_LO12_NC)<<16,
1196 ARM64 | uint32(elf.R_AARCH64_ADR_PREL_PG_HI21)<<16,
1197 ARM64 | uint32(elf.R_AARCH64_ADD_ABS_LO12_NC)<<16,
1198 ARM64 | uint32(elf.R_AARCH64_LDST8_ABS_LO12_NC)<<16,
1199 ARM64 | uint32(elf.R_AARCH64_LDST32_ABS_LO12_NC)<<16,
1200 ARM64 | uint32(elf.R_AARCH64_LDST64_ABS_LO12_NC)<<16,
1201 ARM64 | uint32(elf.R_AARCH64_LDST128_ABS_LO12_NC)<<16,
1202 ARM64 | uint32(elf.R_AARCH64_PREL32)<<16,
1203 ARM64 | uint32(elf.R_AARCH64_JUMP26)<<16,
1204 AMD64 | uint32(elf.R_X86_64_PC32)<<16,
1205 AMD64 | uint32(elf.R_X86_64_PLT32)<<16,
1206 AMD64 | uint32(elf.R_X86_64_GOTPCREL)<<16,
1207 AMD64 | uint32(elf.R_X86_64_GOTPCRELX)<<16,
1208 AMD64 | uint32(elf.R_X86_64_REX_GOTPCRELX)<<16,
1209 I386 | uint32(elf.R_386_32)<<16,
1210 I386 | uint32(elf.R_386_PC32)<<16,
1211 I386 | uint32(elf.R_386_GOT32)<<16,
1212 I386 | uint32(elf.R_386_PLT32)<<16,
1213 I386 | uint32(elf.R_386_GOTOFF)<<16,
1214 I386 | uint32(elf.R_386_GOTPC)<<16,
1215 I386 | uint32(elf.R_386_GOT32X)<<16,
1216 PPC64 | uint32(elf.R_PPC64_REL24)<<16,
1217 PPC64 | uint32(elf.R_PPC_REL32)<<16,
1218 S390X | uint32(elf.R_390_32)<<16,
1219 S390X | uint32(elf.R_390_PC32)<<16,
1220 S390X | uint32(elf.R_390_GOT32)<<16,
1221 S390X | uint32(elf.R_390_PLT32)<<16,
1222 S390X | uint32(elf.R_390_PC32DBL)<<16,
1223 S390X | uint32(elf.R_390_PLT32DBL)<<16,
1224 S390X | uint32(elf.R_390_GOTPCDBL)<<16,
1225 S390X | uint32(elf.R_390_GOTENT)<<16:
1228 case AMD64 | uint32(elf.R_X86_64_64)<<16,
1229 AMD64 | uint32(elf.R_X86_64_PC64)<<16,
1230 ARM64 | uint32(elf.R_AARCH64_ABS64)<<16,
1231 ARM64 | uint32(elf.R_AARCH64_PREL64)<<16,
1232 PPC64 | uint32(elf.R_PPC64_ADDR64)<<16,
1233 S390X | uint32(elf.R_390_GLOB_DAT)<<16,
1234 S390X | uint32(elf.R_390_RELATIVE)<<16,
1235 S390X | uint32(elf.R_390_GOTOFF)<<16,
1236 S390X | uint32(elf.R_390_GOTPC)<<16,
1237 S390X | uint32(elf.R_390_64)<<16,
1238 S390X | uint32(elf.R_390_PC64)<<16,
1239 S390X | uint32(elf.R_390_GOT64)<<16,
1240 S390X | uint32(elf.R_390_PLT64)<<16:
1245 func cstring(x []byte) string {
1246 i := bytes.IndexByte(x, '\x00')