blob: a4ccbac74199f7067137278cf5d97d73801bcc6b [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <lib/zbitl/error-stdio.h>
#include <cstdint>
#include <phys/address-space.h>
#include <phys/elf-image.h>
#include <phys/kernel-package.h>
#include <phys/symbolize.h>
#include "../physload-test-main.h"
#include "get-int.h"
#ifdef __aarch64__
#include <lib/arch/arm64/system.h>
#endif
#include <ktl/enforce.h>
namespace {
constexpr const char* kTestName = "virtual-address-loading-loading-test";
// The name of ELF module to be loaded.
constexpr ktl::string_view kGetInt = "get-int.virtual-address-loading-test";
// TODO(https://fxbug.dev/42172722): Pick a load address through a sort of allocator
// (i.e., as we would in production).
constexpr uint64_t kLoadAddress = 0xffff'ffff'0000'0000;
} // namespace
int PhysLoadTestMain(KernelStorage kernelfs) {
gSymbolize->set_name(kTestName);
#ifdef __aarch64__
// TODO(https://fxbug.dev/42085337): There is no upper address space in EL2+ by
// default, so drop down to EL1 and proceed with the test.
if (auto el = arch::ArmCurrentEl::Read().el(); el > 1) {
printf(
"TODO(https://fxbug.dev/42085337): %s test is only supported for EL1 (current EL is %lu); skipping it\n",
kTestName, el);
return 0;
}
#endif
printf("Loading %.*s...\n", static_cast<int>(kGetInt.size()), kGetInt.data());
ElfImage elf;
if (auto result = elf.Init(kernelfs.root(), kGetInt, true); result.is_error()) {
zbitl::PrintBootfsError(result.error_value());
return 1;
}
ZX_ASSERT(!elf.has_patches());
// The GN target for get-int uses kernel_elf_interp() on this test binary.
printf("Verifying PT_INTERP matches test build ID...\n");
elf.AssertInterpMatchesBuildId(kGetInt, gSymbolize->build_id());
Allocation loaded = elf.Load(kLoadAddress);
elf.Relocate();
// TODO(https://fxbug.dev/42172722): Set up C++ ABI support and map and jump into a
// loaded C++ program.
if (auto result = elf.MapInto(*gAddressSpace); result.is_error()) {
printf("Failed to map loaded image\n");
return 1;
}
printf("Calling virtual entry point %#" PRIx64 "...\n", elf.entry());
// We should now be able to access GetInt()!
constexpr int kExpected = 42;
if (int actual = elf.Call<decltype(GetInt)>(); actual != kExpected) {
printf("FAILED: Expected %d; got %d\n", kExpected, actual);
return 1;
}
return 0;
}