[dotnet] Create and parse runtimeconfig.bin when using CoreCLR. (#12122)

We need to process the runtimeconfig.json file somehow when using CoreCLR, and
the embedding API we use (coreclr_initialize) won't parse it for us. So re-use
the logic we already have to process runtimeconfig.json for MonoVM (which
involves converting it to a binary format at build time, which we then process
at runtime).
This commit is contained in:
Rolf Bjarne Kvinge 2021-07-16 16:15:17 +02:00 коммит произвёл GitHub
Родитель 9d7efe6de0
Коммит d775794fd2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 129 добавлений и 5 удалений

Просмотреть файл

@ -677,7 +677,6 @@
<!-- App bundle creation tasks -->
<Target Name="_CreateRuntimeConfiguration"
Condition="'$(UseMonoRuntime)' != 'false'"
Inputs="$(ProjectRuntimeConfigFilePath)"
Outputs="$(_ParsedRuntimeConfigFilePath)"
DependsOnTargets="GenerateBuildRuntimeConfigurationFiles;_ComputePublishLocation"

Просмотреть файл

@ -8,6 +8,7 @@
#if defined (CORECLR_RUNTIME)
#include <sys/stat.h>
#include <inttypes.h>
#include <pthread.h>
@ -351,23 +352,147 @@ xamarin_enable_new_refcount ()
// Nothing to do here.
}
/**
* xamarin_bridge_decode_value:
*
* This implementation is a slightly modified copy (to make it compile) of mono_metadata_decode_value
* https://github.com/dotnet/runtime/blob/08a7b2382799082eedb94d70fca6c66eb75f2872/src/mono/mono/metadata/metadata.c#L1525
*/
guint32
xamarin_bridge_decode_value (const char *_ptr, const char **rptr)
{
const unsigned char *ptr = (const unsigned char *) _ptr;
unsigned char b = *ptr;
guint32 len;
if ((b & 0x80) == 0){
len = b;
++ptr;
} else if ((b & 0x40) == 0){
len = (guint32) ((b & 0x3f) << 8 | ptr [1]);
ptr += 2;
} else {
len = (guint32) (((b & 0x1f) << 24) |
(ptr [1] << 16) |
(ptr [2] << 8) |
ptr [3]);
ptr += 4;
}
if (rptr)
*rptr = (char*)ptr;
return len;
}
static char *
xamarin_read_config_string (const char **buf)
{
guint32 configLength = xamarin_bridge_decode_value (*buf, buf);
char *value = strndup (*buf, configLength);
*buf = *buf + configLength;
return value;
}
static void *
xamarin_mmap_runtime_config_file (size_t *length)
{
if (xamarin_runtime_configuration_name == NULL) {
LOG (PRODUCT ": No runtime config file provided at build time.\n");
return NULL;
}
char path [1024];
if (!xamarin_locate_app_resource (xamarin_runtime_configuration_name, path, sizeof (path))) {
LOG (PRODUCT ": Could not locate the runtime config file '%s' in the app bundle.\n", xamarin_runtime_configuration_name);
return NULL;
}
int fd = open (path, O_RDONLY);
if (fd == -1) {
LOG (PRODUCT ": Could not open the runtime config file '%s' in the app bundle: %s\n", path, strerror (errno));
return NULL;
}
struct stat stat_buf = { 0 };
if (fstat (fd, &stat_buf) == -1) {
LOG (PRODUCT ": Could not stat the runtime config file '%s' in the app bundle: %s\n", path, strerror (errno));
close (fd);
return NULL;
}
*length = (size_t) stat_buf.st_size;
void *buffer = mmap (NULL, *length, PROT_READ, MAP_PRIVATE, fd, 0);
close (fd);
return buffer;
}
// Input: the property keys + values passed to xamarin_bridge_vm_initialize
// Output: newly allocated arrays of property keys + values that include those passed to xamarin_bridge_vm_initialize together with those in the runtimeconfig.bin file
// Caller must free the allocated arrays + their elements
void
xamarin_bridge_compute_properties (int inputCount, const char **inputKeys, const char **inputValues, int* outputCount, const char ***outputKeys, const char ***outputValues)
{
size_t fd_len = 0;
const char *buf = (const char *) xamarin_mmap_runtime_config_file (&fd_len);
int runtimeConfigCount = 0;
if (buf != NULL)
runtimeConfigCount = (int) xamarin_bridge_decode_value (buf, &buf);
// Allocate the output arrays
*outputCount = inputCount + runtimeConfigCount;
*outputKeys = (const char **) calloc ((size_t) *outputCount, sizeof (char *));
*outputValues = (const char **) calloc ((size_t) *outputCount, sizeof (char *));
// Read the runtimeconfig properties
// https://github.com/dotnet/runtime/blob/57bfe474518ab5b7cfe6bf7424a79ce3af9d6657/docs/design/mono/mobile-runtimeconfig-json.md#the-encoded-runtimeconfig-format
for (int i = 0; i < runtimeConfigCount; i++) {
char *key = xamarin_read_config_string (&buf);
char *value = xamarin_read_config_string (&buf);
(*outputKeys) [i] = key;
(*outputValues) [i] = value;
}
// Copy the input properties
for (int i = 0; i < inputCount; i++) {
(*outputKeys) [i + runtimeConfigCount] = strdup (inputKeys [i]);
(*outputValues) [i + runtimeConfigCount] = strdup (inputValues [i]);
}
if (buf != NULL)
munmap ((void *) buf, fd_len);
}
bool
xamarin_bridge_vm_initialize (int propertyCount, const char **propertyKeys, const char **propertyValues)
{
int rv;
int combinedPropertyCount = 0;
const char **combinedPropertyKeys = NULL;
const char **combinedPropertyValues = NULL;
xamarin_bridge_compute_properties (propertyCount, propertyKeys, propertyValues, &combinedPropertyCount, &combinedPropertyKeys, &combinedPropertyValues);
const char *executablePath = [[[[NSBundle mainBundle] executableURL] path] UTF8String];
rv = coreclr_initialize (
executablePath,
xamarin_executable_name,
propertyCount,
propertyKeys,
propertyValues,
combinedPropertyCount,
combinedPropertyKeys,
combinedPropertyValues,
&coreclr_handle,
&coreclr_domainId
);
LOG_CORECLR (stderr, "xamarin_vm_initialize (%i, %p, %p): rv: %i domainId: %i handle: %p\n", propertyCount, propertyKeys, propertyValues, rv, coreclr_domainId, coreclr_handle);
for (int i = 0; i < combinedPropertyCount; i++) {
free ((void *) combinedPropertyKeys [i]);
free ((void *) combinedPropertyValues [i]);
}
free ((void *) combinedPropertyKeys);
free ((void *) combinedPropertyValues);
LOG_CORECLR (stderr, "xamarin_vm_initialize (%i, %p, %p): rv: %i domainId: %i handle: %p\n", combinedPropertyCount, combinedPropertyKeys, combinedPropertyValues, rv, coreclr_domainId, coreclr_handle);
return rv == 0;
}