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

     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++ -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.)
   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