blob: ae2f023f9a14c64726c0e6e357a8d64957dbdda2 [file] [log] [blame]
// Copyright 2025 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.
#include "ld-load-zircon-ldsvc-tests-base.h"
#include <lib/elfldltl/vmo.h>
#include <lib/fit/defer.h>
#include <lib/ld/abi.h>
#include <lib/ld/testing/get-test-vmo.h>
#include <lib/ld/testing/interp.h>
#include <lib/ld/testing/test-elf-object.h>
#include <filesystem>
namespace ld::testing {
std::string LdLoadZirconLdsvcTestsBase::FindInterp(zx::unowned_vmo vmo) {
return ld::testing::FindInterp<elfldltl::UnownedVmoFile>(std::move(vmo));
}
std::optional<std::string> LdLoadZirconLdsvcTestsBase::ConfigFromInterp( //
const std::filesystem::path& interp, std::optional<std::string_view> expected_config) {
std::optional<std::string> config = ld::testing::ConfigFromInterp(interp, expected_config);
if (expected_config) {
return std::nullopt;
}
if (config) {
mock_.path_prefix_append(*config);
}
return config;
}
zx::vmo LdLoadZirconLdsvcTestsBase::GetExecutableVmoWithInterpConfig(
std::string_view executable, std::optional<std::string_view> expected_config) {
zx::vmo vmo = GetExecutableVmo(executable);
if (vmo) {
LdsvcExpectConfig(ConfigFromInterp(vmo.borrow(), expected_config));
}
return vmo;
}
zx::vmo LdLoadZirconLdsvcTestsBase::GetInterp(std::string_view executable_name,
std::optional<std::string_view> expected_config) {
if (!expected_config) {
return GetLibVmo(abi::kInterp);
}
const std::string name_str{executable_name};
elfldltl::Soname<> set_name{name_str};
const TestElfLoadSet* load_set = TestElfLoadSet::Get(set_name);
if (!load_set) {
ADD_FAILURE() << "load set " << set_name << " not found";
return {};
}
const TestElfLoadSet::SonameMap soname_map = load_set->MakeSonameMap();
auto it = soname_map.find(abi::Abi<>::kSoname);
if (it == soname_map.end()) {
ADD_FAILURE() << abi::Abi<>::kSoname << " not in load set " << set_name;
return {};
}
std::optional libprefix = it->second.libprefix;
if (!libprefix) {
return GetLibVmo(abi::kInterp);
}
std::filesystem::path interp{*libprefix};
interp /= abi::kInterp;
return GetLibVmo(interp.native());
}
void LdLoadZirconLdsvcTestsBase::NeededViaLoadSet( //
elfldltl::Soname<> set_name, std::initializer_list<std::string_view> names) {
auto restore_prefix = fit::defer([this, path_prefix = mock_.path_prefix()]() mutable {
mock_.set_path_prefix(std::move(path_prefix));
});
const TestElfLoadSet* load_set = TestElfLoadSet::Get(set_name);
ASSERT_TRUE(load_set) << set_name;
const TestElfLoadSet::SonameMap soname_map = load_set->MakeSonameMap();
for (std::string_view dep : names) {
auto it = soname_map.find(elfldltl::Soname<>{std::string{dep}});
ASSERT_NE(it, soname_map.end()) << dep << " for " << set_name;
LdsvcPathPrefix(set_name.str(), it->second.libprefix);
ASSERT_NO_FATAL_FAILURE(LdsvcExpectDependency(dep));
}
}
void LdLoadZirconLdsvcTestsBase::LdsvcPathPrefix( //
std::string_view executable, std::optional<std::string_view> libprefix) {
mock_.set_path_prefix(GetExecutableLibPath(executable, libprefix));
}
} // namespace ld::testing