...
Run Format

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

Documentation: cmd/internal/objfile

  // Copyright 2013 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  // Parsing of ELF executables (Linux, FreeBSD, and so on).
  
  package objfile
  
  import (
  	"debug/dwarf"
  	"debug/elf"
  	"encoding/binary"
  	"fmt"
  	"os"
  )
  
  type elfFile struct {
  	elf *elf.File
  }
  
  func openElf(r *os.File) (rawFile, error) {
  	f, err := elf.NewFile(r)
  	if err != nil {
  		return nil, err
  	}
  	return &elfFile{f}, nil
  }
  
  func (f *elfFile) symbols() ([]Sym, error) {
  	elfSyms, err := f.elf.Symbols()
  	if err != nil {
  		return nil, err
  	}
  
  	var syms []Sym
  	for _, s := range elfSyms {
  		sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'}
  		switch s.Section {
  		case elf.SHN_UNDEF:
  			sym.Code = 'U'
  		case elf.SHN_COMMON:
  			sym.Code = 'B'
  		default:
  			i := int(s.Section)
  			if i < 0 || i >= len(f.elf.Sections) {
  				break
  			}
  			sect := f.elf.Sections[i]
  			switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) {
  			case elf.SHF_ALLOC | elf.SHF_EXECINSTR:
  				sym.Code = 'T'
  			case elf.SHF_ALLOC:
  				sym.Code = 'R'
  			case elf.SHF_ALLOC | elf.SHF_WRITE:
  				sym.Code = 'D'
  			}
  		}
  		if elf.ST_BIND(s.Info) == elf.STB_LOCAL {
  			sym.Code += 'a' - 'A'
  		}
  		syms = append(syms, sym)
  	}
  
  	return syms, nil
  }
  
  func (f *elfFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) {
  	if sect := f.elf.Section(".text"); sect != nil {
  		textStart = sect.Addr
  	}
  	if sect := f.elf.Section(".gosymtab"); sect != nil {
  		if symtab, err = sect.Data(); err != nil {
  			return 0, nil, nil, err
  		}
  	}
  	if sect := f.elf.Section(".gopclntab"); sect != nil {
  		if pclntab, err = sect.Data(); err != nil {
  			return 0, nil, nil, err
  		}
  	}
  	return textStart, symtab, pclntab, nil
  }
  
  func (f *elfFile) text() (textStart uint64, text []byte, err error) {
  	sect := f.elf.Section(".text")
  	if sect == nil {
  		return 0, nil, fmt.Errorf("text section not found")
  	}
  	textStart = sect.Addr
  	text, err = sect.Data()
  	return
  }
  
  func (f *elfFile) goarch() string {
  	switch f.elf.Machine {
  	case elf.EM_386:
  		return "386"
  	case elf.EM_X86_64:
  		return "amd64"
  	case elf.EM_ARM:
  		return "arm"
  	case elf.EM_PPC64:
  		if f.elf.ByteOrder == binary.LittleEndian {
  			return "ppc64le"
  		}
  		return "ppc64"
  	case elf.EM_S390:
  		return "s390x"
  	}
  	return ""
  }
  
  func (f *elfFile) loadAddress() (uint64, error) {
  	for _, p := range f.elf.Progs {
  		if p.Type == elf.PT_LOAD {
  			return p.Vaddr, nil
  		}
  	}
  	return 0, fmt.Errorf("unknown load address")
  }
  
  func (f *elfFile) dwarf() (*dwarf.Data, error) {
  	return f.elf.DWARF()
  }
  

View as plain text