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 9export TERM=dumb 10 11set -e 12set -x 13id 14date 15export LANG=C 16unset LANGUAGE 17 18case $(uname -m) in 19x86_64) export GOARCH=amd64 ;; 20aarch64) export GOARCH=arm64 ;; 21*) 22 echo 'unknown uname -m:' $(uname -m) >&2 23 exit 2 24esac 25 26export 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 30set -e 31cd /boring/godriver 32cat >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;} 39int main() { 40int ret = 0; 41#include "goboringcrypto.x" 42return ret; 43} 44EOF 45 46cat >boringx.awk <<'EOF' 47BEGIN { 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} 62enum && $1 == "};" { 63 enum = 0 64 next 65} 66enum && /^}.*;$/ { 67 enum = 0 68 next 69} 70enum && 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} 78enum { 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 110END { 111 exit exitcode 112} 113EOF 114 115cat >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"} 119EOF 120 121awk -f boringx.awk goboringcrypto.h # writes goboringcrypto.x 122awk -f boringh.awk goboringcrypto.h # writes goboringcrypto[01].h 123 124ls -l ../boringssl/include 125clang++ -std=c++11 -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.) 133cat >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 1621: 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 169EOF 170 171cat >umod-arm64.c <<'EOF' 172typedef unsigned int u128 __attribute__((mode(TI))); 173 174static 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 194u128 __umodti3(u128 x, u128 y) { 195 u128 r; 196 div(x, y, &r); 197 return r; 198} 199 200u128 __udivti3(u128 x, u128 y) { 201 return div(x, y, 0); 202} 203EOF 204 205extra="" 206case $GOARCH in 207amd64) 208 cp umod-amd64.s umod.s 209 clang -c -o umod.o umod.s 210 extra=umod.o 211 ;; 212arm64) 213 cp umod-arm64.c umod.c 214 clang -c -o umod.o umod.c 215 extra=umod.o 216 ;; 217esac 218 219# Prepare copy of libcrypto.a with only the checked functions renamed and exported. 220# All other symbols are left alone and hidden. 221echo BORINGSSL_bcm_power_on_self_test >>syms.txt 222awk '{print "_goboringcrypto_" $0 }' syms.txt >globals.txt 223awk '{print $0 " _goboringcrypto_" $0 }' syms.txt >renames.txt 224objcopy --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. 228ld -r -nostdlib --whole-archive -o goboringcrypto.o libcrypto.a $extra 229 230echo __umodti3 _goboringcrypto___umodti3 >>renames.txt 231echo __udivti3 _goboringcrypto___udivti3 >>renames.txt 232objcopy --remove-section=.llvm_addrsig goboringcrypto.o goboringcrypto1.o # b/179161016 233objcopy --redefine-syms=renames.txt goboringcrypto1.o goboringcrypto2.o 234objcopy --keep-global-symbols=globals.txt --strip-unneeded goboringcrypto2.o goboringcrypto_linux_$GOARCH.syso 235 236# Done! 237ls -l goboringcrypto_linux_$GOARCH.syso 238