• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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