llcppsymg:symbol generate test

llcppsymg:symbo test

llcppsymg:exist symb file test

llcppsymg:GenSymbolTabledata

llcppsymg:GenSymbolTableData test

llcppsymg:full symg operation test
This commit is contained in:
luoliwoshang
2024-09-25 14:59:02 +08:00
parent 174fdd40da
commit 944133de6e
13 changed files with 499 additions and 139 deletions

View File

@@ -4,43 +4,10 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/goplus/llgo/chore/_xtool/llcppsymg/header"
)
func GenHeaderFilePath(cflags string, files []string) ([]string, error) {
prefixPath := strings.TrimPrefix(cflags, "-I")
var validPaths []string
var errs []string
for _, file := range files {
if file == "" {
continue
}
fullPath := filepath.Join(prefixPath, file)
if f, err := os.Open(fullPath); err != nil {
if os.IsNotExist(err) {
errs = append(errs, fmt.Sprintf("file not found: %s", file))
} else {
errs = append(errs, fmt.Sprintf("error accessing file %s: %v", file, err))
}
} else {
f.Close()
validPaths = append(validPaths, fullPath)
}
}
if len(validPaths) == 0 && len(errs) == 0 {
return nil, fmt.Errorf("no valid header files")
}
if len(errs) > 0 {
return validPaths, fmt.Errorf("some files not found or inaccessible: %v", errs)
}
return validPaths, nil
}
func TestGenHeaderFilePath() {
fmt.Println("=== Test GenHeaderFilePath ===")
@@ -83,7 +50,7 @@ func TestGenHeaderFilePath() {
fmt.Printf("Test case: %s\n", tc.name)
fmt.Printf("Input files: %v\n", tc.files)
result, err := GenHeaderFilePath(tc.cflags, tc.files)
result, err := header.GenHeaderFilePath(tc.cflags, tc.files)
if err != nil {
fmt.Printf("Error: %v\n", err)

View File

@@ -0,0 +1,46 @@
#stdout
=== Test GetCommonSymbols ===
Test Case: Lua symbols
Common Symbols (4):
Mangle: lua_absindex, CPP: lua_absindex(lua_State *, int), Go: Absindex
Mangle: lua_arith, CPP: lua_arith(lua_State *, int), Go: Arith
Mangle: lua_atpanic, CPP: lua_atpanic(lua_State *, lua_CFunction), Go: Atpanic
Mangle: lua_callk, CPP: lua_callk(lua_State *, int, int, lua_KContext, lua_KFunction), Go: Callk
Test Case: INIReader and Std library symbols
Common Symbols (3):
Mangle: ZNK9INIReader12GetInteger64ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_x, CPP: INIReader::GetInteger64(const std::string &, const std::string &, int64_t), Go: (*Reader).GetInteger64
Mangle: ZNK9INIReader7GetRealERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_d, CPP: INIReader::GetReal(const std::string &, const std::string &, double), Go: (*Reader).GetReal
Mangle: ZNK9INIReader10ParseErrorEv, CPP: INIReader::ParseError(), Go: (*Reader).ParseError
=== Test ReadExistingSymbolTable ===
Symbols read from the file:
Symbol Map GoName: (*Reader).Init__1, ProtoName In HeaderFile: INIReader::INIReader(const char *, size_t), MangledName: _ZN9INIReaderC1EPKcm
Symbol Map GoName: (*Reader).GetBoolean, ProtoName In HeaderFile: INIReader::GetBoolean(const std::string &, const std::string &, bool), MangledName: _ZNK9INIReader10GetBooleanERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_b
Symbol Map GoName: (*Reader).ParseError, ProtoName In HeaderFile: INIReader::ParseError(), MangledName: _ZNK9INIReader10ParseErrorEv
Havent existed symb file
=== Test GenSymbolTableData ===
[{
"mangle": "lua_absindex",
"c++": "lua_absindex(lua_State *, int)",
"go": "Absindex"
}, {
"mangle": "lua_arith",
"c++": "lua_arith(lua_State *, int)",
"go": "Arith"
}, {
"mangle": "lua_atpanic",
"c++": "lua_atpanic(lua_State *, lua_CFunction)",
"go": "Atpanic"
}, {
"mangle": "lua_callk",
"c++": "lua_callk(lua_State *, int, int, lua_KContext, lua_KFunction)",
"go": "ModifiedCallk"
}]
#stderr
#exit 0

View File

@@ -0,0 +1,152 @@
package main
import (
"fmt"
"os"
"sort"
"github.com/goplus/llgo/chore/_xtool/llcppsymg/parse"
"github.com/goplus/llgo/chore/_xtool/llcppsymg/symbol"
"github.com/goplus/llgo/chore/llcppg/types"
"github.com/goplus/llgo/xtool/nm"
)
func main() {
TestGetCommonSymbols()
TestReadExistingSymbolTable()
TestGenSymbolTableData()
}
func TestGetCommonSymbols() {
fmt.Println("=== Test GetCommonSymbols ===")
testCases := []struct {
name string
dylibSymbols []*nm.Symbol
headerSymbols map[string]*parse.SymbolInfo
}{
{
name: "Lua symbols",
dylibSymbols: []*nm.Symbol{
{Name: "_lua_absindex"},
{Name: "_lua_arith"},
{Name: "_lua_atpanic"},
{Name: "_lua_callk"},
{Name: "_lua_lib_nonexistent"},
},
headerSymbols: map[string]*parse.SymbolInfo{
"lua_absindex": {ProtoName: "lua_absindex(lua_State *, int)", GoName: "Absindex"},
"lua_arith": {ProtoName: "lua_arith(lua_State *, int)", GoName: "Arith"},
"lua_atpanic": {ProtoName: "lua_atpanic(lua_State *, lua_CFunction)", GoName: "Atpanic"},
"lua_callk": {ProtoName: "lua_callk(lua_State *, int, int, lua_KContext, lua_KFunction)", GoName: "Callk"},
"lua_header_nonexistent": {ProtoName: "lua_header_nonexistent()", GoName: "HeaderNonexistent"},
},
},
{
name: "INIReader and Std library symbols",
dylibSymbols: []*nm.Symbol{
{Name: "_ZNK9INIReader12GetInteger64ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_x"},
{Name: "_ZNK9INIReader7GetRealERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_d"},
{Name: "_ZNK9INIReader10ParseErrorEv"},
},
headerSymbols: map[string]*parse.SymbolInfo{
"ZNK9INIReader12GetInteger64ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_x": {GoName: "(*Reader).GetInteger64", ProtoName: "INIReader::GetInteger64(const std::string &, const std::string &, int64_t)"},
"ZNK9INIReader13GetUnsigned64ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_y": {GoName: "(*Reader).GetUnsigned64", ProtoName: "INIReader::GetUnsigned64(const std::string &, const std::string &, uint64_t)"},
"ZNK9INIReader7GetRealERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_d": {GoName: "(*Reader).GetReal", ProtoName: "INIReader::GetReal(const std::string &, const std::string &, double)"},
"ZNK9INIReader10ParseErrorEv": {GoName: "(*Reader).ParseError", ProtoName: "INIReader::ParseError()"},
"ZNK9INIReader10GetBooleanERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_b": {GoName: "(*Reader).GetBoolean", ProtoName: "INIReader::GetBoolean(const std::string &, const std::string &, bool)"},
},
},
}
for _, tc := range testCases {
fmt.Printf("\nTest Case: %s\n", tc.name)
commonSymbols := symbol.GetCommonSymbols(tc.dylibSymbols, tc.headerSymbols)
fmt.Printf("Common Symbols (%d):\n", len(commonSymbols))
for _, sym := range commonSymbols {
fmt.Printf("Mangle: %s, CPP: %s, Go: %s\n", sym.Mangle, sym.CPP, sym.Go)
}
}
fmt.Println()
}
func TestReadExistingSymbolTable() {
fmt.Println("=== Test ReadExistingSymbolTable ===")
tmpFile, err := os.CreateTemp("", "llcppg.symb.json")
if err != nil {
fmt.Printf("Failed to create temp file: %v\n", err)
return
}
defer os.Remove(tmpFile.Name())
testData := `[
{
"mangle": "_ZN9INIReaderC1EPKcm",
"c++": "INIReader::INIReader(const char *, size_t)",
"go": "(*Reader).Init__1"
},
{
"mangle": "_ZNK9INIReader10GetBooleanERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_b",
"c++": "INIReader::GetBoolean(const std::string &, const std::string &, bool)",
"go": "(*Reader).GetBoolean"
},
{
"mangle": "_ZNK9INIReader10ParseErrorEv",
"c++": "INIReader::ParseError()",
"go": "(*Reader).ParseError"
}
]`
if _, err := tmpFile.Write([]byte(testData)); err != nil {
fmt.Printf("Failed to write test data: %v\n", err)
return
}
tmpFile.Close()
symbols, exist := symbol.ReadExistingSymbolTable(tmpFile.Name())
if !exist {
fmt.Printf("ReadExistingSymbolTable failed")
return
}
fmt.Println("Symbols read from the file:")
var keys []string
for key := range symbols {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
info := symbols[key]
fmt.Printf("Symbol Map GoName: %s, ProtoName In HeaderFile: %s, MangledName: %s\n",
info.Go, info.CPP, key)
}
_, exist = symbol.ReadExistingSymbolTable("other.json")
if !exist {
fmt.Println("Havent existed symb file")
}
fmt.Println()
}
func TestGenSymbolTableData() {
fmt.Println("=== Test GenSymbolTableData ===")
commonSymbols := []*types.SymbolInfo{
{Mangle: "lua_absindex", CPP: "lua_absindex(lua_State *, int)", Go: "Absindex"},
{Mangle: "lua_arith", CPP: "lua_arith(lua_State *, int)", Go: "Arith"},
{Mangle: "lua_atpanic", CPP: "lua_atpanic(lua_State *, lua_CFunction)", Go: "Atpanic"},
{Mangle: "lua_callk", CPP: "lua_callk(lua_State *, int, int, lua_KContext, lua_KFunction)", Go: "Callk"},
}
existingSymbols := map[string]types.SymbolInfo{
"lua_absindex": {Mangle: "lua_absindex", CPP: "lua_absindex(lua_State *, int)", Go: "Absindex"},
"lua_arith": {Mangle: "lua_arith", CPP: "lua_arith(lua_State *, int)", Go: "Arith"},
"lua_callk": {Mangle: "lua_callk", CPP: "lua_callk(lua_State *, int, int, lua_KContext, lua_KFunction)", Go: "ModifiedCallk"},
}
data, err := symbol.GenSymbolTableData(commonSymbols, existingSymbols)
if err != nil {
fmt.Printf("Error generating symbol table data: %v\n", err)
return
}
fmt.Println(string(data))
fmt.Println()
}

View File

@@ -0,0 +1,45 @@
#stdout
=== Test Case: inireader ===
[{
"mangle": "_ZN9INIReaderC1EPKc",
"c++": "INIReader::INIReader(const char *)",
"go": "(*Reader).Init"
}, {
"mangle": "_ZN9INIReaderC1EPKcl",
"c++": "INIReader::INIReader(const char *, long)",
"go": "(*Reader).Init__1"
}, {
"mangle": "_ZN9INIReaderD1Ev",
"c++": "INIReader::~INIReader()",
"go": "(*Reader).Dispose"
}, {
"mangle": "_ZNK9INIReader10ParseErrorEv",
"c++": "INIReader::ParseError()",
"go": "(*Reader).ModifyedParseError"
}, {
"mangle": "_ZNK9INIReader3GetEPKcS1_S1_",
"c++": "INIReader::Get(const char *, const char *, const char *)",
"go": "(*Reader).Get"
}]
=== Test Case: lua ===
[{
"mangle": "lua_error",
"c++": "lua_error(lua_State *)",
"go": "Error"
}, {
"mangle": "lua_next",
"c++": "lua_next(lua_State *, int)",
"go": "Next"
}, {
"mangle": "lua_concat",
"c++": "lua_concat(lua_State *, int)",
"go": "Concat"
}, {
"mangle": "lua_stringtonumber",
"c++": "lua_stringtonumber(lua_State *, const char *)",
"go": "Stringtonumber"
}]
#stderr
#exit 0

View File

@@ -0,0 +1,117 @@
package main
import (
"fmt"
"os"
"github.com/goplus/llgo/chore/_xtool/llcppsymg/parse"
"github.com/goplus/llgo/chore/_xtool/llcppsymg/symbol"
"github.com/goplus/llgo/xtool/nm"
)
func main() {
TestParseHeaderFile()
}
func TestParseHeaderFile() {
testCases := []struct {
name string
content string
isCpp bool
prefixes []string
dylibSymbols []*nm.Symbol
symbFileContent string
}{
{
name: "inireader",
content: `
#define INI_API __attribute__((visibility("default")))
class INIReader {
public:
__attribute__((visibility("default"))) explicit INIReader(const char *filename);
INI_API explicit INIReader(const char *buffer, long buffer_size);
~INIReader();
INI_API int ParseError() const;
INI_API const char * Get(const char *section, const char *name,
const char *default_value) const;
private:
static const char * MakeKey(const char *section, const char *name);
};
`,
isCpp: true,
prefixes: []string{"INI"},
dylibSymbols: []*nm.Symbol{
{Name: "__ZN9INIReaderC1EPKc"},
{Name: "__ZN9INIReaderC1EPKcl"},
{Name: "__ZN9INIReaderD1Ev"},
{Name: "__ZNK9INIReader10ParseErrorEv"},
{Name: "__ZNK9INIReader3GetEPKcS1_S1_"},
},
symbFileContent: `
[{
"mangle": "_ZN9INIReaderC1EPKc",
"c++": "INIReader::INIReader(const char *)",
"go": "(*Reader).Init"
}, {
"mangle": "_ZN9INIReaderC1EPKcl",
"c++": "INIReader::INIReader(const char *, long)",
"go": "(*Reader).Init__1"
}, {
"mangle": "_ZN9INIReaderD1Ev",
"c++": "INIReader::~INIReader()",
"go": "(*Reader).Dispose"
}, {
"mangle": "_ZNK9INIReader10ParseErrorEv",
"c++": "INIReader::ParseError()",
"go": "(*Reader).ModifyedParseError"
}]`,
},
{
name: "lua",
content: `
typedef struct lua_State lua_State;
LUA_API int(lua_error)(lua_State *L);
LUA_API int(lua_next)(lua_State *L, int idx);
LUA_API void(lua_concat)(lua_State *L, int n);
LUA_API void(lua_len)(lua_State *L, int idx);
LUA_API long unsigned int(lua_stringtonumber)(lua_State *L, const char *s);
LUA_API void(lua_setallocf)(lua_State *L, lua_Alloc f, void *ud);
LUA_API void(lua_toclose)(lua_State *L, int idx);
LUA_API void(lua_closeslot)(lua_State *L, int idx);
`,
isCpp: false,
prefixes: []string{"lua_"},
dylibSymbols: []*nm.Symbol{
{Name: "_lua_error"},
{Name: "_lua_next"},
{Name: "_lua_concat"},
{Name: "_lua_stringtonumber"},
},
},
}
for _, tc := range testCases {
fmt.Printf("=== Test Case: %s ===\n", tc.name)
headerSymbolMap, err := parse.ParseHeaderFile([]string{tc.content}, tc.prefixes, tc.isCpp, true)
if err != nil {
fmt.Println("Error:", err)
}
tmpFile, err := os.CreateTemp("", "llcppg.symb.json")
if err != nil {
fmt.Printf("Failed to create temp file: %v\n", err)
return
}
tmpFile.Write([]byte(tc.symbFileContent))
symbolData, err := symbol.GenerateAndUpdateSymbolTable(tc.dylibSymbols, headerSymbolMap, tmpFile.Name())
if err != nil {
fmt.Println("Error:", err)
}
fmt.Println(string(symbolData))
os.Remove(tmpFile.Name())
}
}

View File

@@ -2,22 +2,41 @@ package header
import (
"fmt"
"os"
"path/filepath"
"strings"
)
func GenHeaderFilePath(cflags string, files []string) ([]string, error) {
fmt.Printf("get filepath from config cflags%s & include:%v\n", cflags, files)
prefixPath := strings.TrimPrefix(cflags, "-I")
var includePaths []string
var validPaths []string
var errs []string
for _, file := range files {
if file == "" {
continue
}
includePaths = append(includePaths, filepath.Join(prefixPath, "/"+file))
fullPath := filepath.Join(prefixPath, file)
if f, err := os.Open(fullPath); err != nil {
if os.IsNotExist(err) {
errs = append(errs, fmt.Sprintf("file not found: %s", file))
} else {
errs = append(errs, fmt.Sprintf("error accessing file %s: %v", file, err))
}
} else {
f.Close()
validPaths = append(validPaths, fullPath)
}
}
if len(includePaths) == 0 {
if len(validPaths) == 0 && len(errs) == 0 {
return nil, fmt.Errorf("no valid header files")
}
return includePaths, nil
if len(errs) > 0 {
return validPaths, fmt.Errorf("some files not found or inaccessible: %v", errs)
}
return validPaths, nil
}

View File

@@ -17,25 +17,20 @@
package main
import (
"errors"
"fmt"
"io"
"os"
"strings"
"unsafe"
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/cjson"
"github.com/goplus/llgo/chore/_xtool/llcppsymg/config"
"github.com/goplus/llgo/chore/_xtool/llcppsymg/dylib"
"github.com/goplus/llgo/chore/_xtool/llcppsymg/header"
"github.com/goplus/llgo/chore/_xtool/llcppsymg/parse"
"github.com/goplus/llgo/chore/llcppg/types"
"github.com/goplus/llgo/xtool/nm"
"github.com/goplus/llgo/chore/_xtool/llcppsymg/symbol"
)
func main() {
cfgFile := "llcppg.cfg"
symbFile := "llcppg.symb.json"
if len(os.Args) > 1 {
cfgFile = os.Args[1]
}
@@ -63,9 +58,10 @@ func main() {
headerInfos, err := parse.ParseHeaderFile(filepaths, conf.TrimPrefixes, conf.Cplusplus, false)
check(err)
symbolInfo := getCommonSymbols(symbols, headerInfos, conf.TrimPrefixes)
symbolData, err := symbol.GenerateAndUpdateSymbolTable(symbols, headerInfos, symbFile)
check(err)
err = genSymbolTableFile(symbolInfo)
err = os.WriteFile(symbFile, symbolData, 0644)
check(err)
}
@@ -74,92 +70,3 @@ func check(err error) {
panic(err)
}
}
func getCommonSymbols(dylibSymbols []*nm.Symbol, symbolMap map[string]*parse.SymbolInfo, prefix []string) []*types.SymbolInfo {
var commonSymbols []*types.SymbolInfo
for _, dylibSym := range dylibSymbols {
symName := strings.TrimPrefix(dylibSym.Name, "_")
if symInfo, ok := symbolMap[symName]; ok {
symbolInfo := &types.SymbolInfo{
Mangle: symName,
CPP: symInfo.ProtoName,
Go: symInfo.GoName,
}
commonSymbols = append(commonSymbols, symbolInfo)
}
}
return commonSymbols
}
func genSymbolTableFile(symbolInfos []*types.SymbolInfo) error {
fileName := "llcppg.symb.json"
existingSymbols, err := readExistingSymbolTable(fileName)
if err != nil {
return err
}
for i := range symbolInfos {
if existingSymbol, exists := existingSymbols[symbolInfos[i].Mangle]; exists {
symbolInfos[i].Go = existingSymbol.Go
}
}
root := cjson.Array()
defer root.Delete()
for _, symbol := range symbolInfos {
item := cjson.Object()
item.SetItem(c.Str("mangle"), cjson.String(c.AllocaCStr(symbol.Mangle)))
item.SetItem(c.Str("c++"), cjson.String(c.AllocaCStr(symbol.CPP)))
item.SetItem(c.Str("go"), cjson.String(c.AllocaCStr(symbol.Go)))
root.AddItem(item)
}
cStr := root.Print()
if cStr == nil {
return errors.New("symbol table is empty")
}
defer c.Free(unsafe.Pointer(cStr))
data := unsafe.Slice((*byte)(unsafe.Pointer(cStr)), c.Strlen(cStr))
if err := os.WriteFile(fileName, data, 0644); err != nil {
return errors.New("failed to write symbol table file")
}
return nil
}
func readExistingSymbolTable(fileName string) (map[string]types.SymbolInfo, error) {
existingSymbols := make(map[string]types.SymbolInfo)
if _, err := os.Stat(fileName); err != nil {
return existingSymbols, nil
}
data, err := os.ReadFile(fileName)
if err != nil {
return nil, errors.New("failed to read symbol table file")
}
parsedJSON := cjson.ParseBytes(data)
if parsedJSON == nil {
return nil, errors.New("failed to parse JSON")
}
arraySize := parsedJSON.GetArraySize()
for i := 0; i < int(arraySize); i++ {
item := parsedJSON.GetArrayItem(c.Int(i))
if item == nil {
continue
}
symbol := types.SymbolInfo{
Mangle: config.GetStringItem(item, "mangle", ""),
CPP: config.GetStringItem(item, "c++", ""),
Go: config.GetStringItem(item, "go", ""),
}
existingSymbols[symbol.Mangle] = symbol
}
return existingSymbols, nil
}

View File

@@ -0,0 +1,107 @@
package symbol
import (
"errors"
"os"
"strings"
"unsafe"
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/c/cjson"
"github.com/goplus/llgo/chore/_xtool/llcppsymg/config"
"github.com/goplus/llgo/chore/_xtool/llcppsymg/parse"
"github.com/goplus/llgo/chore/llcppg/types"
"github.com/goplus/llgo/xtool/nm"
)
// finds the intersection of symbols from the dynamic library's symbol table and the symbols parsed from header files.
// It returns a list of symbols that can be externally linked.
func GetCommonSymbols(dylibSymbols []*nm.Symbol, headerSymbols map[string]*parse.SymbolInfo) []*types.SymbolInfo {
var commonSymbols []*types.SymbolInfo
for _, dylibSym := range dylibSymbols {
symName := strings.TrimPrefix(dylibSym.Name, "_")
if symInfo, ok := headerSymbols[symName]; ok {
symbolInfo := &types.SymbolInfo{
Mangle: symName,
CPP: symInfo.ProtoName,
Go: symInfo.GoName,
}
commonSymbols = append(commonSymbols, symbolInfo)
}
}
return commonSymbols
}
func ReadExistingSymbolTable(fileName string) (map[string]types.SymbolInfo, bool) {
if _, err := os.Stat(fileName); err != nil {
return nil, false
}
data, err := os.ReadFile(fileName)
if err != nil {
return nil, false
}
parsedJSON := cjson.ParseBytes(data)
if parsedJSON == nil {
return nil, false
}
existingSymbols := make(map[string]types.SymbolInfo)
arraySize := parsedJSON.GetArraySize()
for i := 0; i < int(arraySize); i++ {
item := parsedJSON.GetArrayItem(c.Int(i))
symbol := types.SymbolInfo{
Mangle: config.GetStringItem(item, "mangle", ""),
CPP: config.GetStringItem(item, "c++", ""),
Go: config.GetStringItem(item, "go", ""),
}
existingSymbols[symbol.Mangle] = symbol
}
return existingSymbols, true
}
func GenSymbolTableData(commonSymbols []*types.SymbolInfo, existingSymbols map[string]types.SymbolInfo) ([]byte, error) {
// todo(zzy): len(existingSymbols) !=0
// https://github.com/goplus/llgo/issues/808 will cause unexpected panic
// https://github.com/goplus/llgo/pull/793 this pr can fix it
for i := range commonSymbols {
if existingSymbol, exists := existingSymbols[commonSymbols[i].Mangle]; exists {
commonSymbols[i].Go = existingSymbol.Go
}
}
root := cjson.Array()
defer root.Delete()
for _, symbol := range commonSymbols {
item := cjson.Object()
item.SetItem(c.Str("mangle"), cjson.String(c.AllocaCStr(symbol.Mangle)))
item.SetItem(c.Str("c++"), cjson.String(c.AllocaCStr(symbol.CPP)))
item.SetItem(c.Str("go"), cjson.String(c.AllocaCStr(symbol.Go)))
root.AddItem(item)
}
cStr := root.Print()
if cStr == nil {
return nil, errors.New("symbol table is empty")
}
defer c.Free(unsafe.Pointer(cStr))
result := []byte(c.GoString(cStr))
return result, nil
}
func GenerateAndUpdateSymbolTable(symbols []*nm.Symbol, headerInfos map[string]*parse.SymbolInfo, symbFile string) ([]byte, error) {
commonSymbols := GetCommonSymbols(symbols, headerInfos)
existSymbols, _ := ReadExistingSymbolTable(symbFile)
symbolData, err := GenSymbolTableData(commonSymbols, existSymbols)
if err != nil {
return nil, err
}
return symbolData, nil
}