fortrangoingonforty/afs-ld / 1eae32b

Browse files

Respect direct address materialization

Authored by espadonne
SHA
1eae32b5b9e0b24c3c0c371cc89cf7490363aeb9
Parents
9454823
Tree
14fc4c3

2 changed files

StatusFile+-
M src/icf.rs 14 7
M tests/linker_run.rs 98 0
src/icf.rsmodified
@@ -3,9 +3,7 @@ use std::fmt;
33
 
44
 use crate::atom::{Atom, AtomFlags, AtomSection, AtomTable};
55
 use crate::layout::LayoutInput;
6
-use crate::reloc::{
7
-    parse_raw_relocs, parse_relocs, Referent, Reloc, RelocKind, RelocLength,
8
-};
6
+use crate::reloc::{parse_raw_relocs, parse_relocs, Referent, Reloc, RelocKind, RelocLength};
97
 use crate::resolve::{AtomId, InputId, Symbol, SymbolId, SymbolTable};
108
 
119
 #[derive(Debug, Clone, Default)]
@@ -227,8 +225,10 @@ fn fold_order_key(
227225
     order_by_input: &HashMap<InputId, (usize, Option<u32>)>,
228226
     atom_id: AtomId,
229227
 ) -> (usize, u32, u32, u32) {
230
-    let (load_order, archive_member_offset) =
231
-        order_by_input.get(&atom.origin).copied().unwrap_or((usize::MAX, None));
228
+    let (load_order, archive_member_offset) = order_by_input
229
+        .get(&atom.origin)
230
+        .copied()
231
+        .unwrap_or((usize::MAX, None));
232232
     (
233233
         load_order,
234234
         archive_member_offset.unwrap_or(0),
@@ -363,6 +363,8 @@ fn marks_address_taken(kind: RelocKind) -> bool {
363363
     matches!(
364364
         kind,
365365
         RelocKind::Unsigned
366
+            | RelocKind::Page21
367
+            | RelocKind::PageOff12
366368
             | RelocKind::PointerToGot
367369
             | RelocKind::GotLoadPage21
368370
             | RelocKind::GotLoadPageOff12
@@ -375,7 +377,9 @@ fn relocs_for_atom<'a>(relocs: &'a [Reloc], atom: &Atom) -> impl Iterator<Item =
375377
     let start = atom.input_offset;
376378
     let end = atom.input_offset.saturating_add(atom.size);
377379
     relocs.iter().copied().filter(move |reloc| {
378
-        let reloc_end = reloc.offset.saturating_add(reloc.length.byte_width() as u32);
380
+        let reloc_end = reloc
381
+            .offset
382
+            .saturating_add(reloc.length.byte_width() as u32);
379383
         reloc.offset >= start && reloc_end <= end
380384
     })
381385
 }
@@ -469,7 +473,10 @@ fn atom_symbols(atom: &Atom) -> impl Iterator<Item = SymbolId> + '_ {
469473
 }
470474
 
471475
 fn symbol_name(sym_table: &SymbolTable, symbol_id: SymbolId) -> String {
472
-    sym_table.interner.resolve(sym_table.get(symbol_id).name()).to_string()
476
+    sym_table
477
+        .interner
478
+        .resolve(sym_table.get(symbol_id).name())
479
+        .to_string()
473480
 }
474481
 
475482
 fn target_atoms_for_reloc(
tests/linker_run.rsmodified
@@ -7051,6 +7051,104 @@ fn linker_run_icf_safe_keeps_address_taken_functions_distinct() {
70517051
     let _ = fs::remove_file(our_out);
70527052
 }
70537053
 
7054
+#[test]
7055
+fn linker_run_icf_safe_keeps_adrp_add_address_taken_functions_distinct() {
7056
+    if !have_xcrun() {
7057
+        eprintln!("skipping: xcrun unavailable");
7058
+        return;
7059
+    };
7060
+
7061
+    let obj = scratch("icf-adrp-address-taken.o");
7062
+    let baseline_out = scratch("icf-adrp-address-taken-baseline.out");
7063
+    let our_out = scratch("icf-adrp-address-taken-ours.out");
7064
+    let src = r#"
7065
+        .section __TEXT,__text,regular,pure_instructions
7066
+        .globl _main
7067
+        _main:
7068
+            stp x29, x30, [sp, #-16]!
7069
+            mov x29, sp
7070
+            adrp x10, _helper1@PAGE
7071
+            add x10, x10, _helper1@PAGEOFF
7072
+            adrp x11, _helper2@PAGE
7073
+            add x11, x11, _helper2@PAGEOFF
7074
+            cmp x10, x11
7075
+            b.ne 1f
7076
+            mov w0, #1
7077
+            ldp x29, x30, [sp], #16
7078
+            ret
7079
+        1:
7080
+            mov w0, #0
7081
+            ldp x29, x30, [sp], #16
7082
+            ret
7083
+
7084
+        .private_extern _helper1
7085
+        _helper1:
7086
+            mov w0, #7
7087
+            ret
7088
+
7089
+        .private_extern _helper2
7090
+        _helper2:
7091
+            mov w0, #7
7092
+            ret
7093
+        .subsections_via_symbols
7094
+    "#;
7095
+    if let Err(e) = assemble(src, &obj) {
7096
+        eprintln!("skipping: assemble failed: {e}");
7097
+        return;
7098
+    }
7099
+
7100
+    let baseline_opts = LinkOptions {
7101
+        inputs: vec![obj.clone()],
7102
+        output: Some(baseline_out.clone()),
7103
+        kind: OutputKind::Executable,
7104
+        ..LinkOptions::default()
7105
+    };
7106
+    Linker::run(&baseline_opts).unwrap();
7107
+
7108
+    let opts = LinkOptions {
7109
+        inputs: vec![obj.clone()],
7110
+        output: Some(our_out.clone()),
7111
+        kind: OutputKind::Executable,
7112
+        icf_mode: afs_ld::IcfMode::Safe,
7113
+        ..LinkOptions::default()
7114
+    };
7115
+    Linker::run(&opts).unwrap();
7116
+
7117
+    let baseline_bytes = fs::read(&baseline_out).unwrap();
7118
+    let our_bytes = fs::read(&our_out).unwrap();
7119
+    let baseline_symbols = symbol_values(&baseline_bytes);
7120
+    let our_symbols = symbol_values(&our_bytes);
7121
+    let baseline_text = output_section(&baseline_bytes, "__TEXT", "__text")
7122
+        .unwrap()
7123
+        .1;
7124
+    let our_text = output_section(&our_bytes, "__TEXT", "__text").unwrap().1;
7125
+
7126
+    assert_ne!(
7127
+        our_symbols.get("_helper1"),
7128
+        our_symbols.get("_helper2"),
7129
+        "adrp/add address-taken helpers should not be folded by afs-ld -icf=safe"
7130
+    );
7131
+    assert_ne!(
7132
+        baseline_symbols.get("_helper1"),
7133
+        baseline_symbols.get("_helper2"),
7134
+        "baseline link should keep adrp/add address-taken helpers separate"
7135
+    );
7136
+    assert_eq!(
7137
+        Command::new(&our_out).status().unwrap().code(),
7138
+        Some(0),
7139
+        "adrp/add address-taken executable should preserve pointer inequality"
7140
+    );
7141
+    assert_eq!(
7142
+        our_text.len(),
7143
+        baseline_text.len(),
7144
+        "adrp/add address-taken helpers should not shrink under -icf=safe"
7145
+    );
7146
+
7147
+    let _ = fs::remove_file(obj);
7148
+    let _ = fs::remove_file(baseline_out);
7149
+    let _ = fs::remove_file(our_out);
7150
+}
7151
+
70547152
 #[test]
70557153
 fn linker_run_icf_safe_folds_matching_branch_relocs() {
70567154
     if !have_xcrun() {