...
Run Format

Source file src/debug/elf/file.go

Documentation: debug/elf

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

View as plain text