246 lines
9.8 KiB
C++
246 lines
9.8 KiB
C++
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
|
|
#ifndef __LIBHOST_H__
|
|
#define __LIBHOST_H__
|
|
#include <stdint.h>
|
|
#include "trace.h"
|
|
#include "runtime_config.h"
|
|
#include "fx_ver.h"
|
|
|
|
enum host_mode_t
|
|
{
|
|
invalid = 0,
|
|
muxer,
|
|
standalone,
|
|
split_fx
|
|
};
|
|
|
|
class fx_ver_t;
|
|
class runtime_config_t;
|
|
|
|
#define _HOST_INTERFACE_PACK 1
|
|
#pragma pack(push, _HOST_INTERFACE_PACK)
|
|
struct strarr_t
|
|
{
|
|
// DO NOT modify this struct. It is used in a layout
|
|
// dependent manner. Create another for your use.
|
|
size_t len;
|
|
const pal::char_t** arr;
|
|
};
|
|
|
|
struct host_interface_t
|
|
{
|
|
size_t version_lo; // Just assign sizeof() to this field.
|
|
size_t version_hi; // Breaking changes to the layout -- increment HOST_INTERFACE_LAYOUT_VERSION
|
|
strarr_t config_keys;
|
|
strarr_t config_values;
|
|
const pal::char_t* fx_dir;
|
|
const pal::char_t* fx_name;
|
|
const pal::char_t* deps_file;
|
|
size_t is_portable;
|
|
strarr_t probe_paths;
|
|
size_t patch_roll_forward;
|
|
size_t prerelease_roll_forward;
|
|
size_t host_mode;
|
|
// !! WARNING / WARNING / WARNING / WARNING / WARNING / WARNING / WARNING / WARNING / WARNING
|
|
// !! 1. Only append to this structure to maintain compat.
|
|
// !! 2. Any nested structs should not use compiler specific padding (pack with _HOST_INTERFACE_PACK)
|
|
// !! 3. Do not take address of the fields of this struct or be prepared to deal with unaligned accesses.
|
|
// !! 4. Must be POD types; only use non-const size_t and pointer types; no access modifiers.
|
|
// !! 5. Do not reorder fields or change any existing field types.
|
|
// !! 6. Add static asserts for fields you add.
|
|
};
|
|
#pragma pack(pop)
|
|
static_assert(_HOST_INTERFACE_PACK == 1, "Packing size should not be modified for back compat");
|
|
static_assert(offsetof(host_interface_t, version_lo) == 0 * sizeof(size_t), "Struct offset breaks backwards compatibility");
|
|
static_assert(offsetof(host_interface_t, version_hi) == 1 * sizeof(size_t), "Struct offset breaks backwards compatibility");
|
|
static_assert(offsetof(host_interface_t, config_keys) == 2 * sizeof(size_t), "Struct offset breaks backwards compatibility");
|
|
static_assert(offsetof(host_interface_t, config_values) == 4 * sizeof(size_t), "Struct offset breaks backwards compatibility");
|
|
static_assert(offsetof(host_interface_t, fx_dir) == 6 * sizeof(size_t), "Struct offset breaks backwards compatibility");
|
|
static_assert(offsetof(host_interface_t, fx_name) == 7 * sizeof(size_t), "Struct offset breaks backwards compatibility");
|
|
static_assert(offsetof(host_interface_t, deps_file) == 8 * sizeof(size_t), "Struct offset breaks backwards compatibility");
|
|
static_assert(offsetof(host_interface_t, is_portable) == 9 * sizeof(size_t), "Struct offset breaks backwards compatibility");
|
|
static_assert(offsetof(host_interface_t, probe_paths) == 10 * sizeof(size_t), "Struct offset breaks backwards compatibility");
|
|
static_assert(offsetof(host_interface_t, patch_roll_forward) == 12 * sizeof(size_t), "Struct offset breaks backwards compatibility");
|
|
static_assert(offsetof(host_interface_t, prerelease_roll_forward) == 13 * sizeof(size_t), "Struct offset breaks backwards compatibility");
|
|
static_assert(offsetof(host_interface_t, host_mode) == 14 * sizeof(size_t), "Struct offset breaks backwards compatibility");
|
|
static_assert(sizeof(host_interface_t) == 15 * sizeof(size_t), "Did you add static asserts for the newly added fields?");
|
|
|
|
#define HOST_INTERFACE_LAYOUT_VERSION_HI 0x16041101 // YYMMDD:nn always increases when layout breaks compat.
|
|
#define HOST_INTERFACE_LAYOUT_VERSION_LO sizeof(host_interface_t)
|
|
|
|
class corehost_init_t
|
|
{
|
|
private:
|
|
std::vector<pal::string_t> m_clr_keys;
|
|
std::vector<pal::string_t> m_clr_values;
|
|
std::vector<const pal::char_t*> m_clr_keys_cstr;
|
|
std::vector<const pal::char_t*> m_clr_values_cstr;
|
|
const pal::string_t m_fx_dir;
|
|
const pal::string_t m_fx_name;
|
|
const pal::string_t m_deps_file;
|
|
bool m_portable;
|
|
std::vector<pal::string_t> m_probe_paths;
|
|
std::vector<const pal::char_t*> m_probe_paths_cstr;
|
|
bool m_patch_roll_forward;
|
|
bool m_prerelease_roll_forward;
|
|
host_mode_t m_host_mode;
|
|
host_interface_t m_host_interface;
|
|
const pal::string_t m_fx_ver;
|
|
public:
|
|
corehost_init_t(
|
|
const pal::string_t& deps_file,
|
|
const std::vector<pal::string_t>& probe_paths,
|
|
const pal::string_t& fx_dir,
|
|
const host_mode_t mode,
|
|
const runtime_config_t& runtime_config)
|
|
: m_fx_dir(fx_dir)
|
|
, m_fx_name(runtime_config.get_fx_name())
|
|
, m_deps_file(deps_file)
|
|
, m_portable(runtime_config.get_portable())
|
|
, m_probe_paths(probe_paths)
|
|
, m_patch_roll_forward(runtime_config.get_patch_roll_fwd())
|
|
, m_prerelease_roll_forward(runtime_config.get_prerelease_roll_fwd())
|
|
, m_host_mode(mode)
|
|
, m_host_interface()
|
|
, m_fx_ver(runtime_config.get_fx_version())
|
|
{
|
|
runtime_config.config_kv(&m_clr_keys, &m_clr_values);
|
|
make_cstr_arr(m_clr_keys, &m_clr_keys_cstr);
|
|
make_cstr_arr(m_clr_values, &m_clr_values_cstr);
|
|
make_cstr_arr(m_probe_paths, &m_probe_paths_cstr);
|
|
}
|
|
|
|
const pal::string_t& fx_dir() const
|
|
{
|
|
return m_fx_dir;
|
|
}
|
|
|
|
const pal::string_t& fx_name() const
|
|
{
|
|
return m_fx_name;
|
|
}
|
|
|
|
const pal::string_t& fx_version() const
|
|
{
|
|
return m_fx_ver;
|
|
}
|
|
|
|
const host_interface_t& get_host_init_data()
|
|
{
|
|
host_interface_t& hi = m_host_interface;
|
|
|
|
hi.version_lo = HOST_INTERFACE_LAYOUT_VERSION_LO;
|
|
hi.version_hi = HOST_INTERFACE_LAYOUT_VERSION_HI;
|
|
|
|
hi.config_keys.len = m_clr_keys_cstr.size();
|
|
hi.config_keys.arr = m_clr_keys_cstr.data();
|
|
|
|
hi.config_values.len = m_clr_values_cstr.size();
|
|
hi.config_values.arr = m_clr_values_cstr.data();
|
|
|
|
hi.fx_dir = m_fx_dir.c_str();
|
|
hi.fx_name = m_fx_name.c_str();
|
|
hi.deps_file = m_deps_file.c_str();
|
|
hi.is_portable = m_portable;
|
|
|
|
hi.probe_paths.len = m_probe_paths_cstr.size();
|
|
hi.probe_paths.arr = m_probe_paths_cstr.data();
|
|
|
|
hi.patch_roll_forward = m_patch_roll_forward;
|
|
hi.prerelease_roll_forward = m_prerelease_roll_forward;
|
|
hi.host_mode = m_host_mode;
|
|
|
|
return hi;
|
|
}
|
|
|
|
private:
|
|
|
|
static void make_cstr_arr(const std::vector<pal::string_t>& arr, std::vector<const pal::char_t*>* out)
|
|
{
|
|
out->reserve(arr.size());
|
|
for (const auto& str : arr)
|
|
{
|
|
out->push_back(str.c_str());
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
struct hostpolicy_init_t
|
|
{
|
|
std::vector<std::vector<char>> cfg_keys;
|
|
std::vector<std::vector<char>> cfg_values;
|
|
pal::string_t deps_file;
|
|
std::vector<pal::string_t> probe_paths;
|
|
pal::string_t fx_dir;
|
|
pal::string_t fx_name;
|
|
host_mode_t host_mode;
|
|
bool patch_roll_forward;
|
|
bool prerelease_roll_forward;
|
|
bool is_portable;
|
|
|
|
static bool init(host_interface_t* input, hostpolicy_init_t* init)
|
|
{
|
|
// Check if there are any breaking changes.
|
|
if (input->version_hi != HOST_INTERFACE_LAYOUT_VERSION_HI)
|
|
{
|
|
trace::error(_X("The version of the data layout used to initialize %s is [0x%04x]; expected version [0x%04x]"), LIBHOSTPOLICY_NAME, input->version_hi, HOST_INTERFACE_LAYOUT_VERSION_HI);
|
|
return false;
|
|
}
|
|
// Check if the size is at least what we expect to contain.
|
|
if (input->version_lo < HOST_INTERFACE_LAYOUT_VERSION_LO)
|
|
{
|
|
trace::error(_X("The size of the data layout used to initialize %s is %d; expected at least %d"), LIBHOSTPOLICY_NAME, input->version_lo, HOST_INTERFACE_LAYOUT_VERSION_LO);
|
|
return false;
|
|
}
|
|
trace::verbose(_X("Reading from host interface version: [0x%04x:%d] to initialize policy version: [0x%04x:%d]"), input->version_hi, input->version_lo, HOST_INTERFACE_LAYOUT_VERSION_HI, HOST_INTERFACE_LAYOUT_VERSION_LO);
|
|
|
|
make_clrstr_arr(input->config_keys.len, input->config_keys.arr, &init->cfg_keys);
|
|
make_clrstr_arr(input->config_values.len, input->config_values.arr, &init->cfg_values);
|
|
|
|
init->fx_dir = input->fx_dir;
|
|
init->fx_name = input->fx_name;
|
|
init->deps_file = input->deps_file;
|
|
init->is_portable = input->is_portable;
|
|
|
|
make_palstr_arr(input->probe_paths.len, input->probe_paths.arr, &init->probe_paths);
|
|
|
|
init->patch_roll_forward = input->patch_roll_forward;
|
|
init->prerelease_roll_forward = input->prerelease_roll_forward;
|
|
init->host_mode = (host_mode_t) input->host_mode;
|
|
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
static void make_palstr_arr(int argc, const pal::char_t** argv, std::vector<pal::string_t>* out)
|
|
{
|
|
out->reserve(argc);
|
|
for (int i = 0; i < argc; ++i)
|
|
{
|
|
out->push_back(argv[i]);
|
|
}
|
|
}
|
|
|
|
static void make_clrstr_arr(int argc, const pal::char_t** argv, std::vector<std::vector<char>>* out)
|
|
{
|
|
out->resize(argc);
|
|
for (int i = 0; i < argc; ++i)
|
|
{
|
|
pal::pal_clrstring(pal::string_t(argv[i]), &(*out)[i]);
|
|
}
|
|
}
|
|
};
|
|
|
|
void get_runtime_config_paths_from_app(const pal::string_t& file, pal::string_t* config_file, pal::string_t* dev_config_file);
|
|
void get_runtime_config_paths_from_arg(const pal::string_t& file, pal::string_t* config_file, pal::string_t* dev_config_file);
|
|
|
|
host_mode_t detect_operating_mode(const pal::string_t& own_dir, const pal::string_t& own_dll, const pal::string_t& own_name);
|
|
bool hostpolicy_exists_in_svc(pal::string_t* resolved_dir);
|
|
|
|
void try_patch_roll_forward_in_dir(const pal::string_t& cur_dir, const fx_ver_t& start_ver, pal::string_t* max_str);
|
|
void try_prerelease_roll_forward_in_dir(const pal::string_t& cur_dir, const fx_ver_t& start_ver, pal::string_t* max_str);
|
|
|
|
#endif // __LIBHOST_H__
|