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

View as plain text