...
Run Format

Source file src/debug/elf/file.go

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

View as plain text