Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BearSSL's automatic static linking trimming doesn't work completely #53

Open
iffy opened this issue Dec 29, 2023 · 1 comment
Open

BearSSL's automatic static linking trimming doesn't work completely #53

iffy opened this issue Dec 29, 2023 · 1 comment

Comments

@iffy
Copy link

iffy commented Dec 29, 2023

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?

@arnetheduck
Copy link
Member

Is it because of the {.used.} pragma I see in various places? Or something else?

{.used.} should not affect this at all - that's a pure nim-side construct - I too would be interested to know in depth what is causing the symbol references - ie it could be that some constant or semi-constant is getting generated somewhere that touches the symbols causing them to be included but this would require some digging. Happy to look at a PR if you find something!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants