1 //
2 // part of renode portable
3 //
4
5 //
6 // reimplement some libc stuff not present in older versions
7 // but possibly used by libmono
8 //
9
10 #include <syscall.h>
__wrap_getrandom(void * buffer,size_t length,unsigned int flags)11 ssize_t __wrap_getrandom (void *buffer, size_t length, unsigned int flags) {
12 return syscall(__NR_getrandom, buffer, length, flags);
13 }
14
__wrap_powf()15 void __wrap_powf() {
16 printf("!!!! powf!\n"); // TODO
17 }
18
__wrap_logf()19 void __wrap_logf() {
20 printf("!!!! logf!\n"); // TODO
21 }
22
__wrap_expf()23 void __wrap_expf() {
24 printf("!!!! expf!\n"); // TODO
25 }
26
27 #define LIST_LENGTH 2048
28 #define MAX_FILENAME_LENGTH 4096
29
30 char binary_path[MAX_FILENAME_LENGTH];
31
32 void* list_ptrs[LIST_LENGTH];
33 char* list_names[LIST_LENGTH];
34 int list_counter = 0;
35
get_name(void * ptr)36 static char* get_name(void* ptr) {
37 for (int i = 0; i < list_counter; i++) {
38 if (list_ptrs[i] == ptr) {
39 return list_names[i];
40 }
41 }
42 return "(unknown)";
43 }
44
45 #include <dlfcn.h>
46 #include <string.h>
47 #include <stdio.h>
48 #include <libgen.h>
49
50 #ifdef DEBUG_PRINT
51 #define debug_print printf
52 #define error_print printf
53 #else
54 #define debug_print(...)
55 #define error_print(...)
56 #endif
57
58 #define SHM "/dev/shm/"
__wrap___shm_directory(size_t * len)59 const char * __wrap___shm_directory(size_t *len) {
60 *len = sizeof(SHM);
61 return SHM;
62 }
63
__wrap_mono_dl_lookup_symbol(void ** module_handle,const char * name)64 void *__wrap_mono_dl_lookup_symbol(void **module_handle, const char *name) {
65 debug_print("mono_dl_lookup_symbol(%p, %s)\n", *module_handle, name);
66 debug_print(">>> dlsym: looking for symbol '%s' in %p [%s]\n", name, *module_handle, get_name(*module_handle));
67 return dlsym(*module_handle, name);
68 }
69
__wrap_mono_dl_open_file(const char * name,int flags)70 void *__wrap_mono_dl_open_file(const char *name, int flags) {
71 debug_print("mono_dl_open_file(%s, %d)\n", name, flags);
72 if (name == NULL) {
73 return NULL;
74 }
75
76 char filename[MAX_FILENAME_LENGTH];
77 int l = snprintf(filename, MAX_FILENAME_LENGTH, "%s", name);
78 if (l < 0 || l >= MAX_FILENAME_LENGTH) {
79 error_print(">>> dlopen: error while configuring the filename: %s\n", filename);
80 return NULL;
81 }
82
83 debug_print(">>> dlopen: %s\n", filename);
84
85 // skip .dll.so calls.
86 if (strstr(filename, ".dll.so") != 0) {
87 debug_print(">>> dlopen: ignoring %s as it is .dll.so\n", filename);
88 return NULL;
89 }
90
91 // patch current directory
92 if (strlen(filename) >= 2 && filename[0] == '.' && filename[1] == '/') {
93 // +2 to skip the initial './'
94 int l = snprintf(filename, MAX_FILENAME_LENGTH, "%s%s", binary_path, name + 2);
95 if (l < 0 || l >= MAX_FILENAME_LENGTH) {
96 error_print(">>> dlopen: error while patching the filename\n");
97 return NULL;
98 }
99 debug_print(">>> dlopen: filename patched to %s\n", filename);
100 }
101
102 void* result = dlopen((strcmp(filename, "__Internal") == 0) ? "" : filename, flags);
103 debug_print(">>> dlopen: result is %p; filename was %s, flag was %d\n", result, filename, flags);
104 if (result != NULL) {
105 list_ptrs[list_counter] = result;
106 list_names[list_counter] = strdup(basename(filename));
107 debug_print(">>> dlopen: %s returns %p\n", list_names[list_counter], result);
108 list_counter = (list_counter + 1) % LIST_LENGTH;
109 } else {
110 debug_print(">>> dlopen: result is null: %s\n", dlerror());
111 }
112
113 return result;
114 }
115
116 // import MonoPosixHelper functions so that they're exported
117 extern void Mono_Posix_Syscall_get_at_fdcwd();
118 extern void Mono_Posix_Syscall_L_ctermid();
119 extern void Mono_Posix_Syscall_get_utime_now();
120 extern void Mono_Posix_Syscall_readlink();
121 extern void Mono_Posix_Stdlib_SIG_DFL();
122 extern void Mono_Posix_Stdlib_EXIT_FAILURE();
123 extern void CreateZStream();
124 extern void CloseZStream();
125 extern void ReadZStream();
126 extern void WriteZStream();
127
128 // dummy function so that they're not optimized away
129 #define ATTR __attribute__ ((__visibility__ ("default"))) __attribute__((noinline))
DO_NOT_RUN_dummy_callback(void)130 ATTR void DO_NOT_RUN_dummy_callback(void) {
131 // the section below contains a list of all
132 // symbols that are to be remapped in the dllmap
133 // by the tools/packaging/make_linux_portable.sh script;
134 // they are extracted automatically, so please
135 // add all new items between markers and
136 // *DO NOT* modify markers themselves
137
138 // --- REMAPPED SYMBOLS SECTION STARTS ---
139 Mono_Posix_Syscall_get_at_fdcwd();
140 Mono_Posix_Syscall_L_ctermid();
141 Mono_Posix_Syscall_get_utime_now();
142 Mono_Posix_Syscall_readlink();
143 Mono_Posix_Stdlib_SIG_DFL();
144 Mono_Posix_Stdlib_EXIT_FAILURE();
145 CreateZStream();
146 CloseZStream();
147 ReadZStream();
148 WriteZStream();
149 // --- REMAPPED SYMBOLS SECTION ENDS ---
150 }
151
152 //
153 // end of reimplement
154 //
155
156 //
157 // helper methods
158 //
GetBundlesCount(void)159 ATTR int GetBundlesCount(void) {
160 static int bundle_count = -1;
161 if (bundle_count != -1) return bundle_count;
162 MonoBundledAssembly **ptr = (MonoBundledAssembly **) compressed;
163 int nbundles = 0;
164 while (*ptr++ != NULL) {
165 nbundles++;
166 }
167 bundle_count = nbundles;
168 return bundle_count;
169 }
170
get_bundle(int id)171 static MonoBundledAssembly *get_bundle(int id) {
172 return (id >= GetBundlesCount()) ? NULL : bundled[id];
173 }
174
GetBundleName(int id)175 ATTR char* GetBundleName(int id) {
176 MonoBundledAssembly *bundle = get_bundle(id);
177 return bundle ? (char*)(bundle->name) : "";
178 }
179
GetBundleDataSize(int id)180 ATTR uint32_t GetBundleDataSize(int id) {
181 MonoBundledAssembly *bundle = get_bundle(id);
182 return bundle ? bundle->size : 0;
183 }
184
GetBundleDataPointer(int id)185 ATTR void* GetBundleDataPointer(int id) {
186 MonoBundledAssembly *bundle = get_bundle(id);
187 return bundle ? (void*)bundle->data : NULL;
188 }
189
190 //
191 // end of helper methods
192 //
193
194 #include <mono/jit/jit.h>
main(int argc,char * argv[])195 int main (int argc, char* argv[]) {
196 char **newargs;
197 int i, k = 0;
198
199 // dirname might modify the content, so let's keep
200 // the link in a separate buffer first
201 char tmp[MAX_FILENAME_LENGTH];
202 ssize_t l = readlink("/proc/self/exe", tmp, MAX_FILENAME_LENGTH);
203 // adding 2 to the size to make room for `/` and the final NULL character
204 // in theory 1 should be enough as we call `dirname`, but let's be safe
205 if (l < 0 || l >= MAX_FILENAME_LENGTH - 2) {
206 printf("ERROR: Could read the link to self and determine the binary path. Exiting");
207 return 1;
208 }
209 sprintf(binary_path, "%s/", dirname(tmp));
210
211 newargs = (char **) malloc (sizeof (char *) * (argc + 2));
212 newargs [k++] = image_name;
213
214 for (i = 1; i < argc; i++) {
215 newargs [k++] = argv [i];
216 }
217 newargs [k] = NULL;
218
219 if (config_dir != NULL && getenv ("MONO_CFG_DIR") == NULL) {
220 mono_set_dirs (getenv ("MONO_PATH"), config_dir);
221 }
222
223 mono_mkbundle_init();
224
225 MonoDomain *domain = mono_jit_init ("Renode.exe");
226 MonoAssembly *assembly;
227 assembly = mono_domain_assembly_open (domain, "Renode.exe");
228
229 mono_jit_exec (domain, assembly, k, newargs);
230 int retval = mono_environment_exitcode_get ();
231 mono_jit_cleanup (domain);
232
233 return retval;
234 }
235
236