Source file src/debug/pe/section.go

     1  // Copyright 2016 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 pe
     6  
     7  import (
     8  	"encoding/binary"
     9  	"fmt"
    10  	"io"
    11  	"strconv"
    12  )
    13  
    14  // SectionHeader32 represents real PE COFF section header.
    15  type SectionHeader32 struct {
    16  	Name                 [8]uint8
    17  	VirtualSize          uint32
    18  	VirtualAddress       uint32
    19  	SizeOfRawData        uint32
    20  	PointerToRawData     uint32
    21  	PointerToRelocations uint32
    22  	PointerToLineNumbers uint32
    23  	NumberOfRelocations  uint16
    24  	NumberOfLineNumbers  uint16
    25  	Characteristics      uint32
    26  }
    27  
    28  // fullName finds real name of section sh. Normally name is stored
    29  // in sh.Name, but if it is longer then 8 characters, it is stored
    30  // in COFF string table st instead.
    31  func (sh *SectionHeader32) fullName(st StringTable) (string, error) {
    32  	if sh.Name[0] != '/' {
    33  		return cstring(sh.Name[:]), nil
    34  	}
    35  	i, err := strconv.Atoi(cstring(sh.Name[1:]))
    36  	if err != nil {
    37  		return "", err
    38  	}
    39  	return st.String(uint32(i))
    40  }
    41  
    42  // TODO(brainman): copy all IMAGE_REL_* consts from ldpe.go here
    43  
    44  // Reloc represents a PE COFF relocation.
    45  // Each section contains its own relocation list.
    46  type Reloc struct {
    47  	VirtualAddress   uint32
    48  	SymbolTableIndex uint32
    49  	Type             uint16
    50  }
    51  
    52  func readRelocs(sh *SectionHeader, r io.ReadSeeker) ([]Reloc, error) {
    53  	if sh.NumberOfRelocations <= 0 {
    54  		return nil, nil
    55  	}
    56  	_, err := r.Seek(int64(sh.PointerToRelocations), seekStart)
    57  	if err != nil {
    58  		return nil, fmt.Errorf("fail to seek to %q section relocations: %v", sh.Name, err)
    59  	}
    60  	relocs := make([]Reloc, sh.NumberOfRelocations)
    61  	err = binary.Read(r, binary.LittleEndian, relocs)
    62  	if err != nil {
    63  		return nil, fmt.Errorf("fail to read section relocations: %v", err)
    64  	}
    65  	return relocs, nil
    66  }
    67  
    68  // SectionHeader is similar to SectionHeader32 with Name
    69  // field replaced by Go string.
    70  type SectionHeader struct {
    71  	Name                 string
    72  	VirtualSize          uint32
    73  	VirtualAddress       uint32
    74  	Size                 uint32
    75  	Offset               uint32
    76  	PointerToRelocations uint32
    77  	PointerToLineNumbers uint32
    78  	NumberOfRelocations  uint16
    79  	NumberOfLineNumbers  uint16
    80  	Characteristics      uint32
    81  }
    82  
    83  // Section provides access to PE COFF section.
    84  type Section struct {
    85  	SectionHeader
    86  	Relocs []Reloc
    87  
    88  	// Embed ReaderAt for ReadAt method.
    89  	// Do not embed SectionReader directly
    90  	// to avoid having Read and Seek.
    91  	// If a client wants Read and Seek it must use
    92  	// Open() to avoid fighting over the seek offset
    93  	// with other clients.
    94  	io.ReaderAt
    95  	sr *io.SectionReader
    96  }
    97  
    98  // Data reads and returns the contents of the PE section s.
    99  func (s *Section) Data() ([]byte, error) {
   100  	dat := make([]byte, s.sr.Size())
   101  	n, err := s.sr.ReadAt(dat, 0)
   102  	if n == len(dat) {
   103  		err = nil
   104  	}
   105  	return dat[0:n], err
   106  }
   107  
   108  // Open returns a new ReadSeeker reading the PE section s.
   109  func (s *Section) Open() io.ReadSeeker {
   110  	return io.NewSectionReader(s.sr, 0, 1<<63-1)
   111  }
   112  

View as plain text