fortrangoingonforty/afs-ld / 72e7349

Browse files

Match Apple ld load commands

Authored by espadonne
SHA
72e7349ce2cf10e95854d9a0550d31531ed212f4
Parents
f277ac8
Tree
9e96d71

2 changed files

StatusFile+-
M src/macho/writer.rs 6 6
M tests/load_command_parity.rs 101 28
src/macho/writer.rsmodified
@@ -477,12 +477,6 @@ fn build_commands(
477477
         }
478478
     }
479479
 
480
-    for rpath in &opts.rpaths {
481
-        commands.push(LoadCommand::Rpath(RpathCmd {
482
-            path: rpath.clone(),
483
-        }));
484
-    }
485
-
486480
     for dylib in dylibs {
487481
         commands.push(LoadCommand::Dylib(DylibCmd {
488482
             cmd: dylib.kind.load_cmd(),
@@ -493,6 +487,12 @@ fn build_commands(
493487
         }));
494488
     }
495489
 
490
+    for rpath in &opts.rpaths {
491
+        commands.push(LoadCommand::Rpath(RpathCmd {
492
+            path: rpath.clone(),
493
+        }));
494
+    }
495
+
496496
     if let Some(loh) = linkedit.loh {
497497
         commands.push(raw_linkedit_command(
498498
             LC_LINKER_OPTIMIZATION_HINT,
tests/load_command_parity.rsmodified
@@ -23,6 +23,26 @@ fn have_clang() -> bool {
2323
         .unwrap_or(false)
2424
 }
2525
 
26
+fn have_ld() -> bool {
27
+    Command::new("xcrun")
28
+        .arg("-f")
29
+        .arg("ld")
30
+        .output()
31
+        .map(|o| o.status.success())
32
+        .unwrap_or(false)
33
+}
34
+
35
+fn sdk_path() -> Option<String> {
36
+    Command::new("xcrun")
37
+        .args(["--sdk", "macosx", "--show-sdk-path"])
38
+        .output()
39
+        .ok()
40
+        .filter(|out| out.status.success())
41
+        .and_then(|out| String::from_utf8(out.stdout).ok())
42
+        .map(|text| text.trim().to_string())
43
+        .filter(|text| !text.is_empty())
44
+}
45
+
2646
 fn scratch(name: &str) -> PathBuf {
2747
     std::env::temp_dir().join(format!("afs-ld-load-order-{}-{name}", std::process::id()))
2848
 }
@@ -141,14 +161,18 @@ fn normalize(ids: &[u32]) -> Vec<&'static str> {
141161
 
142162
 #[test]
143163
 fn executable_load_command_order_matches_apple_for_common_surface() {
144
-    if !have_xcrun() || !have_clang() {
145
-        eprintln!("skipping: xcrun as / clang unavailable");
164
+    if !have_xcrun() || !have_ld() {
165
+        eprintln!("skipping: xcrun as / ld unavailable");
146166
         return;
147167
     }
168
+    let Some(sdk) = sdk_path() else {
169
+        eprintln!("skipping: xcrun --show-sdk-path unavailable");
170
+        return;
171
+    };
148172
 
149173
     let obj = scratch("main.o");
150174
     let ours = scratch("ours-exec");
151
-    let theirs = scratch("clang-exec");
175
+    let theirs = scratch("apple-exec");
152176
     assemble(
153177
         r#"
154178
             .section __TEXT,__text,regular,pure_instructions
@@ -159,15 +183,32 @@ fn executable_load_command_order_matches_apple_for_common_surface() {
159183
         &obj,
160184
     )
161185
     .expect("assemble");
162
-    link_with_afs_ld(&[obj.to_str().unwrap(), "-o", ours.to_str().unwrap()]).expect("afs-ld");
186
+    link_with_afs_ld(&[
187
+        "-syslibroot",
188
+        &sdk,
189
+        "-lSystem",
190
+        obj.to_str().unwrap(),
191
+        "-o",
192
+        ours.to_str().unwrap(),
193
+    ])
194
+    .expect("afs-ld");
163195
     let status = Command::new("xcrun")
164
-        .args(["--sdk", "macosx", "clang", "-arch", "arm64"])
165
-        .arg(&obj)
166
-        .arg("-o")
196
+        .args([
197
+            "ld",
198
+            "-arch",
199
+            "arm64",
200
+            "-syslibroot",
201
+            &sdk,
202
+            "-lSystem",
203
+            "-e",
204
+            "_main",
205
+            "-o",
206
+        ])
167207
         .arg(&theirs)
208
+        .arg(&obj)
168209
         .status()
169
-        .expect("spawn clang");
170
-    assert!(status.success(), "clang link failed");
210
+        .expect("spawn ld");
211
+    assert!(status.success(), "ld link failed");
171212
 
172213
     assert_eq!(
173214
         normalize(&command_ids(&ours)),
@@ -181,14 +222,18 @@ fn executable_load_command_order_matches_apple_for_common_surface() {
181222
 
182223
 #[test]
183224
 fn dylib_load_command_order_matches_apple_for_common_surface() {
184
-    if !have_xcrun() || !have_clang() {
185
-        eprintln!("skipping: xcrun as / clang unavailable");
225
+    if !have_xcrun() || !have_ld() {
226
+        eprintln!("skipping: xcrun as / ld unavailable");
186227
         return;
187228
     }
229
+    let Some(sdk) = sdk_path() else {
230
+        eprintln!("skipping: xcrun --show-sdk-path unavailable");
231
+        return;
232
+    };
188233
 
189234
     let obj = scratch("lib.o");
190235
     let ours = scratch("ours.dylib");
191
-    let theirs = scratch("clang.dylib");
236
+    let theirs = scratch("apple.dylib");
192237
     assemble(
193238
         r#"
194239
             .section __TEXT,__text,regular,pure_instructions
@@ -201,21 +246,32 @@ fn dylib_load_command_order_matches_apple_for_common_surface() {
201246
     .expect("assemble");
202247
     link_with_afs_ld(&[
203248
         "-dylib",
249
+        "-syslibroot",
250
+        &sdk,
251
+        "-lSystem",
204252
         obj.to_str().unwrap(),
205253
         "-o",
206254
         ours.to_str().unwrap(),
207255
     ])
208256
     .expect("afs-ld dylib");
209257
     let status = Command::new("xcrun")
210
-        .args(["--sdk", "macosx", "clang", "-shared", "-arch", "arm64"])
211
-        .arg(&obj)
212
-        .arg("-install_name")
213
-        .arg("@rpath/libparity.dylib")
214
-        .arg("-o")
258
+        .args([
259
+            "ld",
260
+            "-dylib",
261
+            "-arch",
262
+            "arm64",
263
+            "-syslibroot",
264
+            &sdk,
265
+            "-lSystem",
266
+            "-install_name",
267
+            "@rpath/libparity.dylib",
268
+            "-o",
269
+        ])
215270
         .arg(&theirs)
271
+        .arg(&obj)
216272
         .status()
217
-        .expect("spawn clang");
218
-    assert!(status.success(), "clang dylib link failed");
273
+        .expect("spawn ld");
274
+    assert!(status.success(), "ld dylib link failed");
219275
 
220276
     assert_eq!(
221277
         normalize(&command_ids(&ours)),
@@ -229,15 +285,19 @@ fn dylib_load_command_order_matches_apple_for_common_surface() {
229285
 
230286
 #[test]
231287
 fn executable_load_command_order_with_dependency_and_rpath_matches_common_surface() {
232
-    if !have_xcrun() || !have_clang() {
233
-        eprintln!("skipping: xcrun as / clang unavailable");
288
+    if !have_xcrun() || !have_clang() || !have_ld() {
289
+        eprintln!("skipping: xcrun as / clang / ld unavailable");
234290
         return;
235291
     }
292
+    let Some(sdk) = sdk_path() else {
293
+        eprintln!("skipping: xcrun --show-sdk-path unavailable");
294
+        return;
295
+    };
236296
 
237297
     let obj = scratch("dep-main.o");
238298
     let dep = scratch("dep.dylib");
239299
     let ours = scratch("ours-dep");
240
-    let theirs = scratch("clang-dep");
300
+    let theirs = scratch("apple-dep");
241301
     assemble(
242302
         r#"
243303
             .section __TEXT,__text,regular,pure_instructions
@@ -251,6 +311,9 @@ fn executable_load_command_order_with_dependency_and_rpath_matches_common_surfac
251311
     build_test_dylib("int dep(void) { return 1; }\n", &dep, "@rpath/libdep.dylib")
252312
         .expect("build dylib");
253313
     link_with_afs_ld(&[
314
+        "-syslibroot",
315
+        &sdk,
316
+        "-lSystem",
254317
         obj.to_str().unwrap(),
255318
         dep.to_str().unwrap(),
256319
         "-rpath",
@@ -261,15 +324,25 @@ fn executable_load_command_order_with_dependency_and_rpath_matches_common_surfac
261324
     .expect("afs-ld with dep");
262325
 
263326
     let status = Command::new("xcrun")
264
-        .args(["--sdk", "macosx", "clang", "-arch", "arm64"])
327
+        .args([
328
+            "ld",
329
+            "-arch",
330
+            "arm64",
331
+            "-syslibroot",
332
+            &sdk,
333
+            "-lSystem",
334
+            "-e",
335
+            "_main",
336
+            "-o",
337
+        ])
338
+        .arg(&theirs)
265339
         .arg(&obj)
266340
         .arg(&dep)
267
-        .arg("-Wl,-rpath,@executable_path/../lib")
268
-        .arg("-o")
269
-        .arg(&theirs)
341
+        .arg("-rpath")
342
+        .arg("@executable_path/../lib")
270343
         .status()
271
-        .expect("spawn clang");
272
-    assert!(status.success(), "clang dep link failed");
344
+        .expect("spawn ld");
345
+    assert!(status.success(), "ld dep link failed");
273346
 
274347
     assert_eq!(
275348
         normalize(&command_ids(&ours)),