github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/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  	case f.Class == ELFCLASS64 && f.Machine == EM_SPARCV9:
   602  		return f.applyRelocationsSPARC64(dst, rels)
   603  	default:
   604  		return errors.New("applyRelocations: not implemented")
   605  	}
   606  }
   607  
   608  func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
   609  	// 24 is the size of Rela64.
   610  	if len(rels)%24 != 0 {
   611  		return errors.New("length of relocation section is not a multiple of 24")
   612  	}
   613  
   614  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   615  	if err != nil {
   616  		return err
   617  	}
   618  
   619  	b := bytes.NewReader(rels)
   620  	var rela Rela64
   621  
   622  	for b.Len() > 0 {
   623  		binary.Read(b, f.ByteOrder, &rela)
   624  		symNo := rela.Info >> 32
   625  		t := R_X86_64(rela.Info & 0xffff)
   626  
   627  		if symNo == 0 || symNo > uint64(len(symbols)) {
   628  			continue
   629  		}
   630  		sym := &symbols[symNo-1]
   631  		if SymType(sym.Info&0xf) != STT_SECTION {
   632  			// We don't handle non-section relocations for now.
   633  			continue
   634  		}
   635  
   636  		// There are relocations, so this must be a normal
   637  		// object file, and we only look at section symbols,
   638  		// so we assume that the symbol value is 0.
   639  
   640  		switch t {
   641  		case R_X86_64_64:
   642  			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
   643  				continue
   644  			}
   645  			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
   646  		case R_X86_64_32:
   647  			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
   648  				continue
   649  			}
   650  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   651  		}
   652  	}
   653  
   654  	return nil
   655  }
   656  
   657  func (f *File) applyRelocations386(dst []byte, rels []byte) error {
   658  	// 8 is the size of Rel32.
   659  	if len(rels)%8 != 0 {
   660  		return errors.New("length of relocation section is not a multiple of 8")
   661  	}
   662  
   663  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   664  	if err != nil {
   665  		return err
   666  	}
   667  
   668  	b := bytes.NewReader(rels)
   669  	var rel Rel32
   670  
   671  	for b.Len() > 0 {
   672  		binary.Read(b, f.ByteOrder, &rel)
   673  		symNo := rel.Info >> 8
   674  		t := R_386(rel.Info & 0xff)
   675  
   676  		if symNo == 0 || symNo > uint32(len(symbols)) {
   677  			continue
   678  		}
   679  		sym := &symbols[symNo-1]
   680  
   681  		if t == R_386_32 {
   682  			if rel.Off+4 >= uint32(len(dst)) {
   683  				continue
   684  			}
   685  			val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
   686  			val += uint32(sym.Value)
   687  			f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
   688  		}
   689  	}
   690  
   691  	return nil
   692  }
   693  
   694  func (f *File) applyRelocationsARM(dst []byte, rels []byte) error {
   695  	// 8 is the size of Rel32.
   696  	if len(rels)%8 != 0 {
   697  		return errors.New("length of relocation section is not a multiple of 8")
   698  	}
   699  
   700  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   701  	if err != nil {
   702  		return err
   703  	}
   704  
   705  	b := bytes.NewReader(rels)
   706  	var rel Rel32
   707  
   708  	for b.Len() > 0 {
   709  		binary.Read(b, f.ByteOrder, &rel)
   710  		symNo := rel.Info >> 8
   711  		t := R_ARM(rel.Info & 0xff)
   712  
   713  		if symNo == 0 || symNo > uint32(len(symbols)) {
   714  			continue
   715  		}
   716  		sym := &symbols[symNo-1]
   717  
   718  		switch t {
   719  		case R_ARM_ABS32:
   720  			if rel.Off+4 >= uint32(len(dst)) {
   721  				continue
   722  			}
   723  			val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
   724  			val += uint32(sym.Value)
   725  			f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
   726  		}
   727  	}
   728  
   729  	return nil
   730  }
   731  
   732  func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error {
   733  	// 24 is the size of Rela64.
   734  	if len(rels)%24 != 0 {
   735  		return errors.New("length of relocation section is not a multiple of 24")
   736  	}
   737  
   738  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   739  	if err != nil {
   740  		return err
   741  	}
   742  
   743  	b := bytes.NewReader(rels)
   744  	var rela Rela64
   745  
   746  	for b.Len() > 0 {
   747  		binary.Read(b, f.ByteOrder, &rela)
   748  		symNo := rela.Info >> 32
   749  		t := R_AARCH64(rela.Info & 0xffff)
   750  
   751  		if symNo == 0 || symNo > uint64(len(symbols)) {
   752  			continue
   753  		}
   754  		sym := &symbols[symNo-1]
   755  		if SymType(sym.Info&0xf) != STT_SECTION {
   756  			// We don't handle non-section relocations for now.
   757  			continue
   758  		}
   759  
   760  		// There are relocations, so this must be a normal
   761  		// object file, and we only look at section symbols,
   762  		// so we assume that the symbol value is 0.
   763  
   764  		switch t {
   765  		case R_AARCH64_ABS64:
   766  			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
   767  				continue
   768  			}
   769  			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
   770  		case R_AARCH64_ABS32:
   771  			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
   772  				continue
   773  			}
   774  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   775  		}
   776  	}
   777  
   778  	return nil
   779  }
   780  
   781  func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error {
   782  	// 12 is the size of Rela32.
   783  	if len(rels)%12 != 0 {
   784  		return errors.New("length of relocation section is not a multiple of 12")
   785  	}
   786  
   787  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   788  	if err != nil {
   789  		return err
   790  	}
   791  
   792  	b := bytes.NewReader(rels)
   793  	var rela Rela32
   794  
   795  	for b.Len() > 0 {
   796  		binary.Read(b, f.ByteOrder, &rela)
   797  		symNo := rela.Info >> 8
   798  		t := R_PPC(rela.Info & 0xff)
   799  
   800  		if symNo == 0 || symNo > uint32(len(symbols)) {
   801  			continue
   802  		}
   803  		sym := &symbols[symNo-1]
   804  		if SymType(sym.Info&0xf) != STT_SECTION {
   805  			// We don't handle non-section relocations for now.
   806  			continue
   807  		}
   808  
   809  		switch t {
   810  		case R_PPC_ADDR32:
   811  			if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 {
   812  				continue
   813  			}
   814  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   815  		}
   816  	}
   817  
   818  	return nil
   819  }
   820  
   821  func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error {
   822  	// 24 is the size of Rela64.
   823  	if len(rels)%24 != 0 {
   824  		return errors.New("length of relocation section is not a multiple of 24")
   825  	}
   826  
   827  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   828  	if err != nil {
   829  		return err
   830  	}
   831  
   832  	b := bytes.NewReader(rels)
   833  	var rela Rela64
   834  
   835  	for b.Len() > 0 {
   836  		binary.Read(b, f.ByteOrder, &rela)
   837  		symNo := rela.Info >> 32
   838  		t := R_PPC64(rela.Info & 0xffff)
   839  
   840  		if symNo == 0 || symNo > uint64(len(symbols)) {
   841  			continue
   842  		}
   843  		sym := &symbols[symNo-1]
   844  		if SymType(sym.Info&0xf) != STT_SECTION {
   845  			// We don't handle non-section relocations for now.
   846  			continue
   847  		}
   848  
   849  		switch t {
   850  		case R_PPC64_ADDR64:
   851  			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
   852  				continue
   853  			}
   854  			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
   855  		case R_PPC64_ADDR32:
   856  			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
   857  				continue
   858  			}
   859  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   860  		}
   861  	}
   862  
   863  	return nil
   864  }
   865  
   866  func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error {
   867  	// 24 is the size of Rela64.
   868  	if len(rels)%24 != 0 {
   869  		return errors.New("length of relocation section is not a multiple of 24")
   870  	}
   871  
   872  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   873  	if err != nil {
   874  		return err
   875  	}
   876  
   877  	b := bytes.NewReader(rels)
   878  	var rela Rela64
   879  
   880  	for b.Len() > 0 {
   881  		binary.Read(b, f.ByteOrder, &rela)
   882  		var symNo uint64
   883  		var t R_MIPS
   884  		if f.ByteOrder == binary.BigEndian {
   885  			symNo = rela.Info >> 32
   886  			t = R_MIPS(rela.Info & 0xff)
   887  		} else {
   888  			symNo = rela.Info & 0xffffffff
   889  			t = R_MIPS(rela.Info >> 56)
   890  		}
   891  
   892  		if symNo == 0 || symNo > uint64(len(symbols)) {
   893  			continue
   894  		}
   895  		sym := &symbols[symNo-1]
   896  		if SymType(sym.Info&0xf) != STT_SECTION {
   897  			// We don't handle non-section relocations for now.
   898  			continue
   899  		}
   900  
   901  		switch t {
   902  		case R_MIPS_64:
   903  			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
   904  				continue
   905  			}
   906  			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
   907  		case R_MIPS_32:
   908  			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
   909  				continue
   910  			}
   911  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   912  		}
   913  	}
   914  
   915  	return nil
   916  }
   917  
   918  func (f *File) applyRelocationss390x(dst []byte, rels []byte) error {
   919  	// 24 is the size of Rela64.
   920  	if len(rels)%24 != 0 {
   921  		return errors.New("length of relocation section is not a multiple of 24")
   922  	}
   923  
   924  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   925  	if err != nil {
   926  		return err
   927  	}
   928  
   929  	b := bytes.NewReader(rels)
   930  	var rela Rela64
   931  
   932  	for b.Len() > 0 {
   933  		binary.Read(b, f.ByteOrder, &rela)
   934  		symNo := rela.Info >> 32
   935  		t := R_390(rela.Info & 0xffff)
   936  
   937  		if symNo == 0 || symNo > uint64(len(symbols)) {
   938  			continue
   939  		}
   940  		sym := &symbols[symNo-1]
   941  		switch SymType(sym.Info & 0xf) {
   942  		case STT_SECTION, STT_NOTYPE:
   943  			break
   944  		default:
   945  			continue
   946  		}
   947  
   948  		switch t {
   949  		case R_390_64:
   950  			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
   951  				continue
   952  			}
   953  			val := sym.Value + uint64(rela.Addend)
   954  			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val)
   955  		case R_390_32:
   956  			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
   957  				continue
   958  			}
   959  			val := uint32(sym.Value) + uint32(rela.Addend)
   960  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val)
   961  		}
   962  	}
   963  
   964  	return nil
   965  }
   966  
   967  func (f *File) applyRelocationsSPARC64(dst []byte, rels []byte) error {
   968  	// 24 is the size of Rela64.
   969  	if len(rels)%24 != 0 {
   970  		return errors.New("length of relocation section is not a multiple of 24")
   971  	}
   972  
   973  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   974  	if err != nil {
   975  		return err
   976  	}
   977  
   978  	b := bytes.NewReader(rels)
   979  	var rela Rela64
   980  
   981  	for b.Len() > 0 {
   982  		binary.Read(b, f.ByteOrder, &rela)
   983  		symNo := rela.Info >> 32
   984  		t := R_SPARC(rela.Info & 0xffff)
   985  
   986  		if symNo == 0 || symNo > uint64(len(symbols)) {
   987  			continue
   988  		}
   989  		sym := &symbols[symNo-1]
   990  		if SymType(sym.Info&0xf) != STT_SECTION {
   991  			// We don't handle non-section relocations for now.
   992  			continue
   993  		}
   994  
   995  		switch t {
   996  		case R_SPARC_64, R_SPARC_UA64:
   997  			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
   998  				continue
   999  			}
  1000  			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
  1001  		case R_SPARC_32, R_SPARC_UA32:
  1002  			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
  1003  				continue
  1004  			}
  1005  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
  1006  		}
  1007  	}
  1008  
  1009  	return nil
  1010  }
  1011  
  1012  func (f *File) DWARF() (*dwarf.Data, error) {
  1013  	// sectionData gets the data for s, checks its size, and
  1014  	// applies any applicable relations.
  1015  	sectionData := func(i int, s *Section) ([]byte, error) {
  1016  		b, err := s.Data()
  1017  		if err != nil && uint64(len(b)) < s.Size {
  1018  			return nil, err
  1019  		}
  1020  
  1021  		if len(b) >= 12 && string(b[:4]) == "ZLIB" {
  1022  			dlen := binary.BigEndian.Uint64(b[4:12])
  1023  			dbuf := make([]byte, dlen)
  1024  			r, err := zlib.NewReader(bytes.NewBuffer(b[12:]))
  1025  			if err != nil {
  1026  				return nil, err
  1027  			}
  1028  			if _, err := io.ReadFull(r, dbuf); err != nil {
  1029  				return nil, err
  1030  			}
  1031  			if err := r.Close(); err != nil {
  1032  				return nil, err
  1033  			}
  1034  			b = dbuf
  1035  		}
  1036  
  1037  		for _, r := range f.Sections {
  1038  			if r.Type != SHT_RELA && r.Type != SHT_REL {
  1039  				continue
  1040  			}
  1041  			if int(r.Info) != i {
  1042  				continue
  1043  			}
  1044  			rd, err := r.Data()
  1045  			if err != nil {
  1046  				return nil, err
  1047  			}
  1048  			err = f.applyRelocations(b, rd)
  1049  			if err != nil {
  1050  				return nil, err
  1051  			}
  1052  		}
  1053  		return b, nil
  1054  	}
  1055  
  1056  	// There are many other DWARF sections, but these
  1057  	// are the ones the debug/dwarf package uses.
  1058  	// Don't bother loading others.
  1059  	var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil, "ranges": nil}
  1060  	for i, s := range f.Sections {
  1061  		suffix := ""
  1062  		switch {
  1063  		case strings.HasPrefix(s.Name, ".debug_"):
  1064  			suffix = s.Name[7:]
  1065  		case strings.HasPrefix(s.Name, ".zdebug_"):
  1066  			suffix = s.Name[8:]
  1067  		default:
  1068  			continue
  1069  		}
  1070  		if _, ok := dat[suffix]; !ok {
  1071  			continue
  1072  		}
  1073  		b, err := sectionData(i, s)
  1074  		if err != nil {
  1075  			return nil, err
  1076  		}
  1077  		dat[suffix] = b
  1078  	}
  1079  
  1080  	d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, dat["ranges"], dat["str"])
  1081  	if err != nil {
  1082  		return nil, err
  1083  	}
  1084  
  1085  	// Look for DWARF4 .debug_types sections.
  1086  	for i, s := range f.Sections {
  1087  		if s.Name == ".debug_types" {
  1088  			b, err := sectionData(i, s)
  1089  			if err != nil {
  1090  				return nil, err
  1091  			}
  1092  
  1093  			err = d.AddTypes(fmt.Sprintf("types-%d", i), b)
  1094  			if err != nil {
  1095  				return nil, err
  1096  			}
  1097  		}
  1098  	}
  1099  
  1100  	return d, nil
  1101  }
  1102  
  1103  // Symbols returns the symbol table for f. The symbols will be listed in the order
  1104  // they appear in f.
  1105  //
  1106  // For compatibility with Go 1.0, Symbols omits the null symbol at index 0.
  1107  // After retrieving the symbols as symtab, an externally supplied index x
  1108  // corresponds to symtab[x-1], not symtab[x].
  1109  func (f *File) Symbols() ([]Symbol, error) {
  1110  	sym, _, err := f.getSymbols(SHT_SYMTAB)
  1111  	return sym, err
  1112  }
  1113  
  1114  // DynamicSymbols returns the dynamic symbol table for f. The symbols
  1115  // will be listed in the order they appear in f.
  1116  //
  1117  // For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0.
  1118  // After retrieving the symbols as symtab, an externally supplied index x
  1119  // corresponds to symtab[x-1], not symtab[x].
  1120  func (f *File) DynamicSymbols() ([]Symbol, error) {
  1121  	sym, _, err := f.getSymbols(SHT_DYNSYM)
  1122  	return sym, err
  1123  }
  1124  
  1125  type ImportedSymbol struct {
  1126  	Name    string
  1127  	Version string
  1128  	Library string
  1129  }
  1130  
  1131  // ImportedSymbols returns the names of all symbols
  1132  // referred to by the binary f that are expected to be
  1133  // satisfied by other libraries at dynamic load time.
  1134  // It does not return weak symbols.
  1135  func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
  1136  	sym, str, err := f.getSymbols(SHT_DYNSYM)
  1137  	if err != nil {
  1138  		return nil, err
  1139  	}
  1140  	f.gnuVersionInit(str)
  1141  	var all []ImportedSymbol
  1142  	for i, s := range sym {
  1143  		if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
  1144  			all = append(all, ImportedSymbol{Name: s.Name})
  1145  			f.gnuVersion(i, &all[len(all)-1])
  1146  		}
  1147  	}
  1148  	return all, nil
  1149  }
  1150  
  1151  type verneed struct {
  1152  	File string
  1153  	Name string
  1154  }
  1155  
  1156  // gnuVersionInit parses the GNU version tables
  1157  // for use by calls to gnuVersion.
  1158  func (f *File) gnuVersionInit(str []byte) {
  1159  	// Accumulate verneed information.
  1160  	vn := f.SectionByType(SHT_GNU_VERNEED)
  1161  	if vn == nil {
  1162  		return
  1163  	}
  1164  	d, _ := vn.Data()
  1165  
  1166  	var need []verneed
  1167  	i := 0
  1168  	for {
  1169  		if i+16 > len(d) {
  1170  			break
  1171  		}
  1172  		vers := f.ByteOrder.Uint16(d[i : i+2])
  1173  		if vers != 1 {
  1174  			break
  1175  		}
  1176  		cnt := f.ByteOrder.Uint16(d[i+2 : i+4])
  1177  		fileoff := f.ByteOrder.Uint32(d[i+4 : i+8])
  1178  		aux := f.ByteOrder.Uint32(d[i+8 : i+12])
  1179  		next := f.ByteOrder.Uint32(d[i+12 : i+16])
  1180  		file, _ := getString(str, int(fileoff))
  1181  
  1182  		var name string
  1183  		j := i + int(aux)
  1184  		for c := 0; c < int(cnt); c++ {
  1185  			if j+16 > len(d) {
  1186  				break
  1187  			}
  1188  			// hash := f.ByteOrder.Uint32(d[j:j+4])
  1189  			// flags := f.ByteOrder.Uint16(d[j+4:j+6])
  1190  			other := f.ByteOrder.Uint16(d[j+6 : j+8])
  1191  			nameoff := f.ByteOrder.Uint32(d[j+8 : j+12])
  1192  			next := f.ByteOrder.Uint32(d[j+12 : j+16])
  1193  			name, _ = getString(str, int(nameoff))
  1194  			ndx := int(other)
  1195  			if ndx >= len(need) {
  1196  				a := make([]verneed, 2*(ndx+1))
  1197  				copy(a, need)
  1198  				need = a
  1199  			}
  1200  
  1201  			need[ndx] = verneed{file, name}
  1202  			if next == 0 {
  1203  				break
  1204  			}
  1205  			j += int(next)
  1206  		}
  1207  
  1208  		if next == 0 {
  1209  			break
  1210  		}
  1211  		i += int(next)
  1212  	}
  1213  
  1214  	// Versym parallels symbol table, indexing into verneed.
  1215  	vs := f.SectionByType(SHT_GNU_VERSYM)
  1216  	if vs == nil {
  1217  		return
  1218  	}
  1219  	d, _ = vs.Data()
  1220  
  1221  	f.gnuNeed = need
  1222  	f.gnuVersym = d
  1223  }
  1224  
  1225  // gnuVersion adds Library and Version information to sym,
  1226  // which came from offset i of the symbol table.
  1227  func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
  1228  	// Each entry is two bytes.
  1229  	i = (i + 1) * 2
  1230  	if i >= len(f.gnuVersym) {
  1231  		return
  1232  	}
  1233  	j := int(f.ByteOrder.Uint16(f.gnuVersym[i:]))
  1234  	if j < 2 || j >= len(f.gnuNeed) {
  1235  		return
  1236  	}
  1237  	n := &f.gnuNeed[j]
  1238  	sym.Library = n.File
  1239  	sym.Version = n.Name
  1240  }
  1241  
  1242  // ImportedLibraries returns the names of all libraries
  1243  // referred to by the binary f that are expected to be
  1244  // linked with the binary at dynamic link time.
  1245  func (f *File) ImportedLibraries() ([]string, error) {
  1246  	return f.DynString(DT_NEEDED)
  1247  }
  1248  
  1249  // DynString returns the strings listed for the given tag in the file's dynamic
  1250  // section.
  1251  //
  1252  // The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or
  1253  // DT_RUNPATH.
  1254  func (f *File) DynString(tag DynTag) ([]string, error) {
  1255  	switch tag {
  1256  	case DT_NEEDED, DT_SONAME, DT_RPATH, DT_RUNPATH:
  1257  	default:
  1258  		return nil, fmt.Errorf("non-string-valued tag %v", tag)
  1259  	}
  1260  	ds := f.SectionByType(SHT_DYNAMIC)
  1261  	if ds == nil {
  1262  		// not dynamic, so no libraries
  1263  		return nil, nil
  1264  	}
  1265  	d, err := ds.Data()
  1266  	if err != nil {
  1267  		return nil, err
  1268  	}
  1269  	str, err := f.stringTable(ds.Link)
  1270  	if err != nil {
  1271  		return nil, err
  1272  	}
  1273  	var all []string
  1274  	for len(d) > 0 {
  1275  		var t DynTag
  1276  		var v uint64
  1277  		switch f.Class {
  1278  		case ELFCLASS32:
  1279  			t = DynTag(f.ByteOrder.Uint32(d[0:4]))
  1280  			v = uint64(f.ByteOrder.Uint32(d[4:8]))
  1281  			d = d[8:]
  1282  		case ELFCLASS64:
  1283  			t = DynTag(f.ByteOrder.Uint64(d[0:8]))
  1284  			v = f.ByteOrder.Uint64(d[8:16])
  1285  			d = d[16:]
  1286  		}
  1287  		if t == tag {
  1288  			s, ok := getString(str, int(v))
  1289  			if ok {
  1290  				all = append(all, s)
  1291  			}
  1292  		}
  1293  	}
  1294  	return all, nil
  1295  }