static void lynx_resume (struct thread_resume *resume_info, size_t n) { ptid_t ptid = resume_info[0].thread; const int request = (resume_info[0].kind == resume_step ? (n == 1 ? PTRACE_SINGLESTEP_ONE : PTRACE_SINGLESTEP) : PTRACE_CONT); const int signal = resume_info[0].sig; /* If given a minus_one_ptid, then try using the current_process' private->last_wait_event_ptid. On most LynxOS versions, using any of the process' thread works well enough, but LynxOS 178 is a little more sensitive, and triggers some unexpected signals (Eg SIG61) when we resume the inferior using a different thread. */ if (ptid_equal (ptid, minus_one_ptid)) ptid = current_process()->priv->last_wait_event_ptid; /* The ptid might still be minus_one_ptid; this can happen between the moment we create the inferior or attach to a process, and the moment we resume its execution for the first time. It is fine to use the current_thread's ptid in those cases. */ if (ptid_equal (ptid, minus_one_ptid)) ptid = thread_to_gdb_id (current_thread); regcache_invalidate (); errno = 0; lynx_ptrace (request, ptid, 1, signal, 0); if (errno) perror_with_name ("ptrace"); }
void set_register_cache (struct reg *regs, int n) { int offset, i; #ifndef IN_PROCESS_AGENT /* Before changing the register cache internal layout, flush the contents of valid caches back to the threads. */ regcache_invalidate (); #endif reg_defs = regs; num_registers = n; offset = 0; for (i = 0; i < n; i++) { regs[i].offset = offset; offset += regs[i].size; } register_bytes = offset / 8; /* Make sure PBUFSIZ is large enough to hold a full register packet. */ if (2 * register_bytes + 32 > PBUFSIZ) fatal ("Register packet size exceeds PBUFSIZ."); #ifndef IN_PROCESS_AGENT /* Re-allocate all pre-existing register caches. */ for_each_inferior (&all_threads, realloc_register_cache); #endif }
unsigned char valgrind_wait (char *ourstatus) { int pid; unsigned long wptid; ThreadState *tst; enum target_signal sig; int code; pid = VG_(getpid) (); dlog(1, "enter valgrind_wait pid %d\n", pid); regcache_invalidate(); valgrind_update_threads(pid); /* First see if we are done with this process. */ if (exit_status_to_report != 0) { *ourstatus = exit_status_to_report; exit_status_to_report = 0; if (*ourstatus == 'W') { code = exit_code_to_report; exit_code_to_report = 0; dlog(1, "exit valgrind_wait status W exit code %d\n", code); return code; } if (*ourstatus == 'X') { sig = target_signal_from_host(exit_code_to_report); exit_code_to_report = 0; dlog(1, "exit valgrind_wait status X signal %u\n", sig); return sig; } } /* in valgrind, we consider that a wait always succeeds with STOPPED 'T' and with a signal TRAP (i.e. a breakpoint), unless there is a signal to report. */ *ourstatus = 'T'; if (vki_signal_to_report.si_signo == 0) sig = TARGET_SIGNAL_TRAP; else sig = target_signal_from_host(vki_signal_to_report.si_signo); if (vgdb_interrupted_tid != 0) tst = VG_(get_ThreadState) (vgdb_interrupted_tid); else tst = VG_(get_ThreadState) (VG_(running_tid)); wptid = tst->os_state.lwpid; /* we can only change the current_inferior when the wptid references an existing thread. Otherwise, we are still in the init phase. (hack similar to main thread hack in valgrind_update_threads) */ if (tst->os_state.lwpid) current_inferior = gdb_id_to_thread (wptid); stop_pc = (*the_low_target.get_pc) (); dlog(1, "exit valgrind_wait status T ptid %s stop_pc %s signal %u\n", image_ptid (wptid), sym (stop_pc), sig); return sig; }
void valgrind_resume (struct thread_resume *resume_info) { dlog(1, "resume_info step %d sig %d stepping %d\n", resume_info->step, resume_info->sig, stepping); if (valgrind_stopped_by_watchpoint()) { dlog(1, "clearing watchpoint stopped_data_address %p\n", C2v(stopped_data_address)); VG_(set_watchpoint_stop_address) ((Addr) 0); } vki_signal_to_deliver.si_signo = resume_info->sig; /* signal was reported to GDB, GDB told us to resume execution. So, reset the signal to report to 0. */ VG_(memset) (&vki_signal_to_report, 0, sizeof(vki_signal_to_report)); stepping = resume_info->step; resume_pc = (*the_low_target.get_pc) (); if (resume_pc != stop_pc) { dlog(1, "stop_pc %p changed to be resume_pc %s\n", C2v(stop_pc), sym(resume_pc)); } regcache_invalidate(); }
static void lynx_resume (struct thread_resume *resume_info, size_t n) { ptid_t inferior_ptid = thread_to_gdb_id (current_inferior); /* FIXME: Assume for now that n == 1. */ const int request = (resume_info[0].kind == resume_step ? PTRACE_SINGLESTEP : PTRACE_CONT); const int signal = resume_info[0].sig; int ret; regcache_invalidate (); ret = lynx_ptrace (request, inferior_ptid, 1, signal, 0); }
void initialize_shadow_low(Bool shadow_mode) { if (non_shadow_reg_defs == NULL) { non_shadow_reg_defs = the_low_target.reg_defs; non_shadow_num_regs = the_low_target.num_regs; } regcache_invalidate(); if (the_low_target.reg_defs != non_shadow_reg_defs) { free (the_low_target.reg_defs); } if (shadow_mode) { the_low_target.num_regs = 3 * non_shadow_num_regs; the_low_target.reg_defs = build_shadow_arch (non_shadow_reg_defs, non_shadow_num_regs); } else { the_low_target.num_regs = non_shadow_num_regs; the_low_target.reg_defs = non_shadow_reg_defs; } set_register_cache (the_low_target.reg_defs, the_low_target.num_regs); }
void valgrind_resume (struct thread_resume *resume_info) { dlog(1, "resume_info step %d sig %d stepping %d\n", resume_info->step, resume_info->sig, stepping); if (valgrind_stopped_by_watchpoint()) { dlog(1, "clearing watchpoint stopped_data_address %p\n", C2v(stopped_data_address)); VG_(set_watchpoint_stop_address) ((Addr) 0); } vki_signal_to_deliver = resume_info->sig; stepping = resume_info->step; resume_pc = (*the_low_target.get_pc) (); if (resume_pc != stop_pc) { dlog(1, "stop_pc %p changed to be resume_pc %s\n", C2v(stop_pc), sym(resume_pc)); } regcache_invalidate(); }
/* Resume the inferior process. RESUME_INFO describes how we want to resume. */ static void win32_resume (struct thread_resume *resume_info, size_t n) { DWORD tid; enum target_signal sig; int step; win32_thread_info *th; DWORD continue_status = DBG_CONTINUE; ptid_t ptid; /* This handles the very limited set of resume packets that GDB can currently produce. */ if (n == 1 && ptid_equal (resume_info[0].thread, minus_one_ptid)) tid = -1; else if (n > 1) tid = -1; else /* Yes, we're ignoring resume_info[0].thread. It'd be tricky to make the Windows resume code do the right thing for thread switching. */ tid = current_event.dwThreadId; if (!ptid_equal (resume_info[0].thread, minus_one_ptid)) { sig = resume_info[0].sig; step = resume_info[0].kind == resume_step; } else { sig = 0; step = 0; } if (sig != TARGET_SIGNAL_0) { if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT) { OUTMSG (("Cannot continue with signal %d here.\n", sig)); } else if (sig == last_sig) continue_status = DBG_EXCEPTION_NOT_HANDLED; else OUTMSG (("Can only continue with recieved signal %d.\n", last_sig)); } last_sig = TARGET_SIGNAL_0; /* Get context for the currently selected thread. */ ptid = debug_event_ptid (¤t_event); th = thread_rec (ptid, FALSE); if (th) { if (th->context.ContextFlags) { /* Move register values from the inferior into the thread context structure. */ regcache_invalidate (); if (step) { if (the_low_target.single_step != NULL) (*the_low_target.single_step) (th); else error ("Single stepping is not supported " "in this configuration.\n"); } win32_set_thread_context (th); th->context.ContextFlags = 0; } } /* Allow continuing with the same signal that interrupted us. Otherwise complain. */ child_continue (continue_status, tid); }
static void nto_resume (struct thread_resume *resume_info, size_t n) { /* We can only work in all-stop mode. */ procfs_status status; procfs_run run; int err; TRACE ("%s\n", __func__); /* Workaround for aliasing rules violation. */ sigset_t *run_fault = (sigset_t *) (void *) &run.fault; nto_set_thread (resume_info->thread); run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE; if (resume_info->kind == resume_step) run.flags |= _DEBUG_RUN_STEP; run.flags |= _DEBUG_RUN_ARM; sigemptyset (run_fault); sigaddset (run_fault, FLTBPT); sigaddset (run_fault, FLTTRACE); sigaddset (run_fault, FLTILL); sigaddset (run_fault, FLTPRIV); sigaddset (run_fault, FLTBOUNDS); sigaddset (run_fault, FLTIOVF); sigaddset (run_fault, FLTIZDIV); sigaddset (run_fault, FLTFPE); sigaddset (run_fault, FLTPAGE); sigaddset (run_fault, FLTSTACK); sigaddset (run_fault, FLTACCESS); sigemptyset (&run.trace); if (resume_info->sig) { int signal_to_pass; devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0); signal_to_pass = resume_info->sig; if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED)) { if (signal_to_pass != status.info.si_signo) { kill (status.pid, signal_to_pass); run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG; } else /* Let it kill the program without telling us. */ sigdelset (&run.trace, signal_to_pass); } } else run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT; sigfillset (&run.trace); regcache_invalidate (); err = devctl (nto_inferior.ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0); if (err != EOK) TRACE ("Error: %d \"%s\"\n", err, strerror (err)); }