[vm, test] Enable some AOT testing for Fuchsia.

Fix the standalone embedder's ELF loader to open files with the executable permission.

TEST=ci
Bug: b/399714829
Bug: https://github.com/dart-lang/sdk/issues/60442
Cq-Include-Trybots: luci.dart.try:vm-fuchsia-release-arm64-try,vm-fuchsia-release-x64-try
Change-Id: I2652a5849462ce63585550e6c581cc578a228955
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/419341
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Zijie He <zijiehe@google.com>
This commit is contained in:
Ryan Macnak
2025-04-01 09:50:12 -07:00
committed by Commit Queue
parent 9cd4cdf351
commit 4ab313cf09
15 changed files with 145 additions and 48 deletions
+16 -3
View File
@@ -225,12 +225,13 @@ group("compressed_observatory_archive") {
if (is_fuchsia) {
import("third_party/fuchsia/gn-sdk/src/component.gni")
import("third_party/fuchsia/gn-sdk/src/package.gni")
import("utils/aot_snapshot.gni")
import("utils/application_snapshot.gni")
# TODO(b/399714829): Test packages should be created at test-time, not build-time.
# tests/ffi/**_test.dart except those with compile-time errors
test_sources = [
"tests/ffi/abi_specific_int_incomplete_aot_test.dart",
"tests/ffi/abi_specific_int_incomplete_jit_test.dart",
"tests/ffi/abi_specific_int_test.dart",
"tests/ffi/abi_test.dart",
"tests/ffi/address_of_array_generated_test.dart",
@@ -393,6 +394,7 @@ if (is_fuchsia) {
test_resources = []
foreach(test_source, test_sources) {
label = string_replace(test_source, "/", "_")
aot_label = label + "_aot"
application_snapshot(label) {
dart_snapshot_kind = "kernel"
@@ -400,13 +402,24 @@ if (is_fuchsia) {
training_args = [] # Not used
output = "$target_gen_dir/$test_source.dill"
}
aot_snapshot(aot_label) {
main_dart = test_source
output = "$target_gen_dir/$test_source.elf"
}
test_deps += [ ":$label" ]
test_deps += [
":$aot_label",
":$label",
]
test_resources += [
{
path = rebase_path("$target_gen_dir/$test_source.dill")
dest = "data/$test_source"
},
{
path = rebase_path("$target_gen_dir/$test_source.elf")
dest = "data/$test_source.elf"
},
]
}
@@ -105,6 +105,11 @@ abstract class CompilerConfiguration {
return NoneCompilerConfiguration(configuration);
case Compiler.dartkp:
// TODO(b/399714829): Test packages should be created at test-time, not
// build time.
if (configuration.system == System.fuchsia) {
return NoneCompilerConfiguration(configuration);
}
return PrecompilerCompilerConfiguration(configuration);
case Compiler.specParser:
+19 -5
View File
@@ -49,17 +49,22 @@ class FuchsiaEmulator {
// Returns a command to execute a set of tests against the running Fuchsia
// environment.
VMCommand getTestCommand(String buildDir, String mode, String arch,
List<String> arguments, Map<String, String> environmentOverrides) {
VMCommand getTestCommand(
String buildDir,
String mode,
String arch,
String component,
List<String> arguments,
Map<String, String> environmentOverrides) {
environmentOverrides.addAll(envs);
return VMCommand(
withEnv,
[
"./third_party/fuchsia/test_scripts/test/run_executable_test.py",
"--test-name=fuchsia-pkg://fuchsia.com/dart_test_$mode#meta/dart_test_component.cm",
"--test-name=fuchsia-pkg://fuchsia.com/dart_test_$mode#meta/$component",
// VmexResource not available in default hermetic realm
// TODO(38752): Setup a Dart test realm.
"--test-realm=/core/testing:system-tests",
"--test-realm=/core/testing/system-tests",
"--out-dir=${_outDir(buildDir, mode)}",
"--package-deps=dart_test_$mode.far",
...arguments
@@ -68,7 +73,16 @@ class FuchsiaEmulator {
}
// Tears down the Fuchsia environment.
Future<void> stop() async {
Future<void> stop(bool verbose) async {
if (verbose) {
// Get the logs before they're deleted.
var logDump = await Process.start(withEnv,
["third_party/fuchsia/sdk/linux/tools/x64/ffx", "log", "dump"],
environment: {"FFX_ISOLATE_DIR": daemonIsolateDir!.path},
mode: ProcessStartMode.inheritStdio);
await logDump.exitCode;
}
publisher!.kill();
await publisher!.exitCode;
publisher = null;
@@ -44,7 +44,7 @@ abstract class RuntimeConfiguration {
if (configuration.system == System.android) {
return DartkAdbRuntimeConfiguration();
} else if (configuration.system == System.fuchsia) {
return DartkFuchsiaEmulatorRuntimeConfiguration();
return DartkFuchsiaEmulatorRuntimeConfiguration(false);
}
return StandaloneDartRuntimeConfiguration();
@@ -53,11 +53,12 @@ abstract class RuntimeConfiguration {
return DartPrecompiledAdbRuntimeConfiguration(
configuration.useElf,
);
} else {
return DartPrecompiledRuntimeConfiguration(
} else if (configuration.system == System.fuchsia) {
return DartkFuchsiaEmulatorRuntimeConfiguration(true);
}
return DartPrecompiledRuntimeConfiguration(
configuration.useElf,
);
}
}
throw "unreachable";
}
@@ -513,6 +514,9 @@ class DartPrecompiledAdbRuntimeConfiguration
class DartkFuchsiaEmulatorRuntimeConfiguration
extends DartVmRuntimeConfiguration {
final bool aot;
DartkFuchsiaEmulatorRuntimeConfiguration(this.aot);
@override
List<Command> computeRuntimeCommands(
CommandArtifact? artifact,
@@ -539,12 +543,20 @@ class DartkFuchsiaEmulatorRuntimeConfiguration
argument.replaceAll(Directory.current.path, "pkg/data"))
.toList();
var component = "dart_test_component.cm";
if (aot) {
component = "dartaotruntime_test_component.cm";
arguments[arguments.length - 1] =
arguments[arguments.length - 1].replaceAll(".dart", ".dart.elf");
}
arguments.insert(arguments.length - 1, '--disable-dart-dev');
return [
FuchsiaEmulator.instance().getTestCommand(
_configuration.buildDirectory,
_configuration.mode.name,
_configuration.architecture.name,
component,
arguments,
environmentOverrides)
];
@@ -190,7 +190,7 @@ Future testConfigurations(List<TestConfiguration> configurations) async {
if (configurations.any((configuration) {
return configuration.system == System.fuchsia;
})) {
FuchsiaEmulator.instance().stop();
FuchsiaEmulator.instance().stop(firstConf.isVerbose);
}
DebugLogger.close();
+1
View File
@@ -59,6 +59,7 @@ template("build_libdart_builtin") {
public_configs = [ ":libdart_builtin_config" ]
deps = []
if (is_fuchsia) {
deps += [ "$fuchsia_sdk/fidl/fuchsia.io" ]
public_deps = [ "$fuchsia_sdk/pkg/fdio" ]
}
if (is_win) {
+2 -3
View File
@@ -149,7 +149,8 @@ class MemoryMappable : public Mappable {
};
Mappable* Mappable::FromPath(const char* path) {
return new FileMappable(File::Open(/*namespc=*/nullptr, path, File::kRead));
return new FileMappable(File::Open(/*namespc=*/nullptr, path, File::kRead,
/*executable=*/true));
}
#if defined(DART_HOST_OS_FUCHSIA) || defined(DART_HOST_OS_LINUX)
@@ -583,7 +584,6 @@ DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Fd(int fd,
}
#endif
#if !defined(DART_HOST_OS_FUCHSIA)
DART_EXPORT Dart_LoadedElf* Dart_LoadELF(const char* filename,
uint64_t file_offset,
const char** error,
@@ -608,7 +608,6 @@ DART_EXPORT Dart_LoadedElf* Dart_LoadELF(const char* filename,
return reinterpret_cast<Dart_LoadedElf*>(elf.release());
}
#endif
DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Memory(
const uint8_t* snapshot,
-2
View File
@@ -36,7 +36,6 @@ DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Fd(int fd,
const uint8_t** vm_isolate_instrs);
#endif
#if !defined(__Fuchsia__)
/// Please see documentation for Dart_LoadElf_Fd.
DART_EXPORT Dart_LoadedElf* Dart_LoadELF(const char* filename,
uint64_t file_offset,
@@ -45,7 +44,6 @@ DART_EXPORT Dart_LoadedElf* Dart_LoadELF(const char* filename,
const uint8_t** vm_snapshot_instrs,
const uint8_t** vm_isolate_data,
const uint8_t** vm_isolate_instrs);
#endif
/// Please see documentation for Dart_LoadElf_Fd.
DART_EXPORT Dart_LoadedElf* Dart_LoadELF_Memory(
+8 -2
View File
@@ -223,11 +223,17 @@ class File : public ReferenceCounted<File> {
// reading and writing. If mode contains kWrite and the file does
// not exist the file is created. The file is truncated to length 0 if
// mode contains kTruncate.
static File* Open(Namespace* namespc, const char* path, FileOpenMode mode);
static File* Open(Namespace* namespc,
const char* path,
FileOpenMode mode,
bool executable = false);
// Same as [File::Open], but attempts to convert uri to path before opening
// the file. If conversion fails, uri is treated as a path.
static File* OpenUri(Namespace* namespc, const char* uri, FileOpenMode mode);
static File* OpenUri(Namespace* namespc,
const char* uri,
FileOpenMode mode,
bool executable = false);
// Attempts to convert the given [uri] to a file path.
static CStringUniquePtr UriToPath(const char* uri);
+33 -14
View File
@@ -7,16 +7,18 @@
#include "bin/file.h"
#include <errno.h> // NOLINT
#include <fcntl.h> // NOLINT
#include <lib/fdio/fdio.h> // NOLINT
#include <lib/fdio/namespace.h> // NOLINT
#include <libgen.h> // NOLINT
#include <sys/mman.h> // NOLINT
#include <sys/stat.h> // NOLINT
#include <sys/types.h> // NOLINT
#include <unistd.h> // NOLINT
#include <utime.h> // NOLINT
#include <errno.h>
#include <fcntl.h>
#include <fuchsia/io/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/namespace.h>
#include <libgen.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <utime.h>
#include "bin/builtin.h"
#include "bin/fdutils.h"
@@ -216,7 +218,10 @@ File* File::OpenFD(int fd) {
return new File(new FileHandle(fd));
}
File* File::Open(Namespace* namespc, const char* name, FileOpenMode mode) {
File* File::Open(Namespace* namespc,
const char* name,
FileOpenMode mode,
bool executable) {
NamespaceScope ns(namespc, name);
// Report errors for non-regular files.
struct stat st;
@@ -239,7 +244,18 @@ File* File::Open(Namespace* namespc, const char* name, FileOpenMode mode) {
flags = flags | O_TRUNC;
}
flags |= O_CLOEXEC;
int fd = NO_RETRY_EXPECTED(openat(ns.fd(), ns.path(), flags, 0666));
int fd;
if (executable) {
fuchsia::io::Flags flags =
fuchsia::io::PERM_READABLE | fuchsia::io::PERM_EXECUTABLE;
zx_status_t status =
fdio_open3_fd_at(ns.fd(), ns.path(), uint64_t{flags}, &fd);
if (status != ZX_OK) {
return nullptr;
}
} else {
fd = NO_RETRY_EXPECTED(openat(ns.fd(), ns.path(), flags, 0666));
}
if (fd < 0) {
return nullptr;
}
@@ -264,12 +280,15 @@ CStringUniquePtr File::UriToPath(const char* uri) {
return CStringUniquePtr(strdup(uri_decoder.decoded()));
}
File* File::OpenUri(Namespace* namespc, const char* uri, FileOpenMode mode) {
File* File::OpenUri(Namespace* namespc,
const char* uri,
FileOpenMode mode,
bool executable) {
auto path = UriToPath(uri);
if (path == nullptr) {
return nullptr;
}
return File::Open(namespc, path.get(), mode);
return File::Open(namespc, path.get(), mode, executable);
}
File* File::OpenStdio(int fd) {
+9 -3
View File
@@ -227,7 +227,10 @@ File* File::OpenFD(int fd) {
return new File(new FileHandle(fd));
}
File* File::Open(Namespace* namespc, const char* name, FileOpenMode mode) {
File* File::Open(Namespace* namespc,
const char* name,
FileOpenMode mode,
bool executable) {
NamespaceScope ns(namespc, name);
// Report errors for non-regular files.
struct stat64 st;
@@ -276,12 +279,15 @@ CStringUniquePtr File::UriToPath(const char* uri) {
return CStringUniquePtr(strdup(uri_decoder.decoded()));
}
File* File::OpenUri(Namespace* namespc, const char* uri, FileOpenMode mode) {
File* File::OpenUri(Namespace* namespc,
const char* uri,
FileOpenMode mode,
bool executable) {
auto path = UriToPath(uri);
if (path == nullptr) {
return nullptr;
}
return File::Open(namespc, path.get(), mode);
return File::Open(namespc, path.get(), mode, executable);
}
File* File::OpenStdio(int fd) {
+9 -3
View File
@@ -266,7 +266,10 @@ File* File::OpenFD(int fd) {
return new File(new FileHandle(fd));
}
File* File::Open(Namespace* namespc, const char* name, FileOpenMode mode) {
File* File::Open(Namespace* namespc,
const char* name,
FileOpenMode mode,
bool executable) {
// Report errors for non-regular files.
struct stat st;
if (NO_RETRY_EXPECTED(stat(name, &st)) == 0) {
@@ -314,12 +317,15 @@ CStringUniquePtr File::UriToPath(const char* uri) {
return CStringUniquePtr(strdup(uri_decoder.decoded()));
}
File* File::OpenUri(Namespace* namespc, const char* uri, FileOpenMode mode) {
File* File::OpenUri(Namespace* namespc,
const char* uri,
FileOpenMode mode,
bool executable) {
auto path = UriToPath(uri);
if (path == nullptr) {
return nullptr;
}
return File::Open(namespc, path.get(), mode);
return File::Open(namespc, path.get(), mode, executable);
}
File* File::OpenStdio(int fd) {
+9 -3
View File
@@ -404,7 +404,10 @@ std::unique_ptr<wchar_t[]> ToWinAPIPath(const char* utf8_path) {
return result;
}
File* File::Open(Namespace* namespc, const char* name, FileOpenMode mode) {
File* File::Open(Namespace* namespc,
const char* name,
FileOpenMode mode,
bool executable) {
const auto path = ToWinAPIPath(name);
if (path.get() == nullptr) {
SetLastError(ERROR_INVALID_NAME);
@@ -437,12 +440,15 @@ CStringUniquePtr File::UriToPath(const char* uri) {
return utf8_path.release();
}
File* File::OpenUri(Namespace* namespc, const char* uri, FileOpenMode mode) {
File* File::OpenUri(Namespace* namespc,
const char* uri,
FileOpenMode mode,
bool executable) {
auto path = UriToPath(uri);
if (path == nullptr) {
return nullptr;
}
return Open(namespc, path.get(), mode);
return Open(namespc, path.get(), mode, executable);
}
File* File::OpenStdio(int fd) {
-4
View File
@@ -188,9 +188,7 @@ static AppSnapshot* TryReadAppSnapshotElf(
*isolate_data_buffer = nullptr,
*isolate_instructions_buffer = nullptr;
Dart_LoadedElf* handle = nullptr;
#if !defined(DART_HOST_OS_FUCHSIA)
if (force_load_elf_from_memory) {
#endif
File* const file =
File::Open(/*namespc=*/nullptr, script_name, File::kRead);
if (file == nullptr) return nullptr;
@@ -205,13 +203,11 @@ static AppSnapshot* TryReadAppSnapshotElf(
&isolate_data_buffer, &isolate_instructions_buffer);
delete memory;
file->Release();
#if !defined(DART_HOST_OS_FUCHSIA)
} else {
handle = Dart_LoadELF(script_name, file_offset, &error, &vm_data_buffer,
&vm_instructions_buffer, &isolate_data_buffer,
&isolate_instructions_buffer);
}
#endif
if (handle == nullptr) {
Syslog::PrintErr("Loading failed: %s\n", error);
return nullptr;
+17 -1
View File
@@ -313,7 +313,7 @@
"enable-asserts": true
}
},
"vm-aot-(linux|mac)-(debug|product|release)-(x64|x64c|arm64|arm64c)": {
"vm-aot-(linux|mac|fuchsia)-(debug|product|release)-(x64|x64c|arm64|arm64c)": {
"options": {}
},
"vm-aot-win-(debug|product|release)-(x64|x64c|arm64|arm64c)": {
@@ -1641,6 +1641,14 @@
"-j4",
"ffi"
]
},
{
"name": "vm tests",
"arguments": [
"-nvm-aot-${system}-${mode}-${arch}",
"-j4",
"ffi"
]
}
]
},
@@ -1667,6 +1675,14 @@
"-j1",
"ffi"
]
},
{
"name": "vm tests",
"arguments": [
"-nvm-aot-${system}-${mode}-${arch}",
"-j1",
"ffi"
]
}
]
},