]> Cypherpunks repositories - gostls13.git/commitdiff
debug/pe: introduce StringTable type
authorAlex Brainman <alex.brainman@gmail.com>
Mon, 18 Apr 2016 06:12:48 +0000 (16:12 +1000)
committerAlex Brainman <alex.brainman@gmail.com>
Wed, 20 Apr 2016 02:01:36 +0000 (02:01 +0000)
PE specification requires that long section and symbol names
are stored in PE string table. Introduce StringTable that
implements this functionality. Only string table reading is
implemented.

Updates #15345

Change-Id: Ib9638617f2ab1881ad707111d96fc68b0e47340e
Reviewed-on: https://go-review.googlesource.com/22181
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
src/debug/pe/file.go
src/debug/pe/string.go [new file with mode: 0644]

index bfc4cf8a184101547d69ca8937fe1f4720308bc4..f7b74e92a4a27afdade51207234b4a05da463264 100644 (file)
@@ -21,6 +21,7 @@ type File struct {
        OptionalHeader interface{} // of type *OptionalHeader32 or *OptionalHeader64
        Sections       []*Section
        Symbols        []*Symbol
+       StringTable    StringTable
 
        closer io.Closer
 }
@@ -133,6 +134,14 @@ func NewFile(r io.ReaderAt) (*File, error) {
                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.
@@ -237,13 +246,6 @@ func NewFile(r io.ReaderAt) (*File, error) {
        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) {
diff --git a/src/debug/pe/string.go b/src/debug/pe/string.go
new file mode 100644 (file)
index 0000000..f0928d0
--- /dev/null
@@ -0,0 +1,64 @@
+// 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
+}