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