Dollar sign is handled incorrectly for section names in inline-assembly on Windows platform
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
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
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 with the inline-assembly reproducer on x86_64-pc-windows-msvc and inspect the generated assembly produced by RUSTFLAGS="--emit asm". Trace where .foo$a becomes .fooa, compare it with the working link_section behavior, and add a regression test showing that the dollar-suffixed section is emitted and linked as .foo.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100