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