[build] Remove unsigned executable memory permissions from the AOT runtime on Mac.

Snapshots are now generally signed Mach-O dylibs loaded by dlopen, instead of ELF files mapped executable by the VM's loader.

TEST=ci
Change-Id: Id19877bed0bd0282b320f070904a848b0c076a54
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/505200
Reviewed-by: Tess Strickland <sstrickl@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak
2026-06-01 07:21:29 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 94b953305a
commit fc750ac8e0
47 changed files with 191 additions and 103 deletions
+3
View File
@@ -722,6 +722,9 @@ static void CreateAndWritePrecompiledSnapshot() {
// Not currently implemented.
next_callback = nullptr;
create_multiple_callback = nullptr;
if (loading_unit_manifest_filename != nullptr) {
PrintErrAndExit("error: deferred loading not implemented for Mach-O");
}
break;
default:
UNREACHABLE();
@@ -86,7 +86,7 @@ class AotTestRunner extends TestRunner {
AotTestRunner(this.buildDir, this.arguments, this.aotArguments);
Future runTest(List<PotentialCrash> crashes) async {
await withTempDir((String dir) async {
await withTempDir("iso-stress", (String dir) async {
final elfFile = path.join(dir, 'app.elf');
if (await run('$buildDir/gen_snapshot', [
@@ -57,8 +57,13 @@ Future<void> main(List<String> args) async {
'--disassemble',
'--disassemble_stubs',
'--always_generate_trampolines_for_testing',
'--snapshot-kind=app-aot-elf',
'--elf=$elfFile',
if (Platform.isMacOS) ...[
'--snapshot-kind=app-aot-macho-dylib',
'--macho=$elfFile',
] else ...[
'--snapshot-kind=app-aot-elf',
'--elf=$elfFile',
],
scriptDill,
]);
@@ -40,10 +40,15 @@ main(List<String> args) async {
final elfFile = path.join(tempDir, 'aot.snapshot');
await Future.wait(<Future>[
run(genSnapshot, <String>[
'--snapshot-kind=app-aot-elf',
if (Platform.isMacOS) ...[
'--snapshot-kind=app-aot-macho-dylib',
'--macho=$elfFile',
] else ...[
'--snapshot-kind=app-aot-elf',
'--elf=$elfFile',
],
'--print-instructions-sizes-to=$appSizesJson',
'--write-v8-snapshot-profile-to=$appHeapsnapshot',
'--elf=$elfFile',
scriptDill,
]),
]);
@@ -13,7 +13,7 @@ import 'isolates/reload_utils.dart';
Future main() async {
if (!currentVmSupportsReload) return;
await withTempDir((String tempDir) async {
await withTempDir("flutter-regress-93676", (String tempDir) async {
final filename = path.join(tempDir, 'testee.dart');
File(filename).writeAsStringSync(dartTestFile('AA', 'BB'));
@@ -65,8 +65,13 @@ main(List<String> args) async {
final elfFile = path.join(tempDir.path, 'aot.snapshot');
await run(genSnapshot, <String>[
'--snapshot-kind=app-aot-elf',
'--elf=$elfFile',
if (Platform.isMacOS) ...[
'--snapshot-kind=app-aot-macho-dylib',
'--macho=$elfFile',
] else ...[
'--snapshot-kind=app-aot-elf',
'--elf=$elfFile',
],
scriptDill,
]);
@@ -82,8 +82,13 @@ main(List<String> args) async {
// Compile kernel to ELF.
await run(genSnapshot, <String>[
"--snapshot-kind=app-aot-elf",
"--elf=$snapshot1",
if (Platform.isMacOS) ...[
"--snapshot-kind=app-aot-macho-dylib",
"--macho=$snapshot1",
] else ...[
"--snapshot-kind=app-aot-elf",
"--elf=$snapshot1",
],
"--loading-unit-manifest=$manifest1",
dill1,
]);
@@ -98,8 +103,13 @@ main(List<String> args) async {
Expect.isTrue(await new File(deferredSnapshot1).exists());
await run(genSnapshot, <String>[
"--snapshot-kind=app-aot-elf",
"--elf=$snapshot2",
if (Platform.isMacOS) ...[
"--snapshot-kind=app-aot-macho-dylib",
"--macho=$snapshot2",
] else ...[
"--snapshot-kind=app-aot-elf",
"--elf=$snapshot2",
],
"--loading-unit-manifest=$manifest2",
dill2,
]);
@@ -50,8 +50,13 @@ void main() async {
]);
Expect.equals(result.exitCode, 0);
result = Process.runSync(genSnapshot, <String>[
'--snapshot_kind=app-aot-elf',
'--elf=$aotOutput',
if (Platform.isMacOS) ...[
'--snapshot_kind=app-aot-macho-dylib',
'--macho=$aotOutput',
] else ...[
'--snapshot_kind=app-aot-elf',
'--elf=$aotOutput',
],
kernelOutput,
]);
Expect.equals(result.exitCode, 0);
@@ -11,7 +11,7 @@ final N = 5;
main() async {
if (!currentVmSupportsReload) return;
await withTempDir((String tempDir) async {
await withTempDir("reload-active-stack", (String tempDir) async {
final dills = await generateDills(tempDir, dartTestFile(N));
final reloader = await launchOn(dills[0]);
@@ -15,7 +15,7 @@ final N = runningInSimulator ? 2 : math.min(20, Platform.numberOfProcessors);
main() async {
if (!currentVmSupportsReload) return;
await withTempDir((String tempDir) async {
await withTempDir("reload-many-isolates", (String tempDir) async {
final dills = await generateDills(tempDir, dartTestFile(N));
final reloader = await launchOn(dills[0] /*, verbose: true*/);
@@ -12,7 +12,7 @@ const N = 250;
main() async {
if (!currentVmSupportsReload) return;
await withTempDir((String tempDir) async {
await withTempDir("reload-many", (String tempDir) async {
final dills = await generateDills(tempDir, dartTestFile(N));
final reloader = await launchOn(dills[0]);
@@ -11,7 +11,7 @@ const N = 5;
main() async {
if (!currentVmSupportsReload) return;
await withTempDir((String tempDir) async {
await withTempDir("reload-no-active-stack", (String tempDir) async {
final dills = await generateDills(tempDir, dartTestFile(N));
final reloader = await launchOn(dills[0]);
@@ -16,7 +16,7 @@ compileAndRunMinimalDillTest(List<String> extraCompilationArgs) async {
final testScriptUri = Platform.script.resolve('minimal_kernel_script.dart');
final message = 'Round_trip_message';
await withTempDir((String temp) async {
await withTempDir("minimal-kernel", (String temp) async {
final minimalDillPath = path.join(temp, 'minimal.dill');
await runGenKernel('BUILD MINIMAL DILL FILE', [
'--minimal-kernel',
@@ -9,7 +9,7 @@ import 'isolates/reload_utils.dart';
main() async {
if (!currentVmSupportsReload) return;
await withTempDir((String tempDir) async {
await withTempDir("regress-48523", (String tempDir) async {
final dills = await generateDills(tempDir, dartTestFile());
final reloader = await launchOn(dills[0]);
@@ -48,8 +48,13 @@ main(List<String> args) async {
final profile = path.join(tempDir, 'profile.json');
final snapshot = path.join(tempDir, 'snapshot.so');
await run(genSnapshot, <String>[
'--snapshot-kind=app-aot-elf',
'--elf=$snapshot',
if (Platform.isMacOS) ...[
'--snapshot-kind=app-aot-macho-dylib',
'--macho=$snapshot',
] else ...[
'--snapshot-kind=app-aot-elf',
'--elf=$snapshot',
],
'--loading-unit-manifest=$manifest',
'--write-v8-snapshot-profile-to=$profile',
scriptDill,
@@ -26,7 +26,7 @@ Future<void> main(List<String> args) async {
'run_appended_aot_snapshot_test.dart',
);
await withTempDir((String tmp) async {
await withTempDir("run-appended-snapshot", (String tmp) async {
final String exeName = 'test.exe';
final String dillPath = path.join(tmp, 'test.dill');
final String aotPath = path.join(tmp, 'test.aot');
@@ -145,8 +145,13 @@ Future<ProcessResult> generateAotSnapshotHelper(
String snapshotFile,
) {
return Process.run(genSnapshot, [
'--snapshot-kind=app-aot-elf',
'--elf=$snapshotFile',
if (Platform.isMacOS) ...[
'--snapshot-kind=app-aot-macho-dylib',
'--macho=$snapshotFile',
] else ...[
'--snapshot-kind=app-aot-elf',
'--elf=$snapshotFile',
],
kernelFile,
]);
}
@@ -67,18 +67,33 @@ main() async {
]);
await run(noneGenSnapshot, [
"--snapshot-kind=app-aot-elf",
"--elf=$noneElf",
if (Platform.isMacOS) ...[
"--snapshot-kind=app-aot-macho-dylib",
"--macho=$noneElf",
] else ...[
"--snapshot-kind=app-aot-elf",
"--elf=$noneElf",
],
aotDill,
]);
await run(sanitizerGenSnapshot, [
"--snapshot-kind=app-aot-elf",
"--elf=$sanitizerElf",
if (Platform.isMacOS) ...[
"--snapshot-kind=app-aot-macho-dylib",
"--macho=$sanitizerElf",
] else ...[
"--snapshot-kind=app-aot-elf",
"--elf=$sanitizerElf",
],
aotDill,
]);
await run(noneGenSnapshot, [
"--snapshot-kind=app-aot-elf",
"--elf=$sanitizerElf2",
if (Platform.isMacOS) ...[
"--snapshot-kind=app-aot-macho-dylib",
"--macho=$sanitizerElf2",
] else ...[
"--snapshot-kind=app-aot-elf",
"--elf=$sanitizerElf2",
],
targetFlag,
aotDill,
]);
+1 -1
View File
@@ -29,7 +29,7 @@ Future<void> main(List<String> args) async {
'sdk_hash_test.dart',
);
await withTempDir((String tmp) async {
await withTempDir("sdk-hash-test", (String tmp) async {
final String dillPath = path.join(tmp, 'test.dill');
{
@@ -16,7 +16,7 @@ Future<void> main(List<String> args) async {
return;
}
await withTempDir((String temp) async {
await withTempDir("snapshot-depfile", (String temp) async {
final snapshotPath = p.join(temp, 'snapshot_depfile_test.snapshot');
final depfilePath = p.join(temp, 'snapshot_depfile_test.snapshot.d');
@@ -138,17 +138,8 @@ ${processResult.stderr}''');
return result;
}
withTempDir(Future fun(String dir)) async {
final Directory tempDir = Directory.systemTemp.createTempSync();
try {
return await fun(tempDir.path);
} finally {
tempDir.deleteSync(recursive: true);
}
}
checkDeterministicSnapshot(String snapshotKind, String expectedStdout) async {
await withTempDir((String temp) async {
await withTempDir('snapshot', (String temp) async {
final snapshot1Path = p.join(temp, 'snapshot1');
final snapshot2Path = p.join(temp, 'snapshot2');
@@ -202,7 +193,7 @@ runAppJitTest(
runSnapshot ??= (snapshotPath) =>
runDart('RUN FROM SNAPSHOT', [snapshotPath]);
await withTempDir((String temp) async {
await withTempDir('snapshot', (String temp) async {
final snapshotPath = p.join(temp, 'app.jit');
final testPath = testScriptUri.toFilePath();
@@ -72,8 +72,13 @@ main(List<String> args) async {
final scriptAot = path.join(dir, '$basename.dart.dill.so');
await run(genSnapshot, <String>[
if (checked) '--enable-asserts',
'--snapshot-kind=app-aot-elf',
'--elf=$scriptAot',
if (!Platform.isMacOS) ...[
'--snapshot-kind=app-aot-elf',
'--elf=$scriptAot',
] else ...[
'--snapshot-kind=app-aot-macho-dylib',
'--macho=$scriptAot',
],
scriptDill,
]);
}
@@ -12,7 +12,7 @@ import 'package:path/path.dart' as path;
import 'snapshot_test_helper.dart';
Future<void> runSplitAOTKernelGenerationTest(Uri testScriptUri) async {
await withTempDir((String temp) async {
await withTempDir("split-test", (String temp) async {
final intermediateDillPath = path.join(temp, 'intermediate.dill');
final outputDillPath = path.join(temp, 'output.dill');
final snapshotPath = path.join(temp, 'aot.snapshot');
@@ -33,8 +33,13 @@ Future<void> runSplitAOTKernelGenerationTest(Uri testScriptUri) async {
]);
await runGenSnapshot('GENERATE SNAPSHOT', [
'--snapshot-kind=app-aot-elf',
'--elf=$snapshotPath',
if (Platform.isMacOS) ...[
'--snapshot-kind=app-aot-macho-dylib',
'--macho=$snapshotPath',
] else ...[
'--snapshot-kind=app-aot-elf',
'--elf=$snapshotPath',
],
outputDillPath,
]);
+1 -1
View File
@@ -13,7 +13,7 @@ Future<List<TimelineEvent>> runAndCollectTimeline(
String streams,
List<String> args,
) async {
return await withTempDir((String tmp) async {
return await withTempDir("timeline-test", (String tmp) async {
final String timelinePath = path.join(tmp, 'timeline.json');
final p = await Process.run(Platform.executable, [
...Platform.executableArguments,
@@ -54,7 +54,10 @@ Future<void> main(List<String> args) async {
script,
]);
await checkElf(tempDir, scriptDill);
if (!Platform.isMacOS) {
// Don't run ELF on MacOS since that requires allow-unsigned-executable-memory.
await checkElf(tempDir, scriptDill);
}
await checkMachO(tempDir, scriptDill);
await checkAssembly(tempDir, scriptDill);
});
@@ -45,14 +45,24 @@ main(List<String> args) async {
await Future.wait(<Future>[
run(genSnapshot, <String>[
'--code-comments',
'--snapshot-kind=app-aot-elf',
'--elf=$scriptCommentedSnapshot',
if (Platform.isMacOS) ...[
'--snapshot-kind=app-aot-macho-dylib',
'--macho=$scriptCommentedSnapshot',
] else ...[
'--snapshot-kind=app-aot-elf',
'--elf=$scriptCommentedSnapshot',
],
scriptDill,
]),
run(genSnapshot, <String>[
'--no-code-comments',
'--snapshot-kind=app-aot-elf',
'--elf=$scriptUncommentedSnapshot',
if (Platform.isMacOS) ...[
'--snapshot-kind=app-aot-macho-dylib',
'--macho=$scriptUncommentedSnapshot',
] else ...[
'--snapshot-kind=app-aot-elf',
'--elf=$scriptUncommentedSnapshot',
],
scriptDill,
]),
]);
@@ -37,7 +37,8 @@ Future<void> main() async {
),
runNonDwarf,
[
runElf,
// Don't run ELF on MacOS since that requires allow-unsigned-executable-memory.
if (!Platform.isMacOS) runElf,
// Don't run assembly on Windows since DLLs don't contain DWARF.
if (!Platform.isWindows) runAssembly,
],
@@ -73,8 +74,13 @@ Future<NonDwarfState> runNonDwarf(String tempDir, String scriptDill) async {
await run(genSnapshot, <String>[
'--no-dwarf-stack-traces-mode',
'--loading-unit-manifest=$manifestPath',
'--snapshot-kind=app-aot-elf',
'--elf=$snapshotPath',
if (Platform.isMacOS) ...[
'--snapshot-kind=app-aot-macho-dylib',
'--macho=$snapshotPath',
] else ...[
'--snapshot-kind=app-aot-elf',
'--elf=$snapshotPath',
],
scriptDill,
]);
@@ -41,7 +41,8 @@ Future<void> main() async {
),
runNonDwarf,
[
runElf,
// Don't run ELF on MacOS since that requires allow-unsigned-executable-memory.
if (!Platform.isMacOS) runElf,
runMachODylib,
if (hasDsymutil) runMachODsym,
// Don't run assembly on Windows since DLLs don't contain DWARF.
@@ -59,8 +60,13 @@ Future<NonDwarfState> runNonDwarf(String tempDir, String scriptDill) async {
// other flags. This way, we limit the difference between the two
// snapshots and also directly test the flag saved as a VM global flag.
'--no-dwarf-stack-traces-mode',
'--snapshot-kind=app-aot-elf',
'--elf=$scriptNonDwarfSnapshot',
if (Platform.isMacOS) ...[
'--snapshot-kind=app-aot-macho-dylib',
'--macho=$scriptNonDwarfSnapshot',
] else ...[
'--snapshot-kind=app-aot-elf',
'--elf=$scriptNonDwarfSnapshot',
],
scriptDill,
]);
@@ -283,10 +283,10 @@ Future<List<String>> runError(
const keepTempKey = 'KEEP_TEMPORARY_DIRECTORIES';
Future<void> withTempDir(String name, Future<void> fun(String dir)) async {
Future<R> withTempDir<R>(String name, Future<R> fun(String dir)) async {
final tempDir = Directory.systemTemp.createTempSync(name);
try {
await fun(tempDir.path);
return await fun(tempDir.path);
} finally {
if (!Platform.environment.containsKey(keepTempKey) ||
Platform.environment[keepTempKey]!.isEmpty) {
@@ -27,6 +27,11 @@ main(List<String> args) async {
if (Platform.isAndroid) {
return; // SDK tree and dart_bootstrap not available on the test device.
}
if (Platform.isMacOS) {
// Don't run ELF on MacOS since that requires
// allow-unsigned-executable-memory. Mach-O check unimplemented.
return;
}
// These are the tools we need to be available to run on a given platform:
if (!await testExecutable(genSnapshot)) {
+14 -4
View File
@@ -53,15 +53,25 @@ main(List<String> args) async {
// Run the AOT compiler to generate stripped and unstripped ELF snapshots.
final unstrippedSnapshot = path.join(tempDir, 'whole.so');
await run(genSnapshot, <String>[
'--snapshot-kind=app-aot-elf',
'--elf=$unstrippedSnapshot',
if (Platform.isMacOS) ...[
'--snapshot-kind=app-aot-macho-dylib',
'--macho=$unstrippedSnapshot',
] else ...[
'--snapshot-kind=app-aot-elf',
'--elf=$unstrippedSnapshot',
],
scriptDill,
]);
final strippedSnapshot = path.join(tempDir, 'stripped.so');
await run(genSnapshot, <String>[
'--snapshot-kind=app-aot-elf',
'--elf=$strippedSnapshot',
if (Platform.isMacOS) ...[
'--snapshot-kind=app-aot-macho-dylib',
'--macho=$strippedSnapshot',
] else ...[
'--snapshot-kind=app-aot-elf',
'--elf=$strippedSnapshot',
],
'--strip',
scriptDill,
]);
-2
View File
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>