about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJimmy Brush <code@jimmah.com>2018-02-10 13:16:59 -0500
committerJimmy Brush <code@jimmah.com>2018-02-13 22:10:26 -0500
commit8a72f589e5f8d628a5dcfcedbdd8eec117fbe2a2 (patch)
tree747884289dd4b8bd2713eaa562e77976f972b003 /src
parent16350526d8d8b514327c62b904d26f74937a1b23 (diff)
downloadrust-8a72f589e5f8d628a5dcfcedbdd8eec117fbe2a2.tar.gz
rust-8a72f589e5f8d628a5dcfcedbdd8eec117fbe2a2.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_trans/back/link.rs66
1 files changed, 23 insertions, 43 deletions
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index a84ac5cb8bc..d15450212ae 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -652,9 +652,6 @@ fn link_natively(sess: &Session,
         prog = time(sess.time_passes(), "running linker", || {
             exec_linker(sess, &mut cmd, tmpdir)
         });
-        if !retry_on_segfault || i > 3 {
-            break
-        }
         let output = match prog {
             Ok(ref output) => output,
             Err(_) => break,
@@ -665,6 +662,26 @@ fn link_natively(sess: &Session,
         let mut out = output.stderr.clone();
         out.extend(&output.stdout);
         let out = String::from_utf8_lossy(&out);
+
+        // Check to see if the link failed with "unrecognized command line option:
+        // '-no-pie'". If so, reperform the link step without the -no-pie option. This
+        // 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") {
+            info!("linker output: {:?}", out);
+            warn!("Linker does not support -no-pie command line option. Retrying without.");
+            for arg in cmd.take_args() {
+                if arg.to_string_lossy() != "-no-pie" {
+                    cmd.arg(arg);
+                }
+            }
+            info!("{:?}", &cmd);
+            continue;
+        }
+        if !retry_on_segfault || i > 3 {
+            break
+        }
         let msg_segv = "clang: error: unable to execute command: Segmentation fault: 11";
         let msg_bus  = "clang: error: unable to execute command: Bus error: 10";
         if !(out.contains(msg_segv) || out.contains(msg_bus)) {
@@ -912,18 +929,10 @@ fn link_args(cmd: &mut Linker,
             }
         }
 
-        // 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();
-            }
+        if position_independent_executable {
+            cmd.position_independent_executable();
         } else {
-            if position_independent_executable {
-                cmd.position_independent_executable();
-            }
+            cmd.no_position_independent_executable();
         }
     }
 
@@ -1438,32 +1447,3 @@ 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,
-    }
-}