fn add_linked_symbol_object(
cmd: &mut dyn Linker,
sess: &Session,
tmpdir: &Path,
symbols: &[(String, SymbolExportKind)],
)
Expand description
Add a synthetic object file that contains reference to all symbols that we want to expose to the linker.
Background: we implement rlibs as static library (archives). Linkers treat archives
differently from object files: all object files participate in linking, while archives will
only participate in linking if they can satisfy at least one undefined reference (version
scripts doesn’t count). This causes #[no_mangle]
or #[used]
items to be ignored by the
linker, and since they never participate in the linking, using KEEP
in the linker scripts
can’t keep them either. This causes #47384.
To keep them around, we could use --whole-archive
and equivalents to force rlib to
participate in linking like object files, but this proves to be expensive (#93791). Therefore
we instead just introduce an undefined reference to them. This could be done by -u
command
line option to the linker or EXTERN(...)
in linker scripts, however they does not only
introduce an undefined reference, but also make them the GC roots, preventing --gc-sections
from removing them, and this is especially problematic for embedded programming where every
byte counts.
This method creates a synthetic object file, which contains undefined references to all symbols
that are necessary for the linking. They are only present in symbol table but not actually
used in any sections, so the linker will therefore pick relevant rlibs for linking, but
unused #[no_mangle]
or #[used]
can still be discard by GC sections.
There’s a few internal crates in the standard library (aka libcore and
libstd) which actually have a circular dependence upon one another. This
currently arises through “weak lang items” where libcore requires things
like rust_begin_unwind
but libstd ends up defining it. To get this
circular dependence to work correctly we declare some of these things
in this synthetic object.