Change:
"-fno-use-linker-plugin".to_string(), // Always enable DEP (NX bit) when it is available "-Wl,--nxcompat".to_string(), <ins> // Enable ASLR "-Wl,--dynamicbase".to_string(), // ASLR will rebase it anyway so leaving that option enabled only leads to confusion "-Wl,--disable-auto-image-base".to_string(), </ins> ], );

Discussion:
This appears to be a MinGW-w64 linker bug.
Triage: I am not sure if there has been any change, nor steps to reproduce.
If this was a mingw-specific bug, we may be able to reactivate it on the msvc builds.
According to so we've already been effectively using ASLR with targets.
Can someone comment on whether thread locals are broken on Windows MinGW-w64 today? What are the reproduction steps?
I've done a cursory check of TLS with 64 bit binaries compiled with msvc and mingw32-g++ and both are working correctly. msvc output: Rage counter for a: 2 Rage counter for b: 2 Rage counter for main: 1 mingw32-g++ output: Rage counter for main: 1 Rage counter for a: 2 Rage counter for b: 2 64 bit binaries on Windows use ASLR by default unless explicitly disabled with a linker option. Both binaries in this test had the NX Compatible flag set in the executable image header. Happy to test further if anyone has a pointer to the problem code.
The key thing is statics in Rust. The NX compatible bit does not indicate ASLR, rather it needs to have the Dynamic base bit.
Does anybody have reproducer?

%5D%0Afn%20main()%20%7B%0Ause%20std%3A%3Acell%3A%3ARefCell%3B%0Ause%20std%3A%3Athread%3B%0A%0Athreadlocal!(static%20FOO%3A%20RefCell%3Cu32%3E%20%3D%20RefCell%3A%3Anew(1))(%7Cf%7C%20%7B%0A%20%20%20%20asserteq!(f.borrow()%2C%201)%3B%0A%20%20%20%20f.borrowmut()%20%3D%202%3B%0A%7D)%3B%0A%0A%2F%2F%20each%20thread%20starts%20out%20with%20the%20initial%20value%20of%201%0Alet%20t%20%3D%20thread%3A%3Aspawn((%7Cf%7C%20%7B%0A%20%20%20%20%20%20%20%20asserteq!(f.borrow()%2C%201)%3B%0A%20%20%20%20%20%20%20%20f.borrowmut()%20%3D%203%3B%0A%20%20%20%20%7D)%3B%0A%7D)().unwrap()(%7Cf%7C%20%7B%0A%20%20%20%20asserteq!(*f.borrow()%2C%202)%3B%0A%7D)%3B%0A%7D&edition=2018) still works for me after enabling ASLR.

MinGW-w64 doesn't expose the necessary flag yet, so I'll look into adding it to their linker. It should be as easy as adding support for an extra flag there and then passing the switch from the Rust compiler.
gdb-patches 301'd to the binutils list: which accepted the patch:
closing in favor of
This is a separate issue from .
Triage: not sure if anything has changed here, but I don't think so.
Triage: same as in 2016

This should be as simple as passing to the linker for both libraries and executables. However, the necessary relocations are never generated by MinGW or MinGW-w64 for executables so nothing is actually randomized without also passing . The switch is also broken and results in a messed up entry point, but it may not actually be required.
Hi, I found this issue while looking for an old reference, but I thought you might be interested in a possible fix. We needed for Tor's hardening options and after some back and forth settled on a working binutils patch which is here (works for 2.24 and is being submitted upstream shortly): This patch has not been reviewed at all, since no one at Tor feels sufficiently capable. Hopefully the binutils folks will have something to say, but as language developers you might too. (edit: fix link to patch)
We ended up working around it for the time being by doing a dllexport of main in order to force it to output a relocation section, since the executable counts as a library. I would really like to have this fixed properly though so I'll look into it some more when I have time.
Needs to be disabled again due to .
Note that recent binutils may have support for high entropy ASLR. ( was accepted last year. See ) It would be good to check if mingw-w64 would contain the patch when we re-enable ASLR.
Triage: not sure if anything has changed here, but I don't think so.
Triage: same as in 2016