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