Skip to content

Adding lto = true causes duplicated symbol errors on .weak symbols #133974

Open
@rslawson

Description

@rslawson

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LTOArea: Link-time optimization (LTO)A-inline-assemblyArea: Inline assembly (`asm!(…)`)A-linkageArea: linking into static, shared libraries and binariesC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions