github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/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  	default:
   541  		return errors.New("applyRelocations: not implemented")
   542  	}
   543  }
   544  
   545  func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
   546  	// 24 is the size of Rela64.
   547  	if len(rels)%24 != 0 {
   548  		return errors.New("length of relocation section is not a multiple of 24")
   549  	}
   550  
   551  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   552  	if err != nil {
   553  		return err
   554  	}
   555  
   556  	b := bytes.NewReader(rels)
   557  	var rela Rela64
   558  
   559  	for b.Len() > 0 {
   560  		binary.Read(b, f.ByteOrder, &rela)
   561  		symNo := rela.Info >> 32
   562  		t := R_X86_64(rela.Info & 0xffff)
   563  
   564  		if symNo == 0 || symNo > uint64(len(symbols)) {
   565  			continue
   566  		}
   567  		sym := &symbols[symNo-1]
   568  		if SymType(sym.Info&0xf) != STT_SECTION {
   569  			// We don't handle non-section relocations for now.
   570  			continue
   571  		}
   572  
   573  		// There are relocations, so this must be a normal
   574  		// object file, and we only look at section symbols,
   575  		// so we assume that the symbol value is 0.
   576  
   577  		switch t {
   578  		case R_X86_64_64:
   579  			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
   580  				continue
   581  			}
   582  			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
   583  		case R_X86_64_32:
   584  			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
   585  				continue
   586  			}
   587  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   588  		}
   589  	}
   590  
   591  	return nil
   592  }
   593  
   594  func (f *File) applyRelocations386(dst []byte, rels []byte) error {
   595  	// 8 is the size of Rel32.
   596  	if len(rels)%8 != 0 {
   597  		return errors.New("length of relocation section is not a multiple of 8")
   598  	}
   599  
   600  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   601  	if err != nil {
   602  		return err
   603  	}
   604  
   605  	b := bytes.NewReader(rels)
   606  	var rel Rel32
   607  
   608  	for b.Len() > 0 {
   609  		binary.Read(b, f.ByteOrder, &rel)
   610  		symNo := rel.Info >> 8
   611  		t := R_386(rel.Info & 0xff)
   612  
   613  		if symNo == 0 || symNo > uint32(len(symbols)) {
   614  			continue
   615  		}
   616  		sym := &symbols[symNo-1]
   617  
   618  		if t == R_386_32 {
   619  			if rel.Off+4 >= uint32(len(dst)) {
   620  				continue
   621  			}
   622  			val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
   623  			val += uint32(sym.Value)
   624  			f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
   625  		}
   626  	}
   627  
   628  	return nil
   629  }
   630  
   631  func (f *File) applyRelocationsARM(dst []byte, rels []byte) error {
   632  	// 8 is the size of Rel32.
   633  	if len(rels)%8 != 0 {
   634  		return errors.New("length of relocation section is not a multiple of 8")
   635  	}
   636  
   637  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   638  	if err != nil {
   639  		return err
   640  	}
   641  
   642  	b := bytes.NewReader(rels)
   643  	var rel Rel32
   644  
   645  	for b.Len() > 0 {
   646  		binary.Read(b, f.ByteOrder, &rel)
   647  		symNo := rel.Info >> 8
   648  		t := R_ARM(rel.Info & 0xff)
   649  
   650  		if symNo == 0 || symNo > uint32(len(symbols)) {
   651  			continue
   652  		}
   653  		sym := &symbols[symNo-1]
   654  
   655  		switch t {
   656  		case R_ARM_ABS32:
   657  			if rel.Off+4 >= uint32(len(dst)) {
   658  				continue
   659  			}
   660  			val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
   661  			val += uint32(sym.Value)
   662  			f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
   663  		}
   664  	}
   665  
   666  	return nil
   667  }
   668  
   669  func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error {
   670  	// 24 is the size of Rela64.
   671  	if len(rels)%24 != 0 {
   672  		return errors.New("length of relocation section is not a multiple of 24")
   673  	}
   674  
   675  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   676  	if err != nil {
   677  		return err
   678  	}
   679  
   680  	b := bytes.NewReader(rels)
   681  	var rela Rela64
   682  
   683  	for b.Len() > 0 {
   684  		binary.Read(b, f.ByteOrder, &rela)
   685  		symNo := rela.Info >> 32
   686  		t := R_AARCH64(rela.Info & 0xffff)
   687  
   688  		if symNo == 0 || symNo > uint64(len(symbols)) {
   689  			continue
   690  		}
   691  		sym := &symbols[symNo-1]
   692  		if SymType(sym.Info&0xf) != STT_SECTION {
   693  			// We don't handle non-section relocations for now.
   694  			continue
   695  		}
   696  
   697  		// There are relocations, so this must be a normal
   698  		// object file, and we only look at section symbols,
   699  		// so we assume that the symbol value is 0.
   700  
   701  		switch t {
   702  		case R_AARCH64_ABS64:
   703  			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
   704  				continue
   705  			}
   706  			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
   707  		case R_AARCH64_ABS32:
   708  			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
   709  				continue
   710  			}
   711  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   712  		}
   713  	}
   714  
   715  	return nil
   716  }
   717  
   718  func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error {
   719  	// 12 is the size of Rela32.
   720  	if len(rels)%12 != 0 {
   721  		return errors.New("length of relocation section is not a multiple of 12")
   722  	}
   723  
   724  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   725  	if err != nil {
   726  		return err
   727  	}
   728  
   729  	b := bytes.NewReader(rels)
   730  	var rela Rela32
   731  
   732  	for b.Len() > 0 {
   733  		binary.Read(b, f.ByteOrder, &rela)
   734  		symNo := rela.Info >> 8
   735  		t := R_PPC(rela.Info & 0xff)
   736  
   737  		if symNo == 0 || symNo > uint32(len(symbols)) {
   738  			continue
   739  		}
   740  		sym := &symbols[symNo-1]
   741  		if SymType(sym.Info&0xf) != STT_SECTION {
   742  			// We don't handle non-section relocations for now.
   743  			continue
   744  		}
   745  
   746  		switch t {
   747  		case R_PPC_ADDR32:
   748  			if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 {
   749  				continue
   750  			}
   751  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   752  		}
   753  	}
   754  
   755  	return nil
   756  }
   757  
   758  func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error {
   759  	// 24 is the size of Rela64.
   760  	if len(rels)%24 != 0 {
   761  		return errors.New("length of relocation section is not a multiple of 24")
   762  	}
   763  
   764  	symbols, _, err := f.getSymbols(SHT_SYMTAB)
   765  	if err != nil {
   766  		return err
   767  	}
   768  
   769  	b := bytes.NewReader(rels)
   770  	var rela Rela64
   771  
   772  	for b.Len() > 0 {
   773  		binary.Read(b, f.ByteOrder, &rela)
   774  		symNo := rela.Info >> 32
   775  		t := R_PPC64(rela.Info & 0xffff)
   776  
   777  		if symNo == 0 || symNo > uint64(len(symbols)) {
   778  			continue
   779  		}
   780  		sym := &symbols[symNo-1]
   781  		if SymType(sym.Info&0xf) != STT_SECTION {
   782  			// We don't handle non-section relocations for now.
   783  			continue
   784  		}
   785  
   786  		switch t {
   787  		case R_PPC64_ADDR64:
   788  			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
   789  				continue
   790  			}
   791  			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
   792  		case R_PPC64_ADDR32:
   793  			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
   794  				continue
   795  			}
   796  			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
   797  		}
   798  	}
   799  
   800  	return nil
   801  }
   802  
   803  func (f *File) DWARF() (*dwarf.Data, error) {
   804  	// sectionData gets the data for s, checks its size, and
   805  	// applies any applicable relations.
   806  	sectionData := func(i int, s *Section) ([]byte, error) {
   807  		b, err := s.Data()
   808  		if err != nil && uint64(len(b)) < s.Size {
   809  			return nil, err
   810  		}
   811  
   812  		for _, r := range f.Sections {
   813  			if r.Type != SHT_RELA && r.Type != SHT_REL {
   814  				continue
   815  			}
   816  			if int(r.Info) != i {
   817  				continue
   818  			}
   819  			rd, err := r.Data()
   820  			if err != nil {
   821  				return nil, err
   822  			}
   823  			err = f.applyRelocations(b, rd)
   824  			if err != nil {
   825  				return nil, err
   826  			}
   827  		}
   828  		return b, nil
   829  	}
   830  
   831  	// There are many other DWARF sections, but these
   832  	// are the ones the debug/dwarf package uses.
   833  	// Don't bother loading others.
   834  	var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil}
   835  	for i, s := range f.Sections {
   836  		if !strings.HasPrefix(s.Name, ".debug_") {
   837  			continue
   838  		}
   839  		if _, ok := dat[s.Name[7:]]; !ok {
   840  			continue
   841  		}
   842  		b, err := sectionData(i, s)
   843  		if err != nil {
   844  			return nil, err
   845  		}
   846  		dat[s.Name[7:]] = b
   847  	}
   848  
   849  	d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, nil, dat["str"])
   850  	if err != nil {
   851  		return nil, err
   852  	}
   853  
   854  	// Look for DWARF4 .debug_types sections.
   855  	for i, s := range f.Sections {
   856  		if s.Name == ".debug_types" {
   857  			b, err := sectionData(i, s)
   858  			if err != nil {
   859  				return nil, err
   860  			}
   861  
   862  			err = d.AddTypes(fmt.Sprintf("types-%d", i), b)
   863  			if err != nil {
   864  				return nil, err
   865  			}
   866  		}
   867  	}
   868  
   869  	return d, nil
   870  }
   871  
   872  // Symbols returns the symbol table for f. The symbols will be listed in the order
   873  // they appear in f.
   874  //
   875  // For compatibility with Go 1.0, Symbols omits the null symbol at index 0.
   876  // After retrieving the symbols as symtab, an externally supplied index x
   877  // corresponds to symtab[x-1], not symtab[x].
   878  func (f *File) Symbols() ([]Symbol, error) {
   879  	sym, _, err := f.getSymbols(SHT_SYMTAB)
   880  	return sym, err
   881  }
   882  
   883  // DynamicSymbols returns the dynamic symbol table for f. The symbols
   884  // will be listed in the order they appear in f.
   885  //
   886  // For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0.
   887  // After retrieving the symbols as symtab, an externally supplied index x
   888  // corresponds to symtab[x-1], not symtab[x].
   889  func (f *File) DynamicSymbols() ([]Symbol, error) {
   890  	sym, _, err := f.getSymbols(SHT_DYNSYM)
   891  	return sym, err
   892  }
   893  
   894  type ImportedSymbol struct {
   895  	Name    string
   896  	Version string
   897  	Library string
   898  }
   899  
   900  // ImportedSymbols returns the names of all symbols
   901  // referred to by the binary f that are expected to be
   902  // satisfied by other libraries at dynamic load time.
   903  // It does not return weak symbols.
   904  func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
   905  	sym, str, err := f.getSymbols(SHT_DYNSYM)
   906  	if err != nil {
   907  		return nil, err
   908  	}
   909  	f.gnuVersionInit(str)
   910  	var all []ImportedSymbol
   911  	for i, s := range sym {
   912  		if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
   913  			all = append(all, ImportedSymbol{Name: s.Name})
   914  			f.gnuVersion(i, &all[len(all)-1])
   915  		}
   916  	}
   917  	return all, nil
   918  }
   919  
   920  type verneed struct {
   921  	File string
   922  	Name string
   923  }
   924  
   925  // gnuVersionInit parses the GNU version tables
   926  // for use by calls to gnuVersion.
   927  func (f *File) gnuVersionInit(str []byte) {
   928  	// Accumulate verneed information.
   929  	vn := f.SectionByType(SHT_GNU_VERNEED)
   930  	if vn == nil {
   931  		return
   932  	}
   933  	d, _ := vn.Data()
   934  
   935  	var need []verneed
   936  	i := 0
   937  	for {
   938  		if i+16 > len(d) {
   939  			break
   940  		}
   941  		vers := f.ByteOrder.Uint16(d[i : i+2])
   942  		if vers != 1 {
   943  			break
   944  		}
   945  		cnt := f.ByteOrder.Uint16(d[i+2 : i+4])
   946  		fileoff := f.ByteOrder.Uint32(d[i+4 : i+8])
   947  		aux := f.ByteOrder.Uint32(d[i+8 : i+12])
   948  		next := f.ByteOrder.Uint32(d[i+12 : i+16])
   949  		file, _ := getString(str, int(fileoff))
   950  
   951  		var name string
   952  		j := i + int(aux)
   953  		for c := 0; c < int(cnt); c++ {
   954  			if j+16 > len(d) {
   955  				break
   956  			}
   957  			// hash := f.ByteOrder.Uint32(d[j:j+4])
   958  			// flags := f.ByteOrder.Uint16(d[j+4:j+6])
   959  			other := f.ByteOrder.Uint16(d[j+6 : j+8])
   960  			nameoff := f.ByteOrder.Uint32(d[j+8 : j+12])
   961  			next := f.ByteOrder.Uint32(d[j+12 : j+16])
   962  			name, _ = getString(str, int(nameoff))
   963  			ndx := int(other)
   964  			if ndx >= len(need) {
   965  				a := make([]verneed, 2*(ndx+1))
   966  				copy(a, need)
   967  				need = a
   968  			}
   969  
   970  			need[ndx] = verneed{file, name}
   971  			if next == 0 {
   972  				break
   973  			}
   974  			j += int(next)
   975  		}
   976  
   977  		if next == 0 {
   978  			break
   979  		}
   980  		i += int(next)
   981  	}
   982  
   983  	// Versym parallels symbol table, indexing into verneed.
   984  	vs := f.SectionByType(SHT_GNU_VERSYM)
   985  	if vs == nil {
   986  		return
   987  	}
   988  	d, _ = vs.Data()
   989  
   990  	f.gnuNeed = need
   991  	f.gnuVersym = d
   992  }
   993  
   994  // gnuVersion adds Library and Version information to sym,
   995  // which came from offset i of the symbol table.
   996  func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
   997  	// Each entry is two bytes.
   998  	i = (i + 1) * 2
   999  	if i >= len(f.gnuVersym) {
  1000  		return
  1001  	}
  1002  	j := int(f.ByteOrder.Uint16(f.gnuVersym[i:]))
  1003  	if j < 2 || j >= len(f.gnuNeed) {
  1004  		return
  1005  	}
  1006  	n := &f.gnuNeed[j]
  1007  	sym.Library = n.File
  1008  	sym.Version = n.Name
  1009  }
  1010  
  1011  // ImportedLibraries returns the names of all libraries
  1012  // referred to by the binary f that are expected to be
  1013  // linked with the binary at dynamic link time.
  1014  func (f *File) ImportedLibraries() ([]string, error) {
  1015  	return f.DynString(DT_NEEDED)
  1016  }
  1017  
  1018  // DynString returns the strings listed for the given tag in the file's dynamic
  1019  // section.
  1020  //
  1021  // The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or
  1022  // DT_RUNPATH.
  1023  func (f *File) DynString(tag DynTag) ([]string, error) {
  1024  	switch tag {
  1025  	case DT_NEEDED, DT_SONAME, DT_RPATH, DT_RUNPATH:
  1026  	default:
  1027  		return nil, fmt.Errorf("non-string-valued tag %v", tag)
  1028  	}
  1029  	ds := f.SectionByType(SHT_DYNAMIC)
  1030  	if ds == nil {
  1031  		// not dynamic, so no libraries
  1032  		return nil, nil
  1033  	}
  1034  	d, err := ds.Data()
  1035  	if err != nil {
  1036  		return nil, err
  1037  	}
  1038  	str, err := f.stringTable(ds.Link)
  1039  	if err != nil {
  1040  		return nil, err
  1041  	}
  1042  	var all []string
  1043  	for len(d) > 0 {
  1044  		var t DynTag
  1045  		var v uint64
  1046  		switch f.Class {
  1047  		case ELFCLASS32:
  1048  			t = DynTag(f.ByteOrder.Uint32(d[0:4]))
  1049  			v = uint64(f.ByteOrder.Uint32(d[4:8]))
  1050  			d = d[8:]
  1051  		case ELFCLASS64:
  1052  			t = DynTag(f.ByteOrder.Uint64(d[0:8]))
  1053  			v = f.ByteOrder.Uint64(d[8:16])
  1054  			d = d[16:]
  1055  		}
  1056  		if t == tag {
  1057  			s, ok := getString(str, int(v))
  1058  			if ok {
  1059  				all = append(all, s)
  1060  			}
  1061  		}
  1062  	}
  1063  	return all, nil
  1064  }