// // part of renode portable // // // reimplement some libc stuff not present in older versions // but possibly used by libmono // #include ssize_t __wrap_getrandom (void *buffer, size_t length, unsigned int flags) { return syscall(__NR_getrandom, buffer, length, flags); } void __wrap_powf() { printf("!!!! powf!\n"); // TODO } void __wrap_logf() { printf("!!!! logf!\n"); // TODO } void __wrap_expf() { printf("!!!! expf!\n"); // TODO } #define LIST_LENGTH 2048 #define MAX_FILENAME_LENGTH 4096 char binary_path[MAX_FILENAME_LENGTH]; void* list_ptrs[LIST_LENGTH]; char* list_names[LIST_LENGTH]; int list_counter = 0; static char* get_name(void* ptr) { for (int i = 0; i < list_counter; i++) { if (list_ptrs[i] == ptr) { return list_names[i]; } } return "(unknown)"; } #include #include #include #include #ifdef DEBUG_PRINT #define debug_print printf #define error_print printf #else #define debug_print(...) #define error_print(...) #endif #define SHM "/dev/shm/" const char * __wrap___shm_directory(size_t *len) { *len = sizeof(SHM); return SHM; } void *__wrap_mono_dl_lookup_symbol(void **module_handle, const char *name) { debug_print("mono_dl_lookup_symbol(%p, %s)\n", *module_handle, name); debug_print(">>> dlsym: looking for symbol '%s' in %p [%s]\n", name, *module_handle, get_name(*module_handle)); return dlsym(*module_handle, name); } void *__wrap_mono_dl_open_file(const char *name, int flags) { debug_print("mono_dl_open_file(%s, %d)\n", name, flags); if (name == NULL) { return NULL; } char filename[MAX_FILENAME_LENGTH]; int l = snprintf(filename, MAX_FILENAME_LENGTH, "%s", name); if (l < 0 || l >= MAX_FILENAME_LENGTH) { error_print(">>> dlopen: error while configuring the filename: %s\n", filename); return NULL; } debug_print(">>> dlopen: %s\n", filename); // skip .dll.so calls. if (strstr(filename, ".dll.so") != 0) { debug_print(">>> dlopen: ignoring %s as it is .dll.so\n", filename); return NULL; } // patch current directory if (strlen(filename) >= 2 && filename[0] == '.' && filename[1] == '/') { // +2 to skip the initial './' int l = snprintf(filename, MAX_FILENAME_LENGTH, "%s%s", binary_path, name + 2); if (l < 0 || l >= MAX_FILENAME_LENGTH) { error_print(">>> dlopen: error while patching the filename\n"); return NULL; } debug_print(">>> dlopen: filename patched to %s\n", filename); } void* result = dlopen((strcmp(filename, "__Internal") == 0) ? "" : filename, flags); debug_print(">>> dlopen: result is %p; filename was %s, flag was %d\n", result, filename, flags); if (result != NULL) { list_ptrs[list_counter] = result; list_names[list_counter] = strdup(basename(filename)); debug_print(">>> dlopen: %s returns %p\n", list_names[list_counter], result); list_counter = (list_counter + 1) % LIST_LENGTH; } else { debug_print(">>> dlopen: result is null: %s\n", dlerror()); } return result; } // import MonoPosixHelper functions so that they're exported extern void Mono_Posix_Syscall_get_at_fdcwd(); extern void Mono_Posix_Syscall_L_ctermid(); extern void Mono_Posix_Syscall_get_utime_now(); extern void Mono_Posix_Syscall_readlink(); extern void Mono_Posix_Stdlib_SIG_DFL(); extern void Mono_Posix_Stdlib_EXIT_FAILURE(); extern void CreateZStream(); extern void CloseZStream(); extern void ReadZStream(); extern void WriteZStream(); // dummy function so that they're not optimized away #define ATTR __attribute__ ((__visibility__ ("default"))) __attribute__((noinline)) ATTR void DO_NOT_RUN_dummy_callback(void) { // the section below contains a list of all // symbols that are to be remapped in the dllmap // by the tools/packaging/make_linux_portable.sh script; // they are extracted automatically, so please // add all new items between markers and // *DO NOT* modify markers themselves // --- REMAPPED SYMBOLS SECTION STARTS --- Mono_Posix_Syscall_get_at_fdcwd(); Mono_Posix_Syscall_L_ctermid(); Mono_Posix_Syscall_get_utime_now(); Mono_Posix_Syscall_readlink(); Mono_Posix_Stdlib_SIG_DFL(); Mono_Posix_Stdlib_EXIT_FAILURE(); CreateZStream(); CloseZStream(); ReadZStream(); WriteZStream(); // --- REMAPPED SYMBOLS SECTION ENDS --- } // // end of reimplement // // // helper methods // ATTR int GetBundlesCount(void) { static int bundle_count = -1; if (bundle_count != -1) return bundle_count; MonoBundledAssembly **ptr = (MonoBundledAssembly **) compressed; int nbundles = 0; while (*ptr++ != NULL) { nbundles++; } bundle_count = nbundles; return bundle_count; } static MonoBundledAssembly *get_bundle(int id) { return (id >= GetBundlesCount()) ? NULL : bundled[id]; } ATTR char* GetBundleName(int id) { MonoBundledAssembly *bundle = get_bundle(id); return bundle ? (char*)(bundle->name) : ""; } ATTR uint32_t GetBundleDataSize(int id) { MonoBundledAssembly *bundle = get_bundle(id); return bundle ? bundle->size : 0; } ATTR void* GetBundleDataPointer(int id) { MonoBundledAssembly *bundle = get_bundle(id); return bundle ? (void*)bundle->data : NULL; } // // end of helper methods // #include int main (int argc, char* argv[]) { char **newargs; int i, k = 0; // dirname might modify the content, so let's keep // the link in a separate buffer first char tmp[MAX_FILENAME_LENGTH]; ssize_t l = readlink("/proc/self/exe", tmp, MAX_FILENAME_LENGTH); // adding 2 to the size to make room for `/` and the final NULL character // in theory 1 should be enough as we call `dirname`, but let's be safe if (l < 0 || l >= MAX_FILENAME_LENGTH - 2) { printf("ERROR: Could read the link to self and determine the binary path. Exiting"); return 1; } sprintf(binary_path, "%s/", dirname(tmp)); newargs = (char **) malloc (sizeof (char *) * (argc + 2)); newargs [k++] = image_name; for (i = 1; i < argc; i++) { newargs [k++] = argv [i]; } newargs [k] = NULL; if (config_dir != NULL && getenv ("MONO_CFG_DIR") == NULL) { mono_set_dirs (getenv ("MONO_PATH"), config_dir); } mono_mkbundle_init(); MonoDomain *domain = mono_jit_init ("Renode.exe"); MonoAssembly *assembly; assembly = mono_domain_assembly_open (domain, "Renode.exe"); mono_jit_exec (domain, assembly, k, newargs); int retval = mono_environment_exitcode_get (); mono_jit_cleanup (domain); return retval; }