github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/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), 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  }