Introduce macro BORINGSSL_ALWAYS_USE_STATIC_INLINE. This will control use of `static inline` even when compiling as C++. This is related to symbol renaming, as `static inline` functions do not need to be renamed; however it is not recommended to generally use this in C++, as use of `static inline` functions from `inline` functions typically violates the ODR. This should unblock use of symbol-renamed BoringSSL with Swift, as in that configuration all symbols will either be `static inline` or use the `redefine_extname` mechanism. (May also want to consider switching to this for Rust) Bug: 42220000 Change-Id: I63cde49b8e1d20adc1478c53805261086a6a6964 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/89867 Auto-Submit: Rudolf Polzer <rpolzer@google.com> Reviewed-by: Xiangfei Ding <xfding@google.com> Commit-Queue: Rudolf Polzer <rpolzer@google.com>
diff --git a/include/openssl/base.h b/include/openssl/base.h index 36b9051..9954e17 100644 --- a/include/openssl/base.h +++ b/include/openssl/base.h
@@ -200,13 +200,17 @@ // not used much in practice, extern inline is tedious, and there are conflicts // with the old gnu89 model: // https://stackoverflow.com/questions/216510/extern-inline -#if defined(__cplusplus) -#define OPENSSL_INLINE inline -#else +#if !defined(__cplusplus) && !defined(BORINGSSL_ALWAYS_USE_STATIC_INLINE) +#define BORINGSSL_ALWAYS_USE_STATIC_INLINE +#endif + +#if defined(BORINGSSL_ALWAYS_USE_STATIC_INLINE) // Add OPENSSL_UNUSED so that, should an inline function be emitted via macro // (e.g. a |STACK_OF(T)| implementation) in a source file without tripping // clang's -Wunused-function. #define OPENSSL_INLINE static inline OPENSSL_UNUSED +#else +#define OPENSSL_INLINE inline #endif #if defined(__cplusplus)
diff --git a/include/openssl/prefix_symbols.h b/include/openssl/prefix_symbols.h index 9a6b269..95bf738 100644 --- a/include/openssl/prefix_symbols.h +++ b/include/openssl/prefix_symbols.h
@@ -6154,6 +6154,8 @@ #endif // __PRAGMA_REDEFINE_EXTNAME +#if !defined(BORINGSSL_ALWAYS_USE_STATIC_INLINE) + #define CBS_data BORINGSSL_ADD_PREFIX(CBS_data) #define CBS_init BORINGSSL_ADD_PREFIX(CBS_init) #define CBS_len BORINGSSL_ADD_PREFIX(CBS_len) @@ -6912,4 +6914,6 @@ #define sk_void_value BORINGSSL_ADD_PREFIX(sk_void_value) #define sk_void_zero BORINGSSL_ADD_PREFIX(sk_void_zero) +#endif // !BORINGSSL_ALWAYS_USE_STATIC_INLINE + #endif // OPENSSL_HEADER_PREFIX_SYMBOLS_H
diff --git a/util/pregenerate/build.go b/util/pregenerate/build.go index 5aa8935..3203f38 100644 --- a/util/pregenerate/build.go +++ b/util/pregenerate/build.go
@@ -372,25 +372,25 @@ // MakePrefixingIncludes returns the tasks to generate the header files for symbol prefixing. func MakePrefixingIncludes(in map[string]InputTarget, targetsOut map[string]build.Target) []*Task { - var cHeader, bindgenInclude []byte + var syms cSymbolData var err error buildHeadersOnce := func() { var headers []string for _, t := range in { headers = append(headers, t.Hdrs...) } - cHeader, bindgenInclude, err = BuildCRenamingIncludes(headers) + syms, err = CollectCSymbols(headers) } addGeneratedHeader(targetsOut, "include/openssl/prefix_symbols.h") var once sync.Once return []*Task{ NewSimpleTask("prefix_symbols", "include/openssl/prefix_symbols.h", func() ([]byte, error) { once.Do(buildHeadersOnce) - return cHeader, err + return BuildCRenamingInclude(syms), err }), NewSimpleTask("prefix_symbols", "rust/bssl-sys/boringssl_prefix_symbols_bindgen.rs.in", func() ([]byte, error) { once.Do(buildHeadersOnce) - return bindgenInclude, err + return BuildBindgenRenamingInclude(syms), err }), } }
diff --git a/util/pregenerate/idextractor.go b/util/pregenerate/idextractor.go index a4dc42c..18e1df4 100644 --- a/util/pregenerate/idextractor.go +++ b/util/pregenerate/idextractor.go
@@ -52,13 +52,19 @@ return strings.TrimSuffix(strings.ToLower(filepath.Base(clang)), ".exe") == "clang-cl", nil } -// BuildCRenamingHeader calls Clang to extract the AST of the headers, then processes them to extract the symbols. +// cSymbolData is data for generating the C renaming includes. +type cSymbolData struct { + inlineDefinitions map[string]struct{} + externDeclarations map[string]struct{} +} + +// CollectCSymbols calls Clang to extract the AST of the headers, then processes them to extract the symbols. // -// It returns a header for C and a matching one for Rust's bindgen. -func BuildCRenamingIncludes(headers []string) (cHeader []byte, bindgenInclude []byte, err error) { +// It returns data for generating C and Rust includes. +func CollectCSymbols(headers []string) (syms cSymbolData, err error) { cmd := *clangPath if cmd == "" { - return nil, nil, fmt.Errorf("%w: clang has been disabled by flag", TaskSkipped) + return cSymbolData{}, fmt.Errorf("%w: clang has been disabled by flag", TaskSkipped) } defer func() { @@ -69,7 +75,7 @@ isCL, err := isClangCL(cmd) if err != nil { - return nil, nil, err + return cSymbolData{}, err } var args []string @@ -106,23 +112,23 @@ stdout, err := c.StdoutPipe() if err != nil { - return nil, nil, err + return cSymbolData{}, err } defer stdout.Close() err = c.Start() if err != nil { - return nil, nil, err + return cSymbolData{}, err } - var viaRedefineExtname = map[string]struct{}{} + syms.externDeclarations = map[string]struct{}{} for _, sym := range platformDependentRedefineExtnameSymbols { - viaRedefineExtname[sym] = struct{}{} + syms.externDeclarations[sym] = struct{}{} } - var viaMacro = map[string]struct{}{} + syms.inlineDefinitions = map[string]struct{}{} for _, sym := range platformDependentMacroSymbols { - viaMacro[sym] = struct{}{} + syms.inlineDefinitions[sym] = struct{}{} } report := func(id idextractor.IdentifierInfo) error { @@ -136,7 +142,7 @@ // Already in a namespace. return nil } - canRedefineExtname := true + var isInline bool switch id.Linkage { case "", "static", "static inline": // Definitely not linked. @@ -144,9 +150,10 @@ case `extern "C" inline`, `extern "C++" inline`: // Sorry, can't redefine_extname inline functions: // error: #pragma redefine_extname is applicable to external C declarations only; not applied to function - canRedefineExtname = false + isInline = true case `extern "C"`: // Link those. + isInline = false default: return fmt.Errorf("unexpected linkage: %q", id.Linkage) } @@ -159,10 +166,10 @@ // however cannot be namespaced as known callers forward declare them. return nil case "function", "var": - if canRedefineExtname { - viaRedefineExtname[id.Symbol] = struct{}{} + if isInline { + syms.inlineDefinitions[id.Symbol] = struct{}{} } else { - viaMacro[id.Symbol] = struct{}{} + syms.externDeclarations[id.Symbol] = struct{}{} } return nil default: @@ -170,26 +177,30 @@ } } - for sym := range viaMacro { - if _, found := viaRedefineExtname[sym]; found { - return nil, nil, fmt.Errorf("symbol %q both marked for macro and redefine_extname renaming; please fix", sym) + for sym := range syms.inlineDefinitions { + if _, found := syms.externDeclarations[sym]; found { + return cSymbolData{}, fmt.Errorf("symbol %q both marked as extern and inline type symbol renaming; please fix", sym) } } err = idextractor.New(report, idextractor.Options{Language: "C++"}).Parse(stdout) if err != nil { c.Process.Kill() - return nil, nil, err + return cSymbolData{}, err } err = c.Wait() if err != nil { - return nil, nil, err + return cSymbolData{}, err } - var cOutput bytes.Buffer - writeHeader(&cOutput, "//") - cOutput.WriteString(` + return syms, nil +} + +func BuildCRenamingInclude(syms cSymbolData) []byte { + var output bytes.Buffer + writeHeader(&output, "//") + output.WriteString(` #ifndef OPENSSL_HEADER_PREFIX_SYMBOLS_H #define OPENSSL_HEADER_PREFIX_SYMBOLS_H @@ -207,33 +218,40 @@ #endif // __APPLE__ `) - cOutput.WriteString("#if defined(__PRAGMA_REDEFINE_EXTNAME)\n") - cOutput.WriteString("\n") - for _, sym := range slices.Sorted(maps.Keys(viaRedefineExtname)) { - fmt.Fprintf(&cOutput, "#pragma redefine_extname %s BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(%s))\n", sym, sym) + output.WriteString("#if defined(__PRAGMA_REDEFINE_EXTNAME)\n") + output.WriteString("\n") + for _, sym := range slices.Sorted(maps.Keys(syms.externDeclarations)) { + fmt.Fprintf(&output, "#pragma redefine_extname %s BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(%s))\n", sym, sym) } - cOutput.WriteString("\n") - cOutput.WriteString("#else // __PRAGMA_REDEFINE_EXTNAME\n") - cOutput.WriteString("\n") - for _, sym := range slices.Sorted(maps.Keys(viaRedefineExtname)) { - fmt.Fprintf(&cOutput, "#define %s BORINGSSL_ADD_PREFIX(%s)\n", sym, sym) + output.WriteString("\n") + output.WriteString("#else // __PRAGMA_REDEFINE_EXTNAME\n") + output.WriteString("\n") + for _, sym := range slices.Sorted(maps.Keys(syms.externDeclarations)) { + fmt.Fprintf(&output, "#define %s BORINGSSL_ADD_PREFIX(%s)\n", sym, sym) } - cOutput.WriteString("\n") - cOutput.WriteString("#endif // __PRAGMA_REDEFINE_EXTNAME\n") - cOutput.WriteString("\n") - for _, sym := range slices.Sorted(maps.Keys(viaMacro)) { - fmt.Fprintf(&cOutput, "#define %s BORINGSSL_ADD_PREFIX(%s)\n", sym, sym) + output.WriteString("\n") + output.WriteString("#endif // __PRAGMA_REDEFINE_EXTNAME\n") + output.WriteString("\n") + output.WriteString("#if !defined(BORINGSSL_ALWAYS_USE_STATIC_INLINE)\n") + output.WriteString("\n") + for _, sym := range slices.Sorted(maps.Keys(syms.inlineDefinitions)) { + fmt.Fprintf(&output, "#define %s BORINGSSL_ADD_PREFIX(%s)\n", sym, sym) } - cOutput.WriteString(` + output.WriteString("\n") + output.WriteString("#endif // !BORINGSSL_ALWAYS_USE_STATIC_INLINE\n") + output.WriteString(` #endif // OPENSSL_HEADER_PREFIX_SYMBOLS_H `) + return output.Bytes() +} - var bindgenOutput bytes.Buffer - writeHeader(&bindgenOutput, "//") - bindgenOutput.WriteString("\n") - for _, sym := range slices.Sorted(maps.Keys(viaMacro)) { - fmt.Fprintf(&bindgenOutput, "pub use ${BORINGSSL_PREFIX}_%s as %s;\n", sym, sym) +func BuildBindgenRenamingInclude(syms cSymbolData) []byte { + var output bytes.Buffer + writeHeader(&output, "//") + output.WriteString("\n") + for _, sym := range slices.Sorted(maps.Keys(syms.inlineDefinitions)) { + fmt.Fprintf(&output, "pub use ${BORINGSSL_PREFIX}_%s as %s;\n", sym, sym) } - return cOutput.Bytes(), bindgenOutput.Bytes(), nil + return output.Bytes() }