Skip to content

Commit

Permalink
Merge pull request #1559 from MoarVM/debug-server-fixes
Browse files Browse the repository at this point in the history
Assorted debug server fixes
  • Loading branch information
jnthn committed Oct 8, 2021
2 parents a6ff2c0 + 86d0a05 commit 1f00f12
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 19 deletions.
60 changes: 46 additions & 14 deletions src/debug/debugserver.c
Expand Up @@ -137,18 +137,27 @@ typedef struct {
} request_data;

static void write_stacktrace_frames(MVMThreadContext *dtc, cmp_ctx_t *ctx, MVMThread *thread);
static MVMint32 request_all_threads_suspend(MVMThreadContext *dtc, cmp_ctx_t *ctx, request_data *argument);
static void request_all_threads_suspend(MVMThreadContext *dtc, cmp_ctx_t *ctx, request_data *argument);
static MVMuint64 allocate_handle(MVMThreadContext *dtc, MVMObject *target);

/* Breakpoint stuff */
void normalize_filename(char *name) {
/* On Windows, we sometimes see forward slashes, sometimes backslashes.
* Normalize them to forward slash so we can reliably hit breakpoints. */
char *cur_bs = strchr(name, '\\');
while (cur_bs) {
*cur_bs = '/';
cur_bs = strchr(cur_bs + 1, '\\');
}
}
MVM_PUBLIC void MVM_debugserver_register_line(MVMThreadContext *tc, char *filename, MVMuint32 filename_len, MVMuint32 line_no, MVMuint32 *file_idx) {
MVMDebugServerData *debugserver = tc->instance->debugserver;
MVMDebugServerBreakpointTable *table = debugserver->breakpoints;
MVMDebugServerBreakpointFileTable *found = NULL;
MVMuint32 index = 0;

normalize_filename(filename);
char *open_paren_pos = (char *)memchr(filename, '(', filename_len);

if (open_paren_pos) {
if (open_paren_pos[-1] == ' ') {
filename_len = open_paren_pos - filename - 1;
Expand Down Expand Up @@ -662,7 +671,7 @@ static MVMint32 request_thread_suspends(MVMThreadContext *dtc, cmp_ctx_t *ctx, r
}

if (argument && argument->type == MT_SuspendOne)
communicate_success(tc, ctx, argument);
communicate_success(tc, ctx, argument);

MVM_gc_mark_thread_unblocked(dtc);
if (tc->instance->debugserver->debugspam_protocol)
Expand All @@ -671,7 +680,7 @@ static MVMint32 request_thread_suspends(MVMThreadContext *dtc, cmp_ctx_t *ctx, r
return 0;
}

static MVMint32 request_all_threads_suspend(MVMThreadContext *dtc, cmp_ctx_t *ctx, request_data *argument) {
static void request_all_threads_suspend(MVMThreadContext *dtc, cmp_ctx_t *ctx, request_data *argument) {
MVMInstance *vm = dtc->instance;
MVMThread *cur_thread = 0;
MVMuint32 success = 1;
Expand Down Expand Up @@ -702,14 +711,13 @@ static MVMint32 request_all_threads_suspend(MVMThreadContext *dtc, cmp_ctx_t *ct
communicate_error(dtc, ctx, argument);

uv_mutex_unlock(&vm->mutex_threads);

return success;
}

static MVMint32 request_thread_resumes(MVMThreadContext *dtc, cmp_ctx_t *ctx, request_data *argument, MVMThread *thread) {
MVMInstance *vm = dtc->instance;
MVMThread *to_do = thread ? thread : find_thread_by_id(vm, argument->thread_id);
MVMThreadContext *tc = to_do ? to_do->body.tc : NULL;
MVMint32 is_one = !argument || argument->type != MT_ResumeAll;
AO_t current;

if (!tc) {
Expand All @@ -732,7 +740,11 @@ static MVMint32 request_thread_resumes(MVMThreadContext *dtc, cmp_ctx_t *ctx, re
/* Success! We signalled the thread and can now tell it to
* mark itself unblocked, which takes care of any looming GC
* and related business. */
uv_cond_broadcast(&vm->debugserver->tell_threads);
if (is_one) {
uv_mutex_lock(&vm->debugserver->mutex_cond);
uv_cond_broadcast(&vm->debugserver->tell_threads);
uv_mutex_unlock(&vm->debugserver->mutex_cond);
}
break;
} else if ((current & MVMGCSTATUS_MASK) == MVMGCStatus_STOLEN) {
uv_mutex_lock(&tc->instance->mutex_gc_orchestrate);
Expand All @@ -742,17 +754,23 @@ static MVMint32 request_thread_resumes(MVMThreadContext *dtc, cmp_ctx_t *ctx, re
}
uv_mutex_unlock(&tc->instance->mutex_gc_orchestrate);
} else {
/* Suspend request wasn't handled during the suspended time. */
if (current == (MVMGCStatus_UNABLE | MVMSuspendState_SUSPEND_REQUEST)) {
if (MVM_cas(&tc->gc_status, current, MVMGCStatus_UNABLE) == current) {
break;
}
}
else if (current == (MVMGCStatus_INTERRUPT | MVMSuspendState_SUSPEND_REQUEST)) {
if (MVM_cas(&tc->gc_status, current, MVMGCStatus_NONE) == current) {
break;
}
}
}
}

MVM_gc_mark_thread_unblocked(dtc);

if (argument && argument->type == MT_ResumeOne)
if (is_one)
communicate_success(tc, ctx, argument);

if (tc->instance->debugserver->debugspam_protocol)
Expand All @@ -761,7 +779,7 @@ static MVMint32 request_thread_resumes(MVMThreadContext *dtc, cmp_ctx_t *ctx, re
return 0;
}

static MVMint32 request_all_threads_resume(MVMThreadContext *dtc, cmp_ctx_t *ctx, request_data *argument) {
static void request_all_threads_resume(MVMThreadContext *dtc, cmp_ctx_t *ctx, request_data *argument) {
MVMInstance *vm = dtc->instance;
MVMThread *cur_thread = 0;
MVMuint8 success = 1;
Expand All @@ -773,6 +791,7 @@ static MVMint32 request_all_threads_resume(MVMThreadContext *dtc, cmp_ctx_t *ctx
if (cur_thread != dtc->thread_obj) {
AO_t current = MVM_load(&cur_thread->body.tc->gc_status);
if (current == (MVMGCStatus_UNABLE | MVMSuspendState_SUSPENDED) ||
current == (MVMGCStatus_UNABLE | MVMSuspendState_SUSPEND_REQUEST) ||
current == (MVMGCStatus_INTERRUPT | MVMSuspendState_SUSPEND_REQUEST) ||
current == (MVMGCStatus_STOLEN | MVMSuspendState_SUSPEND_REQUEST)) {
if (request_thread_resumes(dtc, ctx, argument, cur_thread)) {
Expand All @@ -787,14 +806,16 @@ static MVMint32 request_all_threads_resume(MVMThreadContext *dtc, cmp_ctx_t *ctx
}
});

uv_mutex_lock(&vm->debugserver->mutex_cond);
uv_cond_broadcast(&vm->debugserver->tell_threads);
uv_mutex_unlock(&vm->debugserver->mutex_cond);

if (success)
communicate_success(dtc, ctx, argument);
else
communicate_error(dtc, ctx, argument);

uv_mutex_unlock(&vm->mutex_threads);

return !success;
}

static void write_stacktrace_frames(MVMThreadContext *dtc, cmp_ctx_t *ctx, MVMThread *thread) {
Expand Down Expand Up @@ -985,10 +1006,15 @@ MVMuint8 setup_step(MVMThreadContext *dtc, cmp_ctx_t *ctx, request_data *argumen
MVMThread *to_do = thread ? thread : find_thread_by_id(dtc->instance, argument->thread_id);
MVMThreadContext *tc;

if (!to_do)
if (!to_do) {
if (tc->instance->debugserver->debugspam_protocol)
fprintf(stderr, "Setting up step failed: no thread found\n");
return 1;
}

if ((to_do->body.tc->gc_status & MVMGCSTATUS_MASK) != MVMGCStatus_UNABLE) {
if (tc->instance->debugserver->debugspam_protocol)
fprintf(stderr, "Setting up step failed: thread has wrong status\n");
return 1;
}

Expand All @@ -1000,6 +1026,9 @@ MVMuint8 setup_step(MVMThreadContext *dtc, cmp_ctx_t *ctx, request_data *argumen

tc->step_mode = mode;

if (tc->instance->debugserver->debugspam_protocol)
fprintf(stderr, "Setting up step successful, going to resume\n");

request_thread_resumes(dtc, ctx, NULL, to_do);

return 0;
Expand Down Expand Up @@ -1661,7 +1690,9 @@ static MVMuint64 request_invoke_code(MVMThreadContext *dtc, cmp_ctx_t *ctx, requ

MVM_store(&debugserver->request_data.status, MVM_DebugRequestStatus_sender_is_waiting);

uv_mutex_lock(&debugserver->mutex_cond);
uv_cond_broadcast(&debugserver->tell_threads);
uv_mutex_unlock(&debugserver->mutex_cond);

while (1) {
if (MVM_cas(&debugserver->request_data.status,
Expand Down Expand Up @@ -2989,6 +3020,7 @@ MVMint32 parse_message_map(MVMThreadContext *tc, cmp_ctx_t *ctx, request_data *d

switch (field_to_set) {
case FS_file:
normalize_filename(string);
data->file = string;
break;
case FS_name:
Expand Down Expand Up @@ -3266,10 +3298,10 @@ static void debugserver_worker(MVMThreadContext *tc, MVMArgs arg_info) {
send_is_execution_suspended_info(tc, &ctx, &argument);
break;
case MT_SuspendAll:
COMMUNICATE_ERROR(request_all_threads_suspend(tc, &ctx, &argument));
request_all_threads_suspend(tc, &ctx, &argument);
break;
case MT_ResumeAll:
COMMUNICATE_ERROR(request_all_threads_resume(tc, &ctx, &argument));
request_all_threads_resume(tc, &ctx, &argument);
break;
case MT_SuspendOne:
COMMUNICATE_ERROR(request_thread_suspends(tc, &ctx, &argument, NULL));
Expand Down
13 changes: 9 additions & 4 deletions src/gc/orchestrate.c
Expand Up @@ -355,7 +355,8 @@ void MVM_gc_mark_thread_unblocked(MVMThreadContext *tc) {
}
}
} else if (MVM_load(&tc->gc_status) == MVMGCStatus_NONE) {
fprintf(stderr, "marking thread %d unblocked, but its status is already NONE.\n", tc->thread_id);
if (tc->instance->debugserver && tc->instance->debugserver->debugspam_protocol)
fprintf(stderr, "marking thread %d unblocked, but its status is already NONE.\n", tc->thread_id);
break;
} else {
MVM_platform_thread_yield();
Expand Down Expand Up @@ -624,7 +625,7 @@ void MVM_gc_enter_from_allocator(MVMThreadContext *tc) {
* MVMSUSPENDSTATUS_MASK.
* */
static int react_to_debugserver_request(MVMThreadContext *tc) {
if (tc->instance->debugserver->debugspam_protocol)
if (tc->instance->debugserver && tc->instance->debugserver->debugspam_protocol)
fprintf(stderr, "thread %p has received a request.\n", tc);

MVMDebugServerRequestKind kind = tc->instance->debugserver->request_data.kind;
Expand All @@ -647,15 +648,17 @@ static int react_to_debugserver_request(MVMThreadContext *tc) {
MVM_gc_mark_thread_blocked(tc);
}
else {
fprintf(stderr, "this debug request kind not implemented: %d\n", kind);
if (tc->instance->debugserver && tc->instance->debugserver->debugspam_protocol)
fprintf(stderr, "this debug request kind not implemented: %d\n", kind);
return 0;
}

if (MVM_cas(&tc->instance->debugserver->request_data.status,
MVM_DebugRequestStatus_sender_is_waiting,
MVM_DebugRequestStatus_receiver_acknowledged)
!= MVM_DebugRequestStatus_sender_is_waiting) {
fprintf(stderr, "could not acknowledge request?!?\n");
if (tc->instance->debugserver && tc->instance->debugserver->debugspam_protocol)
fprintf(stderr, "could not acknowledge request?!?\n");
}
tc->instance->debugserver->request_data.kind = MVM_DebugRequest_empty;

Expand All @@ -670,7 +673,9 @@ void MVM_gc_enter_from_interrupt(MVMThreadContext *tc) {
fprintf(stderr, "thread %d reacting to suspend request\n", tc->thread_id);
MVM_gc_mark_thread_blocked(tc);
while (1) {
uv_mutex_lock(&tc->instance->debugserver->mutex_cond);
uv_cond_wait(&tc->instance->debugserver->tell_threads, &tc->instance->debugserver->mutex_cond);
uv_mutex_unlock(&tc->instance->debugserver->mutex_cond);
if ((MVM_load(&tc->gc_status) & MVMSUSPENDSTATUS_MASK) == MVMSuspendState_NONE) {
if (tc->instance->debugserver && tc->instance->debugserver->debugspam_protocol)
fprintf(stderr, "thread %d got un-suspended\n", tc->thread_id);
Expand Down
4 changes: 3 additions & 1 deletion src/instrument/line_coverage.c
Expand Up @@ -8,6 +8,7 @@ static void instrument_graph_with_breakpoints(MVMThreadContext *tc, MVMSpeshGrap
MVMSpeshBB *bb = g->entry->linear_next;

MVMint32 last_filename = -1;
MVMint64 last_line_number = -1;

char *filename_buf = NULL;

Expand Down Expand Up @@ -46,7 +47,7 @@ static void instrument_graph_with_breakpoints(MVMThreadContext *tc, MVMSpeshGrap
continue;
}

if (line_number >= 0) {
if (line_number >= 0 && line_number != last_line_number) {
breakpoint_ins = MVM_spesh_alloc(tc, g, sizeof(MVMSpeshIns));
breakpoint_ins->info = MVM_op_get_op(MVM_OP_breakpoint);
breakpoint_ins->operands = MVM_spesh_alloc(tc, g, 2 * sizeof(MVMSpeshOperand));
Expand All @@ -63,6 +64,7 @@ static void instrument_graph_with_breakpoints(MVMThreadContext *tc, MVMSpeshGrap
breakpoint_ins->operands[1].lit_i32 = line_number;

last_filename = filename_string_index;
last_line_number = line_number;

MVM_spesh_manipulate_insert_ins(tc, bb, ins->prev, breakpoint_ins);
}
Expand Down

0 comments on commit 1f00f12

Please sign in to comment.