Skip to content

Commit a4801d0

Browse files
authored
[CoreCLR] Add src/native/clr for CoreCLR hosting bits (#9778)
Context: #9572 Add a new `src/native/common` for files which can be shared between MonoVM and CoreCLR, and move common infrastructural source there, such as `jni-wrappers.hh` and `strings.hh`. Copy the parts of `src/native/mono` that will be used by #9572 but require modification to be used with CoreCLR into `src/native/clr`. `src/native/clr` is not yet compiled; this merely serves the purpose of making #9572 smaller and easier to review, copying code from the existing MonoVM implementation to the CoreCLR one, mostly without functional changes. There are very few functional changes, most code is copied verbatim with the only changes being formatting, function declaration syntax and, sometimes, the class in which the code lives. Only the code that's actually used in #9572 is copied. This allows us to refresh our runtime code while cleaning it up at the same time, with the goal of having an implementation that is tailored strictly towards CoreCLR (which doesn't have e.g. Mono's embedding APIs)
1 parent ff4c6d4 commit a4801d0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+5155
-285
lines changed

.gdn/policheck/source.gdnsuppress

+11
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,17 @@
9090
"justification": "Matching against `aapt2` tool output.",
9191
"createdDate": "2025-02-05 11:48:04Z"
9292
},
93+
"26d3e99b351de02627162b255b2513d833a0343a6f25064f35d7310eb07cf3ff": {
94+
"signature": "26d3e99b351de02627162b255b2513d833a0343a6f25064f35d7310eb07cf3ff",
95+
"alternativeSignatures": [
96+
"d23c1bf667150310fd782f0ad92064dcf077226a64d9bf1dd6762ead152f7703"
97+
],
98+
"memberOf": [
99+
"default"
100+
],
101+
"justification": "Reference to ffs(3) find first set bit function.",
102+
"createdDate": "2025-02-10 19:44:17Z"
103+
},
93104
"a5555a74b0e940543802a63a6465b4d965eff4f6c858552813df633186794c45": {
94105
"signature": "a5555a74b0e940543802a63a6465b4d965eff4f6c858552813df633186794c45",
95106
"alternativeSignatures": [

build-tools/scripts/generate-pinvoke-tables.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ case ${HOST} in
6464
*) die Unsupported OS ;;
6565
esac
6666

67-
${COMPILER} -O2 -std=c++20 -I${EXTERNAL_DIR} -I${EXTERNAL_DIR}/constexpr-xxh3 -I${NATIVE_DIR}/shared "${GENERATOR_SOURCE}" -o "${GENERATOR_BINARY}"
67+
${COMPILER} -O2 -std=c++20 -I${EXTERNAL_DIR} -I${EXTERNAL_DIR}/constexpr-xxh3 -I${NATIVE_DIR}/shared -I${NATIVE_DIR}/../common/include "${GENERATOR_SOURCE}" -o "${GENERATOR_BINARY}"
6868
"${GENERATOR_BINARY}" "${GENERATED_FILE}"
6969

7070
FILES_DIFFER="no"

src/native/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ set(SYSROOT_CXX_INCLUDE_DIR ${CMAKE_SYSROOT}/usr/include/c++/v1)
170170
set(MONO_RUNTIME_INCLUDE_DIR ${NET_RUNTIME_DIR}/native/include/mono-2.0)
171171
set(JAVA_INTEROP_INCLUDE_DIR ${JAVA_INTEROP_SRC_PATH})
172172

173+
include_directories(common/include)
174+
include_directories(mono)
175+
173176
#
174177
# Compiler defines
175178
#

src/native/clr/include/constants.hh

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
#pragma once
2+
3+
#include <fcntl.h>
4+
#include <sys/system_properties.h>
5+
6+
#include <string_view>
7+
8+
#include <shared/cpp-util.hh>
9+
10+
namespace xamarin::android {
11+
class Constants
12+
{
13+
#if INTPTR_MAX == INT64_MAX
14+
static inline constexpr std::string_view BITNESS { "64bit" };
15+
#else
16+
static inline constexpr std::string_view BITNESS { "32bit" };
17+
#endif
18+
19+
public:
20+
#if INTPTR_MAX == INT64_MAX
21+
static inline constexpr bool is_64_bit_target = true;
22+
#else
23+
static inline constexpr bool is_64_bit_target = false;
24+
#endif
25+
26+
#if defined(RELEASE)
27+
static constexpr bool is_release_build = true;
28+
static constexpr bool is_debug_build = false;
29+
#else
30+
static constexpr bool is_release_build = false;
31+
static constexpr bool is_debug_build = true;
32+
#endif
33+
static constexpr std::string_view MANGLED_ASSEMBLY_NAME_EXT { ".so" };
34+
35+
private:
36+
static constexpr std::string_view RUNTIME_CONFIG_BLOB_BASE_NAME { "libarc.bin" };
37+
static constexpr size_t runtime_config_blob_name_size = calc_size (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT);
38+
static constexpr auto RUNTIME_CONFIG_BLOB_NAME_ARRAY = concat_string_views<runtime_config_blob_name_size> (RUNTIME_CONFIG_BLOB_BASE_NAME, MANGLED_ASSEMBLY_NAME_EXT);
39+
40+
public:
41+
// .data() must be used otherwise string_view length will include the trailing \0 in the array
42+
static constexpr std::string_view RUNTIME_CONFIG_BLOB_NAME { RUNTIME_CONFIG_BLOB_NAME_ARRAY.data () };
43+
static constexpr std::string_view OVERRIDE_DIRECTORY_NAME { ".__override__" };
44+
45+
/* Android property containing connection information, set by XS */
46+
static inline constexpr std::string_view DEBUG_MONO_CONNECT_PROPERTY { "debug.mono.connect" };
47+
static inline constexpr std::string_view DEBUG_MONO_DEBUG_PROPERTY { "debug.mono.debug" };
48+
static inline constexpr std::string_view DEBUG_MONO_ENV_PROPERTY { "debug.mono.env" };
49+
static inline constexpr std::string_view DEBUG_MONO_EXTRA_PROPERTY { "debug.mono.extra" };
50+
static inline constexpr std::string_view DEBUG_MONO_GC_PROPERTY { "debug.mono.gc" };
51+
static inline constexpr std::string_view DEBUG_MONO_GDB_PROPERTY { "debug.mono.gdb" };
52+
static inline constexpr std::string_view DEBUG_MONO_LOG_PROPERTY { "debug.mono.log" };
53+
static inline constexpr std::string_view DEBUG_MONO_MAX_GREFC { "debug.mono.max_grefc" };
54+
static inline constexpr std::string_view DEBUG_MONO_PROFILE_PROPERTY { "debug.mono.profile" };
55+
static inline constexpr std::string_view DEBUG_MONO_RUNTIME_ARGS_PROPERTY { "debug.mono.runtime_args" };
56+
static inline constexpr std::string_view DEBUG_MONO_SOFT_BREAKPOINTS { "debug.mono.soft_breakpoints" };
57+
static inline constexpr std::string_view DEBUG_MONO_TRACE_PROPERTY { "debug.mono.trace" };
58+
static inline constexpr std::string_view DEBUG_MONO_WREF_PROPERTY { "debug.mono.wref" };
59+
60+
static constexpr std::string_view LOG_CATEGORY_NAME_NONE { "*none*" };
61+
static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID { "monodroid" };
62+
static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_ASSEMBLY { "monodroid-assembly" };
63+
static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_DEBUG { "monodroid-debug" };
64+
static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_GC { "monodroid-gc" };
65+
static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_GREF { "monodroid-gref" };
66+
static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_LREF { "monodroid-lref" };
67+
static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_TIMING { "monodroid-timing" };
68+
static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_BUNDLE { "monodroid-bundle" };
69+
static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_NETWORK { "monodroid-network" };
70+
static constexpr std::string_view LOG_CATEGORY_NAME_MONODROID_NETLINK { "monodroid-netlink" };
71+
static constexpr std::string_view LOG_CATEGORY_NAME_ERROR { "*error*" };
72+
73+
#if defined(__arm__)
74+
static constexpr std::string_view android_abi { "armeabi_v7a" };
75+
static constexpr std::string_view android_lib_abi { "armeabi-v7a" };
76+
static constexpr std::string_view runtime_identifier { "android-arm" };
77+
#elif defined(__aarch64__)
78+
static constexpr std::string_view android_abi { "arm64_v8a" };
79+
static constexpr std::string_view android_lib_abi { "arm64-v8a" };
80+
static constexpr std::string_view runtime_identifier { "android-arm64" };
81+
#elif defined(__x86_64__)
82+
static constexpr std::string_view android_abi { "x86_64" };
83+
static constexpr std::string_view android_lib_abi { "x86_64" };
84+
static constexpr std::string_view runtime_identifier { "android-x64" };
85+
#elif defined(__i386__)
86+
static constexpr std::string_view android_abi { "x86" };
87+
static constexpr std::string_view android_lib_abi { "x86" };
88+
static constexpr std::string_view runtime_identifier { "android-x86" };
89+
#endif
90+
91+
static constexpr std::string_view split_config_prefix { "/split_config." };
92+
static constexpr std::string_view split_config_extension { ".apk" };
93+
94+
private:
95+
static constexpr size_t split_config_abi_apk_name_size = calc_size (split_config_prefix, android_abi, split_config_extension);
96+
97+
public:
98+
static constexpr auto split_config_abi_apk_name = concat_string_views<split_config_abi_apk_name_size> (split_config_prefix, android_abi, split_config_extension);
99+
100+
//
101+
// Indexes must match these of trhe `appDirs` array in src/java-runtime/mono/android/MonoPackageManager.java
102+
//
103+
static constexpr size_t APP_DIRS_FILES_DIR_INDEX = 0uz;
104+
static constexpr size_t APP_DIRS_CACHE_DIR_INDEX = 1uz;
105+
static constexpr size_t APP_DIRS_DATA_DIR_INDEX = 2uz;
106+
107+
static inline constexpr size_t PROPERTY_VALUE_BUFFER_LEN = PROP_VALUE_MAX + 1uz;
108+
109+
// 64-bit unsigned or 64-bit signed with sign
110+
static constexpr size_t MAX_INTEGER_DIGIT_COUNT_BASE10 = 21uz;
111+
static constexpr size_t INTEGER_BASE10_BUFFER_SIZE = MAX_INTEGER_DIGIT_COUNT_BASE10 + 1uz;
112+
113+
// Documented in NDK's <android/log.h> comments
114+
static constexpr size_t MAX_LOGCAT_MESSAGE_LENGTH = 1023uz;
115+
116+
// PATH_MAX is always 4096 on Linux, but for our purposes it's most likely too much and since
117+
// we use this value to allocate stack variables mostly, let's downsize it a bit to what the
118+
// _XOPEN_PATH_MAX is set to
119+
static constexpr size_t SENSIBLE_PATH_MAX = 1024uz;
120+
121+
static constexpr int DEFAULT_DIRECTORY_MODE = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
122+
123+
#if defined (DEBUG)
124+
static constexpr std::string_view OVERRIDE_ENVIRONMENT_FILE_NAME { "environment" };
125+
static constexpr uint32_t OVERRIDE_ENVIRONMENT_FILE_HEADER_SIZE = 22;
126+
#endif
127+
128+
static constexpr std::string_view MONO_ANDROID_ASSEMBLY_NAME { "Mono.Android" };
129+
static constexpr std::string_view ANDROID_RUNTIME_NS_NAME { "Android.Runtime" };
130+
static constexpr std::string_view JNIENVINIT_CLASS_NAME { "JNIEnvInit" };
131+
static constexpr std::string_view JNIENV_CLASS_NAME { "JNIEnv" };
132+
133+
private:
134+
static constexpr size_t JNIENVINIT_FULL_TYPE_NAME_SIZE = calc_size (ANDROID_RUNTIME_NS_NAME, "."sv, JNIENVINIT_CLASS_NAME);
135+
static constexpr auto JNIENVINIT_FULL_TYPE_NAME_ARRAY = concat_string_views<JNIENVINIT_FULL_TYPE_NAME_SIZE> (ANDROID_RUNTIME_NS_NAME, "."sv, JNIENVINIT_CLASS_NAME);
136+
137+
public:
138+
static constexpr std::string_view JNIENVINIT_FULL_TYPE_NAME { JNIENVINIT_FULL_TYPE_NAME_ARRAY.data () };
139+
140+
static constexpr std::string_view ANDROID_ENVIRONMENT_CLASS_NAME { "AndroidEnvironment" };
141+
static constexpr std::string_view ANDROID_RUNTIME_INTERNAL_CLASS_NAME { "AndroidRuntimeInternal" };
142+
};
143+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#pragma once
2+
3+
#include <array>
4+
#include <limits>
5+
#include <string>
6+
#include <string_view>
7+
#include <unordered_map>
8+
9+
#include "../constants.hh"
10+
#include "../shared/log_types.hh"
11+
#include "../runtime-base/cpu-arch.hh"
12+
#include <runtime-base/jni-wrappers.hh>
13+
#include <runtime-base/strings.hh>
14+
#include "util.hh"
15+
16+
struct BundledProperty;
17+
18+
namespace xamarin::android {
19+
class AndroidSystem
20+
{
21+
// This optimizes things a little bit. The array is allocated at build time, so we pay no cost for its
22+
// allocation and at run time it allows us to skip dynamic memory allocation.
23+
inline static std::array<std::string, 1> single_app_lib_directory{};
24+
inline static std::span<std::string> app_lib_directories;
25+
26+
// TODO: override dirs not implemented
27+
inline static std::array<std::string, 1> override_dirs{};
28+
29+
static constexpr std::array<std::string_view, 7> android_abi_names {
30+
std::string_view { "unknown" }, // CPU_KIND_UNKNOWN
31+
std::string_view { "armeabi-v7a" }, // CPU_KIND_ARM
32+
std::string_view { "arm64-v8a" }, // CPU_KIND_ARM64
33+
std::string_view { "mips" }, // CPU_KIND_MIPS
34+
std::string_view { "x86" }, // CPU_KIND_X86
35+
std::string_view { "x86_64" }, // CPU_KIND_X86_64
36+
std::string_view { "riscv" }, // CPU_KIND_RISCV
37+
};
38+
39+
public:
40+
static auto get_gref_gc_threshold () noexcept -> long
41+
{
42+
if (max_gref_count == std::numeric_limits<int>::max ()) {
43+
return max_gref_count;
44+
}
45+
return static_cast<int> ((max_gref_count * 90LL) / 100LL);
46+
}
47+
48+
static auto get_max_gref_count () noexcept -> long
49+
{
50+
return max_gref_count;
51+
}
52+
53+
static void init_max_gref_count () noexcept
54+
{
55+
max_gref_count = get_max_gref_count_from_system ();
56+
}
57+
58+
static void set_running_in_emulator (bool yesno) noexcept
59+
{
60+
running_in_emulator = yesno;
61+
}
62+
63+
static auto get_primary_override_dir () noexcept -> std::string const&
64+
{
65+
return primary_override_dir;
66+
}
67+
68+
static void set_primary_override_dir (jstring_wrapper& home) noexcept
69+
{
70+
primary_override_dir = determine_primary_override_dir (home);
71+
}
72+
73+
static void create_update_dir (std::string const& override_dir) noexcept
74+
{
75+
if constexpr (Constants::is_release_build) {
76+
/*
77+
* Don't create .__override__ on Release builds, because Google requires
78+
* that pre-loaded apps not create world-writable directories.
79+
*
80+
* However, if any logging is enabled (which should _not_ happen with
81+
* pre-loaded apps!), we need the .__override__ directory...
82+
*/
83+
dynamic_local_string<Constants::PROPERTY_VALUE_BUFFER_LEN> value;
84+
if (log_categories == 0 && monodroid_get_system_property (Constants::DEBUG_MONO_PROFILE_PROPERTY, value) == 0) [[likely]] {
85+
return;
86+
}
87+
}
88+
89+
Util::create_public_directory (override_dir);
90+
log_warn (LOG_DEFAULT, "Creating public update directory: `{}`", override_dir);
91+
}
92+
93+
static auto is_embedded_dso_mode_enabled () noexcept -> bool
94+
{
95+
return embedded_dso_mode_enabled;
96+
}
97+
98+
static auto monodroid_get_system_property (std::string_view const& name, dynamic_local_string<Constants::PROPERTY_VALUE_BUFFER_LEN> &value) noexcept -> int;
99+
static void detect_embedded_dso_mode (jstring_array_wrapper& appDirs) noexcept;
100+
static void setup_environment () noexcept;
101+
static void setup_app_library_directories (jstring_array_wrapper& runtimeApks, jstring_array_wrapper& appDirs, bool have_split_apks) noexcept;
102+
static auto load_dso (const char *path, unsigned int dl_flags, bool skip_exists_check) noexcept -> void*;
103+
static auto load_dso_from_any_directories (const char *name, unsigned int dl_flags) noexcept -> void*;
104+
105+
private:
106+
static auto get_full_dso_path (std::string const& base_dir, const char *dso_path, dynamic_local_string<SENSIBLE_PATH_MAX>& path) noexcept -> bool;
107+
108+
template<class TContainer> // TODO: replace with a concept
109+
static auto load_dso_from_specified_dirs (TContainer directories, const char *dso_name, unsigned int dl_flags) noexcept -> void*;
110+
static auto load_dso_from_app_lib_dirs (const char *name, unsigned int dl_flags) noexcept -> void*;
111+
static auto load_dso_from_override_dirs (const char *name, unsigned int dl_flags) noexcept -> void*;
112+
static auto lookup_system_property (std::string_view const &name, size_t &value_len) noexcept -> const char*;
113+
static auto monodroid__system_property_get (std::string_view const&, char *sp_value, size_t sp_value_len) noexcept -> int;
114+
static auto get_max_gref_count_from_system () noexcept -> long;
115+
static void add_apk_libdir (std::string_view const& apk, size_t &index, std::string_view const& abi) noexcept;
116+
static void setup_apk_directories (unsigned short running_on_cpu, jstring_array_wrapper &runtimeApks, bool have_split_apks) noexcept;
117+
#if defined(DEBUG)
118+
static void add_system_property (const char *name, const char *value) noexcept;
119+
static void setup_environment (const char *name, const char *value) noexcept;
120+
static void setup_environment_from_override_file (dynamic_local_string<Constants::SENSIBLE_PATH_MAX> const& path) noexcept;
121+
#endif
122+
123+
static void set_embedded_dso_mode_enabled (bool yesno) noexcept
124+
{
125+
embedded_dso_mode_enabled = yesno;
126+
}
127+
128+
static auto determine_primary_override_dir (jstring_wrapper &home) noexcept -> std::string
129+
{
130+
dynamic_local_string<SENSIBLE_PATH_MAX> name { home.get_cstr () };
131+
name.append ("/")
132+
.append (Constants::OVERRIDE_DIRECTORY_NAME)
133+
.append ("/")
134+
.append (Constants::android_lib_abi);
135+
136+
return {name.get (), name.length ()};
137+
}
138+
139+
private:
140+
static inline long max_gref_count = 0;
141+
static inline bool running_in_emulator = false;
142+
static inline bool embedded_dso_mode_enabled = false;
143+
static inline std::string primary_override_dir;
144+
145+
#if defined (DEBUG)
146+
static inline std::unordered_map<std::string, std::string> bundled_properties;
147+
#endif
148+
};
149+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
5+
static inline constexpr uint16_t CPU_KIND_UNKNOWN = 0;
6+
static inline constexpr uint16_t CPU_KIND_ARM = 1;
7+
static inline constexpr uint16_t CPU_KIND_ARM64 = 2;
8+
static inline constexpr uint16_t CPU_KIND_MIPS = 3;
9+
static inline constexpr uint16_t CPU_KIND_X86 = 4;
10+
static inline constexpr uint16_t CPU_KIND_X86_64 = 5;
11+
static inline constexpr uint16_t CPU_KIND_RISCV = 6;
12+
13+
void _monodroid_detect_cpu_and_architecture (uint16_t &built_for_cpu, uint16_t &running_on_cpu, bool &is64bit);

0 commit comments

Comments
 (0)