Commit d697a9d5 authored by Alex Brainman's avatar Alex Brainman

debug/pe: introduce StringTable type

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: 's avatarAlex Brainman <alex.brainman@gmail.com>
parent 5183ad69
......@@ -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) {
......
// 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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment