Skip to content

Commit 725856d

Browse files
authored
Rollup merge of rust-lang#48076 - canarysnort01:fix_pie, r=alexcrichton
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
2 parents e253224 + ab9cae1 commit 725856d

File tree

3 files changed

+62
-12
lines changed

3 files changed

+62
-12
lines changed

Diff for: src/librustc_trans/back/command.rs

+4
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ impl Command {
109109

110110
// extensions
111111

112+
pub fn get_args(&self) -> &[OsString] {
113+
&self.args
114+
}
115+
112116
pub fn take_args(&mut self) -> Vec<OsString> {
113117
mem::replace(&mut self.args, Vec::new())
114118
}

Diff for: src/librustc_trans/back/link.rs

+48-12
Original file line numberDiff line numberDiff line change
@@ -700,9 +700,6 @@ fn link_natively(sess: &Session,
700700
prog = time(sess.time_passes(), "running linker", || {
701701
exec_linker(sess, &mut cmd, tmpdir)
702702
});
703-
if !retry_on_segfault || i > 3 {
704-
break
705-
}
706703
let output = match prog {
707704
Ok(ref output) => output,
708705
Err(_) => break,
@@ -713,6 +710,31 @@ fn link_natively(sess: &Session,
713710
let mut out = output.stderr.clone();
714711
out.extend(&output.stdout);
715712
let out = String::from_utf8_lossy(&out);
713+
714+
// Check to see if the link failed with "unrecognized command line option:
715+
// '-no-pie'" for gcc or "unknown argument: '-no-pie'" for clang. If so,
716+
// reperform the link step without the -no-pie option. This is safe because
717+
// if the linker doesn't support -no-pie then it should not default to
718+
// linking executables as pie. Different versions of gcc seem to use
719+
// different quotes in the error message so don't check for them.
720+
if sess.target.target.options.linker_is_gnu &&
721+
(out.contains("unrecognized command line option") ||
722+
out.contains("unknown argument")) &&
723+
out.contains("-no-pie") &&
724+
cmd.get_args().iter().any(|e| e.to_string_lossy() == "-no-pie") {
725+
info!("linker output: {:?}", out);
726+
warn!("Linker does not support -no-pie command line option. Retrying without.");
727+
for arg in cmd.take_args() {
728+
if arg.to_string_lossy() != "-no-pie" {
729+
cmd.arg(arg);
730+
}
731+
}
732+
info!("{:?}", &cmd);
733+
continue;
734+
}
735+
if !retry_on_segfault || i > 3 {
736+
break
737+
}
716738
let msg_segv = "clang: error: unable to execute command: Segmentation fault: 11";
717739
let msg_bus = "clang: error: unable to execute command: Bus error: 10";
718740
if !(out.contains(msg_segv) || out.contains(msg_bus)) {
@@ -949,16 +971,30 @@ fn link_args(cmd: &mut Linker,
949971

950972
let used_link_args = &trans.crate_info.link_args;
951973

952-
if crate_type == config::CrateTypeExecutable &&
953-
t.options.position_independent_executables {
954-
let empty_vec = Vec::new();
955-
let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec);
956-
let more_args = &sess.opts.cg.link_arg;
957-
let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter());
958-
959-
if get_reloc_model(sess) == llvm::RelocMode::PIC
960-
&& !sess.crt_static() && !args.any(|x| *x == "-static") {
974+
if crate_type == config::CrateTypeExecutable {
975+
let mut position_independent_executable = false;
976+
977+
if t.options.position_independent_executables {
978+
let empty_vec = Vec::new();
979+
let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec);
980+
let more_args = &sess.opts.cg.link_arg;
981+
let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter());
982+
983+
if get_reloc_model(sess) == llvm::RelocMode::PIC
984+
&& !sess.crt_static() && !args.any(|x| *x == "-static") {
985+
position_independent_executable = true;
986+
}
987+
}
988+
989+
if position_independent_executable {
961990
cmd.position_independent_executable();
991+
} else {
992+
// recent versions of gcc can be configured to generate position
993+
// independent executables by default. We have to pass -no-pie to
994+
// explicitly turn that off.
995+
if sess.target.target.options.linker_is_gnu {
996+
cmd.no_position_independent_executable();
997+
}
962998
}
963999
}
9641000

Diff for: src/librustc_trans/back/linker.rs

+10
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ pub trait Linker {
105105
fn add_object(&mut self, path: &Path);
106106
fn gc_sections(&mut self, keep_metadata: bool);
107107
fn position_independent_executable(&mut self);
108+
fn no_position_independent_executable(&mut self);
108109
fn partial_relro(&mut self);
109110
fn full_relro(&mut self);
110111
fn optimize(&mut self);
@@ -179,6 +180,7 @@ impl<'a> Linker for GccLinker<'a> {
179180
fn output_filename(&mut self, path: &Path) { self.cmd.arg("-o").arg(path); }
180181
fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
181182
fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); }
183+
fn no_position_independent_executable(&mut self) { self.cmd.arg("-no-pie"); }
182184
fn partial_relro(&mut self) { self.linker_arg("-z,relro"); }
183185
fn full_relro(&mut self) { self.linker_arg("-z,relro,-z,now"); }
184186
fn build_static_executable(&mut self) { self.cmd.arg("-static"); }
@@ -439,6 +441,10 @@ impl<'a> Linker for MsvcLinker<'a> {
439441
// noop
440442
}
441443

444+
fn no_position_independent_executable(&mut self) {
445+
// noop
446+
}
447+
442448
fn partial_relro(&mut self) {
443449
// noop
444450
}
@@ -647,6 +653,10 @@ impl<'a> Linker for EmLinker<'a> {
647653
// noop
648654
}
649655

656+
fn no_position_independent_executable(&mut self) {
657+
// noop
658+
}
659+
650660
fn partial_relro(&mut self) {
651661
// noop
652662
}

0 commit comments

Comments
 (0)