-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#[thread_local]
alignment broken on Windows, GNU ABI
#135719
Comments
Does this also reproduce with Also what exactly do you mean with Wine here? Building it normally on Windows and running it with Wine? Building it in Wine too? |
The real Windows vs Wine separation refers to the environment the code is run in. I haven't considered building the code in different environments. All GNU targets were cross-compiled on Linux, all MSVC targets were compiled with cargo-xwin. I don't have access to a Windows machine right now, someone should probably try building directly on Windows, too, although I doubt there'd be a difference in the produced executables.
Eugh, kind of. #[repr(align(256))]
struct HighAlignment(u8);
thread_local! {
static EXAMPLE1: HighAlignment = const { HighAlignment(0) };
}
thread_local! {
static EXAMPLE2: HighAlignment = const { HighAlignment(0) };
}
thread_local! {
static EXAMPLE3: HighAlignment = const { HighAlignment(0) };
}
fn main() {
EXAMPLE1.with(|a| {
EXAMPLE2.with(|b| {
EXAMPLE3.with(|c| {
println!(
"{:?}, {:?}, {:?}",
a as *const HighAlignment, b as *const HighAlignment, c as *const HighAlignment
);
})
})
});
} Gives unaligned addresses on Wine on |
Running that sample on real Windows yields
, so it's fine. |
Turns out |
I haven't managed to reproduce the bug with |
Have you tried to put a smaller thread local between these over-aligned ones? like thread_local! {
static EXAMPLE1: HighAlignment = const { HighAlignment(0) };
static BREAK_ALIGNMENT: u16 = 135;
static EXAMPLE2: HighAlignment = const { HighAlignment(0) };
static EXAMPLE3: HighAlignment = const { HighAlignment(0) };
} |
@ProgramCrafter This is a bit more complicated. The thread locals themselves are aligned just fine within the global TLS storage. You can think of it as a typical Rust structure containing individual variables, and it's layouted correctly. However, the TLS storage itself is underaligned when allocated. So adding more fields won't help, as the goal is to analyze the allocation properties of the TLS storage itself. |
Also note windows-gnu targets do not enable |
So! First things first: I forgot about the A bit of an introduction:
As sections are purely descriptive and don't affect the behavior of the PE loader, the information about the
"256 byte align" was parsed from the Now, if you compile for the
The If we check the target specifications, we'll see that MSVC and GNU LLVM enable The above explains the behavior of the first four bullet points from the original post. What about Wine? It turns out Wine allocates TLS on the heap without a particular alignment, ignoring the As expected, Wine fails with GNU LLVM and MSVC binaries, because it never respects the alignment requirements. That was all about I don't think we can work around this Wine bug. Fixing it on the Wine side sounds simpler and shouldn't be difficult. I'll see if I can do that within the next week. |
To summarize, there are two bugs:
Let us track the former bug here and leave the latter to Wine folks. @rustbot label -O-windows +O-windows-gnu |
#[thread_local]
alignment broken on Windows#[thread_local]
alignment broken on Windows, GNU ABI
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I haven't dug deeply, but I think I've narrowed it down to another binutils bug. Once you enable it in the spec, you will get a few thousand crashes in the test suite. Enabling emulated TLS could possibly help (this is how GCC handles TLS for Windows), but it might need some fixes first. |
Nightly only issue @rustbot label -P-medium +requires-nightly |
I tried this code:
I expected to see this happen: three
0x100
-aligned pointers.Instead, this happened: metal pipe falling
0x1f39e953850, 0x1f39e953950, 0x1f39e953a50
(unaligned)0x1c287893900, 0x1c287893a00, 0x1c287893b00
(aligned)0xf9a5f8, 0xf9a6f8, 0xf9a7f8
(unaligned)0x6d2f00, 0x6d3000, 0x6d3100
(aligned)0x232c80, 0x232d80, 0x232e80
(unaligned)0x1320e0, 0x1321e0, 0x1322e0
(unaligned)0x341f28, 0x342028, 0x342128
(unaligned)0x34f010, 0x34f110, 0x34f210
(unaligned)So either this affects all of Windows and I just got lucky twice, or this is two bugs in a trenchcoat, one affecting GNU ABI and another one in Wine. Not sure which.
Notably, checking mixed-alignment thread locals, like
u8, u8, u128, u128, u128
, shows that the variables are correctly aligned with respect to each other within TLS, but the TLS base itself seems to be unaligned.Tentatively marking as
I-unsound
because of unaligned references bad, feel free to retag.Meta
rustc --version --verbose
:wine --version
:wine-9.22 (Staging)
Tracking issue for visibility: #29594
The text was updated successfully, but these errors were encountered: