Home | History | Annotate | Download | only in 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 // 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 }
   1336