boringssl/util/make_prefix_headers.go
David Benjamin 8c23d3a5df Make Windows symbol-prefixing work.
This teaches read_symbols.go to use debug/pe, and fixes miscellaneous
issues with NASM. It also reveals a problem with this strategy of
getting symbols out at the linker level: inline functions.  I'm thinking
a better long-term mechanism may be to parse our header files.

Change-Id: I11b008543a7a97db3db9d4062ee4ddb910d174b7
Reviewed-on: https://boringssl-review.googlesource.com/c/33349
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
2018-11-27 22:13:22 +00:00

233 lines
7.8 KiB
Go

// Copyright (c) 2018, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// This program takes a file containing newline-separated symbols, and generates
// boringssl_prefix_symbols.h, boringssl_prefix_symbols_asm.h, and
// boringssl_prefix_symbols_nasm.inc. These header files can be used to build
// BoringSSL with a prefix for all symbols in order to avoid symbol name
// conflicts when linking a project with multiple copies of BoringSSL; see
// BUILDING.md for more details.
// TODO(joshlf): For platforms which support it, use '#pragma redefine_extname'
// instead of a custom macro. This avoids the need for a custom macro, but also
// ensures that our renaming won't conflict with symbols defined and used by our
// consumers (the "HMAC" problem). An example of this approach can be seen in
// IllumOS' fork of OpenSSL:
// https://github.com/joyent/illumos-extra/blob/master/openssl1x/sunw_prefix.h
package main
import (
"bufio"
"flag"
"fmt"
"os"
"path/filepath"
"strings"
)
var out = flag.String("out", ".", "Path to a directory where the outputs will be written")
// Read newline-separated symbols from a file, ignoring any comments started
// with '#'.
func readSymbols(path string) ([]string, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
scanner := bufio.NewScanner(f)
var ret []string
for scanner.Scan() {
line := scanner.Text()
if idx := strings.IndexByte(line, '#'); idx >= 0 {
line = line[:idx]
}
line = strings.TrimSpace(line)
if len(line) == 0 {
continue
}
ret = append(ret, line)
}
if err := scanner.Err(); err != nil {
return nil, err
}
return ret, nil
}
func writeCHeader(symbols []string, path string) error {
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
if _, err := f.WriteString(`// Copyright (c) 2018, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// BORINGSSL_ADD_PREFIX pastes two identifiers into one. It performs one
// iteration of macro expansion on its arguments before pasting.
#define BORINGSSL_ADD_PREFIX(a, b) BORINGSSL_ADD_PREFIX_INNER(a, b)
#define BORINGSSL_ADD_PREFIX_INNER(a, b) a ## _ ## b
`); err != nil {
return err
}
for _, symbol := range symbols {
if _, err := fmt.Fprintf(f, "#define %s BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, %s)\n", symbol, symbol); err != nil {
return err
}
}
return nil
}
func writeASMHeader(symbols []string, path string) error {
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
if _, err := f.WriteString(`// Copyright (c) 2018, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#if !defined(__APPLE__)
#include <boringssl_prefix_symbols.h>
#else
// On iOS and macOS, we need to treat assembly symbols differently from other
// symbols. The linker expects symbols to be prefixed with an underscore.
// Perlasm thus generates symbol with this underscore applied. Our macros must,
// in turn, incorporate it.
#define BORINGSSL_ADD_PREFIX_MAC_ASM(a, b) BORINGSSL_ADD_PREFIX_INNER_MAC_ASM(a, b)
#define BORINGSSL_ADD_PREFIX_INNER_MAC_ASM(a, b) _ ## a ## _ ## b
`); err != nil {
return err
}
for _, symbol := range symbols {
if _, err := fmt.Fprintf(f, "#define _%s BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, %s)\n", symbol, symbol); err != nil {
return err
}
}
_, err = fmt.Fprintf(f, "#endif\n")
return nil
}
func writeNASMHeader(symbols []string, path string) error {
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
// NASM uses a different syntax from the C preprocessor.
if _, err := f.WriteString(`; Copyright (c) 2018, Google Inc.
;
; Permission to use, copy, modify, and/or distribute this software for any
; purpose with or without fee is hereby granted, provided that the above
; copyright notice and this permission notice appear in all copies.
;
; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
; SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
; OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
; CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
; 32-bit Windows adds underscores to C functions, while 64-bit Windows does not.
%ifidn __OUTPUT_FORMAT__, win32
`); err != nil {
return err
}
for _, symbol := range symbols {
if _, err := fmt.Fprintf(f, "%%xdefine _%s _ %%+ BORINGSSL_PREFIX %%+ _%s\n", symbol, symbol); err != nil {
return err
}
}
if _, err := fmt.Fprintf(f, "%%else\n"); err != nil {
return err
}
for _, symbol := range symbols {
if _, err := fmt.Fprintf(f, "%%xdefine %s BORINGSSL_PREFIX %%+ _%s\n", symbol, symbol); err != nil {
return err
}
}
if _, err := fmt.Fprintf(f, "%%endif\n"); err != nil {
return err
}
return nil
}
func main() {
flag.Parse()
if flag.NArg() != 1 {
fmt.Fprintf(os.Stderr, "Usage: %s [-out OUT] SYMBOLS\n", os.Args[0])
os.Exit(1)
}
symbols, err := readSymbols(flag.Arg(0))
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading symbols: %s\n", err)
os.Exit(1)
}
if err := writeCHeader(symbols, filepath.Join(*out, "boringssl_prefix_symbols.h")); err != nil {
fmt.Fprintf(os.Stderr, "Error writing boringssl_prefix_symbols.h: %s\n", err)
os.Exit(1)
}
if err := writeASMHeader(symbols, filepath.Join(*out, "boringssl_prefix_symbols_asm.h")); err != nil {
fmt.Fprintf(os.Stderr, "Error writing boringssl_prefix_symbols_asm.h: %s\n", err)
os.Exit(1)
}
if err := writeNASMHeader(symbols, filepath.Join(*out, "boringssl_prefix_symbols_nasm.inc")); err != nil {
fmt.Fprintf(os.Stderr, "Error writing boringssl_prefix_symbols_nasm.inc: %s\n", err)
os.Exit(1)
}
}