PageRenderTime 95ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/mono/utils/mono-error.c

https://bitbucket.org/puffnfresh/mono-dependency-analysis
C | 521 lines | 411 code | 87 blank | 23 comment | 64 complexity | da0e04d88490020360b4cb3522c53c0f MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, Unlicense, Apache-2.0, LGPL-2.0
  1. /*
  2. * mono-error.c: Error handling code
  3. *
  4. * Authors:
  5. * Rodrigo Kumpera (rkumpera@novell.com)
  6. * Copyright 2009 Novell, Inc (http://www.novell.com)
  7. */
  8. #include <glib.h>
  9. #include "mono-error.h"
  10. #include "mono-error-internals.h"
  11. #include <mono/metadata/exception.h>
  12. #include <mono/metadata/object-internals.h>
  13. #include <mono/metadata/debug-helpers.h>
  14. #define mono_internal_error_get_message(E) ((E)->full_message ? (E)->full_message : (E)->message)
  15. #define set_error_message() do { \
  16. va_list args; \
  17. va_start (args, msg_format); \
  18. if (g_vsnprintf (error->message, sizeof (error->message), msg_format, args) >= sizeof (error->message)) {\
  19. va_end (args); \
  20. va_start (args, msg_format); \
  21. if (!(error->full_message = g_strdup_vprintf (msg_format, args))) \
  22. error->flags |= MONO_ERROR_INCOMPLETE; \
  23. } \
  24. va_end (args); \
  25. } while (0)
  26. static void
  27. mono_error_prepare (MonoErrorInternal *error)
  28. {
  29. if (error->error_code != MONO_ERROR_NONE)
  30. return;
  31. error->type_name = error->assembly_name = error->member_name = error->full_message = error->exception_name_space = error->exception_name = NULL;
  32. error->klass = NULL;
  33. error->message [0] = 0;
  34. }
  35. void
  36. mono_error_init_flags (MonoError *oerror, unsigned short flags)
  37. {
  38. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  39. g_assert (sizeof (MonoError) == sizeof (MonoErrorInternal));
  40. error->error_code = MONO_ERROR_NONE;
  41. error->flags = flags;
  42. }
  43. void
  44. mono_error_init (MonoError *error)
  45. {
  46. mono_error_init_flags (error, 0);
  47. }
  48. void
  49. mono_error_cleanup (MonoError *oerror)
  50. {
  51. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  52. if (error->error_code == MONO_ERROR_NONE)
  53. return;
  54. g_free ((char*)error->full_message);
  55. if (!(error->flags & MONO_ERROR_FREE_STRINGS)) //no memory was allocated
  56. return;
  57. g_free ((char*)error->type_name);
  58. g_free ((char*)error->assembly_name);
  59. g_free ((char*)error->member_name);
  60. g_free ((char*)error->exception_name_space);
  61. g_free ((char*)error->exception_name);
  62. }
  63. gboolean
  64. mono_error_ok (MonoError *error)
  65. {
  66. return error->error_code == MONO_ERROR_NONE;
  67. }
  68. unsigned short
  69. mono_error_get_error_code (MonoError *error)
  70. {
  71. return error->error_code;
  72. }
  73. /*Return a pointer to the internal error message, might be NULL.
  74. Caller should not release it.*/
  75. const char*
  76. mono_error_get_message (MonoError *oerror)
  77. {
  78. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  79. if (error->error_code == MONO_ERROR_NONE)
  80. return NULL;
  81. return mono_internal_error_get_message (error);
  82. }
  83. /*
  84. * Inform that this error has heap allocated strings.
  85. * The strings will be duplicated if @dup_strings is TRUE
  86. * otherwise they will just be free'd in mono_error_cleanup.
  87. */
  88. void
  89. mono_error_dup_strings (MonoError *oerror, gboolean dup_strings)
  90. {
  91. #define DUP_STR(field) do { if (error->field) {\
  92. if (!(error->field = g_strdup (error->field))) \
  93. error->flags |= MONO_ERROR_INCOMPLETE; \
  94. }} while (0);
  95. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  96. error->flags |= MONO_ERROR_FREE_STRINGS;
  97. if (dup_strings) {
  98. DUP_STR (type_name);
  99. DUP_STR (assembly_name);
  100. DUP_STR (member_name);
  101. DUP_STR (exception_name_space);
  102. DUP_STR (exception_name);
  103. }
  104. #undef DUP_STR
  105. }
  106. void
  107. mono_error_set_error (MonoError *oerror, int error_code, const char *msg_format, ...)
  108. {
  109. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  110. mono_error_prepare (error);
  111. error->error_code = error_code;
  112. set_error_message ();
  113. }
  114. static void
  115. mono_error_set_assembly_name (MonoError *oerror, const char *assembly_name)
  116. {
  117. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  118. g_assert (error->error_code != MONO_ERROR_NONE);
  119. error->assembly_name = assembly_name;
  120. }
  121. static void
  122. mono_error_set_member_name (MonoError *oerror, const char *member_name)
  123. {
  124. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  125. error->member_name = member_name;
  126. }
  127. static void
  128. mono_error_set_type_name (MonoError *oerror, const char *type_name)
  129. {
  130. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  131. error->type_name = type_name;
  132. }
  133. static void
  134. mono_error_set_class (MonoError *oerror, MonoClass *klass)
  135. {
  136. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  137. error->klass = klass;
  138. }
  139. static void
  140. mono_error_set_corlib_exception (MonoError *oerror, const char *name_space, const char *name)
  141. {
  142. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  143. error->exception_name_space = name_space;
  144. error->exception_name = name;
  145. }
  146. void
  147. mono_error_set_assembly_load (MonoError *oerror, const char *assembly_name, const char *msg_format, ...)
  148. {
  149. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  150. mono_error_prepare (error);
  151. error->error_code = MONO_ERROR_FILE_NOT_FOUND;
  152. mono_error_set_assembly_name (oerror, assembly_name);
  153. set_error_message ();
  154. }
  155. void
  156. mono_error_set_type_load_class (MonoError *oerror, MonoClass *klass, const char *msg_format, ...)
  157. {
  158. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  159. mono_error_prepare (error);
  160. error->error_code = MONO_ERROR_TYPE_LOAD;
  161. mono_error_set_class (oerror, klass);
  162. set_error_message ();
  163. }
  164. void
  165. mono_error_set_type_load_name (MonoError *oerror, const char *type_name, const char *assembly_name, const char *msg_format, ...)
  166. {
  167. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  168. mono_error_prepare (error);
  169. error->error_code = MONO_ERROR_TYPE_LOAD;
  170. mono_error_set_type_name (oerror, type_name);
  171. mono_error_set_assembly_name (oerror, assembly_name);
  172. set_error_message ();
  173. }
  174. void
  175. mono_error_set_method_load (MonoError *oerror, MonoClass *klass, const char *method_name, const char *msg_format, ...)
  176. {
  177. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  178. mono_error_prepare (error);
  179. error->error_code = MONO_ERROR_MISSING_METHOD;
  180. mono_error_set_class (oerror, klass);
  181. mono_error_set_member_name (oerror, method_name);
  182. set_error_message ();
  183. }
  184. void
  185. mono_error_set_field_load (MonoError *oerror, MonoClass *klass, const char *field_name, const char *msg_format, ...)
  186. {
  187. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  188. mono_error_prepare (error);
  189. error->error_code = MONO_ERROR_MISSING_FIELD;
  190. mono_error_set_class (oerror, klass);
  191. mono_error_set_member_name (oerror, field_name);
  192. set_error_message ();
  193. }
  194. void
  195. mono_error_set_bad_image_name (MonoError *oerror, const char *assembly_name, const char *msg_format, ...)
  196. {
  197. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  198. mono_error_prepare (error);
  199. error->error_code = MONO_ERROR_BAD_IMAGE;
  200. mono_error_set_assembly_name (oerror, assembly_name);
  201. set_error_message ();
  202. }
  203. void
  204. mono_error_set_bad_image (MonoError *oerror, MonoImage *image, const char *msg_format, ...)
  205. {
  206. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  207. mono_error_prepare (error);
  208. error->error_code = MONO_ERROR_BAD_IMAGE;
  209. error->assembly_name = image ? mono_image_get_name (image) : "<no_image>";
  210. set_error_message ();
  211. }
  212. void
  213. mono_error_set_generic_error (MonoError *oerror, const char * name_space, const char *name, const char *msg_format, ...)
  214. {
  215. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  216. mono_error_prepare (error);
  217. error->error_code = MONO_ERROR_GENERIC;
  218. mono_error_set_corlib_exception (oerror, name_space, name);
  219. set_error_message ();
  220. }
  221. void
  222. mono_error_set_out_of_memory (MonoError *oerror, const char *msg_format, ...)
  223. {
  224. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  225. va_list args;
  226. mono_error_prepare (error);
  227. error->error_code = MONO_ERROR_OUT_OF_MEMORY;
  228. va_start (args, msg_format);
  229. g_vsnprintf (error->message, sizeof (error->message), msg_format, args);
  230. va_end (args);
  231. }
  232. void
  233. mono_error_set_argument (MonoError *oerror, const char *argument, const char *msg_format, ...)
  234. {
  235. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  236. mono_error_prepare (error);
  237. error->error_code = MONO_ERROR_ARGUMENT;
  238. error->type_name = argument; /*use the first available string slot*/
  239. set_error_message ();
  240. }
  241. void
  242. mono_error_set_not_verifiable (MonoError *oerror, MonoMethod *method, const char *msg_format, ...)
  243. {
  244. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  245. mono_error_prepare (error);
  246. error->error_code = MONO_ERROR_NOT_VERIFIABLE;
  247. mono_error_set_class (oerror, method->klass);
  248. if (method)
  249. mono_error_set_member_name (oerror, mono_method_full_name (method, 1));
  250. set_error_message ();
  251. }
  252. static MonoString*
  253. get_type_name_as_mono_string (MonoErrorInternal *error, MonoDomain *domain, MonoError *error_out)
  254. {
  255. MonoString* res = NULL;
  256. if (error->type_name) {
  257. res = mono_string_new (domain, error->type_name);
  258. } else if (error->klass) {
  259. char *name = mono_type_full_name (&error->klass->byval_arg);
  260. if (name) {
  261. res = mono_string_new (domain, name);
  262. g_free (name);
  263. }
  264. }
  265. if (!res)
  266. mono_error_set_out_of_memory (error_out, "Could not allocate type name");
  267. return res;
  268. }
  269. static void
  270. set_message_on_exception (MonoException *exception, MonoErrorInternal *error, MonoError *error_out)
  271. {
  272. MonoString *msg = mono_string_new (mono_domain_get (), mono_internal_error_get_message (error));
  273. if (msg)
  274. MONO_OBJECT_SETREF (exception, message, msg);
  275. else
  276. mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
  277. }
  278. /*Can fail with out-of-memory*/
  279. MonoException*
  280. mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
  281. {
  282. MonoErrorInternal *error = (MonoErrorInternal*)oerror;
  283. MonoException* exception = NULL;
  284. MonoString *assembly_name = NULL, *type_name = NULL, *method_name = NULL, *field_name = NULL, *msg = NULL;
  285. MonoDomain *domain = mono_domain_get ();
  286. mono_error_init (error_out);
  287. switch (error->error_code) {
  288. case MONO_ERROR_NONE:
  289. return NULL;
  290. case MONO_ERROR_MISSING_METHOD:
  291. if ((error->type_name || error->klass) && error->member_name) {
  292. type_name = get_type_name_as_mono_string (error, domain, error_out);
  293. if (!mono_error_ok (error_out))
  294. break;
  295. method_name = mono_string_new (domain, error->member_name);
  296. if (!method_name) {
  297. mono_error_set_out_of_memory (error_out, "Could not allocate method name");
  298. break;
  299. }
  300. exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingMethodException", type_name, method_name);
  301. if (exception)
  302. set_message_on_exception (exception, error, error_out);
  303. } else {
  304. exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", mono_internal_error_get_message (error));
  305. }
  306. break;
  307. case MONO_ERROR_MISSING_FIELD:
  308. if ((error->type_name || error->klass) && error->member_name) {
  309. type_name = get_type_name_as_mono_string (error, domain, error_out);
  310. if (!mono_error_ok (error_out))
  311. break;
  312. field_name = mono_string_new (domain, error->member_name);
  313. if (!field_name) {
  314. mono_error_set_out_of_memory (error_out, "Could not allocate field name");
  315. break;
  316. }
  317. exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingFieldException", type_name, field_name);
  318. if (exception)
  319. set_message_on_exception (exception, error, error_out);
  320. } else {
  321. exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", mono_internal_error_get_message (error));
  322. }
  323. break;
  324. case MONO_ERROR_TYPE_LOAD:
  325. if (error->type_name || error->assembly_name) {
  326. type_name = get_type_name_as_mono_string (error, domain, error_out);
  327. if (!mono_error_ok (error_out))
  328. break;
  329. if (error->assembly_name) {
  330. assembly_name = mono_string_new (domain, error->assembly_name);
  331. if (!assembly_name) {
  332. mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
  333. break;
  334. }
  335. }
  336. exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name);
  337. if (exception)
  338. set_message_on_exception (exception, error, error_out);
  339. } else {
  340. exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", mono_internal_error_get_message (error));
  341. }
  342. break;
  343. case MONO_ERROR_FILE_NOT_FOUND:
  344. case MONO_ERROR_BAD_IMAGE:
  345. if (error->assembly_name) {
  346. msg = mono_string_new (domain, mono_internal_error_get_message (error));
  347. if (!msg) {
  348. mono_error_set_out_of_memory (error_out, "Could not allocate message");
  349. break;
  350. }
  351. if (error->assembly_name) {
  352. assembly_name = mono_string_new (domain, error->assembly_name);
  353. if (!assembly_name) {
  354. mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
  355. break;
  356. }
  357. }
  358. if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
  359. exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System.IO", "FileNotFoundException", msg, assembly_name);
  360. else
  361. exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "BadImageFormatException", msg, assembly_name);
  362. } else {
  363. if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
  364. exception = mono_exception_from_name_msg (mono_get_corlib (), "System.IO", "FileNotFoundException", mono_internal_error_get_message (error));
  365. else
  366. exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "BadImageFormatException", mono_internal_error_get_message (error));
  367. }
  368. break;
  369. case MONO_ERROR_OUT_OF_MEMORY:
  370. exception = mono_get_exception_out_of_memory ();
  371. break;
  372. case MONO_ERROR_ARGUMENT:
  373. exception = mono_get_exception_argument (error->type_name, mono_internal_error_get_message (error));
  374. break;
  375. case MONO_ERROR_NOT_VERIFIABLE: {
  376. char *type_name = NULL, *message;
  377. if (error->klass) {
  378. type_name = mono_type_get_full_name (error->klass);
  379. if (!type_name) {
  380. mono_error_set_out_of_memory (error_out, "Could not allocate message");
  381. break;
  382. }
  383. }
  384. message = g_strdup_printf ("Error in %s:%s %s", type_name, error->member_name, mono_internal_error_get_message (error));
  385. if (!message) {
  386. g_free (type_name);
  387. mono_error_set_out_of_memory (error_out, "Could not allocate message");
  388. break;
  389. }
  390. exception = mono_exception_from_name_msg (mono_defaults.corlib, "System.Security", "VerificationException", message);
  391. g_free (message);
  392. g_free (type_name);
  393. break;
  394. }
  395. case MONO_ERROR_GENERIC:
  396. if (!error->exception_name_space || !error->exception_name)
  397. mono_error_set_generic_error (error_out, "System", "ExecutionEngineException", "MonoError with generic error but no exception name was supplied");
  398. else
  399. exception = mono_exception_from_name_msg (mono_defaults.corlib, error->exception_name_space, error->exception_name, mono_internal_error_get_message (error));
  400. break;
  401. default:
  402. mono_error_set_generic_error (error_out, "System", "ExecutionEngineException", "Invalid error-code %d", error->error_code);
  403. }
  404. if (!mono_error_ok (error_out))
  405. return NULL;
  406. if (!exception)
  407. mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
  408. return exception;
  409. }
  410. /*
  411. Raises the exception of @error.
  412. Does nothing if @error has a success error code.
  413. Aborts in case of a double fault. This happens when it can't recover from an error caused by trying
  414. to construct the first exception object.
  415. The error object @error is cleaned up.
  416. */
  417. void
  418. mono_error_raise_exception (MonoError *target_error)
  419. {
  420. MonoError error;
  421. MonoException *ex;
  422. if (mono_error_ok (target_error))
  423. return;
  424. ex = mono_error_prepare_exception (target_error, &error);
  425. if (!mono_error_ok (&error)) {
  426. MonoError second_chance;
  427. /*Try to produce the exception for the second error. FIXME maybe we should log about the original one*/
  428. ex = mono_error_prepare_exception (&error, &second_chance);
  429. g_assert (mono_error_ok (&second_chance)); /*We can't reasonable handle double faults, maybe later.*/
  430. mono_error_cleanup (&error);
  431. }
  432. mono_error_cleanup (target_error);
  433. mono_raise_exception (ex);
  434. }