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