Index: src/session_asm.s =================================================================== --- src/session_asm.s (revision 3781) +++ src/session_asm.s (working copy) @@ -39,14 +39,38 @@ @ SWI vector handler .globl swi_handler swi_handler: - STMFD r13!, {r0, r1} + STMFD r13!, {r0-r12, r14} MRS r1, SPSR + STR r1, [r13, #-4]! @ Save SPSR + ANDS r1, r1, #0xf @ not called from USR => bail MOVNE r0, #0 LDREQ r0, current_session TEQ r0, #0 @ current_session == NULL => bail - STRNE r1, [r0] @ save return address into session - LDMIA r13!, {r0, r1} + BEQ 1f + + SUB r13, r13, #8 + STMIA r13, {r13, r14}^ @ Save USR r13 + r14 + NOP + + STR r14, [r0] @ save return address into session + + LDR r1, [r14, #-4] @ read SWI instruction + BIC r1, r1, #0xff000000 @ clear uninteresting bits + BIC r1, r1, #0x00020000 @ clear X + MOV r2, #0x40000 + ORR r2, r2, #0xc0 + TEQ r1, r2 @ (X)Wimp_Initialise? + @ r0 -> current_session + BLEQ session_wimp_initialise + + LDMIA r13, {r13, r14}^ @ Restore USR r13 + r14 + ADD r13, r13, #8 + +1: + LDR r1, [r13], #4 + MSR SPSR, r1 @ Restore SPSR + LDMIA r13!, {r0-r12, r14} LDR pc, prev_swi_vector @ pass on to previous claimant @@ -107,6 +131,7 @@ LDREQ pc, prev_dabort_vector @ current_session == NULL => bail STMIB r0, {r0-r14}^ @ Save USR mode's r0-r14 + NOP LDR r1, [r13] STR r1, [r0, #4] @ Fix up saved r0 @@ -207,6 +232,7 @@ LDREQ pc, prev_prefetch_vector@ current_session == NULL => bail STMIB r0, {r0-r14}^ @ Save USR mode's r0-r14 + NOP LDR r1, [r13] STR r1, [r0, #4] @ Fix up saved r0 @@ -321,6 +347,7 @@ LDR r1, [r13, #4] @ Restore aborted r1 STMIB r0, {r0-r14}^ @ Save USR mode's r0-r14 + NOP LDR r1, [r13] STR r1, [r0, #4] @ Fix up saved r0 Index: src/session.c =================================================================== --- src/session.c (revision 3780) +++ src/session.c (working copy) @@ -14,7 +14,7 @@ #include "step.h" #include "utils.h" -static const char post_filter_name[] = "GDBServer"; +static const char session_filter_name[] = "GDBServer"; /* Ideally, keep this synced with N_CTX in gdb.c */ #define MAX_SESSIONS 5 @@ -145,8 +145,11 @@ } if (ctx->task_handle != 0) { + _swix(Filter_DeRegisterPreFilter, _INR(0,3), + session_filter_name, session_pre_poll, + ctx->pw, ctx->task_handle); _swix(Filter_DeRegisterPostFilter, _INR(0,4), - post_filter_name, session_post_poll, + session_filter_name, session_post_poll, ctx->pw, ctx->task_handle, 0); } @@ -229,11 +232,15 @@ { session_ctx *session = (session_ctx *) ctx; + debug("Current break state: %d\n", session->brk); + /* Ignore any attempts to break while we're paused */ if (session->brk == 1) return 0; if (session == session_get_current()) { + debug("Session is current%s", ""); + /* Inject bkpt, so debuggee breaks on resumption */ if (session_set_bkpt(ctx, session->cur_pc | BKPT_ONE_SHOT) == 0) @@ -433,28 +440,75 @@ ctx->env_ctx[2].buf); } -void session_set_task_handle(session_ctx *ctx, uint32_t task) +void session_wimp_initialise(session_ctx *ctx) { - /* Not us, if we've already got a task handle */ + /* Important: This function (and those called by it), *must* not + * attempt to access non-automatic variables (i.e. globals) or call + * SCL functions. + * The magic words at the bottom of the SVC stack are not set up + * by our exception handlers so relocations will fail. + */ + + /* Ignore this if we already have a task handle */ if (ctx->task_handle != 0) return; + /* Add a callback to grab the task handle and register filters */ + _swix(OS_AddCallBack, _INR(0,1), post_wimp_initialise, ctx->pw); +} + +_kernel_oserror *post_wimp_initialise_handler(_kernel_swi_regs *r, void *pw) +{ + session_ctx *ctx = session_get_current(); + _kernel_oserror *error; + uint32_t task; + + UNUSED(r); + + /* Read task handle from Wimp */ + _swix(Wimp_ReadSysInfo, _IN(0) | _OUT(0), 5, &task); + + debug("Task handle: 0x%0x\n", task); + + /* Install pre filter to invalidate current_session. */ + error = _swix(Filter_RegisterPreFilter, _INR(0,3), + session_filter_name, session_pre_poll, + pw, task); + if (error != NULL) { + debug("Filter_RegisterPreFilter: 0x%x %s\n", + error->errnum, error->errmess); + } + /* Install post poll filter so that: * * 1) we do the right thing when the client tries to interrupt * the debuggee. * 2) we keep current_session in sync with reality. - * - * The global pre poll filter will invalidate current_session if it - * is set. */ - _swix(Filter_RegisterPostFilter, _INR(0,4), - post_filter_name, session_post_poll, - ctx->pw, task, 0); + error = _swix(Filter_RegisterPostFilter, _INR(0,4), + session_filter_name, session_post_poll, + pw, task, 0); + if (error != NULL) { + debug("XFilter_RegisterPostFilter: 0x%x %s\n", + error->errnum, error->errmess); + } ctx->task_handle = task; + + return NULL; } +_kernel_oserror *session_pre_poll_handler(_kernel_swi_regs *r, void *pw) +{ + UNUSED(r); + UNUSED(pw); + + /* Invalidate current_session, as we're about to leave it */ + session_set_current(NULL); + + return NULL; +} + _kernel_oserror *session_post_poll_handler(_kernel_swi_regs *r, void *pw) { session_ctx *session = session_find_by_task_handle(r->r[2]); Index: src/header.cmhg =================================================================== --- src/header.cmhg (revision 3780) +++ src/header.cmhg (working copy) @@ -14,6 +14,6 @@ event-handler: internet 19 generic-veneers: post_run, appexit, apperror, appupcall, post_abort, - global_pre_poll, session_post_poll + post_wimp_initialise, session_pre_poll, session_post_poll service-call-handler: mod_service &2a Index: src/module.c =================================================================== --- src/module.c (revision 3780) +++ src/module.c (working copy) @@ -10,9 +10,6 @@ #include "session.h" #include "utils.h" -/* Global pre filter name */ -static const char *global_pre_filter_name = "GDBServer"; - /** Session currently being initialised */ static session_ctx *init_session; static uint32_t init_timeout; @@ -32,10 +29,6 @@ /* Don't really care if this fails */ _swix(OS_Byte, _INR(0,1), 14 /* Enable event */, 19); - _swix(Filter_RegisterPreFilter, _INR(0,3), - global_pre_filter_name, global_pre_poll, - pw, 0); - /* Claim CPU vectors. Disable IRQs while we do this. */ _swix(OS_IntOff, _IN(0), 0); @@ -73,11 +66,7 @@ UNUSED(podule_base); session_fini(); - - _swix(Filter_DeRegisterPreFilter, _INR(0,3), - global_pre_filter_name, global_pre_poll, - pw, 0); - + /* Release CPU vectors. Disable IRQs while we do this. */ _swix(OS_IntOff, _IN(0), 0); @@ -296,22 +285,3 @@ return NULL; } -_kernel_oserror *global_pre_poll_handler(_kernel_swi_regs *r, void *pw) -{ - session_ctx *ctx = session_get_current(); - - UNUSED(pw); - - if (ctx != NULL) { - debug("Wimp task: 0x%08x\n", r->r[2]); - - /* Potential new Wimp task -- inform session */ - session_set_task_handle(ctx, r->r[2]); - - /* Invalidate current_session, as we're about to leave it */ - session_set_current(NULL); - } - - return NULL; -} - Index: src/session.h =================================================================== --- src/session.h (revision 3780) +++ src/session.h (working copy) @@ -20,7 +20,7 @@ void session_change_environment(session_ctx *ctx, void *pw); void session_restore_environment(session_ctx *ctx); -void session_set_task_handle(session_ctx *ctx, uint32_t task); +void session_wimp_initialise(session_ctx *ctx); void session_get_error(session_ctx *ctx, _kernel_oserror *error); Index: src/gdb.c =================================================================== --- src/gdb.c (revision 3780) +++ src/gdb.c (working copy) @@ -102,6 +102,7 @@ switch (data[0]) { case 3: /* Tell client to interrupt application */ + debug("Received interrupt%s\n", ""); ctx->brk(ctx->pw); break; case '$': Index: src/header.h =================================================================== --- src/header.h (revision 3780) +++ src/header.h (working copy) @@ -14,7 +14,7 @@ #define Module_VersionString "0.01" #define Module_VersionNumber 1 #ifndef Module_Date -#define Module_Date "21 Mar 2009" +#define Module_Date "30 Mar 2009" #endif #ifdef __cplusplus @@ -46,7 +46,7 @@ * podule_base = address of podule module was started from, or * NULL if none * pw = private word for module - * On exit: Return 0 for successful finalisation, or a pointer to an + * On exit: Return NULL for successful finalisation, or a pointer to an * error block if module was not shutdown properly. **************************************************************************/ _kernel_oserror *mod_fini(int fatal, int podule_base, void *pw); @@ -240,17 +240,17 @@ /*************************************************************************** - * Function: global_pre_poll + * Function: post_wimp_initialise * Description: Symbol for entry point to module - NOT a C function. * This name should be used as an argument to * OS_Claim/OS_Release as required, but should never be called * from C. **************************************************************************/ -extern void global_pre_poll(void); +extern void post_wimp_initialise(void); /*************************************************************************** - * Function: global_pre_poll_handler + * Function: post_wimp_initialise_handler * Description: Generic handler function * Parameters: r = pointer to register block on entry * pw = private word for module @@ -258,10 +258,32 @@ * Return NULL to return with V clear * Return an error pointer to set V and r0 **************************************************************************/ -_kernel_oserror *global_pre_poll_handler(_kernel_swi_regs *r, void *pw); +_kernel_oserror *post_wimp_initialise_handler(_kernel_swi_regs *r, void *pw); /*************************************************************************** + * Function: session_pre_poll + * Description: Symbol for entry point to module - NOT a C function. + * This name should be used as an argument to + * OS_Claim/OS_Release as required, but should never be called + * from C. + **************************************************************************/ +extern void session_pre_poll(void); + + +/*************************************************************************** + * Function: session_pre_poll_handler + * Description: Generic handler function + * Parameters: r = pointer to register block on entry + * pw = private word for module + * On exit: Update r to alter return values + * Return NULL to return with V clear + * Return an error pointer to set V and r0 + **************************************************************************/ +_kernel_oserror *session_pre_poll_handler(_kernel_swi_regs *r, void *pw); + + +/*************************************************************************** * Function: session_post_poll * Description: Symbol for entry point to module - NOT a C function. * This name should be used as an argument to Index: Makefile =================================================================== --- Makefile (revision 3780) +++ Makefile (working copy) @@ -29,7 +29,7 @@ # Toolchain flags WARNFLAGS := -Wall -Wextra -Wundef -Wpointer-arith -Wcast-align \ -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes \ - -Wmissing-declarations -Wnested-externs -Werror -pedantic + -Wmissing-declarations -Wnested-externs #-Werror -pedantic CFLAGS = -std=c99 -I$(GCCSDK_INSTALL_ENV)/include $(WARNFLAGS) \ -mpoke-function-name -mmodule RELEASECFLAGS = $(CFLAGS) -DNDEBUG -O2