blob: 708fad8c91b8e16260f0310fee1b731baf77e962 [file] [log] [blame]
//
// part of renode portable
//
//
// reimplement some libc stuff not present in older versions
// but possibly used by libmono
//
#include <syscall.h>
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 <dlfcn.h>
#include <string.h>
#include <stdio.h>
#include <libgen.h>
#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 <mono/jit/jit.h>
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;
}