Skip to content

Dollar sign is handled incorrectly for section names in inline-assembly on Windows platform #128177

Open
@Evian-Zhang

Description

@Evian-Zhang

I tried this code:

fn main() {
    unsafe {
        core::arch::asm!(
            r#"
        .pushsection .foo$a
        .long 0x1234
        .popsection
        "#
        );
    }
}

I expected to see this happen: Generated executable contains a section named ".foo".

Instead, this happened: Generated executable contains a section named ".fooa".

Further explanation:

On Windows platform, section names are divided by "$". The former part is used as section name in final binary, and the latter part is used to sort and merge sections with names with same former part, and the latter part will be erased in final binary. For example, if I declare a section ".foo$a" in source code, it will be generated to section ".foo" in final executable.

This is a extremely useful feature to achieve a symbol pointing to the start and end of certain sections (See this and this, and this is what the famous linkme crate does). If we use link_section attribute on statics in Rust, things go right:

#[link_section = ".foo$a"]
#[used]
static mut MY_VAR: xxxx = xxxx;

The MY_VAR will be generated into ".foo" section.

However, in some situations, we can only use inline assembly instead of statics to declare some datas (more concretely, I'm re-implementing Linux kernel's static-keys mechanism into Rust userland, see static-keys). And the inline-assembly generates the wrong section name, which prevents us from getting the right section-start and section-end symbols.

Moreover, I use RUSTFLAGS="--emit asm" to check, it turns out that, inside generated assembly file, the section name has already become ".fooa" instead of ".foo$a", so it is not a linker bug.

I don't if this bug is Rust-related or LLVM-related (since it is hard to use LLVM tools to write a C inline-asm to test on a Windows platform), and hope someone could help. :) BTW, by searching ".split('$').second" in LLVM source code, it seems that there is nothing wrong?

Meta

rustc --version --verbose:

rustc 1.79.0 (129f3b996 2024-06-10)
binary: rustc
commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081
commit-date: 2024-06-10
host: x86_64-pc-windows-msvc
release: 1.79.0
LLVM version: 18.1.7

rustc +nightly --version --verbose:

rustc 1.82.0-nightly (c1a6199e9 2024-07-24)
binary: rustc
commit-hash: c1a6199e9d92bb785c17a6d7ffd8b8b552f79c10
commit-date: 2024-07-24
host: x86_64-pc-windows-msvc
release: 1.82.0-nightly
LLVM version: 18.1.7

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-inline-assemblyArea: Inline assembly (`asm!(…)`)C-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