[VM/Runtime] Report error when an AOT snapshot is used in spawnUri while

running in the JIT VM

TEST=new test added

Bug:54528
Change-Id: Ifa0176ee453e5af4e45bb0b74cf9ac9ba23fb93e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/346060
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Siva Annamalai <asiva@google.com>
This commit is contained in:
asiva 2024-01-31 21:43:27 +00:00 committed by Commit Queue
parent 1e5480262c
commit eabfad1158
12 changed files with 290 additions and 115 deletions

View file

@ -37,6 +37,13 @@ const char* DartUtils::original_working_directory = nullptr;
dart::SimpleHashMap* DartUtils::environment_ = nullptr;
MagicNumberData appjit_magic_number = {8, {0xdc, 0xdc, 0xf6, 0xf6, 0, 0, 0, 0}};
MagicNumberData aotelf_magic_number = {4, {0x7F, 0x45, 0x4C, 0x46, 0x0}};
MagicNumberData aotmacho32_magic_number = {4, {0xFE, 0xED, 0xFA, 0xCE}};
MagicNumberData aotmacho64_magic_number = {4, {0xFE, 0xED, 0xFA, 0xCF}};
MagicNumberData aotcoff_arm32_magic_number = {2, {0x01, 0xC0}};
MagicNumberData aotcoff_arm64_magic_number = {2, {0xAA, 0x64}};
MagicNumberData aotcoff_riscv32_magic_number = {2, {0x50, 0x32}};
MagicNumberData aotcoff_riscv64_magic_number = {2, {0x50, 0x64}};
MagicNumberData kernel_magic_number = {4, {0x90, 0xab, 0xcd, 0xef}};
MagicNumberData kernel_list_magic_number = {
7,
@ -398,22 +405,23 @@ static bool CheckMagicNumber(const uint8_t* buffer,
DartUtils::MagicNumber DartUtils::SniffForMagicNumber(const char* filename) {
MagicNumber magic_number = DartUtils::kUnknownMagicNumber;
ASSERT(kMaxMagicNumberSize == appjit_magic_number.length);
ASSERT(aotelf_magic_number.length <= appjit_magic_number.length);
ASSERT(aotmacho32_magic_number.length <= appjit_magic_number.length);
ASSERT(aotmacho64_magic_number.length <= appjit_magic_number.length);
ASSERT(aotcoff_arm32_magic_number.length <= appjit_magic_number.length);
ASSERT(aotcoff_arm64_magic_number.length <= appjit_magic_number.length);
ASSERT(aotcoff_riscv32_magic_number.length <= appjit_magic_number.length);
ASSERT(aotcoff_riscv64_magic_number.length <= appjit_magic_number.length);
ASSERT(kernel_magic_number.length <= appjit_magic_number.length);
ASSERT(kernel_list_magic_number.length <= appjit_magic_number.length);
ASSERT(gzip_magic_number.length <= appjit_magic_number.length);
if (File::GetType(nullptr, filename, true) == File::kIsFile) {
File* file = File::Open(nullptr, filename, File::kRead);
if (file != nullptr) {
RefCntReleaseScope<File> rs(file);
intptr_t max_magic_length = 0;
max_magic_length =
Utils::Maximum(max_magic_length, appjit_magic_number.length);
max_magic_length =
Utils::Maximum(max_magic_length, kernel_magic_number.length);
max_magic_length =
Utils::Maximum(max_magic_length, kernel_list_magic_number.length);
max_magic_length =
Utils::Maximum(max_magic_length, gzip_magic_number.length);
ASSERT(max_magic_length <= 8);
uint8_t header[8];
if (file->ReadFully(&header, max_magic_length)) {
uint8_t header[kMaxMagicNumberSize];
if (file->ReadFully(&header, kMaxMagicNumberSize)) {
magic_number = DartUtils::SniffForMagicNumber(header, sizeof(header));
}
}
@ -443,6 +451,34 @@ DartUtils::MagicNumber DartUtils::SniffForMagicNumber(const uint8_t* buffer,
return kGzipMagicNumber;
}
if (CheckMagicNumber(buffer, buffer_length, aotelf_magic_number)) {
return kAotELFMagicNumber;
}
if (CheckMagicNumber(buffer, buffer_length, aotmacho32_magic_number)) {
return kAotMachO32MagicNumber;
}
if (CheckMagicNumber(buffer, buffer_length, aotmacho64_magic_number)) {
return kAotMachO64MagicNumber;
}
if (CheckMagicNumber(buffer, buffer_length, aotcoff_arm32_magic_number)) {
return kAotCoffARM32MagicNumber;
}
if (CheckMagicNumber(buffer, buffer_length, aotcoff_arm64_magic_number)) {
return kAotCoffARM64MagicNumber;
}
if (CheckMagicNumber(buffer, buffer_length, aotcoff_riscv32_magic_number)) {
return kAotCoffRISCV32MagicNumber;
}
if (CheckMagicNumber(buffer, buffer_length, aotcoff_riscv64_magic_number)) {
return kAotCoffRISCV64MagicNumber;
}
return kUnknownMagicNumber;
}

View file

@ -245,8 +245,23 @@ class DartUtils {
kKernelMagicNumber,
kKernelListMagicNumber,
kGzipMagicNumber,
kAotELFMagicNumber,
kAotMachO32MagicNumber,
kAotMachO64MagicNumber,
kAotCoffARM32MagicNumber,
kAotCoffARM64MagicNumber,
kAotCoffRISCV32MagicNumber,
kAotCoffRISCV64MagicNumber,
kUnknownMagicNumber
};
static constexpr int64_t kMaxMagicNumberSize = 8;
// Note: The check for AOT magic number must match up with the enum
// order above.
static bool IsAotMagicNumber(MagicNumber number) {
return (number >= DartUtils::kAotELFMagicNumber) &&
(number <= DartUtils::kAotCoffRISCV64MagicNumber);
}
// Checks if the buffer is a script snapshot, kernel file, or gzip file.
static MagicNumber SniffForMagicNumber(const char* filename);
@ -629,6 +644,7 @@ struct MagicNumberData {
};
extern MagicNumberData appjit_magic_number;
extern MagicNumberData aotelf_magic_number;
extern MagicNumberData kernel_magic_number;
extern MagicNumberData kernel_list_magic_number;
extern MagicNumberData gzip_magic_number;

View file

@ -11,6 +11,7 @@
#include "bin/file.h"
#include "bin/lockers.h"
#include "bin/platform.h"
#include "bin/snapshot_utils.h"
#include "bin/utils.h"
#include "include/dart_tools_api.h"
#include "platform/utils.h"
@ -238,13 +239,14 @@ void DFE::CompileAndReadScript(const char* script_uri,
}
void DFE::ReadScript(const char* script_uri,
const AppSnapshot* app_snapshot,
uint8_t** kernel_buffer,
intptr_t* kernel_buffer_size,
bool decode_uri,
std::shared_ptr<uint8_t>* kernel_blob_ptr) {
int64_t start = Dart_TimelineGetMicros();
if (!TryReadKernelFile(script_uri, kernel_buffer, kernel_buffer_size,
decode_uri, kernel_blob_ptr)) {
if (!TryReadKernelFile(script_uri, app_snapshot, kernel_buffer,
kernel_buffer_size, decode_uri, kernel_blob_ptr)) {
return;
}
if (!Dart_IsKernel(*kernel_buffer, *kernel_buffer_size)) {
@ -435,6 +437,7 @@ static bool TryReadKernelListBuffer(const char* script_uri,
}
bool DFE::TryReadKernelFile(const char* script_uri,
const AppSnapshot* app_snapshot,
uint8_t** kernel_ir,
intptr_t* kernel_ir_size,
bool decode_uri,
@ -451,19 +454,31 @@ bool DFE::TryReadKernelFile(const char* script_uri,
return true;
}
}
uint8_t* buffer;
if (!TryReadFile(script_uri, &buffer, kernel_ir_size, decode_uri)) {
return false;
if (app_snapshot == nullptr || app_snapshot->IsKernel() ||
app_snapshot->IsKernelList()) {
uint8_t* buffer;
if (!TryReadFile(script_uri, &buffer, kernel_ir_size, decode_uri)) {
return false;
}
auto magic_number = DartUtils::kUnknownMagicNumber;
if (app_snapshot == nullptr) {
magic_number = DartUtils::SniffForMagicNumber(buffer, *kernel_ir_size);
} else if (app_snapshot->IsKernel()) {
magic_number = DartUtils::kKernelMagicNumber;
ASSERT(DartUtils::SniffForMagicNumber(buffer, *kernel_ir_size) ==
DartUtils::kKernelMagicNumber);
} else {
magic_number = DartUtils::kKernelListMagicNumber;
ASSERT(DartUtils::SniffForMagicNumber(buffer, *kernel_ir_size) ==
DartUtils::kKernelListMagicNumber);
}
if (magic_number == DartUtils::kKernelListMagicNumber) {
return TryReadKernelListBuffer(script_uri, buffer, *kernel_ir_size,
kernel_ir, kernel_ir_size);
}
return TryReadSimpleKernelBuffer(buffer, kernel_ir, kernel_ir_size);
}
DartUtils::MagicNumber magic_number =
DartUtils::SniffForMagicNumber(buffer, *kernel_ir_size);
if (magic_number == DartUtils::kKernelListMagicNumber) {
return TryReadKernelListBuffer(script_uri, buffer, *kernel_ir_size,
kernel_ir, kernel_ir_size);
}
return TryReadSimpleKernelBuffer(buffer, kernel_ir, kernel_ir_size);
return false;
}
const char* DFE::RegisterKernelBlob(const uint8_t* kernel_buffer,

View file

@ -18,6 +18,8 @@
namespace dart {
namespace bin {
class AppSnapshot; // Forward declaration.
class DFE {
public:
DFE();
@ -100,6 +102,7 @@ class DFE {
// to a shared pointer which owns the kernel buffer.
// Otherwise, the caller is responsible for free()ing 'kernel_buffer'.
void ReadScript(const char* script_uri,
const AppSnapshot* app_snapshot,
uint8_t** kernel_buffer,
intptr_t* kernel_buffer_size,
bool decode_uri = true,
@ -117,6 +120,7 @@ class DFE {
// Otherwise, the caller is responsible for free()ing 'kernel_buffer'
// if `true` was returned.
bool TryReadKernelFile(const char* script_uri,
const AppSnapshot* app_snapshot,
uint8_t** kernel_buffer,
intptr_t* kernel_buffer_size,
bool decode_uri = true,

View file

@ -93,7 +93,7 @@ Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
if (tag == Dart_kKernelTag) {
uint8_t* kernel_buffer = nullptr;
intptr_t kernel_buffer_size = 0;
if (!dfe.TryReadKernelFile(url_string, &kernel_buffer,
if (!dfe.TryReadKernelFile(url_string, nullptr, &kernel_buffer,
&kernel_buffer_size)) {
return DartUtils::NewError("'%s' is not a kernel file", url_string);
}

View file

@ -430,11 +430,12 @@ static Dart_Isolate CreateAndSetupKernelIsolate(const char* script_uri,
IsolateData* isolate_data = nullptr;
bool isolate_run_app_snapshot = false;
AppSnapshot* app_snapshot = nullptr;
// Kernel isolate uses an app snapshot or uses the dill file.
// Kernel isolate uses an app JIT snapshot or uses the dill file.
if ((kernel_snapshot_uri != nullptr) &&
(app_snapshot = Snapshot::TryReadAppSnapshot(
kernel_snapshot_uri, /*force_load_elf_from_memory=*/false,
/*decode_uri=*/false)) != nullptr) {
((app_snapshot = Snapshot::TryReadAppSnapshot(
kernel_snapshot_uri, /*force_load_elf_from_memory=*/false,
/*decode_uri=*/false)) != nullptr) &&
app_snapshot->IsJIT()) {
const uint8_t* isolate_snapshot_data = nullptr;
const uint8_t* isolate_snapshot_instructions = nullptr;
const uint8_t* ignore_vm_snapshot_data;
@ -611,9 +612,11 @@ static Dart_Isolate CreateAndSetupDartDevIsolate(const char* script_uri,
IsolateData* isolate_data = nullptr;
AppSnapshot* app_snapshot = nullptr;
bool isolate_run_app_snapshot = true;
if ((app_snapshot = Snapshot::TryReadAppSnapshot(
dartdev_path.get(), /*force_load_elf_from_memory=*/false,
/*decode_uri=*/false)) != nullptr) {
// dartdev isolate uses an app JIT snapshot or uses the dill file.
if (((app_snapshot = Snapshot::TryReadAppSnapshot(
dartdev_path.get(), /*force_load_elf_from_memory=*/false,
/*decode_uri=*/false)) != nullptr) &&
app_snapshot->IsJIT()) {
const uint8_t* isolate_snapshot_data = nullptr;
const uint8_t* isolate_snapshot_instructions = nullptr;
const uint8_t* ignore_vm_snapshot_data;
@ -647,7 +650,7 @@ static Dart_Isolate CreateAndSetupDartDevIsolate(const char* script_uri,
isolate_run_app_snapshot);
uint8_t* application_kernel_buffer = nullptr;
intptr_t application_kernel_buffer_size = 0;
dfe.ReadScript(dartdev_path.get(), &application_kernel_buffer,
dfe.ReadScript(dartdev_path.get(), nullptr, &application_kernel_buffer,
&application_kernel_buffer_size, /*decode_uri=*/false);
isolate_group_data->SetKernelBufferNewlyOwned(
application_kernel_buffer, application_kernel_buffer_size);
@ -702,10 +705,11 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
const bool kForceLoadElfFromMemory = false;
app_snapshot =
Snapshot::TryReadAppSnapshot(script_uri, kForceLoadElfFromMemory);
if (app_snapshot == nullptr) {
*error = Utils::StrDup(
"The uri provided to `Isolate.spawnUri()` does not "
"contain a valid AOT snapshot.");
if (app_snapshot == nullptr || !app_snapshot->IsAOT()) {
*error = Utils::SCreate(
"The uri(%s) provided to `Isolate.spawnUri()` does not "
"contain a valid AOT snapshot.",
script_uri);
return nullptr;
}
@ -735,7 +739,14 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
isolate_snapshot_instructions = app_isolate_snapshot_instructions;
} else if (!is_main_isolate) {
app_snapshot = Snapshot::TryReadAppSnapshot(script_uri);
if (app_snapshot != nullptr) {
if (app_snapshot != nullptr && app_snapshot->IsJITorAOT()) {
if (app_snapshot->IsAOT()) {
*error = Utils::SCreate(
"The uri(%s) provided to `Isolate.spawnUri()` is an "
"AOT snapshot and the JIT VM cannot spawn an isolate using it.",
script_uri);
return nullptr;
}
isolate_run_app_snapshot = true;
const uint8_t* ignore_vm_snapshot_data;
const uint8_t* ignore_vm_snapshot_instructions;
@ -754,8 +765,9 @@ static Dart_Isolate CreateIsolateGroupAndSetupHelper(
}
if (kernel_buffer == nullptr && !isolate_run_app_snapshot) {
dfe.ReadScript(script_uri, &kernel_buffer, &kernel_buffer_size,
/*decode_uri=*/true, &kernel_buffer_ptr);
dfe.ReadScript(script_uri, app_snapshot, &kernel_buffer,
&kernel_buffer_size, /*decode_uri=*/true,
&kernel_buffer_ptr);
}
PathSanitizer script_uri_sanitizer(script_uri);
PathSanitizer packages_config_sanitizer(packages_config);
@ -1271,7 +1283,13 @@ void main(int argc, char** argv) {
app_snapshot =
Snapshot::TryReadAppSnapshot(script_name, force_load_elf_from_memory);
}
if (app_snapshot != nullptr) {
if (app_snapshot != nullptr && app_snapshot->IsJITorAOT()) {
if (app_snapshot->IsAOT() && !Dart_IsPrecompiledRuntime()) {
Syslog::PrintErr(
"%s is an AOT snapshot and should be run with 'dartaotruntime'\n",
script_name);
Platform::Exit(kErrorExitCode);
}
vm_run_app_snapshot = true;
app_snapshot->SetBuffers(&vm_snapshot_data, &vm_snapshot_instructions,
&app_isolate_snapshot_data,
@ -1331,7 +1349,7 @@ void main(int argc, char** argv) {
if (script_name != nullptr) {
uint8_t* application_kernel_buffer = nullptr;
intptr_t application_kernel_buffer_size = 0;
dfe.ReadScript(script_name, &application_kernel_buffer,
dfe.ReadScript(script_name, app_snapshot, &application_kernel_buffer,
&application_kernel_buffer_size);
if (application_kernel_buffer != nullptr) {
// Since we loaded the script anyway, save it.
@ -1415,21 +1433,12 @@ void main(int argc, char** argv) {
#endif // !defined(DART_PRECOMPILED_RUNTIME)
if (should_run_user_program) {
if (!Dart_IsPrecompiledRuntime() && Snapshot::IsAOTSnapshot(script_name)) {
Syslog::PrintErr(
"%s is an AOT snapshot and should be run with 'dartaotruntime'\n",
script_name);
Platform::Exit(kErrorExitCode);
if (Options::gen_snapshot_kind() == kKernel) {
CompileAndSaveKernel(script_name, package_config_override, &dart_options);
} else {
if (Options::gen_snapshot_kind() == kKernel) {
CompileAndSaveKernel(script_name, package_config_override,
&dart_options);
} else {
// Run the main isolate until we aren't told to restart.
RunMainIsolate(script_name, package_config_override,
force_no_sound_null_safety, &dart_options);
}
// Run the main isolate until we aren't told to restart.
RunMainIsolate(script_name, package_config_override,
force_no_sound_null_safety, &dart_options);
}
}

View file

@ -26,18 +26,37 @@
namespace dart {
namespace bin {
static constexpr int64_t kAppSnapshotHeaderSize = 5 * kInt64Size;
static constexpr int64_t kAppSnapshotHeaderSize = 4 * kInt64Size;
static constexpr int64_t kAppSnapshotPageSize = 16 * KB;
static const char kMachOAppSnapshotNoteName[] DART_UNUSED = "__dart_app_snap";
#if !defined(DART_PRECOMPILED_RUNTIME)
class DummySnapshot : public AppSnapshot {
public:
explicit DummySnapshot(DartUtils::MagicNumber num) : AppSnapshot(num) {}
~DummySnapshot() {}
void SetBuffers(const uint8_t** vm_data_buffer,
const uint8_t** vm_instructions_buffer,
const uint8_t** isolate_data_buffer,
const uint8_t** isolate_instructions_buffer) {
UNREACHABLE();
}
private:
};
#endif // !defined(DART_PRECOMPILED_RUNTIME)
class MappedAppSnapshot : public AppSnapshot {
public:
MappedAppSnapshot(MappedMemory* vm_snapshot_data,
MappedMemory* vm_snapshot_instructions,
MappedMemory* isolate_snapshot_data,
MappedMemory* isolate_snapshot_instructions)
: vm_data_mapping_(vm_snapshot_data),
: AppSnapshot(DartUtils::kAppJITMagicNumber),
vm_data_mapping_(vm_snapshot_data),
vm_instructions_mapping_(vm_snapshot_instructions),
isolate_data_mapping_(isolate_snapshot_data),
isolate_instructions_mapping_(isolate_snapshot_instructions) {}
@ -84,30 +103,24 @@ static AppSnapshot* TryReadAppSnapshotBlobs(const char* script_name,
return nullptr;
}
int64_t header[5];
int64_t header[4];
ASSERT(sizeof(header) == kAppSnapshotHeaderSize);
if (!file->ReadFully(&header, kAppSnapshotHeaderSize)) {
return nullptr;
}
ASSERT(sizeof(header[0]) == appjit_magic_number.length);
if (memcmp(&header[0], appjit_magic_number.bytes,
appjit_magic_number.length) != 0) {
return nullptr;
}
int64_t vm_data_size = header[1];
int64_t vm_data_size = header[0];
int64_t vm_data_position =
Utils::RoundUp(file->Position(), kAppSnapshotPageSize);
int64_t vm_instructions_size = header[2];
int64_t vm_instructions_size = header[1];
int64_t vm_instructions_position = vm_data_position + vm_data_size;
if (vm_instructions_size != 0) {
vm_instructions_position =
Utils::RoundUp(vm_instructions_position, kAppSnapshotPageSize);
}
int64_t isolate_data_size = header[3];
int64_t isolate_data_size = header[2];
int64_t isolate_data_position = Utils::RoundUp(
vm_instructions_position + vm_instructions_size, kAppSnapshotPageSize);
int64_t isolate_instructions_size = header[4];
int64_t isolate_instructions_size = header[3];
int64_t isolate_instructions_position =
isolate_data_position + isolate_data_size;
if (isolate_instructions_size != 0) {
@ -152,17 +165,10 @@ static AppSnapshot* TryReadAppSnapshotBlobs(const char* script_name,
}
}
return new MappedAppSnapshot(vm_data_mapping, vm_instr_mapping,
isolate_data_mapping, isolate_instr_mapping);
}
static AppSnapshot* TryReadAppSnapshotBlobs(const char* script_name) {
File* file = File::Open(nullptr, script_name, File::kRead);
if (file == nullptr) {
return nullptr;
}
RefCntReleaseScope<File> rs(file);
return TryReadAppSnapshotBlobs(script_name, file);
auto app_snapshot =
new MappedAppSnapshot(vm_data_mapping, vm_instr_mapping,
isolate_data_mapping, isolate_instr_mapping);
return app_snapshot;
}
#if defined(DART_PRECOMPILED_RUNTIME)
@ -173,7 +179,8 @@ class ElfAppSnapshot : public AppSnapshot {
const uint8_t* vm_snapshot_instructions,
const uint8_t* isolate_snapshot_data,
const uint8_t* isolate_snapshot_instructions)
: elf_(elf),
: AppSnapshot{DartUtils::kAotELFMagicNumber},
elf_(elf),
vm_snapshot_data_(vm_snapshot_data),
vm_snapshot_instructions_(vm_snapshot_instructions),
isolate_snapshot_data_(isolate_snapshot_data),
@ -432,7 +439,8 @@ class DylibAppSnapshot : public AppSnapshot {
const uint8_t* vm_snapshot_instructions,
const uint8_t* isolate_snapshot_data,
const uint8_t* isolate_snapshot_instructions)
: library_(library),
: AppSnapshot(DartUtils::kAotELFMagicNumber),
library_(library),
vm_snapshot_data_(vm_snapshot_data),
vm_snapshot_instructions_(vm_snapshot_instructions),
isolate_snapshot_data_(isolate_snapshot_data),
@ -597,11 +605,31 @@ AppSnapshot* Snapshot::TryReadAppSnapshot(const char* script_uri,
// anyway if it was).
return nullptr;
}
AppSnapshot* snapshot = TryReadAppSnapshotBlobs(script_name);
if (snapshot != nullptr) {
return snapshot;
File* file = File::Open(nullptr, script_name, File::kRead);
if (file == nullptr) {
return nullptr;
}
RefCntReleaseScope<File> rs(file);
if ((file->Length() - file->Position()) < DartUtils::kMaxMagicNumberSize) {
return nullptr;
}
uint8_t header[DartUtils::kMaxMagicNumberSize];
ASSERT(sizeof(header) == DartUtils::kMaxMagicNumberSize);
if (!file->ReadFully(&header, DartUtils::kMaxMagicNumberSize)) {
return nullptr;
}
DartUtils::MagicNumber magic_number =
DartUtils::SniffForMagicNumber(header, sizeof(header));
if (magic_number == DartUtils::kAppJITMagicNumber) {
// Return the JIT snapshot.
return TryReadAppSnapshotBlobs(script_name, file);
}
#if defined(DART_PRECOMPILED_RUNTIME)
if (!DartUtils::IsAotMagicNumber(magic_number)) {
return nullptr;
}
// For testing AOT with the standalone embedder, we also support loading
// from a dynamic library to simulate what happens on iOS.
@ -613,16 +641,21 @@ AppSnapshot* Snapshot::TryReadAppSnapshot(const char* script_uri,
script_name = absolute_path.get();
#endif
AppSnapshot* snapshot = nullptr;
if (!force_load_elf_from_memory) {
snapshot = TryReadAppSnapshotDynamicLibrary(script_name);
if (snapshot != nullptr) {
return snapshot;
}
}
return TryReadAppSnapshotElf(script_name, /*file_offset=*/0,
force_load_elf_from_memory);
#else
// We create a dummy snapshot object just to remember the type which
// has already been identified by sniffing the magic number.
return new DummySnapshot(magic_number);
#endif // defined(DART_PRECOMPILED_RUNTIME)
return nullptr;
}
@ -667,7 +700,8 @@ void Snapshot::WriteAppSnapshot(const char* filename,
WriteInt64(file, vm_instructions_size);
WriteInt64(file, isolate_data_size);
WriteInt64(file, isolate_instructions_size);
ASSERT(file->Position() == kAppSnapshotHeaderSize);
ASSERT(file->Position() ==
(kAppSnapshotHeaderSize + DartUtils::kMaxMagicNumberSize));
file->SetPosition(Utils::RoundUp(file->Position(), kAppSnapshotPageSize));
if (LOG_SECTION_BOUNDARIES) {
@ -720,7 +754,7 @@ void Snapshot::GenerateKernel(const char* snapshot_filename,
uint8_t* kernel_buffer = nullptr;
intptr_t kernel_buffer_size = 0;
dfe.ReadScript(script_name, &kernel_buffer, &kernel_buffer_size);
dfe.ReadScript(script_name, nullptr, &kernel_buffer, &kernel_buffer_size);
if (kernel_buffer != nullptr) {
WriteSnapshotFile(snapshot_filename, kernel_buffer, kernel_buffer_size);
free(kernel_buffer);
@ -795,24 +829,5 @@ void Snapshot::GenerateAppAOTAsAssembly(const char* snapshot_filename) {
}
}
bool Snapshot::IsAOTSnapshot(const char* snapshot_filename) {
// Header is simply "ELF" prefixed with the DEL character.
const char elf_header[] = {0x7F, 0x45, 0x4C, 0x46, 0x0};
const int64_t elf_header_len = strlen(elf_header);
File* file = File::Open(nullptr, snapshot_filename, File::kRead);
if (file == nullptr) {
return false;
}
if (file->Length() < elf_header_len) {
file->Release();
return false;
}
auto buf = std::unique_ptr<char[]>(new char[elf_header_len]);
bool success = file->ReadFully(buf.get(), elf_header_len);
file->Release();
ASSERT(success);
return (strncmp(elf_header, buf.get(), elf_header_len) == 0);
}
} // namespace bin
} // namespace dart

View file

@ -5,6 +5,7 @@
#ifndef RUNTIME_BIN_SNAPSHOT_UTILS_H_
#define RUNTIME_BIN_SNAPSHOT_UTILS_H_
#include "bin/dartutils.h"
#include "platform/globals.h"
namespace dart {
@ -19,10 +20,21 @@ class AppSnapshot {
const uint8_t** isolate_data_buffer,
const uint8_t** isolate_instructions_buffer) = 0;
bool IsJIT() const { return magic_number_ == DartUtils::kAppJITMagicNumber; }
bool IsAOT() const { return DartUtils::IsAotMagicNumber(magic_number_); }
bool IsJITorAOT() const { return IsJIT() || IsAOT(); }
bool IsKernel() const {
return magic_number_ == DartUtils::kKernelMagicNumber;
}
bool IsKernelList() const {
return magic_number_ == DartUtils::kKernelListMagicNumber;
}
protected:
AppSnapshot() {}
explicit AppSnapshot(DartUtils::MagicNumber num) : magic_number_(num) {}
private:
DartUtils::MagicNumber magic_number_;
DISALLOW_COPY_AND_ASSIGN(AppSnapshot);
};
@ -34,10 +46,6 @@ class Snapshot {
static void GenerateAppJIT(const char* snapshot_filename);
static void GenerateAppAOTAsAssembly(const char* snapshot_filename);
// Returns true if snapshot_filename points to an AOT snapshot (aka,
// an ELF binary). May report false negatives.
static bool IsAOTSnapshot(const char* snapshot_filename);
#if defined(DART_TARGET_OS_MACOS)
static bool IsMachOFormattedBinary(const char* container_path);
#endif

View file

@ -0,0 +1,7 @@
// Copyright (c) 2024, 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.
/* file: func.dart */
void main() {
print('func.dart');
}

View file

@ -0,0 +1,63 @@
// Copyright (c) 2024, 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:isolate';
import 'dart:io';
import 'package:expect/expect.dart';
import 'package:path/path.dart' as path;
import '../use_flag_test_helper.dart';
void main() async {
var result = 1;
final d = Directory.systemTemp.createTempSync('aot_tmp');
try {
// This test is checking if we get an error when a spawnURI is
// done using an AOT snapshot in a JIT VM and hence is skipped
// for AOT runs.
if (isAOTRuntime) return;
if (Platform.isAndroid || Platform.isIOS) {
return; // SDK tree not available on the test device.
}
// These are the tools we need to be available to run on a given platform:
if (!File(platformDill).existsSync()) {
throw "Cannot run test as $platformDill does not exist";
}
// Generate an AOT snapshot.
final spawnTest =
path.join(sdkDir, 'runtime/tests/vm/dart/isolates/func.dart');
Expect.isTrue(File(spawnTest).existsSync(), "Can't locate $spawnTest");
final kernelOutput = File.fromUri(d.uri.resolve('func.dill')).path;
final aotOutput = File.fromUri(d.uri.resolve('func.aot')).path;
// Compile source to kernel.
var result = Process.runSync(genKernel, <String>[
'--aot',
'--platform=$platformDill',
'-o',
kernelOutput,
spawnTest,
]);
Expect.equals(result.exitCode, 0);
result = Process.runSync(genSnapshot, <String>[
'--snapshot_kind=app-aot-elf',
'--elf=$aotOutput',
kernelOutput,
]);
Expect.equals(result.exitCode, 0);
// Now try spawning an isolate using that AOT file that was just generated.
final isolate = await Isolate.spawnUri(Uri.parse(aotOutput), [], null);
} catch (e) {
Expect.contains("func.aot", e.toString());
result = 0;
} finally {
d.deleteSync(recursive: true);
}
Expect.equals(result, 0);
}

View file

@ -114,8 +114,9 @@ main(List<String> args) async {
path.join(dir, 'does_not_exist.dart.dill.so'),
]);
Expect.notEquals(0, result3.exitCode);
Expect.contains('The uri', result3.stderr);
Expect.contains(
'The uri provided to `Isolate.spawnUri()` does not contain a valid AOT '
'provided to `Isolate.spawnUri()` does not contain a valid AOT '
'snapshot',
result3.stderr);
});

View file

@ -197,6 +197,7 @@ cc/Profiler_TypedArrayAllocation: SkipByDesign
cc/Service_Profile: SkipByDesign
dart/gc/splay_c_finalizer_test: SkipByDesign # No FFI on simulators
dart/isolates/dart_api_create_lightweight_isolate_test: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
dart/isolates/regress_54528_test: SkipByDesign # Invokes gen_kernel/gen_snapshot
dart/isolates/thread_pool_test: SkipByDesign # https://dartbug.com/37299 Test uses dart:ffi which is not supported on simulators.
dart/reachability_test: SkipByDesign # Test takes too long on the simulator
dart/regress_41971_test: SkipByDesign # https://dartbug.com/37299 dart:ffi is not supported on simulator