#include <mono/metadata/gc-internals.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/threads-types.h>
-#include <mono/metadata/threadpool-ms.h>
-#include <mono/metadata/socket-io.h>
+#include <mono/metadata/threadpool.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/runtime.h>
#include <mono/metadata/verify-internals.h>
#include <mono/metadata/reflection-internals.h>
+#include <mono/metadata/w32socket.h>
#include <mono/utils/mono-coop-mutex.h>
#include <mono/utils/mono-coop-semaphore.h>
#include <mono/utils/mono-error-internals.h>
#include "debugger-agent.h"
#include "mini.h"
#include "seq-points.h"
+#include <mono/io-layer/io-layer.h>
/*
* On iOS we can't use System.Environment.Exit () as it will do the wrong
GSList *bps;
/* The number of frames at the start of a step-over */
int nframes;
+ /* If set, don't stop in methods that are not part of user assemblies */
+ MonoAssembly** user_assemblies;
} SingleStepReq;
/*
res = (Id *)g_ptr_array_index (ids [type], GPOINTER_TO_INT (id - 1));
dbg_unlock ();
- if (res->domain == NULL) {
+ if (res->domain == NULL || res->domain->state == MONO_APPDOMAIN_UNLOADED) {
DEBUG_PRINTF (1, "ERR_UNLOADED, id=%d, type=%d.\n", id, type);
*err = ERR_UNLOADED;
return NULL;
/*
* Suspend creation of new threadpool threads, since they cannot run
*/
- mono_threadpool_ms_suspend ();
+ mono_threadpool_suspend ();
mono_loader_unlock ();
}
//g_assert (err == 0);
if (suspend_count == 0)
- mono_threadpool_ms_resume ();
+ mono_threadpool_resume ();
mono_loader_unlock ();
}
if (method->klass == mono_defaults.string_class && (!strcmp (method->name, "memset") || strstr (method->name, "memcpy")))
return;
+ /*
+ * This could be in ss_update method, but mono_find_next_seq_point_for_native_offset is pretty expensive method,
+ * hence we prefer this check here.
+ */
+ if (ss_req->user_assemblies) {
+ gboolean found = FALSE;
+ for (int k = 0; ss_req->user_assemblies[k]; k++)
+ if (ss_req->user_assemblies[k] == method->klass->image->assembly) {
+ found = TRUE;
+ break;
+ }
+ if (!found)
+ return;
+ }
+
+
/*
* The ip points to the instruction causing the single step event, which is before
* the offset recorded in the seq point map, so find the next seq point after ip.
nframes = tls->frame_count;
}
+ /* Need to stop in catch clauses as well */
+ for (i = ss_req->depth == STEP_DEPTH_OUT ? 1 : 0; i < nframes; ++i) {
+ StackFrame *frame = frames [i];
+
+ if (frame->ji) {
+ MonoJitInfo *jinfo = frame->ji;
+ for (j = 0; j < jinfo->num_clauses; ++j) {
+ MonoJitExceptionInfo *ei = &jinfo->clauses [j];
+
+ if (mono_find_next_seq_point_for_native_offset (frame->domain, frame->method, (char*)ei->handler_start - (char*)jinfo->code_start, NULL, &local_sp))
+ ss_bp_add_one (ss_req, &ss_req_bp_count, &ss_req_bp_cache, frame->method, local_sp.il_offset);
+ }
+ }
+ }
+
/*
* Find the first sequence point in the current or in a previous frame which
* is not the last in its method.
ss_req->depth = STEP_DEPTH_INTO;
}
- if (ss_req->depth == STEP_DEPTH_OVER) {
- /* Need to stop in catch clauses as well */
- for (i = 0; i < nframes; ++i) {
- StackFrame *frame = frames [i];
-
- if (frame->ji) {
- MonoJitInfo *jinfo = frame->ji;
- for (j = 0; j < jinfo->num_clauses; ++j) {
- MonoJitExceptionInfo *ei = &jinfo->clauses [j];
-
- found_sp = mono_find_next_seq_point_for_native_offset (frame->domain, frame->method, (char*)ei->handler_start - (char*)jinfo->code_start, NULL, &local_sp);
- sp = (found_sp)? &local_sp : NULL;
-
- if (found_sp)
- ss_bp_add_one (ss_req, &ss_req_bp_count, &ss_req_bp_cache, frame->method, sp->il_offset);
- }
- }
- }
- }
-
if (ss_req->depth == STEP_DEPTH_INTO) {
/* Enable global stepping so we stop at method entry too */
enable_global = TRUE;
ss_req->filter = filter;
req->info = ss_req;
+ for (int i = 0; i < req->nmodifiers; i++) {
+ if (req->modifiers[i].kind == MOD_KIND_ASSEMBLY_ONLY) {
+ ss_req->user_assemblies = req->modifiers[i].data.assemblies;
+ break;
+ }
+ }
+
mono_loader_lock ();
tls = (DebuggerTlsData *)mono_g_hash_table_lookup (thread_to_tls, thread);
mono_loader_unlock ();
}
if (match_count) {
- newassemblies = g_new0 (MonoAssembly*, count - match_count);
+ // +1 because we don't know length and we use last element to check for end
+ newassemblies = g_new0 (MonoAssembly*, count - match_count + 1);
pos = 0;
for (i = 0; i < count; ++i)
int n = decode_int (p, &p, end);
int j;
- req->modifiers [i].data.assemblies = g_new0 (MonoAssembly*, n);
+ // +1 because we don't know length and we use last element to check for end
+ req->modifiers [i].data.assemblies = g_new0 (MonoAssembly*, n + 1);
for (j = 0; j < n; ++j) {
req->modifiers [i].data.assemblies [j] = decode_assemblyid (p, &p, end, &domain, &err);
if (err != ERR_NONE) {
return ERR_NONE;
}
+static ErrorCode
+get_assembly_object_command (MonoDomain *domain, MonoAssembly *ass, Buffer *buf, MonoError *error)
+{
+ HANDLE_FUNCTION_ENTER();
+ ErrorCode err = ERR_NONE;
+ mono_error_init (error);
+ MonoReflectionAssemblyHandle o = mono_assembly_get_object_handle (domain, ass, error);
+ if (MONO_HANDLE_IS_NULL (o)) {
+ err = ERR_INVALID_OBJECT;
+ goto leave;
+ }
+ buffer_add_objid (buf, MONO_HANDLE_RAW (MONO_HANDLE_CAST (MonoObject, o)));
+leave:
+ HANDLE_FUNCTION_RETURN_VAL (err);
+}
+
+
static ErrorCode
assembly_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
{
}
case CMD_ASSEMBLY_GET_OBJECT: {
MonoError error;
- MonoObject *o = (MonoObject*)mono_assembly_get_object_checked (domain, ass, &error);
- if (!o) {
- mono_error_cleanup (&error); /* FIXME don't swallow the error */
- return ERR_INVALID_OBJECT;
- }
- buffer_add_objid (buf, o);
- break;
+ err = get_assembly_object_command (domain, ass, buf, &error);
+ mono_error_cleanup (&error);
+ return err;
}
case CMD_ASSEMBLY_GET_TYPE: {
MonoError error;