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