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