c/clang/symg: use xtool/nm to parse symbol

This commit is contained in:
luoliwoshang
2024-07-30 15:07:33 +08:00
parent 14face336e
commit 099c80e04b
2 changed files with 40 additions and 44 deletions

View File

@@ -17,13 +17,10 @@
package main package main
import ( import (
"bufio"
"bytes"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
@@ -34,6 +31,7 @@ import (
"github.com/goplus/llgo/chore/_xtool/llcppsymg/parse" "github.com/goplus/llgo/chore/_xtool/llcppsymg/parse"
"github.com/goplus/llgo/chore/llcppg/types" "github.com/goplus/llgo/chore/llcppg/types"
"github.com/goplus/llgo/cpp/llvm" "github.com/goplus/llgo/cpp/llvm"
"github.com/goplus/llgo/xtool/nm"
) )
func main() { func main() {
@@ -124,21 +122,26 @@ func getStringArrayItem(obj *cjson.JSON, key string) (value []string) {
} }
func parseDylibSymbols(lib string) ([]types.CPPSymbol, error) { func parseDylibSymbols(lib string) ([]types.CPPSymbol, error) {
dylibPath, _ := generateDylibPath(lib) dylibPath, err := generateDylibPath(lib)
nmCmd := exec.Command("nm", "-gU", dylibPath)
nmOutput, err := nmCmd.Output() // maybe lock
if err != nil { if err != nil {
return nil, errors.New("failed to execute nm command") return nil, errors.New("failed to generate dylib path")
} }
symbols := parseNmOutput(nmOutput) files, err := nm.New("").List(dylibPath)
for i, sym := range symbols {
decodedName, err := decodeSymbolName(sym.Name)
if err != nil { if err != nil {
return nil, err return nil, errors.New("failed to list symbols in dylib")
}
var symbols []types.CPPSymbol
for _, file := range files {
for _, sym := range file.Symbols {
demangleName := decodeSymbolName(sym.Name)
symbols = append(symbols, types.CPPSymbol{
Symbol: sym,
DemangleName: demangleName,
})
} }
symbols[i].Name = decodedName
} }
return symbols, nil return symbols, nil
@@ -164,35 +167,28 @@ func generateDylibPath(lib string) (string, error) {
return dylibPath, nil return dylibPath, nil
} }
func parseNmOutput(output []byte) []types.CPPSymbol { func decodeSymbolName(symbolName string) string {
scanner := bufio.NewScanner(bytes.NewReader(output)) if symbolName == "" {
var symbols []types.CPPSymbol return ""
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
if len(fields) < 3 {
continue
}
symbolName := fields[2]
// Check if the symbol name starts with an underscore and remove it if present
symbolName = strings.TrimPrefix(symbolName, "_")
symbols = append(symbols, types.CPPSymbol{
Symbol: symbolName,
Type: fields[1],
Name: fields[2],
})
} }
return symbols demangled := llvm.ItaniumDemangle(symbolName, true)
if demangled == nil {
return symbolName
}
defer c.Free(unsafe.Pointer(demangled))
demangleName := c.GoString(demangled)
if demangleName == "" {
return symbolName
} }
func decodeSymbolName(symbolName string) (string, error) { decodedName := strings.TrimSpace(demangleName)
llvm.ItaniumDemangle(symbolName, true) decodedName = strings.ReplaceAll(decodedName,
demangleName := c.GoString(llvm.ItaniumDemangle(symbolName, true)) "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const",
decodedName := strings.TrimSpace(string(demangleName)) "std::string")
decodedName = strings.ReplaceAll(decodedName, "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const", "std::string")
return decodedName, nil return decodedName
} }
func generateHeaderFilePath(cflags string, files []string) []string { func generateHeaderFilePath(cflags string, files []string) []string {
@@ -211,11 +207,11 @@ func getCommonSymbols(dylibSymbols []types.CPPSymbol, astInfoList []types.ASTInf
for _, astInfo := range astInfoList { for _, astInfo := range astInfoList {
for _, dylibSym := range dylibSymbols { for _, dylibSym := range dylibSymbols {
if dylibSym.Symbol == astInfo.Symbol { if strings.TrimPrefix(dylibSym.Name, "_") == astInfo.Symbol {
cppName := generateCPPName(astInfo) cppName := generateCPPName(astInfo)
functionNameMap[cppName]++ functionNameMap[cppName]++
symbolInfo := types.SymbolInfo{ symbolInfo := types.SymbolInfo{
Mangle: dylibSym.Symbol, Mangle: strings.TrimPrefix(dylibSym.Name, "_"),
CPP: cppName, CPP: cppName,
Go: generateMangle(astInfo, functionNameMap[cppName], prefix), Go: generateMangle(astInfo, functionNameMap[cppName], prefix),
} }

View File

@@ -18,6 +18,7 @@ package types
import ( import (
"github.com/goplus/llgo/c/cjson" "github.com/goplus/llgo/c/cjson"
"github.com/goplus/llgo/xtool/nm"
) )
// Config represents a configuration for the llcppg tool. // Config represents a configuration for the llcppg tool.
@@ -35,9 +36,8 @@ type Conf struct {
} }
type CPPSymbol struct { type CPPSymbol struct {
Symbol string `json:"symbol"` DemangleName string
Type string `json:"type"` *nm.Symbol
Name string `json:"name"`
} }
type ASTInformation struct { type ASTInformation struct {