Skip to content

Commit

Permalink
Mixed mode exception handling (mono#4777)
Browse files Browse the repository at this point in the history
* [mixed] Add beginnings of unwinding support for interp->jit transitions by pushing an LMF frame on the stack when exiting interpreted code.

* [runtime] Add a mono_debug_lookup_source_location_by_il () helper function to lookup a source location using an IL offset.

* [mixed] Add support for mixed mode managed stack walks.

* [interp] Generate line number info for interpreted code, using the same MonoDebugMethodJitInfo structure used by the JIT.

* [interp] Pass the clause index to the MINT_ENDFINALLY opcode. Not yet used.

* [interp] Create a MonoJitInfo structure for each interpreted method. Not yet used.

* [interp] Add a mono_interp_set_resume_state () function which can be used to set the frame/ip the interpreter will resume execution from when execution returns to it.

* [mixed] Add support for mixed mode exception handling by extending the normal JIT exception handling code in mini-exceptions.c to handle interpreted frames as well.

* [jit] Add an Unwinder type to reduce the amount of code duplication when unwinding though interpreter frames.

* [interp] Fix the !ENABLE_INTERPRETER build.

* [interp] Disable an assert which is hit even when running without --interpreter.

* Fix a comment.

* [interp] Fix an assertion. Fix/add comments.
  • Loading branch information
vargaz committed May 3, 2017
1 parent b89cb75 commit 5e7137b
Show file tree
Hide file tree
Showing 16 changed files with 680 additions and 81 deletions.
3 changes: 3 additions & 0 deletions mono/metadata/debug-internals.h
Expand Up @@ -84,4 +84,7 @@ mono_debug_free_method_async_debug_info (MonoDebugMethodAsyncInfo *info);
gboolean
mono_debug_image_has_debug_info (MonoImage *image);

MonoDebugSourceLocation *
mono_debug_lookup_source_location_by_il (MonoMethod *method, guint32 il_offset, MonoDomain *domain);

#endif /* __DEBUG_INTERNALS_H__ */
34 changes: 34 additions & 0 deletions mono/metadata/mono-debug.c
Expand Up @@ -793,6 +793,40 @@ mono_debug_lookup_source_location (MonoMethod *method, guint32 address, MonoDoma
return location;
}

/**
* mono_debug_lookup_source_location_by_il:
*
* Same as mono_debug_lookup_source_location but take an IL_OFFSET argument.
*/
MonoDebugSourceLocation *
mono_debug_lookup_source_location_by_il (MonoMethod *method, guint32 il_offset, MonoDomain *domain)
{
MonoDebugMethodInfo *minfo;
MonoDebugSourceLocation *location;

if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
return NULL;

mono_debugger_lock ();
minfo = mono_debug_lookup_method_internal (method);
if (!minfo || !minfo->handle) {
mono_debugger_unlock ();
return NULL;
}

if (!minfo->handle->ppdb && (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile))) {
mono_debugger_unlock ();
return NULL;
}

if (minfo->handle->ppdb)
location = mono_ppdb_lookup_location (minfo, il_offset);
else
location = mono_debug_symfile_lookup_location (minfo, il_offset);
mono_debugger_unlock ();
return location;
}

MonoDebugSourceLocation *
mono_debug_method_lookup_location (MonoDebugMethodInfo *minfo, int il_offset)
{
Expand Down
2 changes: 1 addition & 1 deletion mono/metadata/object.c
Expand Up @@ -7826,7 +7826,7 @@ mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpoint
g_assert (method);
method = mono_marshal_get_remoting_invoke (method);
#ifdef ENABLE_INTERPRETER
g_error ("need RuntimeMethod in method_ptr when using interpreter");
//g_error ("need RuntimeMethod in method_ptr when using interpreter");
#endif
delegate->method_ptr = mono_compile_method_checked (method, error);
return_val_if_nok (error, FALSE);
Expand Down
22 changes: 13 additions & 9 deletions mono/mini/exceptions-amd64.c
Expand Up @@ -582,20 +582,24 @@ mono_arch_unwind_frame (MonoDomain *domain, MonoJitTlsData *jit_tls,
guint64 rip;

if (((guint64)(*lmf)->previous_lmf) & 2) {
/*
* This LMF entry is created by the soft debug code to mark transitions to
* managed code done during invokes.
*/
MonoLMFExt *ext = (MonoLMFExt*)(*lmf);

g_assert (ext->debugger_invoke);

memcpy (new_ctx, &ext->ctx, sizeof (MonoContext));
if (ext->debugger_invoke) {
/*
* This LMF entry is created by the soft debug code to mark transitions to
* managed code done during invokes.
*/
frame->type = FRAME_TYPE_DEBUGGER_INVOKE;
memcpy (new_ctx, &ext->ctx, sizeof (MonoContext));
} else if (ext->interp_exit) {
frame->type = FRAME_TYPE_INTERP_TO_MANAGED;
frame->interp_exit_data = ext->interp_exit_data;
} else {
g_assert_not_reached ();
}

*lmf = (MonoLMF *)(((guint64)(*lmf)->previous_lmf) & ~7);

frame->type = FRAME_TYPE_DEBUGGER_INVOKE;

return TRUE;
}

Expand Down
9 changes: 9 additions & 0 deletions mono/mini/interp/interp-internals.h
Expand Up @@ -7,6 +7,7 @@
#include <mono/metadata/object.h>
#include <mono/metadata/domain-internals.h>
#include <mono/metadata/class-internals.h>
#include <mono/metadata/debug-internals.h>
#include "config.h"

enum {
Expand Down Expand Up @@ -88,6 +89,7 @@ typedef struct _RuntimeMethod
gpointer jit_entry;
MonoType *rtype;
MonoType **param_types;
MonoJitInfo *jinfo;
} RuntimeMethod;

struct _MonoInvocation {
Expand Down Expand Up @@ -115,6 +117,13 @@ typedef struct {
jmp_buf *current_env;
unsigned char search_for_handler;
unsigned char managed_code;

/* Resume state for resuming execution in mixed mode */
gboolean has_resume_state;
/* Frame to resume execution at */
MonoInvocation *handler_frame;
/* IP to resume execution at */
gpointer handler_ip;
} ThreadContext;

extern int mono_interp_traceopt;
Expand Down

0 comments on commit 5e7137b

Please sign in to comment.