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 <sjindel@google.com>
> Reviewed-by: Ryan Macnak <rmacnak@google.com>

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 <asiva@google.com>
Commit-Queue: Siva Annamalai <asiva@google.com>
diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart
index b96782c..fdc14d2 100644
--- a/pkg/smith/lib/configuration.dart
+++ b/pkg/smith/lib/configuration.dart
@@ -259,6 +259,7 @@
         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 @@
   final bool useAnalyzerCfe;
   final bool useAnalyzerFastaParser;
 
+  // TODO(rnystrom): What is this?
+  final bool useBlobs;
   final bool useElf;
 
   final bool useHotReload;
@@ -356,6 +359,7 @@
       bool isMinified,
       bool useAnalyzerCfe,
       bool useAnalyzerFastaParser,
+      bool useBlobs,
       bool useElf,
       bool useHotReload,
       bool useHotReloadRollback,
@@ -377,6 +381,7 @@
         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 @@
       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 @@
         isMinified,
         useAnalyzerCfe,
         useAnalyzerFastaParser,
+        useBlobs,
         useElf,
         useHotReload,
         useHotReloadRollback,
@@ -496,6 +503,7 @@
     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 @@
     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 d558cc2..bf2c631 100644
--- a/pkg/smith/test/configuration_test.dart
+++ b/pkg/smith/test/configuration_test.dart
@@ -382,6 +382,7 @@
         isMinified: true,
         useAnalyzerCfe: true,
         useAnalyzerFastaParser: true,
+        useBlobs: true,
         useElf: true,
         useHotReload: true,
         useHotReloadRollback: true,
@@ -411,6 +412,7 @@
    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 7ea9107..938d48c 100644
--- a/pkg/test_runner/lib/src/command.dart
+++ b/pkg/test_runner/lib/src/command.dart
@@ -547,6 +547,7 @@
   final String processTestFilename;
   final String precompiledTestDirectory;
   final List<String> arguments;
+  final bool useBlobs;
   final bool useElf;
   final List<String> extraLibraries;
 
@@ -555,6 +556,7 @@
       this.processTestFilename,
       this.precompiledTestDirectory,
       this.arguments,
+      this.useBlobs,
       this.useElf,
       this.extraLibraries,
       {int index = 0})
@@ -565,6 +567,7 @@
       processTestFilename,
       precompiledTestDirectory,
       arguments,
+      useBlobs,
       useElf,
       extraLibraries,
       index: index);
@@ -579,6 +582,7 @@
     builder.add(buildPath);
     builder.add(precompiledTestDirectory);
     builder.add(arguments);
+    builder.add(useBlobs);
     builder.add(useElf);
     extraLibraries.forEach(builder.add);
   }
@@ -586,6 +590,7 @@
   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 fd48df2..90b6dcd 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -626,7 +626,7 @@
           tempDir, arguments, environmentOverrides));
     }
 
-    if (!_configuration.useElf) {
+    if (!_configuration.useBlobs && !_configuration.useElf) {
       commands.add(
           computeAssembleCommand(tempDir, arguments, environmentOverrides));
       if (!_configuration.keepGeneratedFiles) {
@@ -698,7 +698,10 @@
     }
 
     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 63fc701..4982613 100644
--- a/pkg/test_runner/lib/src/configuration.dart
+++ b/pkg/test_runner/lib/src/configuration.dart
@@ -115,6 +115,7 @@
   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 95f9217..09a824c 100644
--- a/pkg/test_runner/lib/src/options.dart
+++ b/pkg/test_runner/lib/src/options.dart
@@ -816,6 +816,7 @@
                   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 1bb10ab..05fbe2b 100644
--- a/pkg/test_runner/lib/src/runtime_configuration.dart
+++ b/pkg/test_runner/lib/src/runtime_configuration.dart
@@ -48,10 +48,12 @@
       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 DartPrecompiledRuntimeConfiguration extends DartVmRuntimeConfiguration {
+  final bool useBlobs;
   final bool useElf;
-  DartPrecompiledRuntimeConfiguration({bool useElf}) : useElf = useElf;
+  DartPrecompiledRuntimeConfiguration({bool useBlobs, bool useElf})
+      : useBlobs = useBlobs,
+        useElf = useElf;
 
   List<Command> computeRuntimeCommands(
       CommandArtifact artifact,
@@ -335,8 +340,11 @@
   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<Command> computeRuntimeCommands(
       CommandArtifact artifact,
@@ -353,7 +361,7 @@
     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 568fa5f..93db88b 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -81,6 +81,7 @@
   kCoreJIT,
   kApp,
   kAppJIT,
+  kAppAOTBlobs,
   kAppAOTAssembly,
   kAppAOTElf,
   kVMAOTAssembly,
@@ -94,6 +95,7 @@
     "core-jit",
     "app",
     "app-jit",
+    "app-aot-blobs",
     "app-aot-assembly",
     "app-aot-elf",
     "vm-aot-assembly",
@@ -144,7 +146,8 @@
 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 @@
       }
       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 @@
           "         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 @@
       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 36f6293..bf9d270 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -509,6 +509,29 @@
 #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 e84014c..b17875c 100644
--- a/runtime/bin/snapshot_utils.h
+++ b/runtime/bin/snapshot_utils.h
@@ -32,6 +32,7 @@
                              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 1679968..c68de7b 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -3481,6 +3481,31 @@
                                    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
  * more efficient and is done before writing snapshots.
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index 490114e..0a40666 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -473,6 +473,14 @@
 
 #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 665e212..601099c 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -6241,6 +6241,78 @@
 #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 b8afa52..d1bd1bf 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -1028,8 +1028,8 @@
       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 @@
       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 @@
       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 @@
 #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 @@
       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<compiler::target::word*>(
-          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<compiler::target::word*>(
+            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 @@
 #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 f7e931e..c28ef48 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -15880,6 +15880,24 @@
   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<word*>(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 3d67731..8b8f9fa 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -5815,6 +5815,9 @@
 
   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 f327d2d..24f9e46 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"
         ]