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
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
@@ -34,6 +31,7 @@ import (
"github.com/goplus/llgo/chore/_xtool/llcppsymg/parse"
"github.com/goplus/llgo/chore/llcppg/types"
"github.com/goplus/llgo/cpp/llvm"
"github.com/goplus/llgo/xtool/nm"
)
func main() {
@@ -124,21 +122,26 @@ func getStringArrayItem(obj *cjson.JSON, key string) (value []string) {
}
func parseDylibSymbols(lib string) ([]types.CPPSymbol, error) {
dylibPath, _ := generateDylibPath(lib)
nmCmd := exec.Command("nm", "-gU", dylibPath)
nmOutput, err := nmCmd.Output() // maybe lock
dylibPath, err := generateDylibPath(lib)
if err != nil {
return nil, errors.New("failed to execute nm command")
return nil, errors.New("failed to generate dylib path")
}
symbols := parseNmOutput(nmOutput)
for i, sym := range symbols {
decodedName, err := decodeSymbolName(sym.Name)
files, err := nm.New("").List(dylibPath)
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
@@ -164,35 +167,28 @@ func generateDylibPath(lib string) (string, error) {
return dylibPath, nil
}
func parseNmOutput(output []byte) []types.CPPSymbol {
scanner := bufio.NewScanner(bytes.NewReader(output))
var symbols []types.CPPSymbol
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],
})
func decodeSymbolName(symbolName string) string {
if symbolName == "" {
return ""
}
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) {
llvm.ItaniumDemangle(symbolName, true)
demangleName := c.GoString(llvm.ItaniumDemangle(symbolName, true))
decodedName := strings.TrimSpace(string(demangleName))
decodedName = strings.ReplaceAll(decodedName, "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const", "std::string")
return decodedName, nil
decodedName := strings.TrimSpace(demangleName)
decodedName = strings.ReplaceAll(decodedName,
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const",
"std::string")
return decodedName
}
func generateHeaderFilePath(cflags string, files []string) []string {
@@ -211,11 +207,11 @@ func getCommonSymbols(dylibSymbols []types.CPPSymbol, astInfoList []types.ASTInf
for _, astInfo := range astInfoList {
for _, dylibSym := range dylibSymbols {
if dylibSym.Symbol == astInfo.Symbol {
if strings.TrimPrefix(dylibSym.Name, "_") == astInfo.Symbol {
cppName := generateCPPName(astInfo)
functionNameMap[cppName]++
symbolInfo := types.SymbolInfo{
Mangle: dylibSym.Symbol,
Mangle: strings.TrimPrefix(dylibSym.Name, "_"),
CPP: cppName,
Go: generateMangle(astInfo, functionNameMap[cppName], prefix),
}

View File

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