Skip to content

Commit 8a72f58

Browse files
committed
pass correct pie args to gcc linker 2
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.
1 parent 1635052 commit 8a72f58

File tree

1 file changed

+23
-43
lines changed

1 file changed

+23
-43
lines changed

src/librustc_trans/back/link.rs

Lines changed: 23 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -652,9 +652,6 @@ fn link_natively(sess: &Session,
652652
prog = time(sess.time_passes(), "running linker", || {
653653
exec_linker(sess, &mut cmd, tmpdir)
654654
});
655-
if !retry_on_segfault || i > 3 {
656-
break
657-
}
658655
let output = match prog {
659656
Ok(ref output) => output,
660657
Err(_) => break,
@@ -665,6 +662,26 @@ fn link_natively(sess: &Session,
665662
let mut out = output.stderr.clone();
666663
out.extend(&output.stdout);
667664
let out = String::from_utf8_lossy(&out);
665+
666+
// Check to see if the link failed with "unrecognized command line option:
667+
// '-no-pie'". If so, reperform the link step without the -no-pie option. This
668+
// is safe because if the linker doesn't support -no-pie then it should not
669+
// default to linking executables as pie. Different versions of gcc seem to
670+
// use different quotes in the error message so don't check for them.
671+
if out.contains("unrecognized command line option") && out.contains("-no-pie") {
672+
info!("linker output: {:?}", out);
673+
warn!("Linker does not support -no-pie command line option. Retrying without.");
674+
for arg in cmd.take_args() {
675+
if arg.to_string_lossy() != "-no-pie" {
676+
cmd.arg(arg);
677+
}
678+
}
679+
info!("{:?}", &cmd);
680+
continue;
681+
}
682+
if !retry_on_segfault || i > 3 {
683+
break
684+
}
668685
let msg_segv = "clang: error: unable to execute command: Segmentation fault: 11";
669686
let msg_bus = "clang: error: unable to execute command: Bus error: 10";
670687
if !(out.contains(msg_segv) || out.contains(msg_bus)) {
@@ -912,18 +929,10 @@ fn link_args(cmd: &mut Linker,
912929
}
913930
}
914931

915-
// Check to see if gcc defaults to generating a position independent
916-
// executable. If so, tell it when to disable pie. Otherwise, tell it
917-
// when to enable it. We can't do both because older versions of gcc
918-
// don't understand -no-pie and will blow up.
919-
if is_pie_default(sess) {
920-
if !position_independent_executable {
921-
cmd.no_position_independent_executable();
922-
}
932+
if position_independent_executable {
933+
cmd.position_independent_executable();
923934
} else {
924-
if position_independent_executable {
925-
cmd.position_independent_executable();
926-
}
935+
cmd.no_position_independent_executable();
927936
}
928937
}
929938

@@ -1438,32 +1447,3 @@ fn is_full_lto_enabled(sess: &Session) -> bool {
14381447
Lto::ThinLocal => false,
14391448
}
14401449
}
1441-
1442-
fn is_pie_default(sess: &Session) -> bool {
1443-
match sess.linker_flavor() {
1444-
LinkerFlavor::Gcc => {
1445-
let (_, mut cmd, envs) = get_linker(sess);
1446-
// This will set PATH on windows
1447-
cmd.envs(envs);
1448-
cmd.arg("-v");
1449-
1450-
info!("{:?}", &cmd);
1451-
1452-
let output = cmd.command()
1453-
.stdout(Stdio::piped()).stderr(Stdio::piped())
1454-
.spawn()
1455-
.unwrap()
1456-
.wait_with_output()
1457-
.unwrap();
1458-
1459-
let ret = String::from_utf8_lossy(&output.stderr)
1460-
.contains("--enable-default-pie");
1461-
1462-
info!("gcc {} compiled with --enable-default-pie",
1463-
if ret { "IS" } else { "is NOT" });
1464-
1465-
ret
1466-
},
1467-
_ => false,
1468-
}
1469-
}

0 commit comments

Comments
 (0)