summaryrefslogtreecommitdiffstats
path: root/src/debug/pe/section.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug/pe/section.go')
-rw-r--r--src/debug/pe/section.go125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/debug/pe/section.go b/src/debug/pe/section.go
new file mode 100644
index 0000000..70d0c22
--- /dev/null
+++ b/src/debug/pe/section.go
@@ -0,0 +1,125 @@
+// 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"
+ "internal/saferio"
+ "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.
+//
+// If s.Offset is 0, the section has no contents,
+// and Data will always return a non-nil error.
+func (s *Section) Data() ([]byte, error) {
+ return saferio.ReadDataAt(s.sr, uint64(s.Size), 0)
+}
+
+// Open returns a new ReadSeeker reading the PE section s.
+//
+// If s.Offset is 0, the section has no contents, and all calls
+// to the returned reader will return a non-nil error.
+func (s *Section) Open() io.ReadSeeker {
+ return io.NewSectionReader(s.sr, 0, 1<<63-1)
+}
+
+// Section characteristics flags.
+const (
+ IMAGE_SCN_CNT_CODE = 0x00000020
+ IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040
+ IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
+ IMAGE_SCN_LNK_COMDAT = 0x00001000
+ IMAGE_SCN_MEM_DISCARDABLE = 0x02000000
+ IMAGE_SCN_MEM_EXECUTE = 0x20000000
+ IMAGE_SCN_MEM_READ = 0x40000000
+ IMAGE_SCN_MEM_WRITE = 0x80000000
+)