fortrangoingonforty/afs-ld / 2e63cb5

Browse files

Cover forced thunk sharing

Authored by espadonne
SHA
2e63cb57e89f201faca68600b984ec15352bcaf9
Parents
320ee1c
Tree
b7caac3

1 changed file

StatusFile+-
M tests/linker_run.rs 79 0
tests/linker_run.rsmodified
@@ -4508,6 +4508,85 @@ fn linker_run_safe_thunks_do_not_grow_small_programs() {
4508
     let _ = fs::remove_file(out);
4508
     let _ = fs::remove_file(out);
4509
 }
4509
 }
4510
 
4510
 
4511
+#[test]
4512
+fn linker_run_thunks_all_forces_shared_thunk_for_in_range_calls() {
4513
+    if !have_xcrun() || !have_tool("codesign") {
4514
+        eprintln!("skipping: xcrun or codesign unavailable");
4515
+        return;
4516
+    }
4517
+
4518
+    let obj = scratch("branch26-thunks-all.o");
4519
+    let out = scratch("branch26-thunks-all.out");
4520
+    let src = r#"
4521
+        .section __TEXT,__text,regular,pure_instructions
4522
+        .globl _main
4523
+        _main:
4524
+            stp x29, x30, [sp, #-16]!
4525
+            mov x29, sp
4526
+            bl _helper
4527
+            bl _helper
4528
+            ldp x29, x30, [sp], #16
4529
+            ret
4530
+
4531
+        _helper:
4532
+            mov w0, #0
4533
+            ret
4534
+        .subsections_via_symbols
4535
+    "#;
4536
+    if let Err(e) = assemble(src, &obj) {
4537
+        eprintln!("skipping: assemble failed: {e}");
4538
+        return;
4539
+    }
4540
+
4541
+    let opts = LinkOptions {
4542
+        inputs: vec![obj.clone()],
4543
+        output: Some(out.clone()),
4544
+        kind: OutputKind::Executable,
4545
+        thunks: afs_ld::ThunkMode::All,
4546
+        ..LinkOptions::default()
4547
+    };
4548
+    Linker::run(&opts).unwrap();
4549
+
4550
+    let bytes = fs::read(&out).unwrap();
4551
+    let (text_addr, text) = output_section(&bytes, "__TEXT", "__text").unwrap();
4552
+    let (thunks_addr, thunks) = output_section(&bytes, "__TEXT", "__thunks").unwrap();
4553
+    assert_eq!(
4554
+        thunks.len(),
4555
+        12,
4556
+        "expected both in-range calls to share one forced thunk"
4557
+    );
4558
+    assert_eq!(
4559
+        decode_branch_target(&text, text_addr, 8).unwrap(),
4560
+        thunks_addr,
4561
+        "expected first BL to route through __thunks under -thunks=all"
4562
+    );
4563
+    assert_eq!(
4564
+        decode_branch_target(&text, text_addr, 12).unwrap(),
4565
+        thunks_addr,
4566
+        "expected second BL to share the same thunk target"
4567
+    );
4568
+
4569
+    let verify = Command::new("codesign")
4570
+        .arg("-v")
4571
+        .arg(&out)
4572
+        .output()
4573
+        .unwrap();
4574
+    assert!(
4575
+        verify.status.success(),
4576
+        "codesign verify failed: {}",
4577
+        String::from_utf8_lossy(&verify.stderr)
4578
+    );
4579
+    let status = Command::new(&out).status().unwrap();
4580
+    assert_eq!(
4581
+        status.code(),
4582
+        Some(0),
4583
+        "expected -thunks=all executable to exit 0"
4584
+    );
4585
+
4586
+    let _ = fs::remove_file(obj);
4587
+    let _ = fs::remove_file(out);
4588
+}
4589
+
4511
 #[test]
4590
 #[test]
4512
 fn linker_run_places_thunks_in_caller_segment() {
4591
 fn linker_run_places_thunks_in_caller_segment() {
4513
     if !have_xcrun() || !have_tool("codesign") {
4592
     if !have_xcrun() || !have_tool("codesign") {