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  }