Mold Linker Version 3.0.0 Release – Rewritten in Rust
Announcement: Mold Linker v3.0.0 — Now Powered by Rust
The high-speed linker, mold, has reached a major milestone with the release of version 3.0.0. As previously hinted at in the 2.42.1 notes, the project has undergone a complete architectural transformation: mold has been rewritten from C++ in Rust.
🎯 Strategic Objectives
The primary goals for the 3.x series are:
- Closing Compatibility Gaps: Specifically improving support for linker scripts to align more closely with
GNU ld. - Distribution Readiness: Preparing the tool for adoption as the standard default linker across various Linux distributions.
Note on Compatibility: Mold 3.0.0 maintains parity with previous versions regarding target architectures, command-line arguments, and general output, with the exception of the specific bug fixes detailed below.
Verification Process
To ensure a seamless transition, the developers employed a rigorous validation strategy:
- Execution of the full test suite across all supported targets.
- Comparative analysis of linker output using a vast array of real-world workloads and option permutations.
- Successful builds of the entire Gentoo package set.
🛡️ Safety and Stability
The migration to Rust significantly enhances the linker's resilience when handling malformed or corrupted input files.
| Version | Behavior on Corrupted Input | Result |
|---|---|---|
| C++ Version | Potential out-of-bounds memory reads | |
| Rust Version | Strict bounds-checking |
🛠️ Build and Installation Guide
The build pipeline has been overhauled. Please follow these updated instructions:
Compilation Steps
- Execute
cargo build --releaseto compile the binary. - Run
./install-mold.shto perform the installation.
Environment Variables:
PREFIXandDESTDIR: Supported by the installation script.MOLD_LIBDIR: If libraries are installed in a non-standard path (e.g.,/usr/lib64instead of$PREFIX/lib), this variable must be set during both the build and install phases somold -runcan locatemold-wrapper.so.
Dependencies and Allocation
- Memory Allocation: By default, it statically links
mimalloc 3.5.3. To switch to the system's allocator, use:--features system-allocator - Compression/Hashing: Includes
zstdandBLAKE3, and links the systemzlibif present. To force the use of the system'szstdvia pkg-config, set:ZSTD_SYS_USE_PKG_CONFIG=1
Build System Changes
Note: install-test-deps.sh is now only required for those running the test suite.
🐛 Bug Fixes & Compatibility Enhancements
💥 Crash Fixes
- Resolved crashes occurring during the creation of statically-linked executables when using
--default-symveror version scripts. - Fixed a corruption/crash issue when the output file was also listed as an input (e.g.,
mold -r -o foo.o foo.o bar.o). - Fixed crashes associated with
--icf=allwhen combined with--emit-relocs. - Fixed crashes in
--noinhibit-execwhen referencing symbols in discarded COMDAT groups.
⚙️ Logic and Behavioral Improvements
- Section GC:
--gc-sectionswill no longer strip functions designated by--finior--init. - Symbol Handling: Common symbols with identical names but varying sizes now adopt the largest size and most stringent alignment (matching
lldandGNU ld). - ICF:
--icf=safeno longer folds functions that are exported from shared libraries. - Versioning:
- Versioned references (e.g.,
foo@VER) in shared libraries no longer trigger the inclusion of unversionedfoomembers from archives. - In version scripts, if a symbol appears in multiple nodes, the first occurrence now takes precedence.
- Versioned references (e.g.,
- Determinism: Eliminated non-deterministic output in several areas:
--reproand--dependency-file.- Dynamic relocations.
-rwhen handling numerous COMDAT groups with the same name.
🛠️ Relocatable (-r) and Relocation Fixes
- Relocatable Bugs: Fixed issues where C++ exceptions failed in subsequent input files, symbols were erroneously removed by
-s,-x, or-X, and data was dropped by--gc-sections. - Section Headers: Corrected
sh_linkforSHF_LINK_ORDERsections (such as.ARM.exidx). - DWARF: Fixed crashes when using
--strip-debugwith DWARF type units. - Address Accuracy: Corrected silent address errors for
R_ARM_REL32andR_X86_64_GOTOFF64(GOT-relative relocations) against shared library symbols. - Diagnostics: PC-relative relocation errors in position-independent output now provide clear explanations and remediation steps.
⚠️ Error Handling (Now failing explicitly instead of crashing)
The following scenarios now trigger a formal error:
--defsymvalues exceeding .--defsymaliasing a symbol already defined in a shared library.- Undefined non-weak hidden symbols in shared libraries (or when using
--unresolved-symbols=ignore-all). - Allocated sections that are simultaneously compressed.
- Combining
--strip-allwith--emit-relocs.
⌨️ CLI and Environment
- GNU Parity: Single-dash options are now parsed identically to
GNU ld. - Argument Parsing: The following flags no longer consume the subsequent argument:
--thinlto-index-only--lto-pseudo-probe-for-profiling--dynamic-list-data
- New Options: Added support for
--no-color-diagnostics. - Paths: Fixed relative path handling for
--repro,--chroot, and-C. - Resources:
Reserved of virtual address space at startupRemoved reservation, enabling compatibility withulimit -v. - Environment:
MOLD_JOBSnow functions correctly even ifXDG_RUNTIME_DIRis an empty string.
🏗️ Miscellaneous & Architecture Specifics
- Debug Files:
.gnu_debuglinksections are no longer included in files created via--separate-debug-file. - Symbols: Removed redundant symbols:
__start_EHDR,__stop_EHDR,__start_PHDR, and__stop_PHDR. - Architecture Fixes:
- [AArch64/PPC32/ARM32]: Fixed range extension thunks for static function calls in different sections (critical for large binaries like Chromium ARM64 debug builds).
- [AArch64]: Added support for
R_AARCH64_GOT_LD_PREL19andR_AARCH64_TSTBR14. - [ARM32]: Expanded support for various relocation types (e.g.,
R_ARM_...).