github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/cmd/internal/objfile/elf.go (about)

     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/elf"
    11  	"fmt"
    12  	"os"
    13  )
    14  
    15  type elfFile struct {
    16  	elf *elf.File
    17  }
    18  
    19  func openElf(r *os.File) (rawFile, error) {
    20  	f, err := elf.NewFile(r)
    21  	if err != nil {
    22  		return nil, err
    23  	}
    24  	return &elfFile{f}, nil
    25  }
    26  
    27  func (f *elfFile) symbols() ([]Sym, error) {
    28  	elfSyms, err := f.elf.Symbols()
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  
    33  	var syms []Sym
    34  	for _, s := range elfSyms {
    35  		sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'}
    36  		switch s.Section {
    37  		case elf.SHN_UNDEF:
    38  			sym.Code = 'U'
    39  		case elf.SHN_COMMON:
    40  			sym.Code = 'B'
    41  		default:
    42  			i := int(s.Section)
    43  			if i < 0 || i >= len(f.elf.Sections) {
    44  				break
    45  			}
    46  			sect := f.elf.Sections[i]
    47  			switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) {
    48  			case elf.SHF_ALLOC | elf.SHF_EXECINSTR:
    49  				sym.Code = 'T'
    50  			case elf.SHF_ALLOC:
    51  				sym.Code = 'R'
    52  			case elf.SHF_ALLOC | elf.SHF_WRITE:
    53  				sym.Code = 'D'
    54  			}
    55  		}
    56  		if elf.ST_BIND(s.Info) == elf.STB_LOCAL {
    57  			sym.Code += 'a' - 'A'
    58  		}
    59  		syms = append(syms, sym)
    60  	}
    61  
    62  	return syms, nil
    63  }
    64  
    65  func (f *elfFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) {
    66  	if sect := f.elf.Section(".text"); sect != nil {
    67  		textStart = sect.Addr
    68  	}
    69  	if sect := f.elf.Section(".gosymtab"); sect != nil {
    70  		if symtab, err = sect.Data(); err != nil {
    71  			return 0, nil, nil, err
    72  		}
    73  	}
    74  	if sect := f.elf.Section(".gopclntab"); sect != nil {
    75  		if pclntab, err = sect.Data(); err != nil {
    76  			return 0, nil, nil, err
    77  		}
    78  	}
    79  	return textStart, symtab, pclntab, nil
    80  }
    81  
    82  func (f *elfFile) text() (textStart uint64, text []byte, err error) {
    83  	sect := f.elf.Section(".text")
    84  	if sect == nil {
    85  		return 0, nil, fmt.Errorf("text section not found")
    86  	}
    87  	textStart = sect.Addr
    88  	text, err = sect.Data()
    89  	return
    90  }
    91  
    92  func (f *elfFile) goarch() string {
    93  	switch f.elf.Machine {
    94  	case elf.EM_386:
    95  		return "386"
    96  	case elf.EM_X86_64:
    97  		return "amd64"
    98  	case elf.EM_ARM:
    99  		return "arm"
   100  	case elf.EM_PPC64:
   101  		return "ppc64"
   102  	}
   103  	return ""
   104  }