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")); }
static CORE_ADDR mn10300_read_pc (ptid_t ptid) { return read_register_pid (E_PC_REGNUM, ptid); }