...

Text file src/crypto/internal/boring/build-goboring.sh

Documentation: crypto/internal/boring

     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

View as plain text