PageRenderTime 62ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/mono/metadata/domain.c

https://bitbucket.org/danipen/mono
C | 2701 lines | 1847 code | 474 blank | 380 comment | 305 complexity | e460b1959b4e67183c0fd03c10e88161 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. /*
  2. * domain.c: MonoDomain functions
  3. *
  4. * Author:
  5. * Dietmar Maurer (dietmar@ximian.com)
  6. * Patrik Torstensson
  7. *
  8. * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  9. * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  10. * Copyright 2011-2012 Xamarin, Inc (http://www.xamarin.com)
  11. */
  12. #include <config.h>
  13. #include <glib.h>
  14. #include <string.h>
  15. #include <sys/stat.h>
  16. #include <mono/metadata/gc-internal.h>
  17. #include <mono/utils/mono-compiler.h>
  18. #include <mono/utils/mono-logger-internal.h>
  19. #include <mono/utils/mono-membar.h>
  20. #include <mono/utils/mono-counters.h>
  21. #include <mono/utils/hazard-pointer.h>
  22. #include <mono/utils/mono-tls.h>
  23. #include <mono/metadata/object.h>
  24. #include <mono/metadata/object-internals.h>
  25. #include <mono/metadata/domain-internals.h>
  26. #include <mono/metadata/class-internals.h>
  27. #include <mono/metadata/assembly.h>
  28. #include <mono/metadata/exception.h>
  29. #include <mono/metadata/metadata-internals.h>
  30. #include <mono/metadata/gc-internal.h>
  31. #include <mono/metadata/appdomain.h>
  32. #include <mono/metadata/mono-debug-debugger.h>
  33. #include <mono/metadata/mono-config.h>
  34. #include <mono/metadata/threads-types.h>
  35. #include <metadata/threads.h>
  36. #include <metadata/profiler-private.h>
  37. #include <mono/metadata/coree.h>
  38. /* #define DEBUG_DOMAIN_UNLOAD */
  39. /* we need to use both the Tls* functions and __thread because
  40. * some archs may generate faster jit code with one meachanism
  41. * or the other (we used to do it because tls slots were GC-tracked,
  42. * but we can't depend on this).
  43. */
  44. static MonoNativeTlsKey appdomain_thread_id;
  45. #ifdef MONO_HAVE_FAST_TLS
  46. MONO_FAST_TLS_DECLARE(tls_appdomain);
  47. #define GET_APPDOMAIN() ((MonoDomain*)MONO_FAST_TLS_GET(tls_appdomain))
  48. #define SET_APPDOMAIN(x) do { \
  49. MONO_FAST_TLS_SET (tls_appdomain,x); \
  50. mono_native_tls_set_value (appdomain_thread_id, x); \
  51. mono_gc_set_current_thread_appdomain (x); \
  52. } while (FALSE)
  53. #else /* !MONO_HAVE_FAST_TLS */
  54. #define GET_APPDOMAIN() ((MonoDomain *)mono_native_tls_get_value (appdomain_thread_id))
  55. #define SET_APPDOMAIN(x) do { \
  56. mono_native_tls_set_value (appdomain_thread_id, x); \
  57. mono_gc_set_current_thread_appdomain (x); \
  58. } while (FALSE)
  59. #endif
  60. #define GET_APPCONTEXT() (mono_thread_internal_current ()->current_appcontext)
  61. #define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_internal_current (), current_appcontext, (x))
  62. static guint16 appdomain_list_size = 0;
  63. static guint16 appdomain_next = 0;
  64. static MonoDomain **appdomains_list = NULL;
  65. static MonoImage *exe_image;
  66. gboolean mono_dont_free_domains;
  67. #define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
  68. #define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
  69. static CRITICAL_SECTION appdomains_mutex;
  70. static MonoDomain *mono_root_domain = NULL;
  71. /* some statistics */
  72. static int max_domain_code_size = 0;
  73. static int max_domain_code_alloc = 0;
  74. static int total_domain_code_alloc = 0;
  75. /* AppConfigInfo: Information about runtime versions supported by an
  76. * aplication.
  77. */
  78. typedef struct {
  79. GSList *supported_runtimes;
  80. char *required_runtime;
  81. int configuration_count;
  82. int startup_count;
  83. } AppConfigInfo;
  84. /*
  85. * AotModuleInfo: Contains information about AOT modules.
  86. */
  87. typedef struct {
  88. MonoImage *image;
  89. gpointer start, end;
  90. } AotModuleInfo;
  91. static const MonoRuntimeInfo *current_runtime = NULL;
  92. static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL;
  93. /*
  94. * Contains information about AOT loaded code.
  95. */
  96. static MonoAotModuleInfoTable *aot_modules = NULL;
  97. /* This is the list of runtime versions supported by this JIT.
  98. */
  99. static const MonoRuntimeInfo supported_runtimes[] = {
  100. {"v2.0.50215","2.0", { {2,0,0,0}, { 8,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
  101. {"v2.0.50727","2.0", { {2,0,0,0}, { 8,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
  102. {"v4.0.30319","4.5", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
  103. {"v4.0.30128","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
  104. {"v4.0.20506","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
  105. {"moonlight", "2.1", { {2,0,5,0}, { 9,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
  106. };
  107. /* The stable runtime version */
  108. #define DEFAULT_RUNTIME_VERSION "v2.0.50727"
  109. /* Callbacks installed by the JIT */
  110. static MonoCreateDomainFunc create_domain_hook;
  111. static MonoFreeDomainFunc free_domain_hook;
  112. /* This is intentionally not in the header file, so people don't misuse it. */
  113. extern void _mono_debug_init_corlib (MonoDomain *domain);
  114. static void
  115. get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes);
  116. static const MonoRuntimeInfo*
  117. get_runtime_by_version (const char *version);
  118. static MonoImage*
  119. mono_jit_info_find_aot_module (guint8* addr);
  120. MonoNativeTlsKey
  121. mono_domain_get_tls_key (void)
  122. {
  123. return appdomain_thread_id;
  124. }
  125. gint32
  126. mono_domain_get_tls_offset (void)
  127. {
  128. int offset = -1;
  129. MONO_THREAD_VAR_OFFSET (tls_appdomain, offset);
  130. /* __asm ("jmp 1f; .section writetext, \"awx\"; 1: movl $tls_appdomain@ntpoff, %0; jmp 2f; .previous; 2:"
  131. : "=r" (offset));*/
  132. return offset;
  133. }
  134. #define JIT_INFO_TABLE_FILL_RATIO_NOM 3
  135. #define JIT_INFO_TABLE_FILL_RATIO_DENOM 4
  136. #define JIT_INFO_TABLE_FILLED_NUM_ELEMENTS (MONO_JIT_INFO_TABLE_CHUNK_SIZE * JIT_INFO_TABLE_FILL_RATIO_NOM / JIT_INFO_TABLE_FILL_RATIO_DENOM)
  137. #define JIT_INFO_TABLE_LOW_WATERMARK(n) ((n) / 2)
  138. #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6)
  139. #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL)
  140. #define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == JIT_INFO_TOMBSTONE_MARKER)
  141. #define JIT_INFO_TABLE_HAZARD_INDEX 0
  142. #define JIT_INFO_HAZARD_INDEX 1
  143. static int
  144. jit_info_table_num_elements (MonoJitInfoTable *table)
  145. {
  146. int i;
  147. int num_elements = 0;
  148. for (i = 0; i < table->num_chunks; ++i) {
  149. MonoJitInfoTableChunk *chunk = table->chunks [i];
  150. int chunk_num_elements = chunk->num_elements;
  151. int j;
  152. for (j = 0; j < chunk_num_elements; ++j) {
  153. if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j]))
  154. ++num_elements;
  155. }
  156. }
  157. return num_elements;
  158. }
  159. static MonoJitInfoTableChunk*
  160. jit_info_table_new_chunk (void)
  161. {
  162. MonoJitInfoTableChunk *chunk = g_new0 (MonoJitInfoTableChunk, 1);
  163. chunk->refcount = 1;
  164. return chunk;
  165. }
  166. static MonoJitInfoTable *
  167. jit_info_table_new (MonoDomain *domain)
  168. {
  169. MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*));
  170. table->domain = domain;
  171. table->num_chunks = 1;
  172. table->chunks [0] = jit_info_table_new_chunk ();
  173. return table;
  174. }
  175. static void
  176. jit_info_table_free (MonoJitInfoTable *table)
  177. {
  178. int i;
  179. int num_chunks = table->num_chunks;
  180. MonoDomain *domain = table->domain;
  181. mono_domain_lock (domain);
  182. table->domain->num_jit_info_tables--;
  183. if (table->domain->num_jit_info_tables <= 1) {
  184. GSList *list;
  185. for (list = table->domain->jit_info_free_queue; list; list = list->next)
  186. g_free (list->data);
  187. g_slist_free (table->domain->jit_info_free_queue);
  188. table->domain->jit_info_free_queue = NULL;
  189. }
  190. /* At this point we assume that there are no other threads
  191. still accessing the table, so we don't have to worry about
  192. hazardous pointers. */
  193. for (i = 0; i < num_chunks; ++i) {
  194. MonoJitInfoTableChunk *chunk = table->chunks [i];
  195. int num_elements;
  196. int j;
  197. if (--chunk->refcount > 0)
  198. continue;
  199. num_elements = chunk->num_elements;
  200. for (j = 0; j < num_elements; ++j) {
  201. MonoJitInfo *ji = chunk->data [j];
  202. if (IS_JIT_INFO_TOMBSTONE (ji))
  203. g_free (ji);
  204. }
  205. g_free (chunk);
  206. }
  207. mono_domain_unlock (domain);
  208. g_free (table);
  209. }
  210. /* The jit_info_table is sorted in ascending order by the end
  211. * addresses of the compiled methods. The reason why we have to do
  212. * this is that once we introduce tombstones, it becomes possible for
  213. * code ranges to overlap, and if we sort by code start and insert at
  214. * the back of the table, we cannot guarantee that we won't overlook
  215. * an entry.
  216. *
  217. * There are actually two possible ways to do the sorting and
  218. * inserting which work with our lock-free mechanism:
  219. *
  220. * 1. Sort by start address and insert at the front. When looking for
  221. * an entry, find the last one with a start address lower than the one
  222. * you're looking for, then work your way to the front of the table.
  223. *
  224. * 2. Sort by end address and insert at the back. When looking for an
  225. * entry, find the first one with an end address higher than the one
  226. * you're looking for, then work your way to the end of the table.
  227. *
  228. * We chose the latter out of convenience.
  229. */
  230. static int
  231. jit_info_table_index (MonoJitInfoTable *table, gint8 *addr)
  232. {
  233. int left = 0, right = table->num_chunks;
  234. g_assert (left < right);
  235. do {
  236. int pos = (left + right) / 2;
  237. MonoJitInfoTableChunk *chunk = table->chunks [pos];
  238. if (addr < chunk->last_code_end)
  239. right = pos;
  240. else
  241. left = pos + 1;
  242. } while (left < right);
  243. g_assert (left == right);
  244. if (left >= table->num_chunks)
  245. return table->num_chunks - 1;
  246. return left;
  247. }
  248. static int
  249. jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointers *hp, gint8 *addr)
  250. {
  251. int left = 0, right = chunk->num_elements;
  252. while (left < right) {
  253. int pos = (left + right) / 2;
  254. MonoJitInfo *ji = get_hazardous_pointer((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
  255. gint8 *code_end = (gint8*)ji->code_start + ji->code_size;
  256. if (addr < code_end)
  257. right = pos;
  258. else
  259. left = pos + 1;
  260. }
  261. g_assert (left == right);
  262. return left;
  263. }
  264. MonoJitInfo*
  265. mono_jit_info_table_find (MonoDomain *domain, char *addr)
  266. {
  267. MonoJitInfoTable *table;
  268. MonoJitInfo *ji;
  269. int chunk_pos, pos;
  270. MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
  271. MonoImage *image;
  272. ++mono_stats.jit_info_table_lookup_count;
  273. /* First we have to get the domain's jit_info_table. This is
  274. complicated by the fact that a writer might substitute a
  275. new table and free the old one. What the writer guarantees
  276. us is that it looks at the hazard pointers after it has
  277. changed the jit_info_table pointer. So, if we guard the
  278. table by a hazard pointer and make sure that the pointer is
  279. still there after we've made it hazardous, we don't have to
  280. worry about the writer freeing the table. */
  281. table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX);
  282. chunk_pos = jit_info_table_index (table, (gint8*)addr);
  283. g_assert (chunk_pos < table->num_chunks);
  284. pos = jit_info_table_chunk_index (table->chunks [chunk_pos], hp, (gint8*)addr);
  285. /* We now have a position that's very close to that of the
  286. first element whose end address is higher than the one
  287. we're looking for. If we don't have the exact position,
  288. then we have a position below that one, so we'll just
  289. search upward until we find our element. */
  290. do {
  291. MonoJitInfoTableChunk *chunk = table->chunks [chunk_pos];
  292. while (pos < chunk->num_elements) {
  293. ji = get_hazardous_pointer ((gpointer volatile*)&chunk->data [pos], hp, JIT_INFO_HAZARD_INDEX);
  294. ++pos;
  295. if (IS_JIT_INFO_TOMBSTONE (ji)) {
  296. mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
  297. continue;
  298. }
  299. if ((gint8*)addr >= (gint8*)ji->code_start
  300. && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) {
  301. mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
  302. mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
  303. return ji;
  304. }
  305. /* If we find a non-tombstone element which is already
  306. beyond what we're looking for, we have to end the
  307. search. */
  308. if ((gint8*)addr < (gint8*)ji->code_start)
  309. goto not_found;
  310. }
  311. ++chunk_pos;
  312. pos = 0;
  313. } while (chunk_pos < table->num_chunks);
  314. not_found:
  315. if (!hp)
  316. return NULL;
  317. mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX);
  318. mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX);
  319. ji = NULL;
  320. /* Maybe its an AOT module */
  321. image = mono_jit_info_find_aot_module ((guint8*)addr);
  322. if (image)
  323. ji = jit_info_find_in_aot_func (domain, image, addr);
  324. return ji;
  325. }
  326. static G_GNUC_UNUSED void
  327. jit_info_table_check (MonoJitInfoTable *table)
  328. {
  329. int i;
  330. for (i = 0; i < table->num_chunks; ++i) {
  331. MonoJitInfoTableChunk *chunk = table->chunks [i];
  332. int j;
  333. g_assert (chunk->refcount > 0 /* && chunk->refcount <= 8 */);
  334. if (chunk->refcount > 10)
  335. printf("warning: chunk refcount is %d\n", chunk->refcount);
  336. g_assert (chunk->num_elements <= MONO_JIT_INFO_TABLE_CHUNK_SIZE);
  337. for (j = 0; j < chunk->num_elements; ++j) {
  338. MonoJitInfo *this = chunk->data [j];
  339. MonoJitInfo *next;
  340. g_assert ((gint8*)this->code_start + this->code_size <= chunk->last_code_end);
  341. if (j < chunk->num_elements - 1)
  342. next = chunk->data [j + 1];
  343. else if (i < table->num_chunks - 1) {
  344. int k;
  345. for (k = i + 1; k < table->num_chunks; ++k)
  346. if (table->chunks [k]->num_elements > 0)
  347. break;
  348. if (k >= table->num_chunks)
  349. return;
  350. g_assert (table->chunks [k]->num_elements > 0);
  351. next = table->chunks [k]->data [0];
  352. } else
  353. return;
  354. g_assert ((gint8*)this->code_start + this->code_size <= (gint8*)next->code_start + next->code_size);
  355. }
  356. }
  357. }
  358. static MonoJitInfoTable*
  359. jit_info_table_realloc (MonoJitInfoTable *old)
  360. {
  361. int i;
  362. int num_elements = jit_info_table_num_elements (old);
  363. int required_size;
  364. int num_chunks;
  365. int new_chunk, new_element;
  366. MonoJitInfoTable *new;
  367. /* number of needed places for elements needed */
  368. required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM);
  369. num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE;
  370. if (num_chunks == 0) {
  371. g_assert (num_elements == 0);
  372. return jit_info_table_new (old->domain);
  373. }
  374. g_assert (num_chunks > 0);
  375. new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks);
  376. new->domain = old->domain;
  377. new->num_chunks = num_chunks;
  378. for (i = 0; i < num_chunks; ++i)
  379. new->chunks [i] = jit_info_table_new_chunk ();
  380. new_chunk = 0;
  381. new_element = 0;
  382. for (i = 0; i < old->num_chunks; ++i) {
  383. MonoJitInfoTableChunk *chunk = old->chunks [i];
  384. int chunk_num_elements = chunk->num_elements;
  385. int j;
  386. for (j = 0; j < chunk_num_elements; ++j) {
  387. if (!IS_JIT_INFO_TOMBSTONE (chunk->data [j])) {
  388. g_assert (new_chunk < num_chunks);
  389. new->chunks [new_chunk]->data [new_element] = chunk->data [j];
  390. if (++new_element >= JIT_INFO_TABLE_FILLED_NUM_ELEMENTS) {
  391. new->chunks [new_chunk]->num_elements = new_element;
  392. ++new_chunk;
  393. new_element = 0;
  394. }
  395. }
  396. }
  397. }
  398. if (new_chunk < num_chunks) {
  399. g_assert (new_chunk == num_chunks - 1);
  400. new->chunks [new_chunk]->num_elements = new_element;
  401. g_assert (new->chunks [new_chunk]->num_elements > 0);
  402. }
  403. for (i = 0; i < num_chunks; ++i) {
  404. MonoJitInfoTableChunk *chunk = new->chunks [i];
  405. MonoJitInfo *ji = chunk->data [chunk->num_elements - 1];
  406. new->chunks [i]->last_code_end = (gint8*)ji->code_start + ji->code_size;
  407. }
  408. return new;
  409. }
  410. static void
  411. jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk **new1p, MonoJitInfoTableChunk **new2p)
  412. {
  413. MonoJitInfoTableChunk *new1 = jit_info_table_new_chunk ();
  414. MonoJitInfoTableChunk *new2 = jit_info_table_new_chunk ();
  415. g_assert (chunk->num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE);
  416. new1->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE / 2;
  417. new2->num_elements = MONO_JIT_INFO_TABLE_CHUNK_SIZE - new1->num_elements;
  418. memcpy ((void*)new1->data, (void*)chunk->data, sizeof (MonoJitInfo*) * new1->num_elements);
  419. memcpy ((void*)new2->data, (void*)(chunk->data + new1->num_elements), sizeof (MonoJitInfo*) * new2->num_elements);
  420. new1->last_code_end = (gint8*)new1->data [new1->num_elements - 1]->code_start
  421. + new1->data [new1->num_elements - 1]->code_size;
  422. new2->last_code_end = (gint8*)new2->data [new2->num_elements - 1]->code_start
  423. + new2->data [new2->num_elements - 1]->code_size;
  424. *new1p = new1;
  425. *new2p = new2;
  426. }
  427. static MonoJitInfoTable*
  428. jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
  429. {
  430. MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
  431. + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1));
  432. int i, j;
  433. new_table->domain = table->domain;
  434. new_table->num_chunks = table->num_chunks + 1;
  435. j = 0;
  436. for (i = 0; i < table->num_chunks; ++i) {
  437. if (table->chunks [i] == chunk) {
  438. jit_info_table_split_chunk (chunk, &new_table->chunks [j], &new_table->chunks [j + 1]);
  439. j += 2;
  440. } else {
  441. new_table->chunks [j] = table->chunks [i];
  442. ++new_table->chunks [j]->refcount;
  443. ++j;
  444. }
  445. }
  446. g_assert (j == new_table->num_chunks);
  447. return new_table;
  448. }
  449. static MonoJitInfoTableChunk*
  450. jit_info_table_purify_chunk (MonoJitInfoTableChunk *old)
  451. {
  452. MonoJitInfoTableChunk *new = jit_info_table_new_chunk ();
  453. int i, j;
  454. j = 0;
  455. for (i = 0; i < old->num_elements; ++i) {
  456. if (!IS_JIT_INFO_TOMBSTONE (old->data [i]))
  457. new->data [j++] = old->data [i];
  458. }
  459. new->num_elements = j;
  460. if (new->num_elements > 0)
  461. new->last_code_end = (gint8*)new->data [j - 1]->code_start + new->data [j - 1]->code_size;
  462. else
  463. new->last_code_end = old->last_code_end;
  464. return new;
  465. }
  466. static MonoJitInfoTable*
  467. jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
  468. {
  469. MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE
  470. + sizeof (MonoJitInfoTableChunk*) * table->num_chunks);
  471. int i, j;
  472. new_table->domain = table->domain;
  473. new_table->num_chunks = table->num_chunks;
  474. j = 0;
  475. for (i = 0; i < table->num_chunks; ++i) {
  476. if (table->chunks [i] == chunk)
  477. new_table->chunks [j++] = jit_info_table_purify_chunk (table->chunks [i]);
  478. else {
  479. new_table->chunks [j] = table->chunks [i];
  480. ++new_table->chunks [j]->refcount;
  481. ++j;
  482. }
  483. }
  484. g_assert (j == new_table->num_chunks);
  485. return new_table;
  486. }
  487. /* As we add an element to the table the case can arise that the chunk
  488. * to which we need to add is already full. In that case we have to
  489. * allocate a new table and do something about that chunk. We have
  490. * several strategies:
  491. *
  492. * If the number of elements in the table is below the low watermark
  493. * or above the high watermark, we reallocate the whole table.
  494. * Otherwise we only concern ourselves with the overflowing chunk:
  495. *
  496. * If there are no tombstones in the chunk then we split the chunk in
  497. * two, each half full.
  498. *
  499. * If the chunk does contain tombstones, we just make a new copy of
  500. * the chunk without the tombstones, which will have room for at least
  501. * the one element we have to add.
  502. */
  503. static MonoJitInfoTable*
  504. jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk)
  505. {
  506. int num_elements = jit_info_table_num_elements (table);
  507. int i;
  508. if (num_elements < JIT_INFO_TABLE_LOW_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)
  509. || num_elements > JIT_INFO_TABLE_HIGH_WATERMARK (table->num_chunks * MONO_JIT_INFO_TABLE_CHUNK_SIZE)) {
  510. //printf ("reallocing table\n");
  511. return jit_info_table_realloc (table);
  512. }
  513. /* count the number of non-tombstone elements in the chunk */
  514. num_elements = 0;
  515. for (i = 0; i < chunk->num_elements; ++i) {
  516. if (!IS_JIT_INFO_TOMBSTONE (chunk->data [i]))
  517. ++num_elements;
  518. }
  519. if (num_elements == MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
  520. //printf ("splitting chunk\n");
  521. return jit_info_table_copy_and_split_chunk (table, chunk);
  522. }
  523. //printf ("purifying chunk\n");
  524. return jit_info_table_copy_and_purify_chunk (table, chunk);
  525. }
  526. /* We add elements to the table by first making space for them by
  527. * shifting the elements at the back to the right, one at a time.
  528. * This results in duplicate entries during the process, but during
  529. * all the time the table is in a sorted state. Also, when an element
  530. * is replaced by another one, the element that replaces it has an end
  531. * address that is equal to or lower than that of the replaced
  532. * element. That property is necessary to guarantee that when
  533. * searching for an element we end up at a position not higher than
  534. * the one we're looking for (i.e. we either find the element directly
  535. * or we end up to the left of it).
  536. */
  537. void
  538. mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
  539. {
  540. MonoJitInfoTable *table;
  541. int chunk_pos, pos;
  542. MonoJitInfoTableChunk *chunk;
  543. int num_elements;
  544. int i;
  545. g_assert (ji->method != NULL);
  546. mono_domain_lock (domain);
  547. ++mono_stats.jit_info_table_insert_count;
  548. table = domain->jit_info_table;
  549. restart:
  550. chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size);
  551. g_assert (chunk_pos < table->num_chunks);
  552. chunk = table->chunks [chunk_pos];
  553. if (chunk->num_elements >= MONO_JIT_INFO_TABLE_CHUNK_SIZE) {
  554. MonoJitInfoTable *new_table = jit_info_table_chunk_overflow (table, chunk);
  555. /* Debugging code, should be removed. */
  556. //jit_info_table_check (new_table);
  557. domain->jit_info_table = new_table;
  558. mono_memory_barrier ();
  559. domain->num_jit_info_tables++;
  560. mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free, TRUE, FALSE);
  561. table = new_table;
  562. goto restart;
  563. }
  564. /* Debugging code, should be removed. */
  565. //jit_info_table_check (table);
  566. num_elements = chunk->num_elements;
  567. pos = jit_info_table_chunk_index (chunk, NULL, (gint8*)ji->code_start + ji->code_size);
  568. /* First we need to size up the chunk by one, by copying the
  569. last item, or inserting the first one, if the table is
  570. empty. */
  571. if (num_elements > 0)
  572. chunk->data [num_elements] = chunk->data [num_elements - 1];
  573. else
  574. chunk->data [0] = ji;
  575. mono_memory_write_barrier ();
  576. chunk->num_elements = ++num_elements;
  577. /* Shift the elements up one by one. */
  578. for (i = num_elements - 2; i >= pos; --i) {
  579. mono_memory_write_barrier ();
  580. chunk->data [i + 1] = chunk->data [i];
  581. }
  582. /* Now we have room and can insert the new item. */
  583. mono_memory_write_barrier ();
  584. chunk->data [pos] = ji;
  585. /* Set the high code end address chunk entry. */
  586. chunk->last_code_end = (gint8*)chunk->data [chunk->num_elements - 1]->code_start
  587. + chunk->data [chunk->num_elements - 1]->code_size;
  588. /* Debugging code, should be removed. */
  589. //jit_info_table_check (table);
  590. mono_domain_unlock (domain);
  591. }
  592. static MonoJitInfo*
  593. mono_jit_info_make_tombstone (MonoJitInfo *ji)
  594. {
  595. MonoJitInfo *tombstone = g_new0 (MonoJitInfo, 1);
  596. tombstone->code_start = ji->code_start;
  597. tombstone->code_size = ji->code_size;
  598. tombstone->method = JIT_INFO_TOMBSTONE_MARKER;
  599. return tombstone;
  600. }
  601. /*
  602. * LOCKING: domain lock
  603. */
  604. static void
  605. mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
  606. {
  607. if (domain->num_jit_info_tables <= 1) {
  608. /* Can it actually happen that we only have one table
  609. but ji is still hazardous? */
  610. mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE);
  611. } else {
  612. domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
  613. }
  614. }
  615. void
  616. mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji)
  617. {
  618. MonoJitInfoTable *table;
  619. MonoJitInfoTableChunk *chunk;
  620. gpointer start = ji->code_start;
  621. int chunk_pos, pos;
  622. mono_domain_lock (domain);
  623. table = domain->jit_info_table;
  624. ++mono_stats.jit_info_table_remove_count;
  625. chunk_pos = jit_info_table_index (table, start);
  626. g_assert (chunk_pos < table->num_chunks);
  627. pos = jit_info_table_chunk_index (table->chunks [chunk_pos], NULL, start);
  628. do {
  629. chunk = table->chunks [chunk_pos];
  630. while (pos < chunk->num_elements) {
  631. if (chunk->data [pos] == ji)
  632. goto found;
  633. g_assert (IS_JIT_INFO_TOMBSTONE (chunk->data [pos]));
  634. g_assert ((guint8*)chunk->data [pos]->code_start + chunk->data [pos]->code_size
  635. <= (guint8*)ji->code_start + ji->code_size);
  636. ++pos;
  637. }
  638. ++chunk_pos;
  639. pos = 0;
  640. } while (chunk_pos < table->num_chunks);
  641. found:
  642. g_assert (chunk->data [pos] == ji);
  643. chunk->data [pos] = mono_jit_info_make_tombstone (ji);
  644. /* Debugging code, should be removed. */
  645. //jit_info_table_check (table);
  646. mono_jit_info_free_or_queue (domain, ji);
  647. mono_domain_unlock (domain);
  648. }
  649. static MonoAotModuleInfoTable*
  650. mono_aot_module_info_table_new (void)
  651. {
  652. return g_array_new (FALSE, FALSE, sizeof (gpointer));
  653. }
  654. static int
  655. aot_info_table_index (MonoAotModuleInfoTable *table, char *addr)
  656. {
  657. int left = 0, right = table->len;
  658. while (left < right) {
  659. int pos = (left + right) / 2;
  660. AotModuleInfo *ainfo = g_array_index (table, gpointer, pos);
  661. char *start = ainfo->start;
  662. char *end = ainfo->end;
  663. if (addr < start)
  664. right = pos;
  665. else if (addr >= end)
  666. left = pos + 1;
  667. else
  668. return pos;
  669. }
  670. return left;
  671. }
  672. void
  673. mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
  674. {
  675. AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1);
  676. int pos;
  677. ainfo->image = image;
  678. ainfo->start = start;
  679. ainfo->end = end;
  680. mono_appdomains_lock ();
  681. if (!aot_modules)
  682. aot_modules = mono_aot_module_info_table_new ();
  683. pos = aot_info_table_index (aot_modules, start);
  684. g_array_insert_val (aot_modules, pos, ainfo);
  685. mono_appdomains_unlock ();
  686. }
  687. static MonoImage*
  688. mono_jit_info_find_aot_module (guint8* addr)
  689. {
  690. guint left = 0, right;
  691. if (!aot_modules)
  692. return NULL;
  693. mono_appdomains_lock ();
  694. right = aot_modules->len;
  695. while (left < right) {
  696. guint pos = (left + right) / 2;
  697. AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos);
  698. if (addr < (guint8*)ai->start)
  699. right = pos;
  700. else if (addr >= (guint8*)ai->end)
  701. left = pos + 1;
  702. else {
  703. mono_appdomains_unlock ();
  704. return ai->image;
  705. }
  706. }
  707. mono_appdomains_unlock ();
  708. return NULL;
  709. }
  710. void
  711. mono_install_jit_info_find_in_aot (MonoJitInfoFindInAot func)
  712. {
  713. jit_info_find_in_aot_func = func;
  714. }
  715. gpointer
  716. mono_jit_info_get_code_start (MonoJitInfo* ji)
  717. {
  718. return ji->code_start;
  719. }
  720. int
  721. mono_jit_info_get_code_size (MonoJitInfo* ji)
  722. {
  723. return ji->code_size;
  724. }
  725. MonoMethod*
  726. mono_jit_info_get_method (MonoJitInfo* ji)
  727. {
  728. return ji->method;
  729. }
  730. static gpointer
  731. jit_info_key_extract (gpointer value)
  732. {
  733. MonoJitInfo *info = (MonoJitInfo*)value;
  734. return info->method;
  735. }
  736. static gpointer*
  737. jit_info_next_value (gpointer value)
  738. {
  739. MonoJitInfo *info = (MonoJitInfo*)value;
  740. return (gpointer*)&info->next_jit_code_hash;
  741. }
  742. void
  743. mono_jit_code_hash_init (MonoInternalHashTable *jit_code_hash)
  744. {
  745. mono_internal_hash_table_init (jit_code_hash,
  746. mono_aligned_addr_hash,
  747. jit_info_key_extract,
  748. jit_info_next_value);
  749. }
  750. MonoGenericJitInfo*
  751. mono_jit_info_get_generic_jit_info (MonoJitInfo *ji)
  752. {
  753. if (ji->has_generic_jit_info)
  754. return (MonoGenericJitInfo*)&ji->clauses [ji->num_clauses];
  755. else
  756. return NULL;
  757. }
  758. /*
  759. * mono_jit_info_get_generic_sharing_context:
  760. * @ji: a jit info
  761. *
  762. * Returns the jit info's generic sharing context, or NULL if it
  763. * doesn't have one.
  764. */
  765. MonoGenericSharingContext*
  766. mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji)
  767. {
  768. MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
  769. if (gi)
  770. return gi->generic_sharing_context;
  771. else
  772. return NULL;
  773. }
  774. /*
  775. * mono_jit_info_set_generic_sharing_context:
  776. * @ji: a jit info
  777. * @gsctx: a generic sharing context
  778. *
  779. * Sets the jit info's generic sharing context. The jit info must
  780. * have memory allocated for the context.
  781. */
  782. void
  783. mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingContext *gsctx)
  784. {
  785. MonoGenericJitInfo *gi = mono_jit_info_get_generic_jit_info (ji);
  786. g_assert (gi);
  787. gi->generic_sharing_context = gsctx;
  788. }
  789. MonoTryBlockHoleTableJitInfo*
  790. mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji)
  791. {
  792. if (ji->has_try_block_holes) {
  793. char *ptr = (char*)&ji->clauses [ji->num_clauses];
  794. if (ji->has_generic_jit_info)
  795. ptr += sizeof (MonoGenericJitInfo);
  796. return (MonoTryBlockHoleTableJitInfo*)ptr;
  797. } else {
  798. return NULL;
  799. }
  800. }
  801. MonoArchEHJitInfo*
  802. mono_jit_info_get_arch_eh_info (MonoJitInfo *ji)
  803. {
  804. if (ji->has_arch_eh_info) {
  805. char *ptr = (char*)&ji->clauses [ji->num_clauses];
  806. if (ji->has_generic_jit_info)
  807. ptr += sizeof (MonoGenericJitInfo);
  808. if (ji->has_try_block_holes)
  809. ptr += sizeof (MonoTryBlockHoleTableJitInfo);
  810. return (MonoArchEHJitInfo*)ptr;
  811. } else {
  812. return NULL;
  813. }
  814. }
  815. MonoMethodCasInfo*
  816. mono_jit_info_get_cas_info (MonoJitInfo *ji)
  817. {
  818. if (ji->has_cas_info) {
  819. char *ptr = (char*)&ji->clauses [ji->num_clauses];
  820. if (ji->has_generic_jit_info)
  821. ptr += sizeof (MonoGenericJitInfo);
  822. if (ji->has_try_block_holes)
  823. ptr += sizeof (MonoTryBlockHoleTableJitInfo);
  824. if (ji->has_arch_eh_info)
  825. ptr += sizeof (MonoArchEHJitInfo);
  826. return (MonoMethodCasInfo*)ptr;
  827. } else {
  828. return NULL;
  829. }
  830. }
  831. void
  832. mono_install_create_domain_hook (MonoCreateDomainFunc func)
  833. {
  834. create_domain_hook = func;
  835. }
  836. void
  837. mono_install_free_domain_hook (MonoFreeDomainFunc func)
  838. {
  839. free_domain_hook = func;
  840. }
  841. /**
  842. * mono_string_equal:
  843. * @s1: First string to compare
  844. * @s2: Second string to compare
  845. *
  846. * Returns FALSE if the strings differ.
  847. */
  848. gboolean
  849. mono_string_equal (MonoString *s1, MonoString *s2)
  850. {
  851. int l1 = mono_string_length (s1);
  852. int l2 = mono_string_length (s2);
  853. if (s1 == s2)
  854. return TRUE;
  855. if (l1 != l2)
  856. return FALSE;
  857. return memcmp (mono_string_chars (s1), mono_string_chars (s2), l1 * 2) == 0;
  858. }
  859. /**
  860. * mono_string_hash:
  861. * @s: the string to hash
  862. *
  863. * Returns the hash for the string.
  864. */
  865. guint
  866. mono_string_hash (MonoString *s)
  867. {
  868. const guint16 *p = mono_string_chars (s);
  869. int i, len = mono_string_length (s);
  870. guint h = 0;
  871. for (i = 0; i < len; i++) {
  872. h = (h << 5) - h + *p;
  873. p++;
  874. }
  875. return h;
  876. }
  877. static gboolean
  878. mono_ptrarray_equal (gpointer *s1, gpointer *s2)
  879. {
  880. int len = GPOINTER_TO_INT (s1 [0]);
  881. if (len != GPOINTER_TO_INT (s2 [0]))
  882. return FALSE;
  883. return memcmp (s1 + 1, s2 + 1, len * sizeof(gpointer)) == 0;
  884. }
  885. static guint
  886. mono_ptrarray_hash (gpointer *s)
  887. {
  888. int i;
  889. int len = GPOINTER_TO_INT (s [0]);
  890. guint hash = 0;
  891. for (i = 1; i < len; i++)
  892. hash += GPOINTER_TO_UINT (s [i]);
  893. return hash;
  894. }
  895. /*
  896. * Allocate an id for domain and set domain->domain_id.
  897. * LOCKING: must be called while holding appdomains_mutex.
  898. * We try to assign low numbers to the domain, so it can be used
  899. * as an index in data tables to lookup domain-specific info
  900. * with minimal memory overhead. We also try not to reuse the
  901. * same id too quickly (to help debugging).
  902. */
  903. static int
  904. domain_id_alloc (MonoDomain *domain)
  905. {
  906. int id = -1, i;
  907. if (!appdomains_list) {
  908. appdomain_list_size = 2;
  909. appdomains_list = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
  910. }
  911. for (i = appdomain_next; i < appdomain_list_size; ++i) {
  912. if (!appdomains_list [i]) {
  913. id = i;
  914. break;
  915. }
  916. }
  917. if (id == -1) {
  918. for (i = 0; i < appdomain_next; ++i) {
  919. if (!appdomains_list [i]) {
  920. id = i;
  921. break;
  922. }
  923. }
  924. }
  925. if (id == -1) {
  926. MonoDomain **new_list;
  927. int new_size = appdomain_list_size * 2;
  928. if (new_size >= (1 << 16))
  929. g_assert_not_reached ();
  930. id = appdomain_list_size;
  931. new_list = mono_gc_alloc_fixed (new_size * sizeof (void*), NULL);
  932. memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
  933. mono_gc_free_fixed (appdomains_list);
  934. appdomains_list = new_list;
  935. appdomain_list_size = new_size;
  936. }
  937. domain->domain_id = id;
  938. appdomains_list [id] = domain;
  939. appdomain_next++;
  940. if (appdomain_next > appdomain_list_size)
  941. appdomain_next = 0;
  942. return id;
  943. }
  944. static gsize domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1];
  945. static gpointer domain_gc_desc = NULL;
  946. static guint32 domain_shadow_serial = 0L;
  947. MonoDomain *
  948. mono_domain_create (void)
  949. {
  950. MonoDomain *domain;
  951. guint32 shadow_serial;
  952. mono_appdomains_lock ();
  953. shadow_serial = domain_shadow_serial++;
  954. if (!domain_gc_desc) {
  955. unsigned int i, bit = 0;
  956. for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) {
  957. bit = i / sizeof (gpointer);
  958. domain_gc_bitmap [bit / 32] |= (gsize) 1 << (bit % 32);
  959. }
  960. domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1);
  961. }
  962. mono_appdomains_unlock ();
  963. #ifdef HAVE_BOEHM_GC
  964. /*
  965. * Boehm doesn't like roots inside GC allocated objects, and alloc_fixed returns
  966. * a GC_MALLOC-ed object, contrary to the api docs. This causes random crashes when
  967. * running the corlib test suite.
  968. * To solve this, we pass a NULL descriptor, and don't register roots.
  969. */
  970. domain = mono_gc_alloc_fixed (sizeof (MonoDomain), NULL);
  971. #else
  972. domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc);
  973. mono_gc_register_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED), G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_LAST_GC_TRACKED) - G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED), NULL);
  974. #endif
  975. domain->shadow_serial = shadow_serial;
  976. domain->domain = NULL;
  977. domain->setup = NULL;
  978. domain->friendly_name = NULL;
  979. domain->search_path = NULL;
  980. mono_profiler_appdomain_event (domain, MONO_PROFILE_START_LOAD);
  981. domain->mp = mono_mempool_new ();
  982. domain->code_mp = mono_code_manager_new ();
  983. domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
  984. domain->domain_assemblies = NULL;
  985. domain->assembly_bindings = NULL;
  986. domain->assembly_bindings_parsed = FALSE;
  987. domain->class_vtable_array = g_ptr_array_new ();
  988. domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal);
  989. domain->static_data_array = NULL;
  990. mono_jit_code_hash_init (&domain->jit_code_hash);
  991. domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC);
  992. domain->num_jit_info_tables = 1;
  993. domain->jit_info_table = jit_info_table_new (domain);
  994. domain->jit_info_free_queue = NULL;
  995. domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
  996. domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
  997. InitializeCriticalSection (&domain->lock);
  998. InitializeCriticalSection (&domain->assemblies_lock);
  999. InitializeCriticalSection (&domain->jit_code_hash_lock);
  1000. InitializeCriticalSection (&domain->finalizable_objects_hash_lock);
  1001. domain->method_rgctx_hash = NULL;
  1002. mono_appdomains_lock ();
  1003. domain_id_alloc (domain);
  1004. mono_appdomains_unlock ();
  1005. #ifndef DISABLE_PERFCOUNTERS
  1006. mono_perfcounters->loader_appdomains++;
  1007. mono_perfcounters->loader_total_appdomains++;
  1008. #endif
  1009. mono_debug_domain_create (domain);
  1010. if (create_domain_hook)
  1011. create_domain_hook (domain);
  1012. mono_profiler_appdomain_loaded (domain, MONO_PROFILE_OK);
  1013. return domain;
  1014. }
  1015. /**
  1016. * mono_init_internal:
  1017. *
  1018. * Creates the initial application domain and initializes the mono_defaults
  1019. * structure.
  1020. * This function is guaranteed to not run any IL code.
  1021. * If exe_filename is not NULL, the method will determine the required runtime
  1022. * from the exe configuration file or the version PE field.
  1023. * If runtime_version is not NULL, that runtime version will be used.
  1024. * Either exe_filename or runtime_version must be provided.
  1025. *
  1026. * Returns: the initial domain.
  1027. */
  1028. static MonoDomain *
  1029. mono_init_internal (const char *filename, const char *exe_filename, const char *runtime_version)
  1030. {
  1031. static MonoDomain *domain = NULL;
  1032. MonoAssembly *ass = NULL;
  1033. MonoImageOpenStatus status = MONO_IMAGE_OK;
  1034. const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
  1035. int n;
  1036. if (domain)
  1037. g_assert_not_reached ();
  1038. #ifdef HOST_WIN32
  1039. /* Avoid system error message boxes. */
  1040. SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  1041. #endif
  1042. #ifndef HOST_WIN32
  1043. wapi_init ();
  1044. #endif
  1045. #ifndef DISABLE_PERFCOUNTERS
  1046. mono_perfcounters_init ();
  1047. #endif
  1048. mono_counters_register ("Max native code in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
  1049. mono_counters_register ("Max code space allocated in a domain", MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_alloc);
  1050. mono_counters_register ("Total code space allocated", MONO_COUNTER_INT|MONO_COUNTER_JIT, &total_domain_code_alloc);
  1051. mono_gc_base_init ();
  1052. MONO_FAST_TLS_INIT (tls_appdomain);
  1053. mono_native_tls_alloc (&appdomain_thread_id, NULL);
  1054. InitializeCriticalSection (&appdomains_mutex);
  1055. mono_metadata_init ();
  1056. mono_images_init ();
  1057. mono_assemblies_init ();
  1058. mono_classes_init ();
  1059. mono_loader_init ();
  1060. mono_reflection_init ();
  1061. /* FIXME: When should we release this memory? */
  1062. MONO_GC_REGISTER_ROOT_FIXED (appdomains_list);
  1063. domain = mono_domain_create ();
  1064. mono_root_domain = domain;
  1065. SET_APPDOMAIN (domain);
  1066. /* Get a list of runtimes supported by the exe */
  1067. if (exe_filename != NULL) {
  1068. /*
  1069. * This function will load the exe file as a MonoImage. We need to close it, but
  1070. * that would mean it would be reloaded later. So instead, we save it to
  1071. * exe_image, and close it during shutdown.
  1072. */
  1073. get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
  1074. #ifdef HOST_WIN32
  1075. if (!exe_image) {
  1076. exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE);
  1077. if (!exe_image)
  1078. exe_image = mono_image_open (exe_filename, NULL);
  1079. }
  1080. mono_fixup_exe_image (exe_image);
  1081. #endif
  1082. } else if (runtime_version != NULL) {
  1083. runtimes [0] = get_runtime_by_version (runtime_version);
  1084. runtimes [1] = NULL;
  1085. }
  1086. if (runtimes [0] == NULL) {
  1087. const MonoRuntimeInfo *default_runtime = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
  1088. runtimes [0] = default_runtime;
  1089. runtimes [1] = NULL;
  1090. g_print ("WARNING: The runtime version supported by this application is unavailable.\n");
  1091. g_print ("Using default runtime: %s\n", default_runtime->runtime_version);
  1092. }
  1093. /* The selected runtime will be the first one for which there is a mscrolib.dll */
  1094. for (n = 0; runtimes [n] != NULL && ass == NULL; n++) {
  1095. current_runtime = runtimes [n];
  1096. ass = mono_assembly_load_corlib (current_runtime, &status);
  1097. if (status != MONO_IMAGE_OK && status != MONO_IMAGE_ERROR_ERRNO)
  1098. break;
  1099. }
  1100. if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
  1101. switch (status){
  1102. case MONO_IMAGE_ERROR_ERRNO: {
  1103. char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
  1104. g_print ("The assembly mscorlib.dll was not found or could not be loaded.\n");
  1105. g_print ("It should have been installed in the `%s' directory.\n", corlib_file);
  1106. g_free (corlib_file);
  1107. break;
  1108. }
  1109. case MONO_IMAGE_IMAGE_INVALID:
  1110. g_print ("The file %s/mscorlib.dll is an invalid CIL image\n",
  1111. mono_assembly_getrootdir ());
  1112. break;
  1113. case MONO_IMAGE_MISSING_ASSEMBLYREF:
  1114. g_print ("Missing assembly reference in %s/mscorlib.dll\n",
  1115. mono_assembly_getrootdir ());
  1116. break;
  1117. case MONO_IMAGE_OK:
  1118. /* to suppress compiler warning */
  1119. break;
  1120. }
  1121. exit (1);
  1122. }
  1123. mono_defaults.corlib = mono_assembly_get_image (ass);
  1124. mono_defaults.object_class = mono_class_from_name (
  1125. mono_defaults.corlib, "System", "Object");
  1126. g_assert (mono_defaults.object_class != 0);
  1127. mono_defaults.void_class = mono_class_from_name (
  1128. mono_defaults.corlib, "System", "Void");
  1129. g_assert (mono_defaults.void_class != 0);
  1130. mono_defaults.boolean_class = mono_class_from_name (
  1131. mono_defaults.corlib, "System", "Boolean");
  1132. g_assert (mono_defaults.boolean_class != 0);
  1133. mono_defaults.byte_class = mono_class_from_name (
  1134. mono_defaults.corlib, "System", "Byte");
  1135. g_assert (mono_defaults.byte_class != 0);
  1136. mono_defaults.sbyte_class = mono_class_from_name (
  1137. mono_defaults.corlib, "System", "SByte");
  1138. g_assert (mono_defaults.sbyte_class != 0);
  1139. mono_defaults.int16_class = mono_class_from_name (
  1140. mono_defaults.corlib, "System", "Int16");
  1141. g_assert (mono_defaults.int16_class != 0);
  1142. mono_defaults.uint16_class = mono_class_from_name (
  1143. mono_defaults.corlib, "System", "UInt16");
  1144. g_assert (mono_defaults.uint16_class != 0);
  1145. mono_defaults.int32_class = mono_class_from_name (
  1146. mono_defaults.corlib, "System", "Int32");
  1147. g_assert (mono_defaults.int32_class != 0);
  1148. mono_defaults.uint32_class = mono_class_from_name (
  1149. mono_defaults.corlib, "System", "UInt32");
  1150. g_assert (mono_defaults.uint32_class != 0);
  1151. mono_defaults.uint_class = mono_class_from_name (
  1152. mono_defaults.corlib, "System", "UIntPtr");
  1153. g_assert (mono_defaults.uint_class != 0);
  1154. mono_defaults.int_class = mono_class_from_name (
  1155. mono_defaults.corlib, "System", "IntPtr");
  1156. g_assert (mono_defaults.int_class != 0);
  1157. mono_defaults.int64_class = mono_class_from_name (
  1158. mono_defaults.corlib, "System", "Int64");
  1159. g_assert (mono_defaults.int64_class != 0);
  1160. mono_defaults.uint64_class = mono_class_from_name (
  1161. mono_defaults.corlib, "System", "UInt64");
  1162. g_assert (mono_defaults.uint64_class != 0);
  1163. mono_defaults.single_class = mono_class_from_name (
  1164. mono_defaults.corlib, "System", "Single");
  1165. g_assert (mono_defaults.single_class != 0);
  1166. mono_defaults.double_class = mono_class_from_name (
  1167. mono_defaults.corlib, "System", "Double");
  1168. g_assert (mono_defaults.double_class != 0);
  1169. mono_defaults.char_class = mono_class_from_name (
  1170. mono_defaults.corlib, "System", "Char");
  1171. g_assert (mono_defaults.char_class != 0);
  1172. mono_defaults.string_class = mono_class_from_name (
  1173. mono_defaults.corlib, "System", "String");
  1174. g_assert (mono_defaults.string_class != 0);
  1175. mono_defaults.enum_class = mono_class_from_name (
  1176. mono_defaults.corlib, "System", "Enum");
  1177. g_assert (mono_defaults.enum_class != 0);
  1178. mono_defaults.array_class = mono_class_from_name (
  1179. mono_defaults.corlib, "System", "Array");
  1180. g_assert (mono_defaults.array_class != 0);
  1181. mono_defaults.delegate_class = mono_class_from_name (
  1182. mono_defaults.corlib, "System", "Delegate");
  1183. g_assert (mono_defaults.delegate_class != 0 );
  1184. mono_defaults.multicastdelegate_class = mono_class_from_name (
  1185. mono_defaults.corlib, "System", "MulticastDelegate");
  1186. g_assert (mono_defaults.multicastdelegate_class != 0 );
  1187. mono_defaults.asyncresult_class = mono_class_from_name (
  1188. mono_defaults.corlib, "System.Runtime.Remoting.Messaging",
  1189. "AsyncResult");
  1190. g_assert (mono_defaults.asyncresult_class != 0 );
  1191. mono_defaults.manualresetevent_class = mono_class_from_name (
  1192. mono_defaults.corlib, "System.Threading", "ManualResetEvent");
  1193. g_assert (mono_defaults.manualresetevent_class != 0 );
  1194. mono_defaults.typehandle_class = mono_class_from_name (
  1195. mono_defaults.corlib, "System", "RuntimeTypeHandle");
  1196. g_assert (mono_defaults.typehandle_class != 0);
  1197. mono_defaults.methodhandle_class = mono_class_from_name (
  1198. mono_defaults.corlib, "System", "RuntimeMethodHandle");
  1199. g_assert (mono_defaults.methodhandle_class != 0);
  1200. mono_defaults.fieldhandle_class = mono_class_from_name (
  1201. mono_defaults.corlib, "System", "RuntimeFieldHandle");
  1202. g_assert (mono_defaults.fieldhandle_class != 0);
  1203. mono_defaults.systemtype_class = mono_class_from_name (
  1204. mono_defaults.corlib, "System", "Type");
  1205. g_assert (mono_defaults.systemtype_class != 0);
  1206. mono_defaults.monotype_class = mono_class_from_name (
  1207. mono_defaults.corlib, "System", "MonoType");
  1208. g_assert (mono_defaults.monotype_class != 0);
  1209. mono_defaults.exception_class = mono_class_from_name (
  1210. mono_defaults.corlib, "System", "Exception");
  1211. g_assert (mono_defaults.exception_class != 0);
  1212. mono_defaults.threadabortexception_class = mono_class_from_name (
  1213. mono_defaults.corlib, "System.Threading", "ThreadAbortException");
  1214. g_assert (mono_defaults.threadabortexception_class != 0);
  1215. mono_defaults.thread_class = mono_class_from_name (
  1216. mono_defaults.corlib, "System.Threading", "Thread");
  1217. g_assert (mono_defaults.thread_class != 0);
  1218. mono_defaults.internal_thread_class = mono_class_from_name (
  1219. mono_defaults.corlib, "System.Threading", "InternalThread");
  1220. if (!mono_defaults.internal_thread_class) {
  1221. /* This can happen with an old mscorlib */
  1222. fprintf (stderr, "Corlib too old for this runtime.\n");
  1223. fprintf (stderr, "Loaded from: %s\n",
  1224. mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown");
  1225. exit (1);
  1226. }
  1227. mono_defaults.appdomain_class = mono_class_from_name (
  1228. mono_defaults.corlib, "System", "AppDomain");
  1229. g_assert (mono_defaults.appdomain_class != 0);
  1230. #ifndef DISABLE_REMOTING
  1231. mono_defaults.transparent_proxy_class = mono_class_from_name (
  1232. mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy");
  1233. g_assert (mono_defaults.transparent_proxy_class != 0);
  1234. mono_defaults.real_proxy_class = mono_class_from_name (
  1235. mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy");
  1236. g_assert (mono_defaults.real_proxy_class != 0);
  1237. mono_defaults.marshalbyrefobject_class = mono_class_from_name (
  1238. mono_defaults.corlib, "System", "MarshalByRefObject");
  1239. g_assert (mono_defaults.marshalbyrefobject_class != 0);
  1240. mono_defaults.iremotingtypeinfo_class = mono_class_from_name (
  1241. mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo");
  1242. g_assert (mono_defaults.iremotingtypeinfo_class != 0);
  1243. #endif
  1244. mono_defaults.mono_method_message_class = mono_class_from_name (
  1245. mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage");
  1246. g_assert (mono_defaults.mono_method_message_class != 0);
  1247. mono_defaults.field_info_class = mono_class_from_name (
  1248. mono_defaults.corlib, "System.Reflection", "FieldInfo");
  1249. g_assert (mono_defaults.field_info_class != 0);
  1250. mono_defaults.method_info_class = mono_class_from_name (
  1251. mono_defaults.corlib, "System.Reflection", "MethodInfo");
  1252. g_assert (mono_defaults.method_info_class != 0);
  1253. mono_defaults.stringbuilder_class = mono_class_from_name (
  1254. mono_defaults.corlib, "System.Text", "StringBuilder");
  1255. g_assert (mono_defaults.stringbuilder_class != 0);
  1256. mono_defaults.math_class = mono_class_from_name (
  1257. mono_defaults.corlib, "System", "Math");
  1258. g_assert (mono_defaults.math_class != 0);
  1259. mono_defaults.stack_frame_class = mono_class_from_name (
  1260. mono_defaults.corlib, "System.Diagnostics", "StackFrame");
  1261. g_assert (mono_defaults.stack_frame_class != 0);
  1262. mono_defaults.stack_trace_class = mono_class_from_name (
  1263. mono_defaults.corlib, "System.Diagnostics", "StackTrace");
  1264. g_assert (mono_defaults.stack_trace_class != 0);
  1265. mono_defaults.marshal_class = mono_class_from_name (
  1266. mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal");
  1267. g_assert (mono_defaults.marshal_class != 0);
  1268. mono_defaults.typed_reference_class = mono_class_from_name (
  1269. mono_defaults.corlib, "System", "TypedReference");
  1270. g_assert (mono_defaults.typed_reference_class != 0);
  1271. mono_defaults.argumenthandle_class = mono_class_from_name (
  1272. mono_defaults.corlib, "System", "RuntimeArgumentHandle");
  1273. g_assert (mono_defaults.argumenthandle_class != 0);
  1274. mono_defaults.monitor_class = mono_class_from_name (
  1275. mono_defaults.corlib, "System.Threading", "Monitor");
  1276. g_assert (mono_defaults.monitor_class != 0);
  1277. mono_defaults.runtimesecurityframe_class = mono_class_from_name (
  1278. mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame");
  1279. mono_defaults.executioncontext_class = mono_class_from_name (
  1280. mono_defaults.corlib, "System.Threading", "ExecutionContext");
  1281. mono_defaults.internals_visible_class = mono_class_from_name (
  1282. mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
  1283. mono_defaults.critical_finalizer_object = mono_class_from_name (
  1284. mono_defaults.corlib, "System.Runtime.ConstrainedExecution", "CriticalFinalizerObject");
  1285. /*
  1286. * mscorlib needs a little help, only now it can load its friends list (after we have
  1287. * loaded the InternalsVisibleToAttribute), load it now
  1288. */
  1289. mono_assembly_load_friends (ass);
  1290. mono_defaults.safehandle_class = mono_class_from_name (
  1291. mono_defaults.corlib, "System.Runtime.InteropServices", "SafeHandle");
  1292. mono_defaults.handleref_class = mono_class_from_name (
  1293. mono_defaults.corlib, "System.Runtime.InteropServices", "HandleRef");
  1294. mono_defaults.attribute_class = mono_class_from_name (
  1295. mono_defaults.corlib, "System", "Attribute");
  1296. mono_defaults.customattribute_data_class = mono_class_from_name (
  1297. mono_defaults.corlib, "System.Reflection", "CustomAttributeData");
  1298. /* these are initialized lazily when COM features are used */
  1299. #ifndef DISABLE_COM
  1300. mono_defaults.variant_class = NULL;
  1301. mono_defaults.com_object_class = NULL;
  1302. mono_defaults.com_interop_proxy_class = NULL;
  1303. mono_defaults.iunknown_class = NULL;
  1304. mono_defaults.idispatch_class = NULL;
  1305. #endif
  1306. mono_class_init (mono_defaults.array_class);
  1307. mono_defaults.generic_nullable_class = mono_class_from_name (
  1308. mono_defaults.corlib, "System", "Nullable`1");
  1309. mono_defaults.generic_ilist_class = mono_class_from_name (
  1310. mono_defaults.corlib, "System.Collections.Generic", "IList`1");
  1311. mono_defaults.generic_ireadonlylist_class = mono_class_from_name (
  1312. mono_defaults.corlib, "System.Collections.Generic", "IReadOnlyList`1");
  1313. domain->friendly_name = g_path_get_basename (filename);
  1314. _mono_debug_init_corlib (domain);
  1315. return domain;
  1316. }
  1317. /**
  1318. * mono_init:
  1319. *
  1320. * Creates the initial application domain and initializes the mono_defaults
  1321. * structure.
  1322. * This function is guaranteed to not run any IL code.
  1323. * The runtime is initialized using the default runtime version.
  1324. *
  1325. * Returns: the initial domain.
  1326. */
  1327. MonoDomain *
  1328. mono_init (const char *domain_name)
  1329. {
  1330. return mono_init_internal (domain_name, NULL, DEFAULT_RUNTIME_VERSION);
  1331. }
  1332. /**
  1333. * mono_init_from_assembly:
  1334. * @domain_name: name to give to the initial domain
  1335. * @filename: filename to load on startup
  1336. *
  1337. * Used by the runtime, users should use mono_jit_init instead.
  1338. *
  1339. * Creates the initial application domain and initializes the mono_defaults
  1340. * structure.
  1341. * This function is guaranteed to not run any IL code.
  1342. * The runtime is initialized using the runtime version required by the
  1343. * provided executable. The version is determined by looking at the exe
  1344. * configuration file and the version PE field)
  1345. *
  1346. * Returns: the initial domain.
  1347. */
  1348. MonoDomain *
  1349. mono_init_from_assembly (const char *domain_name, const char *filename)
  1350. {
  1351. return mono_init_internal (domain_name, filename, NULL);
  1352. }
  1353. /**
  1354. * mono_init_version:
  1355. *
  1356. * Used by the runtime, users should use mono_jit_init instead.
  1357. *
  1358. * Creates the initial application domain and initializes the mono_defaults
  1359. * structure.
  1360. *
  1361. * This function is guaranteed to not run any IL code.
  1362. * The runtime is initialized using the provided rutime version.
  1363. *
  1364. * Returns: the initial domain.
  1365. */
  1366. MonoDomain *
  1367. mono_init_version (const char *domain_name, const char *version)
  1368. {
  1369. return mono_init_internal (domain_name, NULL, version);
  1370. }
  1371. #ifndef DISABLE_COM
  1372. /**
  1373. * mono_init_com_types:
  1374. *
  1375. * Initializes all types needed for COM Interop in mono_defaults structure.
  1376. */
  1377. void
  1378. mono_init_com_types (void)
  1379. {
  1380. static gboolean initialized = FALSE;
  1381. if (initialized)
  1382. return;
  1383. /* FIXME: do I need some threading protection here */
  1384. g_assert (mono_defaults.corlib);
  1385. mono_defaults.variant_class = mono_class_from_name (
  1386. mono_defaults.corlib, "System", "Variant");
  1387. g_assert (mono_defaults.variant_class != 0);
  1388. mono_defaults.com_object_class = mono_class_from_name (
  1389. mono_defaults.corlib, "System", "__ComObject");
  1390. g_assert (mono_defaults.com_object_class != 0);
  1391. mono_defaults.com_interop_proxy_class = mono_class_from_name (
  1392. mono_defaults.corlib, "Mono.Interop", "ComInteropProxy");
  1393. g_assert (mono_defaults.com_interop_proxy_class != 0);
  1394. mono_defaults.iunknown_class = mono_class_from_name (
  1395. mono_defaults.corlib, "Mono.Interop", "IUnknown");
  1396. g_assert (mono_defaults.iunknown_class != 0);
  1397. mono_defaults.idispatch_class = mono_class_from_name (
  1398. mono_defaults.corlib, "Mono.Interop", "IDispatch");
  1399. g_assert (mono_defaults.idispatch_class != 0);
  1400. initialized = TRUE;
  1401. }
  1402. #endif /*DISABLE_COM*/
  1403. /**
  1404. * mono_cleanup:
  1405. *
  1406. * Cleans up all metadata modules.
  1407. */
  1408. void
  1409. mono_cleanup (void)
  1410. {
  1411. mono_close_exe_image ();
  1412. mono_defaults.corlib = NULL;
  1413. mono_config_cleanup ();
  1414. mono_loader_cleanup ();
  1415. mono_classes_cleanup ();
  1416. mono_assemblies_cleanup ();
  1417. mono_images_cleanup ();
  1418. mono_debug_cleanup ();
  1419. mono_metadata_cleanup ();
  1420. mono_native_tls_free (appdomain_thread_id);
  1421. DeleteCriticalSection (&appdomains_mutex);
  1422. #ifndef HOST_WIN32
  1423. wapi_cleanup ();
  1424. #endif
  1425. }
  1426. void
  1427. mono_close_exe_image (void)
  1428. {
  1429. if (exe_image)
  1430. mono_image_close (exe_image);
  1431. }
  1432. /**
  1433. * mono_get_root_domain:
  1434. *
  1435. * The root AppDomain is the initial domain created by the runtime when it is
  1436. * initialized. Programs execute on this AppDomain, but can create new ones
  1437. * later. Currently there is no unmanaged API to create new AppDomains, this
  1438. * must be done from managed code.
  1439. *
  1440. * Returns: the root appdomain, to obtain the current domain, use mono_domain_get ()
  1441. */
  1442. MonoDomain*
  1443. mono_get_root_domain (void)
  1444. {
  1445. return mono_root_domain;
  1446. }
  1447. /**
  1448. * mono_domain_get:
  1449. *
  1450. * Returns: the current domain, to obtain the root domain use
  1451. * mono_get_root_domain().
  1452. */
  1453. MonoDomain *
  1454. mono_domain_get ()
  1455. {
  1456. return GET_APPDOMAIN ();
  1457. }
  1458. void
  1459. mono_domain_unset (void)
  1460. {
  1461. SET_APPDOMAIN (NULL);
  1462. }
  1463. void
  1464. mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exception)
  1465. {
  1466. MonoInternalThread *thread;
  1467. if (mono_domain_get () == domain)
  1468. return;
  1469. SET_APPDOMAIN (domain);
  1470. SET_APPCONTEXT (domain->default_context);
  1471. if (migrate_exception) {
  1472. thread = mono_thread_internal_current ();
  1473. if (!thread->abort_exc)
  1474. return;
  1475. g_assert (thread->abort_exc->object.vtable->domain != domain);
  1476. MONO_OBJECT_SETREF (thread, abort_exc, mono_get_exception_thread_abort ());
  1477. g_assert (thread->abort_exc->object.vtable->domain == domain);
  1478. }
  1479. }
  1480. /**
  1481. * mono_domain_set_internal:
  1482. * @domain: the new domain
  1483. *
  1484. * Sets the current domain to @domain.
  1485. */
  1486. void
  1487. mono_domain_set_internal (MonoDomain *domain)
  1488. {
  1489. mono_domain_set_internal_with_options (domain, TRUE);
  1490. }
  1491. void
  1492. mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
  1493. {
  1494. int i, size;
  1495. MonoDomain **copy;
  1496. /*
  1497. * Create a copy of the data to avoid calling the user callback
  1498. * inside the lock because that could lead to deadlocks.
  1499. * We can do this because this function is not perf. critical.
  1500. */
  1501. mono_appdomains_lock ();
  1502. size = appdomain_list_size;
  1503. copy = mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), NULL);
  1504. memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
  1505. mono_appdomains_unlock ();
  1506. for (i = 0; i < size; ++i) {
  1507. if (copy [i])
  1508. func (copy [i], user_data);
  1509. }
  1510. mono_gc_free_fixed (copy);
  1511. }
  1512. /**
  1513. * mono_domain_assembly_open:
  1514. * @domain: the application domain
  1515. * @name: file name of the assembly
  1516. *
  1517. * fixme: maybe we should integrate this with mono_assembly_open ??
  1518. */
  1519. MonoAssembly *
  1520. mono_domain_assembly_open (MonoDomain *domain, const char *name)
  1521. {
  1522. MonoDomain *current;
  1523. MonoAssembly *ass;
  1524. GSList *tmp;
  1525. mono_domain_assemblies_lock (domain);
  1526. for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
  1527. ass = tmp->data;
  1528. if (strcmp (name, ass->aname.name) == 0) {
  1529. mono_domain_assemblies_unlock (domain);
  1530. return ass;
  1531. }
  1532. }
  1533. mono_domain_assemblies_unlock (domain);
  1534. if (domain != mono_domain_get ()) {
  1535. current = mono_domain_get ();
  1536. mono_domain_set (domain, FALSE);
  1537. ass = mono_assembly_open (name, NULL);
  1538. mono_domain_set (current, FALSE);
  1539. } else {
  1540. ass = mono_assembly_open (name, NULL);
  1541. }
  1542. return ass;
  1543. }
  1544. static void
  1545. unregister_vtable_reflection_type (MonoVTable *vtable)
  1546. {
  1547. MonoObject *type = vtable->type;
  1548. if (type->vtable->klass != mono_defaults.monotype_class)
  1549. MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type);
  1550. }
  1551. void
  1552. mono_domain_free (MonoDomain *domain, gboolean force)
  1553. {
  1554. int code_size, code_alloc;
  1555. GSList *tmp;
  1556. if ((domain == mono_root_domain) && !force) {
  1557. g_warning ("cant unload root domain");
  1558. return;
  1559. }
  1560. if (mono_dont_free_domains)
  1561. return;
  1562. mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD);
  1563. mono_debug_domain_unload (domain);
  1564. mono_appdomains_lock ();
  1565. appdomains_list [domain->domain_id] = NULL;
  1566. mono_appdomains_unlock ();
  1567. /* must do this early as it accesses fields and types */
  1568. if (domain->special_static_fields) {
  1569. mono_alloc_special_static_data_free (domain->special_static_fields);
  1570. g_hash_table_destroy (domain->special_static_fields);
  1571. domain->special_static_fields = NULL;
  1572. }
  1573. /*
  1574. * We must destroy all these hash tables here because they
  1575. * contain references to managed objects belonging to the
  1576. * domain. Once we let the GC clear the domain there must be
  1577. * no more such references, or we'll crash if a collection
  1578. * occurs.
  1579. */
  1580. mono_g_hash_table_destroy (domain->ldstr_table);
  1581. domain->ldstr_table = NULL;
  1582. mono_g_hash_table_destroy (domain->env);
  1583. domain->env = NULL;
  1584. if (domain->tlsrec_list) {
  1585. mono_thread_destroy_domain_tls (domain);
  1586. domain->tlsrec_list = NULL;
  1587. }
  1588. mono_reflection_cleanup_domain (domain);
  1589. if (domain->type_hash) {
  1590. mono_g_hash_table_destroy (domain->type_hash);
  1591. domain->type_hash = NULL;
  1592. }
  1593. if (domain->type_init_exception_hash) {
  1594. mono_g_hash_table_destroy (domain->type_init_exception_hash);
  1595. domain->type_init_exception_hash = NULL;
  1596. }
  1597. if (domain->class_vtable_array) {
  1598. int i;
  1599. for (i = 0; i < domain->class_vtable_array->len; ++i)
  1600. unregister_vtable_reflection_type (g_ptr_array_index (domain->class_vtable_array, i));
  1601. }
  1602. for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
  1603. MonoAssembly *ass = tmp->data;
  1604. mono_assembly_release_gc_roots (ass);
  1605. }
  1606. /* This needs to be done before closing assemblies */
  1607. mono_gc_clear_domain (domain);
  1608. for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
  1609. MonoAssembly *ass = tmp->data;
  1610. mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading domain %s[%p], assembly %s[%p], ref_count=%d", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count);
  1611. if (!mono_assembly_close_except_image_pools (ass))
  1612. tmp->data = NULL;
  1613. }
  1614. for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
  1615. MonoAssembly *ass = tmp->data;
  1616. if (ass)
  1617. mono_assembly_close_finish (ass);
  1618. }
  1619. g_slist_free (domain->domain_assemblies);
  1620. domain->domain_assemblies = NULL;
  1621. /*
  1622. * Send this after the assemblies have been unloaded and the domain is still in a
  1623. * usable state.
  1624. */
  1625. mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD);
  1626. if (free_domain_hook)
  1627. free_domain_hook (domain);
  1628. /* FIXME: free delegate_hash_table when it's used */
  1629. if (domain->search_path) {
  1630. g_strfreev (domain->search_path);
  1631. domain->search_path = NULL;
  1632. }
  1633. domain->create_proxy_for_type_method = NULL;
  1634. domain->private_invoke_method = NULL;
  1635. domain->default_context = NULL;
  1636. domain->out_of_memory_ex = NULL;
  1637. domain->null_reference_ex = NULL;
  1638. domain->stack_overflow_ex = NULL;
  1639. domain->ephemeron_tombstone = NULL;
  1640. domain->entry_assembly = NULL;
  1641. g_free (domain->friendly_name);
  1642. domain->friendly_name = NULL;
  1643. g_ptr_array_free (domain->class_vtable_array, TRUE);
  1644. domain->class_vtable_array = NULL;
  1645. g_hash_table_destroy (domain->proxy_vtable_hash);
  1646. domain->proxy_vtable_hash = NULL;
  1647. if (domain->static_data_array) {
  1648. mono_gc_free_fixed (domain->static_data_array);
  1649. domain->static_data_array = NULL;
  1650. }
  1651. mono_internal_hash_table_destroy (&domain->jit_code_hash);
  1652. /*
  1653. * There might still be jit info tables of this domain which
  1654. * are not freed. Since the domain cannot be in use anymore,
  1655. * this will free them.
  1656. */
  1657. mono_thread_hazardous_try_free_all ();
  1658. g_assert (domain->num_jit_info_tables == 1);
  1659. jit_info_table_free (domain->jit_info_table);
  1660. domain->jit_info_table = NULL;
  1661. g_assert (!domain->jit_info_free_queue);
  1662. /* collect statistics */
  1663. code_alloc = mono_code_manager_size (domain->code_mp, &code_size);
  1664. total_domain_code_alloc += code_alloc;
  1665. max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
  1666. max_domain_code_size = MAX (max_domain_code_size, code_size);
  1667. #ifdef DEBUG_DOMAIN_UNLOAD
  1668. mono_mempool_invalidate (domain->mp);
  1669. mono_code_manager_invalidate (domain->code_mp);
  1670. #else
  1671. #ifndef DISABLE_PERFCOUNTERS
  1672. mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
  1673. #endif
  1674. mono_mempool_destroy (domain->mp);
  1675. domain->mp = NULL;
  1676. mono_code_manager_destroy (domain->code_mp);
  1677. domain->code_mp = NULL;
  1678. #endif
  1679. g_hash_table_destroy (domain->finalizable_objects_hash);
  1680. domain->finalizable_objects_hash = NULL;
  1681. if (domain->method_rgctx_hash) {
  1682. g_hash_table_destroy (domain->method_rgctx_hash);
  1683. domain->method_rgctx_hash = NULL;
  1684. }
  1685. if (domain->generic_virtual_cases) {
  1686. g_hash_table_destroy (domain->generic_virtual_cases);
  1687. domain->generic_virtual_cases = NULL;
  1688. }
  1689. if (domain->generic_virtual_thunks) {
  1690. g_hash_table_destroy (domain->generic_virtual_thunks);
  1691. domain->generic_virtual_thunks = NULL;
  1692. }
  1693. if (domain->ftnptrs_hash) {
  1694. g_hash_table_destroy (domain->ftnptrs_hash);
  1695. domain->ftnptrs_hash = NULL;
  1696. }
  1697. DeleteCriticalSection (&domain->finalizable_objects_hash_lock);
  1698. DeleteCriticalSection (&domain->assemblies_lock);
  1699. DeleteCriticalSection (&domain->jit_code_hash_lock);
  1700. DeleteCriticalSection (&domain->lock);
  1701. domain->setup = NULL;
  1702. mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
  1703. /* FIXME: anything else required ? */
  1704. mono_gc_free_fixed (domain);
  1705. #ifndef DISABLE_PERFCOUNTERS
  1706. mono_perfcounters->loader_appdomains--;
  1707. #endif
  1708. if (domain == mono_root_domain)
  1709. mono_root_domain = NULL;
  1710. }
  1711. /**
  1712. * mono_domain_get_id:
  1713. * @domainid: the ID
  1714. *
  1715. * Returns: the a domain for a specific domain id.
  1716. */
  1717. MonoDomain *
  1718. mono_domain_get_by_id (gint32 domainid)
  1719. {
  1720. MonoDomain * domain;
  1721. mono_appdomains_lock ();
  1722. if (domainid < appdomain_list_size)
  1723. domain = appdomains_list [domainid];
  1724. else
  1725. domain = NULL;
  1726. mono_appdomains_unlock ();
  1727. return domain;
  1728. }
  1729. gint32
  1730. mono_domain_get_id (MonoDomain *domain)
  1731. {
  1732. return domain->domain_id;
  1733. }
  1734. /*
  1735. * mono_domain_alloc:
  1736. *
  1737. * LOCKING: Acquires the domain lock.
  1738. */
  1739. gpointer
  1740. mono_domain_alloc (MonoDomain *domain, guint size)
  1741. {
  1742. gpointer res;
  1743. mono_domain_lock (domain);
  1744. #ifndef DISABLE_PERFCOUNTERS
  1745. mono_perfcounters->loader_bytes += size;
  1746. #endif
  1747. res = mono_mempool_alloc (domain->mp, size);
  1748. mono_domain_unlock (domain);
  1749. return res;
  1750. }
  1751. /*
  1752. * mono_domain_alloc0:
  1753. *
  1754. * LOCKING: Acquires the domain lock.
  1755. */
  1756. gpointer
  1757. mono_domain_alloc0 (MonoDomain *domain, guint size)
  1758. {
  1759. gpointer res;
  1760. mono_domain_lock (domain);
  1761. #ifndef DISABLE_PERFCOUNTERS
  1762. mono_perfcounters->loader_bytes += size;
  1763. #endif
  1764. res = mono_mempool_alloc0 (domain->mp, size);
  1765. mono_domain_unlock (domain);
  1766. return res;
  1767. }
  1768. /*
  1769. * mono_domain_code_reserve:
  1770. *
  1771. * LOCKING: Acquires the domain lock.
  1772. */
  1773. void*
  1774. mono_domain_code_reserve (MonoDomain *domain, int size)
  1775. {
  1776. gpointer res;
  1777. mono_domain_lock (domain);
  1778. res = mono_code_manager_reserve (domain->code_mp, size);
  1779. mono_domain_unlock (domain);
  1780. return res;
  1781. }
  1782. /*
  1783. * mono_domain_code_reserve_align:
  1784. *
  1785. * LOCKING: Acquires the domain lock.
  1786. */
  1787. void*
  1788. mono_domain_code_reserve_align (MonoDomain *domain, int size, int alignment)
  1789. {
  1790. gpointer res;
  1791. mono_domain_lock (domain);
  1792. res = mono_code_manager_reserve_align (domain->code_mp, size, alignment);
  1793. mono_domain_unlock (domain);
  1794. return res;
  1795. }
  1796. /*
  1797. * mono_domain_code_commit:
  1798. *
  1799. * LOCKING: Acquires the domain lock.
  1800. */
  1801. void
  1802. mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize)
  1803. {
  1804. mono_domain_lock (domain);
  1805. mono_code_manager_commit (domain->code_mp, data, size, newsize);
  1806. mono_domain_unlock (domain);
  1807. }
  1808. #if defined(__native_client_codegen__) && defined(__native_client__)
  1809. /*
  1810. * Given the temporary buffer (allocated by mono_domain_code_reserve) into which
  1811. * we are generating code, return a pointer to the destination in the dynamic
  1812. * code segment into which the code will be copied when mono_domain_code_commit
  1813. * is called.
  1814. * LOCKING: Acquires the domain lock.
  1815. */
  1816. void *
  1817. nacl_domain_get_code_dest (MonoDomain *domain, void *data)
  1818. {
  1819. void *dest;
  1820. mono_domain_lock (domain);
  1821. dest = nacl_code_manager_get_code_dest (domain->code_mp, data);
  1822. mono_domain_unlock (domain);
  1823. return dest;
  1824. }
  1825. /*
  1826. * Convenience function which calls mono_domain_code_commit to validate and copy
  1827. * the code. The caller sets *buf_base and *buf_size to the start and size of
  1828. * the buffer (allocated by mono_domain_code_reserve), and *code_end to the byte
  1829. * after the last instruction byte. On return, *buf_base will point to the start
  1830. * of the copied in the code segment, and *code_end will point after the end of
  1831. * the copied code.
  1832. */
  1833. void
  1834. nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
  1835. {
  1836. guint8 *tmp = nacl_domain_get_code_dest (domain, *buf_base);
  1837. mono_domain_code_commit (domain, *buf_base, buf_size, *code_end - *buf_base);
  1838. *code_end = tmp + (*code_end - *buf_base);
  1839. *buf_base = tmp;
  1840. }
  1841. #else
  1842. /* no-op versions of Native Client functions */
  1843. void *
  1844. nacl_domain_get_code_dest (MonoDomain *domain, void *data)
  1845. {
  1846. return data;
  1847. }
  1848. void
  1849. nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end)
  1850. {
  1851. }
  1852. #endif
  1853. /*
  1854. * mono_domain_code_foreach:
  1855. * Iterate over the code thunks of the code manager of @domain.
  1856. *
  1857. * The @func callback MUST not take any locks. If it really needs to, it must respect
  1858. * the locking rules of the runtime: http://www.mono-project.com/Mono:Runtime:Documentation:ThreadSafety
  1859. * LOCKING: Acquires the domain lock.
  1860. */
  1861. void
  1862. mono_domain_code_foreach (MonoDomain *domain, MonoCodeManagerFunc func, void *user_data)
  1863. {
  1864. mono_domain_lock (domain);
  1865. mono_code_manager_foreach (domain->code_mp, func, user_data);
  1866. mono_domain_unlock (domain);
  1867. }
  1868. void
  1869. mono_context_set (MonoAppContext * new_context)
  1870. {
  1871. SET_APPCONTEXT (new_context);
  1872. }
  1873. MonoAppContext *
  1874. mono_context_get (void)
  1875. {
  1876. return GET_APPCONTEXT ();
  1877. }
  1878. /* LOCKING: the caller holds the lock for this domain */
  1879. void
  1880. mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointer data, guint32 *bitmap)
  1881. {
  1882. /* The first entry in the array is the index of the next free slot
  1883. * and the total size of the array
  1884. */
  1885. int next;
  1886. if (domain->static_data_array) {
  1887. int size = GPOINTER_TO_INT (domain->static_data_array [1]);
  1888. next = GPOINTER_TO_INT (domain->static_data_array [0]);
  1889. if (next >= size) {
  1890. /* 'data' is allocated by alloc_fixed */
  1891. gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), MONO_GC_ROOT_DESCR_FOR_FIXED (size * 2));
  1892. mono_gc_memmove (new_array, domain->static_data_array, sizeof (gpointer) * size);
  1893. size *= 2;
  1894. new_array [1] = GINT_TO_POINTER (size);
  1895. mono_gc_free_fixed (domain->static_data_array);
  1896. domain->static_data_array = new_array;
  1897. }
  1898. } else {
  1899. int size = 32;
  1900. gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, MONO_GC_ROOT_DESCR_FOR_FIXED (size));
  1901. next = 2;
  1902. new_array [0] = GINT_TO_POINTER (next);
  1903. new_array [1] = GINT_TO_POINTER (size);
  1904. domain->static_data_array = new_array;
  1905. }
  1906. domain->static_data_array [next++] = data;
  1907. domain->static_data_array [0] = GINT_TO_POINTER (next);
  1908. }
  1909. MonoImage*
  1910. mono_get_corlib (void)
  1911. {
  1912. return mono_defaults.corlib;
  1913. }
  1914. MonoClass*
  1915. mono_get_object_class (void)
  1916. {
  1917. return mono_defaults.object_class;
  1918. }
  1919. MonoClass*
  1920. mono_get_byte_class (void)
  1921. {
  1922. return mono_defaults.byte_class;
  1923. }
  1924. MonoClass*
  1925. mono_get_void_class (void)
  1926. {
  1927. return mono_defaults.void_class;
  1928. }
  1929. MonoClass*
  1930. mono_get_boolean_class (void)
  1931. {
  1932. return mono_defaults.boolean_class;
  1933. }
  1934. MonoClass*
  1935. mono_get_sbyte_class (void)
  1936. {
  1937. return mono_defaults.sbyte_class;
  1938. }
  1939. MonoClass*
  1940. mono_get_int16_class (void)
  1941. {
  1942. return mono_defaults.int16_class;
  1943. }
  1944. MonoClass*
  1945. mono_get_uint16_class (void)
  1946. {
  1947. return mono_defaults.uint16_class;
  1948. }
  1949. MonoClass*
  1950. mono_get_int32_class (void)
  1951. {
  1952. return mono_defaults.int32_class;
  1953. }
  1954. MonoClass*
  1955. mono_get_uint32_class (void)
  1956. {
  1957. return mono_defaults.uint32_class;
  1958. }
  1959. MonoClass*
  1960. mono_get_intptr_class (void)
  1961. {
  1962. return mono_defaults.int_class;
  1963. }
  1964. MonoClass*
  1965. mono_get_uintptr_class (void)
  1966. {
  1967. return mono_defaults.uint_class;
  1968. }
  1969. MonoClass*
  1970. mono_get_int64_class (void)
  1971. {
  1972. return mono_defaults.int64_class;
  1973. }
  1974. MonoClass*
  1975. mono_get_uint64_class (void)
  1976. {
  1977. return mono_defaults.uint64_class;
  1978. }
  1979. MonoClass*
  1980. mono_get_single_class (void)
  1981. {
  1982. return mono_defaults.single_class;
  1983. }
  1984. MonoClass*
  1985. mono_get_double_class (void)
  1986. {
  1987. return mono_defaults.double_class;
  1988. }
  1989. MonoClass*
  1990. mono_get_char_class (void)
  1991. {
  1992. return mono_defaults.char_class;
  1993. }
  1994. MonoClass*
  1995. mono_get_string_class (void)
  1996. {
  1997. return mono_defaults.string_class;
  1998. }
  1999. MonoClass*
  2000. mono_get_enum_class (void)
  2001. {
  2002. return mono_defaults.enum_class;
  2003. }
  2004. MonoClass*
  2005. mono_get_array_class (void)
  2006. {
  2007. return mono_defaults.array_class;
  2008. }
  2009. MonoClass*
  2010. mono_get_thread_class (void)
  2011. {
  2012. return mono_defaults.thread_class;
  2013. }
  2014. MonoClass*
  2015. mono_get_exception_class (void)
  2016. {
  2017. return mono_defaults.exception_class;
  2018. }
  2019. static char* get_attribute_value (const gchar **attribute_names,
  2020. const gchar **attribute_values,
  2021. const char *att_name)
  2022. {
  2023. int n;
  2024. for (n=0; attribute_names[n] != NULL; n++) {
  2025. if (strcmp (attribute_names[n], att_name) == 0)
  2026. return g_strdup (attribute_values[n]);
  2027. }
  2028. return NULL;
  2029. }
  2030. static void start_element (GMarkupParseContext *context,
  2031. const gchar *element_name,
  2032. const gchar **attribute_names,
  2033. const gchar **attribute_values,
  2034. gpointer user_data,
  2035. GError **error)
  2036. {
  2037. AppConfigInfo* app_config = (AppConfigInfo*) user_data;
  2038. if (strcmp (element_name, "configuration") == 0) {
  2039. app_config->configuration_count++;
  2040. return;
  2041. }
  2042. if (strcmp (element_name, "startup") == 0) {
  2043. app_config->startup_count++;
  2044. return;
  2045. }
  2046. if (app_config->configuration_count != 1 || app_config->startup_count != 1)
  2047. return;
  2048. if (strcmp (element_name, "requiredRuntime") == 0) {
  2049. app_config->required_runtime = get_attribute_value (attribute_names, attribute_values, "version");
  2050. } else if (strcmp (element_name, "supportedRuntime") == 0) {
  2051. char *version = get_attribute_value (attribute_names, attribute_values, "version");
  2052. app_config->supported_runtimes = g_slist_append (app_config->supported_runtimes, version);
  2053. }
  2054. }
  2055. static void end_element (GMarkupParseContext *context,
  2056. const gchar *element_name,
  2057. gpointer user_data,
  2058. GError **error)
  2059. {
  2060. AppConfigInfo* app_config = (AppConfigInfo*) user_data;
  2061. if (strcmp (element_name, "configuration") == 0) {
  2062. app_config->configuration_count--;
  2063. } else if (strcmp (element_name, "startup") == 0) {
  2064. app_config->startup_count--;
  2065. }
  2066. }
  2067. static const GMarkupParser
  2068. mono_parser = {
  2069. start_element,
  2070. end_element,
  2071. NULL,
  2072. NULL,
  2073. NULL
  2074. };
  2075. static AppConfigInfo *
  2076. app_config_parse (const char *exe_filename)
  2077. {
  2078. AppConfigInfo *app_config;
  2079. GMarkupParseContext *context;
  2080. char *text;
  2081. gsize len;
  2082. const char *bundled_config;
  2083. char *config_filename;
  2084. bundled_config = mono_config_string_for_assembly_file (exe_filename);
  2085. if (bundled_config) {
  2086. text = g_strdup (bundled_config);
  2087. len = strlen (text);
  2088. } else {
  2089. config_filename = g_strconcat (exe_filename, ".config", NULL);
  2090. if (!g_file_get_contents (config_filename, &text, &len, NULL)) {
  2091. g_free (config_filename);
  2092. return NULL;
  2093. }
  2094. g_free (config_filename);
  2095. }
  2096. app_config = g_new0 (AppConfigInfo, 1);
  2097. context = g_markup_parse_context_new (&mono_parser, 0, app_config, NULL);
  2098. if (g_markup_parse_context_parse (context, text, len, NULL)) {
  2099. g_markup_parse_context_end_parse (context, NULL);
  2100. }
  2101. g_markup_parse_context_free (context);
  2102. g_free (text);
  2103. return app_config;
  2104. }
  2105. static void
  2106. app_config_free (AppConfigInfo* app_config)
  2107. {
  2108. char *rt;
  2109. GSList *list = app_config->supported_runtimes;
  2110. while (list != NULL) {
  2111. rt = (char*)list->data;
  2112. g_free (rt);
  2113. list = g_slist_next (list);
  2114. }
  2115. g_slist_free (app_config->supported_runtimes);
  2116. g_free (app_config->required_runtime);
  2117. g_free (app_config);
  2118. }
  2119. static const MonoRuntimeInfo*
  2120. get_runtime_by_version (const char *version)
  2121. {
  2122. int n;
  2123. int max = G_N_ELEMENTS (supported_runtimes);
  2124. int vlen;
  2125. if (!version)
  2126. return NULL;
  2127. for (n=0; n<max; n++) {
  2128. if (strcmp (version, supported_runtimes[n].runtime_version) == 0)
  2129. return &supported_runtimes[n];
  2130. }
  2131. vlen = strlen (version);
  2132. if (vlen >= 4 && version [1] - '0' >= 4) {
  2133. for (n=0; n<max; n++) {
  2134. if (strncmp (version, supported_runtimes[n].runtime_version, 4) == 0)
  2135. return &supported_runtimes[n];
  2136. }
  2137. }
  2138. return NULL;
  2139. }
  2140. static void
  2141. get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRuntimeInfo** runtimes)
  2142. {
  2143. AppConfigInfo* app_config;
  2144. char *version;
  2145. const MonoRuntimeInfo* runtime = NULL;
  2146. MonoImage *image = NULL;
  2147. app_config = app_config_parse (exe_file);
  2148. if (app_config != NULL) {
  2149. /* Check supportedRuntime elements, if none is supported, fail.
  2150. * If there are no such elements, look for a requiredRuntime element.
  2151. */
  2152. if (app_config->supported_runtimes != NULL) {
  2153. int n = 0;
  2154. GSList *list = app_config->supported_runtimes;
  2155. while (list != NULL) {
  2156. version = (char*) list->data;
  2157. runtime = get_runtime_by_version (version);
  2158. if (runtime != NULL)
  2159. runtimes [n++] = runtime;
  2160. list = g_slist_next (list);
  2161. }
  2162. runtimes [n] = NULL;
  2163. app_config_free (app_config);
  2164. return;
  2165. }
  2166. /* Check the requiredRuntime element. This is for 1.0 apps only. */
  2167. if (app_config->required_runtime != NULL) {
  2168. runtimes [0] = get_runtime_by_version (app_config->required_runtime);
  2169. runtimes [1] = NULL;
  2170. app_config_free (app_config);
  2171. return;
  2172. }
  2173. app_config_free (app_config);
  2174. }
  2175. /* Look for a runtime with the exact version */
  2176. image = mono_assembly_open_from_bundle (exe_file, NULL, FALSE);
  2177. if (image == NULL)
  2178. image = mono_image_open (exe_file, NULL);
  2179. if (image == NULL) {
  2180. /* The image is wrong or the file was not found. In this case return
  2181. * a default runtime and leave to the initialization method the work of
  2182. * reporting the error.
  2183. */
  2184. runtimes [0] = get_runtime_by_version (DEFAULT_RUNTIME_VERSION);
  2185. runtimes [1] = NULL;
  2186. return;
  2187. }
  2188. *exe_image = image;
  2189. runtimes [0] = get_runtime_by_version (image->version);
  2190. runtimes [1] = NULL;
  2191. }
  2192. /**
  2193. * mono_get_runtime_info:
  2194. *
  2195. * Returns: the version of the current runtime instance.
  2196. */
  2197. const MonoRuntimeInfo*
  2198. mono_get_runtime_info (void)
  2199. {
  2200. return current_runtime;
  2201. }
  2202. gchar *
  2203. mono_debugger_check_runtime_version (const char *filename)
  2204. {
  2205. const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
  2206. const MonoRuntimeInfo *rinfo;
  2207. MonoImage *image;
  2208. get_runtimes_from_exe (filename, &image, runtimes);
  2209. rinfo = runtimes [0];
  2210. if (!rinfo)
  2211. return g_strdup_printf ("Cannot get runtime version from assembly `%s'", filename);
  2212. if (rinfo != current_runtime)
  2213. return g_strdup_printf ("The Mono Debugger is currently using the `%s' runtime, but "
  2214. "the assembly `%s' requires version `%s'", current_runtime->runtime_version,
  2215. filename, rinfo->runtime_version);
  2216. return NULL;
  2217. }
  2218. /**
  2219. * mono_framework_version:
  2220. *
  2221. * Return the major version of the framework curently executing.
  2222. */
  2223. int
  2224. mono_framework_version (void)
  2225. {
  2226. return current_runtime->framework_version [0] - '0';
  2227. }