summaryrefslogtreecommitdiffstats
path: root/src/debug/pe/symbol.go
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 13:14:23 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 13:14:23 +0000
commit73df946d56c74384511a194dd01dbe099584fd1a (patch)
treefd0bcea490dd81327ddfbb31e215439672c9a068 /src/debug/pe/symbol.go
parentInitial commit. (diff)
downloadgolang-1.16-73df946d56c74384511a194dd01dbe099584fd1a.tar.xz
golang-1.16-73df946d56c74384511a194dd01dbe099584fd1a.zip
Adding upstream version 1.16.10.upstream/1.16.10upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/debug/pe/symbol.go')
-rw-r--r--src/debug/pe/symbol.go98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/debug/pe/symbol.go b/src/debug/pe/symbol.go
new file mode 100644
index 0000000..7fa5948
--- /dev/null
+++ b/src/debug/pe/symbol.go
@@ -0,0 +1,98 @@
+// 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"
+)
+
+const COFFSymbolSize = 18
+
+// COFFSymbol represents single COFF symbol table record.
+type COFFSymbol struct {
+ Name [8]uint8
+ Value uint32
+ SectionNumber int16
+ Type uint16
+ StorageClass uint8
+ NumberOfAuxSymbols uint8
+}
+
+func readCOFFSymbols(fh *FileHeader, r io.ReadSeeker) ([]COFFSymbol, error) {
+ if fh.PointerToSymbolTable == 0 {
+ return nil, nil
+ }
+ if fh.NumberOfSymbols <= 0 {
+ return nil, nil
+ }
+ _, err := r.Seek(int64(fh.PointerToSymbolTable), seekStart)
+ if err != nil {
+ return nil, fmt.Errorf("fail to seek to symbol table: %v", err)
+ }
+ syms := make([]COFFSymbol, fh.NumberOfSymbols)
+ err = binary.Read(r, binary.LittleEndian, syms)
+ if err != nil {
+ return nil, fmt.Errorf("fail to read symbol table: %v", err)
+ }
+ return syms, nil
+}
+
+// isSymNameOffset checks symbol name if it is encoded as offset into string table.
+func isSymNameOffset(name [8]byte) (bool, uint32) {
+ if name[0] == 0 && name[1] == 0 && name[2] == 0 && name[3] == 0 {
+ return true, binary.LittleEndian.Uint32(name[4:])
+ }
+ return false, 0
+}
+
+// FullName finds real name of symbol sym. Normally name is stored
+// in sym.Name, but if it is longer then 8 characters, it is stored
+// in COFF string table st instead.
+func (sym *COFFSymbol) FullName(st StringTable) (string, error) {
+ if ok, offset := isSymNameOffset(sym.Name); ok {
+ return st.String(offset)
+ }
+ return cstring(sym.Name[:]), nil
+}
+
+func removeAuxSymbols(allsyms []COFFSymbol, st StringTable) ([]*Symbol, error) {
+ if len(allsyms) == 0 {
+ return nil, nil
+ }
+ syms := make([]*Symbol, 0)
+ aux := uint8(0)
+ for _, sym := range allsyms {
+ if aux > 0 {
+ aux--
+ continue
+ }
+ name, err := sym.FullName(st)
+ if err != nil {
+ return nil, err
+ }
+ aux = sym.NumberOfAuxSymbols
+ s := &Symbol{
+ Name: name,
+ Value: sym.Value,
+ SectionNumber: sym.SectionNumber,
+ Type: sym.Type,
+ StorageClass: sym.StorageClass,
+ }
+ syms = append(syms, s)
+ }
+ return syms, nil
+}
+
+// Symbol is similar to COFFSymbol with Name field replaced
+// by Go string. Symbol also does not have NumberOfAuxSymbols.
+type Symbol struct {
+ Name string
+ Value uint32
+ SectionNumber int16
+ Type uint16
+ StorageClass uint8
+}