PAYATHON 2026

为何 lld 会让 aarch64 musl 程序出现动态解释器?

数据小许

结论

可以尝试使用 aarch64-linux-musl-gcc,并显式传入 -static,同时选择 lld。目前能确认的是,切换到 lld 后,aarch64 输出包含动态解释器路径。仅凭 file 的结果,无法判断是哪条链接参数或 linker 规则导致的,需要检查实际链接命令。

file 显示 interpreter /lib/ld-musl-aarch64.so.1,说明 ELF 中记录了程序解释器,因此不能据此认定文件是完全静态链接的。题目中的两个目标输出也不相同:未指定 lld 时,aarch64 显示 statically linked,x86_64 显示 static-pie linked。这说明两种目标的链接方式或默认参数存在差异,x86_64 的结果不能用来推断 aarch64 的行为。

显式请求静态链接

保留 Cargo 中的 linker 配置,并将 -static 作为独立链接参数传给 linker 驱动。可以在 .cargo/config.toml 中这样配置:

[target.aarch64-unknown-linux-musl]
linker = "aarch64-linux-musl-gcc"
rustflags = [
  "-C", "link-arg=-fuse-ld=lld",
  "-C", "link-arg=-static",
]

重新构建后检查产物:

cargo clean
cargo build --target aarch64-unknown-linux-musl
file target/aarch64-unknown-linux-musl/debug/build-test
readelf -l target/aarch64-unknown-linux-musl/debug/build-test

-static 用来请求静态链接,但最终能否成功取决于实际使用的 linker、目标库和链接参数。配置文件本身不能证明产物已经完全静态。检查 readelf -l 的程序头,确认没有 INTERP 段;也要确认 file 不再显示 interpreter 路径。

查明两个目标为何不同

使用 Cargo 的详细输出查看 Rust 实际调用的 linker:

cargo clean
RUSTFLAGS="-Clink-args=-fuse-ld=lld" cargo build -vv --target aarch64-unknown-linux-musl

再对比添加静态参数后的调用。重点查看 aarch64 链接命令是否包含 -static,以及是否包含指定解释器的参数。需要检查 GCC 驱动最终准备执行的命令时,可以用对应的 aarch64-linux-musl-gcc 和相同选项加上 -###。

题目提供的版本和 file 输出没有包含完整链接命令,无法据此确定架构差异的确切原因。对比两个目标最终使用的 linker 参数,才能查明切换到 -fuse-ld=lld 后,哪些静态链接选项没有保留或发生了变化。

备注:内容仅供参考。