From edd64e6d5c7924a5fb1ef80c5226d24006e7977b Mon Sep 17 00:00:00 2001 From: Siva Annamalai Date: Fri, 14 Feb 2020 06:40:31 +0000 Subject: [PATCH] Revert "[vm] AOT blobs snapshots are obsolete. Remove dead code." This reverts commit bcc0900e6ac2fc971869153b2e825d9b7b77bda8. Reason for revert: This CL is breaking the Fuchsia Flutter build see https://github.com/flutter/engine/pull/16604/checks?check_run_id=445155807 Original change's description: > [vm] AOT blobs snapshots are obsolete. Remove dead code. > > Change-Id: I35cf4befbe66b92197dcd659172f90be3de30f8e > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134840 > Commit-Queue: Samir Jindel > Reviewed-by: Ryan Macnak TBR=rmacnak@google.com,sjindel@google.com Change-Id: I9dd32a71bf43907f59ed766b98bf453bab99ea3c No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135881 Reviewed-by: Siva Annamalai Commit-Queue: Siva Annamalai --- pkg/smith/lib/configuration.dart | 9 ++ pkg/smith/test/configuration_test.dart | 2 + pkg/test_runner/lib/src/command.dart | 5 ++ .../lib/src/compiler_configuration.dart | 7 +- pkg/test_runner/lib/src/configuration.dart | 1 + pkg/test_runner/lib/src/options.dart | 1 + .../lib/src/runtime_configuration.dart | 14 +++- runtime/bin/gen_snapshot.cc | 82 ++++++++++++++++++- runtime/bin/snapshot_utils.cc | 23 ++++++ runtime/bin/snapshot_utils.h | 1 + runtime/include/dart_api.h | 25 ++++++ runtime/lib/ffi.cc | 8 ++ runtime/vm/dart_api_impl.cc | 72 ++++++++++++++++ runtime/vm/image_snapshot.cc | 72 +++++++++------- runtime/vm/object.cc | 18 ++++ runtime/vm/object.h | 3 + tools/bots/test_matrix.json | 6 +- 17 files changed, 309 insertions(+), 40 deletions(-) diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart index b96782c5c55..fdc14d2ba17 100644 --- a/pkg/smith/lib/configuration.dart +++ b/pkg/smith/lib/configuration.dart @@ -259,6 +259,7 @@ class Configuration { isMinified: boolOption("minified"), useAnalyzerCfe: boolOption("use-cfe"), useAnalyzerFastaParser: boolOption("analyzer-use-fasta-parser"), + useBlobs: boolOption("use-blobs"), useElf: boolOption("use-elf"), useHotReload: boolOption("hot-reload"), useHotReloadRollback: boolOption("hot-reload-rollback"), @@ -329,6 +330,8 @@ class Configuration { final bool useAnalyzerCfe; final bool useAnalyzerFastaParser; + // TODO(rnystrom): What is this? + final bool useBlobs; final bool useElf; final bool useHotReload; @@ -356,6 +359,7 @@ class Configuration { bool isMinified, bool useAnalyzerCfe, bool useAnalyzerFastaParser, + bool useBlobs, bool useElf, bool useHotReload, bool useHotReloadRollback, @@ -377,6 +381,7 @@ class Configuration { isMinified = isMinified ?? false, useAnalyzerCfe = useAnalyzerCfe ?? false, useAnalyzerFastaParser = useAnalyzerFastaParser ?? false, + useBlobs = useBlobs ?? false, useElf = useElf ?? false, useHotReload = useHotReload ?? false, useHotReloadRollback = useHotReloadRollback ?? false, @@ -407,6 +412,7 @@ class Configuration { isMinified == other.isMinified && useAnalyzerCfe == other.useAnalyzerCfe && useAnalyzerFastaParser == other.useAnalyzerFastaParser && + useBlobs == other.useBlobs && useElf == other.useElf && useHotReload == other.useHotReload && useHotReloadRollback == other.useHotReloadRollback && @@ -456,6 +462,7 @@ class Configuration { isMinified, useAnalyzerCfe, useAnalyzerFastaParser, + useBlobs, useElf, useHotReload, useHotReloadRollback, @@ -496,6 +503,7 @@ class Configuration { if (isMinified) fields.add("minified"); if (useAnalyzerCfe) fields.add("use-cfe"); if (useAnalyzerFastaParser) fields.add("analyzer-use-fasta-parser"); + if (useBlobs) fields.add("use-blobs"); if (useHotReload) fields.add("hot-reload"); if (useHotReloadRollback) fields.add("hot-reload-rollback"); if (useSdk) fields.add("use-sdk"); @@ -553,6 +561,7 @@ class Configuration { boolField("use-cfe", useAnalyzerCfe, other.useAnalyzerCfe); boolField("analyzer-use-fasta-parser", useAnalyzerFastaParser, other.useAnalyzerFastaParser); + boolField("use-blobs", useBlobs, other.useBlobs); boolField("host-checked", isHostChecked, other.isHostChecked); boolField("hot-reload", useHotReload, other.useHotReload); boolField("hot-reload-rollback", useHotReloadRollback, diff --git a/pkg/smith/test/configuration_test.dart b/pkg/smith/test/configuration_test.dart index d558cc2bc48..bf2c63165d5 100644 --- a/pkg/smith/test/configuration_test.dart +++ b/pkg/smith/test/configuration_test.dart @@ -382,6 +382,7 @@ void main() { isMinified: true, useAnalyzerCfe: true, useAnalyzerFastaParser: true, + useBlobs: true, useElf: true, useHotReload: true, useHotReloadRollback: true, @@ -411,6 +412,7 @@ architecture: ia32 x64 minified: false true use-cfe: false true analyzer-use-fasta-parser: false true + use-blobs: false true host-checked: false true hot-reload: false true hot-reload-rollback: false true diff --git a/pkg/test_runner/lib/src/command.dart b/pkg/test_runner/lib/src/command.dart index 7ea9107ae38..938d48c45eb 100644 --- a/pkg/test_runner/lib/src/command.dart +++ b/pkg/test_runner/lib/src/command.dart @@ -547,6 +547,7 @@ class AdbPrecompilationCommand extends Command implements AdbCommand { final String processTestFilename; final String precompiledTestDirectory; final List arguments; + final bool useBlobs; final bool useElf; final List extraLibraries; @@ -555,6 +556,7 @@ class AdbPrecompilationCommand extends Command implements AdbCommand { this.processTestFilename, this.precompiledTestDirectory, this.arguments, + this.useBlobs, this.useElf, this.extraLibraries, {int index = 0}) @@ -565,6 +567,7 @@ class AdbPrecompilationCommand extends Command implements AdbCommand { processTestFilename, precompiledTestDirectory, arguments, + useBlobs, useElf, extraLibraries, index: index); @@ -579,6 +582,7 @@ class AdbPrecompilationCommand extends Command implements AdbCommand { builder.add(buildPath); builder.add(precompiledTestDirectory); builder.add(arguments); + builder.add(useBlobs); builder.add(useElf); extraLibraries.forEach(builder.add); } @@ -586,6 +590,7 @@ class AdbPrecompilationCommand extends Command implements AdbCommand { bool _equal(AdbPrecompilationCommand other) => super._equal(other) && buildPath == other.buildPath && + useBlobs == other.useBlobs && useElf == other.useElf && arguments == other.arguments && precompiledTestDirectory == other.precompiledTestDirectory && diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart index fd48df20664..90b6dcd5b4b 100644 --- a/pkg/test_runner/lib/src/compiler_configuration.dart +++ b/pkg/test_runner/lib/src/compiler_configuration.dart @@ -626,7 +626,7 @@ class PrecompilerCompilerConfiguration extends CompilerConfiguration tempDir, arguments, environmentOverrides)); } - if (!_configuration.useElf) { + if (!_configuration.useBlobs && !_configuration.useElf) { commands.add( computeAssembleCommand(tempDir, arguments, environmentOverrides)); if (!_configuration.keepGeneratedFiles) { @@ -698,7 +698,10 @@ class PrecompilerCompilerConfiguration extends CompilerConfiguration } var args = [ - if (_configuration.useElf) ...[ + if (_configuration.useBlobs) ...[ + "--snapshot-kind=app-aot-blobs", + "--blobs_container_filename=$tempDir/out.aotsnapshot" + ] else if (_configuration.useElf) ...[ "--snapshot-kind=app-aot-elf", "--elf=$tempDir/out.aotsnapshot" ] else ...[ diff --git a/pkg/test_runner/lib/src/configuration.dart b/pkg/test_runner/lib/src/configuration.dart index 63fc701dbd7..49826130d1e 100644 --- a/pkg/test_runner/lib/src/configuration.dart +++ b/pkg/test_runner/lib/src/configuration.dart @@ -115,6 +115,7 @@ class TestConfiguration { bool get isMinified => configuration.isMinified; bool get useAnalyzerCfe => configuration.useAnalyzerCfe; bool get useAnalyzerFastaParser => configuration.useAnalyzerFastaParser; + bool get useBlobs => configuration.useBlobs; bool get useElf => configuration.useElf; bool get useSdk => configuration.useSdk; bool get enableAsserts => configuration.enableAsserts; diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart index 95f92173696..09a824c42f0 100644 --- a/pkg/test_runner/lib/src/options.dart +++ b/pkg/test_runner/lib/src/options.dart @@ -816,6 +816,7 @@ compiler.''', useAnalyzerCfe: data["use_cfe"] as bool, useAnalyzerFastaParser: data["analyzer_use_fasta_parser"] as bool, + useBlobs: data["use_blobs"] as bool, useElf: data["use_elf"] as bool, useSdk: data["use_sdk"] as bool, useHotReload: data["hot_reload"] as bool, diff --git a/pkg/test_runner/lib/src/runtime_configuration.dart b/pkg/test_runner/lib/src/runtime_configuration.dart index 1bb10ab0237..05fbe2b2060 100644 --- a/pkg/test_runner/lib/src/runtime_configuration.dart +++ b/pkg/test_runner/lib/src/runtime_configuration.dart @@ -48,10 +48,12 @@ abstract class RuntimeConfiguration { case Runtime.dartPrecompiled: if (configuration.system == System.android) { return DartPrecompiledAdbRuntimeConfiguration( + useBlobs: configuration.useBlobs, useElf: configuration.useElf, ); } else { return DartPrecompiledRuntimeConfiguration( + useBlobs: configuration.useBlobs, useElf: configuration.useElf, ); } @@ -280,8 +282,11 @@ class StandaloneDartRuntimeConfiguration extends DartVmRuntimeConfiguration { } class DartPrecompiledRuntimeConfiguration extends DartVmRuntimeConfiguration { + final bool useBlobs; final bool useElf; - DartPrecompiledRuntimeConfiguration({bool useElf}) : useElf = useElf; + DartPrecompiledRuntimeConfiguration({bool useBlobs, bool useElf}) + : useBlobs = useBlobs, + useElf = useElf; List computeRuntimeCommands( CommandArtifact artifact, @@ -335,8 +340,11 @@ class DartPrecompiledAdbRuntimeConfiguration static const deviceDir = '/data/local/tmp/precompilation-testing'; static const deviceTestDir = '/data/local/tmp/precompilation-testing/test'; + final bool useBlobs; final bool useElf; - DartPrecompiledAdbRuntimeConfiguration({bool useElf}) : useElf = useElf; + DartPrecompiledAdbRuntimeConfiguration({bool useBlobs, bool useElf}) + : useBlobs = useBlobs, + useElf = useElf; List computeRuntimeCommands( CommandArtifact artifact, @@ -353,7 +361,7 @@ class DartPrecompiledAdbRuntimeConfiguration var processTest = processTestBinaryFileName; return [ AdbPrecompilationCommand( - buildDir, processTest, script, arguments, useElf, extraLibs) + buildDir, processTest, script, arguments, useBlobs, useElf, extraLibs) ]; } } diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc index 568fa5f570c..93db88bdce7 100644 --- a/runtime/bin/gen_snapshot.cc +++ b/runtime/bin/gen_snapshot.cc @@ -81,6 +81,7 @@ enum SnapshotKind { kCoreJIT, kApp, kAppJIT, + kAppAOTBlobs, kAppAOTAssembly, kAppAOTElf, kVMAOTAssembly, @@ -94,6 +95,7 @@ static const char* kSnapshotKindNames[] = { "core-jit", "app", "app-jit", + "app-aot-blobs", "app-aot-assembly", "app-aot-elf", "vm-aot-assembly", @@ -144,7 +146,8 @@ DEFINE_ENUM_OPTION(snapshot_kind, SnapshotKind, snapshot_kind); DEFINE_CB_OPTION(ProcessEnvironmentOption); static bool IsSnapshottingForPrecompilation() { - return (snapshot_kind == kAppAOTAssembly) || (snapshot_kind == kAppAOTElf) || + return (snapshot_kind == kAppAOTBlobs) || + (snapshot_kind == kAppAOTAssembly) || (snapshot_kind == kAppAOTElf) || (snapshot_kind == kVMAOTAssembly); } @@ -283,6 +286,34 @@ static int ParseArguments(int argc, } break; } + case kAppAOTBlobs: { + if ((blobs_container_filename == NULL) && + ((vm_snapshot_data_filename == NULL) || + (vm_snapshot_instructions_filename == NULL) || + (isolate_snapshot_data_filename == NULL) || + (isolate_snapshot_instructions_filename == NULL))) { + Syslog::PrintErr( + "Building an AOT snapshot as blobs requires specifying output " + "file for --blobs_container_filename or " + "files for --vm_snapshot_data, --vm_snapshot_instructions, " + "--isolate_snapshot_data and --isolate_snapshot_instructions.\n\n"); + return -1; + } + if ((blobs_container_filename != NULL) && + ((vm_snapshot_data_filename != NULL) || + (vm_snapshot_instructions_filename != NULL) || + (isolate_snapshot_data_filename != NULL) || + (isolate_snapshot_instructions_filename != NULL))) { + Syslog::PrintErr( + "Building an AOT snapshot as blobs requires specifying output " + "file for --blobs_container_filename or " + "files for --vm_snapshot_data, --vm_snapshot_instructions, " + "--isolate_snapshot_data and --isolate_snapshot_instructions" + " not both.\n\n"); + return -1; + } + break; + } case kAppAOTElf: { if (elf_filename == NULL) { Syslog::PrintErr( @@ -638,6 +669,54 @@ static void CreateAndWritePrecompiledSnapshot() { " To avoid this, use --strip to remove it and " "--save-debugging-info=<...> to save it to a separate file.\n"); } + } else if (snapshot_kind == kAppAOTBlobs) { + Syslog::PrintErr( + "WARNING: app-aot-blobs snapshots have been deprecated and support for " + "generating them will be removed soon. Please use the app-aot-elf or " + "app-aot-assembly snapshot kinds in conjunction with the portable ELF " + "loader from //runtime/bin:elf_loader if necessary. See " + "http://dartbug.com/38764 for more details.\n"); + + uint8_t* vm_snapshot_data_buffer = NULL; + intptr_t vm_snapshot_data_size = 0; + uint8_t* vm_snapshot_instructions_buffer = NULL; + intptr_t vm_snapshot_instructions_size = 0; + uint8_t* isolate_snapshot_data_buffer = NULL; + intptr_t isolate_snapshot_data_size = 0; + uint8_t* isolate_snapshot_instructions_buffer = NULL; + intptr_t isolate_snapshot_instructions_size = 0; + File* debug_file = nullptr; + if (debugging_info_filename != nullptr) { + debug_file = OpenFile(debugging_info_filename); + } + result = Dart_CreateAppAOTSnapshotAsBlobs( + &vm_snapshot_data_buffer, &vm_snapshot_data_size, + &vm_snapshot_instructions_buffer, &vm_snapshot_instructions_size, + &isolate_snapshot_data_buffer, &isolate_snapshot_data_size, + &isolate_snapshot_instructions_buffer, + &isolate_snapshot_instructions_size, StreamingWriteCallback, + debug_file); + if (debug_file != nullptr) debug_file->Release(); + CHECK_RESULT(result); + + if (blobs_container_filename != NULL) { + Snapshot::WriteAppSnapshot( + blobs_container_filename, vm_snapshot_data_buffer, + vm_snapshot_data_size, vm_snapshot_instructions_buffer, + vm_snapshot_instructions_size, isolate_snapshot_data_buffer, + isolate_snapshot_data_size, isolate_snapshot_instructions_buffer, + isolate_snapshot_instructions_size); + } else { + WriteFile(vm_snapshot_data_filename, vm_snapshot_data_buffer, + vm_snapshot_data_size); + WriteFile(vm_snapshot_instructions_filename, + vm_snapshot_instructions_buffer, vm_snapshot_instructions_size); + WriteFile(isolate_snapshot_data_filename, isolate_snapshot_data_buffer, + isolate_snapshot_data_size); + WriteFile(isolate_snapshot_instructions_filename, + isolate_snapshot_instructions_buffer, + isolate_snapshot_instructions_size); + } } else { UNREACHABLE(); } @@ -747,6 +826,7 @@ static int CreateIsolateAndSnapshot(const CommandLineOptions& inputs) { CreateAndWriteAppJITSnapshot(); break; case kAppAOTAssembly: + case kAppAOTBlobs: case kAppAOTElf: CreateAndWritePrecompiledSnapshot(); break; diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc index 36f629387cf..bf9d2704e22 100644 --- a/runtime/bin/snapshot_utils.cc +++ b/runtime/bin/snapshot_utils.cc @@ -509,6 +509,29 @@ void Snapshot::GenerateAppJIT(const char* snapshot_filename) { #endif } +void Snapshot::GenerateAppAOTAsBlobs(const char* snapshot_filename) { + uint8_t* vm_data_buffer = NULL; + intptr_t vm_data_size = 0; + uint8_t* vm_instructions_buffer = NULL; + intptr_t vm_instructions_size = 0; + uint8_t* isolate_data_buffer = NULL; + intptr_t isolate_data_size = 0; + uint8_t* isolate_instructions_buffer = NULL; + intptr_t isolate_instructions_size = 0; + Dart_Handle result = Dart_CreateAppAOTSnapshotAsBlobs( + &vm_data_buffer, &vm_data_size, &vm_instructions_buffer, + &vm_instructions_size, &isolate_data_buffer, &isolate_data_size, + &isolate_instructions_buffer, &isolate_instructions_size, + /*callback=*/nullptr, /*debug_callback_info=*/nullptr); + if (Dart_IsError(result)) { + ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); + } + WriteAppSnapshot(snapshot_filename, vm_data_buffer, vm_data_size, + vm_instructions_buffer, vm_instructions_size, + isolate_data_buffer, isolate_data_size, + isolate_instructions_buffer, isolate_instructions_size); +} + static void StreamingWriteCallback(void* callback_data, const uint8_t* buffer, intptr_t size) { diff --git a/runtime/bin/snapshot_utils.h b/runtime/bin/snapshot_utils.h index e84014cf3e3..b17875ce5c5 100644 --- a/runtime/bin/snapshot_utils.h +++ b/runtime/bin/snapshot_utils.h @@ -32,6 +32,7 @@ class Snapshot { const char* script_name, const char* package_config); static void GenerateAppJIT(const char* snapshot_filename); + static void GenerateAppAOTAsBlobs(const char* snapshot_filename); static void GenerateAppAOTAsAssembly(const char* snapshot_filename); static AppSnapshot* TryReadAppendedAppSnapshotElf(const char* container_path); diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h index 167996841f9..c68de7b976c 100644 --- a/runtime/include/dart_api.h +++ b/runtime/include/dart_api.h @@ -3480,6 +3480,31 @@ DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_CreateVMAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback, void* callback_data); +/** + * Same as Dart_CreateAppAOTSnapshotAsAssembly, except all the pieces are + * provided directly as bytes that the embedder can load with mmap. The + * instructions pieces must be loaded with read and execute permissions; the + * other pieces may be loaded as read-only. + * + * This function has been DEPRECATED. Please use Dart_CreateAppAOTSnapshotAsELF + * or Dart_CreateAppAOTSnapshotAsAssembly instead. A portable ELF loader is + * available in the target //runtime/bin:elf_loader. + * + * If callback and debug_callback_data are provided, debug_callback_data will + * be used with the callback to provide separate debugging information. + */ +DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle +Dart_CreateAppAOTSnapshotAsBlobs(uint8_t** vm_snapshot_data_buffer, + intptr_t* vm_snapshot_data_size, + uint8_t** vm_snapshot_instructions_buffer, + intptr_t* vm_snapshot_instructions_size, + uint8_t** isolate_snapshot_data_buffer, + intptr_t* isolate_snapshot_data_size, + uint8_t** isolate_snapshot_instructions_buffer, + intptr_t* isolate_snapshot_instructions_size, + Dart_StreamingWriteCallback callback, + void* debug_callback_data); + /** * Sorts the class-ids in depth first traversal order of the inheritance * tree. This is a costly operation, but it can make method dispatch diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc index 490114efe32..0a40666f0a1 100644 --- a/runtime/lib/ffi.cc +++ b/runtime/lib/ffi.cc @@ -473,6 +473,14 @@ DEFINE_NATIVE_ENTRY(Ffi_pointerFromFunction, 1, 1) { #if defined(DART_PRECOMPILED_RUNTIME) code = function.CurrentCode(); + + // Blobs snapshots don't support BSS-relative relocations required by native + // callbacks (yet). Issue an error if the code has an unpatched relocation. + if (!code.VerifyBSSRelocations()) { + Exceptions::ThrowUnsupportedError( + "FFI callbacks are not yet supported in blobs snapshots. Please use " + "ELF or Assembly snapshots instead."); + } #else // We compile the callback immediately because we need to return a pointer to // the entry-point. Native calls do not use patching like Dart calls, so we diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index 665e212f803..601099c4db1 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -6241,6 +6241,78 @@ Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback, #endif } +DART_EXPORT Dart_Handle +Dart_CreateAppAOTSnapshotAsBlobs(uint8_t** vm_snapshot_data_buffer, + intptr_t* vm_snapshot_data_size, + uint8_t** vm_snapshot_instructions_buffer, + intptr_t* vm_snapshot_instructions_size, + uint8_t** isolate_snapshot_data_buffer, + intptr_t* isolate_snapshot_data_size, + uint8_t** isolate_snapshot_instructions_buffer, + intptr_t* isolate_snapshot_instructions_size, + Dart_StreamingWriteCallback callback, + void* debug_callback_data) { +#if defined(TARGET_ARCH_IA32) + return Api::NewError("AOT compilation is not supported on IA32."); +#elif !defined(DART_PRECOMPILER) + return Api::NewError( + "This VM was built without support for AOT compilation."); +#else + DARTSCOPE(Thread::Current()); + API_TIMELINE_DURATION(T); + Isolate* I = T->isolate(); + if (I->compilation_allowed()) { + return Api::NewError( + "Isolate is not precompiled. " + "Did you forget to call Dart_Precompile?"); + } + CHECK_NULL(vm_snapshot_data_buffer); + CHECK_NULL(vm_snapshot_data_size); + CHECK_NULL(vm_snapshot_instructions_buffer); + CHECK_NULL(vm_snapshot_instructions_size); + CHECK_NULL(isolate_snapshot_data_buffer); + CHECK_NULL(isolate_snapshot_data_size); + CHECK_NULL(isolate_snapshot_instructions_buffer); + CHECK_NULL(isolate_snapshot_instructions_size); + + TIMELINE_DURATION(T, Isolate, "WriteAppAOTSnapshot"); + + const bool generate_debug = debug_callback_data != nullptr; + + StreamingWriteStream debug_stream(generate_debug ? kInitialDebugSize : 0, + callback, debug_callback_data); + + Elf* elf = nullptr; + Dwarf* dwarf = nullptr; + if (generate_debug) { + elf = new (Z) Elf(Z, &debug_stream); + dwarf = new (Z) Dwarf(Z, nullptr, elf); + } + + BlobImageWriter vm_image_writer(T, vm_snapshot_instructions_buffer, + ApiReallocate, kInitialSize, dwarf); + BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer, + ApiReallocate, kInitialSize, dwarf); + FullSnapshotWriter writer(Snapshot::kFullAOT, vm_snapshot_data_buffer, + isolate_snapshot_data_buffer, ApiReallocate, + &vm_image_writer, &isolate_image_writer); + + writer.WriteFullSnapshot(); + *vm_snapshot_data_size = writer.VmIsolateSnapshotSize(); + *vm_snapshot_instructions_size = vm_image_writer.InstructionsBlobSize(); + *isolate_snapshot_data_size = writer.IsolateSnapshotSize(); + *isolate_snapshot_instructions_size = + isolate_image_writer.InstructionsBlobSize(); + + if (generate_debug) { + dwarf->Write(); + elf->Finalize(); + } + + return Api::Success(); +#endif +} + #if (!defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)) // Any flag that affects how we compile code might cause a problem when the diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc index b8afa524147..d1bd1bf4a00 100644 --- a/runtime/vm/image_snapshot.cc +++ b/runtime/vm/image_snapshot.cc @@ -1028,8 +1028,8 @@ BlobImageWriter::BlobImageWriter(Thread* thread, bss_base_(bss_base), debug_dwarf_(debug_dwarf) { #if defined(DART_PRECOMPILER) - RELEASE_ASSERT(elf_ != nullptr && - (elf_dwarf_ == nullptr || elf_dwarf_->elf() == elf_)); + RELEASE_ASSERT(elf_ == nullptr || elf_dwarf_ == nullptr || + elf_dwarf_->elf() == elf_); #else RELEASE_ASSERT(elf_ == nullptr); RELEASE_ASSERT(elf_dwarf_ == nullptr); @@ -1048,9 +1048,10 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { FLAG_precompiled_mode && FLAG_use_bare_instructions; #ifdef DART_PRECOMPILER - ASSERT(elf_ != nullptr); intptr_t segment_base = 0; - segment_base = elf_->NextMemoryOffset(); + if (elf_ != nullptr) { + segment_base = elf_->NextMemoryOffset(); + } intptr_t debug_segment_base = 0; if (debug_dwarf_ != nullptr) { debug_segment_base = debug_dwarf_->elf()->NextMemoryOffset(); @@ -1063,7 +1064,8 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { next_text_offset_, compiler::target::ObjectAlignment::kObjectAlignment); instructions_blob_stream_.WriteTargetWord(image_size); #if defined(DART_PRECOMPILER) - instructions_blob_stream_.WriteTargetWord(bss_base_ - segment_base); + instructions_blob_stream_.WriteTargetWord( + elf_ != nullptr ? bss_base_ - segment_base : 0); #else instructions_blob_stream_.WriteTargetWord(0); // No relocations. #endif @@ -1210,7 +1212,7 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { #endif #if defined(DART_PRECOMPILER) - if (elf_dwarf_ != nullptr) { + if (elf_ != nullptr && elf_dwarf_ != nullptr) { const auto& code = *instructions_[i].code_; auto const virtual_address = segment_base + payload_stream_start; elf_dwarf_->AddCode(code, virtual_address); @@ -1223,33 +1225,39 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { debug_dwarf_->AddCode(code, virtual_address); } - const intptr_t current_stream_position = - instructions_blob_stream_.Position(); + // Don't patch the relocation if we're not generating ELF. The regular blobs + // format does not yet support these relocations. Use + // Code::VerifyBSSRelocations to check whether the relocations are patched + // or not after loading. + if (elf_ != nullptr) { + const intptr_t current_stream_position = + instructions_blob_stream_.Position(); - descriptors = data.code_->pc_descriptors(); + descriptors = data.code_->pc_descriptors(); - PcDescriptors::Iterator iterator( - descriptors, /*kind_mask=*/RawPcDescriptors::kBSSRelocation); + PcDescriptors::Iterator iterator( + descriptors, /*kind_mask=*/RawPcDescriptors::kBSSRelocation); - while (iterator.MoveNext()) { - const intptr_t reloc_offset = iterator.PcOffset(); + while (iterator.MoveNext()) { + const intptr_t reloc_offset = iterator.PcOffset(); - // The instruction stream at the relocation position holds an offset - // into BSS corresponding to the symbol being resolved. This addend is - // factored into the relocation. - const auto addend = *reinterpret_cast( - insns.PayloadStart() + reloc_offset); + // The instruction stream at the relocation position holds an offset + // into BSS corresponding to the symbol being resolved. This addend is + // factored into the relocation. + const auto addend = *reinterpret_cast( + insns.PayloadStart() + reloc_offset); - // Overwrite the relocation position in the instruction stream with the - // (positive) offset of the start of the payload from the start of the - // BSS segment plus the addend in the relocation. - instructions_blob_stream_.SetPosition(payload_stream_start + - reloc_offset); + // Overwrite the relocation position in the instruction stream with the + // (positive) offset of the start of the payload from the start of the + // BSS segment plus the addend in the relocation. + instructions_blob_stream_.SetPosition(payload_stream_start + + reloc_offset); - const compiler::target::word offset = - bss_base_ - (segment_base + payload_stream_start + reloc_offset) + - addend; - instructions_blob_stream_.WriteTargetWord(offset); + const compiler::target::word offset = + bss_base_ - (segment_base + payload_stream_start + reloc_offset) + + addend; + instructions_blob_stream_.WriteTargetWord(offset); + } // Restore stream position after the relocation was patched. instructions_blob_stream_.SetPosition(current_stream_position); @@ -1273,10 +1281,12 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { #ifdef DART_PRECOMPILER const char* instructions_symbol = vm ? "_kDartVmSnapshotInstructions" : "_kDartIsolateSnapshotInstructions"; - auto const segment_base2 = - elf_->AddText(instructions_symbol, instructions_blob_stream_.buffer(), - instructions_blob_stream_.bytes_written()); - ASSERT(segment_base == segment_base2); + if (elf_ != nullptr) { + auto const segment_base2 = + elf_->AddText(instructions_symbol, instructions_blob_stream_.buffer(), + instructions_blob_stream_.bytes_written()); + ASSERT(segment_base == segment_base2); + } if (debug_dwarf_ != nullptr) { auto const debug_segment_base2 = debug_dwarf_->elf()->AddText( instructions_symbol, instructions_blob_stream_.buffer(), diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index f7e931e87cf..c28ef48d087 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -15880,6 +15880,24 @@ void Code::DumpSourcePositions(bool relative_addresses) const { reader.DumpSourcePositions(relative_addresses ? 0 : PayloadStart()); } +bool Code::VerifyBSSRelocations() const { + const auto& descriptors = PcDescriptors::Handle(pc_descriptors()); + PcDescriptors::Iterator iterator(descriptors, + RawPcDescriptors::kBSSRelocation); + while (iterator.MoveNext()) { + const uword reloc = PayloadStart() + iterator.PcOffset(); + const word target = *reinterpret_cast(reloc); + // The relocation is in its original unpatched form -- the addend + // representing the target symbol itself. + if (target >= 0 && + target < + BSS::RelocationIndex(BSS::Relocation::NumRelocations) * kWordSize) { + return false; + } + } + return true; +} + void Bytecode::Disassemble(DisassemblyFormatter* formatter) const { #if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER) #if !defined(DART_PRECOMPILED_RUNTIME) diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 3d67731bc87..8b8f9fad063 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -5815,6 +5815,9 @@ class Code : public Object { void Disassemble(DisassemblyFormatter* formatter = NULL) const; + // Returns true if all BSS relocations in the code have been patched. + bool VerifyBSSRelocations() const; + class Comments : public ZoneAllocated { public: static Comments& New(intptr_t count); diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json index f327d2dd7dc..24f9e46b066 100644 --- a/tools/bots/test_matrix.json +++ b/tools/bots/test_matrix.json @@ -625,7 +625,7 @@ "dartk-android-(debug|product|release)-(arm|arm64)": {}, "dartkp-(linux|win|mac)-(debug|product|release)-(simarm|simarm64)": { "options": { - "use-elf": true + "use-blobs": true } }, "dartkp-linux-(debug|product|release)-simarm-crossword": { @@ -636,7 +636,7 @@ "dartkp-(win|mac)-(debug|product|release)-simarm-crossword": { "options": { "builder-tag": "crossword", - "use-elf": true + "use-blobs": true } }, "dartkp-win-(product|release)-x64": { @@ -713,7 +713,7 @@ "dartkp-(linux|mac)-(debug|product|release)-simarm64-ast": { "options": { "builder-tag": "ast", - "use-elf": true, + "use-blobs": true, "gen-kernel-options": [ "--no-gen-bytecode" ]