Skip to content

Commit

Permalink
[mono][debugger] Improve debugger features (dotnet#94066)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
thaystg authored Nov 22, 2023
1 parent 11076f9 commit 3b4f846
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 74 deletions.
181 changes: 123 additions & 58 deletions src/mono/mono/component/debugger-agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -3787,7 +3787,7 @@ process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx
default:
g_assert_not_reached ();
}
#ifdef HOST_WASI
#ifdef HOST_WASI
resumed_from_wasi = FALSE;
while (suspend_policy != SUSPEND_POLICY_NONE && !resumed_from_wasi)
{
Expand Down Expand Up @@ -4122,7 +4122,14 @@ jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)
dbg_unlock ();

if (assembly) {
process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, assembly);
DebuggerTlsData *tls;
tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id);
if (tls->invoke == NULL) {
process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, assembly);
} else {
assembly_load(prof, assembly); //send later
break;
}
} else {
break;
}
Expand Down Expand Up @@ -5043,20 +5050,16 @@ buffer_add_info_for_null_value (Buffer* buf, MonoType* t, MonoDomain* domain)
{
buffer_add_byte (buf, t->type);
switch (t->type) {
case MONO_TYPE_CLASS:
case MONO_TYPE_STRING:
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
break;
case MONO_TYPE_SZARRAY:
case MONO_TYPE_ARRAY:
buffer_add_byte (buf, m_class_get_byval_arg (m_class_get_element_class (mono_class_from_mono_type_internal (t)))->type);
buffer_add_int (buf, m_class_get_rank (mono_class_from_mono_type_internal (t)));
if (m_class_get_byval_arg (m_class_get_element_class (mono_class_from_mono_type_internal (t)))->type == MONO_TYPE_CLASS)
buffer_add_typeid (buf, domain, m_class_get_element_class (mono_class_from_mono_type_internal (t)));
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
break;
default:
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
case MONO_TYPE_SZARRAY:
case MONO_TYPE_ARRAY:
buffer_add_byte (buf, m_class_get_byval_arg (m_class_get_element_class (mono_class_from_mono_type_internal (t)))->type);
buffer_add_int (buf, m_class_get_rank (mono_class_from_mono_type_internal (t)));
if (m_class_get_byval_arg (m_class_get_element_class (mono_class_from_mono_type_internal (t)))->type == MONO_TYPE_CLASS)
buffer_add_typeid (buf, domain, m_class_get_element_class (mono_class_from_mono_type_internal (t)));
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
break;
default:
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
}
}
/*
Expand All @@ -5073,6 +5076,9 @@ buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain,
MonoObject *obj;
gboolean boxed_vtype = FALSE;

if (CHECK_ICORDBG (TRUE))
buffer_add_byte (buf, !!m_type_is_byref (t));

if (m_type_is_byref (t)) {
if (!(*(void**)addr)) {
/* This can happen with compiler generated locals */
Expand Down Expand Up @@ -5273,6 +5279,8 @@ buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain,
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
{
gssize val = *(gssize*)addr;
if (CHECK_ICORDBG (TRUE))
buffer_add_byte (buf, !!m_type_is_byref (f->type));
buffer_add_byte (buf, MONO_TYPE_PTR);
buffer_add_long (buf, val);
if (CHECK_PROTOCOL_VERSION(2, 46))
Expand Down Expand Up @@ -7092,6 +7100,8 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
minor_version = decode_int (p, &p, end);
if (p < end)
using_icordbg = decode_byte (p, &p, end);
if (using_icordbg)
mono_de_set_using_icordbg ();
protocol_version_set = TRUE;
PRINT_DEBUG_MSG (1, "[dbg] Protocol version %d.%d, client protocol version %d.%d.\n", MAJOR_VERSION, MINOR_VERSION, major_version, minor_version);
break;
Expand All @@ -7115,7 +7125,7 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
wait_for_suspend ();
break;
case CMD_VM_RESUME:
#ifndef HOST_WASI
#ifndef HOST_WASI
if (suspend_count == 0) {
if (agent_config.defer && !agent_config.suspend)
// Workaround for issue in debugger-libs when running in defer attach mode.
Expand Down Expand Up @@ -7703,7 +7713,7 @@ event_commands (int command, guint8 *p, guint8 *end, Buffer *buf)

if (req->event_kind == EVENT_KIND_BREAKPOINT) {
g_assert (method);

req->info = mono_de_set_breakpoint (method, location, req, error);
if (!is_ok (error)) {
g_free (req);
Expand Down Expand Up @@ -7940,6 +7950,42 @@ domain_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
buffer_add_objid (buf, o);
break;
}
case MDBGPROT_CMD_APPDOMAIN_GET_ARRAY_OR_POINTER_TYPE: {
MonoClass *klass;
domain = decode_domainid (p, &p, end, NULL, &err);
MonoTypeEnum type = decode_int (p, &p, end);
klass = decode_typeid (p, &p, end, NULL, &err);
int rank = decode_int (p, &p, end);
if (type == MONO_TYPE_SZARRAY || type == MONO_TYPE_ARRAY)
klass = mono_class_create_array (klass, rank);
else
return ERR_INVALID_ARGUMENT;
buffer_add_typeid (buf, domain, klass);
break;
}

case MDBGPROT_CMD_APPDOMAIN_CREATE_ARRAY: {
ERROR_DECL (error);
MonoClass *klass;
MonoArray *arr;
domain = decode_domainid (p, &p, end, NULL, &err);
klass = decode_typeid (p, &p, end, NULL, &err);
int rank = decode_int (p, &p, end);
uintptr_t *lengths = g_newa (uintptr_t, rank);
intptr_t *lower_bounds = g_newa (intptr_t, rank);
for (int i = 0 ; i < rank; i++)
{
lengths [i] = decode_int (p, &p, end);
}
for (int i = 0 ; i < rank; i++)
{
lower_bounds [i] = decode_int (p, &p, end);
}
arr = mono_array_new_full_checked (klass, lengths, lower_bounds, error);
buffer_add_objid (buf, (MonoObject*) arr);
break;
}

default:
return ERR_NOT_IMPLEMENTED;
}
Expand Down Expand Up @@ -8282,6 +8328,21 @@ field_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
}
break;
}
case MDBGPROT_CMD_FIELD_GET_TOKEN_AND_TYPE: {
MonoClassField *f = decode_fieldid (p, &p, end, &domain, &err);
if (G_UNLIKELY (!f->type)) {
ERROR_DECL(field_error);
mono_field_resolve_type (f, field_error);
mono_error_cleanup (field_error);
if (!f->type)
return ERR_INVALID_OBJECT;
}
buffer_add_int (buf, mono_class_get_field_token (f));
buffer_add_byte(buf, GINT_TO_UINT8(m_class_is_valuetype (mono_class_from_mono_type_internal (f->type))));
buffer_add_int (buf, f->type->type);
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (f->type));
break;
}
default:
return ERR_NOT_IMPLEMENTED;
}
Expand Down Expand Up @@ -8471,6 +8532,19 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint
buffer_add_int (buf, 0);
}
}
if (CHECK_ICORDBG (TRUE))
{
if (type->type == MONO_TYPE_FNPTR)
{
buffer_add_int (buf, 1 + type->data.method->param_count);
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (type->data.method->ret));
for (int j = 0; j < type->data.method->param_count; ++j) {
buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (type->data.method->params[j]));
}
} else {
buffer_add_int (buf, 0);
}
}
break;
}
case CMD_TYPE_GET_METHODS: {
Expand Down Expand Up @@ -8886,43 +8960,8 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint
if (CHECK_ICORDBG (TRUE))
{
buffer_add_byte(buf, GINT_TO_UINT8(m_class_is_valuetype (klass)));
if (m_class_is_valuetype (klass))
{
int nfields = 0;
gpointer iter = NULL;
while ((f = mono_class_get_fields_internal (klass, &iter))) {
if (G_UNLIKELY (!f->type)) {
ERROR_DECL(field_error);
mono_field_resolve_type (f, field_error);
mono_error_cleanup (field_error);
if (!f->type)
continue;
}
if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
continue;
if (mono_field_is_deleted (f))
continue;
nfields ++;
}
buffer_add_int (buf, nfields);

iter = NULL;
while ((f = mono_class_get_fields_internal (klass, &iter))) {
if (G_UNLIKELY (!f->type)) {
ERROR_DECL(field_error);
mono_field_resolve_type (f, field_error);
mono_error_cleanup (field_error);
if (!f->type)
continue;
}
if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
continue;
if (mono_field_is_deleted (f))
continue;
buffer_add_int (buf, mono_class_get_field_token (f));
buffer_add_byte (buf, f->type->type);
}
}
buffer_add_int (buf, m_class_get_byval_arg (klass)->type);
buffer_add_typeid (buf, domain, klass);
}
break;
}
Expand Down Expand Up @@ -9002,6 +9041,33 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint
buffer_add_byte (buf, m_class_get_rank (klass));
break;
}
case MDBGPROT_CMD_TYPE_GET_FIELD_RVA:
{
gpointer iter = NULL;
int field_token = decode_int (p, &p, end);
while ((f = mono_class_get_fields_internal (klass, &iter))) {
if (mono_class_get_field_token (f) == field_token)
{
if (G_UNLIKELY (!f->type)) {
ERROR_DECL(field_error);
mono_field_resolve_type (f, field_error);
mono_error_cleanup (field_error);
if (!f->type)
continue;
}
if (f->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
{
gint32 count = 0;
const char* arr = mono_get_span_data_from_field (f, f->type, f->type, &count);
m_dbgprot_buffer_add_byte_array (buf, (uint8_t *)arr, count);
err = ERR_NONE;
goto exit;
}
}
}
m_dbgprot_buffer_add_int (buf, 0);
break;
}
default:
err = ERR_NOT_IMPLEMENTED;
goto exit;
Expand Down Expand Up @@ -10181,7 +10247,7 @@ array_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
MonoTypeEnum type = m_class_get_byval_arg (m_class_get_element_class (arr->obj.vtable->klass))->type;
buffer_add_byte(buf, type);
buffer_add_int (buf, m_class_get_rank (arr->obj.vtable->klass));
if (type == MONO_TYPE_CLASS || type == MONO_TYPE_GENERICINST || type == MONO_TYPE_OBJECT)
if (type == MONO_TYPE_CLASS || type == MONO_TYPE_GENERICINST || type == MONO_TYPE_OBJECT || (CHECK_ICORDBG (TRUE) && (type == MONO_TYPE_VALUETYPE || type == MONO_TYPE_PTR)))
{
buffer_add_typeid (buf, arr->obj.vtable->domain, m_class_get_element_class (arr->obj.vtable->klass));
if (CHECK_ICORDBG (TRUE))
Expand Down Expand Up @@ -10389,8 +10455,7 @@ object_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
break;
}
}
if (!k)
goto invalid_fieldid;

while ((f = mono_class_get_fields_internal (k, &iter))) {
if (mono_class_get_field_token (f) == field_token) {
goto get_field_value;
Expand Down
28 changes: 24 additions & 4 deletions src/mono/mono/component/debugger-engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ static DebuggerEngineCallbacks rt_callbacks;
static int log_level;
static FILE *log_file;

static bool using_icordbg = FALSE;

/*
* Locking
Expand Down Expand Up @@ -160,6 +161,19 @@ insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo
}
}

if (!it_has_sp && using_icordbg)
{
mono_seq_point_iterator_init (&it, seq_points);
while (mono_seq_point_iterator_next (&it)) {
if (it.seq_point.il_offset != METHOD_ENTRY_IL_OFFSET &&
it.seq_point.il_offset != METHOD_EXIT_IL_OFFSET &&
it.seq_point.il_offset > bp->il_offset) {
it_has_sp = TRUE;
break;
}
}
}

if (!it_has_sp) {
char *s = g_strdup_printf ("Unable to insert breakpoint at %s:%ld", mono_method_full_name (jinfo_get_method (ji), TRUE), bp->il_offset);

Expand Down Expand Up @@ -581,10 +595,10 @@ ss_req_cleanup (void)
void
mono_de_start_single_stepping (void)
{
int val = mono_atomic_inc_i32 (&ss_count);
int val = mono_atomic_inc_i32 (&ss_count);

if (val == 1) {
#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
mono_arch_start_single_stepping ();
#endif
mini_get_interp_callbacks_api ()->start_single_stepping ();
Expand All @@ -594,10 +608,10 @@ mono_de_start_single_stepping (void)
void
mono_de_stop_single_stepping (void)
{
int val = mono_atomic_dec_i32 (&ss_count);
int val = mono_atomic_dec_i32 (&ss_count);

if (val == 0) {
#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
mono_arch_stop_single_stepping ();
#endif
mini_get_interp_callbacks_api ()->stop_single_stepping ();
Expand Down Expand Up @@ -1534,6 +1548,12 @@ mono_de_set_log_level (int level, FILE *file)
log_file = file;
}

void
mono_de_set_using_icordbg ()
{
using_icordbg = TRUE;
}

/*
* mono_de_init:
*
Expand Down
2 changes: 2 additions & 0 deletions src/mono/mono/component/debugger-engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,8 @@ mono_debugger_get_thread_state (DebuggerTlsData *ref);
void mono_de_cleanup (void);
void mono_de_set_log_level (int level, FILE *file);

void mono_de_set_using_icordbg (void);

//locking - we expose the lock object from the debugging engine to ensure we keep the same locking semantics of sdb.
void mono_de_lock (void);
void mono_de_unlock (void);
Expand Down
6 changes: 5 additions & 1 deletion src/mono/mono/component/debugger-protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ typedef enum {
MDBGPROT_CMD_APPDOMAIN_GET_CORLIB = 6,
MDBGPROT_CMD_APPDOMAIN_CREATE_BOXED_VALUE = 7,
MDBGPROT_CMD_APPDOMAIN_CREATE_BYTE_ARRAY = 8,
MDBGPROT_CMD_APPDOMAIN_GET_ARRAY_OR_POINTER_TYPE = 9,
MDBGPROT_CMD_APPDOMAIN_CREATE_ARRAY = 10
} MdbgProtCmdAppDomain;

typedef enum {
Expand Down Expand Up @@ -162,6 +164,7 @@ typedef enum {

typedef enum {
MDBGPROT_CMD_FIELD_GET_INFO = 1,
MDBGPROT_CMD_FIELD_GET_TOKEN_AND_TYPE = 2
} MdbgProtCmdField;

typedef enum {
Expand Down Expand Up @@ -215,7 +218,8 @@ typedef enum {
MDBGPROT_CMD_TYPE_BIND_GENERIC_PARAMETERS = 24,
MDBGPROT_CMD_TYPE_ELEMENT_TYPE = 25,
MDBGPROT_CMD_TYPE_RANK = 26,
MDBGPROT_CMD_TYPE_SET_VALUES_BY_FIELD_TOKEN = 27
MDBGPROT_CMD_TYPE_SET_VALUES_BY_FIELD_TOKEN = 27,
MDBGPROT_CMD_TYPE_GET_FIELD_RVA = 28
} MdbgProtCmdType;

typedef enum {
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/metadata/class-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -1450,7 +1450,7 @@ mono_class_get_object_finalize_slot (void);
MonoMethod *
mono_class_get_default_finalize_method (void);

const char *
MONO_COMPONENT_API const char *
mono_field_get_rva (MonoClassField *field, int swizzle);

MONO_COMPONENT_API void
Expand Down
Loading

0 comments on commit 3b4f846

Please sign in to comment.