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

pass correct pie args to gcc linker #48076

Merged
merged 5 commits into from
Feb 25, 2018
Merged

Conversation

canarysnort01
Copy link
Contributor

When linking with gcc, run gcc -v to see if --enable-default-pie is
compiled in. If it is, pass -no-pie when necessary to disable pie.
Otherwise, pass -pie when necessary to enable it.

Fixes #48032 and fixes #35061

@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @eddyb (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@nagisa
Copy link
Member

nagisa commented Feb 8, 2018

Can we pass the -no-pie and -pie always, without checking for the gcc?

@canarysnort01
Copy link
Contributor Author

no, the -no-pie flag will cause older versions of gcc to error out because it doesn't recognize the flag.

@eddyb
Copy link
Member

eddyb commented Feb 8, 2018

r? @alexcrichton

@rust-highfive rust-highfive assigned alexcrichton and unassigned eddyb Feb 8, 2018
@arazabishov arazabishov added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 8, 2018
@alexcrichton
Copy link
Member

Thanks for the PR @canarysnort01! Would it be possible to avoid running gcc --version to figure out if it supports this though? This looks like it'd by default unconditionally run gcc --version on all platforms for all executables, right?

@canarysnort01
Copy link
Contributor Author

Yes, this would run the version check on all platforms on all executables when the link step is configured to use gcc. The benefit here is we know for sure how gcc is configured and we're doing the right thing.

An alternative approach would be:

  1. Do like @nagisa said and always pass -pie or -no-pie
  2. Check if gcc fails when we pass -no-pie
  3. If so, check if stderr contains unrecognized command line option ‘-no-pie’
  4. If so, restart the link step without the -no-pie argument, making the assumption that gcc doesn't have --enable-default-pie, which seems like a valid assumption to make.

The benefit to this approach would be the user only has to pay for the extra linker invocation when it is actually necessary, and would get used less and less as the user base upgrades gcc.

@alexcrichton
Copy link
Member

When was -no-pie added to gcc? Was it recently?

@canarysnort01
Copy link
Contributor Author

According to https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=867853 around gcc 5.3, so a couple years, although it doesn't appear to have been documented until 6.1. The gcc 6.3 in debian stable (stretch) accepts -no-pie, but the gcc in debian oldstable (jessie) (I think 4.8) does not.

@alexcrichton
Copy link
Member

Ok thanks for the info! I think that sounds like a reasonable approach in that case. I believe by default all Rust executables are pie and so it won't hit the "slow path" anyway, but in those cases it does then a gcc upgrade should do it!

// is safe because if the linker doesn't support -no-pie then it should not
// default to linking executables as pie. Different versions of gcc seem to
// use different quotes in the error message so don't check for them.
if out.contains("unrecognized command line option") && out.contains("-no-pie") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To help prevent an accidental infinite loop, could this also have a clause that the cmd has an argument of -no-pie in it?

@alexcrichton
Copy link
Member

@bors: r+

@bors
Copy link
Contributor

bors commented Feb 11, 2018

📌 Commit bc82fec has been approved by alexcrichton

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 11, 2018
@kennytm
Copy link
Member

kennytm commented Feb 12, 2018

@bors r-

Failed on macOS (x86_64-apple-darwin). (Note that on macOS, gcc is an alias of clang.)

[00:50:12]    Compiling smallvec v0.6.0
[00:50:12] error: linking with `cc` failed: exit code: 1
[00:50:12]   |
[00:50:12]   = note: "cc" "-m64" "-L" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1-rustc/release/build/rustc-4f5f147d2791f6cc/build_script_build-4f5f147d2791f6cc.build_script_build0-4bc55960443ab03659164fb01578882c.rs.rcgu.o" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1-rustc/release/build/rustc-4f5f147d2791f6cc/build_script_build-4f5f147d2791f6cc.build_script_build1-4bc55960443ab03659164fb01578882c.rs.rcgu.o" "-o" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1-rustc/release/build/rustc-4f5f147d2791f6cc/build_script_build-4f5f147d2791f6cc" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1-rustc/release/build/rustc-4f5f147d2791f6cc/build_script_build-4f5f147d2791f6cc.crate.allocator.rcgu.o" "-Wl,-dead_strip" "-no-pie" "-nodefaultlibs" "-L" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1-rustc/release/deps" "-L" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libstd-b6e500af6452e0a0.rlib" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-3528cd949b3bc67b.rlib" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/liballoc_jemalloc-62f3c8961bd8f6ac.rlib" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libunwind-84ae26c870c8d23a.rlib" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/liballoc_system-9c91e2a7474fac77.rlib" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/liblibc-e5643cf30768d91d.rlib" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/liballoc-52f38c4b90af6884.rlib" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libstd_unicode-a24b64a7dffe4b1c.rlib" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libcore-37c193a05e2b91ed.rlib" "/Users/travis/build/rust-lang/rust/build/x86_64-apple-darwin/stage1/lib/rustlib/x86_64-apple-darwin/lib/libcompiler_builtins-aa4abcbca82f4be1.rlib" "-l" "System" "-l" "resolv" "-l" "pthread" "-l" "c" "-l" "m"
[00:50:12]   = note: clang: error: unknown argument: '-no-pie'
[00:50:12]           
[00:50:12] 
[00:50:12] error: aborting due to previous error
[00:50:12] 
[00:50:12] error: Could not compile `rustc`.

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Feb 12, 2018
// is safe because if the linker doesn't support -no-pie then it should not
// default to linking executables as pie. Different versions of gcc seem to
// use different quotes in the error message so don't check for them.
if out.contains("unrecognized command line option") &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should check for "error: unknown argument" as well.

@alexcrichton
Copy link
Member

Since this probably isn't applicable to OSX as well, could this logic only get triggered on unix targets?

@canarysnort01
Copy link
Contributor Author

@alexcrichton IIUC you want to check if the target is an OSX target and, if so, never issue the -no-pie argument at all?

It looks like clang might follow in gcc's footsteps in this respect, here's an open issue to do just that: https://bugs.llvm.org/show_bug.cgi?id=13410

Also, it looks like -no-pie was added in clang 5.0 as a no-op for compatibility: https://reviews.llvm.org/rL308268

I'm concerned if we add this exception and osx upgrades/patches their clang to default to pie it will break.

@alexcrichton
Copy link
Member

Is the -pie and/or -no-pie argument recognized on OSX? The fact that this caused a failure on CI (where everything we build should be "as position independent as possible") is pretty worrying. In theory, despite changes here, we shouldn't hit an error in CI

@canarysnort01
Copy link
Contributor Author

Ah I think see where you are coming from now. I was thinking the build failure from @kennytm was from the test suite like in #47037 which I would expect to hit this code path, but iiuc now all builds on OSX failed. (I don't have a mac to test with).

Which makes sense now that I see that position-independent-executables isn't set in OSX's target or the mac base target.

Which leads back to does pie mean anything on OSX... hmm good question.

@canarysnort01
Copy link
Contributor Author

I don't have an answer yet, but I think one option to address this would be to make position-independent-executables have three possible values: yes, no, default.

  • Yes would pass -pie
  • No would pass -no-pie and hit the new code in this PR
  • Default would not pass any argument to the linker and take whatever it's default is

@alexcrichton
Copy link
Member

Invoking the linker tends to be a fickle beast so it's often best to leave it as is unless we need to change it, so perhaps a flag could be added to only pass the flag when linker_is_gnu?

@canarysnort01
Copy link
Contributor Author

That seems like a reasonable solution.

When linking with gcc, run gcc -v to see if --enable-default-pie is
compiled in. If it is, pass -no-pie when necessary to disable pie.
Otherwise, pass -pie when necessary to enable it.

Fixes rust-lang#48032 and fixes rust-lang#35061
Recent versions of gcc default to creating a position independent
executable and must be explicitly told not to with the -no-pie argument.

Old versions of gcc don't understand -no-pie and will throw an error.
Check for that case and retry without -no-pie. This is safe because
these old versions of gcc should never default to creating a position
independent executable.
@canarysnort01
Copy link
Contributor Author

Should I update this PR description to the current solution? Is that what gets put in the merge commit description?

@canarysnort01
Copy link
Contributor Author

@alexcrichton this pr will conflict with #48125

@kennytm kennytm added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 14, 2018
@alexcrichton
Copy link
Member

@bors: r+

Ah that's fine! We can see how @bors arbitrates

@bors
Copy link
Contributor

bors commented Feb 14, 2018

📌 Commit ab9cae1 has been approved by alexcrichton

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 14, 2018
@kennytm kennytm added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Feb 21, 2018
kennytm added a commit to kennytm/rust that referenced this pull request Feb 25, 2018
pass correct pie args to gcc linker

When linking with gcc, run gcc -v to see if --enable-default-pie is
compiled in. If it is, pass -no-pie when necessary to disable pie.
Otherwise, pass -pie when necessary to enable it.

Fixes rust-lang#48032 and fixes rust-lang#35061
bors added a commit that referenced this pull request Feb 25, 2018
Rollup of 17 pull requests

- Successful merges: #47964, #47970, #48076, #48115, #48166, #48281, #48297, #48302, #48362, #48369, #48489, #48491, #48494, #48517, #48529, #48235, #48330
- Failed merges:
@bors bors merged commit ab9cae1 into rust-lang:master Feb 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
8 participants