| #!/bin/bash |
| # Copyright 2020 The Go Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style |
| # license that can be found in the LICENSE file. |
| |
| # Do not run directly; run build.sh, which runs this in Docker. |
| # This script builds goboringcrypto's syso, after boringssl has been built. |
| |
| export TERM=dumb |
| |
| set -e |
| set -x |
| id |
| date |
| export LANG=C |
| unset LANGUAGE |
| |
| case $(uname -m) in |
| x86_64) export GOARCH=amd64 ;; |
| aarch64) export GOARCH=arm64 ;; |
| *) |
| echo 'unknown uname -m:' $(uname -m) >&2 |
| exit 2 |
| esac |
| |
| export CGO_ENABLED=0 |
| |
| # Build and run test C++ program to make sure goboringcrypto.h matches openssl/*.h. |
| # Also collect list of checked symbols in syms.txt |
| set -e |
| cd /boring/godriver |
| cat >goboringcrypto.cc <<'EOF' |
| #include <cassert> |
| #include "goboringcrypto0.h" |
| #include "goboringcrypto1.h" |
| #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;} |
| #define check_func(f) { auto x = f; x = _goboringcrypto_ ## f ; } |
| #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;} |
| int main() { |
| int ret = 0; |
| #include "goboringcrypto.x" |
| return ret; |
| } |
| EOF |
| |
| cat >boringx.awk <<'EOF' |
| BEGIN { |
| exitcode = 0 |
| } |
| |
| # Ignore comments, #includes, blank lines. |
| /^\/\// || /^#/ || NF == 0 { next } |
| |
| # Ignore unchecked declarations. |
| /\/\*unchecked/ { next } |
| |
| # Check enum values. |
| !enum && ($1 == "enum" || $2 == "enum") && $NF == "{" { |
| enum = 1 |
| next |
| } |
| enum && $1 == "};" { |
| enum = 0 |
| next |
| } |
| enum && /^}.*;$/ { |
| enum = 0 |
| next |
| } |
| enum && NF == 3 && $2 == "=" { |
| name = $1 |
| sub(/^GO_/, "", name) |
| val = $3 |
| sub(/,$/, "", val) |
| print "check_value(" name ", " val ")" > "goboringcrypto.x" |
| next |
| } |
| enum { |
| print FILENAME ":" NR ": unexpected line in enum: " $0 > "/dev/stderr" |
| exitcode = 1 |
| next |
| } |
| |
| # Check struct sizes. |
| /^typedef struct / && $NF ~ /^GO_/ { |
| name = $NF |
| sub(/^GO_/, "", name) |
| sub(/;$/, "", name) |
| print "check_size(" name ")" > "goboringcrypto.x" |
| next |
| } |
| |
| # Check function prototypes. |
| /^(const )?[^ ]+ \**_goboringcrypto_.*\(/ { |
| name = $2 |
| if($1 == "const") |
| name = $3 |
| sub(/^\**_goboringcrypto_/, "", name) |
| sub(/\(.*/, "", name) |
| print "check_func(" name ")" > "goboringcrypto.x" |
| print name > "syms.txt" |
| next |
| } |
| |
| { |
| print FILENAME ":" NR ": unexpected line: " $0 > "/dev/stderr" |
| exitcode = 1 |
| } |
| |
| END { |
| exit exitcode |
| } |
| EOF |
| |
| cat >boringh.awk <<'EOF' |
| /^\/\/ #include/ {sub(/\/\//, ""); print > "goboringcrypto0.h"; next} |
| /typedef struct|enum ([a-z_]+ )?{|^[ \t]/ {print >"goboringcrypto1.h";next} |
| {gsub(/GO_/, ""); gsub(/enum go_/, "enum "); gsub(/go_point_conv/, "point_conv"); print >"goboringcrypto1.h"} |
| EOF |
| |
| awk -f boringx.awk goboringcrypto.h # writes goboringcrypto.x |
| awk -f boringh.awk goboringcrypto.h # writes goboringcrypto[01].h |
| |
| ls -l ../boringssl/include |
| clang++ -std=c++11 -fPIC -I../boringssl/include -O2 -o a.out goboringcrypto.cc |
| ./a.out || exit 2 |
| |
| # clang implements u128 % u128 -> u128 by calling __umodti3, |
| # which is in libgcc. To make the result self-contained even if linking |
| # against a different compiler version, link our own __umodti3 into the syso. |
| # This one is specialized so it only expects divisors below 2^64, |
| # which is all BoringCrypto uses. (Otherwise it will seg fault.) |
| cat >umod-amd64.s <<'EOF' |
| # tu_int __umodti3(tu_int x, tu_int y) |
| # x is rsi:rdi, y is rcx:rdx, return result is rdx:rax. |
| .globl __umodti3 |
| __umodti3: |
| # specialized to u128 % u64, so verify that |
| test %rcx,%rcx |
| jne 1f |
| |
| # save divisor |
| movq %rdx, %r8 |
| |
| # reduce top 64 bits mod divisor |
| movq %rsi, %rax |
| xorl %edx, %edx |
| divq %r8 |
| |
| # reduce full 128-bit mod divisor |
| # quotient fits in 64 bits because top 64 bits have been reduced < divisor. |
| # (even though we only care about the remainder, divq also computes |
| # the quotient, and it will trap if the quotient is too large.) |
| movq %rdi, %rax |
| divq %r8 |
| |
| # expand remainder to 128 for return |
| movq %rdx, %rax |
| xorl %edx, %edx |
| ret |
| |
| 1: |
| # crash - only want 64-bit divisor |
| xorl %ecx, %ecx |
| movl %ecx, 0(%ecx) |
| jmp 1b |
| |
| .section .note.GNU-stack,"",@progbits |
| EOF |
| |
| cat >umod-arm64.c <<'EOF' |
| typedef unsigned int u128 __attribute__((mode(TI))); |
| |
| static u128 div(u128 x, u128 y, u128 *rp) { |
| int n = 0; |
| while((y>>(128-1)) != 1 && y < x) { |
| y<<=1; |
| n++; |
| } |
| u128 q = 0; |
| for(;; n--, y>>=1, q<<=1) { |
| if(x>=y) { |
| x -= y; |
| q |= 1; |
| } |
| if(n == 0) |
| break; |
| } |
| if(rp) |
| *rp = x; |
| return q; |
| } |
| |
| u128 __umodti3(u128 x, u128 y) { |
| u128 r; |
| div(x, y, &r); |
| return r; |
| } |
| |
| u128 __udivti3(u128 x, u128 y) { |
| return div(x, y, 0); |
| } |
| EOF |
| |
| extra="" |
| case $GOARCH in |
| amd64) |
| cp umod-amd64.s umod.s |
| clang -c -o umod.o umod.s |
| extra=umod.o |
| ;; |
| arm64) |
| cp umod-arm64.c umod.c |
| clang -c -o umod.o umod.c |
| extra=umod.o |
| ;; |
| esac |
| |
| # Prepare copy of libcrypto.a with only the checked functions renamed and exported. |
| # All other symbols are left alone and hidden. |
| echo BORINGSSL_bcm_power_on_self_test >>syms.txt |
| awk '{print "_goboringcrypto_" $0 }' syms.txt >globals.txt |
| awk '{print $0 " _goboringcrypto_" $0 }' syms.txt >renames.txt |
| objcopy --globalize-symbol=BORINGSSL_bcm_power_on_self_test \ |
| ../boringssl/build/crypto/libcrypto.a libcrypto.a |
| |
| # Link together bcm.o and libcrypto.a into a single object. |
| ld -r -nostdlib --whole-archive -o goboringcrypto.o libcrypto.a $extra |
| |
| echo __umodti3 _goboringcrypto___umodti3 >>renames.txt |
| echo __udivti3 _goboringcrypto___udivti3 >>renames.txt |
| objcopy --remove-section=.llvm_addrsig goboringcrypto.o goboringcrypto1.o # b/179161016 |
| objcopy --redefine-syms=renames.txt goboringcrypto1.o goboringcrypto2.o |
| objcopy --keep-global-symbols=globals.txt --strip-unneeded goboringcrypto2.o goboringcrypto_linux_$GOARCH.syso |
| |
| # Done! |
| ls -l goboringcrypto_linux_$GOARCH.syso |