@@ -3,6 +3,7 @@ use super::command::Command;
3
3
use super :: symbol_export;
4
4
use rustc_span:: symbol:: sym;
5
5
6
+ use std:: env;
6
7
use std:: ffi:: { OsStr , OsString } ;
7
8
use std:: fs:: { self , File } ;
8
9
use std:: io:: prelude:: * ;
@@ -126,7 +127,6 @@ pub fn get_linker<'a>(
126
127
// FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
127
128
// to the linker args construction.
128
129
assert ! ( cmd. get_args( ) . is_empty( ) || sess. target. vendor == "uwp" ) ;
129
-
130
130
match flavor {
131
131
LinkerFlavor :: Lld ( LldFlavor :: Link ) | LinkerFlavor :: Msvc => {
132
132
Box :: new ( MsvcLinker { cmd, sess } ) as Box < dyn Linker >
@@ -149,6 +149,10 @@ pub fn get_linker<'a>(
149
149
LinkerFlavor :: PtxLinker => Box :: new ( PtxLinker { cmd, sess } ) as Box < dyn Linker > ,
150
150
151
151
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
+ } ,
152
156
}
153
157
}
154
158
@@ -1355,6 +1359,172 @@ impl<'a> Linker for WasmLd<'a> {
1355
1359
}
1356
1360
}
1357
1361
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
+
1358
1528
pub ( crate ) fn exported_symbols ( tcx : TyCtxt < ' _ > , crate_type : CrateType ) -> Vec < String > {
1359
1529
if let Some ( ref exports) = tcx. sess . target . override_export_symbols {
1360
1530
return exports. clone ( ) ;
0 commit comments