Adding `lto = true` causes duplicated symbol errors on `.weak` symbols
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Here's a minimal reproducer for the issue described in the title.
.cargo/config.toml:
[build]
target = "riscv32imc-unknown-none-elf"
[unstable]
build-std = ["core,panic_abort"]
memory.x (exact contents unimportant, but provided for convenience):
MEMORY
{
IMEM : ORIGIN = 0x80000000, LENGTH = 1024K
DMEM : ORIGIN = 0x10000000, LENGTH = 256K
}
REGION_ALIAS("REGION_TEXT", IMEM);
REGION_ALIAS("REGION_RODATA", DMEM);
REGION_ALIAS("REGION_DATA", DMEM);
REGION_ALIAS("REGION_BSS", DMEM);
REGION_ALIAS("REGION_HEAP", DMEM);
REGION_ALIAS("REGION_STACK", DMEM);
build.rs:
use std::env;
use std::fs;
use std::path::Path;
fn main() {
let out_dir = env::var("OUT_DIR").expect("No out dir");
let dest_path = Path::new(&out_dir).join("memory.x");
fs::write(dest_path, include_bytes!("memory.x")).expect("Could not write file");
if env::var("CARGO_CFG_TARGET_ARCH").unwrap() == "riscv32" {
println!("cargo:rustc-link-arg=-Tmemory.x");
println!("cargo:rustc-link-arg=-Tlink.x");
}
println!("cargo:rustc-link-search={out_dir}");
println!("cargo:rerun-if-changed=memory.x");
println!("cargo:rerun-if-changed=build.rs");
}
src/main.rs:
#![no_std]
#![no_main]
use riscv_rt::entry;
#[entry]
fn main() -> ! {
loop {}
}
#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
loop {}
}
#[unsafe(export_name = "ExceptionHandler")]
fn exception_handler(_: &riscv_rt::TrapFrame) -> ! {
loop {}
}
#[unsafe(export_name = "DefaultHandler")]
fn default_handler(_: &riscv_rt::TrapFrame) -> ! {
loop {}
}
Cargo.toml:
[package]
name = "lto-bug-repro"
version = "0.1.0"
edition = "2021"
[profile.release]
lto = true # Commenting out this line should allow it to compile successfully
[dependencies]
riscv-rt = "0.13.0"
As is documented in riscv-rt, ExceptionHandler and DefaultHandler are weak symbols, and I verified in the source code for the crate that they're marked with .weak in global_asm! (relevant src). What I don't understand is why enabling lto = true causes the build to fail with the errors
error: DefaultHandler changed binding to STB_GLOBAL
error: symbol 'DefaultHandler' is already defined
error: ExceptionHandler changed binding to STB_GLOBAL
error: could not compile `lto-bug-repro` (bin "lto-bug-repro") due to 3 previous errors
I also have no idea how to track down what's causing this.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the minimal reproducer from .cargo/config.toml, build.rs, src/main.rs, and Cargo.toml with lto enabled and disabled, then inspect the weak-symbol definitions in riscv-rt's src/asm.rs. Trace the compiler or linker stage that changes DefaultHandler and ExceptionHandler bindings; done means the duplicate-symbol failure is explained and a regression test or fix is identified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100