1// Copyright (c) 2018, Google Inc. 2// 3// Permission to use, copy, modify, and/or distribute this software for any 4// purpose with or without fee is hereby granted, provided that the above 5// copyright notice and this permission notice appear in all copies. 6// 7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 15// This program takes a file containing newline-separated symbols, and generates 16// boringssl_prefix_symbols.h, boringssl_prefix_symbols_asm.h, and 17// boringssl_prefix_symbols_nasm.inc. These header files can be used to build 18// BoringSSL with a prefix for all symbols in order to avoid symbol name 19// conflicts when linking a project with multiple copies of BoringSSL; see 20// BUILDING.md for more details. 21 22// TODO(joshlf): For platforms which support it, use '#pragma redefine_extname' 23// instead of a custom macro. This avoids the need for a custom macro, but also 24// ensures that our renaming won't conflict with symbols defined and used by our 25// consumers (the "HMAC" problem). An example of this approach can be seen in 26// IllumOS' fork of OpenSSL: 27// https://github.com/joyent/illumos-extra/blob/master/openssl1x/sunw_prefix.h 28 29package main 30 31import ( 32 "bufio" 33 "flag" 34 "fmt" 35 "os" 36 "path/filepath" 37 "strings" 38) 39 40var out = flag.String("out", ".", "Path to a directory where the outputs will be written") 41 42// Read newline-separated symbols from a file, ignoring any comments started 43// with '#'. 44func readSymbols(path string) ([]string, error) { 45 f, err := os.Open(path) 46 if err != nil { 47 return nil, err 48 } 49 defer f.Close() 50 scanner := bufio.NewScanner(f) 51 var ret []string 52 for scanner.Scan() { 53 line := scanner.Text() 54 if idx := strings.IndexByte(line, '#'); idx >= 0 { 55 line = line[:idx] 56 } 57 line = strings.TrimSpace(line) 58 if len(line) == 0 { 59 continue 60 } 61 ret = append(ret, line) 62 } 63 if err := scanner.Err(); err != nil { 64 return nil, err 65 } 66 return ret, nil 67} 68 69func writeCHeader(symbols []string, path string) error { 70 f, err := os.Create(path) 71 if err != nil { 72 return err 73 } 74 defer f.Close() 75 76 if _, err := f.WriteString(`// Copyright (c) 2018, Google Inc. 77// 78// Permission to use, copy, modify, and/or distribute this software for any 79// purpose with or without fee is hereby granted, provided that the above 80// copyright notice and this permission notice appear in all copies. 81// 82// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 83// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 84// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 85// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 86// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 87// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 88// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 89 90// BORINGSSL_ADD_PREFIX pastes two identifiers into one. It performs one 91// iteration of macro expansion on its arguments before pasting. 92#define BORINGSSL_ADD_PREFIX(a, b) BORINGSSL_ADD_PREFIX_INNER(a, b) 93#define BORINGSSL_ADD_PREFIX_INNER(a, b) a ## _ ## b 94 95`); err != nil { 96 return err 97 } 98 99 for _, symbol := range symbols { 100 if _, err := fmt.Fprintf(f, "#define %s BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, %s)\n", symbol, symbol); err != nil { 101 return err 102 } 103 } 104 105 return nil 106} 107 108func writeASMHeader(symbols []string, path string) error { 109 f, err := os.Create(path) 110 if err != nil { 111 return err 112 } 113 defer f.Close() 114 115 if _, err := f.WriteString(`// Copyright (c) 2018, Google Inc. 116// 117// Permission to use, copy, modify, and/or distribute this software for any 118// purpose with or without fee is hereby granted, provided that the above 119// copyright notice and this permission notice appear in all copies. 120// 121// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 122// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 123// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 124// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 125// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 126// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 127// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 128 129#if !defined(__APPLE__) 130#include <boringssl_prefix_symbols.h> 131#else 132// On iOS and macOS, we need to treat assembly symbols differently from other 133// symbols. The linker expects symbols to be prefixed with an underscore. 134// Perlasm thus generates symbol with this underscore applied. Our macros must, 135// in turn, incorporate it. 136#define BORINGSSL_ADD_PREFIX_MAC_ASM(a, b) BORINGSSL_ADD_PREFIX_INNER_MAC_ASM(a, b) 137#define BORINGSSL_ADD_PREFIX_INNER_MAC_ASM(a, b) _ ## a ## _ ## b 138 139`); err != nil { 140 return err 141 } 142 143 for _, symbol := range symbols { 144 if _, err := fmt.Fprintf(f, "#define _%s BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, %s)\n", symbol, symbol); err != nil { 145 return err 146 } 147 } 148 149 _, err = fmt.Fprintf(f, "#endif\n") 150 return nil 151} 152 153func writeNASMHeader(symbols []string, path string) error { 154 f, err := os.Create(path) 155 if err != nil { 156 return err 157 } 158 defer f.Close() 159 160 // NASM uses a different syntax from the C preprocessor. 161 if _, err := f.WriteString(`; Copyright (c) 2018, Google Inc. 162; 163; Permission to use, copy, modify, and/or distribute this software for any 164; purpose with or without fee is hereby granted, provided that the above 165; copyright notice and this permission notice appear in all copies. 166; 167; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 168; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 169; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 170; SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 171; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 172; OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 173; CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 174 175; 32-bit Windows adds underscores to C functions, while 64-bit Windows does not. 176%ifidn __OUTPUT_FORMAT__, win32 177`); err != nil { 178 return err 179 } 180 181 for _, symbol := range symbols { 182 if _, err := fmt.Fprintf(f, "%%xdefine _%s _ %%+ BORINGSSL_PREFIX %%+ _%s\n", symbol, symbol); err != nil { 183 return err 184 } 185 } 186 187 if _, err := fmt.Fprintf(f, "%%else\n"); err != nil { 188 return err 189 } 190 191 for _, symbol := range symbols { 192 if _, err := fmt.Fprintf(f, "%%xdefine %s BORINGSSL_PREFIX %%+ _%s\n", symbol, symbol); err != nil { 193 return err 194 } 195 } 196 197 if _, err := fmt.Fprintf(f, "%%endif\n"); err != nil { 198 return err 199 } 200 201 return nil 202} 203 204func main() { 205 flag.Parse() 206 if flag.NArg() != 1 { 207 fmt.Fprintf(os.Stderr, "Usage: %s [-out OUT] SYMBOLS\n", os.Args[0]) 208 os.Exit(1) 209 } 210 211 symbols, err := readSymbols(flag.Arg(0)) 212 if err != nil { 213 fmt.Fprintf(os.Stderr, "Error reading symbols: %s\n", err) 214 os.Exit(1) 215 } 216 217 if err := writeCHeader(symbols, filepath.Join(*out, "boringssl_prefix_symbols.h")); err != nil { 218 fmt.Fprintf(os.Stderr, "Error writing boringssl_prefix_symbols.h: %s\n", err) 219 os.Exit(1) 220 } 221 222 if err := writeASMHeader(symbols, filepath.Join(*out, "boringssl_prefix_symbols_asm.h")); err != nil { 223 fmt.Fprintf(os.Stderr, "Error writing boringssl_prefix_symbols_asm.h: %s\n", err) 224 os.Exit(1) 225 } 226 227 if err := writeNASMHeader(symbols, filepath.Join(*out, "boringssl_prefix_symbols_nasm.inc")); err != nil { 228 fmt.Fprintf(os.Stderr, "Error writing boringssl_prefix_symbols_nasm.inc: %s\n", err) 229 os.Exit(1) 230 } 231 232} 233