You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Prevent LTO from optimizing out OpenSSL engine symbols
LTO is enabled by default for .deb packages starting in Ubuntu 21.04[1],
causing build failures on Ubuntu 22.04 when we use GCC ranlib (used by
default with `cc` crate version >= 1.0.74[2]). LTO is incompatible with
`__asm__(".symver ..")` because it uses the linker-script-provided
exported symbols to determine what is safe to optimize out, and the
linker script is naturally unaware of manually-exported symbols. We can
work around this by adding `__attribute__((used))` to the functions we
want to keep in the final object.
Another option would be to use GCC's `__attribute__((symver("..@")))`[3]
directive, but this relies on too new of a toolchain version (GCC 10).
Addendum 1: The fundamental reason for why LTO is a problem for
`aziot-key-openssl-engine-shared` in the first place is that this crate
uses what is, in effect, a "symbol stub" to hook Rust code into
OpenSSL's engine macros. First, `build/engine.c` declares the engine
function signature and uses OpenSSL's macros to expand the dynamic
engine binding. This file is then compiled (but not linked) into an
object that will become the dynamic library's public interface. The way
this is accomplished is by linking the whole object into the `cdylib`
(as opposed to only linking referenced functions). LTO requires us to
go one step further by preventing the linker from optimizing out symbols
not declared as globally-exported in `rustc`'s linker script, which does
not know of the symbol declaration in the stub object. There is an open
RFC request for allowing re-export of C symbols from `cdylib` crates:
rust-lang/rfcs#2771.
Addendum 2: When our supported platforms start shipping with GNU as >=
2.35 and/or Clang 13, we may want to add `,remove` to the `.symver`
directive arguments to lift the restriction that
`aziot-key-openssl-engine-shared` cannot be included in tests[4].
[1]: https://wiki.ubuntu.com/ToolChain/LTO
[2]: Binutils ranlib was used before, see discussion in
rust-lang/cc-rs#735 for full details.
[3]: `..@` instead of `..@@` since we do not define a version
node name, meaning double-at leads to symbol duplication.
[4]: https://maskray.me/blog/2020-11-26-all-about-symbol-versioning
0 commit comments