@@ -12,7 +12,7 @@ use rustc_session::utils::NativeLibKind;
1212/// need out of the shared crate context before we get rid of it.
1313use rustc_session:: { filesearch, Session } ;
1414use rustc_span:: symbol:: Symbol ;
15- use rustc_target:: spec:: crt_objects:: CrtObjectsFallback ;
15+ use rustc_target:: spec:: crt_objects:: { CrtObjects , CrtObjectsFallback } ;
1616use rustc_target:: spec:: { LinkOutputKind , LinkerFlavor , LldFlavor } ;
1717use rustc_target:: spec:: { PanicStrategy , RelocModel , RelroLevel } ;
1818
@@ -25,16 +25,10 @@ use crate::{looks_like_rust_object_file, CodegenResults, CrateInfo, METADATA_FIL
2525use cc:: windows_registry;
2626use tempfile:: { Builder as TempFileBuilder , TempDir } ;
2727
28- use std:: ascii;
29- use std:: char;
30- use std:: env;
3128use std:: ffi:: OsString ;
32- use std:: fmt;
33- use std:: fs;
34- use std:: io;
3529use std:: path:: { Path , PathBuf } ;
3630use std:: process:: { ExitStatus , Output , Stdio } ;
37- use std:: str;
31+ use std:: { ascii , char , env , fmt , fs , io , mem , str} ;
3832
3933pub fn remove ( sess : & Session , path : & Path ) {
4034 if let Err ( e) = fs:: remove_file ( path) {
@@ -543,6 +537,61 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
543537 continue ;
544538 }
545539
540+ // Detect '-static-pie' used with an older version of gcc or clang not supporting it.
541+ // Fallback from '-static-pie' to '-static' in that case.
542+ if sess. target . target . options . linker_is_gnu
543+ && flavor != LinkerFlavor :: Ld
544+ && ( out. contains ( "unrecognized command line option" )
545+ || out. contains ( "unknown argument" ) )
546+ && ( out. contains ( "-static-pie" ) || out. contains ( "--no-dynamic-linker" ) )
547+ && cmd. get_args ( ) . iter ( ) . any ( |e| e. to_string_lossy ( ) == "-static-pie" )
548+ {
549+ info ! ( "linker output: {:?}" , out) ;
550+ warn ! (
551+ "Linker does not support -static-pie command line option. Retrying with -static instead."
552+ ) ;
553+ // Mirror `add_(pre,post)_link_objects` to replace CRT objects.
554+ let fallback = crt_objects_fallback ( sess, crate_type) ;
555+ let opts = & sess. target . target . options ;
556+ let pre_objects =
557+ if fallback { & opts. pre_link_objects_fallback } else { & opts. pre_link_objects } ;
558+ let post_objects =
559+ if fallback { & opts. post_link_objects_fallback } else { & opts. post_link_objects } ;
560+ let get_objects = |objects : & CrtObjects , kind| {
561+ objects
562+ . get ( & kind)
563+ . iter ( )
564+ . copied ( )
565+ . flatten ( )
566+ . map ( |obj| get_object_file_path ( sess, obj) . into_os_string ( ) )
567+ . collect :: < Vec < _ > > ( )
568+ } ;
569+ let pre_objects_static_pie = get_objects ( pre_objects, LinkOutputKind :: StaticPicExe ) ;
570+ let post_objects_static_pie = get_objects ( post_objects, LinkOutputKind :: StaticPicExe ) ;
571+ let mut pre_objects_static = get_objects ( pre_objects, LinkOutputKind :: StaticNoPicExe ) ;
572+ let mut post_objects_static = get_objects ( post_objects, LinkOutputKind :: StaticNoPicExe ) ;
573+ // Assume that we know insertion positions for the replacement arguments from replaced
574+ // arguments, which is true for all supported targets.
575+ assert ! ( pre_objects_static. is_empty( ) || !pre_objects_static_pie. is_empty( ) ) ;
576+ assert ! ( post_objects_static. is_empty( ) || !post_objects_static_pie. is_empty( ) ) ;
577+ for arg in cmd. take_args ( ) {
578+ if arg. to_string_lossy ( ) == "-static-pie" {
579+ // Replace the output kind.
580+ cmd. arg ( "-static" ) ;
581+ } else if pre_objects_static_pie. contains ( & arg) {
582+ // Replace the pre-link objects (replace the first and remove the rest).
583+ cmd. args ( mem:: take ( & mut pre_objects_static) ) ;
584+ } else if post_objects_static_pie. contains ( & arg) {
585+ // Replace the post-link objects (replace the first and remove the rest).
586+ cmd. args ( mem:: take ( & mut post_objects_static) ) ;
587+ } else {
588+ cmd. arg ( arg) ;
589+ }
590+ }
591+ info ! ( "{:?}" , & cmd) ;
592+ continue ;
593+ }
594+
546595 // Here's a terribly awful hack that really shouldn't be present in any
547596 // compiler. Here an environment variable is supported to automatically
548597 // retry the linker invocation if the linker looks like it segfaulted.
0 commit comments