diff --git a/cmd/checkheader/main.go b/cmd/checkheader/main.go index 7505bf3..c613b77 100644 --- a/cmd/checkheader/main.go +++ b/cmd/checkheader/main.go @@ -9,6 +9,7 @@ import ( "log" "os" "os/exec" + "runtime" "strings" "github.com/microsoft/go-crypto-darwin/internal/mkcgo" @@ -52,6 +53,10 @@ func main() { flag.Usage() os.Exit(1) } + if runtime.GOOS != "darwin" { + // This tool only works on macOS + return + } if *osslInclude != "" { if _, err := os.Stat(*osslInclude); err != nil { log.Fatalf("OpenSSL include directory not found: %v\n", err) diff --git a/cmd/genswiftimports/main.go b/cmd/genswiftimports/main.go index fc02469..0d7ff69 100644 --- a/cmd/genswiftimports/main.go +++ b/cmd/genswiftimports/main.go @@ -12,6 +12,7 @@ import ( "os/exec" "path/filepath" "regexp" + "runtime" "slices" "strings" ) @@ -23,6 +24,10 @@ var ( func main() { flag.Parse() + if runtime.GOOS != "darwin" { + // This tool only works on macOS + return + } baseName := "z" + *pkg + "_swift" fmt.Fprintf(os.Stderr, "generating bindings for package %s (base %s)\n", *pkg, baseName) diff --git a/cmd/mkcgo/generate.go b/cmd/mkcgo/generate.go index c0be781..7c225aa 100644 --- a/cmd/mkcgo/generate.go +++ b/cmd/mkcgo/generate.go @@ -5,12 +5,11 @@ package main import ( "fmt" + "go/token" "io" "slices" "strconv" "strings" - "unicode" - "unicode/utf8" "github.com/microsoft/go-crypto-darwin/internal/mkcgo" ) @@ -30,7 +29,7 @@ func generateGo(src *mkcgo.Source, w io.Writer) { // This block outputs C header includes and forward declarations for loader functions. fmt.Fprintf(w, "/*\n") fmt.Fprintf(w, "#cgo CFLAGS: -Wno-attributes\n") - if !*useDynamicLoading { + if dynload() { fmt.Fprintf(w, "#cgo unix LDFLAGS: -ldl\n\n") } if *includeHeader != "" { @@ -50,7 +49,7 @@ func generateGo(src *mkcgo.Source, w io.Writer) { // Generate type aliases for all generateGoAliases(src.Funcs, src.Externs, src.Enums, w) - if !*useDynamicLoading { + if dynload() { // Generate Go wrapper functions that load and unload the C symbols. for _, tag := range src.Tags() { fmt.Fprintf(w, "func %s_%s(handle unsafe.Pointer) {\n", goSymName("mkcgoLoad"), tag) @@ -227,7 +226,7 @@ func generateCHeader(src *mkcgo.Source, w io.Writer) { fmt.Fprintf(w, "void mkcgo_err_free(%s);\n", mkcgoErrState) fmt.Fprintf(w, "void mkcgo_err_clear();\n\n") - if !*useDynamicLoading { + if dynload() { // Add forward declarations for loader functions. for _, tag := range src.Tags() { fmt.Fprintf(w, "void __mkcgo_load_%s(void* handle);\n", tag) @@ -275,7 +274,7 @@ func generateC(src *mkcgo.Source, w io.Writer) { fmt.Fprintf(w, "#include \"%s\"\n", autogeneratedFileName(".h")) fmt.Fprintf(w, "\n") - if !*useDynamicLoading { + if dynload() { // Platform-specific includes. fmt.Fprintf(w, "#ifdef _WIN32\n") fmt.Fprintf(w, "#include \n") @@ -290,14 +289,14 @@ func generateC(src *mkcgo.Source, w io.Writer) { if fn.VariadicTarget != "" { continue } - if !*useDynamicLoading { + if dynload() { fmt.Fprintf(w, "%s (*_g_%s)(%s);\n", fn.Ret, fn.ImportName(), fnToCArgs(fn, true, false)) } else { fmt.Fprintf(w, "%s %s(%s);\n", fn.Ret, fn.ImportName(), fnToCArgs(fn, true, false)) } } fmt.Fprintf(w, "\n") - if !*useDynamicLoading { + if dynload() { fmt.Fprintf(w, "#define __mkcgo__dlsym_nocheck(varname, funcname) _g_##varname = (typeof(_g_##varname))dlsym(handle, #funcname);\n\n") fmt.Fprintf(w, "#define __mkcgo__dlsym(name) __mkcgo__dlsym2(name, name)\n\n") fmt.Fprintf(w, "#define __mkcgo__dlsym2(varname, funcname) \\\n") @@ -308,50 +307,7 @@ func generateC(src *mkcgo.Source, w io.Writer) { fmt.Fprintf(w, "\t}\n\n") // Loader and unloader functions for each tag. - for _, tag := range src.Tags() { - fmt.Fprintf(w, "void __mkcgo_load_%s(void* handle) {\n", tag) - for _, fn := range src.Funcs { - if fn.VariadicTarget != "" { - continue - } - tags := fn.Tags - if len(tags) == 0 { - tags = []mkcgo.TagAttr{{}} - } - for _, tagAttr := range tags { - if tagAttr.Tag == tag { - if tagAttr.Name != "" { - // TODO: if necessary, support optional functions in here too. - fmt.Fprintf(w, "\t__mkcgo__dlsym2(%s, %s)\n", fn.ImportName(), tagAttr.Name) - } else if fn.Optional { - fmt.Fprintf(w, "\t__mkcgo__dlsym_nocheck(%s, %s)\n", fn.ImportName(), fn.ImportName()) - } else { - fmt.Fprintf(w, "\t__mkcgo__dlsym(%s)\n", fn.ImportName()) - } - break - } - } - } - fmt.Fprintf(w, "}\n\n") - - fmt.Fprintf(w, "void __mkcgo_unload_%s() {\n", tag) - for _, fn := range src.Funcs { - if fn.VariadicTarget != "" { - continue - } - tags := fn.Tags - if len(tags) == 0 { - tags = []mkcgo.TagAttr{{}} - } - for _, tagAttr := range tags { - if tagAttr.Tag == tag { - fmt.Fprintf(w, "\t_g_%s = NULL;\n", fn.ImportName()) - break - } - } - } - fmt.Fprintf(w, "}\n\n") - } + generateMkcgoLoadFunctions(src, w) } // Generate C function wrappers. @@ -388,7 +344,7 @@ func generateGoFn(fn *mkcgo.Func, w io.Writer) { return } goType, needCast := cTypeToGo(fn.Ret, false) - if fn.NoError || !*errors { + if fn.NoError || *noerrors { fmt.Fprintf(w, " %s ", goType) } else { fmt.Fprintf(w, " (%s, error) ", goType) @@ -401,7 +357,7 @@ func generateGoFn(fn *mkcgo.Func, w io.Writer) { goType = fmt.Sprintf("(%s)(unsafe.Pointer", goType) needUnsafeCast = true } - if fn.NoError || !*errors { + if fn.NoError || *noerrors { // No error handling, just cast the return value if necessary. fmt.Fprintf(w, "\treturn ") if needCast { @@ -440,7 +396,7 @@ func generateGoFn(fn *mkcgo.Func, w io.Writer) { func generateCFn(typedefs map[string]string, fn *mkcgo.Func, w io.Writer) { var prefix string - if !*useDynamicLoading { + if dynload() { prefix = "_g_" } if !fnNeedErrWrapper(fn) { @@ -513,8 +469,6 @@ var cstdTypesToGo = map[string]string{ "int": "int32", "unsigned": "uint32", "unsigned int": "uint32", - "long": "int64", - "unsigned long": "uint64", "long long": "int64", "unsigned long long": "uint64", "size_t": "int", @@ -523,6 +477,11 @@ var cstdTypesToGo = map[string]string{ "unsigned char": "byte", "signed char": "int8", "void": "", + // On Windows, long and unsigned long are 32 bits, but on Unix they are 64 bits. + // We assume the Unix variant here, as it won't cause information loss when compiling + // for Windows. + "long": "int64", + "unsigned long": "uint64", } // cstdTypesToCgo maps C standard types to special cgo types. @@ -682,7 +641,7 @@ func fnCNameAvailable(fn *mkcgo.Func) string { // fnNeedErrWrapper reports whether function fn needs an error wrapper. func fnNeedErrWrapper(fn *mkcgo.Func) bool { - return *errors && !fn.NoError && !isVoid(fn.Ret) + return !*noerrors && !fn.NoError && !isVoid(fn.Ret) } // fnCalledFromGo reports whether function fn is called from Go code. @@ -698,11 +657,9 @@ func goSymName(name string) string { panic("empty name") } // Strip the 'go_' prefix commonly used in shims so Go symbols are nicer. - if strings.HasPrefix(name, "go_") { - name = name[3:] - } - ch, _ := utf8.DecodeRuneInString(name) - isPrivate := !unicode.IsUpper(ch) + name = strings.TrimPrefix(name, "go_") + + isPrivate := !token.IsExported(name) if *private == isPrivate { // Same access level, no need to change. return name @@ -724,134 +681,79 @@ func goSymName(name string) string { // getFrameworkPath returns the absolute framework path. func getFrameworkPath(dylib mkcgo.Framework) string { + if dylib.Name == "" && dylib.Version == "" { + return "" + } return fmt.Sprintf("/System/Library/Frameworks/%s.framework/Versions/%s/%s", dylib.Name, dylib.Version, dylib.Name) } // needsAssembly checks if assembly trampolines are needed for nocgo mode. -// Returns false if all functions use static imports, true otherwise. func needsAssembly(src *mkcgo.Source) bool { - useStaticImports := false - for _, c := range src.Comments { - if strings.TrimSpace(c) == "mkcgo:static_imports" { - useStaticImports = true - break - } + if dynload() { + return false } - - // If we use static imports, check if all functions are static - if useStaticImports { - for _, fn := range src.Funcs { - if !fn.Static { - return true // Need assembly for non-static functions - } + for _, fn := range src.Funcs { + if !fnCalledFromGo(fn) { + continue } - return false // All functions are static, no assembly needed } - - // Without static imports directive, we need assembly - return true + return false } // generateNocgoGo generates Go source file for nocgo mode from src. func generateNocgoGo(src *mkcgo.Source, w io.Writer) { // Output header notice and package declaration. printHeader(w) - fmt.Fprintf(w, "//go:build !cgo && darwin\n\n") - fmt.Fprintf(w, "package %s\n\n", *packageName) - needsRuntime := false - for _, fn := range src.Funcs { - if !fnCalledFromGo(fn) { - continue - } - // Check if we need runtime import for CCCryptorCreateWithMode - if fn.Name == "CCCryptorCreateWithMode" && len(fn.Params) > 9 { - needsRuntime = true - } + tags := "!cgo" + if *extratags != "" { + tags += " && (" + *extratags + ")" } + fmt.Fprintf(w, "//go:build %s\n\n", tags) + + fmt.Fprintf(w, "package %s\n\n", *packageName) + // Import necessary packages for nocgo mode fmt.Fprintf(w, "import (\n") - if needsRuntime { - fmt.Fprintf(w, "\t\"runtime\"\n") - } - fmt.Fprintf(w, "\t\"syscall\"\n") + fmt.Fprintf(w, "\t\"runtime\"\n") fmt.Fprintf(w, "\t\"unsafe\"\n") fmt.Fprintf(w, ")\n\n") - // Generate linkname declaration for the variadic syscall wrapper. - // Use syscall.syscallN for all syscall invocations to simplify generated - // code and support any number of arguments. - fmt.Fprintf(w, "//go:linkname syscall_syscallN syscall.syscallN\n") - fmt.Fprintf(w, "//go:linkname entersyscall runtime.entersyscall\n") - fmt.Fprintf(w, "//go:linkname exitsyscall runtime.exitsyscall\n") - fmt.Fprintf(w, "\n") - - // Generate function signatures for syscall functions - fmt.Fprintf(w, "//go:noescape\n") - fmt.Fprintf(w, "func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr)\n") - fmt.Fprintf(w, "func entersyscall()\n") - fmt.Fprintf(w, "func exitsyscall()\n") - fmt.Fprintf(w, "\n") - - fmt.Fprintf(w, "//go:nosplit\n") - fmt.Fprintf(w, "func syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr, err syscall.Errno) {\n") - fmt.Fprintf(w, "\tentersyscall()\n") - fmt.Fprintf(w, "\tr1, r2 = syscall_syscallN(fn, args...)\n") - fmt.Fprintf(w, "\texitsyscall()\n") - fmt.Fprintf(w, "\treturn r1, r2, 0\n") - fmt.Fprintf(w, "}\n") - // Generate cgo_import_dynamic directives for extern variables - useStaticImports := false - for _, c := range src.Comments { - if strings.TrimSpace(c) == "mkcgo:static_imports" { - useStaticImports = true - break - } - } - if useStaticImports { - for _, ext := range src.Externs { - extName := ext.Name + for _, ext := range src.Externs { + extName := ext.Name + if ext.Static { localName := extName if !strings.HasPrefix(extName, "go_") { localName = "go_" + extName } fmt.Fprintf(w, "//go:linkname %s %s\n", localName, localName) + continue } - } else { - for _, ext := range src.Externs { - extName := ext.Name - if ext.Static { - localName := extName - if !strings.HasPrefix(extName, "go_") { - localName = "go_" + extName - } - fmt.Fprintf(w, "//go:linkname %s %s\n", localName, localName) - continue - } - frameworkPath := getFrameworkPath(ext.Framework) - fmt.Fprintf(w, "//go:cgo_import_dynamic _mkcgo_%s %s \"%s\"\n", extName, extName, frameworkPath) - fmt.Fprintf(w, "//go:linkname _mkcgo_%s _mkcgo_%s\n", extName, extName) - } + frameworkPath := getFrameworkPath(ext.Framework) + fmt.Fprintf(w, "//go:cgo_import_dynamic _mkcgo_%s %s \"%s\"\n", extName, extName, frameworkPath) + fmt.Fprintf(w, "//go:linkname _mkcgo_%s _mkcgo_%s\n", extName, extName) } fmt.Fprintf(w, "\n") // Generate cgo_import_dynamic directives for each function for _, fn := range src.Funcs { - if !fnCalledFromGo(fn) { + // Skip base variadic functions unless they are targets for wrapper functions + // Variadic wrapper functions don't need their own imports since they call the variadic target + if fn.Attrs.VariadicTarget != "" { continue } - fnName := fn.Name - frameworkPath := getFrameworkPath(fn.Framework) - if useStaticImports || fn.Static { - localName := fnName - if !strings.HasPrefix(fnName, "go_") { - localName = "go_" + fnName + if fn.Static { + localName := fn.Name + if !strings.HasPrefix(localName, "go_") { + localName = "go_" + localName } fmt.Fprintf(w, "//go:linkname %s %s\n", localName, localName) } else { - fmt.Fprintf(w, "//go:cgo_import_dynamic _mkcgo_%s %s \"%s\"\n", fnName, fnName, frameworkPath) + if dynamic() { + fmt.Fprintf(w, "//go:cgo_import_dynamic _mkcgo_%s %s \"%s\"\n", fn.Name, fn.Name, getFrameworkPath(fn.Framework)) + } } } fmt.Fprintf(w, "\n") @@ -864,7 +766,7 @@ func generateNocgoGo(src *mkcgo.Source, w io.Writer) { if !fnCalledFromGo(fn) { continue } - if !useStaticImports && !fn.Static { + if !fn.Static { continue } localName := fn.Name @@ -886,12 +788,20 @@ func generateNocgoGo(src *mkcgo.Source, w io.Writer) { generateNocgoExterns(src.Externs, w) // Generate trampoline address variables and wrapper functions - for _, fn := range src.Funcs { - if !fnCalledFromGo(fn) { + typePtrs := make(map[string]bool, len(src.TypeDefs)) + for _, def := range src.TypeDefs { + if !strings.ContainsRune(def.Type, '*') { continue } - generateNocgoFn(src, fn, w) + typ, _ := cTypeToGo(def.Name, false) + typePtrs[typ] = true + } + for _, fn := range src.Funcs { + generateNocgoFn(typePtrs, src, fn, w) } + + // Generate MkcgoLoad and MkcgoUnload functions for each tag + generateMkcgoLoadFunctions(src, w) } // generateNocgoAliases generates Go type aliases for nocgo mode. @@ -902,12 +812,13 @@ func generateNocgoAliases(typedefs []*mkcgo.TypeDef, w io.Writer) { for _, typedef := range typedefs { // For basic types, make it an alias to the appropriate Go type goType, _ := cTypeToGo(typedef.Type, false) + name := goSymName(typedef.Name) if goType != "" && goType != "unsafe.Pointer" { - fmt.Fprintf(w, "type %s = %s\n", typedef.Name, goType) - seenTypes[typedef.Name] = true + fmt.Fprintf(w, "type %s = %s\n", name, goType) + seenTypes[name] = true } else { - fmt.Fprintf(w, "type %s unsafe.Pointer\n", typedef.Name) - seenTypes[typedef.Name] = true + fmt.Fprintf(w, "type %s unsafe.Pointer\n", name) + seenTypes[name] = true } } @@ -966,33 +877,53 @@ func generateNocgoExterns(externs []*mkcgo.Extern, w io.Writer) { } func trampolineName(fn *mkcgo.Func) string { - return fmt.Sprintf("_mkcgo_%s_trampoline_addr", fn.Name) + if fn.Static { + name := fn.Name + if !strings.HasPrefix(name, "go_") { + name = "go_" + name + } + return name + } + if dynload() { + return fmt.Sprintf("_mkcgo_%s", fn.ImportName()) + } + return fmt.Sprintf("_mkcgo_%s_trampoline_addr", fn.ImportName()) } // generateNocgoFn generates Go function wrapper for nocgo mode. -func generateNocgoFn(src *mkcgo.Source, fn *mkcgo.Func, w io.Writer) { - goFnName := goSymName(fn.Name) - - // Check if we should use static imports - useStaticImports := false - for _, c := range src.Comments { - if strings.TrimSpace(c) == "mkcgo:static_imports" { - useStaticImports = true - break +func generateNocgoFn(typePtrs map[string]bool, src *mkcgo.Source, fn *mkcgo.Func, w io.Writer) { + if fn.Variadic() { + if !fn.Static { + fmt.Fprintf(w, "var %s uintptr\n\n", trampolineName(fn)) } + // Nothing else to do. + return + } + if fn.Optional { + // Generate a function that returns true if the function is available. + // For nocgo mode, check if the function pointer is loaded. + fmt.Fprintf(w, "func %s() bool {\n", fnGoNameAvailable(fn)) + fmt.Fprintf(w, "\treturn %s != 0\n", fnCName(fn)) + fmt.Fprintf(w, "}\n\n") } - // Generate trampoline address variable only for non-static functions - if !useStaticImports && !fn.Static { + // Generate trampoline address variable + if fn.VariadicTarget == "" && !fn.Static { fmt.Fprintf(w, "var %s uintptr\n\n", trampolineName(fn)) } // Generate Go wrapper function - fmt.Fprintf(w, "func %s(", goFnName) + fmt.Fprintf(w, "func %s(", goSymName(fn.Name)) // Generate parameters + paramCount := 0 for i, param := range fn.Params { - if i > 0 { + // Skip void parameters + if param.Type == "void" { + continue + } + + if paramCount > 0 { fmt.Fprintf(w, ", ") } @@ -1003,13 +934,20 @@ func generateNocgoFn(src *mkcgo.Source, fn *mkcgo.Func, w io.Writer) { paramName = fmt.Sprintf("arg%d", i) } fmt.Fprintf(w, "%s %s", paramName, goType) + paramCount++ } fmt.Fprintf(w, ")") - // Generate return type + // Generate return type - only include error for functions that need error wrappers if fn.Ret != "" && fn.Ret != "void" { goRetType, _ := cTypeToGo(fn.Ret, false) - fmt.Fprintf(w, " %s", goRetType) + if fnNeedErrWrapper(fn) { + fmt.Fprintf(w, " (%s, error)", goRetType) + } else { + fmt.Fprintf(w, " %s", goRetType) + } + } else if fnNeedErrWrapper(fn) { + fmt.Fprintf(w, " error") } fmt.Fprintf(w, " {\n") @@ -1017,9 +955,9 @@ func generateNocgoFn(src *mkcgo.Source, fn *mkcgo.Func, w io.Writer) { // Special handling for MacOS ARM64 stack params // Generate architecture-specific code var tmp strings.Builder - macosArm64Params(src, fn.Params, &tmp) - needsSpecalHandling := strings.ContainsRune(tmp.String(), '|') - if needsSpecalHandling { + needsSpecialHandling := macosDarwinArm64Params(src, fn, &tmp) + + if needsSpecialHandling { fmt.Fprintf(w, "\tvar r0 uintptr\n") fmt.Fprintf(w, "\tif runtime.GOOS == \"darwin\" && runtime.GOARCH == \"arm64\" {\n") fmt.Fprintf(w, "\t\t") @@ -1028,34 +966,67 @@ func generateNocgoFn(src *mkcgo.Source, fn *mkcgo.Func, w io.Writer) { } // Use static function pointer or trampoline address - var functionRef string - if useStaticImports || fn.Static { - localName := fn.Name - if !strings.HasPrefix(localName, "go_") { - localName = "go_" + localName - } - functionRef = fmt.Sprintf("uintptr(unsafe.Pointer(&%s))", localName) - } else { - functionRef = trampolineName(fn) + functionRef := trampolineName(fn) + if fn.Static { + functionRef = fmt.Sprintf("uintptr(unsafe.Pointer(&%s))", functionRef) } fmt.Fprintf(w, "syscallN(%s, %s)\n", functionRef, tmp.String()) fmt.Fprintf(w, "\t} else {\n") } - generateNocgoFnBody(src, fn, !needsSpecalHandling, w) - if needsSpecalHandling { + generateNocgoFnBody(src, fn, !needsSpecialHandling, w) + if needsSpecialHandling { fmt.Fprintf(w, "\t}\n") } - // Generate return statement + for _, param := range fn.Params { + // Skip void parameters + if param.Type == "void" { + continue + } + + // Convert C types to Go types for nocgo mode + goType, _ := cTypeToGo(param.Type, false) + _, isPtr := typePtrs[goType] + if isPtr || strings.HasPrefix(goType, "*") { + fmt.Fprintf(w, "\truntime.KeepAlive(%s)\n", param.Name) + } + } + + // Generate return statement - only include error for functions that need error wrappers if fn.Ret != "" && fn.Ret != "void" { goRetType, _ := cTypeToGo(fn.Ret, false) - if strings.HasPrefix(goRetType, "*") { - // Pointer return types need to go through unsafe.Pointer - fmt.Fprintf(w, "\treturn (%s)(unsafe.Pointer(r0))\n", goRetType) + if fnNeedErrWrapper(fn) { + errCond := "<= 0" + zeroVal := "0" + if fn.ErrCond != "" { + errCond = fn.ErrCond + } else if strings.Contains(fn.Ret, "*") { + errCond = "== nil" + zeroVal = "nil" + } else if _, ok := typePtrs[goRetType]; ok { + errCond = "== nil" + zeroVal = "nil" + } + fmt.Fprintf(w, "\tif %s(r0) %s {\n", goRetType, errCond) + fmt.Fprintf(w, "\t\treturn %s, newMkcgoErr(\"%s\", nil)\n", zeroVal, fn.Name) + fmt.Fprintf(w, "\t}\n") + if strings.HasPrefix(goRetType, "*") { + // Pointer return types need to go through unsafe.Pointer + fmt.Fprintf(w, "\treturn (%s)(unsafe.Pointer(r0)), nil\n", goRetType) + } else { + fmt.Fprintf(w, "\treturn %s(r0), nil\n", goRetType) + } } else { - fmt.Fprintf(w, "\treturn %s(r0)\n", goRetType) + if strings.HasPrefix(goRetType, "*") { + // Pointer return types need to go through unsafe.Pointer + fmt.Fprintf(w, "\treturn (%s)(unsafe.Pointer(r0))\n", goRetType) + } else { + fmt.Fprintf(w, "\treturn %s(r0)\n", goRetType) + } } + } else if fnNeedErrWrapper(fn) { + fmt.Fprintf(w, "\treturn nil\n") } fmt.Fprintf(w, "}\n\n") @@ -1063,43 +1034,29 @@ func generateNocgoFn(src *mkcgo.Source, fn *mkcgo.Func, w io.Writer) { // generateNocgoFnBody generates Go function wrapper body for nocgo mode. func generateNocgoFnBody(src *mkcgo.Source, fn *mkcgo.Func, newR0 bool, w io.Writer) { - // Check if we should use static imports - useStaticImports := false - for _, c := range src.Comments { - if strings.TrimSpace(c) == "mkcgo:static_imports" { - useStaticImports = true - break - } - } - - // Generate syscall invocation - syscallFunc := "syscallN" - - // Determine function reference (static pointer or trampoline) - var functionRef string - if useStaticImports || fn.Static { - localName := fn.Name - if !strings.HasPrefix(localName, "go_") { - localName = "go_" + localName - } - functionRef = fmt.Sprintf("uintptr(unsafe.Pointer(&%s))", localName) - } else { - functionRef = trampolineName(fn) + fnArg := trampolineName(fn) + if fn.Static { + fnArg = fmt.Sprintf("uintptr(unsafe.Pointer(&%s))", fnArg) } - // Generate the syscall invocation with proper argument handling for other functions + // Generate the syscall invocation with proper argument handling if fn.Ret != "" && fn.Ret != "void" { colon := ":" if !newR0 { colon = "" } - fmt.Fprintf(w, "\tr0, _, _ %s= %s(%s", colon, syscallFunc, functionRef) + fmt.Fprintf(w, "\tr0, _, _ %s= syscallN(%s", colon, fnArg) } else { - fmt.Fprintf(w, "\t%s(%s", syscallFunc, functionRef) + fmt.Fprintf(w, "\tsyscallN(%s", fnArg) } // Add actual parameters for i, param := range fn.Params { + // Skip void parameters + if param.Type == "void" { + continue + } + paramName := param.Name if paramName == "" { paramName = fmt.Sprintf("arg%d", i) @@ -1121,15 +1078,15 @@ func generateNocgoFnBody(src *mkcgo.Source, fn *mkcgo.Func, newR0 bool, w io.Wri // This function is only called when dynamic imports are used. func generateAssembly(src *mkcgo.Source, w io.Writer) { printHeader(w) - fmt.Fprintf(w, "//go:build !cgo\n\n") + tags := "!cgo" + if *extratags != "" { + tags += " && (" + *extratags + ")" + } + fmt.Fprintf(w, "//go:build %s\n\n", tags) fmt.Fprintf(w, "#include \"textflag.h\"\n \n") // Generate trampolines for each function for _, fn := range src.Funcs { - if !fnCalledFromGo(fn) { - continue - } - fnName := fn.Name fmt.Fprintf(w, "TEXT _mkcgo_%s_trampoline<>(SB),NOSPLIT,$0-0\n", fnName) fmt.Fprintf(w, " JMP _mkcgo_%s(SB)\n", fnName) @@ -1138,12 +1095,32 @@ func generateAssembly(src *mkcgo.Source, w io.Writer) { } } -// macosArm64Params writes the string representing the parameters +// macosDarwinArm64Params writes the string representing the parameters // passed to a function on macOS ARM64. This platform is special // because the first 9 parameters are passed in registers, and // the rest are passed on the stack layed out using each type -// natural alignment. -func macosArm64Params(src *mkcgo.Source, params []*mkcgo.Param, w io.Writer) { +// natural alignment. Also, variadic parameters are passed on the stack. +func macosDarwinArm64Params(src *mkcgo.Source, fn *mkcgo.Func, w io.Writer) bool { + nonVariadicArgs := len(fn.Params) + if fn.VariadicTarget != "" { + var target *mkcgo.Func + for _, f := range src.Funcs { + if f.Name == fn.VariadicTarget { + target = f + break + } + } + if target == nil { + panic(fmt.Errorf("variadic target %q for %q not found: ", fn.VariadicTarget, fn.Name)) + } + nonVariadicArgs = len(target.Params) + for i := len(target.Params) - 1; i >= 0; i-- { + if !target.Params[i].Variadic() { + break + } + nonVariadicArgs-- + } + } var stackOffset, lastShift int shift := func(size int) { v := lastShift + size @@ -1161,14 +1138,27 @@ func macosArm64Params(src *mkcgo.Source, params []*mkcgo.Param, w io.Writer) { lastShift = 0 } } - for i, param := range params { + var needSpecialHandling bool + for i, param := range fn.Params { + const maxParamsInRegisters = 8 + if i == nonVariadicArgs { + // Variadic parameters start here, so we need to pad + // the remaining registers with zeros. + for j := i + 1; j <= maxParamsInRegisters; j++ { + needSpecialHandling = true + if j != 0 { + fmt.Fprintf(w, ", ") + } + fmt.Fprintf(w, "0") + } + } var goParam string if goType, _ := cTypeToGo(param.Type, false); strings.HasPrefix(goType, "*") { goParam = fmt.Sprintf("uintptr(unsafe.Pointer(%s))", param.Name) } else { goParam = fmt.Sprintf("uintptr(%s)", param.Name) } - if i < 9 { + if i <= maxParamsInRegisters { // Regular parameter handling for first 9 parameters. if i != 0 { fmt.Fprintf(w, ", ") @@ -1181,10 +1171,12 @@ func macosArm64Params(src *mkcgo.Source, params []*mkcgo.Param, w io.Writer) { fmt.Fprintf(w, ", ") } else { fmt.Fprintf(w, "|") + needSpecialHandling = true } fmt.Fprintf(w, "%s", goParam) shift(paramSize) } + return needSpecialHandling } func cTypeSize(src *mkcgo.Source, name string) int { @@ -1225,3 +1217,86 @@ func cTypeSize(src *mkcgo.Source, name string) int { return 8 } } + +// generateMkcgoLoadFunctions generates MkcgoLoad and MkcgoUnload functions for each tag +func generateMkcgoLoadFunctions(src *mkcgo.Source, w io.Writer) { + if !dynload() { + // TODO: support tags for other modes too + return + } + // Get all tags from the source + + for _, tag := range src.Tags() { + var tagOpened bool + // Collect functions that should be loaded for this tag + for _, fn := range src.Funcs { + if fn.Attrs.VariadicTarget != "" { + // Skip variadic wrapper functions in nocgo mode as they don't have real symbols + continue + } + tags := fn.Tags + if len(tags) == 0 { + tags = []mkcgo.TagAttr{{}} + } + for _, tagAttr := range tags { + if tagAttr.Tag == tag { + if !tagOpened { + if *nocgo { + fmt.Fprintf(w, "func %s_%s(handle unsafe.Pointer) {\n", goSymName("mkcgoLoad"), tag) + } else { + fmt.Fprintf(w, "void __mkcgo_load_%s(void* handle) {\n", tag) + } + tagOpened = true + } + if *nocgo { + if tagAttr.Name != "" { + // TODO: if necessary, support optional functions in here too. + fmt.Fprintf(w, "\t_mkcgo_%s = dlsym(handle, \"%s\\x00\", %v)\n", fn.Name, tagAttr.Name, fn.Optional) + } else { + fmt.Fprintf(w, "\t_mkcgo_%s = dlsym(handle, \"%s\\x00\", %v)\n", fn.Name, fn.Name, fn.Optional) + } + } else { + if tagAttr.Name != "" { + // TODO: if necessary, support optional functions in here too. + fmt.Fprintf(w, "\t__mkcgo__dlsym2(%s, %s)\n", fn.ImportName(), tagAttr.Name) + } else if fn.Optional { + fmt.Fprintf(w, "\t__mkcgo__dlsym_nocheck(%s, %s)\n", fn.ImportName(), fn.ImportName()) + } else { + fmt.Fprintf(w, "\t__mkcgo__dlsym(%s)\n", fn.ImportName()) + } + } + break + } + } + } + if tagOpened { + fmt.Fprintf(w, "}\n\n") + if *nocgo { + fmt.Fprintf(w, "func %s_%s() {\n", goSymName("mkcgoUnload"), tag) + } else { + fmt.Fprintf(w, "void __mkcgo_unload_%s() {\n", tag) + } + for _, fn := range src.Funcs { + if fn.Attrs.VariadicTarget != "" { + // Skip variadic wrapper functions in nocgo mode as they don't have real symbols + continue + } + tags := fn.Tags + if len(tags) == 0 { + tags = []mkcgo.TagAttr{{}} + } + for _, tagAttr := range tags { + if tagAttr.Tag == tag { + if *nocgo { + fmt.Fprintf(w, "\t_mkcgo_%s = 0\n", fn.Name) + } else { + fmt.Fprintf(w, "\t_g_%s = NULL;\n", fn.ImportName()) + } + break + } + } + } + fmt.Fprintf(w, "}\n\n") + } + } +} diff --git a/cmd/mkcgo/main.go b/cmd/mkcgo/main.go index 31425c6..52036b1 100644 --- a/cmd/mkcgo/main.go +++ b/cmd/mkcgo/main.go @@ -18,13 +18,14 @@ import ( ) var ( - fileName = flag.String("out", "", "output file name (standard output if omitted)") - includeHeader = flag.String("include", "", "include header file") - packageName = flag.String("package", "", "package name") - mode = flag.String("mode", "cgo", "mode: cgo (default), nocgo, all") - private = flag.Bool("private", false, "all Go generated symbols are kept unexported") - useDynamicLoading = flag.Bool("dynamic-loading", true, "use dynamic loading") - errors = flag.Bool("errors", false, "enable error handling") + fileName = flag.String("out", "", "output file name (standard output if omitted)") + includeHeader = flag.String("include", "", "include header file") + packageName = flag.String("package", "", "package name") + nocgo = flag.Bool("nocgo", false, "don't use cgo") + mode = flag.String("mode", "dynamic", "symbol load mode: dynamic, dynload") + private = flag.Bool("private", false, "all Go generated symbols are kept unexported") + noerrors = flag.Bool("noerrors", false, "disable error handling") + extratags = flag.String("tags", "", "tags to add to the generated files") ) func usage() { @@ -34,6 +35,14 @@ func usage() { os.Exit(1) } +func dynamic() bool { + return *mode == "dynamic" +} + +func dynload() bool { + return *mode == "dynload" +} + func main() { // Set up and parse flags. flag.Usage = usage @@ -63,7 +72,15 @@ func main() { return cmp.Compare(a.Name, b.Name) }) - if *mode == "nocgo" || *mode == "all" { + if *nocgo { + // Determine if this is a zdl file for special handling + baseNameForCheck := *fileName + if baseNameForCheck == "" { + baseNameForCheck = "mkcgo" + } else { + baseNameForCheck = strings.TrimSuffix(baseNameForCheck, ".go") + } + // Generate nocgo mode files var nocgoGoBuffer, assemblyBuffer bytes.Buffer generateNocgoGo(&src, &nocgoGoBuffer) @@ -77,11 +94,14 @@ func main() { // Format the generated Go source code. nocgoGoData := goformat(nocgoGoBuffer.Bytes()) + // Determine suffix based on the base name + suffix := "_nocgo.go" + files := []struct { suffix string data []byte }{ - {"_nocgo.go", nocgoGoData}, + {suffix, nocgoGoData}, } // Only add assembly file if needed @@ -108,9 +128,7 @@ func main() { } } - if *mode == "nocgo" { - return - } + return } var gobuf, go124buf, hbuf, cbuf bytes.Buffer @@ -177,7 +195,7 @@ func writeTempSourceFile(data []byte) (string, error) { } func goformat(data []byte) []byte { - data, err := format.Source(data) + fdata, err := format.Source(data) if err != nil { log.Printf("failed to format source: %v", err) f, err := writeTempSourceFile(data) @@ -186,5 +204,5 @@ func goformat(data []byte) []byte { } log.Fatalf("for diagnosis, wrote unformatted source to %v", f) } - return data + return fdata } diff --git a/internal/commoncrypto/commoncrypto.go b/internal/commoncrypto/commoncrypto.go index d39dbb3..fdda3e9 100644 --- a/internal/commoncrypto/commoncrypto.go +++ b/internal/commoncrypto/commoncrypto.go @@ -5,4 +5,5 @@ package commoncrypto //go:generate go run ../../cmd/checkheader -shim shims.h -//go:generate go run ../../cmd/mkcgo -out zcommoncrypto.go -mode all -package commoncrypto shims.h +//go:generate go run ../../cmd/mkcgo -out zcommoncrypto.go -package commoncrypto --noerrors shims.h +//go:generate go run ../../cmd/mkcgo -out zcommoncrypto.go -nocgo -package commoncrypto --noerrors shims.h diff --git a/internal/commoncrypto/syscall_nocgo.go b/internal/commoncrypto/syscall_nocgo.go new file mode 100644 index 0000000..73cedd4 --- /dev/null +++ b/internal/commoncrypto/syscall_nocgo.go @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +//go:build !cgo + +package commoncrypto + +import ( + "syscall" + _ "unsafe" +) + +//go:linkname syscall_syscallN syscall.syscallN +//go:linkname entersyscall runtime.entersyscall +//go:linkname exitsyscall runtime.exitsyscall + +//go:noescape +func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr) +func entersyscall() +func exitsyscall() + +//go:nosplit +func syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr, err syscall.Errno) { + entersyscall() + r1, r2 = syscall_syscallN(fn, args...) + exitsyscall() + return r1, r2, 0 +} diff --git a/internal/commoncrypto/zcommoncrypto_nocgo.go b/internal/commoncrypto/zcommoncrypto_nocgo.go index 778e5f9..373c97f 100644 --- a/internal/commoncrypto/zcommoncrypto_nocgo.go +++ b/internal/commoncrypto/zcommoncrypto_nocgo.go @@ -2,33 +2,15 @@ // Licensed under the MIT License. // Code generated by mkcgo. DO NOT EDIT. -//go:build !cgo && darwin +//go:build !cgo package commoncrypto import ( "runtime" - "syscall" "unsafe" ) -//go:linkname syscall_syscallN syscall.syscallN -//go:linkname entersyscall runtime.entersyscall -//go:linkname exitsyscall runtime.exitsyscall - -//go:noescape -func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr) -func entersyscall() -func exitsyscall() - -//go:nosplit -func syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr, err syscall.Errno) { - entersyscall() - r1, r2 = syscall_syscallN(fn, args...) - exitsyscall() - return r1, r2, 0 -} - //go:cgo_import_dynamic _mkcgo_CCCrypt CCCrypt "/System/Library/Frameworks/System.framework/Versions/B/System" //go:cgo_import_dynamic _mkcgo_CCCryptorCreate CCCryptorCreate "/System/Library/Frameworks/System.framework/Versions/B/System" //go:cgo_import_dynamic _mkcgo_CCCryptorCreateWithMode CCCryptorCreateWithMode "/System/Library/Frameworks/System.framework/Versions/B/System" @@ -104,6 +86,7 @@ var _mkcgo_CCCrypt_trampoline_addr uintptr func CCCrypt(op CCOperation, alg CCAlgorithm, options CCOptions, key unsafe.Pointer, keyLength int, iv unsafe.Pointer, dataIn unsafe.Pointer, dataInLength int, dataOut unsafe.Pointer, dataOutAvailable int, dataOutMoved *int) CCCryptorStatus { r0, _, _ := syscallN(_mkcgo_CCCrypt_trampoline_addr, uintptr(op), uintptr(alg), uintptr(options), uintptr(key), uintptr(keyLength), uintptr(iv), uintptr(dataIn), uintptr(dataInLength), uintptr(dataOut), uintptr(dataOutAvailable), uintptr(unsafe.Pointer(dataOutMoved))) + runtime.KeepAlive(dataOutMoved) return CCCryptorStatus(r0) } @@ -111,6 +94,7 @@ var _mkcgo_CCCryptorCreate_trampoline_addr uintptr func CCCryptorCreate(op CCOperation, alg CCAlgorithm, options CCOptions, key unsafe.Pointer, keyLength int, iv unsafe.Pointer, cryptorRef *CCCryptorRef) CCCryptorStatus { r0, _, _ := syscallN(_mkcgo_CCCryptorCreate_trampoline_addr, uintptr(op), uintptr(alg), uintptr(options), uintptr(key), uintptr(keyLength), uintptr(iv), uintptr(unsafe.Pointer(cryptorRef))) + runtime.KeepAlive(cryptorRef) return CCCryptorStatus(r0) } @@ -123,6 +107,7 @@ func CCCryptorCreateWithMode(op CCOperation, mode CCMode, alg CCAlgorithm, paddi } else { r0, _, _ = syscallN(_mkcgo_CCCryptorCreateWithMode_trampoline_addr, uintptr(op), uintptr(mode), uintptr(alg), uintptr(padding), uintptr(iv), uintptr(key), uintptr(keyLength), uintptr(tweak), uintptr(tweakLength), uintptr(numRounds), uintptr(options), uintptr(unsafe.Pointer(cryptorRef))) } + runtime.KeepAlive(cryptorRef) return CCCryptorStatus(r0) } @@ -130,6 +115,7 @@ var _mkcgo_CCCryptorRelease_trampoline_addr uintptr func CCCryptorRelease(cryptorRef CCCryptorRef) CCCryptorStatus { r0, _, _ := syscallN(_mkcgo_CCCryptorRelease_trampoline_addr, uintptr(cryptorRef)) + runtime.KeepAlive(cryptorRef) return CCCryptorStatus(r0) } @@ -137,6 +123,7 @@ var _mkcgo_CCCryptorReset_trampoline_addr uintptr func CCCryptorReset(cryptorRef CCCryptorRef, iv unsafe.Pointer) CCCryptorStatus { r0, _, _ := syscallN(_mkcgo_CCCryptorReset_trampoline_addr, uintptr(cryptorRef), uintptr(iv)) + runtime.KeepAlive(cryptorRef) return CCCryptorStatus(r0) } @@ -144,6 +131,8 @@ var _mkcgo_CCCryptorUpdate_trampoline_addr uintptr func CCCryptorUpdate(cryptorRef CCCryptorRef, dataIn unsafe.Pointer, dataInLength int, dataOut unsafe.Pointer, dataOutAvailable int, dataOutMoved *int) CCCryptorStatus { r0, _, _ := syscallN(_mkcgo_CCCryptorUpdate_trampoline_addr, uintptr(cryptorRef), uintptr(dataIn), uintptr(dataInLength), uintptr(dataOut), uintptr(dataOutAvailable), uintptr(unsafe.Pointer(dataOutMoved))) + runtime.KeepAlive(cryptorRef) + runtime.KeepAlive(dataOutMoved) return CCCryptorStatus(r0) } @@ -151,5 +140,8 @@ var _mkcgo_CCKeyDerivationPBKDF_trampoline_addr uintptr func CCKeyDerivationPBKDF(algorithm CCPBKDFAlgorithm, password *byte, passwordLen int, salt *uint8, saltLen int, prf CCPseudoRandomAlgorithm, rounds uint32, derivedKey *uint8, derivedKeyLen int) CCCryptorStatus { r0, _, _ := syscallN(_mkcgo_CCKeyDerivationPBKDF_trampoline_addr, uintptr(algorithm), uintptr(unsafe.Pointer(password)), uintptr(passwordLen), uintptr(unsafe.Pointer(salt)), uintptr(saltLen), uintptr(prf), uintptr(rounds), uintptr(unsafe.Pointer(derivedKey)), uintptr(derivedKeyLen)) + runtime.KeepAlive(password) + runtime.KeepAlive(salt) + runtime.KeepAlive(derivedKey) return CCCryptorStatus(r0) } diff --git a/internal/cryptokit/cryptokit.go b/internal/cryptokit/cryptokit.go index 7dde829..18a2506 100644 --- a/internal/cryptokit/cryptokit.go +++ b/internal/cryptokit/cryptokit.go @@ -5,7 +5,8 @@ package cryptokit -//go:generate go run ../../cmd/mkcgo -out zcryptokit.go -mode all -package cryptokit shims.h +//go:generate go run ../../cmd/mkcgo -out zcryptokit.go -package cryptokit --noerrors shims.h +//go:generate go run ../../cmd/mkcgo -out zcryptokit.go -nocgo -package cryptokit --noerrors shims.h //go:generate go run ../../cmd/genswiftimports // #cgo CFLAGS: -Wno-deprecated-declarations diff --git a/internal/cryptokit/syscall_nocgo.go b/internal/cryptokit/syscall_nocgo.go new file mode 100644 index 0000000..1a35e75 --- /dev/null +++ b/internal/cryptokit/syscall_nocgo.go @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +//go:build !cgo + +package cryptokit + +import ( + "syscall" + _ "unsafe" +) + +//go:linkname syscall_syscallN syscall.syscallN +//go:linkname entersyscall runtime.entersyscall +//go:linkname exitsyscall runtime.exitsyscall + +//go:noescape +func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr) +func entersyscall() +func exitsyscall() + +//go:nosplit +func syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr, err syscall.Errno) { + entersyscall() + r1, r2 = syscall_syscallN(fn, args...) + exitsyscall() + return r1, r2, 0 +} diff --git a/internal/cryptokit/zcryptokit_nocgo.go b/internal/cryptokit/zcryptokit_nocgo.go index e12d92a..7b441af 100644 --- a/internal/cryptokit/zcryptokit_nocgo.go +++ b/internal/cryptokit/zcryptokit_nocgo.go @@ -2,32 +2,15 @@ // Licensed under the MIT License. // Code generated by mkcgo. DO NOT EDIT. -//go:build !cgo && darwin +//go:build !cgo package cryptokit import ( - "syscall" + "runtime" "unsafe" ) -//go:linkname syscall_syscallN syscall.syscallN -//go:linkname entersyscall runtime.entersyscall -//go:linkname exitsyscall runtime.exitsyscall - -//go:noescape -func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr) -func entersyscall() -func exitsyscall() - -//go:nosplit -func syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr, err syscall.Errno) { - entersyscall() - r1, r2 = syscall_syscallN(fn, args...) - exitsyscall() - return r1, r2, 0 -} - //go:linkname go_MD5 go_MD5 //go:linkname go_SHA1 go_SHA1 //go:linkname go_SHA256 go_SHA256 @@ -86,22 +69,32 @@ var go_verifyEd25519 byte func MD5(inputPointer *uint8, inputLength int, outputPointer *uint8) { syscallN(uintptr(unsafe.Pointer(&go_MD5)), uintptr(unsafe.Pointer(inputPointer)), uintptr(inputLength), uintptr(unsafe.Pointer(outputPointer))) + runtime.KeepAlive(inputPointer) + runtime.KeepAlive(outputPointer) } func SHA1(inputPointer *uint8, inputLength int, outputPointer *uint8) { syscallN(uintptr(unsafe.Pointer(&go_SHA1)), uintptr(unsafe.Pointer(inputPointer)), uintptr(inputLength), uintptr(unsafe.Pointer(outputPointer))) + runtime.KeepAlive(inputPointer) + runtime.KeepAlive(outputPointer) } func SHA256(inputPointer *uint8, inputLength int, outputPointer *uint8) { syscallN(uintptr(unsafe.Pointer(&go_SHA256)), uintptr(unsafe.Pointer(inputPointer)), uintptr(inputLength), uintptr(unsafe.Pointer(outputPointer))) + runtime.KeepAlive(inputPointer) + runtime.KeepAlive(outputPointer) } func SHA384(inputPointer *uint8, inputLength int, outputPointer *uint8) { syscallN(uintptr(unsafe.Pointer(&go_SHA384)), uintptr(unsafe.Pointer(inputPointer)), uintptr(inputLength), uintptr(unsafe.Pointer(outputPointer))) + runtime.KeepAlive(inputPointer) + runtime.KeepAlive(outputPointer) } func SHA512(inputPointer *uint8, inputLength int, outputPointer *uint8) { syscallN(uintptr(unsafe.Pointer(&go_SHA512)), uintptr(unsafe.Pointer(inputPointer)), uintptr(inputLength), uintptr(unsafe.Pointer(outputPointer))) + runtime.KeepAlive(inputPointer) + runtime.KeepAlive(outputPointer) } func CopyHMAC(hashAlgorithm int32, ptr unsafe.Pointer) unsafe.Pointer { @@ -111,26 +104,46 @@ func CopyHMAC(hashAlgorithm int32, ptr unsafe.Pointer) unsafe.Pointer { func DecryptAESGCM(key *uint8, keyLength int, data *uint8, dataLength int, nonce *uint8, nonceLength int, aad *uint8, aadLength int, tag *uint8, tagLength int, out *uint8, outLength *int) int32 { r0, _, _ := syscallN(uintptr(unsafe.Pointer(&go_decryptAESGCM)), uintptr(unsafe.Pointer(key)), uintptr(keyLength), uintptr(unsafe.Pointer(data)), uintptr(dataLength), uintptr(unsafe.Pointer(nonce)), uintptr(nonceLength), uintptr(unsafe.Pointer(aad)), uintptr(aadLength), uintptr(unsafe.Pointer(tag)), uintptr(tagLength), uintptr(unsafe.Pointer(out)), uintptr(unsafe.Pointer(outLength))) + runtime.KeepAlive(key) + runtime.KeepAlive(data) + runtime.KeepAlive(nonce) + runtime.KeepAlive(aad) + runtime.KeepAlive(tag) + runtime.KeepAlive(out) + runtime.KeepAlive(outLength) return int32(r0) } func EncryptAESGCM(key *uint8, keyLength int, data *uint8, dataLength int, nonce *uint8, nonceLength int, aad *uint8, aadLength int, cipherText *uint8, cipherTextLength int, tag *uint8) int32 { r0, _, _ := syscallN(uintptr(unsafe.Pointer(&go_encryptAESGCM)), uintptr(unsafe.Pointer(key)), uintptr(keyLength), uintptr(unsafe.Pointer(data)), uintptr(dataLength), uintptr(unsafe.Pointer(nonce)), uintptr(nonceLength), uintptr(unsafe.Pointer(aad)), uintptr(aadLength), uintptr(unsafe.Pointer(cipherText)), uintptr(cipherTextLength), uintptr(unsafe.Pointer(tag))) + runtime.KeepAlive(key) + runtime.KeepAlive(data) + runtime.KeepAlive(nonce) + runtime.KeepAlive(aad) + runtime.KeepAlive(cipherText) + runtime.KeepAlive(tag) return int32(r0) } func ExpandHKDF(hashFunction int32, prk *uint8, prkLength int, info *uint8, infoLength int, okm *uint8, okmLength int) int32 { r0, _, _ := syscallN(uintptr(unsafe.Pointer(&go_expandHKDF)), uintptr(hashFunction), uintptr(unsafe.Pointer(prk)), uintptr(prkLength), uintptr(unsafe.Pointer(info)), uintptr(infoLength), uintptr(unsafe.Pointer(okm)), uintptr(okmLength)) + runtime.KeepAlive(prk) + runtime.KeepAlive(info) + runtime.KeepAlive(okm) return int32(r0) } func ExtractHKDF(hashFunction int32, secret *uint8, secretLength int, salt *uint8, saltLength int, prk *uint8, prkLength int) int32 { r0, _, _ := syscallN(uintptr(unsafe.Pointer(&go_extractHKDF)), uintptr(hashFunction), uintptr(unsafe.Pointer(secret)), uintptr(secretLength), uintptr(unsafe.Pointer(salt)), uintptr(saltLength), uintptr(unsafe.Pointer(prk)), uintptr(prkLength)) + runtime.KeepAlive(secret) + runtime.KeepAlive(salt) + runtime.KeepAlive(prk) return int32(r0) } func FinalizeHMAC(hashFunction int32, ptr unsafe.Pointer, outputPointer *uint8) { syscallN(uintptr(unsafe.Pointer(&go_finalizeHMAC)), uintptr(hashFunction), uintptr(ptr), uintptr(unsafe.Pointer(outputPointer))) + runtime.KeepAlive(outputPointer) } func FreeHMAC(hashFunction int32, ptr unsafe.Pointer) { @@ -139,6 +152,7 @@ func FreeHMAC(hashFunction int32, ptr unsafe.Pointer) { func GenerateKeyEd25519(key *uint8) { syscallN(uintptr(unsafe.Pointer(&go_generateKeyEd25519)), uintptr(unsafe.Pointer(key))) + runtime.KeepAlive(key) } func HashBlockSize(hashAlgorithm int32) int32 { @@ -171,37 +185,51 @@ func HashSize(hashAlgorithm int32) int32 { func HashSum(hashAlgorithm int32, ptr unsafe.Pointer, outputPointer *uint8) { syscallN(uintptr(unsafe.Pointer(&go_hashSum)), uintptr(hashAlgorithm), uintptr(ptr), uintptr(unsafe.Pointer(outputPointer))) + runtime.KeepAlive(outputPointer) } func HashWrite(hashAlgorithm int32, ptr unsafe.Pointer, data *uint8, length int32) { syscallN(uintptr(unsafe.Pointer(&go_hashWrite)), uintptr(hashAlgorithm), uintptr(ptr), uintptr(unsafe.Pointer(data)), uintptr(length)) + runtime.KeepAlive(data) } func InitHMAC(hashFunction int32, key *uint8, keyLength int32) unsafe.Pointer { r0, _, _ := syscallN(uintptr(unsafe.Pointer(&go_initHMAC)), uintptr(hashFunction), uintptr(unsafe.Pointer(key)), uintptr(keyLength)) + runtime.KeepAlive(key) return unsafe.Pointer(r0) } func NewPrivateKeyEd25519FromSeed(key *uint8, seed *uint8) int32 { r0, _, _ := syscallN(uintptr(unsafe.Pointer(&go_newPrivateKeyEd25519FromSeed)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(seed))) + runtime.KeepAlive(key) + runtime.KeepAlive(seed) return int32(r0) } func NewPublicKeyEd25519(key *uint8, pub *uint8) int32 { r0, _, _ := syscallN(uintptr(unsafe.Pointer(&go_newPublicKeyEd25519)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(pub))) + runtime.KeepAlive(key) + runtime.KeepAlive(pub) return int32(r0) } func SignEd25519(privateKey *uint8, message *uint8, messageLength int, sigBuffer *uint8) int32 { r0, _, _ := syscallN(uintptr(unsafe.Pointer(&go_signEd25519)), uintptr(unsafe.Pointer(privateKey)), uintptr(unsafe.Pointer(message)), uintptr(messageLength), uintptr(unsafe.Pointer(sigBuffer))) + runtime.KeepAlive(privateKey) + runtime.KeepAlive(message) + runtime.KeepAlive(sigBuffer) return int32(r0) } func UpdateHMAC(hashFunction int32, ptr unsafe.Pointer, data *uint8, length int32) { syscallN(uintptr(unsafe.Pointer(&go_updateHMAC)), uintptr(hashFunction), uintptr(ptr), uintptr(unsafe.Pointer(data)), uintptr(length)) + runtime.KeepAlive(data) } func VerifyEd25519(publicKey *uint8, message *uint8, messageLength int, sig *uint8) int32 { r0, _, _ := syscallN(uintptr(unsafe.Pointer(&go_verifyEd25519)), uintptr(unsafe.Pointer(publicKey)), uintptr(unsafe.Pointer(message)), uintptr(messageLength), uintptr(unsafe.Pointer(sig))) + runtime.KeepAlive(publicKey) + runtime.KeepAlive(message) + runtime.KeepAlive(sig) return int32(r0) } diff --git a/internal/mkcgo/parse.go b/internal/mkcgo/parse.go index dfdf4f9..92ab02b 100644 --- a/internal/mkcgo/parse.go +++ b/internal/mkcgo/parse.go @@ -7,6 +7,7 @@ import ( "bufio" "errors" "fmt" + "go/token" "io" "slices" "strings" @@ -224,8 +225,7 @@ func normalizeParam(name, typ string) (string, string) { name = name[1:] typ += "*" } - switch name { - case "type", "func": + if token.IsKeyword(name) || name == "error" { name = "__" + name } // Remove duplicated spaces. diff --git a/internal/security/security.go b/internal/security/security.go index aedeb5e..0fda5b2 100644 --- a/internal/security/security.go +++ b/internal/security/security.go @@ -5,4 +5,5 @@ package security //go:generate go run ../../cmd/checkheader -shim shims.h -//go:generate go run ../../cmd/mkcgo -out zsecurity.go -mode all -package security shims.h +//go:generate go run ../../cmd/mkcgo -out zsecurity.go -package security --noerrors shims.h +//go:generate go run ../../cmd/mkcgo -out zsecurity.go -nocgo -package security --noerrors shims.h diff --git a/internal/security/syscall_nocgo.go b/internal/security/syscall_nocgo.go new file mode 100644 index 0000000..5d7f123 --- /dev/null +++ b/internal/security/syscall_nocgo.go @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +//go:build !cgo + +package security + +import ( + "syscall" + _ "unsafe" +) + +//go:linkname syscall_syscallN syscall.syscallN +//go:linkname entersyscall runtime.entersyscall +//go:linkname exitsyscall runtime.exitsyscall + +//go:noescape +func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr) +func entersyscall() +func exitsyscall() + +//go:nosplit +func syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr, err syscall.Errno) { + entersyscall() + r1, r2 = syscall_syscallN(fn, args...) + exitsyscall() + return r1, r2, 0 +} diff --git a/internal/security/zsecurity.go b/internal/security/zsecurity.go index 16c4c49..6a6e11d 100644 --- a/internal/security/zsecurity.go +++ b/internal/security/zsecurity.go @@ -108,12 +108,12 @@ func CFDictionarySetValue(theDict CFMutableDictionaryRef, key unsafe.Pointer, va C._mkcgo_CFDictionarySetValue(theDict, key, value) } -func CFErrorCopyDescription(error CFErrorRef) CFStringRef { - return C._mkcgo_CFErrorCopyDescription(error) +func CFErrorCopyDescription(__error CFErrorRef) CFStringRef { + return C._mkcgo_CFErrorCopyDescription(__error) } -func CFErrorGetCode(error CFErrorRef) CFIndex { - return C._mkcgo_CFErrorGetCode(error) +func CFErrorGetCode(__error CFErrorRef) CFIndex { + return C._mkcgo_CFErrorGetCode(__error) } func CFNumberCreate(allocator CFAllocatorRef, theType CFNumberType, valuePtr unsafe.Pointer) CFNumberRef { @@ -132,36 +132,36 @@ func CFStringGetLength(str CFStringRef) CFIndex { return C._mkcgo_CFStringGetLength(str) } -func SecKeyCopyExternalRepresentation(key SecKeyRef, error *CFErrorRef) CFDataRef { - return C._mkcgo_SecKeyCopyExternalRepresentation(key, error) +func SecKeyCopyExternalRepresentation(key SecKeyRef, __error *CFErrorRef) CFDataRef { + return C._mkcgo_SecKeyCopyExternalRepresentation(key, __error) } -func SecKeyCopyKeyExchangeResult(privateKey SecKeyRef, algorithm SecKeyAlgorithm, publicKey SecKeyRef, parameters CFDictionaryRef, error *CFErrorRef) CFDataRef { - return C._mkcgo_SecKeyCopyKeyExchangeResult(privateKey, algorithm, publicKey, parameters, error) +func SecKeyCopyKeyExchangeResult(privateKey SecKeyRef, algorithm SecKeyAlgorithm, publicKey SecKeyRef, parameters CFDictionaryRef, __error *CFErrorRef) CFDataRef { + return C._mkcgo_SecKeyCopyKeyExchangeResult(privateKey, algorithm, publicKey, parameters, __error) } func SecKeyCopyPublicKey(key SecKeyRef) SecKeyRef { return C._mkcgo_SecKeyCopyPublicKey(key) } -func SecKeyCreateDecryptedData(key SecKeyRef, algorithm SecKeyAlgorithm, ciphertext CFDataRef, error *CFErrorRef) CFDataRef { - return C._mkcgo_SecKeyCreateDecryptedData(key, algorithm, ciphertext, error) +func SecKeyCreateDecryptedData(key SecKeyRef, algorithm SecKeyAlgorithm, ciphertext CFDataRef, __error *CFErrorRef) CFDataRef { + return C._mkcgo_SecKeyCreateDecryptedData(key, algorithm, ciphertext, __error) } -func SecKeyCreateEncryptedData(key SecKeyRef, algorithm SecKeyAlgorithm, plaintext CFDataRef, error *CFErrorRef) CFDataRef { - return C._mkcgo_SecKeyCreateEncryptedData(key, algorithm, plaintext, error) +func SecKeyCreateEncryptedData(key SecKeyRef, algorithm SecKeyAlgorithm, plaintext CFDataRef, __error *CFErrorRef) CFDataRef { + return C._mkcgo_SecKeyCreateEncryptedData(key, algorithm, plaintext, __error) } -func SecKeyCreateRandomKey(parameters CFDictionaryRef, error *CFErrorRef) SecKeyRef { - return C._mkcgo_SecKeyCreateRandomKey(parameters, error) +func SecKeyCreateRandomKey(parameters CFDictionaryRef, __error *CFErrorRef) SecKeyRef { + return C._mkcgo_SecKeyCreateRandomKey(parameters, __error) } -func SecKeyCreateSignature(key SecKeyRef, algorithm SecKeyAlgorithm, data CFDataRef, error *CFErrorRef) CFDataRef { - return C._mkcgo_SecKeyCreateSignature(key, algorithm, data, error) +func SecKeyCreateSignature(key SecKeyRef, algorithm SecKeyAlgorithm, data CFDataRef, __error *CFErrorRef) CFDataRef { + return C._mkcgo_SecKeyCreateSignature(key, algorithm, data, __error) } -func SecKeyCreateWithData(keyData CFDataRef, attributes CFDictionaryRef, error *CFErrorRef) SecKeyRef { - return C._mkcgo_SecKeyCreateWithData(keyData, attributes, error) +func SecKeyCreateWithData(keyData CFDataRef, attributes CFDictionaryRef, __error *CFErrorRef) SecKeyRef { + return C._mkcgo_SecKeyCreateWithData(keyData, attributes, __error) } func SecKeyGetBlockSize(key SecKeyRef) int { @@ -172,8 +172,8 @@ func SecKeyIsAlgorithmSupported(key SecKeyRef, operation SecKeyOperationType, al return C._mkcgo_SecKeyIsAlgorithmSupported(key, operation, algorithm) } -func SecKeyVerifySignature(key SecKeyRef, algorithm SecKeyAlgorithm, signedData CFDataRef, signature CFDataRef, error *CFErrorRef) Boolean { - return C._mkcgo_SecKeyVerifySignature(key, algorithm, signedData, signature, error) +func SecKeyVerifySignature(key SecKeyRef, algorithm SecKeyAlgorithm, signedData CFDataRef, signature CFDataRef, __error *CFErrorRef) Boolean { + return C._mkcgo_SecKeyVerifySignature(key, algorithm, signedData, signature, __error) } func SecRandomCopyBytes(rnd SecRandomRef, count int, bytes unsafe.Pointer) int32 { diff --git a/internal/security/zsecurity_nocgo.go b/internal/security/zsecurity_nocgo.go index ef65113..196cb95 100644 --- a/internal/security/zsecurity_nocgo.go +++ b/internal/security/zsecurity_nocgo.go @@ -2,32 +2,15 @@ // Licensed under the MIT License. // Code generated by mkcgo. DO NOT EDIT. -//go:build !cgo && darwin +//go:build !cgo package security import ( - "syscall" + "runtime" "unsafe" ) -//go:linkname syscall_syscallN syscall.syscallN -//go:linkname entersyscall runtime.entersyscall -//go:linkname exitsyscall runtime.exitsyscall - -//go:noescape -func syscall_syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr) -func entersyscall() -func exitsyscall() - -//go:nosplit -func syscallN(fn uintptr, args ...uintptr) (r1, r2 uintptr, err syscall.Errno) { - entersyscall() - r1, r2 = syscall_syscallN(fn, args...) - exitsyscall() - return r1, r2, 0 -} - //go:cgo_import_dynamic _mkcgo_kCFAllocatorDefault kCFAllocatorDefault "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" //go:linkname _mkcgo_kCFAllocatorDefault _mkcgo_kCFAllocatorDefault //go:cgo_import_dynamic _mkcgo_kSecRandomDefault kSecRandomDefault "/System/Library/Frameworks/Security.framework/Versions/A/Security" @@ -347,6 +330,8 @@ var _mkcgo_CFDataCreate_trampoline_addr uintptr func CFDataCreate(allocator CFAllocatorRef, bytes *uint8, length CFIndex) CFDataRef { r0, _, _ := syscallN(_mkcgo_CFDataCreate_trampoline_addr, uintptr(allocator), uintptr(unsafe.Pointer(bytes)), uintptr(length)) + runtime.KeepAlive(allocator) + runtime.KeepAlive(bytes) return CFDataRef(r0) } @@ -354,6 +339,7 @@ var _mkcgo_CFDataGetBytePtr_trampoline_addr uintptr func CFDataGetBytePtr(data CFDataRef) *uint8 { r0, _, _ := syscallN(_mkcgo_CFDataGetBytePtr_trampoline_addr, uintptr(data)) + runtime.KeepAlive(data) return (*uint8)(unsafe.Pointer(r0)) } @@ -361,6 +347,7 @@ var _mkcgo_CFDataGetLength_trampoline_addr uintptr func CFDataGetLength(data CFDataRef) CFIndex { r0, _, _ := syscallN(_mkcgo_CFDataGetLength_trampoline_addr, uintptr(data)) + runtime.KeepAlive(data) return CFIndex(r0) } @@ -368,6 +355,11 @@ var _mkcgo_CFDictionaryCreate_trampoline_addr uintptr func CFDictionaryCreate(allocator CFAllocatorRef, keys *unsafe.Pointer, values *unsafe.Pointer, numValues CFIndex, keyCallBacks *CFDictionaryKeyCallBacks, valueCallBacks *CFDictionaryValueCallBacks) CFDictionaryRef { r0, _, _ := syscallN(_mkcgo_CFDictionaryCreate_trampoline_addr, uintptr(allocator), uintptr(unsafe.Pointer(keys)), uintptr(unsafe.Pointer(values)), uintptr(numValues), uintptr(unsafe.Pointer(keyCallBacks)), uintptr(unsafe.Pointer(valueCallBacks))) + runtime.KeepAlive(allocator) + runtime.KeepAlive(keys) + runtime.KeepAlive(values) + runtime.KeepAlive(keyCallBacks) + runtime.KeepAlive(valueCallBacks) return CFDictionaryRef(r0) } @@ -375,6 +367,9 @@ var _mkcgo_CFDictionaryCreateMutable_trampoline_addr uintptr func CFDictionaryCreateMutable(allocator CFAllocatorRef, capacity CFIndex, keyCallBacks *CFDictionaryKeyCallBacks, valueCallBacks *CFDictionaryValueCallBacks) CFMutableDictionaryRef { r0, _, _ := syscallN(_mkcgo_CFDictionaryCreateMutable_trampoline_addr, uintptr(allocator), uintptr(capacity), uintptr(unsafe.Pointer(keyCallBacks)), uintptr(unsafe.Pointer(valueCallBacks))) + runtime.KeepAlive(allocator) + runtime.KeepAlive(keyCallBacks) + runtime.KeepAlive(valueCallBacks) return CFMutableDictionaryRef(r0) } @@ -382,19 +377,22 @@ var _mkcgo_CFDictionarySetValue_trampoline_addr uintptr func CFDictionarySetValue(theDict CFMutableDictionaryRef, key unsafe.Pointer, value unsafe.Pointer) { syscallN(_mkcgo_CFDictionarySetValue_trampoline_addr, uintptr(theDict), uintptr(key), uintptr(value)) + runtime.KeepAlive(theDict) } var _mkcgo_CFErrorCopyDescription_trampoline_addr uintptr -func CFErrorCopyDescription(error CFErrorRef) CFStringRef { - r0, _, _ := syscallN(_mkcgo_CFErrorCopyDescription_trampoline_addr, uintptr(error)) +func CFErrorCopyDescription(__error CFErrorRef) CFStringRef { + r0, _, _ := syscallN(_mkcgo_CFErrorCopyDescription_trampoline_addr, uintptr(__error)) + runtime.KeepAlive(__error) return CFStringRef(r0) } var _mkcgo_CFErrorGetCode_trampoline_addr uintptr -func CFErrorGetCode(error CFErrorRef) CFIndex { - r0, _, _ := syscallN(_mkcgo_CFErrorGetCode_trampoline_addr, uintptr(error)) +func CFErrorGetCode(__error CFErrorRef) CFIndex { + r0, _, _ := syscallN(_mkcgo_CFErrorGetCode_trampoline_addr, uintptr(__error)) + runtime.KeepAlive(__error) return CFIndex(r0) } @@ -402,6 +400,7 @@ var _mkcgo_CFNumberCreate_trampoline_addr uintptr func CFNumberCreate(allocator CFAllocatorRef, theType CFNumberType, valuePtr unsafe.Pointer) CFNumberRef { r0, _, _ := syscallN(_mkcgo_CFNumberCreate_trampoline_addr, uintptr(allocator), uintptr(theType), uintptr(valuePtr)) + runtime.KeepAlive(allocator) return CFNumberRef(r0) } @@ -409,12 +408,14 @@ var _mkcgo_CFRelease_trampoline_addr uintptr func CFRelease(cf CFTypeRef) { syscallN(_mkcgo_CFRelease_trampoline_addr, uintptr(cf)) + runtime.KeepAlive(cf) } var _mkcgo_CFStringGetCStringPtr_trampoline_addr uintptr func CFStringGetCStringPtr(str CFStringRef, encoding CFStringEncoding) *byte { r0, _, _ := syscallN(_mkcgo_CFStringGetCStringPtr_trampoline_addr, uintptr(str), uintptr(encoding)) + runtime.KeepAlive(str) return (*byte)(unsafe.Pointer(r0)) } @@ -422,20 +423,27 @@ var _mkcgo_CFStringGetLength_trampoline_addr uintptr func CFStringGetLength(str CFStringRef) CFIndex { r0, _, _ := syscallN(_mkcgo_CFStringGetLength_trampoline_addr, uintptr(str)) + runtime.KeepAlive(str) return CFIndex(r0) } var _mkcgo_SecKeyCopyExternalRepresentation_trampoline_addr uintptr -func SecKeyCopyExternalRepresentation(key SecKeyRef, error *CFErrorRef) CFDataRef { - r0, _, _ := syscallN(_mkcgo_SecKeyCopyExternalRepresentation_trampoline_addr, uintptr(key), uintptr(unsafe.Pointer(error))) +func SecKeyCopyExternalRepresentation(key SecKeyRef, __error *CFErrorRef) CFDataRef { + r0, _, _ := syscallN(_mkcgo_SecKeyCopyExternalRepresentation_trampoline_addr, uintptr(key), uintptr(unsafe.Pointer(__error))) + runtime.KeepAlive(key) + runtime.KeepAlive(__error) return CFDataRef(r0) } var _mkcgo_SecKeyCopyKeyExchangeResult_trampoline_addr uintptr -func SecKeyCopyKeyExchangeResult(privateKey SecKeyRef, algorithm SecKeyAlgorithm, publicKey SecKeyRef, parameters CFDictionaryRef, error *CFErrorRef) CFDataRef { - r0, _, _ := syscallN(_mkcgo_SecKeyCopyKeyExchangeResult_trampoline_addr, uintptr(privateKey), uintptr(algorithm), uintptr(publicKey), uintptr(parameters), uintptr(unsafe.Pointer(error))) +func SecKeyCopyKeyExchangeResult(privateKey SecKeyRef, algorithm SecKeyAlgorithm, publicKey SecKeyRef, parameters CFDictionaryRef, __error *CFErrorRef) CFDataRef { + r0, _, _ := syscallN(_mkcgo_SecKeyCopyKeyExchangeResult_trampoline_addr, uintptr(privateKey), uintptr(algorithm), uintptr(publicKey), uintptr(parameters), uintptr(unsafe.Pointer(__error))) + runtime.KeepAlive(privateKey) + runtime.KeepAlive(publicKey) + runtime.KeepAlive(parameters) + runtime.KeepAlive(__error) return CFDataRef(r0) } @@ -443,41 +451,56 @@ var _mkcgo_SecKeyCopyPublicKey_trampoline_addr uintptr func SecKeyCopyPublicKey(key SecKeyRef) SecKeyRef { r0, _, _ := syscallN(_mkcgo_SecKeyCopyPublicKey_trampoline_addr, uintptr(key)) + runtime.KeepAlive(key) return SecKeyRef(r0) } var _mkcgo_SecKeyCreateDecryptedData_trampoline_addr uintptr -func SecKeyCreateDecryptedData(key SecKeyRef, algorithm SecKeyAlgorithm, ciphertext CFDataRef, error *CFErrorRef) CFDataRef { - r0, _, _ := syscallN(_mkcgo_SecKeyCreateDecryptedData_trampoline_addr, uintptr(key), uintptr(algorithm), uintptr(ciphertext), uintptr(unsafe.Pointer(error))) +func SecKeyCreateDecryptedData(key SecKeyRef, algorithm SecKeyAlgorithm, ciphertext CFDataRef, __error *CFErrorRef) CFDataRef { + r0, _, _ := syscallN(_mkcgo_SecKeyCreateDecryptedData_trampoline_addr, uintptr(key), uintptr(algorithm), uintptr(ciphertext), uintptr(unsafe.Pointer(__error))) + runtime.KeepAlive(key) + runtime.KeepAlive(ciphertext) + runtime.KeepAlive(__error) return CFDataRef(r0) } var _mkcgo_SecKeyCreateEncryptedData_trampoline_addr uintptr -func SecKeyCreateEncryptedData(key SecKeyRef, algorithm SecKeyAlgorithm, plaintext CFDataRef, error *CFErrorRef) CFDataRef { - r0, _, _ := syscallN(_mkcgo_SecKeyCreateEncryptedData_trampoline_addr, uintptr(key), uintptr(algorithm), uintptr(plaintext), uintptr(unsafe.Pointer(error))) +func SecKeyCreateEncryptedData(key SecKeyRef, algorithm SecKeyAlgorithm, plaintext CFDataRef, __error *CFErrorRef) CFDataRef { + r0, _, _ := syscallN(_mkcgo_SecKeyCreateEncryptedData_trampoline_addr, uintptr(key), uintptr(algorithm), uintptr(plaintext), uintptr(unsafe.Pointer(__error))) + runtime.KeepAlive(key) + runtime.KeepAlive(plaintext) + runtime.KeepAlive(__error) return CFDataRef(r0) } var _mkcgo_SecKeyCreateRandomKey_trampoline_addr uintptr -func SecKeyCreateRandomKey(parameters CFDictionaryRef, error *CFErrorRef) SecKeyRef { - r0, _, _ := syscallN(_mkcgo_SecKeyCreateRandomKey_trampoline_addr, uintptr(parameters), uintptr(unsafe.Pointer(error))) +func SecKeyCreateRandomKey(parameters CFDictionaryRef, __error *CFErrorRef) SecKeyRef { + r0, _, _ := syscallN(_mkcgo_SecKeyCreateRandomKey_trampoline_addr, uintptr(parameters), uintptr(unsafe.Pointer(__error))) + runtime.KeepAlive(parameters) + runtime.KeepAlive(__error) return SecKeyRef(r0) } var _mkcgo_SecKeyCreateSignature_trampoline_addr uintptr -func SecKeyCreateSignature(key SecKeyRef, algorithm SecKeyAlgorithm, data CFDataRef, error *CFErrorRef) CFDataRef { - r0, _, _ := syscallN(_mkcgo_SecKeyCreateSignature_trampoline_addr, uintptr(key), uintptr(algorithm), uintptr(data), uintptr(unsafe.Pointer(error))) +func SecKeyCreateSignature(key SecKeyRef, algorithm SecKeyAlgorithm, data CFDataRef, __error *CFErrorRef) CFDataRef { + r0, _, _ := syscallN(_mkcgo_SecKeyCreateSignature_trampoline_addr, uintptr(key), uintptr(algorithm), uintptr(data), uintptr(unsafe.Pointer(__error))) + runtime.KeepAlive(key) + runtime.KeepAlive(data) + runtime.KeepAlive(__error) return CFDataRef(r0) } var _mkcgo_SecKeyCreateWithData_trampoline_addr uintptr -func SecKeyCreateWithData(keyData CFDataRef, attributes CFDictionaryRef, error *CFErrorRef) SecKeyRef { - r0, _, _ := syscallN(_mkcgo_SecKeyCreateWithData_trampoline_addr, uintptr(keyData), uintptr(attributes), uintptr(unsafe.Pointer(error))) +func SecKeyCreateWithData(keyData CFDataRef, attributes CFDictionaryRef, __error *CFErrorRef) SecKeyRef { + r0, _, _ := syscallN(_mkcgo_SecKeyCreateWithData_trampoline_addr, uintptr(keyData), uintptr(attributes), uintptr(unsafe.Pointer(__error))) + runtime.KeepAlive(keyData) + runtime.KeepAlive(attributes) + runtime.KeepAlive(__error) return SecKeyRef(r0) } @@ -485,6 +508,7 @@ var _mkcgo_SecKeyGetBlockSize_trampoline_addr uintptr func SecKeyGetBlockSize(key SecKeyRef) int { r0, _, _ := syscallN(_mkcgo_SecKeyGetBlockSize_trampoline_addr, uintptr(key)) + runtime.KeepAlive(key) return int(r0) } @@ -492,13 +516,18 @@ var _mkcgo_SecKeyIsAlgorithmSupported_trampoline_addr uintptr func SecKeyIsAlgorithmSupported(key SecKeyRef, operation SecKeyOperationType, algorithm SecKeyAlgorithm) Boolean { r0, _, _ := syscallN(_mkcgo_SecKeyIsAlgorithmSupported_trampoline_addr, uintptr(key), uintptr(operation), uintptr(algorithm)) + runtime.KeepAlive(key) return Boolean(r0) } var _mkcgo_SecKeyVerifySignature_trampoline_addr uintptr -func SecKeyVerifySignature(key SecKeyRef, algorithm SecKeyAlgorithm, signedData CFDataRef, signature CFDataRef, error *CFErrorRef) Boolean { - r0, _, _ := syscallN(_mkcgo_SecKeyVerifySignature_trampoline_addr, uintptr(key), uintptr(algorithm), uintptr(signedData), uintptr(signature), uintptr(unsafe.Pointer(error))) +func SecKeyVerifySignature(key SecKeyRef, algorithm SecKeyAlgorithm, signedData CFDataRef, signature CFDataRef, __error *CFErrorRef) Boolean { + r0, _, _ := syscallN(_mkcgo_SecKeyVerifySignature_trampoline_addr, uintptr(key), uintptr(algorithm), uintptr(signedData), uintptr(signature), uintptr(unsafe.Pointer(__error))) + runtime.KeepAlive(key) + runtime.KeepAlive(signedData) + runtime.KeepAlive(signature) + runtime.KeepAlive(__error) return Boolean(r0) } @@ -506,5 +535,6 @@ var _mkcgo_SecRandomCopyBytes_trampoline_addr uintptr func SecRandomCopyBytes(rnd SecRandomRef, count int, bytes unsafe.Pointer) int32 { r0, _, _ := syscallN(_mkcgo_SecRandomCopyBytes_trampoline_addr, uintptr(rnd), uintptr(count), uintptr(bytes)) + runtime.KeepAlive(rnd) return int32(r0) }