...

Source file src/pkg/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