mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
debug/pe, cgo: add windows support
R=rsc, mattn CC=golang-dev https://golang.org/cl/1976045
This commit is contained in:
parent
e198a5086a
commit
035696c59a
10 changed files with 407 additions and 1 deletions
|
|
@ -141,6 +141,7 @@ _CGO_CFLAGS_amd64=-m64
|
||||||
_CGO_LDFLAGS_freebsd=-shared -lpthread -lm
|
_CGO_LDFLAGS_freebsd=-shared -lpthread -lm
|
||||||
_CGO_LDFLAGS_linux=-shared -lpthread -lm
|
_CGO_LDFLAGS_linux=-shared -lpthread -lm
|
||||||
_CGO_LDFLAGS_darwin=-dynamiclib -Wl,-undefined,dynamic_lookup
|
_CGO_LDFLAGS_darwin=-dynamiclib -Wl,-undefined,dynamic_lookup
|
||||||
|
_CGO_LDFLAGS_windows=-shared -lm -mthreads
|
||||||
|
|
||||||
# Compile x.cgo4.c with gcc to make package_x.so.
|
# Compile x.cgo4.c with gcc to make package_x.so.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"debug/dwarf"
|
"debug/dwarf"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"debug/macho"
|
"debug/macho"
|
||||||
|
"debug/pe"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
|
@ -504,7 +505,9 @@ func (p *Package) gccDebug(stdin []byte) *dwarf.Data {
|
||||||
var err os.Error
|
var err os.Error
|
||||||
if f, err = elf.Open(gccTmp); err != nil {
|
if f, err = elf.Open(gccTmp); err != nil {
|
||||||
if f, err = macho.Open(gccTmp); err != nil {
|
if f, err = macho.Open(gccTmp); err != nil {
|
||||||
fatal("cannot parse gcc output %s as ELF or Mach-O object", gccTmp)
|
if f, err = pe.Open(gccTmp); err != nil {
|
||||||
|
fatal("cannot parse gcc output %s as ELF or Mach-O or PE object", gccTmp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ DIRS=\
|
||||||
debug/macho\
|
debug/macho\
|
||||||
debug/elf\
|
debug/elf\
|
||||||
debug/gosym\
|
debug/gosym\
|
||||||
|
debug/pe\
|
||||||
debug/proc\
|
debug/proc\
|
||||||
ebnf\
|
ebnf\
|
||||||
encoding/ascii85\
|
encoding/ascii85\
|
||||||
|
|
|
||||||
12
src/pkg/debug/pe/Makefile
Normal file
12
src/pkg/debug/pe/Makefile
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Copyright 2009 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.
|
||||||
|
|
||||||
|
include ../../../Make.inc
|
||||||
|
|
||||||
|
TARG=debug/pe
|
||||||
|
GOFILES=\
|
||||||
|
pe.go\
|
||||||
|
file.go\
|
||||||
|
|
||||||
|
include ../../../Make.pkg
|
||||||
231
src/pkg/debug/pe/file.go
Normal file
231
src/pkg/debug/pe/file.go
Normal file
|
|
@ -0,0 +1,231 @@
|
||||||
|
// Copyright 2009 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 implements access to PE (Microsoft Windows Portable Executable) files.
|
||||||
|
package pe
|
||||||
|
|
||||||
|
import (
|
||||||
|
"debug/dwarf"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A File represents an open PE file.
|
||||||
|
type File struct {
|
||||||
|
FileHeader
|
||||||
|
Sections []*Section
|
||||||
|
|
||||||
|
closer io.Closer
|
||||||
|
}
|
||||||
|
|
||||||
|
type SectionHeader struct {
|
||||||
|
Name string
|
||||||
|
VirtualSize uint32
|
||||||
|
VirtualAddress uint32
|
||||||
|
Size uint32
|
||||||
|
Offset uint32
|
||||||
|
PointerToRelocations uint32
|
||||||
|
PointerToLineNumbers uint32
|
||||||
|
NumberOfRelocations uint16
|
||||||
|
NumberOfLineNumbers uint16
|
||||||
|
Characteristics uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Section struct {
|
||||||
|
SectionHeader
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
func (s *Section) Data() ([]byte, os.Error) {
|
||||||
|
dat := make([]byte, s.sr.Size())
|
||||||
|
n, err := s.sr.ReadAt(dat, 0)
|
||||||
|
return dat[0:n], err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open returns a new ReadSeeker reading the PE section.
|
||||||
|
func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }
|
||||||
|
|
||||||
|
|
||||||
|
type FormatError struct {
|
||||||
|
off int64
|
||||||
|
msg string
|
||||||
|
val interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *FormatError) String() string {
|
||||||
|
msg := e.msg
|
||||||
|
if e.val != nil {
|
||||||
|
msg += fmt.Sprintf(" '%v'", e.val)
|
||||||
|
}
|
||||||
|
msg += fmt.Sprintf(" in record at byte %#x", e.off)
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open opens the named file using os.Open and prepares it for use as a PE binary.
|
||||||
|
func Open(name string) (*File, os.Error) {
|
||||||
|
f, err := os.Open(name, os.O_RDONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ff, err := NewFile(f)
|
||||||
|
if err != nil {
|
||||||
|
f.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ff.closer = f
|
||||||
|
return ff, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the File.
|
||||||
|
// If the File was created using NewFile directly instead of Open,
|
||||||
|
// Close has no effect.
|
||||||
|
func (f *File) Close() os.Error {
|
||||||
|
var err os.Error
|
||||||
|
if f.closer != nil {
|
||||||
|
err = f.closer.Close()
|
||||||
|
f.closer = nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFile creates a new File for acecssing a PE binary in an underlying reader.
|
||||||
|
func NewFile(r io.ReaderAt) (*File, os.Error) {
|
||||||
|
f := new(File)
|
||||||
|
sr := io.NewSectionReader(r, 0, 1<<63-1)
|
||||||
|
|
||||||
|
var dosheader [96]byte
|
||||||
|
if _, err := r.ReadAt(dosheader[0:], 0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var base int64
|
||||||
|
if dosheader[0] == 'M' && dosheader[1] == 'Z' {
|
||||||
|
var sign [4]byte
|
||||||
|
r.ReadAt(sign[0:], int64(dosheader[0x3c]))
|
||||||
|
if !(sign[0] == 'P' && sign[1] == 'E' && sign[2] == 0 && sign[3] == 0) {
|
||||||
|
return nil, os.NewError("Invalid PE File Format.")
|
||||||
|
}
|
||||||
|
base = int64(dosheader[0x3c]) + 4
|
||||||
|
} else {
|
||||||
|
base = int64(0)
|
||||||
|
}
|
||||||
|
sr.Seek(base, 0)
|
||||||
|
if err := binary.Read(sr, binary.LittleEndian, &f.FileHeader); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if f.FileHeader.Machine != IMAGE_FILE_MACHINE_UNKNOWN && f.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64 && f.FileHeader.Machine != IMAGE_FILE_MACHINE_I386 {
|
||||||
|
return nil, os.NewError("Invalid PE File Format.")
|
||||||
|
}
|
||||||
|
// get symbol string table
|
||||||
|
sr.Seek(int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols), 0)
|
||||||
|
var l uint32
|
||||||
|
if err := binary.Read(sr, binary.LittleEndian, &l); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ss := make([]byte, l)
|
||||||
|
if _, err := r.ReadAt(ss, int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sr.Seek(base, 0)
|
||||||
|
binary.Read(sr, binary.LittleEndian, &f.FileHeader)
|
||||||
|
sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), 1) //Skip OptionalHeader
|
||||||
|
f.Sections = make([]*Section, f.FileHeader.NumberOfSections)
|
||||||
|
for i := 0; i < int(f.FileHeader.NumberOfSections); i++ {
|
||||||
|
sh := new(SectionHeader32)
|
||||||
|
if err := binary.Read(sr, binary.LittleEndian, sh); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var name string
|
||||||
|
if sh.Name[0] == '\x2F' {
|
||||||
|
si, _ := strconv.Atoi(cstring(sh.Name[1:]))
|
||||||
|
name, _ = getString(ss, si)
|
||||||
|
} else {
|
||||||
|
name = cstring(sh.Name[0:])
|
||||||
|
}
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
s.sr = io.NewSectionReader(r, int64(s.SectionHeader.Offset), int64(s.SectionHeader.Size))
|
||||||
|
s.ReaderAt = s.sr
|
||||||
|
f.Sections[i] = s
|
||||||
|
}
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func cstring(b []byte) string {
|
||||||
|
var i int
|
||||||
|
for i = 0; i < len(b) && b[i] != 0; i++ {
|
||||||
|
}
|
||||||
|
return string(b[0:i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// getString extracts a string from symbol string table.
|
||||||
|
func getString(section []byte, start int) (string, bool) {
|
||||||
|
if start < 0 || start >= len(section) {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
for end := start; end < len(section); end++ {
|
||||||
|
if section[end] == 0 {
|
||||||
|
return string(section[start:end]), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Section returns the first section with the given name, or nil if no such
|
||||||
|
// section exists.
|
||||||
|
func (f *File) Section(name string) *Section {
|
||||||
|
for _, s := range f.Sections {
|
||||||
|
if s.Name == name {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *File) DWARF() (*dwarf.Data, os.Error) {
|
||||||
|
// There are many other DWARF sections, but these
|
||||||
|
// are the required ones, and the debug/dwarf package
|
||||||
|
// does not use the others, so don't bother loading them.
|
||||||
|
var names = [...]string{"abbrev", "info", "str"}
|
||||||
|
var dat [len(names)][]byte
|
||||||
|
for i, name := range names {
|
||||||
|
name = ".debug_" + name
|
||||||
|
s := f.Section(name)
|
||||||
|
if s == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b, err := s.Data()
|
||||||
|
if err != nil && uint32(len(b)) < s.Size {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
dat[i] = b
|
||||||
|
}
|
||||||
|
|
||||||
|
abbrev, info, str := dat[0], dat[1], dat[2]
|
||||||
|
return dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str)
|
||||||
|
}
|
||||||
99
src/pkg/debug/pe/file_test.go
Normal file
99
src/pkg/debug/pe/file_test.go
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
// Copyright 2009 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 (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fileTest struct {
|
||||||
|
file string
|
||||||
|
hdr FileHeader
|
||||||
|
sections []*SectionHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileTests = []fileTest{
|
||||||
|
fileTest{
|
||||||
|
"testdata/gcc-386-mingw-obj",
|
||||||
|
FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104},
|
||||||
|
[]*SectionHeader{
|
||||||
|
&SectionHeader{".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
|
||||||
|
&SectionHeader{".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
|
||||||
|
&SectionHeader{".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
|
||||||
|
&SectionHeader{".debug_abbrev", 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000},
|
||||||
|
&SectionHeader{".debug_info", 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832},
|
||||||
|
&SectionHeader{".debug_line", 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832},
|
||||||
|
&SectionHeader{".rdata", 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616},
|
||||||
|
&SectionHeader{".debug_frame", 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984},
|
||||||
|
&SectionHeader{".debug_loc", 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832},
|
||||||
|
&SectionHeader{".debug_pubnames", 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832},
|
||||||
|
&SectionHeader{".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
|
||||||
|
&SectionHeader{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fileTest{
|
||||||
|
"testdata/gcc-386-mingw-exec",
|
||||||
|
FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107},
|
||||||
|
[]*SectionHeader{
|
||||||
|
&SectionHeader{Name: ".text", VirtualSize: 0xcd8, VirtualAddress: 0x1000, Size: 0xe00, Offset: 0x400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x60500060},
|
||||||
|
&SectionHeader{Name: ".data", VirtualSize: 0x10, VirtualAddress: 0x2000, Size: 0x200, Offset: 0x1200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
|
||||||
|
&SectionHeader{Name: ".rdata", VirtualSize: 0x120, VirtualAddress: 0x3000, Size: 0x200, Offset: 0x1400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x40300040},
|
||||||
|
&SectionHeader{Name: ".bss", VirtualSize: 0xdc, VirtualAddress: 0x4000, Size: 0x0, Offset: 0x0, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0400080},
|
||||||
|
&SectionHeader{Name: ".idata", VirtualSize: 0x3c8, VirtualAddress: 0x5000, Size: 0x400, Offset: 0x1600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
|
||||||
|
&SectionHeader{Name: ".CRT", VirtualSize: 0x18, VirtualAddress: 0x6000, Size: 0x200, Offset: 0x1a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
|
||||||
|
&SectionHeader{Name: ".tls", VirtualSize: 0x20, VirtualAddress: 0x7000, Size: 0x200, Offset: 0x1c00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040},
|
||||||
|
&SectionHeader{Name: ".debug_aranges", VirtualSize: 0x20, VirtualAddress: 0x8000, Size: 0x200, Offset: 0x1e00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
|
||||||
|
&SectionHeader{Name: ".debug_pubnames", VirtualSize: 0x51, VirtualAddress: 0x9000, Size: 0x200, Offset: 0x2000, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
|
||||||
|
&SectionHeader{Name: ".debug_pubtypes", VirtualSize: 0x91, VirtualAddress: 0xa000, Size: 0x200, Offset: 0x2200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
|
||||||
|
&SectionHeader{Name: ".debug_info", VirtualSize: 0xe22, VirtualAddress: 0xb000, Size: 0x1000, Offset: 0x2400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
|
||||||
|
&SectionHeader{Name: ".debug_abbrev", VirtualSize: 0x157, VirtualAddress: 0xc000, Size: 0x200, Offset: 0x3400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
|
||||||
|
&SectionHeader{Name: ".debug_line", VirtualSize: 0x144, VirtualAddress: 0xd000, Size: 0x200, Offset: 0x3600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
|
||||||
|
&SectionHeader{Name: ".debug_frame", VirtualSize: 0x34, VirtualAddress: 0xe000, Size: 0x200, Offset: 0x3800, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42300000},
|
||||||
|
&SectionHeader{Name: ".debug_loc", VirtualSize: 0x38, VirtualAddress: 0xf000, Size: 0x200, Offset: 0x3a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOpen(t *testing.T) {
|
||||||
|
for i := range fileTests {
|
||||||
|
tt := &fileTests[i]
|
||||||
|
|
||||||
|
f, err := Open(tt.file)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
|
||||||
|
t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, sh := range f.Sections {
|
||||||
|
if i >= len(tt.sections) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
have := &sh.SectionHeader
|
||||||
|
want := tt.sections[i]
|
||||||
|
if !reflect.DeepEqual(have, want) {
|
||||||
|
t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tn := len(tt.sections)
|
||||||
|
fn := len(f.Sections)
|
||||||
|
if tn != fn {
|
||||||
|
t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOpenFailure(t *testing.T) {
|
||||||
|
filename := "file.go" // not a PE file
|
||||||
|
_, err := Open(filename) // don't crash
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("open %s: succeeded unexpectedly", filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
51
src/pkg/debug/pe/pe.go
Normal file
51
src/pkg/debug/pe/pe.go
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
// Copyright 2009 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
|
||||||
|
|
||||||
|
type FileHeader struct {
|
||||||
|
Machine uint16
|
||||||
|
NumberOfSections uint16
|
||||||
|
TimeDateStamp uint32
|
||||||
|
PointerToSymbolTable uint32
|
||||||
|
NumberOfSymbols uint32
|
||||||
|
SizeOfOptionalHeader uint16
|
||||||
|
Characteristics uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type SectionHeader32 struct {
|
||||||
|
Name [8]uint8
|
||||||
|
VirtualSize uint32
|
||||||
|
VirtualAddress uint32
|
||||||
|
SizeOfRawData uint32
|
||||||
|
PointerToRawData uint32
|
||||||
|
PointerToRelocations uint32
|
||||||
|
PointerToLineNumbers uint32
|
||||||
|
NumberOfRelocations uint16
|
||||||
|
NumberOfLineNumbers uint16
|
||||||
|
Characteristics uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
IMAGE_FILE_MACHINE_UNKNOWN = 0x0
|
||||||
|
IMAGE_FILE_MACHINE_AM33 = 0x1d3
|
||||||
|
IMAGE_FILE_MACHINE_AMD64 = 0x8664
|
||||||
|
IMAGE_FILE_MACHINE_ARM = 0x1c0
|
||||||
|
IMAGE_FILE_MACHINE_EBC = 0xebc
|
||||||
|
IMAGE_FILE_MACHINE_I386 = 0x14c
|
||||||
|
IMAGE_FILE_MACHINE_IA64 = 0x200
|
||||||
|
IMAGE_FILE_MACHINE_M32R = 0x9041
|
||||||
|
IMAGE_FILE_MACHINE_MIPS16 = 0x266
|
||||||
|
IMAGE_FILE_MACHINE_MIPSFPU = 0x366
|
||||||
|
IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466
|
||||||
|
IMAGE_FILE_MACHINE_POWERPC = 0x1f0
|
||||||
|
IMAGE_FILE_MACHINE_POWERPCFP = 0x1f1
|
||||||
|
IMAGE_FILE_MACHINE_R4000 = 0x166
|
||||||
|
IMAGE_FILE_MACHINE_SH3 = 0x1a2
|
||||||
|
IMAGE_FILE_MACHINE_SH3DSP = 0x1a3
|
||||||
|
IMAGE_FILE_MACHINE_SH4 = 0x1a6
|
||||||
|
IMAGE_FILE_MACHINE_SH5 = 0x1a8
|
||||||
|
IMAGE_FILE_MACHINE_THUMB = 0x1c2
|
||||||
|
IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169
|
||||||
|
)
|
||||||
BIN
src/pkg/debug/pe/testdata/gcc-386-mingw-exec
vendored
Normal file
BIN
src/pkg/debug/pe/testdata/gcc-386-mingw-exec
vendored
Normal file
Binary file not shown.
BIN
src/pkg/debug/pe/testdata/gcc-386-mingw-obj
vendored
Normal file
BIN
src/pkg/debug/pe/testdata/gcc-386-mingw-obj
vendored
Normal file
Binary file not shown.
8
src/pkg/debug/pe/testdata/hello.c
vendored
Normal file
8
src/pkg/debug/pe/testdata/hello.c
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
printf("hello, world\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue