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