summaryrefslogtreecommitdiff
path: root/src/pkg/debug/pe
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/debug/pe')
-rw-r--r--src/pkg/debug/pe/file.go56
-rw-r--r--src/pkg/debug/pe/file_test.go139
-rw-r--r--src/pkg/debug/pe/pe.go72
-rw-r--r--src/pkg/debug/pe/testdata/gcc-amd64-mingw-execbin0 -> 37376 bytes
-rw-r--r--src/pkg/debug/pe/testdata/gcc-amd64-mingw-objbin0 -> 736 bytes
5 files changed, 238 insertions, 29 deletions
diff --git a/src/pkg/debug/pe/file.go b/src/pkg/debug/pe/file.go
index f521566ef..ce6f1408f 100644
--- a/src/pkg/debug/pe/file.go
+++ b/src/pkg/debug/pe/file.go
@@ -13,13 +13,15 @@ import (
"io"
"os"
"strconv"
+ "unsafe"
)
// A File represents an open PE file.
type File struct {
FileHeader
- Sections []*Section
- Symbols []*Symbol
+ OptionalHeader interface{} // of type *OptionalHeader32 or *OptionalHeader64
+ Sections []*Section
+ Symbols []*Symbol
closer io.Closer
}
@@ -72,6 +74,9 @@ type ImportDirectory struct {
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
}
@@ -193,10 +198,33 @@ func NewFile(r io.ReaderAt) (*File, error) {
}
}
- // Process sections.
+ // Read optional header.
sr.Seek(base, os.SEEK_SET)
- binary.Read(sr, binary.LittleEndian, &f.FileHeader)
- sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), os.SEEK_CUR) //Skip OptionalHeader
+ if err := binary.Read(sr, binary.LittleEndian, &f.FileHeader); err != nil {
+ return nil, err
+ }
+ var oh32 OptionalHeader32
+ var oh64 OptionalHeader64
+ switch uintptr(f.FileHeader.SizeOfOptionalHeader) {
+ case unsafe.Sizeof(oh32):
+ if err := binary.Read(sr, binary.LittleEndian, &oh32); err != nil {
+ return nil, err
+ }
+ if oh32.Magic != 0x10b { // PE32
+ return nil, fmt.Errorf("pe32 optional header has unexpected Magic of 0x%x", oh32.Magic)
+ }
+ f.OptionalHeader = &oh32
+ case unsafe.Sizeof(oh64):
+ if err := binary.Read(sr, binary.LittleEndian, &oh64); err != nil {
+ return nil, err
+ }
+ if oh64.Magic != 0x20b { // PE32+
+ return nil, fmt.Errorf("pe32+ optional header has unexpected Magic of 0x%x", oh64.Magic)
+ }
+ f.OptionalHeader = &oh64
+ }
+
+ // Process sections.
f.Sections = make([]*Section, f.FileHeader.NumberOfSections)
for i := 0; i < int(f.FileHeader.NumberOfSections); i++ {
sh := new(SectionHeader32)
@@ -213,15 +241,15 @@ func NewFile(r io.ReaderAt) (*File, error) {
s := new(Section)
s.SectionHeader = SectionHeader{
Name: name,
- VirtualSize: uint32(sh.VirtualSize),
- VirtualAddress: uint32(sh.VirtualAddress),
- Size: uint32(sh.SizeOfRawData),
- Offset: uint32(sh.PointerToRawData),
- PointerToRelocations: uint32(sh.PointerToRelocations),
- PointerToLineNumbers: uint32(sh.PointerToLineNumbers),
- NumberOfRelocations: uint16(sh.NumberOfRelocations),
- NumberOfLineNumbers: uint16(sh.NumberOfLineNumbers),
- Characteristics: uint32(sh.Characteristics),
+ VirtualSize: sh.VirtualSize,
+ VirtualAddress: sh.VirtualAddress,
+ Size: sh.SizeOfRawData,
+ Offset: sh.PointerToRawData,
+ PointerToRelocations: sh.PointerToRelocations,
+ PointerToLineNumbers: sh.PointerToLineNumbers,
+ NumberOfRelocations: sh.NumberOfRelocations,
+ NumberOfLineNumbers: sh.NumberOfLineNumbers,
+ Characteristics: sh.Characteristics,
}
s.sr = io.NewSectionReader(r, int64(s.SectionHeader.Offset), int64(s.SectionHeader.Size))
s.ReaderAt = s.sr
diff --git a/src/pkg/debug/pe/file_test.go b/src/pkg/debug/pe/file_test.go
index c0f9fcb95..ddbb27174 100644
--- a/src/pkg/debug/pe/file_test.go
+++ b/src/pkg/debug/pe/file_test.go
@@ -12,6 +12,7 @@ import (
type fileTest struct {
file string
hdr FileHeader
+ opthdr interface{}
sections []*SectionHeader
symbols []*Symbol
}
@@ -20,6 +21,7 @@ var fileTests = []fileTest{
{
"testdata/gcc-386-mingw-obj",
FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104},
+ nil,
[]*SectionHeader{
{".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
{".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
@@ -56,27 +58,130 @@ var fileTests = []fileTest{
{
"testdata/gcc-386-mingw-exec",
FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107},
+ &OptionalHeader32{
+ 0x10b, 0x2, 0x38, 0xe00, 0x1a00, 0x200, 0x1160, 0x1000, 0x2000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x1, 0x0, 0x4, 0x0, 0x0, 0x10000, 0x400, 0x14abb, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10,
+ [16]DataDirectory{
+ {0x0, 0x0},
+ {0x5000, 0x3c8},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x7000, 0x18},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ },
+ },
+ []*SectionHeader{
+ {".text", 0xcd8, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
+ {".data", 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
+ {".rdata", 0x120, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
+ {".bss", 0xdc, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0400080},
+ {".idata", 0x3c8, 0x5000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
+ {".CRT", 0x18, 0x6000, 0x200, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
+ {".tls", 0x20, 0x7000, 0x200, 0x1c00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
+ {".debug_aranges", 0x20, 0x8000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+ {".debug_pubnames", 0x51, 0x9000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+ {".debug_pubtypes", 0x91, 0xa000, 0x200, 0x2200, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+ {".debug_info", 0xe22, 0xb000, 0x1000, 0x2400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+ {".debug_abbrev", 0x157, 0xc000, 0x200, 0x3400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+ {".debug_line", 0x144, 0xd000, 0x200, 0x3600, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+ {".debug_frame", 0x34, 0xe000, 0x200, 0x3800, 0x0, 0x0, 0x0, 0x0, 0x42300000},
+ {".debug_loc", 0x38, 0xf000, 0x200, 0x3a00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
+ },
+ []*Symbol{},
+ },
+ {
+ "testdata/gcc-amd64-mingw-obj",
+ FileHeader{0x8664, 0x6, 0x0, 0x198, 0x12, 0x0, 0x4},
+ nil,
+ []*SectionHeader{
+ {".text", 0x0, 0x0, 0x30, 0x104, 0x15c, 0x0, 0x3, 0x0, 0x60500020},
+ {".data", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
+ {".bss", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500080},
+ {".rdata", 0x0, 0x0, 0x10, 0x134, 0x0, 0x0, 0x0, 0x0, 0x40500040},
+ {".xdata", 0x0, 0x0, 0xc, 0x144, 0x0, 0x0, 0x0, 0x0, 0x40300040},
+ {".pdata", 0x0, 0x0, 0xc, 0x150, 0x17a, 0x0, 0x3, 0x0, 0x40300040},
+ },
+ []*Symbol{
+ {".file", 0x0, -2, 0x0, 0x67},
+ {"main", 0x0, 1, 0x20, 0x2},
+ {".text", 0x0, 1, 0x0, 0x3},
+ {".data", 0x0, 2, 0x0, 0x3},
+ {".bss", 0x0, 3, 0x0, 0x3},
+ {".rdata", 0x0, 4, 0x0, 0x3},
+ {".xdata", 0x0, 5, 0x0, 0x3},
+ {".pdata", 0x0, 6, 0x0, 0x3},
+ {"__main", 0x0, 0, 0x20, 0x2},
+ {"puts", 0x0, 0, 0x20, 0x2},
+ },
+ },
+ {
+ "testdata/gcc-amd64-mingw-exec",
+ FileHeader{0x8664, 0x9, 0x53472993, 0x0, 0x0, 0xf0, 0x22f},
+ &OptionalHeader64{
+ 0x20b, 0x2, 0x16, 0x6a00, 0x2400, 0x1600, 0x14e0, 0x1000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x0, 0x0, 0x5, 0x2, 0x0, 0x11000, 0x400, 0x1841e, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10,
+ [16]DataDirectory{
+ {0x0, 0x0},
+ {0xe000, 0x990},
+ {0x0, 0x0},
+ {0xa000, 0x498},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x10000, 0x28},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0xe254, 0x218},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ {0x0, 0x0},
+ },
+ },
[]*SectionHeader{
- {Name: ".text", VirtualSize: 0xcd8, VirtualAddress: 0x1000, Size: 0xe00, Offset: 0x400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x60500060},
- {Name: ".data", VirtualSize: 0x10, VirtualAddress: 0x2000, Size: 0x200, Offset: 0x1200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
- {Name: ".rdata", VirtualSize: 0x120, VirtualAddress: 0x3000, Size: 0x200, Offset: 0x1400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x40300040},
- {Name: ".bss", VirtualSize: 0xdc, VirtualAddress: 0x4000, Size: 0x0, Offset: 0x0, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0400080},
- {Name: ".idata", VirtualSize: 0x3c8, VirtualAddress: 0x5000, Size: 0x400, Offset: 0x1600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
- {Name: ".CRT", VirtualSize: 0x18, VirtualAddress: 0x6000, Size: 0x200, Offset: 0x1a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
- {Name: ".tls", VirtualSize: 0x20, VirtualAddress: 0x7000, Size: 0x200, Offset: 0x1c00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
- {Name: ".debug_aranges", VirtualSize: 0x20, VirtualAddress: 0x8000, Size: 0x200, Offset: 0x1e00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
- {Name: ".debug_pubnames", VirtualSize: 0x51, VirtualAddress: 0x9000, Size: 0x200, Offset: 0x2000, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
- {Name: ".debug_pubtypes", VirtualSize: 0x91, VirtualAddress: 0xa000, Size: 0x200, Offset: 0x2200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
- {Name: ".debug_info", VirtualSize: 0xe22, VirtualAddress: 0xb000, Size: 0x1000, Offset: 0x2400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
- {Name: ".debug_abbrev", VirtualSize: 0x157, VirtualAddress: 0xc000, Size: 0x200, Offset: 0x3400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
- {Name: ".debug_line", VirtualSize: 0x144, VirtualAddress: 0xd000, Size: 0x200, Offset: 0x3600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
- {Name: ".debug_frame", VirtualSize: 0x34, VirtualAddress: 0xe000, Size: 0x200, Offset: 0x3800, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42300000},
- {Name: ".debug_loc", VirtualSize: 0x38, VirtualAddress: 0xf000, Size: 0x200, Offset: 0x3a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
+ {".text", 0x6860, 0x1000, 0x6a00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500020},
+ {".data", 0xe0, 0x8000, 0x200, 0x6e00, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
+ {".rdata", 0x6b0, 0x9000, 0x800, 0x7000, 0x0, 0x0, 0x0, 0x0, 0x40600040},
+ {".pdata", 0x498, 0xa000, 0x600, 0x7800, 0x0, 0x0, 0x0, 0x0, 0x40300040},
+ {".xdata", 0x488, 0xb000, 0x600, 0x7e00, 0x0, 0x0, 0x0, 0x0, 0x40300040},
+ {".bss", 0x1410, 0xc000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0600080},
+ {".idata", 0x990, 0xe000, 0xa00, 0x8400, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
+ {".CRT", 0x68, 0xf000, 0x200, 0x8e00, 0x0, 0x0, 0x0, 0x0, 0xc0400040},
+ {".tls", 0x48, 0x10000, 0x200, 0x9000, 0x0, 0x0, 0x0, 0x0, 0xc0600040},
},
[]*Symbol{},
},
}
+func isOptHdrEq(a, b interface{}) bool {
+ switch va := a.(type) {
+ case *OptionalHeader32:
+ vb, ok := b.(*OptionalHeader32)
+ if !ok {
+ return false
+ }
+ return *vb == *va
+ case *OptionalHeader64:
+ vb, ok := b.(*OptionalHeader64)
+ if !ok {
+ return false
+ }
+ return *vb == *va
+ case nil:
+ return b == nil
+ }
+ return false
+}
+
func TestOpen(t *testing.T) {
for i := range fileTests {
tt := &fileTests[i]
@@ -90,6 +195,10 @@ func TestOpen(t *testing.T) {
t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
continue
}
+ if !isOptHdrEq(tt.opthdr, f.OptionalHeader) {
+ t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.OptionalHeader, tt.opthdr)
+ continue
+ }
for i, sh := range f.Sections {
if i >= len(tt.sections) {
diff --git a/src/pkg/debug/pe/pe.go b/src/pkg/debug/pe/pe.go
index 0606217b3..8e90b1b51 100644
--- a/src/pkg/debug/pe/pe.go
+++ b/src/pkg/debug/pe/pe.go
@@ -14,6 +14,78 @@ type FileHeader struct {
Characteristics uint16
}
+type DataDirectory struct {
+ VirtualAddress uint32
+ Size uint32
+}
+
+type OptionalHeader32 struct {
+ Magic uint16
+ MajorLinkerVersion uint8
+ MinorLinkerVersion uint8
+ SizeOfCode uint32
+ SizeOfInitializedData uint32
+ SizeOfUninitializedData uint32
+ AddressOfEntryPoint uint32
+ BaseOfCode uint32
+ BaseOfData uint32
+ ImageBase uint32
+ SectionAlignment uint32
+ FileAlignment uint32
+ MajorOperatingSystemVersion uint16
+ MinorOperatingSystemVersion uint16
+ MajorImageVersion uint16
+ MinorImageVersion uint16
+ MajorSubsystemVersion uint16
+ MinorSubsystemVersion uint16
+ Win32VersionValue uint32
+ SizeOfImage uint32
+ SizeOfHeaders uint32
+ CheckSum uint32
+ Subsystem uint16
+ DllCharacteristics uint16
+ SizeOfStackReserve uint32
+ SizeOfStackCommit uint32
+ SizeOfHeapReserve uint32
+ SizeOfHeapCommit uint32
+ LoaderFlags uint32
+ NumberOfRvaAndSizes uint32
+ DataDirectory [16]DataDirectory
+}
+
+type OptionalHeader64 struct {
+ Magic uint16
+ MajorLinkerVersion uint8
+ MinorLinkerVersion uint8
+ SizeOfCode uint32
+ SizeOfInitializedData uint32
+ SizeOfUninitializedData uint32
+ AddressOfEntryPoint uint32
+ BaseOfCode uint32
+ ImageBase uint64
+ SectionAlignment uint32
+ FileAlignment uint32
+ MajorOperatingSystemVersion uint16
+ MinorOperatingSystemVersion uint16
+ MajorImageVersion uint16
+ MinorImageVersion uint16
+ MajorSubsystemVersion uint16
+ MinorSubsystemVersion uint16
+ Win32VersionValue uint32
+ SizeOfImage uint32
+ SizeOfHeaders uint32
+ CheckSum uint32
+ Subsystem uint16
+ DllCharacteristics uint16
+ SizeOfStackReserve uint64
+ SizeOfStackCommit uint64
+ SizeOfHeapReserve uint64
+ SizeOfHeapCommit uint64
+ LoaderFlags uint32
+ NumberOfRvaAndSizes uint32
+ DataDirectory [16]DataDirectory
+}
+
type SectionHeader32 struct {
Name [8]uint8
VirtualSize uint32
diff --git a/src/pkg/debug/pe/testdata/gcc-amd64-mingw-exec b/src/pkg/debug/pe/testdata/gcc-amd64-mingw-exec
new file mode 100644
index 000000000..78d4e5fed
--- /dev/null
+++ b/src/pkg/debug/pe/testdata/gcc-amd64-mingw-exec
Binary files differ
diff --git a/src/pkg/debug/pe/testdata/gcc-amd64-mingw-obj b/src/pkg/debug/pe/testdata/gcc-amd64-mingw-obj
new file mode 100644
index 000000000..48ae7921f
--- /dev/null
+++ b/src/pkg/debug/pe/testdata/gcc-amd64-mingw-obj
Binary files differ