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