/* * Occures when key is pressed. * Handles debug Run/Stop/... and add/remove breakpoint activities */ gboolean keys_callback(guint key_id) { switch (key_id) { case KEY_RUN: debug_run(); break; case KEY_STOP: debug_stop(); break; case KEY_RESTART: debug_restart(); break; case KEY_STEP_OVER: debug_step_over(); break; case KEY_STEP_INTO: debug_step_into(); break; case KEY_STEP_OUT: debug_step_out(); break; case KEY_EXECUTE_UNTIL: { GeanyDocument *doc = document_get_current(); if (doc) { int line = sci_get_current_line(doc->editor->sci) + 1; debug_execute_until(DOC_FILENAME(doc), line); } break; } case KEY_BREAKPOINT: { GeanyDocument *doc = document_get_current(); if (doc) { int line = sci_get_current_line(doc->editor->sci) + 1; break_state bs = breaks_get_state(DOC_FILENAME(doc), line); if (BS_NOT_SET == bs) breaks_add(DOC_FILENAME(doc), line, NULL, TRUE, 0); else if (BS_ENABLED == bs) breaks_remove(DOC_FILENAME(doc), line); else if (BS_DISABLED == bs) breaks_switch(DOC_FILENAME(doc), line); scintilla_send_message(doc->editor->sci, SCI_SETFOCUS, TRUE, 0); } break; } case KEY_CURRENT_INSTRUCTION: { if (DBS_STOPPED == debug_get_state() && debug_current_instruction_have_sources()) { debug_jump_to_current_instruction(); gtk_widget_set_sensitive(tab_call_stack, FALSE); stree_select_first_frame(FALSE); gtk_widget_set_sensitive(tab_call_stack, TRUE); } } } return TRUE; }
static void kerext_debug_process(void *args) { PROCESS *prp; THREAD *thp, *act = actives[KERNCPU]; DEBUG *dep; struct kerargs_debug_process *kap = args; int status; int stopped; int tid; if(!(prp = lookup_pid(kap->pid))) { kererr(act, ESRCH); return; } dep = prp->debugger; if(kap->request == NTO_DEBUG_PROCESS_INFO || (prp->flags & _NTO_PF_TERMING)) { tid = 0; } else if(dep && kap->tid == 0) { tid = dep->tid + 1; } else { tid = kap->tid; } thp = 0; if(tid > 0 && !(thp = vector_search(&prp->threads, tid - 1, (kap->request == NTO_DEBUG_THREAD_INFO || kap->request == NTO_DEBUG_STOP) ? (unsigned *)&tid : 0))) { kererr(act, ESRCH); return; } stopped = 0; if(thp && ((thp->flags & _NTO_TF_TO_BE_STOPPED) || (thp->state != STATE_RUNNING && thp->state != STATE_READY))) { stopped = 1; } status = EINVAL; switch(kap->request) { case NTO_DEBUG_PROCESS_INFO: // pid:na:debug_process_t status = debug_process(prp, &kap->data->process); break; case NTO_DEBUG_THREAD_INFO: // pid:tid:debug_thread_t status = debug_thread(prp, thp, &kap->data->thread); break; case NTO_DEBUG_GET_GREG: // pid:tid:debug_greg_t if(thp) { memcpy(&kap->data->greg, &thp->reg, sizeof thp->reg); status = EOK; } break; case NTO_DEBUG_SET_GREG: // pid:tid:debug_greg_t if(stopped) { lock_kernel(); cpu_greg_load(thp, (CPU_REGISTERS *)&kap->data->greg); status = EOK; } break; case NTO_DEBUG_GET_FPREG: // pid:tid:debug_fpreg_t if(thp) { FPU_REGISTERS *fpudata = FPUDATA_PTR(thp->fpudata); int cpu = FPUDATA_CPU(thp->fpudata); status = ENXIO; if(fpudata) { if(FPUDATA_INUSE(thp->fpudata) && cpu != KERNCPU) { // In use on another CPU; send ipi, restart kernel call SENDIPI(cpu, IPI_CONTEXT_SAVE); KERCALL_RESTART(act); return; } if(actives_fpu[thp->runcpu] == thp) { if(KERNCPU == thp->runcpu) { cpu_force_fpu_save(thp); actives_fpu[KERNCPU] = NULL; } else { // We should not get here crash(); } } memcpy(&kap->data->fpreg, fpudata, sizeof *fpudata); status = EOK; } else if(thp->un.lcl.tls && thp->un.lcl.tls->__fpuemu_data) { // @@@ NEED TO FIND PROPER SIZE OF EMULATOR DATA memcpy(&kap->data->fpreg, thp->un.lcl.tls->__fpuemu_data, sizeof(*fpudata) + 256); status = EOK; } } break; case NTO_DEBUG_SET_FPREG: // pid:tid:debug_fpreg_t if(thp && stopped) { FPU_REGISTERS *fpudata = FPUDATA_PTR(thp->fpudata); int cpu = FPUDATA_CPU(thp->fpudata); status = ENXIO; if(thp->fpudata) { if(FPUDATA_INUSE(thp->fpudata) && cpu != KERNCPU) { // In use on another CPU; send ipi, restart kernel call SENDIPI(cpu, IPI_CONTEXT_SAVE); KERCALL_RESTART(act); return; } if(actives_fpu[thp->runcpu] == thp) { if(KERNCPU == thp->runcpu) { cpu_force_fpu_save(thp); actives_fpu[KERNCPU] = NULL; } else { // We should not get here crash(); } } memcpy(fpudata, &kap->data->fpreg, sizeof *fpudata); status = EOK; } else if(thp->un.lcl.tls && thp->un.lcl.tls->__fpuemu_data) { // @@@ NEED TO FIND PROPER SIZE OF EMULATOR DATA memcpy(thp->un.lcl.tls->__fpuemu_data, &kap->data->fpreg, sizeof(*fpudata) + 256); status = EOK; } } break; case NTO_DEBUG_STOP: // pid:na:na if(dep) { status = debug_stop(prp); } break; case NTO_DEBUG_RUN: // pid:tid:debug_run_t if(dep && stopped) { status = debug_run(prp, &kap->data->run); } break; case NTO_DEBUG_CURTHREAD: // pid:tid:NULL if(dep) { lock_kernel(); SETKSTATUS(act, dep->tid + 1); if(thp) { dep->tid = thp->tid; } return; } break; case NTO_DEBUG_FREEZE: // pid:tid:NULL if(thp == NULL){ status = EINVAL; break; } if(stopped) { lock_kernel(); thp->flags |= _NTO_TF_FROZEN; } break; case NTO_DEBUG_THAW: // pid:tid:NULL if(thp == NULL){ status = EINVAL; break; } if(stopped) { lock_kernel(); thp->flags &= ~_NTO_TF_FROZEN; } break; case NTO_DEBUG_BREAK: // pid:na:debug_break_t if(dep && stopped) { status = debug_break(prp, &kap->data->brk); } break; case NTO_DEBUG_GET_BREAKLIST: // pid:na:debug_breaklist_t status = debug_break_list(prp, &kap->data->brklist); break; case NTO_DEBUG_SET_FLAG: // pid:na:uint32_t if(dep && !(kap->data->flags & ~_DEBUG_FLAG_MASK)) { lock_kernel(); dep->flags |= kap->data->flags; } break; case NTO_DEBUG_CLEAR_FLAG: // pid:na:uint32_t if(dep && !(kap->data->flags & ~_DEBUG_FLAG_MASK)) { lock_kernel(); dep->flags &= ~kap->data->flags; } break; case NTO_DEBUG_GET_ALTREG: // pid:tid:debug_altreg_t if(thp) { status = cpu_debug_get_altregs(thp, &kap->data->altreg); } break; case NTO_DEBUG_SET_ALTREG: // pid:tid:debug_altreg_t if(thp) { status = cpu_debug_set_altregs(thp, &kap->data->altreg); } break; case NTO_DEBUG_GET_PERFREG: if ( thp ) { status = cpu_debug_get_perfregs(thp, &kap->data->perfreg); } break; case NTO_DEBUG_SET_PERFREG: if ( thp && !stopped ) status = EINVAL; else { if ( (kap->data->flags & ~PERFREGS_ENABLED_FLAG) == cpu_perfreg_id() ) { status = cpu_debug_set_perfregs(thp, &kap->data->perfreg); } else status = ENODEV; } break; } if(status != EOK) { kererr(act, status); } else { lock_kernel(); SETKSTATUS(act, 0); } }