From 03898249ea80c84f8d580c64875f707d7b782932 Mon Sep 17 00:00:00 2001 From: Alessio Greggi Date: Mon, 27 Jan 2025 17:52:11 +0100 Subject: [PATCH] fix: avoid regex compilation for every symbol Signed-off-by: Alessio Greggi --- cmd/analyze.go | 9 ++++++--- internal/elfreader/symbols.go | 22 ++++++++++++---------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/cmd/analyze.go b/cmd/analyze.go index 5f4941d..4c6e7d1 100644 --- a/cmd/analyze.go +++ b/cmd/analyze.go @@ -102,8 +102,11 @@ var analyzeCmd = &cobra.Command{ } // retrieving function symbols from ELF file. - elf := elfreader.NewElfReader(testBinPath) - symbolsFromElf, err := elf.FunctionSymbols(moduleName) + elf, err := elfreader.NewElfReader(testBinPath) + if err != nil { + return fmt.Errorf("failed to initialize elf file: %v", err) + } + fnSymbols, err := elf.FunctionSymbols(moduleName) if err != nil { return fmt.Errorf("failed to get function symbols: %v", err) } @@ -115,7 +118,7 @@ var analyzeCmd = &cobra.Command{ // in the _test.go files in the same directory. // if not, they will not be included in the report, // so we can avoid useless symbols to be traced. - for _, symbol := range symbolsFromElf { + for _, symbol := range fnSymbols { functionName := analyzer.ExtractFunctionName(symbol) testFiles, _ := listTestFiles(path) for _, testFile := range testFiles { diff --git a/internal/elfreader/symbols.go b/internal/elfreader/symbols.go index a214a82..1765c20 100644 --- a/internal/elfreader/symbols.go +++ b/internal/elfreader/symbols.go @@ -11,15 +11,21 @@ type ElfReader struct { file *elf.File } +// Regular expression to match ".func" followed by one or more digits +var reGoroutine = regexp.MustCompile(`\.func\d+$`) + +// Regular expression to check for valid Test suffix patterns +var reTestFunction = regexp.MustCompile(`\.Test[\w.]*$`) + // NewElfReader opens an ELF file and returns the ElfReader struct. -func NewElfReader(filePath string) *ElfReader { +func NewElfReader(filePath string) (*ElfReader, error) { elfFile, err := elf.Open(filePath) if err != nil { - fmt.Println("error: %w", err) + return nil, fmt.Errorf("%v", err) } return &ElfReader{ file: elfFile, - } + }, nil } // Close closes the ElfReader file. @@ -37,7 +43,7 @@ func (e *ElfReader) FunctionSymbols(pattern string) ([]string, error) { var symbolsList []string for _, symb := range symbols { // filter only function symbols - if !(elf.ST_TYPE(symb.Info) == elf.STT_FUNC) { + if elf.ST_TYPE(symb.Info) != elf.STT_FUNC { continue } // filter for package related symbols @@ -63,14 +69,10 @@ func (e *ElfReader) FunctionSymbols(pattern string) ([]string, error) { // isGoroutine detects if the symbol passed as argument is a goroutine function. func isGoroutine(s string) bool { - // Regular expression to match ".func" followed by one or more digits - re := regexp.MustCompile(`\.func\d+$`) - return re.MatchString(s) + return reGoroutine.MatchString(s) } // isTestFunction detects if the symbol passed as argument is a Test function. func isTestFunction(s string) bool { - // Regular expression to check for valid Test suffix patterns - re := regexp.MustCompile(`\.Test[\w.]*$`) - return re.MatchString(s) + return reTestFunction.MatchString(s) }