-
Notifications
You must be signed in to change notification settings - Fork 10
Description
BearSSL advertises:
A static linking model in which only algorithms that are actually used get pulled into the linked binary. This is done through appropriate usage of function pointers; there is no need to recompile BearSSL with specific preprocessor options to obtain such a trimming.
And in another place
BearSSL is pluggable, so what a given SSL client or server engine supports depends on which algorithms were configured into it. From a programming point of view, each algorithm is configured by setting a pointer to the relevant implementation into the engine context; referencing that implementation means that, at link time, the corresponding code will be pulled into the produced binary, along with all its dependencies.
When wrapped in nim-bearssl, though, it seems like some of the pluggable-ness is gone. For instance, compiling the following, which only uses MD5 still includes symbols for SHA algorithms:
import std/os
import bearssl/hash
let inp = paramStr(1)
var
ctx = Md5Context()
res: array[md5SIZE, uint8]
md5Init(ctx)
md5Update(ctx, inp.cstring, uint inp.len)
md5Out(ctx, addr res[0])
echo $res$ nim c samp && nm samp | grep br_sha
000000010001c7b0 S _br_sha1_IV
0000000100008bb0 T _br_sha1_init
0000000100008d10 T _br_sha1_out
00000001000080f0 T _br_sha1_round
0000000100008f30 T _br_sha1_set_state
0000000100008ef0 T _br_sha1_state
0000000100008c10 T _br_sha1_update
000000010001e120 S _br_sha1_vtable
000000010001cad0 S _br_sha224_IV
000000010000afc0 T _br_sha224_init
000000010000b150 T _br_sha224_out
000000010000b360 T _br_sha224_set_state
000000010000b320 T _br_sha224_state
000000010000b020 T _br_sha224_update
000000010001e1c8 S _br_sha224_vtable
000000010001caf0 S _br_sha256_IV
000000010000b3b0 T _br_sha256_init
000000010000b410 T _br_sha256_out
000000010001e200 S _br_sha256_vtable
000000010000a3a0 T _br_sha2small_round
0000000100008fe0 T _br_sha384_init
0000000100009170 T _br_sha384_out
00000001000093e0 T _br_sha384_set_state
00000001000093a0 T _br_sha384_state
0000000100009040 T _br_sha384_update
000000010001e158 S _br_sha384_vtable
0000000100009430 T _br_sha512_init
0000000100009490 T _br_sha512_out
000000010001e190 S _br_sha512_vtable
Or in this example, nothing from BearSSL is used, yet the resulting binary contains all of BearSSL:
import bearssl
import bearssl/hash
echo "foo"$ nim c samp && nm samp | grep br_
000000010008f2c0 S _br_aes_S
000000010000a1c0 T _br_aes_big_cbcdec_init
000000010000a220 T _br_aes_big_cbcdec_run
0000000100099130 S _br_aes_big_cbcdec_vtable
000000010000a330 T _br_aes_big_cbcenc_init
000000010000a390 T _br_aes_big_cbcenc_run
0000000100099150 S _br_aes_big_cbcenc_vtable
000000010000a470 T _br_aes_big_ctr_init
000000010000a4d0 T _br_aes_big_ctr_run
0000000100099170 S _br_aes_big_ctr_vtable
000000010000a710 T _br_aes_big_ctrcbc_ctr
...
0000000100068020 t _br_x509_minimal_set_hash
000000010006f4c0 t _br_x509_minimal_set_hash
0000000100067fd0 t _br_x509_minimal_set_rsa
000000010006f3d0 t _br_x509_minimal_set_rsa
0000000100099bd8 S _br_x509_minimal_vtable
I'm not complaining, just observing. I'm even willing to submit a PR to enhance this. While in my case this isn't a critical feature, it certainly would be nice to have smaller binaries.
Is it because of the {.used.} pragma I see in various places? Or something else?