Skip to content
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

TEXTREL in i686 since 1.41.0 #68794

Closed
Cogitri opened this issue Feb 3, 2020 · 25 comments · Fixed by #69086
Closed

TEXTREL in i686 since 1.41.0 #68794

Cogitri opened this issue Feb 3, 2020 · 25 comments · Fixed by #69086
Assignees
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. O-android Operating system: Android O-x86_32 Target: x86 processors, 32 bit (like i686-*) P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Cogitri
Copy link

Cogitri commented Feb 3, 2020

Hello,

I'm in the process of upgrading Rust to 1.41.0 on Alpine Linux and it appears that a TEXTREL has been introduced in 1.41.0:

TEXTREL /usr/lib/librustc_macros-4cbed8a36ab240e8.so

The full build log is located here if it's of interest: https://gitlab.alpinelinux.org/Cogitri/aports/-/jobs/44396

@jonas-schievink jonas-schievink added A-linkage Area: linking into static, shared libraries and binaries C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 3, 2020
@jonas-schievink
Copy link
Contributor

jonas-schievink commented Feb 5, 2020

This apparently breaks Android builds, since that forbids text relocations

https://users.rust-lang.org/t/cant-link-rust-code-on-i686-linux-android-with-rust-1-41/37807

@jonas-schievink jonas-schievink added C-bug Category: This is a bug. I-nominated O-android Operating system: Android regression-from-stable-to-stable Performance or correctness regression from one stable version to another. and removed C-enhancement Category: An issue proposing an enhancement or a PR with one. labels Feb 5, 2020
@awakecoding
Copy link

+1 I am one of the unfortunate winner of a release-blocking CI build failure for Android now that we've upgraded to 1.41.0. We've disabled android-x86 builds for now :(

@brainlock
Copy link
Contributor

I added a minimal repro to my repository here: https://github.com/brainlock/rust-1.41-android-linker-bug-repro, in the hope that it can help debugging this (and because I was curious to dig into this myself :-) ).

You can clone the repo, then

docker build -t repro .

docker run --rm -it repro bash

In the container you can run ./repro-min.sh.

I bisected it using rustup and nightly releases, 2012-12-09 is good, 2019-12-10 is bad:

root@dea5c1fdc0d5:/usr/src/repro# rustup default nightly-2019-12-09
info: using existing install for 'nightly-2019-12-09-x86_64-unknown-linux-gnu'
info: default toolchain set to 'nightly-2019-12-09-x86_64-unknown-linux-gnu'

  nightly-2019-12-09-x86_64-unknown-linux-gnu unchanged - rustc 1.41.0-nightly (59947fcae 2019-12-08)

root@dea5c1fdc0d5:/usr/src/repro# ./repro-min.sh
   Compiling repro v0.1.0 (/usr/src/repro)
    Finished release [optimized] target(s) in 0.20s
root@dea5c1fdc0d5:/usr/src/repro# rustup default nightly-2019-12-10
info: using existing install for 'nightly-2019-12-10-x86_64-unknown-linux-gnu'
info: default toolchain set to 'nightly-2019-12-10-x86_64-unknown-linux-gnu'

  nightly-2019-12-10-x86_64-unknown-linux-gnu unchanged - rustc 1.41.0-nightly (76a252ea9 2019-12-09)

root@dea5c1fdc0d5:/usr/src/repro# ./repro-min.sh
   Compiling repro v0.1.0 (/usr/src/repro)
    Finished release [optimized] target(s) in 0.20s
ld: target/i686-unknown-linux-gnu/release/librepro.a(std-c3eaafedbae89cb4.std.52ue7rpt-cgu.0.rcgu.o): warning: relocation against `__rust_probestack' in read-only section `.text._ZN3std3sys4unix2fs4copy17h783e034bf468da7dE'
ld: warning: creating a DT_TEXTREL in a shared object
root@dea5c1fdc0d5:/usr/src/repro#

When using nightly-2019-12-10:

root@28bb5be323b6:/usr/src/repro# rustc --version
rustc 1.41.0-nightly (76a252ea9 2019-12-09)

@Mark-Simulacrum
Copy link
Member

Mark-Simulacrum commented Feb 6, 2020

Conveniently, no rollups!

76a252e Auto merge of #67110 - tmandry:bump-compiler-builtins, r=alexcrichton
7de9402 Auto merge of #67096 - mark-i-m:fix-rustc-guide-2, r=ehuss
3ff17e7 Auto merge of #67016 - lqd:placeholder_loans, r=matthewjasper
dbbe4f1 Auto merge of #67004 - estebank:issue-66958, r=eddyb
2b0e6d2 Auto merge of #67003 - cjgillot:corrida, r=Mark-Simulacrum
14195e1 Auto merge of #66984 - GuillaumeGomez:move-clean-types, r=kinnison

I would personally suspect #67110.

Can you try checking this via https://crates.io/crates/rustup-toolchain-install-master/?

Specifically, comparing 76a252e and 7de9402?

@brainlock
Copy link
Contributor

While rustup-toolchain-install-master compiles ( 😅 ): I see that https://github.com/rust-lang/rust/pull/67110 upgrades compiler-builtins. I had a look at the commits in compiler-builtins which touch __rust_probestack, and I think we can likely narrow it down to rust-lang/compiler-builtins@2566aa6.

At this point I'm too much out of my depth, this needs people more knowledgeable than me 😉 . I hope I could help debugging this, and will continue watching the issue as I'm learning a great deal just by investigating this.

Besides the actual fix, there are two additional things I'd love to understand:

  1. why doesn't scanelf -qT std-c3eaafedbae89cb4.std.52ue7rpt-cgu.0.rcgu.o detect this? It looks like the obj file is not marked in any way has having a TEXTREL, but maybe the inline asm from that commit defines __rust_probestack in such a way that relocating it needs touching the .text section (wild guess)

  2. how would we go at testing this? Where in the rust project would I add a test for this? And given that scanelf can't detect this, maybe a good way to "integration test" this would be to build a minimal rust static lib, and try to link it into a shared object with --warn-shared-textrel --fatal-warnings like I'm doing in the repro code. Do I understand correctly that "all code produced by rustc should be relocatable" is a guaranteed property (thus worth testing), or am I completely mistaken?

@brainlock
Copy link
Contributor

Meanwhile, I can confirm that we got the right commit (76a252e):

albe@myo ~/code/repro [master] % docker build -t repro .
[...]
albe@myo ~/code/repro [master] % docker run --rm -it repro bash
root@c74a4c84b096:/usr/src/repro# rustup default 76a252ea9e7be93a61ffdf33b3533e24a9cf459d
info: default toolchain set to '76a252ea9e7be93a61ffdf33b3533e24a9cf459d'
root@c74a4c84b096:/usr/src/repro# rustc --version
rustc 1.41.0-nightly (76a252ea9 2019-12-09)
root@c74a4c84b096:/usr/src/repro# ./repro-min.sh
ld: target/i686-unknown-linux-gnu/release/librepro.a(std-c3eaafedbae89cb4.std.52ue7rpt-cgu.0.rcgu.o): warning: relocation against `__rust_probestack' in read-only section `.text._ZN3std3sys4unix2fs4copy17h783e034bf468da7dE'
ld: warning: creating a DT_TEXTREL in a shared object
root@c74a4c84b096:/usr/src/repro#
root@c74a4c84b096:/usr/src/repro#
root@c74a4c84b096:/usr/src/repro# rustup default 7de9402b77ded0d8ec9e1c554521b2121449ef2b
info: default toolchain set to '7de9402b77ded0d8ec9e1c554521b2121449ef2b'
root@c74a4c84b096:/usr/src/repro# rustc --version
rustc 1.41.0-nightly (7de9402b7 2019-12-09)
root@c74a4c84b096:/usr/src/repro# ./repro-min.sh
root@c74a4c84b096:/usr/src/repro# echo $?
0
root@c74a4c84b096:/usr/src/repro#

@pnkfelix
Copy link
Member

pnkfelix commented Feb 6, 2020

triage: P-high. Assigning to self. Leaving nominated because I'd like to discuss this at today's meeting.

@pnkfelix pnkfelix self-assigned this Feb 6, 2020
@pnkfelix pnkfelix added P-high High priority and removed I-nominated labels Feb 6, 2020
@nikomatsakis
Copy link
Contributor

nikomatsakis commented Feb 6, 2020

@tmandry
Copy link
Member

tmandry commented Feb 7, 2020

It could be. Likely the difference is in the attributes of the probestack function (before that change it was a #[naked] rust function, afterward it was defined in raw assembly).

@brianlock could you try adding the line .hidden __rust_probestack around here?

If that fixes it, it may break it in other environments (e.g. when generating code for a shared vs static library). We'd probably need to thread some new cfg flags through, but I'm not sure if that's actually possible.

The other way is going back to defining the assembly in a naked function, but a bug, probably in rustc, prevented me from doing this the first time.

cc @alexcrichton

@Mark-Simulacrum
Copy link
Member

cc @Amanieu (though they're on vacation this week I believe) on the inline assembly options as potentially relevant for RFC and if they have thoughts on how to fix it for this case

@alexcrichton
Copy link
Member

I would agree with the conclusion that rust-lang/compiler-builtins#328 is the most likely candidate here for a cause of the regression. That being said I have no idea what TEXTREL is, what's happening there to cause it, or how we might fix this.

@Amanieu
Copy link
Member

Amanieu commented Feb 9, 2020

Looking at the objdump output, you can see the difference between the 2019-12-09 and 2019-12-10 nightlies:

2019-12-09:00000000 g     F .text.__rust_probestack	0000002f .hidden __rust_probestack
2019-12-10:00000000 g     F .text.__rust_probestack	00000031 __rust_probestack

The textrel happens because the __rust_probestack has global visibility and can therefore (in theory) be overridden at runtime, e.g. with LD_PRELOAD. This means that the dynamic linker will need to patch the .text section at load time to fix up the call instruction.

As @tmandry suggested, adding .hidden __rust_probestack should fix the problem since the linker will then resolve references to the symbol within the shared library itself.

@tmandry
Copy link
Member

tmandry commented Feb 11, 2020

As @tmandry suggested, adding .hidden __rust_probestack should fix the problem since the linker will then resolve references to the symbol within the shared library itself.

That's probably the correct fix then, I'm just not 100% sure it will work on all targets . If it fails we should see it in CI, though.

tmandry added a commit to tmandry/rust that referenced this issue Feb 11, 2020
This is to fix rust-lang#68794, but it
may break some platforms.
bors added a commit that referenced this issue Feb 11, 2020
[DO NOT MERGE] Try setting __rust_probestack visibility back to hidden

This is to fix #68794, but it may break some platforms. Uploading this change to test in CI.

r? @ghost
@Cogitri
Copy link
Author

Cogitri commented Feb 13, 2020

Will this be released in a 1.41.1, or should distros just apply this downstream? We'd very much like Rust 1.41.0 without TEXTRELs on x86.

@Cogitri
Copy link
Author

Cogitri commented Feb 13, 2020

Also, thanks for the quick fix of course :)

@Mark-Simulacrum
Copy link
Member

I would not currently wait for a 1.41.1 release. I hope that it will make it into 1.42 though.

@Cogitri
Copy link
Author

Cogitri commented Feb 13, 2020

Alright, thanks for the info.

brainlock added a commit to brainlock/rust that referenced this issue Feb 14, 2020
This is a minimal regression test for the issue rust-lang#68794: "TEXTREL in
i686", which was fixed with e86019c.

The test links a minimal rust static library into a shared library, and
checks that the linker didn't have to add the TEXTREL flag.
brainlock added a commit to brainlock/rust that referenced this issue Feb 14, 2020
This is a minimal regression test for the issue rust-lang#68794: "TEXTREL in
i686", which was fixed with e86019c.

The test links a minimal rust static library into a shared library, and
checks that the linker didn't have to add the TEXTREL flag.
@brainlock
Copy link
Contributor

Thanks for fixing this! I verified that this solves the issue on our end, and opened a PR with a simple regression test. The test fails on i686-unknown-linux-gnu when I revert compiler-builtins to 0.1.24.

bors added a commit that referenced this issue Feb 15, 2020
…lacrum,tmandry

add regression test for issue #68794

This is a minimal regression test for the issue #68794: "TEXTREL in
i686", which was fixed with e86019c.

The test links a minimal rust static library into a shared library, and
checks that the linker didn't have to add the TEXTREL flag.
@brainlock
Copy link
Contributor

I'm not sure this is the right place to bring it up, but without this fix it is impossible to deploy a rust static library to platforms that enforce properly-relocatable code (x86 android). It didn't make the cut for 1.41.1, is there any chance for 1.42? Can we help to make this happen?

Thanks!

@mati865
Copy link
Contributor

mati865 commented Mar 2, 2020

#69086 is beta nominated, it will be backported soon and included in 1.42 release.

@brainlock
Copy link
Contributor

#69086 is beta nominated, it will be backported soon and included in 1.42 release.

Fantastic, thanks. Do you think it would be worth it to also include the regression test (#69168) in the release?

@mati865
Copy link
Contributor

mati865 commented Mar 2, 2020

Do you think it would be worth it to also include the regression test (#69168) in the release?

CCing the reviewers @tmandry @Mark-Simulacrum

@awakecoding
Copy link

awesome, I am waiting for a release with this fix. Any idea when 1.42 is planned?

@Cogitri
Copy link
Author

Cogitri commented Mar 2, 2020

Stable releases usually occur every 6 weeks, so it should land in ~2 weeks.

@Mark-Simulacrum
Copy link
Member

I've nominated the regression test as well!

Mark-Simulacrum pushed a commit to Mark-Simulacrum/rust that referenced this issue Mar 6, 2020
This is a minimal regression test for the issue rust-lang#68794: "TEXTREL in
i686", which was fixed with e86019c.

The test links a minimal rust static library into a shared library, and
checks that the linker didn't have to add the TEXTREL flag.
bors added a commit that referenced this issue Mar 6, 2020
[beta] another round of backports for 1.42

This backports the following pull requests:

* Fix a leak in `DiagnosticBuilder::into_diagnostic`. #69628
* stash API: remove panic to fix ICE. #69623
* Do not ICE on invalid type node after parse recovery #69583
* Backport only: avoid ICE on bad placeholder type #69324
* add regression test for issue #68794 #69168
* Update compiler-builtins to 0.1.25 #69086
* Update RELEASES.md for 1.42.0 #68989
@Noratrieb Noratrieb added O-x86_32 Target: x86 processors, 32 bit (like i686-*) and removed O-x86-all labels Oct 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. O-android Operating system: Android O-x86_32 Target: x86 processors, 32 bit (like i686-*) P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet