blob: 8ee74015d6edf252c4230caca8866f14fd1a6f23 [file] [log] [blame]
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
import "dart:io";
import 'package:front_end/src/api_unstable/vm.dart'
show computePlatformBinariesLocation;
main() {
final Directory tmpDir =
Directory.systemTemp.createTempSync("obfuscationtest");
try {
final Uri tmpDirUri = tmpDir.uri;
final Uri secretfilename = tmpDirUri.resolve("secretfilename.dart");
final File secretfilenameFile = new File.fromUri(secretfilename);
secretfilenameFile.writeAsStringSync("""
import "secretfilename2.dart";
main() {
print("Hello, World!");
verySecretFoo();
}
""");
final Uri secretfilename2 = tmpDirUri.resolve("secretfilename2.dart");
final File secretfilename2File = new File.fromUri(secretfilename2);
secretfilename2File.writeAsStringSync("""
@pragma('vm:entry-point')
void verySecretFoo() {
print("foo!");
alsoVerySecretFoo();
}
void alsoVerySecretFoo() {
print("foo too!");
}
""");
List<MappingPair> mapping = getSnapshotMap(tmpDir, secretfilenameFile);
bool good = verify(mapping, {
// This contains @pragma('vm:entry-point') and the uri should not change.
secretfilename2.toString(),
// This contains @pragma('vm:entry-point') and the name should not change.
"verySecretFoo",
}, {
// This is not special and should have been obfuscated.
secretfilename.toString(),
// This is not special and should have been obfuscated.
"alsoVerySecretFoo"
});
if (!good) throw "Obfuscation didn't work as expected";
print("Good");
} finally {
tmpDir.deleteSync(recursive: true);
}
}
List<MappingPair> getSnapshotMap(Directory tmpDir, File compileDartFile) {
final Uri genKernel = Platform.script.resolve('../bin/gen_kernel.dart');
final File genKernelFile = new File.fromUri(genKernel);
if (!genKernelFile.existsSync()) {
throw "Didn't find gen_kernel at $genKernel";
}
File resolvedExecutableFile = new File(Platform.resolvedExecutable);
Uri resolvedExecutable = resolvedExecutableFile.uri;
String genSnapshotFilename = "gen_snapshot";
if (Platform.isWindows) genSnapshotFilename += ".exe";
Uri genSnapshot = resolvedExecutable.resolve(genSnapshotFilename);
File genSnapshotFile = new File.fromUri(genSnapshot);
if (!genSnapshotFile.existsSync()) {
print(
"Didn't find gen_kernel at $genSnapshot... Trying utils/$genSnapshotFilename");
genSnapshot = resolvedExecutable.resolve("utils/$genSnapshotFilename");
genSnapshotFile = new File.fromUri(genSnapshot);
if (!genSnapshotFile.existsSync()) {
throw "Didn't find gen_kernel at $genSnapshot";
}
}
final Uri platformDill = computePlatformBinariesLocation()
.resolve('vm_platform_strong_product.dill');
final File platformDillFile = new File.fromUri(platformDill);
if (!platformDillFile.existsSync()) {
throw "Didn't find vm_platform_strong_product at $platformDill";
}
final Uri tmpDirUri = tmpDir.uri;
final Uri kernelDill = tmpDirUri.resolve("kernel.dill");
final File kernelDillFile = new File.fromUri(kernelDill);
print("Running gen_kernel");
// Extracted from pkg/dart2native/lib/dart2native.dart.
final ProcessResult kernelRun = Process.runSync(Platform.resolvedExecutable, [
genKernelFile.path,
"--platform",
platformDillFile.path,
"--aot",
"-Ddart.vm.product=true",
"-o",
kernelDillFile.path,
"--invocation-modes=compile",
"--verbosity=all",
compileDartFile.path
]);
if (kernelRun.exitCode != 0) {
throw "Got exit code ${kernelRun.exitCode}\n"
"stdout: ${kernelRun.stdout}\n"
"stderr: ${kernelRun.stderr}";
}
final Uri aotElf = tmpDirUri.resolve("aot.elf");
final File aotElfFile = new File.fromUri(aotElf);
final Uri obfuscationMap = tmpDirUri.resolve("obfuscation.map");
final File obfuscationMapFile = new File.fromUri(obfuscationMap);
print("Running $genSnapshot");
// Extracted from pkg/dart2native/lib/dart2native.dart.
final ProcessResult snapshotRun = Process.runSync(genSnapshotFile.path, [
"--snapshot-kind=app-aot-elf",
"--elf=${aotElfFile.path}",
"--dwarf-stack-traces",
"--obfuscate",
"--strip",
"--save-obfuscation-map=${obfuscationMapFile.path}",
kernelDillFile.path,
]);
if (snapshotRun.exitCode != 0) {
throw "Got exit code ${snapshotRun.exitCode}\n"
"stdout: ${snapshotRun.stdout}\n"
"stderr: ${snapshotRun.stderr}";
}
print("Reading $obfuscationMap");
return readJsonMapping(obfuscationMapFile);
}
List<MappingPair> readJsonMapping(File file) {
List<MappingPair> result = [];
List<dynamic> json = jsonDecode(file.readAsStringSync());
for (int i = 0; i < json.length; i += 2) {
result.add(new MappingPair(json[i] as String, json[i + 1] as String));
}
return result;
}
class MappingPair {
final String from;
final String to;
MappingPair(this.from, this.to);
String toString() => "MappingPair[$from->$to]";
}
bool verify(List<MappingPair> mapping, Set<String> expectedIdentity,
Set<String> expectedDifferent) {
bool good = true;
Set<String> missingKeys = new Set<String>.of(expectedIdentity)
..addAll(expectedDifferent);
for (MappingPair entry in mapping) {
missingKeys.remove(entry.from);
if (expectedIdentity.contains(entry.from) && entry.from != entry.to) {
print("Expected ${entry.from} to map to itself, "
"but mapped to ${entry.to}");
good = false;
}
if (expectedDifferent.contains(entry.from) && entry.from == entry.to) {
print("Expected ${entry.from} to map to something different, "
"but it didn't.");
good = false;
}
}
if (missingKeys.isNotEmpty) {
print("Expected to have seen the following entries which wasn't found:");
for (String missingKey in missingKeys) {
print("- $missingKey");
}
good = false;
}
return good;
}