From 781de52ca6edf1271e10a59dc8eb9cec6decfd45 Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Fri, 27 Mar 2026 23:53:04 +0300 Subject: [PATCH] build: be more aggressive with linker optimizations; wrap mold Signed-off-by: NotAShelf Change-Id: I0e3132ab1499684eda715c3cee9b27a16a6a6964 --- .cargo/config.toml | 30 ++++++++++++++++++++++++++++-- Cargo.toml | 6 +++--- microfetch/Cargo.toml | 8 ++++---- scripts/ld-wrapper | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 9 deletions(-) create mode 100755 scripts/ld-wrapper diff --git a/.cargo/config.toml b/.cargo/config.toml index 7a7a98f..d9f659e 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,5 +1,31 @@ -# Link with Mold, and without libc! We use nostartfiles to avoid the C runtime +# Use a linker wrapper that invokes mold then strips junk sections with objcopy. +# mold cannot discard .eh_frame/.dynstr/.comment via linker scripts, so we do +# it as a post-link step. # See: # [target.'cfg(target_os = "linux")'] -rustflags = [ "-C", "link-arg=-fuse-ld=mold", "-C", "link-arg=-nostartfiles" ] +linker = "scripts/ld-wrapper" +rustflags = [ + # No C runtime, we provide _start ourselves + "-C", + "link-arg=-nostartfiles", + # Fully static, no dynamic linker, no .interp/.dynsym/.dynamic overhead + "-C", + "link-arg=-static", + # Static PIE is incompatible with -static :( + "-C", + "relocation-model=static", + # Suppress .eh_frame emission from our own codegen (does not cover compiler_builtins; + # those remnants are removed by the linker wrapper via objcopy post-link) + "-C", + "force-unwind-tables=no", + # Linker flags + "-C", + "link-arg=-Wl,--gc-sections", # remove unreferenced input sections + "-C", + "link-arg=-Wl,--strip-all", # strip all symbol table entries + "-C", + "link-arg=-Wl,--build-id=none", # omit the .note.gnu.build-id section + "-C", + "link-arg=-Wl,-z,norelro", # disable RELRO (removes relro_padding) +] diff --git a/Cargo.toml b/Cargo.toml index da548d7..9500909 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,15 +11,15 @@ version = "0.4.13" [workspace.dependencies] microfetch-alloc = { path = "./crates/alloc" } -microfetch-asm = { path = "./crates/asm" } -microfetch-lib = { path = "./crates/lib" } +microfetch-asm = { path = "./crates/asm" } +microfetch-lib = { path = "./crates/lib" } criterion = { default-features = false, features = [ "cargo_bench_support" ], version = "0.8.2" } criterion-cycles-per-byte = "0.8.0" [profile.dev] opt-level = 1 -panic = "abort" +panic = "abort" [profile.release] codegen-units = 1 diff --git a/microfetch/Cargo.toml b/microfetch/Cargo.toml index b29b420..43d4f9c 100644 --- a/microfetch/Cargo.toml +++ b/microfetch/Cargo.toml @@ -11,14 +11,14 @@ repository = "https://github.com/notashelf/microfetch" publish = false [dependencies] -hotpath = { optional = true, version = "0.14.0" } +hotpath = { optional = true, version = "0.14.0" } microfetch-alloc.workspace = true -microfetch-lib.workspace = true -microfetch-asm.workspace = true +microfetch-asm.workspace = true +microfetch-lib.workspace = true [features] hotpath = [ "dep:hotpath" ] hotpath-alloc = [ "hotpath/hotpath-alloc" ] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/scripts/ld-wrapper b/scripts/ld-wrapper new file mode 100755 index 0000000..cf2cb21 --- /dev/null +++ b/scripts/ld-wrapper @@ -0,0 +1,34 @@ +#!/usr/bin/env sh +# Invoke mold, then strip junk sections from the output binary with objcopy. +# This (more or less) removes sections that mold cannot discard itself, suck as: +# - .eh_frame / .eh_frame_hdr - unwind tables from compiler_builtins +# - dynstr - mold emits this, even for fully static binaries +# - .comment - compiler version string +# +# We forward everything to mold via -fuse-ld, then post-process the output in place. + +set -eu + +# Locate the output file +OUTPUT="" +prev="" +for arg in "$@"; do + if [ "$prev" = "-o" ]; then + OUTPUT="$arg" + break + fi + prev="$arg" +done + +# Invoke mold via the cc driver, forward all original arguments +cc -fuse-ld=mold "$@" + +# Remove sections that mold cannot discard +if [ -n "$OUTPUT" ] && [ -f "$OUTPUT" ]; then + objcopy \ + --remove-section=.eh_frame \ + --remove-section=.eh_frame_hdr \ + --remove-section=.dynstr \ + --remove-section=.comment \ + "$OUTPUT" +fi