github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/debug/pe/symbol.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package pe 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 "io" 11 ) 12 13 const COFFSymbolSize = 18 14 15 // COFFSymbol represents single COFF symbol table record. 16 type COFFSymbol struct { 17 Name [8]uint8 18 Value uint32 19 SectionNumber int16 20 Type uint16 21 StorageClass uint8 22 NumberOfAuxSymbols uint8 23 } 24 25 func readCOFFSymbols(fh *FileHeader, r io.ReadSeeker) ([]COFFSymbol, error) { 26 if fh.PointerToSymbolTable == 0 { 27 return nil, nil 28 } 29 if fh.NumberOfSymbols <= 0 { 30 return nil, nil 31 } 32 _, err := r.Seek(int64(fh.PointerToSymbolTable), seekStart) 33 if err != nil { 34 return nil, fmt.Errorf("fail to seek to symbol table: %v", err) 35 } 36 syms := make([]COFFSymbol, fh.NumberOfSymbols) 37 err = binary.Read(r, binary.LittleEndian, syms) 38 if err != nil { 39 return nil, fmt.Errorf("fail to read symbol table: %v", err) 40 } 41 return syms, nil 42 } 43 44 // isSymNameOffset checks symbol name if it is encoded as offset into string table. 45 func isSymNameOffset(name [8]byte) (bool, uint32) { 46 if name[0] == 0 && name[1] == 0 && name[2] == 0 && name[3] == 0 { 47 return true, binary.LittleEndian.Uint32(name[4:]) 48 } 49 return false, 0 50 } 51 52 // FullName finds real name of symbol sym. Normally name is stored 53 // in sym.Name, but if it is longer then 8 characters, it is stored 54 // in COFF string table st instead. 55 func (sym *COFFSymbol) FullName(st StringTable) (string, error) { 56 if ok, offset := isSymNameOffset(sym.Name); ok { 57 return st.String(offset) 58 } 59 return cstring(sym.Name[:]), nil 60 } 61 62 func removeAuxSymbols(allsyms []COFFSymbol, st StringTable) ([]*Symbol, error) { 63 if len(allsyms) == 0 { 64 return nil, nil 65 } 66 syms := make([]*Symbol, 0) 67 aux := uint8(0) 68 for _, sym := range allsyms { 69 if aux > 0 { 70 aux-- 71 continue 72 } 73 name, err := sym.FullName(st) 74 if err != nil { 75 return nil, err 76 } 77 aux = sym.NumberOfAuxSymbols 78 s := &Symbol{ 79 Name: name, 80 Value: sym.Value, 81 SectionNumber: sym.SectionNumber, 82 Type: sym.Type, 83 StorageClass: sym.StorageClass, 84 } 85 syms = append(syms, s) 86 } 87 return syms, nil 88 } 89 90 // Symbol is similar to COFFSymbol with Name field replaced 91 // by Go string. Symbol also does not have NumberOfAuxSymbols. 92 type Symbol struct { 93 Name string 94 Value uint32 95 SectionNumber int16 96 Type uint16 97 StorageClass uint8 98 }