diff options
Diffstat (limited to 'src/pkg/debug/pe/file.go')
-rw-r--r-- | src/pkg/debug/pe/file.go | 68 |
1 files changed, 57 insertions, 11 deletions
diff --git a/src/pkg/debug/pe/file.go b/src/pkg/debug/pe/file.go index 6b98a5f45..f521566ef 100644 --- a/src/pkg/debug/pe/file.go +++ b/src/pkg/debug/pe/file.go @@ -19,6 +19,7 @@ import ( type File struct { FileHeader Sections []*Section + Symbols []*Symbol closer io.Closer } @@ -49,6 +50,14 @@ type Section struct { sr *io.SectionReader } +type Symbol struct { + Name string + Value uint32 + SectionNumber int16 + Type uint16 + StorageClass uint8 +} + type ImportDirectory struct { OriginalFirstThunk uint32 TimeDateStamp uint32 @@ -122,12 +131,13 @@ func NewFile(r io.ReaderAt) (*File, error) { } var base int64 if dosheader[0] == 'M' && dosheader[1] == 'Z' { + signoff := int64(binary.LittleEndian.Uint32(dosheader[0x3c:])) var sign [4]byte - r.ReadAt(sign[0:], int64(dosheader[0x3c])) + r.ReadAt(sign[:], signoff) if !(sign[0] == 'P' && sign[1] == 'E' && sign[2] == 0 && sign[3] == 0) { return nil, errors.New("Invalid PE File Format.") } - base = int64(dosheader[0x3c]) + 4 + base = signoff + 4 } else { base = int64(0) } @@ -138,16 +148,52 @@ func NewFile(r io.ReaderAt) (*File, error) { if f.FileHeader.Machine != IMAGE_FILE_MACHINE_UNKNOWN && f.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64 && f.FileHeader.Machine != IMAGE_FILE_MACHINE_I386 { return nil, errors.New("Invalid PE File Format.") } - // get symbol string table - sr.Seek(int64(f.FileHeader.PointerToSymbolTable+18*f.FileHeader.NumberOfSymbols), os.SEEK_SET) - 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 + + var ss []byte + if f.FileHeader.NumberOfSymbols > 0 { + // Get COFF string table, which is located at the end of the COFF symbol table. + sr.Seek(int64(f.FileHeader.PointerToSymbolTable+COFFSymbolSize*f.FileHeader.NumberOfSymbols), os.SEEK_SET) + 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+COFFSymbolSize*f.FileHeader.NumberOfSymbols)); err != nil { + return nil, err + } + + // Process COFF symbol table. + sr.Seek(int64(f.FileHeader.PointerToSymbolTable), os.SEEK_SET) + aux := uint8(0) + for i := 0; i < int(f.FileHeader.NumberOfSymbols); i++ { + cs := new(COFFSymbol) + if err := binary.Read(sr, binary.LittleEndian, cs); err != nil { + return nil, err + } + if aux > 0 { + aux-- + continue + } + var name string + if cs.Name[0] == 0 && cs.Name[1] == 0 && cs.Name[2] == 0 && cs.Name[3] == 0 { + si := int(binary.LittleEndian.Uint32(cs.Name[4:])) + name, _ = getString(ss, si) + } else { + name = cstring(cs.Name[:]) + } + aux = cs.NumberOfAuxSymbols + s := &Symbol{ + Name: name, + Value: cs.Value, + SectionNumber: cs.SectionNumber, + Type: cs.Type, + StorageClass: cs.StorageClass, + } + f.Symbols = append(f.Symbols, s) + } } + + // Process sections. sr.Seek(base, os.SEEK_SET) binary.Read(sr, binary.LittleEndian, &f.FileHeader) sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), os.SEEK_CUR) //Skip OptionalHeader |