Home | History | Annotate | Download | only in elf
      1 // Copyright 2009 The Go Authors.  All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // Package elf implements access to ELF object files.
      6 package elf
      7 
      8 import (
      9 	"bytes"
     10 	"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.
     26 type 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.
     39 type 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.
     49 type 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.
     63 type 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.
     77 func (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.
     88 func (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.
     96 func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }
     97 
     98 // A ProgHeader represents a single ELF program header.
     99 type 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.
    111 type 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.
    125 func (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.
    128 type Symbol struct {
    129 	Name        string
    130 	Info, Other byte
    131 	Section     SectionIndex
    132 	Value, Size uint64
    133 }
    134 
    135 /*
    136  * ELF reader
    137  */
    138 
    139 type FormatError struct {
    140 	off int64
    141 	msg string
    142 	val interface{}
    143 }
    144 
    145 func (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.
    155 func 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.
    172 func (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.
    183 func (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.
    194 func 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.
    397 func (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.
    411 var ErrNoSymbols = errors.New("no symbol section")
    412 
    413 func (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 
    456 func (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.
    500 func 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.
    515 func (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.
    526 func (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 	default:
    541 		return errors.New("applyRelocations: not implemented")
    542 	}
    543 }
    544 
    545 func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
    546 	// 24 is the size of Rela64.
    547 	if len(rels)%24 != 0 {
    548 		return errors.New("length of relocation section is not a multiple of 24")
    549 	}
    550 
    551 	symbols, _, err := f.getSymbols(SHT_SYMTAB)
    552 	if err != nil {
    553 		return err
    554 	}
    555 
    556 	b := bytes.NewReader(rels)
    557 	var rela Rela64
    558 
    559 	for b.Len() > 0 {
    560 		binary.Read(b, f.ByteOrder, &rela)
    561 		symNo := rela.Info >> 32
    562 		t := R_X86_64(rela.Info & 0xffff)
    563 
    564 		if symNo == 0 || symNo > uint64(len(symbols)) {
    565 			continue
    566 		}
    567 		sym := &symbols[symNo-1]
    568 		if SymType(sym.Info&0xf) != STT_SECTION {
    569 			// We don't handle non-section relocations for now.
    570 			continue
    571 		}
    572 
    573 		// There are relocations, so this must be a normal
    574 		// object file, and we only look at section symbols,
    575 		// so we assume that the symbol value is 0.
    576 
    577 		switch t {
    578 		case R_X86_64_64:
    579 			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
    580 				continue
    581 			}
    582 			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
    583 		case R_X86_64_32:
    584 			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
    585 				continue
    586 			}
    587 			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
    588 		}
    589 	}
    590 
    591 	return nil
    592 }
    593 
    594 func (f *File) applyRelocations386(dst []byte, rels []byte) error {
    595 	// 8 is the size of Rel32.
    596 	if len(rels)%8 != 0 {
    597 		return errors.New("length of relocation section is not a multiple of 8")
    598 	}
    599 
    600 	symbols, _, err := f.getSymbols(SHT_SYMTAB)
    601 	if err != nil {
    602 		return err
    603 	}
    604 
    605 	b := bytes.NewReader(rels)
    606 	var rel Rel32
    607 
    608 	for b.Len() > 0 {
    609 		binary.Read(b, f.ByteOrder, &rel)
    610 		symNo := rel.Info >> 8
    611 		t := R_386(rel.Info & 0xff)
    612 
    613 		if symNo == 0 || symNo > uint32(len(symbols)) {
    614 			continue
    615 		}
    616 		sym := &symbols[symNo-1]
    617 
    618 		if t == R_386_32 {
    619 			if rel.Off+4 >= uint32(len(dst)) {
    620 				continue
    621 			}
    622 			val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
    623 			val += uint32(sym.Value)
    624 			f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
    625 		}
    626 	}
    627 
    628 	return nil
    629 }
    630 
    631 func (f *File) applyRelocationsARM(dst []byte, rels []byte) error {
    632 	// 8 is the size of Rel32.
    633 	if len(rels)%8 != 0 {
    634 		return errors.New("length of relocation section is not a multiple of 8")
    635 	}
    636 
    637 	symbols, _, err := f.getSymbols(SHT_SYMTAB)
    638 	if err != nil {
    639 		return err
    640 	}
    641 
    642 	b := bytes.NewReader(rels)
    643 	var rel Rel32
    644 
    645 	for b.Len() > 0 {
    646 		binary.Read(b, f.ByteOrder, &rel)
    647 		symNo := rel.Info >> 8
    648 		t := R_ARM(rel.Info & 0xff)
    649 
    650 		if symNo == 0 || symNo > uint32(len(symbols)) {
    651 			continue
    652 		}
    653 		sym := &symbols[symNo-1]
    654 
    655 		switch t {
    656 		case R_ARM_ABS32:
    657 			if rel.Off+4 >= uint32(len(dst)) {
    658 				continue
    659 			}
    660 			val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
    661 			val += uint32(sym.Value)
    662 			f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
    663 		}
    664 	}
    665 
    666 	return nil
    667 }
    668 
    669 func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error {
    670 	// 24 is the size of Rela64.
    671 	if len(rels)%24 != 0 {
    672 		return errors.New("length of relocation section is not a multiple of 24")
    673 	}
    674 
    675 	symbols, _, err := f.getSymbols(SHT_SYMTAB)
    676 	if err != nil {
    677 		return err
    678 	}
    679 
    680 	b := bytes.NewReader(rels)
    681 	var rela Rela64
    682 
    683 	for b.Len() > 0 {
    684 		binary.Read(b, f.ByteOrder, &rela)
    685 		symNo := rela.Info >> 32
    686 		t := R_AARCH64(rela.Info & 0xffff)
    687 
    688 		if symNo == 0 || symNo > uint64(len(symbols)) {
    689 			continue
    690 		}
    691 		sym := &symbols[symNo-1]
    692 		if SymType(sym.Info&0xf) != STT_SECTION {
    693 			// We don't handle non-section relocations for now.
    694 			continue
    695 		}
    696 
    697 		// There are relocations, so this must be a normal
    698 		// object file, and we only look at section symbols,
    699 		// so we assume that the symbol value is 0.
    700 
    701 		switch t {
    702 		case R_AARCH64_ABS64:
    703 			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
    704 				continue
    705 			}
    706 			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
    707 		case R_AARCH64_ABS32:
    708 			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
    709 				continue
    710 			}
    711 			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
    712 		}
    713 	}
    714 
    715 	return nil
    716 }
    717 
    718 func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error {
    719 	// 12 is the size of Rela32.
    720 	if len(rels)%12 != 0 {
    721 		return errors.New("length of relocation section is not a multiple of 12")
    722 	}
    723 
    724 	symbols, _, err := f.getSymbols(SHT_SYMTAB)
    725 	if err != nil {
    726 		return err
    727 	}
    728 
    729 	b := bytes.NewReader(rels)
    730 	var rela Rela32
    731 
    732 	for b.Len() > 0 {
    733 		binary.Read(b, f.ByteOrder, &rela)
    734 		symNo := rela.Info >> 8
    735 		t := R_PPC(rela.Info & 0xff)
    736 
    737 		if symNo == 0 || symNo > uint32(len(symbols)) {
    738 			continue
    739 		}
    740 		sym := &symbols[symNo-1]
    741 		if SymType(sym.Info&0xf) != STT_SECTION {
    742 			// We don't handle non-section relocations for now.
    743 			continue
    744 		}
    745 
    746 		switch t {
    747 		case R_PPC_ADDR32:
    748 			if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 {
    749 				continue
    750 			}
    751 			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
    752 		}
    753 	}
    754 
    755 	return nil
    756 }
    757 
    758 func (f *File) applyRelocationsPPC64(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_PPC64(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 		switch t {
    787 		case R_PPC64_ADDR64:
    788 			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
    789 				continue
    790 			}
    791 			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
    792 		case R_PPC64_ADDR32:
    793 			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
    794 				continue
    795 			}
    796 			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
    797 		}
    798 	}
    799 
    800 	return nil
    801 }
    802 
    803 func (f *File) DWARF() (*dwarf.Data, error) {
    804 	// sectionData gets the data for s, checks its size, and
    805 	// applies any applicable relations.
    806 	sectionData := func(i int, s *Section) ([]byte, error) {
    807 		b, err := s.Data()
    808 		if err != nil && uint64(len(b)) < s.Size {
    809 			return nil, err
    810 		}
    811 
    812 		for _, r := range f.Sections {
    813 			if r.Type != SHT_RELA && r.Type != SHT_REL {
    814 				continue
    815 			}
    816 			if int(r.Info) != i {
    817 				continue
    818 			}
    819 			rd, err := r.Data()
    820 			if err != nil {
    821 				return nil, err
    822 			}
    823 			err = f.applyRelocations(b, rd)
    824 			if err != nil {
    825 				return nil, err
    826 			}
    827 		}
    828 		return b, nil
    829 	}
    830 
    831 	// There are many other DWARF sections, but these
    832 	// are the ones the debug/dwarf package uses.
    833 	// Don't bother loading others.
    834 	var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil}
    835 	for i, s := range f.Sections {
    836 		if !strings.HasPrefix(s.Name, ".debug_") {
    837 			continue
    838 		}
    839 		if _, ok := dat[s.Name[7:]]; !ok {
    840 			continue
    841 		}
    842 		b, err := sectionData(i, s)
    843 		if err != nil {
    844 			return nil, err
    845 		}
    846 		dat[s.Name[7:]] = b
    847 	}
    848 
    849 	d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, nil, dat["str"])
    850 	if err != nil {
    851 		return nil, err
    852 	}
    853 
    854 	// Look for DWARF4 .debug_types sections.
    855 	for i, s := range f.Sections {
    856 		if s.Name == ".debug_types" {
    857 			b, err := sectionData(i, s)
    858 			if err != nil {
    859 				return nil, err
    860 			}
    861 
    862 			err = d.AddTypes(fmt.Sprintf("types-%d", i), b)
    863 			if err != nil {
    864 				return nil, err
    865 			}
    866 		}
    867 	}
    868 
    869 	return d, nil
    870 }
    871 
    872 // Symbols returns the symbol table for f. The symbols will be listed in the order
    873 // they appear in f.
    874 //
    875 // For compatibility with Go 1.0, Symbols omits the null symbol at index 0.
    876 // After retrieving the symbols as symtab, an externally supplied index x
    877 // corresponds to symtab[x-1], not symtab[x].
    878 func (f *File) Symbols() ([]Symbol, error) {
    879 	sym, _, err := f.getSymbols(SHT_SYMTAB)
    880 	return sym, err
    881 }
    882 
    883 // DynamicSymbols returns the dynamic symbol table for f. The symbols
    884 // will be listed in the order they appear in f.
    885 //
    886 // For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0.
    887 // After retrieving the symbols as symtab, an externally supplied index x
    888 // corresponds to symtab[x-1], not symtab[x].
    889 func (f *File) DynamicSymbols() ([]Symbol, error) {
    890 	sym, _, err := f.getSymbols(SHT_DYNSYM)
    891 	return sym, err
    892 }
    893 
    894 type ImportedSymbol struct {
    895 	Name    string
    896 	Version string
    897 	Library string
    898 }
    899 
    900 // ImportedSymbols returns the names of all symbols
    901 // referred to by the binary f that are expected to be
    902 // satisfied by other libraries at dynamic load time.
    903 // It does not return weak symbols.
    904 func (f *File) ImportedSymbols() ([]ImportedSymbol, error) {
    905 	sym, str, err := f.getSymbols(SHT_DYNSYM)
    906 	if err != nil {
    907 		return nil, err
    908 	}
    909 	f.gnuVersionInit(str)
    910 	var all []ImportedSymbol
    911 	for i, s := range sym {
    912 		if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF {
    913 			all = append(all, ImportedSymbol{Name: s.Name})
    914 			f.gnuVersion(i, &all[len(all)-1])
    915 		}
    916 	}
    917 	return all, nil
    918 }
    919 
    920 type verneed struct {
    921 	File string
    922 	Name string
    923 }
    924 
    925 // gnuVersionInit parses the GNU version tables
    926 // for use by calls to gnuVersion.
    927 func (f *File) gnuVersionInit(str []byte) {
    928 	// Accumulate verneed information.
    929 	vn := f.SectionByType(SHT_GNU_VERNEED)
    930 	if vn == nil {
    931 		return
    932 	}
    933 	d, _ := vn.Data()
    934 
    935 	var need []verneed
    936 	i := 0
    937 	for {
    938 		if i+16 > len(d) {
    939 			break
    940 		}
    941 		vers := f.ByteOrder.Uint16(d[i : i+2])
    942 		if vers != 1 {
    943 			break
    944 		}
    945 		cnt := f.ByteOrder.Uint16(d[i+2 : i+4])
    946 		fileoff := f.ByteOrder.Uint32(d[i+4 : i+8])
    947 		aux := f.ByteOrder.Uint32(d[i+8 : i+12])
    948 		next := f.ByteOrder.Uint32(d[i+12 : i+16])
    949 		file, _ := getString(str, int(fileoff))
    950 
    951 		var name string
    952 		j := i + int(aux)
    953 		for c := 0; c < int(cnt); c++ {
    954 			if j+16 > len(d) {
    955 				break
    956 			}
    957 			// hash := f.ByteOrder.Uint32(d[j:j+4])
    958 			// flags := f.ByteOrder.Uint16(d[j+4:j+6])
    959 			other := f.ByteOrder.Uint16(d[j+6 : j+8])
    960 			nameoff := f.ByteOrder.Uint32(d[j+8 : j+12])
    961 			next := f.ByteOrder.Uint32(d[j+12 : j+16])
    962 			name, _ = getString(str, int(nameoff))
    963 			ndx := int(other)
    964 			if ndx >= len(need) {
    965 				a := make([]verneed, 2*(ndx+1))
    966 				copy(a, need)
    967 				need = a
    968 			}
    969 
    970 			need[ndx] = verneed{file, name}
    971 			if next == 0 {
    972 				break
    973 			}
    974 			j += int(next)
    975 		}
    976 
    977 		if next == 0 {
    978 			break
    979 		}
    980 		i += int(next)
    981 	}
    982 
    983 	// Versym parallels symbol table, indexing into verneed.
    984 	vs := f.SectionByType(SHT_GNU_VERSYM)
    985 	if vs == nil {
    986 		return
    987 	}
    988 	d, _ = vs.Data()
    989 
    990 	f.gnuNeed = need
    991 	f.gnuVersym = d
    992 }
    993 
    994 // gnuVersion adds Library and Version information to sym,
    995 // which came from offset i of the symbol table.
    996 func (f *File) gnuVersion(i int, sym *ImportedSymbol) {
    997 	// Each entry is two bytes.
    998 	i = (i + 1) * 2
    999 	if i >= len(f.gnuVersym) {
   1000 		return
   1001 	}
   1002 	j := int(f.ByteOrder.Uint16(f.gnuVersym[i:]))
   1003 	if j < 2 || j >= len(f.gnuNeed) {
   1004 		return
   1005 	}
   1006 	n := &f.gnuNeed[j]
   1007 	sym.Library = n.File
   1008 	sym.Version = n.Name
   1009 }
   1010 
   1011 // ImportedLibraries returns the names of all libraries
   1012 // referred to by the binary f that are expected to be
   1013 // linked with the binary at dynamic link time.
   1014 func (f *File) ImportedLibraries() ([]string, error) {
   1015 	return f.DynString(DT_NEEDED)
   1016 }
   1017 
   1018 // DynString returns the strings listed for the given tag in the file's dynamic
   1019 // section.
   1020 //
   1021 // The tag must be one that takes string values: DT_NEEDED, DT_SONAME, DT_RPATH, or
   1022 // DT_RUNPATH.
   1023 func (f *File) DynString(tag DynTag) ([]string, error) {
   1024 	switch tag {
   1025 	case DT_NEEDED, DT_SONAME, DT_RPATH, DT_RUNPATH:
   1026 	default:
   1027 		return nil, fmt.Errorf("non-string-valued tag %v", tag)
   1028 	}
   1029 	ds := f.SectionByType(SHT_DYNAMIC)
   1030 	if ds == nil {
   1031 		// not dynamic, so no libraries
   1032 		return nil, nil
   1033 	}
   1034 	d, err := ds.Data()
   1035 	if err != nil {
   1036 		return nil, err
   1037 	}
   1038 	str, err := f.stringTable(ds.Link)
   1039 	if err != nil {
   1040 		return nil, err
   1041 	}
   1042 	var all []string
   1043 	for len(d) > 0 {
   1044 		var t DynTag
   1045 		var v uint64
   1046 		switch f.Class {
   1047 		case ELFCLASS32:
   1048 			t = DynTag(f.ByteOrder.Uint32(d[0:4]))
   1049 			v = uint64(f.ByteOrder.Uint32(d[4:8]))
   1050 			d = d[8:]
   1051 		case ELFCLASS64:
   1052 			t = DynTag(f.ByteOrder.Uint64(d[0:8]))
   1053 			v = f.ByteOrder.Uint64(d[8:16])
   1054 			d = d[16:]
   1055 		}
   1056 		if t == tag {
   1057 			s, ok := getString(str, int(v))
   1058 			if ok {
   1059 				all = append(all, s)
   1060 			}
   1061 		}
   1062 	}
   1063 	return all, nil
   1064 }
   1065