...
Run Format

Source file src/debug/pe/section.go

Documentation: debug/pe

  // Copyright 2016 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  package pe
  
  import (
  	"encoding/binary"
  	"fmt"
  	"io"
  	"strconv"
  )
  
  // SectionHeader32 represents real PE COFF section header.
  type SectionHeader32 struct {
  	Name                 [8]uint8
  	VirtualSize          uint32
  	VirtualAddress       uint32
  	SizeOfRawData        uint32
  	PointerToRawData     uint32
  	PointerToRelocations uint32
  	PointerToLineNumbers uint32
  	NumberOfRelocations  uint16
  	NumberOfLineNumbers  uint16
  	Characteristics      uint32
  }
  
  // fullName finds real name of section sh. Normally name is stored
  // in sh.Name, but if it is longer then 8 characters, it is stored
  // in COFF string table st instead.
  func (sh *SectionHeader32) fullName(st StringTable) (string, error) {
  	if sh.Name[0] != '/' {
  		return cstring(sh.Name[:]), nil
  	}
  	i, err := strconv.Atoi(cstring(sh.Name[1:]))
  	if err != nil {
  		return "", err
  	}
  	return st.String(uint32(i))
  }
  
  // TODO(brainman): copy all IMAGE_REL_* consts from ldpe.go here
  
  // Reloc represents a PE COFF relocation.
  // Each section contains its own relocation list.
  type Reloc struct {
  	VirtualAddress   uint32
  	SymbolTableIndex uint32
  	Type             uint16
  }
  
  func readRelocs(sh *SectionHeader, r io.ReadSeeker) ([]Reloc, error) {
  	if sh.NumberOfRelocations <= 0 {
  		return nil, nil
  	}
  	_, err := r.Seek(int64(sh.PointerToRelocations), seekStart)
  	if err != nil {
  		return nil, fmt.Errorf("fail to seek to %q section relocations: %v", sh.Name, err)
  	}
  	relocs := make([]Reloc, sh.NumberOfRelocations)
  	err = binary.Read(r, binary.LittleEndian, relocs)
  	if err != nil {
  		return nil, fmt.Errorf("fail to read section relocations: %v", err)
  	}
  	return relocs, nil
  }
  
  // SectionHeader is similar to SectionHeader32 with Name
  // field replaced by Go string.
  type SectionHeader struct {
  	Name                 string
  	VirtualSize          uint32
  	VirtualAddress       uint32
  	Size                 uint32
  	Offset               uint32
  	PointerToRelocations uint32
  	PointerToLineNumbers uint32
  	NumberOfRelocations  uint16
  	NumberOfLineNumbers  uint16
  	Characteristics      uint32
  }
  
  // Section provides access to PE COFF section.
  type Section struct {
  	SectionHeader
  	Relocs []Reloc
  
  	// Embed ReaderAt for ReadAt method.
  	// Do not embed SectionReader directly
  	// to avoid having Read and Seek.
  	// If a client wants Read and Seek it must use
  	// Open() to avoid fighting over the seek offset
  	// with other clients.
  	io.ReaderAt
  	sr *io.SectionReader
  }
  
  // Data reads and returns the contents of the PE section s.
  func (s *Section) Data() ([]byte, error) {
  	dat := make([]byte, s.sr.Size())
  	n, err := s.sr.ReadAt(dat, 0)
  	if n == len(dat) {
  		err = nil
  	}
  	return dat[0:n], err
  }
  
  // Open returns a new ReadSeeker reading the PE section s.
  func (s *Section) Open() io.ReadSeeker {
  	return io.NewSectionReader(s.sr, 0, 1<<63-1)
  }
  

View as plain text