Merge pull request #3169 from lambdageek/fix-regression-70561
[mono-project.git] / mono / mini / main.c
blob241e6f57e59772d39287fe0b22cb5c2326ce0925
1 #include <config.h>
2 #include <fcntl.h>
3 #include <mono/metadata/assembly.h>
4 #include <mono/utils/mono-mmap.h>
5 #include "mini.h"
7 #ifdef HAVE_UNISTD_H
8 # include <unistd.h>
9 #endif
10 #ifdef HOST_WIN32
11 # include <io.h>
12 #else
13 # ifndef BUILDVER_INCLUDED
14 # include "buildver-boehm.h"
15 # endif
16 #endif
19 * If the MONO_ENV_OPTIONS environment variable is set, it uses this as a
20 * source of command line arguments that are passed to Mono before the
21 * command line arguments specified in the command line.
23 static int
24 mono_main_with_options (int argc, char *argv [])
26 mono_parse_env_options (&argc, &argv);
28 return mono_main (argc, argv);
31 #define STREAM_INT(x) (*(uint32_t*)x)
32 #define STREAM_LONG(x) (*(uint64_t*)x)
34 static gboolean
35 probe_embedded (const char *program, int *ref_argc, char **ref_argv [])
37 MonoBundledAssembly last = { NULL, 0, 0 };
38 char sigbuffer [16+sizeof (uint64_t)];
39 gboolean status = FALSE;
40 uint64_t directory_location;
41 off_t sigstart, baseline = 0;
42 uint64_t directory_size;
43 char *directory, *p;
44 int items, i;
45 unsigned char *mapaddress = NULL;
46 void *maphandle = NULL;
47 GArray *assemblies;
48 char *entry_point = NULL;
49 char **new_argv;
50 int j;
52 int fd = open (program, O_RDONLY);
53 if (fd == -1)
54 return FALSE;
55 if ((sigstart = lseek (fd, -24, SEEK_END)) == -1)
56 goto doclose;
57 if (read (fd, sigbuffer, sizeof (sigbuffer)) == -1)
58 goto doclose;
59 if (memcmp (sigbuffer+sizeof(uint64_t), "xmonkeysloveplay", 16) != 0)
60 goto doclose;
61 directory_location = GUINT64_FROM_LE ((*(uint64_t *) &sigbuffer [0]));
62 if (lseek (fd, directory_location, SEEK_SET) == -1)
63 goto doclose;
64 directory_size = sigstart-directory_location;
65 directory = g_malloc (directory_size);
66 if (directory == NULL)
67 goto doclose;
68 if (read (fd, directory, directory_size) == -1)
69 goto dofree;
71 items = STREAM_INT (directory);
72 p = directory+4;
74 assemblies = g_array_new (0, 0, sizeof (MonoBundledAssembly*));
75 for (i = 0; i < items; i++){
76 char *kind;
77 int strsize = STREAM_INT (p);
78 uint64_t offset, item_size;
79 kind = p+4;
80 p += 4 + strsize;
81 offset = STREAM_LONG(p);
82 p += 8;
83 item_size = STREAM_INT (p);
84 p += 4;
86 if (mapaddress == NULL){
87 mapaddress = mono_file_map (directory_location-offset, MONO_MMAP_READ | MONO_MMAP_PRIVATE, fd, offset, &maphandle);
88 if (mapaddress == NULL){
89 perror ("Error mapping file");
90 exit (1);
92 baseline = offset;
94 if (strncmp (kind, "assembly:", strlen ("assembly:")) == 0){
95 char *aname = kind + strlen ("assembly:");
96 MonoBundledAssembly mba = { aname, mapaddress + offset - baseline, item_size }, *ptr;
97 ptr = g_new (MonoBundledAssembly, 1);
98 memcpy (ptr, &mba, sizeof (MonoBundledAssembly));
99 g_array_append_val (assemblies, ptr);
100 if (entry_point == NULL)
101 entry_point = aname;
102 } else if (strncmp (kind, "config:", strlen ("config:")) == 0){
103 printf ("c-Found: %s %llx\n", kind, (long long)offset);
104 char *config = kind + strlen ("config:");
105 char *aname = g_strdup (config);
106 aname [strlen(aname)-strlen(".config")] = 0;
107 mono_register_config_for_assembly (aname, config);
108 } else if (strncmp (kind, "system_config:", strlen ("system_config:")) == 0){
109 printf ("TODO s-Found: %s %llx\n", kind, (long long)offset);
110 } else if (strncmp (kind, "options:", strlen ("options:")) == 0){
111 mono_parse_options_from (kind + strlen("options:"), ref_argc, ref_argv);
112 } else if (strncmp (kind, "config_dir:", strlen ("config_dir:")) == 0){
113 printf ("TODO Found: %s %llx\n", kind, (long long)offset);
114 } else {
115 fprintf (stderr, "Unknown stream on embedded package: %s\n", kind);
116 exit (1);
119 g_array_append_val (assemblies, last);
121 mono_register_bundled_assemblies ((const MonoBundledAssembly **) assemblies->data);
122 new_argv = g_new (char *, (*ref_argc)+1);
123 for (j = 0; j < *ref_argc; j++)
124 new_argv [j] = (*ref_argv)[j];
125 new_argv [j] = entry_point;
126 *ref_argv = new_argv;
127 (*ref_argc)++;
129 return TRUE;
131 dofree:
132 g_free (directory);
133 doclose:
134 if (!status)
135 close (fd);
136 return status;
139 #ifdef HOST_WIN32
141 #include <shellapi.h>
144 main (void)
146 TCHAR szFileName[MAX_PATH];
147 int argc;
148 gunichar2** argvw;
149 gchar** argv;
150 int i;
151 DWORD count;
153 argvw = CommandLineToArgvW (GetCommandLine (), &argc);
154 argv = g_new0 (gchar*, argc + 1);
155 for (i = 0; i < argc; i++)
156 argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL);
157 argv [argc] = NULL;
159 LocalFree (argvw);
161 if ((count = GetModuleFileName (NULL, szFileName, MAX_PATH)) != 0){
162 char *entry = g_utf16_to_utf8 (szFileName, count, NULL, NULL, NULL);
163 probe_embedded (entry, &argc, &argv);
166 return mono_main_with_options (argc, argv);
169 #else
172 main (int argc, char* argv[])
174 mono_build_date = build_date;
176 probe_embedded (argv [0], &argc, &argv);
177 return mono_main_with_options (argc, argv);
180 #endif