Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mono][debugger] Support debug after hot-reload #55220

Merged
merged 13 commits into from
Jul 13, 2021
58 changes: 54 additions & 4 deletions src/mono/mono/component/debugger-agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,14 @@ typedef struct {
MonoStackHash *hashes;
} EventInfo;

typedef struct {
MonoImage *image;
gconstpointer meta_bytes;
int meta_len;
gconstpointer pdb_bytes;
int pdb_len;
} EnCInfo;

#ifdef HOST_WIN32
#define get_last_sock_error() WSAGetLastError()
#define MONO_EWOULDBLOCK WSAEWOULDBLOCK
Expand Down Expand Up @@ -1604,7 +1612,7 @@ static MonoGHashTable *suspended_objs;

#ifdef TARGET_WASM
void
mono_init_debugger_agent_for_wasm (int log_level_parm)
mono_init_debugger_agent_for_wasm (int log_level_parm, MonoProfilerHandle *prof)
{
if (mono_atomic_cas_i32 (&agent_inited, 1, 0) == 1)
return;
Expand All @@ -1615,13 +1623,16 @@ mono_init_debugger_agent_for_wasm (int log_level_parm)
ids_init();
objrefs = g_hash_table_new_full (NULL, NULL, NULL, mono_debugger_free_objref);
obj_to_objref = g_hash_table_new (NULL, NULL);
pending_assembly_loads = g_ptr_array_new ();

log_level = log_level_parm;
event_requests = g_ptr_array_new ();
vm_start_event_sent = TRUE;
transport = &transports [0];
memset(&debugger_wasm_thread, 0, sizeof(DebuggerTlsData));
agent_config.enabled = TRUE;

mono_profiler_set_jit_done_callback (*prof, jit_done);
}
#endif

Expand Down Expand Up @@ -3600,6 +3611,9 @@ process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx
case EVENT_KIND_TYPE_LOAD:
buffer_add_typeid (&buf, domain, (MonoClass *)arg);
break;
case MDBGPROT_EVENT_KIND_METHOD_UPDATE:
buffer_add_methodid (&buf, domain, (MonoMethod *)arg);
break;
case EVENT_KIND_BREAKPOINT:
case EVENT_KIND_STEP: {
GET_DEBUGGER_TLS();
Expand Down Expand Up @@ -3655,6 +3669,15 @@ process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx
case EVENT_KIND_KEEPALIVE:
suspend_policy = SUSPEND_POLICY_NONE;
break;

case MDBGPROT_EVENT_KIND_ENC_UPDATE: {
EnCInfo *ei = (EnCInfo *)arg;
buffer_add_moduleid (&buf, mono_domain_get (), ei->image);
m_dbgprot_buffer_add_byte_array (&buf, (uint8_t *) ei->meta_bytes, ei->meta_len);
m_dbgprot_buffer_add_byte_array (&buf, (uint8_t *) ei->pdb_bytes, ei->pdb_len);
break;
}

default:
g_assert_not_reached ();
}
Expand Down Expand Up @@ -4060,6 +4083,9 @@ jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)

send_type_load (method->klass);

if (m_class_get_image(method->klass)->has_updates) {
process_profiler_event (MDBGPROT_EVENT_KIND_METHOD_UPDATE, method);
}
if (jinfo)
mono_de_add_pending_breakpoints (method, jinfo);
}
Expand Down Expand Up @@ -6517,6 +6543,28 @@ get_types_for_source_file (gpointer key, gpointer value, gpointer user_data)
}
}

static void
send_enc_delta (MonoImage *image, gconstpointer dmeta_bytes, int32_t dmeta_len, gconstpointer dpdb_bytes, int32_t dpdb_len)
{
//TODO: if it came from debugger we don't need to pass the parameters back, they are already on debugger client side.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is related to issue #55228 - we can assume that if the debugger is attached, all updates are coming through the debugger command, not through the managed icall.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot change this right now for WASM, am I right?
Because for wasm the updates are not coming through debugger.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right. I think for wasm the updates are always through dotnet watch, and not through the debugger.

if (agent_config.enabled) {
int suspend_policy;
GSList *events;
mono_loader_lock ();
events = create_event_list (MDBGPROT_EVENT_KIND_ENC_UPDATE, NULL, NULL, NULL, &suspend_policy);
mono_loader_unlock ();

EnCInfo info;
info.image = image;
info.meta_bytes = dpdb_bytes;
info.meta_len = dpdb_len;
info.pdb_bytes = dpdb_bytes;
info.pdb_len = dpdb_len;

process_event (MDBGPROT_EVENT_KIND_ENC_UPDATE, &info, 0, NULL, events, suspend_policy);
}
}

static gboolean
module_apply_changes (MonoImage *image, MonoArray *dmeta, MonoArray *dil, MonoArray *dpdb, MonoError *error)
{
Expand All @@ -6525,9 +6573,9 @@ module_apply_changes (MonoImage *image, MonoArray *dmeta, MonoArray *dil, MonoAr
int32_t dmeta_len = mono_array_length_internal (dmeta);
gpointer dil_bytes = (gpointer)mono_array_addr_internal (dil, char, 0);
int32_t dil_len = mono_array_length_internal (dil);
gpointer dpdb_bytes G_GNUC_UNUSED = !dpdb ? NULL : (gpointer)mono_array_addr_internal (dpdb, char, 0);
int32_t dpdb_len G_GNUC_UNUSED = !dpdb ? 0 : mono_array_length_internal (dpdb);
mono_image_load_enc_delta (image, dmeta_bytes, dmeta_len, dil_bytes, dil_len, error);
gpointer dpdb_bytes = !dpdb ? NULL : (gpointer)mono_array_addr_internal (dpdb, char, 0);
int32_t dpdb_len = !dpdb ? 0 : mono_array_length_internal (dpdb);
mono_image_load_enc_delta (image, dmeta_bytes, dmeta_len, dil_bytes, dil_len, dpdb_bytes, dpdb_len, error);
return is_ok (error);
}

Expand Down Expand Up @@ -7239,6 +7287,7 @@ event_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
req->info = mono_de_set_breakpoint (NULL, METHOD_EXIT_IL_OFFSET, req, NULL);
} else if (req->event_kind == EVENT_KIND_EXCEPTION) {
} else if (req->event_kind == EVENT_KIND_TYPE_LOAD) {
} else if (req->event_kind == MDBGPROT_EVENT_KIND_METHOD_UPDATE) {
} else {
if (req->nmodifiers) {
g_free (req);
Expand Down Expand Up @@ -10278,6 +10327,7 @@ debugger_agent_add_function_pointers(MonoComponentDebugger* fn_table)
fn_table->debug_log_is_enabled = debugger_agent_debug_log_is_enabled;
fn_table->send_crash = mono_debugger_agent_send_crash;
fn_table->transport_handshake = debugger_agent_transport_handshake;
fn_table->send_enc_delta = send_enc_delta;
}


Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/component/debugger-agent.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ DebuggerTlsData*
mono_wasm_get_tls (void);

void
mono_init_debugger_agent_for_wasm (int log_level);
mono_init_debugger_agent_for_wasm (int log_level, MonoProfilerHandle *prof);

void
mono_wasm_save_thread_context (void);
Expand Down
4 changes: 3 additions & 1 deletion src/mono/mono/component/debugger-protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,9 @@ typedef enum {
MDBGPROT_EVENT_KIND_KEEPALIVE = 14,
MDBGPROT_EVENT_KIND_USER_BREAK = 15,
MDBGPROT_EVENT_KIND_USER_LOG = 16,
MDBGPROT_EVENT_KIND_CRASH = 17
MDBGPROT_EVENT_KIND_CRASH = 17,
MDBGPROT_EVENT_KIND_ENC_UPDATE = 18,
MDBGPROT_EVENT_KIND_METHOD_UPDATE = 19,
} MdbgProtEventKind;

typedef enum {
Expand Down
13 changes: 12 additions & 1 deletion src/mono/mono/component/debugger-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ stub_mono_wasm_breakpoint_hit (void);
static void
stub_mono_wasm_single_step_hit (void);

static void
stub_send_enc_delta (MonoImage *image, gconstpointer dmeta_bytes, int32_t dmeta_len, gconstpointer dpdb_bytes, int32_t dpdb_len);

static MonoComponentDebugger fn_table = {
{ MONO_COMPONENT_ITF_VERSION, &debugger_avaliable },
&stub_debugger_init,
Expand All @@ -87,7 +90,10 @@ static MonoComponentDebugger fn_table = {

//wasm
&stub_mono_wasm_breakpoint_hit,
&stub_mono_wasm_single_step_hit
&stub_mono_wasm_single_step_hit,

//HotReload
&stub_send_enc_delta,
};

static bool
Expand Down Expand Up @@ -201,3 +207,8 @@ static void
stub_mono_wasm_single_step_hit (void)
{
}

static void
stub_send_enc_delta (MonoImage *image, gconstpointer dmeta_bytes, int32_t dmeta_len, gconstpointer dpdb_bytes, int32_t dpdb_len)
{
}
3 changes: 3 additions & 0 deletions src/mono/mono/component/debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ typedef struct MonoComponentDebugger {
void (*mono_wasm_breakpoint_hit) (void);
void (*mono_wasm_single_step_hit) (void);

//HotReload
void (*send_enc_delta) (MonoImage *image, gconstpointer dmeta_bytes, int32_t dmeta_len, gconstpointer dpdb_bytes, int32_t dpdb_len);

} MonoComponentDebugger;


Expand Down
14 changes: 12 additions & 2 deletions src/mono/mono/component/hot_reload-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ static bool
hot_reload_stub_available (void);

static void
hot_reload_stub_apply_changes (MonoImage *base_image, gconstpointer dmeta, uint32_t dmeta_len, gconstpointer dil, uint32_t dil_len, MonoError *error);
hot_reload_stub_apply_changes (MonoImage *base_image, gconstpointer dmeta, uint32_t dmeta_len, gconstpointer dil, uint32_t dil_len, gconstpointer dpdb_bytes_orig, uint32_t dpdb_length, MonoError *error);

static MonoComponentHotReload *
component_hot_reload_stub_init (void);
Expand Down Expand Up @@ -59,6 +59,9 @@ hot_reload_stub_table_bounds_check (MonoImage *base_image, int table_index, int
static gboolean
hot_reload_stub_delta_heap_lookup (MonoImage *base_image, MetadataHeapGetterFunc get_heap, uint32_t orig_index, MonoImage **image_out, uint32_t *index_out);

static gpointer
hot_reload_stub_get_updated_method_ppdb (MonoImage *base_image, uint32_t idx);

static MonoComponentHotReload fn_table = {
{ MONO_COMPONENT_ITF_VERSION, &hot_reload_stub_available },
&hot_reload_stub_set_fastpath_data,
Expand All @@ -75,6 +78,7 @@ static MonoComponentHotReload fn_table = {
&hot_reload_stub_get_updated_method_rva,
&hot_reload_stub_table_bounds_check,
&hot_reload_stub_delta_heap_lookup,
&hot_reload_stub_get_updated_method_ppdb
};

static bool
Expand Down Expand Up @@ -139,7 +143,7 @@ hot_reload_stub_relative_delta_index (MonoImage *image_dmeta, int token)
}

void
hot_reload_stub_apply_changes (MonoImage *base_image, gconstpointer dmeta, uint32_t dmeta_len, gconstpointer dil, uint32_t dil_len, MonoError *error)
hot_reload_stub_apply_changes (MonoImage *base_image, gconstpointer dmeta, uint32_t dmeta_len, gconstpointer dil, uint32_t dil_len, gconstpointer dpdb_bytes_orig, uint32_t dpdb_length, MonoError *error)
{
mono_error_set_not_supported (error, "Hot reload not supported in this runtime.");
}
Expand Down Expand Up @@ -172,6 +176,12 @@ hot_reload_stub_delta_heap_lookup (MonoImage *base_image, MetadataHeapGetterFunc
g_assert_not_reached ();
}

static gpointer
hot_reload_stub_get_updated_method_ppdb (MonoImage *base_image, uint32_t idx)
{
g_assert_not_reached ();
}

MONO_COMPONENT_EXPORT_ENTRYPOINT
MonoComponentHotReload *
mono_component_hot_reload_init (void)
Expand Down
Loading