Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
symbol.go215 linesDownload Raw Back to pe
1// Copyright 2016 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.4 5package pe6 7import (8	"encoding/binary"9	"errors"10	"fmt"11	"internal/saferio"12	"io"13	"unsafe"14)15 16const COFFSymbolSize = 1817 18// COFFSymbol represents single COFF symbol table record.19type COFFSymbol struct {20	Name               [8]uint821	Value              uint3222	SectionNumber      int1623	Type               uint1624	StorageClass       uint825	NumberOfAuxSymbols uint826}27 28// readCOFFSymbols reads in the symbol table for a PE file, returning29// a slice of COFFSymbol objects. The PE format includes both primary30// symbols (whose fields are described by COFFSymbol above) and31// auxiliary symbols; all symbols are 18 bytes in size. The auxiliary32// symbols for a given primary symbol are placed following it in the33// array, e.g.34//35//	...36//	k+0:  regular sym k37//	k+1:    1st aux symbol for k38//	k+2:    2nd aux symbol for k39//	k+3:  regular sym k+340//	k+4:    1st aux symbol for k+341//	k+5:  regular sym k+542//	k+6:  regular sym k+643//44// The PE format allows for several possible aux symbol formats. For45// more info see:46//47//	https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-symbol-records48//49// At the moment this package only provides APIs for looking at50// aux symbols of format 5 (associated with section definition symbols).51func readCOFFSymbols(fh *FileHeader, r io.ReadSeeker) ([]COFFSymbol, error) {52	if fh.PointerToSymbolTable == 0 {53		return nil, nil54	}55	if fh.NumberOfSymbols <= 0 {56		return nil, nil57	}58	_, err := r.Seek(int64(fh.PointerToSymbolTable), io.SeekStart)59	if err != nil {60		return nil, fmt.Errorf("fail to seek to symbol table: %v", err)61	}62	c := saferio.SliceCap[COFFSymbol](uint64(fh.NumberOfSymbols))63	if c < 0 {64		return nil, errors.New("too many symbols; file may be corrupt")65	}66	syms := make([]COFFSymbol, 0, c)67	naux := 068	for k := uint32(0); k < fh.NumberOfSymbols; k++ {69		var sym COFFSymbol70		if naux == 0 {71			// Read a primary symbol.72			err = binary.Read(r, binary.LittleEndian, &sym)73			if err != nil {74				return nil, fmt.Errorf("fail to read symbol table: %v", err)75			}76			// Record how many auxiliary symbols it has.77			naux = int(sym.NumberOfAuxSymbols)78		} else {79			// Read an aux symbol. At the moment we assume all80			// aux symbols are format 5 (obviously this doesn't always81			// hold; more cases will be needed below if more aux formats82			// are supported in the future).83			naux--84			aux := (*COFFSymbolAuxFormat5)(unsafe.Pointer(&sym))85			err = binary.Read(r, binary.LittleEndian, aux)86			if err != nil {87				return nil, fmt.Errorf("fail to read symbol table: %v", err)88			}89		}90		syms = append(syms, sym)91	}92	if naux != 0 {93		return nil, fmt.Errorf("fail to read symbol table: %d aux symbols unread", naux)94	}95	return syms, nil96}97 98// isSymNameOffset checks symbol name if it is encoded as offset into string table.99func isSymNameOffset(name [8]byte) (bool, uint32) {100	if name[0] == 0 && name[1] == 0 && name[2] == 0 && name[3] == 0 {101		offset := binary.LittleEndian.Uint32(name[4:])102		if offset == 0 {103			// symbol has no name104			return false, 0105		}106		return true, offset107	}108	return false, 0109}110 111// FullName finds real name of symbol sym. Normally name is stored112// in sym.Name, but if it is longer then 8 characters, it is stored113// in COFF string table st instead.114func (sym *COFFSymbol) FullName(st StringTable) (string, error) {115	if ok, offset := isSymNameOffset(sym.Name); ok {116		return st.String(offset)117	}118	return cstring(sym.Name[:]), nil119}120 121func removeAuxSymbols(allsyms []COFFSymbol, st StringTable) ([]*Symbol, error) {122	if len(allsyms) == 0 {123		return nil, nil124	}125	syms := make([]*Symbol, 0)126	aux := uint8(0)127	for _, sym := range allsyms {128		if aux > 0 {129			aux--130			continue131		}132		name, err := sym.FullName(st)133		if err != nil {134			return nil, err135		}136		aux = sym.NumberOfAuxSymbols137		s := &Symbol{138			Name:          name,139			Value:         sym.Value,140			SectionNumber: sym.SectionNumber,141			Type:          sym.Type,142			StorageClass:  sym.StorageClass,143		}144		syms = append(syms, s)145	}146	return syms, nil147}148 149// Symbol is similar to [COFFSymbol] with Name field replaced150// by Go string. Symbol also does not have NumberOfAuxSymbols.151type Symbol struct {152	Name          string153	Value         uint32154	SectionNumber int16155	Type          uint16156	StorageClass  uint8157}158 159// COFFSymbolAuxFormat5 describes the expected form of an aux symbol160// attached to a section definition symbol. The PE format defines a161// number of different aux symbol formats: format 1 for function162// definitions, format 2 for .be and .ef symbols, and so on. Format 5163// holds extra info associated with a section definition, including164// number of relocations + line numbers, as well as COMDAT info. See165// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-format-5-section-definitions166// for more on what's going on here.167type COFFSymbolAuxFormat5 struct {168	Size           uint32169	NumRelocs      uint16170	NumLineNumbers uint16171	Checksum       uint32172	SecNum         uint16173	Selection      uint8174	_              [3]uint8 // padding175}176 177// These constants make up the possible values for the 'Selection'178// field in an AuxFormat5.179const (180	IMAGE_COMDAT_SELECT_NODUPLICATES = 1181	IMAGE_COMDAT_SELECT_ANY          = 2182	IMAGE_COMDAT_SELECT_SAME_SIZE    = 3183	IMAGE_COMDAT_SELECT_EXACT_MATCH  = 4184	IMAGE_COMDAT_SELECT_ASSOCIATIVE  = 5185	IMAGE_COMDAT_SELECT_LARGEST      = 6186)187 188// COFFSymbolReadSectionDefAux returns a blob of auxiliary information189// (including COMDAT info) for a section definition symbol. Here 'idx'190// is the index of a section symbol in the main [COFFSymbol] array for191// the File. Return value is a pointer to the appropriate aux symbol192// struct. For more info, see:193//194// auxiliary symbols: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-symbol-records195// COMDAT sections: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#comdat-sections-object-only196// auxiliary info for section definitions: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#auxiliary-format-5-section-definitions197func (f *File) COFFSymbolReadSectionDefAux(idx int) (*COFFSymbolAuxFormat5, error) {198	var rv *COFFSymbolAuxFormat5199	if idx < 0 || idx >= len(f.COFFSymbols) {200		return rv, fmt.Errorf("invalid symbol index")201	}202	pesym := &f.COFFSymbols[idx]203	const IMAGE_SYM_CLASS_STATIC = 3204	if pesym.StorageClass != uint8(IMAGE_SYM_CLASS_STATIC) {205		return rv, fmt.Errorf("incorrect symbol storage class")206	}207	if pesym.NumberOfAuxSymbols == 0 || idx+1 >= len(f.COFFSymbols) {208		return rv, fmt.Errorf("aux symbol unavailable")209	}210	// Locate and return a pointer to the successor aux symbol.211	pesymn := &f.COFFSymbols[idx+1]212	rv = (*COFFSymbolAuxFormat5)(unsafe.Pointer(pesymn))213	return rv, nil214}215 
codekingpro/portable-devtools · Team Ai