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