OptionalHeader interface{} // of type *OptionalHeader32 or *OptionalHeader64
Sections []*Section
Symbols []*Symbol
+ StringTable StringTable
closer io.Closer
}
return nil, errors.New("Invalid PE File Format.")
}
+ var err error
+
+ // Read string table.
+ f.StringTable, err = readStringTable(&f.FileHeader, sr)
+ if 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.
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) {
--- /dev/null
+// 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"
+ "io"
+)
+
+// TODO(brainman): return error from cstring and see what errors we get and what to do about it
+
+// cstring converts ASCII byte sequence b to string. It stops once it finds 0.
+func cstring(b []byte) string {
+ var i int
+ for i = 0; i < len(b) && b[i] != 0; i++ {
+ }
+ return string(b[:i])
+}
+
+// StringTable is a COFF string table.
+type StringTable []byte
+
+func readStringTable(fh *FileHeader, r io.ReadSeeker) (StringTable, error) {
+ // COFF string table is located right after COFF symbol table.
+ offset := fh.PointerToSymbolTable + COFFSymbolSize*fh.NumberOfSymbols
+ _, err := r.Seek(int64(offset), io.SeekStart)
+ if err != nil {
+ return nil, fmt.Errorf("fail to seek to string table: %v", err)
+ }
+ var l uint32
+ err = binary.Read(r, binary.LittleEndian, &l)
+ if err != nil {
+ return nil, fmt.Errorf("fail to read string table length: %v", err)
+ }
+ // string table length includes itself
+ if l <= 4 {
+ return nil, nil
+ }
+ l -= 4
+ buf := make([]byte, l)
+ _, err = io.ReadFull(r, buf)
+ if err != nil {
+ return nil, fmt.Errorf("fail to read string table: %v", err)
+ }
+ return StringTable(buf), nil
+}
+
+// TODO(brainman): decide if start parameter should be int instead of uint32
+
+// String extracts string from COFF string table st at offset start.
+func (st StringTable) String(start uint32) (string, error) {
+ // start includes 4 bytes of string table length
+ if start < 4 {
+ return "", fmt.Errorf("offset %d is before the start of string table", start)
+ }
+ start -= 4
+ if int(start) > len(st) {
+ return "", fmt.Errorf("offset %d is beyond the end of string table", start)
+ }
+ return cstring(st[start:]), nil
+}