blob: ddedead3830d648d907b77a13f4ad356e55b1703 [file] [log] [blame] [edit]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIB_LD_TEST_LD_STARTUP_CREATE_PROCESS_TESTS_H_
#define LIB_LD_TEST_LD_STARTUP_CREATE_PROCESS_TESTS_H_
#include <lib/elfldltl/layout.h>
#include <lib/elfldltl/testing/loader.h>
#include <lib/ld/testing/test-processargs.h>
#include <lib/zx/thread.h>
#include <lib/zx/vmar.h>
#include <lib/zx/vmo.h>
#include <cstdint>
#include <initializer_list>
#include <optional>
#include <string_view>
#include <gtest/gtest.h>
#include "ld-load-zircon-process-tests-base.h"
namespace ld::testing {
// This is the common base class for template instantiations. It handles the
// process mechanics, while the templated subclass does the loading.
class LdStartupCreateProcessTestsBase : public LdLoadZirconProcessTestsBase {
public:
void Init(std::initializer_list<std::string_view> args = {});
int64_t Run();
~LdStartupCreateProcessTestsBase();
TestProcessArgs& bootstrap() { return procargs_; }
protected:
static zx::unowned_vmo GetVdsoVmo();
const zx::vmar& root_vmar() { return root_vmar_; }
void set_entry(uintptr_t entry) { entry_ = entry; }
void set_vdso_base(uintptr_t vdso_base) { vdso_base_ = vdso_base; }
void set_stack_size(std::optional<size_t> stack_size) { stack_size_ = stack_size; }
private:
uintptr_t entry_ = 0;
uintptr_t vdso_base_ = 0;
std::optional<size_t> stack_size_;
TestProcessArgs procargs_;
zx::vmar root_vmar_;
zx::thread thread_;
};
template <class Elf = elfldltl::Elf<>>
class LdStartupCreateProcessTests
: public elfldltl::testing::LoadTests<elfldltl::testing::RemoteVmarLoaderTraits, Elf>,
public LdStartupCreateProcessTestsBase {
public:
using LdStartupCreateProcessTestsBase::Run;
void Load(std::string_view executable_name) {
ASSERT_TRUE(root_vmar()); // Init must have been called already.
// Load the dynamic linker and record its entry point.
std::optional<LoadResult> result;
ASSERT_NO_FATAL_FAILURE(Load(kLdStartupName, result, root_vmar()));
set_entry(result->entry + result->loader.load_bias());
set_stack_size(result->stack_size);
// The bootstrap message gets the VMAR where the dynamic linker resides.
zx::vmar self_vmar = std::move(result->loader).Commit();
ASSERT_NO_FATAL_FAILURE(bootstrap().AddSelfVmar(std::move(self_vmar)));
// Load the vDSO and record its base address.
// No handles to the VMAR where it was loaded survive.
ASSERT_NO_FATAL_FAILURE(this->Load(*GetVdsoVmo(), result, root_vmar()));
set_vdso_base(result->info.vaddr_start() + result->loader.load_bias());
std::move(result->loader).Commit();
// Send the executable VMO.
ASSERT_NO_FATAL_FAILURE(bootstrap().AddExecutableVmo(executable_name));
}
private:
using Base = elfldltl::testing::LoadTests<elfldltl::testing::RemoteVmarLoaderTraits, Elf>;
using Base::Load;
using typename Base::LoadResult;
};
} // namespace ld::testing
#endif // LIB_LD_TEST_LD_STARTUP_CREATE_PROCESS_TESTS_H_