Skip to content

Commit 3b4f846

Browse files
authored
[mono][debugger] Improve debugger features (#94066)
* Creating new messages, changing some olds, and fixing when jit_end is called while running a invoke_method * Fix compilation error * Fix compilation * Applying suggestions from @lambdageek and adding more changes. * Addressing @lambdageek suggestions. * Addressing @lambdageek comment * Addressing @lambdageek comments * adding mono_component_api to function added.
1 parent 11076f9 commit 3b4f846

File tree

8 files changed

+173
-74
lines changed

8 files changed

+173
-74
lines changed

src/mono/mono/component/debugger-agent.c

Lines changed: 123 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3787,7 +3787,7 @@ process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx
37873787
default:
37883788
g_assert_not_reached ();
37893789
}
3790-
#ifdef HOST_WASI
3790+
#ifdef HOST_WASI
37913791
resumed_from_wasi = FALSE;
37923792
while (suspend_policy != SUSPEND_POLICY_NONE && !resumed_from_wasi)
37933793
{
@@ -4122,7 +4122,14 @@ jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)
41224122
dbg_unlock ();
41234123

41244124
if (assembly) {
4125-
process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, assembly);
4125+
DebuggerTlsData *tls;
4126+
tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id);
4127+
if (tls->invoke == NULL) {
4128+
process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, assembly);
4129+
} else {
4130+
assembly_load(prof, assembly); //send later
4131+
break;
4132+
}
41264133
} else {
41274134
break;
41284135
}
@@ -5043,20 +5050,16 @@ buffer_add_info_for_null_value (Buffer* buf, MonoType* t, MonoDomain* domain)
50435050
{
50445051
buffer_add_byte (buf, t->type);
50455052
switch (t->type) {
5046-
case MONO_TYPE_CLASS:
5047-
case MONO_TYPE_STRING:
5048-
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
5049-
break;
5050-
case MONO_TYPE_SZARRAY:
5051-
case MONO_TYPE_ARRAY:
5052-
buffer_add_byte (buf, m_class_get_byval_arg (m_class_get_element_class (mono_class_from_mono_type_internal (t)))->type);
5053-
buffer_add_int (buf, m_class_get_rank (mono_class_from_mono_type_internal (t)));
5054-
if (m_class_get_byval_arg (m_class_get_element_class (mono_class_from_mono_type_internal (t)))->type == MONO_TYPE_CLASS)
5055-
buffer_add_typeid (buf, domain, m_class_get_element_class (mono_class_from_mono_type_internal (t)));
5056-
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
5057-
break;
5058-
default:
5059-
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
5053+
case MONO_TYPE_SZARRAY:
5054+
case MONO_TYPE_ARRAY:
5055+
buffer_add_byte (buf, m_class_get_byval_arg (m_class_get_element_class (mono_class_from_mono_type_internal (t)))->type);
5056+
buffer_add_int (buf, m_class_get_rank (mono_class_from_mono_type_internal (t)));
5057+
if (m_class_get_byval_arg (m_class_get_element_class (mono_class_from_mono_type_internal (t)))->type == MONO_TYPE_CLASS)
5058+
buffer_add_typeid (buf, domain, m_class_get_element_class (mono_class_from_mono_type_internal (t)));
5059+
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
5060+
break;
5061+
default:
5062+
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
50605063
}
50615064
}
50625065
/*
@@ -5073,6 +5076,9 @@ buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain,
50735076
MonoObject *obj;
50745077
gboolean boxed_vtype = FALSE;
50755078

5079+
if (CHECK_ICORDBG (TRUE))
5080+
buffer_add_byte (buf, !!m_type_is_byref (t));
5081+
50765082
if (m_type_is_byref (t)) {
50775083
if (!(*(void**)addr)) {
50785084
/* This can happen with compiler generated locals */
@@ -5273,6 +5279,8 @@ buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain,
52735279
if (mono_vtype_get_field_addr (addr, f) == addr && mono_class_from_mono_type_internal (t) == mono_class_from_mono_type_internal (f->type) && !boxed_vtype) //to avoid infinite recursion
52745280
{
52755281
gssize val = *(gssize*)addr;
5282+
if (CHECK_ICORDBG (TRUE))
5283+
buffer_add_byte (buf, !!m_type_is_byref (f->type));
52765284
buffer_add_byte (buf, MONO_TYPE_PTR);
52775285
buffer_add_long (buf, val);
52785286
if (CHECK_PROTOCOL_VERSION(2, 46))
@@ -7092,6 +7100,8 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
70927100
minor_version = decode_int (p, &p, end);
70937101
if (p < end)
70947102
using_icordbg = decode_byte (p, &p, end);
7103+
if (using_icordbg)
7104+
mono_de_set_using_icordbg ();
70957105
protocol_version_set = TRUE;
70967106
PRINT_DEBUG_MSG (1, "[dbg] Protocol version %d.%d, client protocol version %d.%d.\n", MAJOR_VERSION, MINOR_VERSION, major_version, minor_version);
70977107
break;
@@ -7115,7 +7125,7 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
71157125
wait_for_suspend ();
71167126
break;
71177127
case CMD_VM_RESUME:
7118-
#ifndef HOST_WASI
7128+
#ifndef HOST_WASI
71197129
if (suspend_count == 0) {
71207130
if (agent_config.defer && !agent_config.suspend)
71217131
// Workaround for issue in debugger-libs when running in defer attach mode.
@@ -7703,7 +7713,7 @@ event_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
77037713

77047714
if (req->event_kind == EVENT_KIND_BREAKPOINT) {
77057715
g_assert (method);
7706-
7716+
77077717
req->info = mono_de_set_breakpoint (method, location, req, error);
77087718
if (!is_ok (error)) {
77097719
g_free (req);
@@ -7940,6 +7950,42 @@ domain_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
79407950
buffer_add_objid (buf, o);
79417951
break;
79427952
}
7953+
case MDBGPROT_CMD_APPDOMAIN_GET_ARRAY_OR_POINTER_TYPE: {
7954+
MonoClass *klass;
7955+
domain = decode_domainid (p, &p, end, NULL, &err);
7956+
MonoTypeEnum type = decode_int (p, &p, end);
7957+
klass = decode_typeid (p, &p, end, NULL, &err);
7958+
int rank = decode_int (p, &p, end);
7959+
if (type == MONO_TYPE_SZARRAY || type == MONO_TYPE_ARRAY)
7960+
klass = mono_class_create_array (klass, rank);
7961+
else
7962+
return ERR_INVALID_ARGUMENT;
7963+
buffer_add_typeid (buf, domain, klass);
7964+
break;
7965+
}
7966+
7967+
case MDBGPROT_CMD_APPDOMAIN_CREATE_ARRAY: {
7968+
ERROR_DECL (error);
7969+
MonoClass *klass;
7970+
MonoArray *arr;
7971+
domain = decode_domainid (p, &p, end, NULL, &err);
7972+
klass = decode_typeid (p, &p, end, NULL, &err);
7973+
int rank = decode_int (p, &p, end);
7974+
uintptr_t *lengths = g_newa (uintptr_t, rank);
7975+
intptr_t *lower_bounds = g_newa (intptr_t, rank);
7976+
for (int i = 0 ; i < rank; i++)
7977+
{
7978+
lengths [i] = decode_int (p, &p, end);
7979+
}
7980+
for (int i = 0 ; i < rank; i++)
7981+
{
7982+
lower_bounds [i] = decode_int (p, &p, end);
7983+
}
7984+
arr = mono_array_new_full_checked (klass, lengths, lower_bounds, error);
7985+
buffer_add_objid (buf, (MonoObject*) arr);
7986+
break;
7987+
}
7988+
79437989
default:
79447990
return ERR_NOT_IMPLEMENTED;
79457991
}
@@ -8282,6 +8328,21 @@ field_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
82828328
}
82838329
break;
82848330
}
8331+
case MDBGPROT_CMD_FIELD_GET_TOKEN_AND_TYPE: {
8332+
MonoClassField *f = decode_fieldid (p, &p, end, &domain, &err);
8333+
if (G_UNLIKELY (!f->type)) {
8334+
ERROR_DECL(field_error);
8335+
mono_field_resolve_type (f, field_error);
8336+
mono_error_cleanup (field_error);
8337+
if (!f->type)
8338+
return ERR_INVALID_OBJECT;
8339+
}
8340+
buffer_add_int (buf, mono_class_get_field_token (f));
8341+
buffer_add_byte(buf, GINT_TO_UINT8(m_class_is_valuetype (mono_class_from_mono_type_internal (f->type))));
8342+
buffer_add_int (buf, f->type->type);
8343+
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (f->type));
8344+
break;
8345+
}
82858346
default:
82868347
return ERR_NOT_IMPLEMENTED;
82878348
}
@@ -8471,6 +8532,19 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint
84718532
buffer_add_int (buf, 0);
84728533
}
84738534
}
8535+
if (CHECK_ICORDBG (TRUE))
8536+
{
8537+
if (type->type == MONO_TYPE_FNPTR)
8538+
{
8539+
buffer_add_int (buf, 1 + type->data.method->param_count);
8540+
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (type->data.method->ret));
8541+
for (int j = 0; j < type->data.method->param_count; ++j) {
8542+
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (type->data.method->params[j]));
8543+
}
8544+
} else {
8545+
buffer_add_int (buf, 0);
8546+
}
8547+
}
84748548
break;
84758549
}
84768550
case CMD_TYPE_GET_METHODS: {
@@ -8886,43 +8960,8 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint
88868960
if (CHECK_ICORDBG (TRUE))
88878961
{
88888962
buffer_add_byte(buf, GINT_TO_UINT8(m_class_is_valuetype (klass)));
8889-
if (m_class_is_valuetype (klass))
8890-
{
8891-
int nfields = 0;
8892-
gpointer iter = NULL;
8893-
while ((f = mono_class_get_fields_internal (klass, &iter))) {
8894-
if (G_UNLIKELY (!f->type)) {
8895-
ERROR_DECL(field_error);
8896-
mono_field_resolve_type (f, field_error);
8897-
mono_error_cleanup (field_error);
8898-
if (!f->type)
8899-
continue;
8900-
}
8901-
if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
8902-
continue;
8903-
if (mono_field_is_deleted (f))
8904-
continue;
8905-
nfields ++;
8906-
}
8907-
buffer_add_int (buf, nfields);
8908-
8909-
iter = NULL;
8910-
while ((f = mono_class_get_fields_internal (klass, &iter))) {
8911-
if (G_UNLIKELY (!f->type)) {
8912-
ERROR_DECL(field_error);
8913-
mono_field_resolve_type (f, field_error);
8914-
mono_error_cleanup (field_error);
8915-
if (!f->type)
8916-
continue;
8917-
}
8918-
if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
8919-
continue;
8920-
if (mono_field_is_deleted (f))
8921-
continue;
8922-
buffer_add_int (buf, mono_class_get_field_token (f));
8923-
buffer_add_byte (buf, f->type->type);
8924-
}
8925-
}
8963+
buffer_add_int (buf, m_class_get_byval_arg (klass)->type);
8964+
buffer_add_typeid (buf, domain, klass);
89268965
}
89278966
break;
89288967
}
@@ -9002,6 +9041,33 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint
90029041
buffer_add_byte (buf, m_class_get_rank (klass));
90039042
break;
90049043
}
9044+
case MDBGPROT_CMD_TYPE_GET_FIELD_RVA:
9045+
{
9046+
gpointer iter = NULL;
9047+
int field_token = decode_int (p, &p, end);
9048+
while ((f = mono_class_get_fields_internal (klass, &iter))) {
9049+
if (mono_class_get_field_token (f) == field_token)
9050+
{
9051+
if (G_UNLIKELY (!f->type)) {
9052+
ERROR_DECL(field_error);
9053+
mono_field_resolve_type (f, field_error);
9054+
mono_error_cleanup (field_error);
9055+
if (!f->type)
9056+
continue;
9057+
}
9058+
if (f->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
9059+
{
9060+
gint32 count = 0;
9061+
const char* arr = mono_get_span_data_from_field (f, f->type, f->type, &count);
9062+
m_dbgprot_buffer_add_byte_array (buf, (uint8_t *)arr, count);
9063+
err = ERR_NONE;
9064+
goto exit;
9065+
}
9066+
}
9067+
}
9068+
m_dbgprot_buffer_add_int (buf, 0);
9069+
break;
9070+
}
90059071
default:
90069072
err = ERR_NOT_IMPLEMENTED;
90079073
goto exit;
@@ -10181,7 +10247,7 @@ array_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
1018110247
MonoTypeEnum type = m_class_get_byval_arg (m_class_get_element_class (arr->obj.vtable->klass))->type;
1018210248
buffer_add_byte(buf, type);
1018310249
buffer_add_int (buf, m_class_get_rank (arr->obj.vtable->klass));
10184-
if (type == MONO_TYPE_CLASS || type == MONO_TYPE_GENERICINST || type == MONO_TYPE_OBJECT)
10250+
if (type == MONO_TYPE_CLASS || type == MONO_TYPE_GENERICINST || type == MONO_TYPE_OBJECT || (CHECK_ICORDBG (TRUE) && (type == MONO_TYPE_VALUETYPE || type == MONO_TYPE_PTR)))
1018510251
{
1018610252
buffer_add_typeid (buf, arr->obj.vtable->domain, m_class_get_element_class (arr->obj.vtable->klass));
1018710253
if (CHECK_ICORDBG (TRUE))
@@ -10389,8 +10455,7 @@ object_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
1038910455
break;
1039010456
}
1039110457
}
10392-
if (!k)
10393-
goto invalid_fieldid;
10458+
1039410459
while ((f = mono_class_get_fields_internal (k, &iter))) {
1039510460
if (mono_class_get_field_token (f) == field_token) {
1039610461
goto get_field_value;

src/mono/mono/component/debugger-engine.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ static DebuggerEngineCallbacks rt_callbacks;
3535
static int log_level;
3636
static FILE *log_file;
3737

38+
static bool using_icordbg = FALSE;
3839

3940
/*
4041
* Locking
@@ -160,6 +161,19 @@ insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo
160161
}
161162
}
162163

164+
if (!it_has_sp && using_icordbg)
165+
{
166+
mono_seq_point_iterator_init (&it, seq_points);
167+
while (mono_seq_point_iterator_next (&it)) {
168+
if (it.seq_point.il_offset != METHOD_ENTRY_IL_OFFSET &&
169+
it.seq_point.il_offset != METHOD_EXIT_IL_OFFSET &&
170+
it.seq_point.il_offset > bp->il_offset) {
171+
it_has_sp = TRUE;
172+
break;
173+
}
174+
}
175+
}
176+
163177
if (!it_has_sp) {
164178
char *s = g_strdup_printf ("Unable to insert breakpoint at %s:%ld", mono_method_full_name (jinfo_get_method (ji), TRUE), bp->il_offset);
165179

@@ -581,10 +595,10 @@ ss_req_cleanup (void)
581595
void
582596
mono_de_start_single_stepping (void)
583597
{
584-
int val = mono_atomic_inc_i32 (&ss_count);
598+
int val = mono_atomic_inc_i32 (&ss_count);
585599

586600
if (val == 1) {
587-
#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
601+
#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
588602
mono_arch_start_single_stepping ();
589603
#endif
590604
mini_get_interp_callbacks_api ()->start_single_stepping ();
@@ -594,10 +608,10 @@ mono_de_start_single_stepping (void)
594608
void
595609
mono_de_stop_single_stepping (void)
596610
{
597-
int val = mono_atomic_dec_i32 (&ss_count);
611+
int val = mono_atomic_dec_i32 (&ss_count);
598612

599613
if (val == 0) {
600-
#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
614+
#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
601615
mono_arch_stop_single_stepping ();
602616
#endif
603617
mini_get_interp_callbacks_api ()->stop_single_stepping ();
@@ -1534,6 +1548,12 @@ mono_de_set_log_level (int level, FILE *file)
15341548
log_file = file;
15351549
}
15361550

1551+
void
1552+
mono_de_set_using_icordbg ()
1553+
{
1554+
using_icordbg = TRUE;
1555+
}
1556+
15371557
/*
15381558
* mono_de_init:
15391559
*

src/mono/mono/component/debugger-engine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,8 @@ mono_debugger_get_thread_state (DebuggerTlsData *ref);
345345
void mono_de_cleanup (void);
346346
void mono_de_set_log_level (int level, FILE *file);
347347

348+
void mono_de_set_using_icordbg (void);
349+
348350
//locking - we expose the lock object from the debugging engine to ensure we keep the same locking semantics of sdb.
349351
void mono_de_lock (void);
350352
void mono_de_unlock (void);

src/mono/mono/component/debugger-protocol.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ typedef enum {
132132
MDBGPROT_CMD_APPDOMAIN_GET_CORLIB = 6,
133133
MDBGPROT_CMD_APPDOMAIN_CREATE_BOXED_VALUE = 7,
134134
MDBGPROT_CMD_APPDOMAIN_CREATE_BYTE_ARRAY = 8,
135+
MDBGPROT_CMD_APPDOMAIN_GET_ARRAY_OR_POINTER_TYPE = 9,
136+
MDBGPROT_CMD_APPDOMAIN_CREATE_ARRAY = 10
135137
} MdbgProtCmdAppDomain;
136138

137139
typedef enum {
@@ -162,6 +164,7 @@ typedef enum {
162164

163165
typedef enum {
164166
MDBGPROT_CMD_FIELD_GET_INFO = 1,
167+
MDBGPROT_CMD_FIELD_GET_TOKEN_AND_TYPE = 2
165168
} MdbgProtCmdField;
166169

167170
typedef enum {
@@ -215,7 +218,8 @@ typedef enum {
215218
MDBGPROT_CMD_TYPE_BIND_GENERIC_PARAMETERS = 24,
216219
MDBGPROT_CMD_TYPE_ELEMENT_TYPE = 25,
217220
MDBGPROT_CMD_TYPE_RANK = 26,
218-
MDBGPROT_CMD_TYPE_SET_VALUES_BY_FIELD_TOKEN = 27
221+
MDBGPROT_CMD_TYPE_SET_VALUES_BY_FIELD_TOKEN = 27,
222+
MDBGPROT_CMD_TYPE_GET_FIELD_RVA = 28
219223
} MdbgProtCmdType;
220224

221225
typedef enum {

src/mono/mono/metadata/class-internals.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1450,7 +1450,7 @@ mono_class_get_object_finalize_slot (void);
14501450
MonoMethod *
14511451
mono_class_get_default_finalize_method (void);
14521452

1453-
const char *
1453+
MONO_COMPONENT_API const char *
14541454
mono_field_get_rva (MonoClassField *field, int swizzle);
14551455

14561456
MONO_COMPONENT_API void

0 commit comments

Comments
 (0)