@@ -3,6 +3,7 @@ use super::command::Command;
33use super :: symbol_export;
44use rustc_span:: symbol:: sym;
55
6+ use std:: env;
67use std:: ffi:: { OsStr , OsString } ;
78use std:: fs:: { self , File } ;
89use std:: io:: prelude:: * ;
@@ -126,7 +127,6 @@ pub fn get_linker<'a>(
126127 // FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
127128 // to the linker args construction.
128129 assert ! ( cmd. get_args( ) . is_empty( ) || sess. target. vendor == "uwp" ) ;
129-
130130 match flavor {
131131 LinkerFlavor :: Lld ( LldFlavor :: Link ) | LinkerFlavor :: Msvc => {
132132 Box :: new ( MsvcLinker { cmd, sess } ) as Box < dyn Linker >
@@ -149,6 +149,10 @@ pub fn get_linker<'a>(
149149 LinkerFlavor :: PtxLinker => Box :: new ( PtxLinker { cmd, sess } ) as Box < dyn Linker > ,
150150
151151 LinkerFlavor :: BpfLinker => Box :: new ( BpfLinker { cmd, sess } ) as Box < dyn Linker > ,
152+
153+ LinkerFlavor :: L4Bender => {
154+ Box :: new ( L4Bender :: new ( cmd, sess) ) as Box < dyn Linker >
155+ } ,
152156 }
153157}
154158
@@ -1355,6 +1359,172 @@ impl<'a> Linker for WasmLd<'a> {
13551359 }
13561360}
13571361
1362+ /// Linker shepherd script for L4Re (Fiasco)
1363+ pub struct L4Bender < ' a > {
1364+ cmd : Command ,
1365+ sess : & ' a Session ,
1366+ hinted_static : bool ,
1367+ }
1368+
1369+ impl < ' a > Linker for L4Bender < ' a > {
1370+ fn link_dylib ( & mut self , _lib : Symbol ) {
1371+ panic ! ( "dylibs not supported yet" )
1372+ }
1373+ fn link_staticlib ( & mut self , lib : Symbol ) {
1374+ self . hint_static ( ) ;
1375+ self . cmd . arg ( format ! ( "-PC{}" , lib) ) ;
1376+ }
1377+ fn link_rlib ( & mut self , lib : & Path ) {
1378+ self . hint_static ( ) ;
1379+ self . cmd . arg ( lib) ;
1380+ }
1381+ fn include_path ( & mut self , path : & Path ) {
1382+ self . cmd . arg ( "-L" ) . arg ( path) ;
1383+ }
1384+ fn framework_path ( & mut self , _: & Path ) {
1385+ bug ! ( "Frameworks are not supported on L4Re!" ) ;
1386+ }
1387+ fn output_filename ( & mut self , path : & Path ) { self . cmd . arg ( "-o" ) . arg ( path) ; }
1388+ fn add_object ( & mut self , path : & Path ) { self . cmd . arg ( path) ; }
1389+ // not sure about pie on L4Re
1390+ fn position_independent_executable ( & mut self ) { }
1391+ fn no_position_independent_executable ( & mut self ) { }
1392+ fn full_relro ( & mut self ) { self . cmd . arg ( "-z,relro,-z,now" ) ; }
1393+ fn partial_relro ( & mut self ) { self . cmd . arg ( "-z,relro" ) ; }
1394+ fn no_relro ( & mut self ) { self . cmd . arg ( "-z,norelro" ) ; }
1395+ fn build_static_executable ( & mut self ) { self . cmd . arg ( "-static" ) ; }
1396+ fn cmd ( & mut self ) -> & mut Command {
1397+ & mut self . cmd
1398+ }
1399+
1400+ fn link_rust_dylib ( & mut self , _: Symbol , _: & Path ) {
1401+ panic ! ( "Rust dylibs not supported" ) ;
1402+ }
1403+
1404+ fn link_framework ( & mut self , _: Symbol ) {
1405+ bug ! ( "Frameworks not supported on L4Re." ) ;
1406+ }
1407+
1408+ // Here we explicitly ask that the entire archive is included into the
1409+ // result artifact. For more details see #15460, but the gist is that
1410+ // the linker will strip away any unused objects in the archive if we
1411+ // don't otherwise explicitly reference them. This can occur for
1412+ // libraries which are just providing bindings, libraries with generic
1413+ // functions, etc.
1414+ fn link_whole_staticlib ( & mut self , lib : Symbol , _: & [ PathBuf ] ) {
1415+ self . hint_static ( ) ;
1416+ self . cmd . arg ( "--whole-archive" ) . arg ( format ! ( "-l{}" , lib) ) ;
1417+ self . cmd . arg ( "--no-whole-archive" ) ;
1418+ }
1419+
1420+ fn link_whole_rlib ( & mut self , lib : & Path ) {
1421+ self . hint_static ( ) ;
1422+ self . cmd . arg ( "--whole-archive" ) . arg ( lib) . arg ( "--no-whole-archive" ) ;
1423+ }
1424+
1425+ fn gc_sections ( & mut self , keep_metadata : bool ) {
1426+ if !keep_metadata {
1427+ self . cmd . arg ( "--gc-sections" ) ;
1428+ }
1429+ }
1430+
1431+ fn optimize ( & mut self ) {
1432+ self . cmd . arg ( "-O2" ) ;
1433+ }
1434+
1435+ fn pgo_gen ( & mut self ) { }
1436+
1437+ fn debuginfo ( & mut self , strip : Strip ) {
1438+ match strip {
1439+ Strip :: None => { }
1440+ Strip :: Debuginfo => {
1441+ self . cmd ( ) . arg ( "--strip-debug" ) ; }
1442+ Strip :: Symbols => {
1443+ self . cmd ( ) . arg ( "--strip-all" ) ;
1444+ }
1445+ }
1446+ }
1447+
1448+ fn no_default_libraries ( & mut self ) {
1449+ self . cmd . arg ( "-nostdlib" ) ;
1450+ }
1451+
1452+ fn build_dylib ( & mut self , _: & Path ) {
1453+ bug ! ( "not implemented" ) ;
1454+ }
1455+
1456+ fn export_symbols ( & mut self , _: & Path , _: CrateType ) {
1457+ // ToDo, not implemented, copy from GCC
1458+ return ;
1459+ }
1460+
1461+ fn subsystem ( & mut self , subsystem : & str ) {
1462+ self . cmd . arg ( & format ! ( "--subsystem,{}" , subsystem) ) ;
1463+ }
1464+
1465+ fn finalize ( & mut self ) {
1466+ self . hint_static ( ) ; // Reset to default before returning the composed command line.
1467+ }
1468+
1469+ fn group_start ( & mut self ) { self . cmd . arg ( "--start-group" ) ; }
1470+ fn group_end ( & mut self ) { self . cmd . arg ( "--end-group" ) ; }
1471+ fn linker_plugin_lto ( & mut self ) {
1472+ // do nothing
1473+ }
1474+ fn control_flow_guard ( & mut self ) {
1475+ self . sess . warn ( "Windows Control Flow Guard is not supported by this linker." ) ;
1476+ }
1477+
1478+ fn no_crt_objects ( & mut self ) { }
1479+ }
1480+
1481+ impl < ' a > L4Bender < ' a > {
1482+ pub fn new ( mut cmd : Command , sess : & ' a Session ) -> L4Bender < ' a > {
1483+ if let Ok ( l4bender_args) = env:: var ( "L4_BENDER_ARGS" ) {
1484+ L4Bender :: split_cmd_args ( & mut cmd, & l4bender_args) ;
1485+ }
1486+
1487+ cmd. arg ( "--" ) ; // separate direct l4-bender args from linker args
1488+
1489+ L4Bender {
1490+ cmd : cmd,
1491+ sess : sess,
1492+ hinted_static : false ,
1493+ }
1494+ }
1495+
1496+ /// This parses a shell-escaped string and unquotes the arguments. It doesn't attempt to
1497+ /// completely understand shell, but should instead allow passing arguments like
1498+ /// `-Dlinker="ld -m x86_64"`, and a copy without quotes, but spaces preserved, is added as an
1499+ /// argument to the given Command. This means that constructs as \" are not understood, so
1500+ /// quote wisely.
1501+ fn split_cmd_args ( cmd : & mut Command , shell_args : & str ) {
1502+ let mut arg = String :: new ( ) ;
1503+ let mut quoted = false ;
1504+ for character in shell_args. chars ( ) {
1505+ match character {
1506+ ' ' if !quoted => {
1507+ cmd. arg ( & arg) ;
1508+ arg. clear ( ) ;
1509+ } ,
1510+ '"' | '\'' => quoted = !quoted,
1511+ _ => arg. push ( character) ,
1512+ } ;
1513+ }
1514+ if arg. len ( ) > 0 {
1515+ cmd. arg ( & arg) ;
1516+ arg. clear ( ) ;
1517+ }
1518+ }
1519+
1520+ fn hint_static ( & mut self ) {
1521+ if !self . hinted_static {
1522+ self . cmd . arg ( "-static" ) ;
1523+ self . hinted_static = true ;
1524+ }
1525+ }
1526+ }
1527+
13581528pub ( crate ) fn exported_symbols ( tcx : TyCtxt < ' _ > , crate_type : CrateType ) -> Vec < String > {
13591529 if let Some ( ref exports) = tcx. sess . target . override_export_symbols {
13601530 return exports. clone ( ) ;
0 commit comments