github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/debug/elf/file.go (about)

     1  // Copyright 2009 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  // Package elf implements access to ELF object files.
     6  package elf
     7  
     8  import (
     9  	"bytes"
    10  	"debug/dwarf"
    11  	"encoding/binary"
    12  	"errors"
    13  	"fmt"
    14  	"io"
    15  	"os"
    16  	"strings"
    17  )
    18  
    19  // TODO: error reporting detail
    20  
    21  /*
    22   * Internal ELF representation
    23   */
    24  
    25  // A FileHeader represents an ELF file header.
    26  type FileHeader struct {
    27  	Class      Class
    28  	Data       Data
    29  	Version    Version
    30  	OSABI      OSABI
    31  	ABIVersion uint8
    32  	ByteOrder  binary.ByteOrder
    33  	Type       Type
    34  	Machine    Machine
    35  	Entry      uint64
    36  }
    37  
    38  // A File represents an open ELF file.
    39  type File struct {
    40  	FileHeader
    41  	Sections  []*Section
    42  	Progs     []*Prog
    43  	closer    io.Closer
    44  	gnuNeed   []verneed
    45  	gnuVersym []byte
    46  }
    47  
    48  // A SectionHeader represents a single ELF section header.
    49  type SectionHeader struct {
    50  	Name      string
    51  	Type      SectionType
    52  	Flags     SectionFlag
    53  	Addr      uint64
    54  	Offset    uint64
    55  	Size      uint64
    56  	Link      uint32
    57  	Info      uint32
    58  	Addralign uint64
    59  	Entsize   uint64
    60  }
    61  
    62  // A Section represents a single section in an ELF file.
    63  type Section struct {
    64  	SectionHeader
    65  
    66  	// Embed ReaderAt for ReadAt method.
    67  	// Do not embed SectionReader directly
    68  	// to avoid having Read and Seek.
    69  	// If a client wants Read and Seek it must use
    70  	// Open() to avoid fighting over the seek offset
    71  	// with other clients.
    72  	io.ReaderAt
    73  	sr *io.SectionReader
    74  }
    75  
    76  // Data reads and returns the contents of the ELF section.
    77  func (s *Section) Data() ([]byte, error) {
    78  	dat := make([]byte, s.sr.Size())
    79  	n, err := s.sr.ReadAt(dat, 0)
    80  	if n == len(dat) {
    81  		err = nil
    82  	}
    83  	return dat[0:n], err
    84  }
    85  
    86  // stringTable reads and returns the string table given by the
    87  // specified link value.
    88  func (f *File) stringTable(link uint32) ([]byte, error) {
    89  	if link <= 0 || link >= uint32(len(f.Sections)) {
    90  		return nil, errors.New("section has invalid string table link")
    91  	}
    92  	return f.Sections[link].Data()
    93  }
    94  
    95  // Open returns a new ReadSeeker reading the ELF section.
    96  func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }
    97  
    98  // A ProgHeader represents a single ELF program header.
    99  type ProgHeader struct {
   100  	Type   ProgType
   101  	Flags  ProgFlag
   102  	Off    uint64
   103  	Vaddr  uint64
   104  	Paddr  uint64
   105  	Filesz uint64
   106  	Memsz  uint64
   107  	Align  uint64
   108  }
   109  
   110  // A Prog represents a single ELF program header in an ELF binary.
   111  type Prog struct {
   112  	ProgHeader
   113  
   114  	// Embed ReaderAt for ReadAt method.
   115  	// Do not embed SectionReader directly
   116  	// to avoid having Read and Seek.
   117  	// If a client wants Read and Seek it must use
   118  	// Open() to avoid fighting over the seek offset
   119  	// with other clients.
   120  	io.ReaderAt
   121  	sr *io.SectionReader
   122  }
   123  
   124  // Open returns a new ReadSeeker reading the ELF program body.
   125  func (p *Prog) Open() io.ReadSeeker { return io.NewSectionReader(p.sr, 0, 1<<63-1) }
   126  
   127  // A Symbol represents an entry in an ELF symbol table section.
   128  type Symbol struct {
   129  	Name        string
   130  	Info, Other byte
   131  	Section     SectionIndex
   132  	Value, Size uint64
   133  }
   134  
   135  /*
   136   * ELF reader
   137   */
   138  
   139  type FormatError struct {
   140  	off int64
   141  	msg string
   142  	val interface{}
   143  }
   144  
   145  func (e *FormatError) Error() string {
   146  	msg := e.msg
   147  	if e.val != nil {
   148  		msg += fmt.Sprintf(" '%v' ", e.val)
   149  	}
   150  	msg += fmt.Sprintf("in record at byte %#x", e.off)
   151  	return msg
   152  }
   153  
   154  // Open opens the named file using os.Open and prepares it for use as an ELF binary.
   155  func Open(name string) (*File, error) {
   156  	f, err := os.Open(name)
   157  	if err != nil {
   158  		return nil, err
   159  	}
   160  	ff, err := NewFile(f)
   161  	if err != nil {
   162  		f.Close()
   163  		return nil, err
   164  	}
   165  	ff.closer = f
   166  	return ff, nil
   167  }
   168  
   169  // Close closes the File.
   170  // If the File was created using NewFile directly instead of Open,
   171  // Close has no effect.
   172  func (f *File) Close() error {
   173  	var err error
   174  	if f.closer != nil {
   175  		err = f.closer.Close()
   176  		f.closer = nil
   177  	}
   178  	return err
   179  }
   180  
   181  // SectionByType returns the first section in f with the
   182  // given type, or nil if there is no such section.
   183  func (f *File) SectionByType(typ SectionType) *Section {
   184  	for _, s := range f.Sections {
   185  		if s.Type == typ {
   186  			return s
   187  		}
   188  	}
   189  	return nil
   190  }
   191  
   192  // NewFile creates a new File for accessing an ELF binary in an underlying reader.
   193  // The ELF binary is expected to start at position 0 in the ReaderAt.
   194  func NewFile(r io.ReaderAt) (*File, error) {
   195  	sr := io.NewSectionReader(r, 0, 1<<63-1)
   196  	// Read and decode ELF identifier
   197  	var ident [16]uint8
   198  	if _, err := r.ReadAt(ident[0:], 0); err != nil {
   199  		return nil, err
   200  	}
   201  	if ident[0] != '\x7f' || ident[1] != 'E' || ident[2] != 'L' || ident[3] != 'F' {
   202  		return nil, &FormatError{0, "bad magic number", ident[0:4]}
   203  	}
   204  
   205  	f := new(File)
   206  	f.Class = Class(ident[EI_CLASS])
   207  	switch f.Class {
   208  	case ELFCLASS32:
   209  	case ELFCLASS64:
   210  		// ok
   211  	default:
   212  		return nil, &FormatError{0, "unknown ELF class", f.Class}
   213  	}
   214  
   215  	f.Data = Data(ident[EI_DATA])
   216  	switch f.Data {
   217  	case ELFDATA2LSB:
   218  		f.ByteOrder = binary.LittleEndian
   219  	case ELFDATA2MSB:
   220  		f.ByteOrder = binary.BigEndian
   221  	default:
   222  		return nil, &FormatError{0, "unknown ELF data encoding", f.Data}
   223  	}
   224  
   225  	f.Version = Version(ident[EI_VERSION])
   226  	if f.Version != EV_CURRENT {
   227  		return nil, &FormatError{0, "unknown ELF version", f.Version}
   228  	}
   229  
   230  	f.OSABI = OSABI(ident[EI_OSABI])
   231  	f.ABIVersion = ident[EI_ABIVERSION]
   232  
   233  	// Read ELF file header
   234  	var phoff int64
   235  	var phentsize, phnum int
   236  	var shoff int64
   237  	var shentsize, shnum, shstrndx int
   238  	shstrndx = -1
   239  	switch f.Class {
   240  	case ELFCLASS32:
   241  		hdr := new(Header32)
   242  		sr.Seek(0, os.SEEK_SET)
   243  		if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
   244  			return nil, err
   245  		}
   246  		f.Type = Type(hdr.Type)
   247  		f.Machine = Machine(hdr.Machine)
   248  		f.Entry = uint64(hdr.Entry)
   249  		if v := Version(hdr.Version); v != f.Version {
   250  			return nil, &FormatError{0, "mismatched ELF version", v}
   251  		}
   252  		phoff = int64(hdr.Phoff)
   253  		phentsize = int(hdr.Phentsize)
   254  		phnum = int(hdr.Phnum)
   255  		shoff = int64(hdr.Shoff)
   256  		shentsize = int(hdr.Shentsize)
   257  		shnum = int(hdr.Shnum)
   258  		shstrndx = int(hdr.Shstrndx)
   259  	case ELFCLASS64:
   260  		hdr := new(Header64)
   261  		sr.Seek(0, os.SEEK_SET)
   262  		if err := binary.Read(sr, f.ByteOrder, hdr); err != nil {
   263  			return nil, err
   264  		}
   265  		f.Type = Type(hdr.Type)
   266  		f.Machine = Machine(hdr.Machine)
   267  		f.Entry = uint64(hdr.Entry)
   268  		if v := Version(hdr.Version); v != f.Version {
   269  			return nil, &FormatError{0, "mismatched ELF version", v}
   270  		}
   271  		phoff = int64(hdr.Phoff)
   272  		phentsize = int(hdr.Phentsize)
   273  		phnum = int(hdr.Phnum)
   274  		shoff = int64(hdr.Shoff)
   275  		shentsize = int(hdr.Shentsize)
   276  		shnum = int(hdr.Shnum)
   277  		shstrndx = int(hdr.Shstrndx)
   278  	}
   279  
   280  	if shnum > 0 && shoff > 0 && (shstrndx < 0 || shstrndx >= shnum) {
   281  		return nil, &FormatError{0, "invalid ELF shstrndx", shstrndx}
   282  	}
   283  
   284  	// Read program headers
   285  	f.Progs = make([]*Prog, phnum)
   286  	for i := 0; i < phnum; i++ {
   287  		off := phoff + int64(i)*int64(phentsize)
   288  		sr.Seek(off, os.SEEK_SET)
   289  		p := new(Prog)
   290  		switch f.Class {
   291  		case ELFCLASS32:
   292  			ph := new(Prog32)
   293  			if err := binary.Read(sr, f.ByteOrder, ph); err != nil {
   294  				return nil, err
   295  			}
   296  			p.ProgHeader = ProgHeader{
   297  				Type:   ProgType(ph.Type),
   298  				Flags:  ProgFlag(ph.Flags),
   299  				Off:    uint64(ph.Off),
   300  				Vaddr:  uint64(ph.Vaddr),
   301  				Paddr:  uint64(ph.Paddr),
   302  				Filesz: uint64(ph.Filesz),
   303  				Memsz:  uint64(ph.Memsz),
   304  				Align:  uint64(ph.Align),
   305  			}
   306  		case ELFCLASS64:
   307  			ph := new(Prog64)
   308  			if err := binary.Read(sr, f.ByteOrder, ph); err != nil {
   309  				return nil, err
   310  			}
   311  			p.ProgHeader = ProgHeader{
   312  				Type:   ProgType(ph.Type),
   313  				Flags:  ProgFlag(ph.Flags),
   314  				Off:    uint64(ph.Off),
   315  				Vaddr:  uint64(ph.Vaddr),
   316  				Paddr:  uint64(ph.Paddr),
   317  				Filesz: uint64(ph.Filesz),
   318  				Memsz:  uint64(ph.Memsz),
   319  				Align:  uint64(ph.Align),
   320  			}
   321  		}
   322  		p.sr = io.NewSectionReader(r, int64(p.Off), int64(p.Filesz))
   323  		p.ReaderAt = p.sr
   324  		f.Progs[i] = p
   325  	}
   326  
   327  	// Read section headers
   328  	f.Sections = make([]*Section, shnum)
   329  	names := make([]uint32, shnum)
   330  	for i := 0; i < shnum; i++ {
   331  		off := shoff + int64(i)*int64(shentsize)
   332  		sr.Seek(off, os.SEEK_SET)
   333  		s := new(Section)
   334  		switch f.Class {
   335  		case ELFCLASS32:
   336  			sh := new(Section32)
   337  			if err := binary.Read(sr, f.ByteOrder, sh); err != nil {
   338  				return nil, err
   339  			}
   340  			names[i] = sh.Name
   341  			s.SectionHeader = SectionHeader{
   342  				Type:      SectionType(sh.Type),
   343  				Flags:     SectionFlag(sh.Flags),
   344  				Addr:      uint64(sh.Addr),
   345  				Offset:    uint64(sh.Off),
   346  				Size:      uint64(sh.Size),
   347  				Link:      uint32(sh.Link),
   348  				Info:      uint32(sh.Info),
   349  				Addralign: uint64(sh.Addralign),
   350  				Entsize:   uint64(sh.Entsize),
   351  			}
   352  		case ELFCLASS64:
   353  			sh := new(Section64)
   354  			if err := binary.Read(sr, f.ByteOrder, sh); err != nil {
   355  				return nil, err
   356  			}
   357  			names[i] = sh.Name
   358  			s.SectionHeader = SectionHeader{
   359  				Type:      SectionType(sh.Type),
   360  				Flags:     SectionFlag(sh.Flags),
   361  				Offset:    uint64(sh.Off),
   362  				Size:      uint64(sh.Size),
   363  				Addr:      uint64(sh.Addr),
   364  				Link:      uint32(sh.Link),
   365  				Info:      uint32(sh.Info),
   366  				Addralign: uint64(sh.Addralign),
   367  				Entsize:   uint64(sh.Entsize),
   368  			}
   369  		}
   370  		s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Size))
   371  		s.ReaderAt = s.sr
   372  		f.Sections[i] = s
   373  	}
   374  
   375  	if len(f.Sections) == 0 {
   376  		return f, nil
   377  	}
   378  
   379  	// Load section header string table.
   380  	shstrtab, err := f.Sections[shstrndx].Data()
   381  	if err != nil {
   382  		return nil, err
   383  	}
   384  	for i, s := range f.Sections {
   385  		var ok bool
   386  		s.Name, ok = getString(shstrtab, int(names[i]))
   387  		if !ok {
   388  			return nil, &FormatError{shoff + int64(i*shentsize), "bad section name index", names[i]}
   389  		}
   390  	}
   391  
   392  	return f, nil
   393  }
   394  
   395  // getSymbols returns a slice of Symbols from parsing the symbol table
   396  // with the given type, along with the associated string table.
   397  func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, error) {
   398  	switch f.Class {
   399  	case ELFCLASS64:
   400  		return f.getSymbols64(typ)
   401  
   402  	case ELFCLASS32:
   403  		return f.getSymbols32(typ)
   404  	}
   405  
   406  	return nil, nil, errors.New("not implemented")
   407  }
   408  
   409  // ErrNoSymbols is returned by File.Symbols and File.DynamicSymbols
   410  // if there is no such section in the File.
   411  var ErrNoSymbols = errors.New("no symbol section")
   412  
   413  func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
   414  	symtabSection := f.SectionByType(typ)
   415  	if symtabSection == nil {
   416  		return nil, nil, ErrNoSymbols
   417  	}
   418  
   419  	data, err := symtabSection.Data()
   420  	if err != nil {
   421  		return nil, nil, errors.New("cannot load symbol section")
   422  	}
   423  	symtab := bytes.NewReader(data)
   424  	if symtab.Len()%Sym32Size != 0 {
   425  		return nil, nil, errors.New("length of symbol section is not a multiple of SymSize")
   426  	}
   427  
   428  	strdata, err := f.stringTable(symtabSection.Link)
   429  	if err != nil {
   430  		return nil, nil, errors.New("cannot load string table section")
   431  	}
   432  
   433  	// The first entry is all zeros.
   434  	var skip [Sym32Size]byte
   435  	symtab.Read(skip[:])
   436  
   437  	symbols := make([]Symbol, symtab.Len()/Sym32Size)
   438  
   439  	i := 0
   440  	var sym Sym32
   441  	for symtab.Len() > 0 {
   442  		binary.Read(symtab, f.ByteOrder, &sym)
   443  		str, _ := getString(strdata, int(sym.Name))
   444  		symbols[i].Name = str
   445  		symbols[i].Info = sym.Info
   446  		symbols[i].Other = sym.Other
   447  		symbols[i].Section = SectionIndex(sym.Shndx)
   448  		symbols[i].Value = uint64(sym.Value)
   449  		symbols[i].Size = uint64(sym.Size)
   450  		i++
   451  	}
   452  
   453  	return symbols, strdata, nil
   454  }
   455  
   456  func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
   457  	symtabSection := f.SectionByType(typ)
   458  	if symtabSection == nil {
   459  		return nil, nil, ErrNoSymbols
   460  	}
   461  
   462  	data, err := symtabSection.Data()
   463  	if err != nil {
   464  		return nil, nil, errors.New("cannot load symbol section")
   465  	}
   466  	symtab := bytes.NewReader(data)
   467  	if symtab.Len()%Sym64Size != 0 {
   468  		return nil, nil, errors.New("length of symbol section is not a multiple of Sym64Size")
   469  	}
   470  
   471  	strdata, err := f.stringTable(symtabSection.Link)
   472  	if err != nil {
   473  		return nil, nil, errors.New("cannot load string table section")
   474  	}
   475  
   476  	// The first entry is all zeros.
   477  	var skip [Sym64Size]byte
   478  	symtab.Read(skip[:])
   479  
   480  	symbols := make([]Symbol, symtab.Len()/Sym64Size)
   481  
   482  	i := 0
   483  	var sym Sym64
   484  	for symtab.Len() > 0 {
   485  		binary.Read(symtab, f.ByteOrder, &sym)
   486  		str, _ := getString(strdata, int(sym.Name))
   487  		symbols[i].Name = str
   488  		symbols[i].Info = sym.Info
   489  		symbols[i].Other = sym.Other
   490  		symbols[i].Section = SectionIndex(sym.Shndx)
   491  		symbols[i].Value = sym.Value
   492  		symbols[i].Size = sym.Size
   493  		i++
   494  	}
   495  
   496  	return symbols, strdata, nil
   497  }
   498  
   499  // getString extracts a string from an ELF string table.
   500  func getString(section []byte, start int) (string, bool) {
   501  	if start < 0 || start >= len(section) {
   502  		return "", false
   503  	}
   504  
   505  	for end := start; end < len(section); end++ {
   506  		if section[end] == 0 {
   507  			return string(section[start:end]), true
   508  		}
   509  	}
   510  	return "", false
   511  }
   512  
   513  // Section returns a section with the given name, or nil if no such
   514  // section exists.
   515  func (f *File) Section(name string) *Section {
   516  	for _, s := range f.Sections {
   517  		if s.Name == name {
   518  			return s
   519  		}
   520  	}
   521  	return nil
   522  }
   523  
   524  // applyRelocations applies relocations to dst. rels is a relocations section
   525  // in RELA format.
   526  func (f *File) applyRelocations(dst []byte, rels []byte) error {
   527  	switch {
   528  	case f.Class == ELFCLASS64 && f.Machine == EM_X86_64:
   529  		return f.applyRelocationsAMD64(dst, rels)
   530  	case f.Class == ELFCLASS32 && f.Machine == EM_386:
   531  		return f.applyRelocations386(dst, rels)
   532  	case f.Class == ELFCLASS32 && f.Machine == EM_ARM:
   533  		return f.applyRelocationsARM(dst, rels)
   534  	case f.Class == ELFCLASS64 && f.Machine == EM_AARCH64:
   535  		return f.applyRelocationsARM64(dst, rels)
   536  	case f.Class == ELFCLASS32 && f.Machine == EM_PPC:
   537  		return f.applyRelocationsPPC(dst, rels)
   538  	case f.Class == ELFCLASS64 && f.Machine == EM_PPC64:
   539  		return f.applyRelocationsPPC64(dst, rels)
   540  	case f.Class == ELFCLASS64 && f.Machine == EM_MIPS:
   541  		return f.applyRelocationsMIPS64(dst, rels)
   542  	default:
   543  		return errors.New("applyRelocations: not implemented")
   544  	}
   545  }
   546  
   547  func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
   548  	// 24 is the size of Rela64.
   549  	if len(rels)%24 != 0 {
   550  		return errors.New("length of relocation section is not a multiple of 24")
   551  	}
   552  
   553  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   554  	if err != nil {
   555  		return err
   556  	}
   557  
   558  	b := bytes.NewReader(rels)
   559  	var rela Rela64
   560  
   561  	for b.Len() > 0 {
   562  		binary.Read(b, f.ByteOrder, &rela)
   563  		symNo := rela.Info >> 32
   564  		t := R_X86_64(rela.Info & 0xffff)
   565  
   566  		if symNo == 0 || symNo > uint64(len(symbols)) {
   567  			continue
   568  		}
   569  		sym := &symbols[symNo-1]
   570  		if SymType(sym.Info&0xf) != STT_SECTION {
   571  			// We don't handle non-section relocations for now.
   572  			continue
   573  		}
   574  
   575  		// There are relocations, so this must be a normal
   576  		// object file, and we only look at section symbols,
   577  		// so we assume that the symbol value is 0.
   578  
   579  		switch t {
   580  		case R_X86_64_64:
   581  			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
   582  				continue
   583  			}
   584  			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
   585  		case R_X86_64_32:
   586  			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
   587  				continue
   588  			}
   589  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   590  		}
   591  	}
   592  
   593  	return nil
   594  }
   595  
   596  func (f *File) applyRelocations386(dst []byte, rels []byte) error {
   597  	// 8 is the size of Rel32.
   598  	if len(rels)%8 != 0 {
   599  		return errors.New("length of relocation section is not a multiple of 8")
   600  	}
   601  
   602  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   603  	if err != nil {
   604  		return err
   605  	}
   606  
   607  	b := bytes.NewReader(rels)
   608  	var rel Rel32
   609  
   610  	for b.Len() > 0 {
   611  		binary.Read(b, f.ByteOrder, &rel)
   612  		symNo := rel.Info >> 8
   613  		t := R_386(rel.Info & 0xff)
   614  
   615  		if symNo == 0 || symNo > uint32(len(symbols)) {
   616  			continue
   617  		}
   618  		sym := &symbols[symNo-1]
   619  
   620  		if t == R_386_32 {
   621  			if rel.Off+4 >= uint32(len(dst)) {
   622  				continue
   623  			}
   624  			val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
   625  			val += uint32(sym.Value)
   626  			f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
   627  		}
   628  	}
   629  
   630  	return nil
   631  }
   632  
   633  func (f *File) applyRelocationsARM(dst []byte, rels []byte) error {
   634  	// 8 is the size of Rel32.
   635  	if len(rels)%8 != 0 {
   636  		return errors.New("length of relocation section is not a multiple of 8")
   637  	}
   638  
   639  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   640  	if err != nil {
   641  		return err
   642  	}
   643  
   644  	b := bytes.NewReader(rels)
   645  	var rel Rel32
   646  
   647  	for b.Len() > 0 {
   648  		binary.Read(b, f.ByteOrder, &rel)
   649  		symNo := rel.Info >> 8
   650  		t := R_ARM(rel.Info & 0xff)
   651  
   652  		if symNo == 0 || symNo > uint32(len(symbols)) {
   653  			continue
   654  		}
   655  		sym := &symbols[symNo-1]
   656  
   657  		switch t {
   658  		case R_ARM_ABS32:
   659  			if rel.Off+4 >= uint32(len(dst)) {
   660  				continue
   661  			}
   662  			val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
   663  			val += uint32(sym.Value)
   664  			f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
   665  		}
   666  	}
   667  
   668  	return nil
   669  }
   670  
   671  func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error {
   672  	// 24 is the size of Rela64.
   673  	if len(rels)%24 != 0 {
   674  		return errors.New("length of relocation section is not a multiple of 24")
   675  	}
   676  
   677  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   678  	if err != nil {
   679  		return err
   680  	}
   681  
   682  	b := bytes.NewReader(rels)
   683  	var rela Rela64
   684  
   685  	for b.Len() > 0 {
   686  		binary.Read(b, f.ByteOrder, &rela)
   687  		symNo := rela.Info >> 32
   688  		t := R_AARCH64(rela.Info & 0xffff)
   689  
   690  		if symNo == 0 || symNo > uint64(len(symbols)) {
   691  			continue
   692  		}
   693  		sym := &symbols[symNo-1]
   694  		if SymType(sym.Info&0xf) != STT_SECTION {
   695  			// We don't handle non-section relocations for now.
   696  			continue
   697  		}
   698  
   699  		// There are relocations, so this must be a normal
   700  		// object file, and we only look at section symbols,
   701  		// so we assume that the symbol value is 0.
   702  
   703  		switch t {
   704  		case R_AARCH64_ABS64:
   705  			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
   706  				continue
   707  			}
   708  			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
   709  		case R_AARCH64_ABS32:
   710  			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
   711  				continue
   712  			}
   713  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   714  		}
   715  	}
   716  
   717  	return nil
   718  }
   719  
   720  func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error {
   721  	// 12 is the size of Rela32.
   722  	if len(rels)%12 != 0 {
   723  		return errors.New("length of relocation section is not a multiple of 12")
   724  	}
   725  
   726  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   727  	if err != nil {
   728  		return err
   729  	}
   730  
   731  	b := bytes.NewReader(rels)
   732  	var rela Rela32
   733  
   734  	for b.Len() > 0 {
   735  		binary.Read(b, f.ByteOrder, &rela)
   736  		symNo := rela.Info >> 8
   737  		t := R_PPC(rela.Info & 0xff)
   738  
   739  		if symNo == 0 || symNo > uint32(len(symbols)) {
   740  			continue
   741  		}
   742  		sym := &symbols[symNo-1]
   743  		if SymType(sym.Info&0xf) != STT_SECTION {
   744  			// We don't handle non-section relocations for now.
   745  			continue
   746  		}
   747  
   748  		switch t {
   749  		case R_PPC_ADDR32:
   750  			if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 {
   751  				continue
   752  			}
   753  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   754  		}
   755  	}
   756  
   757  	return nil
   758  }
   759  
   760  func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error {
   761  	// 24 is the size of Rela64.
   762  	if len(rels)%24 != 0 {
   763  		return errors.New("length of relocation section is not a multiple of 24")
   764  	}
   765  
   766  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   767  	if err != nil {
   768  		return err
   769  	}
   770  
   771  	b := bytes.NewReader(rels)
   772  	var rela Rela64
   773  
   774  	for b.Len() > 0 {
   775  		binary.Read(b, f.ByteOrder, &rela)
   776  		symNo := rela.Info >> 32
   777  		t := R_PPC64(rela.Info & 0xffff)
   778  
   779  		if symNo == 0 || symNo > uint64(len(symbols)) {
   780  			continue
   781  		}
   782  		sym := &symbols[symNo-1]
   783  		if SymType(sym.Info&0xf) != STT_SECTION {
   784  			// We don't handle non-section relocations for now.
   785  			continue
   786  		}
   787  
   788  		switch t {
   789  		case R_PPC64_ADDR64:
   790  			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
   791  				continue
   792  			}
   793  			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
   794  		case R_PPC64_ADDR32:
   795  			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
   796  				continue
   797  			}
   798  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   799  		}
   800  	}
   801  
   802  	return nil
   803  }
   804  
   805  func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error {
   806  	// 24 is the size of Rela64.
   807  	if len(rels)%24 != 0 {
   808  		return errors.New("length of relocation section is not a multiple of 24")
   809  	}
   810  
   811  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   812  	if err != nil {
   813  		return err
   814  	}
   815  
   816  	b := bytes.NewReader(rels)
   817  	var rela Rela64
   818  
   819  	for b.Len() > 0 {
   820  		binary.Read(b, f.ByteOrder, &rela)
   821  		var symNo uint64
   822  		var t R_MIPS
   823  		if f.ByteOrder == binary.BigEndian {
   824  			symNo = rela.Info >> 32
   825  			t = R_MIPS(rela.Info & 0xff)
   826  		} else {
   827  			symNo = rela.Info & 0xffffffff
   828  			t = R_MIPS(rela.Info >> 56)
   829  		}
   830  
   831  		if symNo == 0 || symNo > uint64(len(symbols)) {
   832  			continue
   833  		}
   834  		sym := &symbols[symNo-1]
   835  		if SymType(sym.Info&0xf) != STT_SECTION {
   836  			// We don't handle non-section relocations for now.
   837  			continue
   838  		}
   839  
   840  		switch t {
   841  		case R_MIPS_64:
   842  			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
   843  				continue
   844  			}
   845  			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
   846  		case R_MIPS_32:
   847  			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
   848  				continue
   849  			}
   850  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   851  		}
   852  	}
   853  
   854  	return nil
   855  }
   856  
   857  func (f *File) DWARF() (*dwarf.Data, error) {
   858  	// sectionData gets the data for s, checks its size, and
   859  	// applies any applicable relations.
   860  	sectionData := func(i int, s *Section) ([]byte, error) {
   861  		b, err := s.Data()
   862  		if err != nil && uint64(len(b)) < s.Size {
   863  			return nil, err
   864  		}
   865  
   866  		for _, r := range f.Sections {
   867  			if r.Type != SHT_RELA && r.Type != SHT_REL {
   868  				continue
   869  			}
   870  			if int(r.Info) != i {
   871  				continue
   872  			}
   873  			rd, err := r.Data()
   874  			if err != nil {
   875  				return nil, err
   876  			}
   877  			err = f.applyRelocations(b, rd)
   878  			if err != nil {
   879  				return nil, err
   880  			}
   881  		}
   882  		return b, nil
   883  	}
   884  
   885  	// There are many other DWARF sections, but these
   886  	// are the ones the debug/dwarf package uses.
   887  	// Don't bother loading others.
   888  	var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil}
   889  	for i, s := range f.Sections {
   890  		if !strings.HasPrefix(s.Name, ".debug_") {
   891  			continue
   892  		}
   893  		if _, ok := dat[s.Name[7:]]; !ok {
   894  			continue
   895  		}
   896  		b, err := sectionData(i, s)
   897  		if err != nil {
   898  			return nil, err
   899  		}
   900  		dat[s.Name[7:]] = b
   901  	}
   902  
   903  	d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, nil, dat["str"])
   904  	if err != nil {
   905  		return nil, err
   906  	}
   907  
   908  	// Look for DWARF4 .debug_types sections.
   909  	for i, s := range f.Sections {
   910  		if s.Name == ".debug_types" {
   911  			b, err := sectionData(i, s)
   912  			if err != nil {
   913  				return nil, err
   914  			}
   915  
   916  			err = d.AddTypes(fmt.Sprintf("types-%d", i), b)
   917  			if err != nil {
   918  				return nil, err
   919  			}
   920  		}
   921  	}
   922  
   923  	return d, nil
   924  }
   925  
   926  // Symbols returns the symbol table for f. The symbols will be listed in the order
   927  // they appear in f.
   928  //
   929  // For compatibility with Go 1.0, Symbols omits the null symbol at index 0.
   930  // After retrieving the symbols as symtab, an externally supplied index x
   931  // corresponds to symtab[x-1], not symtab[x].
   932  func (f *File) Symbols() ([]Symbol, error) {
   933  	sym, _, err := f.getSymbols(SHT_SYMTAB)
   934  	return sym, err
   935  }
   936  
   937  // DynamicSymbols returns the dynamic symbol table for f. The symbols
   938  // will be listed in the order they appear in f.
   939  //
   940  // For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0.
   941  // After retrieving the symbols as symtab, an externally supplied index x
   942  // corresponds to symtab[x-1], not symtab[x].
   943  func (f *File) DynamicSymbols() ([]Symbol, error) {
   944  	sym, _, err := f.getSymbols(SHT_DYNSYM)
   945  	return sym, err
   946  }
   947  
   948  type ImportedSymbol struct {
   949  	Name    string
   950  	Version string
   951  	Library string
   952  }
   953  
   954  // ImportedSymbols returns the names of all symbols
   955  // referred to by the binary f that are expected to be
   956  // satisfied by other libraries at dynamic load time.
   957  // It does not return weak symbols.
   958  func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
   959  	sym, str, err := f.getSymbols(SHT_DYNSYM)
   960  	if err != nil {
   961  		return nil, err
   962  	}
   963  	f.gnuVersionInit(str)
   964  	var all []ImportedSymbol
   965  	for i, s := range sym {
   966  		if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
   967  			all = append(all, ImportedSymbol{Name: s.Name})
   968  			f.gnuVersion(i, &all[len(all)-1])
   969  		}
   970  	}
   971  	return all, nil
   972  }
   973  
   974  type verneed struct {
   975  	File string
   976  	Name string
   977  }
   978  
   979  // gnuVersionInit parses the GNU version tables
   980  // for use by calls to gnuVersion.
   981  func (f *File) gnuVersionInit(str []byte) {
   982  	// Accumulate verneed information.
   983  	vn := f.SectionByType(SHT_GNU_VERNEED)
   984  	if vn == nil {
   985  		return
   986  	}
   987  	d, _ := vn.Data()
   988  
   989  	var need []verneed
   990  	i := 0
   991  	for {
   992  		if i+16 > len(d) {
   993  			break
   994  		}
   995  		vers := f.ByteOrder.Uint16(d[i : i+2])
   996  		if vers != 1 {
   997  			break
   998  		}
   999  		cnt := f.ByteOrder.Uint16(d[i+2 : i+4])
  1000  		fileoff := f.ByteOrder.Uint32(d[i+4 : i+8])
  1001  		aux := f.ByteOrder.Uint32(d[i+8 : i+12])
  1002  		next := f.ByteOrder.Uint32(d[i+12 : i+16])
  1003  		file, _ := getString(str, int(fileoff))
  1004  
  1005  		var name string
  1006  		j := i + int(aux)
  1007  		for c := 0; c < int(cnt); c++ {
  1008  			if j+16 > len(d) {
  1009  				break
  1010  			}
  1011  			// hash := f.ByteOrder.Uint32(d[j:j+4])
  1012  			// flags := f.ByteOrder.Uint16(d[j+4:j+6])
  1013  			other := f.ByteOrder.Uint16(d[j+6 : j+8])
  1014  			nameoff := f.ByteOrder.Uint32(d[j+8 : j+12])
  1015  			next := f.ByteOrder.Uint32(d[j+12 : j+16])
  1016  			name, _ = getString(str, int(nameoff))
  1017  			ndx := int(other)
  1018  			if ndx >= len(need) {
  1019  				a := make([]verneed, 2*(ndx+1))
  1020  				copy(a, need)
  1021  				need = a
  1022  			}
  1023  
  1024  			need[ndx] = verneed{file, name}
  1025  			if next == 0 {
  1026  				break
  1027  			}
  1028  			j += int(next)
  1029  		}
  1030  
  1031  		if next == 0 {
  1032  			break
  1033  		}
  1034  		i += int(next)
  1035  	}
  1036  
  1037  	// Versym parallels symbol table, indexing into verneed.
  1038  	vs := f.SectionByType(SHT_GNU_VERSYM)
  1039  	if vs == nil {
  1040  		return
  1041  	}
  1042  	d, _ = vs.Data()
  1043  
  1044  	f.gnuNeed = need
  1045  	f.gnuVersym = d
  1046  }
  1047  
  1048  // gnuVersion adds Library and Version information to sym,
  1049  // which came from offset i of the symbol table.
  1050  func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
  1051  	// Each entry is two bytes.
  1052  	i = (i + 1) * 2
  1053  	if i >= len(f.gnuVersym) {
  1054  		return
  1055  	}
  1056  	j := int(f.ByteOrder.Uint16(f.gnuVersym[i:]))
  1057  	if j < 2 || j >= len(f.gnuNeed) {
  1058  		return
  1059  	}
  1060  	n := &f.gnuNeed[j]
  1061  	sym.Library = n.File
  1062  	sym.Version = n.Name
  1063  }
  1064  
  1065  // ImportedLibraries returns the names of all libraries
  1066  // referred to by the binary f that are expected to be
  1067  // linked with the binary at dynamic link time.
  1068  func (f *File) ImportedLibraries() ([]string, error) {
  1069  	return f.DynString(DT_NEEDED)
  1070  }
  1071  
  1072  // DynString returns the strings listed for the given tag in the file's dynamic
  1073  // section.
  1074  //
  1075  // The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or
  1076  // DT_RUNPATH.
  1077  func (f *File) DynString(tag DynTag) ([]string, error) {
  1078  	switch tag {
  1079  	case DT_NEEDED, DT_SONAME, DT_RPATH, DT_RUNPATH:
  1080  	default:
  1081  		return nil, fmt.Errorf("non-string-valued tag %v", tag)
  1082  	}
  1083  	ds := f.SectionByType(SHT_DYNAMIC)
  1084  	if ds == nil {
  1085  		// not dynamic, so no libraries
  1086  		return nil, nil
  1087  	}
  1088  	d, err := ds.Data()
  1089  	if err != nil {
  1090  		return nil, err
  1091  	}
  1092  	str, err := f.stringTable(ds.Link)
  1093  	if err != nil {
  1094  		return nil, err
  1095  	}
  1096  	var all []string
  1097  	for len(d) > 0 {
  1098  		var t DynTag
  1099  		var v uint64
  1100  		switch f.Class {
  1101  		case ELFCLASS32:
  1102  			t = DynTag(f.ByteOrder.Uint32(d[0:4]))
  1103  			v = uint64(f.ByteOrder.Uint32(d[4:8]))
  1104  			d = d[8:]
  1105  		case ELFCLASS64:
  1106  			t = DynTag(f.ByteOrder.Uint64(d[0:8]))
  1107  			v = f.ByteOrder.Uint64(d[8:16])
  1108  			d = d[16:]
  1109  		}
  1110  		if t == tag {
  1111  			s, ok := getString(str, int(v))
  1112  			if ok {
  1113  				all = append(all, s)
  1114  			}
  1115  		}
  1116  	}
  1117  	return all, nil
  1118  }