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.