Skip to content

Commit

Permalink
Add mechanism for runtime to query host for information
Browse files Browse the repository at this point in the history
  • Loading branch information
elinor-fung committed Nov 24, 2022
1 parent 78b3f9d commit 5d744ee
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 5 deletions.
27 changes: 23 additions & 4 deletions src/coreclr/dlls/mscoree/exports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#endif // FEATURE_GDBJIT
#include "bundle.h"
#include "pinvokeoverride.h"
#include <hostinformation.h>
#include <corehost/host_runtime_contract.h>

#define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS((expr))

Expand Down Expand Up @@ -122,7 +124,8 @@ static void ConvertConfigPropertiesToUnicode(
LPCWSTR** propertyValuesWRef,
BundleProbeFn** bundleProbe,
PInvokeOverrideFn** pinvokeOverride,
bool* hostPolicyEmbedded)
bool* hostPolicyEmbedded,
host_runtime_contract** hostContract)
{
LPCWSTR* propertyKeysW = new (nothrow) LPCWSTR[propertyCount];
ASSERTE_ALL_BUILDS(propertyKeysW != nullptr);
Expand All @@ -139,7 +142,8 @@ static void ConvertConfigPropertiesToUnicode(
{
// If this application is a single-file bundle, the bundle-probe callback
// is passed in as the value of "BUNDLE_PROBE" property (encoded as a string).
*bundleProbe = (BundleProbeFn*)_wcstoui64(propertyValuesW[propertyIndex], nullptr, 0);
if (*bundleProbe == nullptr)
*bundleProbe = (BundleProbeFn*)_wcstoui64(propertyValuesW[propertyIndex], nullptr, 0);
}
else if (strcmp(propertyKeys[propertyIndex], "PINVOKE_OVERRIDE") == 0)
{
Expand All @@ -152,6 +156,14 @@ static void ConvertConfigPropertiesToUnicode(
// The HOSTPOLICY_EMBEDDED property indicates if the executable has hostpolicy statically linked in
*hostPolicyEmbedded = (wcscmp(propertyValuesW[propertyIndex], W("true")) == 0);
}
else if (strcmp(propertyKeys[propertyIndex], HOST_PROPERTY_RUNTIME_CONTRACT) == 0)
{
// Host contract is passed in as the value of HOST_RUNTIME_CONTRACT property (encoded as a string).
host_runtime_contract* hostContractLocal = (host_runtime_contract*)_wcstoui64(propertyValuesW[propertyIndex], nullptr, 0);
*hostContract = hostContractLocal;
if (hostContractLocal->bundle_probe != nullptr)
*bundleProbe = hostContractLocal->bundle_probe;
}
}

*propertyKeysWRef = propertyKeysW;
Expand Down Expand Up @@ -196,6 +208,7 @@ int coreclr_initialize(
BundleProbeFn* bundleProbe = nullptr;
bool hostPolicyEmbedded = false;
PInvokeOverrideFn* pinvokeOverride = nullptr;
host_runtime_contract* hostContract = nullptr;

ConvertConfigPropertiesToUnicode(
propertyKeys,
Expand All @@ -205,7 +218,8 @@ int coreclr_initialize(
&propertyValuesW,
&bundleProbe,
&pinvokeOverride,
&hostPolicyEmbedded);
&hostPolicyEmbedded,
&hostContract);

#ifdef TARGET_UNIX
DWORD error = PAL_InitializeCoreCLR(exePath, g_coreclr_embedded);
Expand All @@ -221,7 +235,12 @@ int coreclr_initialize(

g_hostpolicy_embedded = hostPolicyEmbedded;

if (pinvokeOverride != nullptr)
if (hostContract != nullptr)
{
HostInformation::SetContract(hostContract);
}

if (pinvokeOverride != nullptr && (hostContract == nullptr || hostContract->pinvoke_override == nullptr))
{
PInvokeOverride::SetPInvokeOverride(pinvokeOverride, PInvokeOverride::Source::RuntimeConfiguration);
}
Expand Down
16 changes: 16 additions & 0 deletions src/coreclr/inc/hostinformation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#ifndef _HOSTINFORMATION_H_
#define _HOSTINFORMATION_H_

#include <corehost/host_runtime_contract.h>

class HostInformation
{
public:
static void SetContract(_In_ host_runtime_contract* hostContract);
static bool GetProperty(_In_z_ const char* name, SString& value);
};

#endif // _HOSTINFORMATION_H_
1 change: 1 addition & 0 deletions src/coreclr/vm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ set(VM_SOURCES_WKS
genanalysis.cpp
genmeth.cpp
hosting.cpp
hostinformation.cpp
ilmarshalers.cpp
interopconverter.cpp
interoputil.cpp
Expand Down
46 changes: 46 additions & 0 deletions src/coreclr/vm/hostinformation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#include "common.h"
#include "hostinformation.h"
#include "pinvokeoverride.h"

namespace
{
host_runtime_contract* s_hostContract = nullptr;
}

void HostInformation::SetContract(_In_ host_runtime_contract* hostContract)
{
_ASSERTE(s_hostContract == nullptr);
s_hostContract = hostContract;

if (s_hostContract->pinvoke_override != nullptr)
PInvokeOverride::SetPInvokeOverride(s_hostContract->pinvoke_override, PInvokeOverride::Source::RuntimeConfiguration);
}

bool HostInformation::GetProperty(_In_z_ const char* name, SString& value)
{
if (s_hostContract == nullptr || s_hostContract->get_runtime_property == nullptr)
return false;

size_t len = MAX_PATH + 1;
char* dest = value.OpenUTF8Buffer(static_cast<COUNT_T>(len));
size_t lenActual = s_hostContract->get_runtime_property(name, dest, len, s_hostContract->context);
value.CloseBuffer();

// Doesn't exist or failed to get property
if (lenActual == (size_t)-1 || lenActual == 0)
return false;

if (lenActual <= len)
return true;

// Buffer was not large enough
len = lenActual;
dest = value.OpenUTF8Buffer(static_cast<COUNT_T>(len));
lenActual = s_hostContract->get_runtime_property(name, dest, len, s_hostContract->context);
value.CloseBuffer();

return lenActual > 0 && lenActual <= len;
}
41 changes: 41 additions & 0 deletions src/native/corehost/host_runtime_contract.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#ifndef __HOST_RUNTIME_CONTRACT_H__
#define __HOST_RUNTIME_CONTRACT_H__

#include <stddef.h>
#include <stdint.h>

#if defined(_WIN32)
#define HOST_CONTRACT_CALLTYPE __stdcall
#else
#define HOST_CONTRACT_CALLTYPE
#endif

// Known host property names
#define HOST_PROPERTY_RUNTIME_CONTRACT "HOST_RUNTIME_CONTRACT"
#define HOST_PROPERTY_ENTRY_ASSEMBLY_NAME "ENTRY_ASSEMBLY_NAME"

struct host_runtime_contract
{
void* context;

bool(HOST_CONTRACT_CALLTYPE* bundle_probe)(
const char* path,
int64_t* offset,
int64_t* size,
int64_t* compressedSize);

const void* (HOST_CONTRACT_CALLTYPE* pinvoke_override)(
const char* library_name,
const char* entry_point_name);

size_t(HOST_CONTRACT_CALLTYPE* get_runtime_property)(
const char* key,
char* value_buffer,
size_t value_buffer_size,
void* contract_context);
};

#endif // __HOST_RUNTIME_CONTRACT_H__
11 changes: 11 additions & 0 deletions src/native/corehost/hostmisc/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ namespace pal
return buffer;
}

size_t pal_utf8string(const string_t& str, char* out_buffer, size_t len);
bool pal_utf8string(const string_t& str, std::vector<char>* out);
bool pal_clrstring(const string_t& str, std::vector<char>* out);
bool clr_palstring(const char* cstr, string_t* out);
Expand Down Expand Up @@ -236,6 +237,16 @@ namespace pal

inline const string_t strerror(int errnum) { return ::strerror(errnum); }

inline size_t pal_utf8string(const string_t& str, char* out_buffer, size_t buffer_len)
{
size_t len = str.size() + 1;
if (buffer_len < len)
return len;

::strncpy(out_buffer, str.c_str(), str.size());
out_buffer[len - 1] = '\0';
return len;
}
inline bool pal_utf8string(const string_t& str, std::vector<char>* out) { out->assign(str.begin(), str.end()); out->push_back('\0'); return true; }
inline bool pal_clrstring(const string_t& str, std::vector<char>* out) { return pal_utf8string(str, out); }
inline bool clr_palstring(const char* cstr, string_t* out) { out->assign(cstr); return true; }
Expand Down
11 changes: 11 additions & 0 deletions src/native/corehost/hostmisc/pal.windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,17 @@ static bool wchar_convert_helper(DWORD code_page, const char* cstr, size_t len,
return ::MultiByteToWideChar(code_page, 0, cstr, static_cast<uint32_t>(len), &(*out)[0], static_cast<uint32_t>(out->size())) != 0;
}

size_t pal::pal_utf8string(const pal::string_t& str, char* out_buffer, size_t len)
{
// Pass -1 as we want explicit null termination in the char buffer.
size_t size = ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, nullptr, 0, nullptr, nullptr);
if (size == 0 || size > len)
return size;

// Pass -1 as we want explicit null termination in the char buffer.
return ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, out_buffer, static_cast<uint32_t>(len), nullptr, nullptr);
}

bool pal::pal_utf8string(const pal::string_t& str, std::vector<char>* out)
{
out->clear();
Expand Down
48 changes: 47 additions & 1 deletion src/native/corehost/hostpolicy/hostpolicy_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.

#include "hostpolicy_context.h"
#include "hostpolicy.h"
#include <hostpolicy.h>
#include <host_runtime_contract.h>

#include "deps_resolver.h"
#include <error_codes.h>
Expand Down Expand Up @@ -104,6 +105,31 @@ namespace
return nullptr;
}
#endif

size_t HOST_CONTRACT_CALLTYPE get_runtime_property(
const char* key,
char* value_buffer,
size_t value_buffer_size,
void* contract_context)
{
hostpolicy_context_t* context = static_cast<hostpolicy_context_t*>(contract_context);
if (::strcmp(key, HOST_PROPERTY_ENTRY_ASSEMBLY_NAME) == 0)
{
return pal::pal_utf8string(get_filename_without_ext(context->application), value_buffer, value_buffer_size);
}

pal::string_t key_str;
if (pal::clr_palstring(key, &key_str))
{
const pal::char_t* value;
if (context->coreclr_properties.try_get(key_str.c_str(), &value))
{
return pal::pal_utf8string(value, value_buffer, value_buffer_size);
}
}

return -1;
}
}

int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const arguments_t &args, bool enable_breadcrumbs)
Expand Down Expand Up @@ -324,5 +350,25 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a
}
#endif

{
host_contract = { this };
if (bundle::info_t::is_single_file_bundle())
{
host_contract.bundle_probe = &bundle_probe;
#if defined(NATIVE_LIBS_EMBEDDED)
host_contract.pinvoke_override = &pinvoke_override;
#endif
}

host_contract.get_runtime_property = &get_runtime_property;
pal::stringstream_t ptr_stream;
ptr_stream << "0x" << std::hex << (size_t)(&host_contract);
if (!coreclr_properties.add(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT), ptr_stream.str().c_str()))
{
log_duplicate_property_error(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT));
return StatusCode::LibHostDuplicateProperty;
}
}

return StatusCode::Success;
}
3 changes: 3 additions & 0 deletions src/native/corehost/hostpolicy/hostpolicy_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "args.h"
#include "coreclr.h"
#include <corehost_context_contract.h>
#include <host_runtime_contract.h>
#include "hostpolicy_init.h"

struct hostpolicy_context_t
Expand All @@ -27,6 +28,8 @@ struct hostpolicy_context_t

std::unique_ptr<coreclr_t> coreclr;

host_runtime_contract host_contract;

int initialize(hostpolicy_init_t &hostpolicy_init, const arguments_t &args, bool enable_breadcrumbs);
};

Expand Down

0 comments on commit 5d744ee

Please sign in to comment.