diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index f050edcd513b9..a84ac5cb8bc2f 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -897,16 +897,33 @@ fn link_args(cmd: &mut Linker, let used_link_args = &trans.crate_info.link_args; - if crate_type == config::CrateTypeExecutable && - t.options.position_independent_executables { - let empty_vec = Vec::new(); - let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec); - let more_args = &sess.opts.cg.link_arg; - let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter()); - - if get_reloc_model(sess) == llvm::RelocMode::PIC - && !sess.crt_static() && !args.any(|x| *x == "-static") { - cmd.position_independent_executable(); + if crate_type == config::CrateTypeExecutable { + let mut position_independent_executable = false; + + if t.options.position_independent_executables { + let empty_vec = Vec::new(); + let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec); + let more_args = &sess.opts.cg.link_arg; + let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter()); + + if get_reloc_model(sess) == llvm::RelocMode::PIC + && !sess.crt_static() && !args.any(|x| *x == "-static") { + position_independent_executable = true; + } + } + + // Check to see if gcc defaults to generating a position independent + // executable. If so, tell it when to disable pie. Otherwise, tell it + // when to enable it. We can't do both because older versions of gcc + // don't understand -no-pie and will blow up. + if is_pie_default(sess) { + if !position_independent_executable { + cmd.no_position_independent_executable(); + } + } else { + if position_independent_executable { + cmd.position_independent_executable(); + } } } @@ -1421,3 +1438,32 @@ fn is_full_lto_enabled(sess: &Session) -> bool { Lto::ThinLocal => false, } } + +fn is_pie_default(sess: &Session) -> bool { + match sess.linker_flavor() { + LinkerFlavor::Gcc => { + let (_, mut cmd, envs) = get_linker(sess); + // This will set PATH on windows + cmd.envs(envs); + cmd.arg("-v"); + + info!("{:?}", &cmd); + + let output = cmd.command() + .stdout(Stdio::piped()).stderr(Stdio::piped()) + .spawn() + .unwrap() + .wait_with_output() + .unwrap(); + + let ret = String::from_utf8_lossy(&output.stderr) + .contains("--enable-default-pie"); + + info!("gcc {} compiled with --enable-default-pie", + if ret { "IS" } else { "is NOT" }); + + ret + }, + _ => false, + } +} diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index aa29c3cc12058..7e7811c56c74e 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -105,6 +105,7 @@ pub trait Linker { fn add_object(&mut self, path: &Path); fn gc_sections(&mut self, keep_metadata: bool); fn position_independent_executable(&mut self); + fn no_position_independent_executable(&mut self); fn partial_relro(&mut self); fn full_relro(&mut self); fn optimize(&mut self); @@ -179,6 +180,7 @@ impl<'a> Linker for GccLinker<'a> { fn output_filename(&mut self, path: &Path) { self.cmd.arg("-o").arg(path); } fn add_object(&mut self, path: &Path) { self.cmd.arg(path); } fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); } + fn no_position_independent_executable(&mut self) { self.cmd.arg("-no-pie"); } fn partial_relro(&mut self) { self.linker_arg("-z,relro"); } fn full_relro(&mut self) { self.linker_arg("-z,relro,-z,now"); } fn build_static_executable(&mut self) { self.cmd.arg("-static"); } @@ -439,6 +441,10 @@ impl<'a> Linker for MsvcLinker<'a> { // noop } + fn no_position_independent_executable(&mut self) { + // noop + } + fn partial_relro(&mut self) { // noop } @@ -647,6 +653,10 @@ impl<'a> Linker for EmLinker<'a> { // noop } + fn no_position_independent_executable(&mut self) { + // noop + } + fn partial_relro(&mut self) { // noop }