static void i386_linux_resume (ptid_t ptid, int step, enum target_signal signal) { int pid = PIDGET (ptid); int request = PTRACE_CONT; if (pid == -1) /* Resume all threads. */ /* I think this only gets used in the non-threaded case, where "resume all threads" and "resume inferior_ptid" are the same. */ pid = PIDGET (inferior_ptid); if (step) { CORE_ADDR pc = read_pc_pid (pid_to_ptid (pid)); gdb_byte buf[LINUX_SYSCALL_LEN]; request = PTRACE_SINGLESTEP; /* Returning from a signal trampoline is done by calling a special system call (sigreturn or rt_sigreturn, see i386-linux-tdep.c for more information). This system call restores the registers that were saved when the signal was raised, including %eflags. That means that single-stepping won't work. Instead, we'll have to modify the signal context that's about to be restored, and set the trace flag there. */ /* First check if PC is at a system call. */ if (deprecated_read_memory_nobpt (pc, buf, LINUX_SYSCALL_LEN) == 0 && memcmp (buf, linux_syscall, LINUX_SYSCALL_LEN) == 0) { int syscall = read_register_pid (LINUX_SYSCALL_REGNUM, pid_to_ptid (pid)); /* Then check the system call number. */ if (syscall == SYS_sigreturn || syscall == SYS_rt_sigreturn) { CORE_ADDR sp = read_register (I386_ESP_REGNUM); CORE_ADDR addr = sp; unsigned long int eflags; if (syscall == SYS_rt_sigreturn) addr = read_memory_integer (sp + 8, 4) + 20; /* Set the trace flag in the context that's about to be restored. */ addr += LINUX_SIGCONTEXT_EFLAGS_OFFSET; read_memory (addr, (gdb_byte *) &eflags, 4); eflags |= 0x0100; write_memory (addr, (gdb_byte *) &eflags, 4); } } } if (ptrace (request, pid, 0, target_signal_to_host (signal)) == -1) perror_with_name (("ptrace")); }
/* Generic prepare_to_proceed(). This one should be suitable for most targets that support threads. */ int generic_prepare_to_proceed (int select_it) { ptid_t wait_ptid; struct target_waitstatus wait_status; /* Get the last target status returned by target_wait(). */ get_last_target_status (&wait_ptid, &wait_status); /* Make sure we were stopped either at a breakpoint, or because of a Ctrl-C. */ if (wait_status.kind != TARGET_WAITKIND_STOPPED || (wait_status.value.sig != TARGET_SIGNAL_TRAP && wait_status.value.sig != TARGET_SIGNAL_INT)) { return 0; } if (!ptid_equal (wait_ptid, minus_one_ptid) && !ptid_equal (inferior_ptid, wait_ptid)) { /* Switched over from WAIT_PID. */ CORE_ADDR wait_pc = read_pc_pid (wait_ptid); if (wait_pc != read_pc ()) { if (select_it) { /* Switch back to WAIT_PID thread. */ inferior_ptid = wait_ptid; /* FIXME: This stuff came from switch_to_thread() in thread.c (which should probably be a public function). */ flush_cached_frames (); registers_changed (); stop_pc = wait_pc; select_frame (get_current_frame ()); } /* We return 1 to indicate that there is a breakpoint here, so we need to step over it before continuing to avoid hitting it straight away. */ if (breakpoint_here_p (wait_pc)) { return 1; } } } return 0; }
static void check_event (ptid_t ptid) { td_event_msg_t msg; td_thrinfo_t ti; td_err_e err; CORE_ADDR stop_pc; int loop = 0; /* Bail out early if we're not at a thread event breakpoint. */ stop_pc = read_pc_pid (ptid) - DECR_PC_AFTER_BREAK; if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr) return; loop = 1; do { err = td_ta_event_getmsg_p (thread_agent, &msg); if (err != TD_OK) { if (err == TD_NOMSG) return; error ("Cannot get thread event message: %s", thread_db_err_str (err)); } err = td_thr_get_info_p ((void *)(uintptr_t)msg.th_p, &ti); if (err != TD_OK) error ("Cannot get thread info: %s", thread_db_err_str (err)); ptid = BUILD_THREAD (ti.ti_tid, GET_PID (ptid)); switch (msg.event) { case TD_CREATE: /* We may already know about this thread, for instance when the user has issued the `info threads' command before the SIGTRAP for hitting the thread creation breakpoint was reported. */ attach_thread (ptid, (void *)(uintptr_t)msg.th_p, &ti, 1); break; case TD_DEATH: if (!in_thread_list (ptid)) error ("Spurious thread death event."); detach_thread (ptid, 1); break; default: error ("Spurious thread event."); } } while (loop); }