...

Source file src/cmd/internal/objfile/elf.go

     1	// Copyright 2013 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	// Parsing of ELF executables (Linux, FreeBSD, and so on).
     6	
     7	package objfile
     8	
     9	import (
    10		"debug/dwarf"
    11		"debug/elf"
    12		"encoding/binary"
    13		"fmt"
    14		"io"
    15	)
    16	
    17	type elfFile struct {
    18		elf *elf.File
    19	}
    20	
    21	func openElf(r io.ReaderAt) (rawFile, error) {
    22		f, err := elf.NewFile(r)
    23		if err != nil {
    24			return nil, err
    25		}
    26		return &elfFile{f}, nil
    27	}
    28	
    29	func (f *elfFile) symbols() ([]Sym, error) {
    30		elfSyms, err := f.elf.Symbols()
    31		if err != nil {
    32			return nil, err
    33		}
    34	
    35		var syms []Sym
    36		for _, s := range elfSyms {
    37			sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'}
    38			switch s.Section {
    39			case elf.SHN_UNDEF:
    40				sym.Code = 'U'
    41			case elf.SHN_COMMON:
    42				sym.Code = 'B'
    43			default:
    44				i := int(s.Section)
    45				if i < 0 || i >= len(f.elf.Sections) {
    46					break
    47				}
    48				sect := f.elf.Sections[i]
    49				switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) {
    50				case elf.SHF_ALLOC | elf.SHF_EXECINSTR:
    51					sym.Code = 'T'
    52				case elf.SHF_ALLOC:
    53					sym.Code = 'R'
    54				case elf.SHF_ALLOC | elf.SHF_WRITE:
    55					sym.Code = 'D'
    56				}
    57			}
    58			if elf.ST_BIND(s.Info) == elf.STB_LOCAL {
    59				sym.Code += 'a' - 'A'
    60			}
    61			syms = append(syms, sym)
    62		}
    63	
    64		return syms, nil
    65	}
    66	
    67	func (f *elfFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) {
    68		if sect := f.elf.Section(".text"); sect != nil {
    69			textStart = sect.Addr
    70		}
    71		if sect := f.elf.Section(".gosymtab"); sect != nil {
    72			if symtab, err = sect.Data(); err != nil {
    73				return 0, nil, nil, err
    74			}
    75		}
    76		if sect := f.elf.Section(".gopclntab"); sect != nil {
    77			if pclntab, err = sect.Data(); err != nil {
    78				return 0, nil, nil, err
    79			}
    80		}
    81		return textStart, symtab, pclntab, nil
    82	}
    83	
    84	func (f *elfFile) text() (textStart uint64, text []byte, err error) {
    85		sect := f.elf.Section(".text")
    86		if sect == nil {
    87			return 0, nil, fmt.Errorf("text section not found")
    88		}
    89		textStart = sect.Addr
    90		text, err = sect.Data()
    91		return
    92	}
    93	
    94	func (f *elfFile) goarch() string {
    95		switch f.elf.Machine {
    96		case elf.EM_386:
    97			return "386"
    98		case elf.EM_X86_64:
    99			return "amd64"
   100		case elf.EM_ARM:
   101			return "arm"
   102		case elf.EM_AARCH64:
   103			return "arm64"
   104		case elf.EM_PPC64:
   105			if f.elf.ByteOrder == binary.LittleEndian {
   106				return "ppc64le"
   107			}
   108			return "ppc64"
   109		case elf.EM_S390:
   110			return "s390x"
   111		}
   112		return ""
   113	}
   114	
   115	func (f *elfFile) loadAddress() (uint64, error) {
   116		for _, p := range f.elf.Progs {
   117			if p.Type == elf.PT_LOAD && p.Flags&elf.PF_X != 0 {
   118				return p.Vaddr, nil
   119			}
   120		}
   121		return 0, fmt.Errorf("unknown load address")
   122	}
   123	
   124	func (f *elfFile) dwarf() (*dwarf.Data, error) {
   125		return f.elf.DWARF()
   126	}
   127	

View as plain text