github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/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.NumberOfSymbols <= 0 { 27 return nil, nil 28 } 29 _, err := r.Seek(int64(fh.PointerToSymbolTable), io.SeekStart) 30 if err != nil { 31 return nil, fmt.Errorf("fail to seek to symbol table: %v", err) 32 } 33 syms := make([]COFFSymbol, fh.NumberOfSymbols) 34 err = binary.Read(r, binary.LittleEndian, syms) 35 if err != nil { 36 return nil, fmt.Errorf("fail to read symbol table: %v", err) 37 } 38 return syms, nil 39 } 40 41 // isSymNameOffset checks symbol name if it is encoded as offset into string table. 42 func isSymNameOffset(name [8]byte) (bool, uint32) { 43 if name[0] == 0 && name[1] == 0 && name[2] == 0 && name[3] == 0 { 44 return true, binary.LittleEndian.Uint32(name[4:]) 45 } 46 return false, 0 47 } 48 49 // _FullName finds real name of symbol sym. Normally name is stored 50 // in sym.Name, but if it is longer then 8 characters, it is stored 51 // in COFF string table st instead. 52 func (sym *COFFSymbol) _FullName(st _StringTable) (string, error) { 53 if ok, offset := isSymNameOffset(sym.Name); ok { 54 return st.String(offset) 55 } 56 return cstring(sym.Name[:]), nil 57 } 58 59 func removeAuxSymbols(allsyms []COFFSymbol, st _StringTable) ([]*Symbol, error) { 60 if len(allsyms) == 0 { 61 return nil, nil 62 } 63 syms := make([]*Symbol, 0) 64 aux := uint8(0) 65 for _, sym := range allsyms { 66 if aux > 0 { 67 aux-- 68 continue 69 } 70 name, err := sym._FullName(st) 71 if err != nil { 72 return nil, err 73 } 74 aux = sym.NumberOfAuxSymbols 75 s := &Symbol{ 76 Name: name, 77 Value: sym.Value, 78 SectionNumber: sym.SectionNumber, 79 Type: sym.Type, 80 StorageClass: sym.StorageClass, 81 } 82 syms = append(syms, s) 83 } 84 return syms, nil 85 } 86 87 // Symbol is similar to COFFSymbol with Name field replaced 88 // by Go string. Symbol also does not have NumberOfAuxSymbols. 89 type Symbol struct { 90 Name string 91 Value uint32 92 SectionNumber int16 93 Type uint16 94 StorageClass uint8 95 }