github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/crypto/internal/boring/build-goboring.sh (about)

     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" && $NF == "{" {
    59  	enum = 1
    60  	next
    61  }
    62  enum && $1 == "};" {
    63  	enum = 0
    64  	next
    65  }
    66  enum && NF == 3 && $2 == "=" {
    67  	name = $1
    68  	sub(/^GO_/, "", name)
    69  	val = $3
    70  	sub(/,$/, "", val)
    71  	print "check_value(" name ", " val ")" > "goboringcrypto.x"
    72  	next
    73  }
    74  enum {
    75  	print FILENAME ":" NR ": unexpected line in enum: " $0 > "/dev/stderr"
    76  	exitcode = 1
    77  	next
    78  }
    79  
    80  # Check struct sizes.
    81  /^typedef struct / && $NF ~ /^GO_/ {
    82  	name = $NF
    83  	sub(/^GO_/, "", name)
    84  	sub(/;$/, "", name)
    85  	print "check_size(" name ")" > "goboringcrypto.x"
    86  	next
    87  }
    88  
    89  # Check function prototypes.
    90  /^(const )?[^ ]+ \**_goboringcrypto_.*\(/ {
    91  	name = $2
    92  	if($1 == "const")
    93  		name = $3
    94  	sub(/^\**_goboringcrypto_/, "", name)
    95  	sub(/\(.*/, "", name)
    96  	print "check_func(" name ")" > "goboringcrypto.x"
    97  	print name > "syms.txt"
    98  	next
    99  }
   100  
   101  {
   102  	print FILENAME ":" NR ": unexpected line: " $0 > "/dev/stderr"
   103  	exitcode = 1
   104  }
   105  
   106  END {
   107  	exit exitcode
   108  }
   109  EOF
   110  
   111  cat >boringh.awk <<'EOF'
   112  /^\/\/ #include/ {sub(/\/\//, ""); print > "goboringcrypto0.h"; next}
   113  /typedef struct|enum ([a-z_]+ )?{|^[ \t]/ {print >"goboringcrypto1.h";next}
   114  {gsub(/GO_/, ""); gsub(/enum go_/, "enum "); print >"goboringcrypto1.h"}
   115  EOF
   116  
   117  awk -f boringx.awk goboringcrypto.h # writes goboringcrypto.x
   118  awk -f boringh.awk goboringcrypto.h # writes goboringcrypto[01].h
   119  
   120  ls -l ../boringssl/include
   121  clang++ -std=c++11 -fPIC -I../boringssl/include -O2 -o a.out  goboringcrypto.cc
   122  ./a.out || exit 2
   123  
   124  # clang implements u128 % u128 -> u128 by calling __umodti3,
   125  # which is in libgcc. To make the result self-contained even if linking
   126  # against a different compiler version, link our own __umodti3 into the syso.
   127  # This one is specialized so it only expects divisors below 2^64,
   128  # which is all BoringCrypto uses. (Otherwise it will seg fault.)
   129  cat >umod-amd64.s <<'EOF'
   130  # tu_int __umodti3(tu_int x, tu_int y)
   131  # x is rsi:rdi, y is rcx:rdx, return result is rdx:rax.
   132  .globl __umodti3
   133  __umodti3:
   134  	# specialized to u128 % u64, so verify that
   135  	test %rcx,%rcx
   136  	jne 1f
   137  
   138  	# save divisor
   139  	movq %rdx, %r8
   140  
   141  	# reduce top 64 bits mod divisor
   142  	movq %rsi, %rax
   143  	xorl %edx, %edx
   144  	divq %r8
   145  
   146  	# reduce full 128-bit mod divisor
   147  	# quotient fits in 64 bits because top 64 bits have been reduced < divisor.
   148  	# (even though we only care about the remainder, divq also computes
   149  	# the quotient, and it will trap if the quotient is too large.)
   150  	movq %rdi, %rax
   151  	divq %r8
   152  
   153  	# expand remainder to 128 for return
   154  	movq %rdx, %rax
   155  	xorl %edx, %edx
   156  	ret
   157  
   158  1:
   159  	# crash - only want 64-bit divisor
   160  	xorl %ecx, %ecx
   161  	movl %ecx, 0(%ecx)
   162  	jmp 1b
   163  
   164  .section .note.GNU-stack,"",@progbits
   165  EOF
   166  
   167  cat >umod-arm64.c <<'EOF'
   168  typedef unsigned int u128 __attribute__((mode(TI)));
   169  
   170  static u128 div(u128 x, u128 y, u128 *rp) {
   171  	int n = 0;
   172  	while((y>>(128-1)) != 1 && y < x) {
   173  		y<<=1;
   174  		n++;
   175  	}
   176  	u128 q = 0;
   177  	for(;; n--, y>>=1, q<<=1) {
   178  		if(x>=y) {
   179  			x -= y;
   180  			q |= 1;
   181  		}
   182  		if(n == 0)
   183  			break;
   184  	}
   185  	if(rp)
   186  		*rp = x;
   187  	return q;
   188  }
   189  
   190  u128 __umodti3(u128 x, u128 y) {
   191  	u128 r;
   192  	div(x, y, &r);
   193  	return r;
   194  }
   195  
   196  u128 __udivti3(u128 x, u128 y) {
   197  	return div(x, y, 0);
   198  }
   199  EOF
   200  
   201  extra=""
   202  case $GOARCH in
   203  amd64)
   204  	cp umod-amd64.s umod.s
   205  	clang -c -o umod.o umod.s
   206  	extra=umod.o
   207  	;;
   208  arm64)
   209  	cp umod-arm64.c umod.c
   210  	clang -c -o umod.o umod.c
   211  	extra=umod.o
   212  	;;
   213  esac
   214  
   215  # Prepare copy of libcrypto.a with only the checked functions renamed and exported.
   216  # All other symbols are left alone and hidden.
   217  echo BORINGSSL_bcm_power_on_self_test >>syms.txt
   218  awk '{print "_goboringcrypto_" $0 }' syms.txt >globals.txt
   219  awk '{print $0 " _goboringcrypto_" $0 }' syms.txt >renames.txt
   220  objcopy --globalize-symbol=BORINGSSL_bcm_power_on_self_test \
   221  	../boringssl/build/crypto/libcrypto.a libcrypto.a
   222  
   223  # Link together bcm.o and libcrypto.a into a single object.
   224  ld -r -nostdlib --whole-archive -o goboringcrypto.o libcrypto.a $extra
   225  
   226  echo __umodti3 _goboringcrypto___umodti3 >>renames.txt
   227  echo __udivti3 _goboringcrypto___udivti3 >>renames.txt
   228  objcopy --remove-section=.llvm_addrsig goboringcrypto.o goboringcrypto1.o # b/179161016
   229  objcopy --redefine-syms=renames.txt goboringcrypto1.o goboringcrypto2.o
   230  objcopy --keep-global-symbols=globals.txt --strip-unneeded goboringcrypto2.o goboringcrypto_linux_$GOARCH.syso
   231  
   232  # Done!
   233  ls -l goboringcrypto_linux_$GOARCH.syso