1 #!/bin/bash
2 # Copyright 2020 The Go Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style
4 # license that can be found in the LICENSE file.
5
6 # Do not run directly; run build.sh, which runs this in Docker.
7 # This script builds goboringcrypto's syso, after boringssl has been built.
8
9 export TERM=dumb
10
11 set -e
12 set -x
13 id
14 date
15 export LANG=C
16 unset LANGUAGE
17
18 case $(uname -m) in
19 x86_64) export GOARCH=amd64 ;;
20 aarch64) export GOARCH=arm64 ;;
21 *)
22 echo 'unknown uname -m:' $(uname -m) >&2
23 exit 2
24 esac
25
26 export CGO_ENABLED=0
27
28 # Build and run test C++ program to make sure goboringcrypto.h matches openssl/*.h.
29 # Also collect list of checked symbols in syms.txt
30 set -e
31 cd /boring/godriver
32 cat >goboringcrypto.cc <<'EOF'
33 #include <cassert>
34 #include "goboringcrypto0.h"
35 #include "goboringcrypto1.h"
36 #define check_size(t) if(sizeof(t) != sizeof(GO_ ## t)) {printf("sizeof(" #t ")=%d, but sizeof(GO_" #t ")=%d\n", (int)sizeof(t), (int)sizeof(GO_ ## t)); ret=1;}
37 #define check_func(f) { auto x = f; x = _goboringcrypto_ ## f ; }
38 #define check_value(n, v) if(n != v) {printf(#n "=%d, but goboringcrypto.h defines it as %d\n", (int)n, (int)v); ret=1;}
39 int main() {
40 int ret = 0;
41 #include "goboringcrypto.x"
42 return ret;
43 }
44 EOF
45
46 cat >boringx.awk <<'EOF'
47 BEGIN {
48 exitcode = 0
49 }
50
51 # Ignore comments, #includes, blank lines.
52 /^\/\// || /^#/ || NF == 0 { next }
53
54 # Ignore unchecked declarations.
55 /\/\*unchecked/ { next }
56
57 # Check enum values.
58 !enum && ($1 == "enum" || $2 == "enum") && $NF == "{" {
59 enum = 1
60 next
61 }
62 enum && $1 == "};" {
63 enum = 0
64 next
65 }
66 enum && /^}.*;$/ {
67 enum = 0
68 next
69 }
70 enum && NF == 3 && $2 == "=" {
71 name = $1
72 sub(/^GO_/, "", name)
73 val = $3
74 sub(/,$/, "", val)
75 print "check_value(" name ", " val ")" > "goboringcrypto.x"
76 next
77 }
78 enum {
79 print FILENAME ":" NR ": unexpected line in enum: " $0 > "/dev/stderr"
80 exitcode = 1
81 next
82 }
83
84 # Check struct sizes.
85 /^typedef struct / && $NF ~ /^GO_/ {
86 name = $NF
87 sub(/^GO_/, "", name)
88 sub(/;$/, "", name)
89 print "check_size(" name ")" > "goboringcrypto.x"
90 next
91 }
92
93 # Check function prototypes.
94 /^(const )?[^ ]+ \**_goboringcrypto_.*\(/ {
95 name = $2
96 if($1 == "const")
97 name = $3
98 sub(/^\**_goboringcrypto_/, "", name)
99 sub(/\(.*/, "", name)
100 print "check_func(" name ")" > "goboringcrypto.x"
101 print name > "syms.txt"
102 next
103 }
104
105 {
106 print FILENAME ":" NR ": unexpected line: " $0 > "/dev/stderr"
107 exitcode = 1
108 }
109
110 END {
111 exit exitcode
112 }
113 EOF
114
115 cat >boringh.awk <<'EOF'
116 /^\/\/ #include/ {sub(/\/\//, ""); print > "goboringcrypto0.h"; next}
117 /typedef struct|enum ([a-z_]+ )?{|^[ \t]/ {print >"goboringcrypto1.h";next}
118 {gsub(/GO_/, ""); gsub(/enum go_/, "enum "); gsub(/go_point_conv/, "point_conv"); print >"goboringcrypto1.h"}
119 EOF
120
121 awk -f boringx.awk goboringcrypto.h # writes goboringcrypto.x
122 awk -f boringh.awk goboringcrypto.h # writes goboringcrypto[01].h
123
124 ls -l ../boringssl/include
125 clang++ -fPIC -I../boringssl/include -O2 -o a.out goboringcrypto.cc
126 ./a.out || exit 2
127
128 # clang implements u128 % u128 -> u128 by calling __umodti3,
129 # which is in libgcc. To make the result self-contained even if linking
130 # against a different compiler version, link our own __umodti3 into the syso.
131 # This one is specialized so it only expects divisors below 2^64,
132 # which is all BoringCrypto uses. (Otherwise it will seg fault.)
133 cat >umod-amd64.s <<'EOF'
134 # tu_int __umodti3(tu_int x, tu_int y)
135 # x is rsi:rdi, y is rcx:rdx, return result is rdx:rax.
136 .globl __umodti3
137 __umodti3:
138 # specialized to u128 % u64, so verify that
139 test %rcx,%rcx
140 jne 1f
141
142 # save divisor
143 movq %rdx, %r8
144
145 # reduce top 64 bits mod divisor
146 movq %rsi, %rax
147 xorl %edx, %edx
148 divq %r8
149
150 # reduce full 128-bit mod divisor
151 # quotient fits in 64 bits because top 64 bits have been reduced < divisor.
152 # (even though we only care about the remainder, divq also computes
153 # the quotient, and it will trap if the quotient is too large.)
154 movq %rdi, %rax
155 divq %r8
156
157 # expand remainder to 128 for return
158 movq %rdx, %rax
159 xorl %edx, %edx
160 ret
161
162 1:
163 # crash - only want 64-bit divisor
164 xorl %ecx, %ecx
165 movl %ecx, 0(%ecx)
166 jmp 1b
167
168 .section .note.GNU-stack,"",@progbits
169 EOF
170
171 cat >umod-arm64.c <<'EOF'
172 typedef unsigned int u128 __attribute__((mode(TI)));
173
174 static u128 div(u128 x, u128 y, u128 *rp) {
175 int n = 0;
176 while((y>>(128-1)) != 1 && y < x) {
177 y<<=1;
178 n++;
179 }
180 u128 q = 0;
181 for(;; n--, y>>=1, q<<=1) {
182 if(x>=y) {
183 x -= y;
184 q |= 1;
185 }
186 if(n == 0)
187 break;
188 }
189 if(rp)
190 *rp = x;
191 return q;
192 }
193
194 u128 __umodti3(u128 x, u128 y) {
195 u128 r;
196 div(x, y, &r);
197 return r;
198 }
199
200 u128 __udivti3(u128 x, u128 y) {
201 return div(x, y, 0);
202 }
203 EOF
204
205 extra=""
206 case $GOARCH in
207 amd64)
208 cp umod-amd64.s umod.s
209 clang -c -o umod.o umod.s
210 extra=umod.o
211 ;;
212 arm64)
213 cp umod-arm64.c umod.c
214 clang -c -o umod.o umod.c
215 extra=umod.o
216 ;;
217 esac
218
219 # Prepare copy of libcrypto.a with only the checked functions renamed and exported.
220 # All other symbols are left alone and hidden.
221 echo BORINGSSL_bcm_power_on_self_test >>syms.txt
222 awk '{print "_goboringcrypto_" $0 }' syms.txt >globals.txt
223 awk '{print $0 " _goboringcrypto_" $0 }' syms.txt >renames.txt
224 objcopy --globalize-symbol=BORINGSSL_bcm_power_on_self_test \
225 ../boringssl/build/crypto/libcrypto.a libcrypto.a
226
227 # Link together bcm.o and libcrypto.a into a single object.
228 ld -r -nostdlib --whole-archive -o goboringcrypto.o libcrypto.a $extra
229
230 echo __umodti3 _goboringcrypto___umodti3 >>renames.txt
231 echo __udivti3 _goboringcrypto___udivti3 >>renames.txt
232 objcopy --remove-section=.llvm_addrsig goboringcrypto.o goboringcrypto1.o # b/179161016
233 objcopy --redefine-syms=renames.txt goboringcrypto1.o goboringcrypto2.o
234 objcopy --keep-global-symbols=globals.txt --strip-unneeded goboringcrypto2.o goboringcrypto_linux_$GOARCH.syso
235
236 # Done!
237 ls -l goboringcrypto_linux_$GOARCH.syso
238
View as plain text