diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/linux-nat.c | 117 | ||||
-rw-r--r-- | gdb/record.c | 3 | ||||
-rw-r--r-- | gdb/record.h | 1 |
3 files changed, 117 insertions, 4 deletions
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index a0dc634ff83..7d94a68404d 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -50,6 +50,8 @@ #include "event-loop.h" #include "event-top.h" +#include "record.h" + #ifdef HAVE_PERSONALITY # include <sys/personality.h> # if !HAVE_DECL_ADDR_NO_RANDOMIZE @@ -503,6 +505,107 @@ my_waitpid (int pid, int *status, int flags) return ret; } +extern struct bp_location *bp_location_chain; +static struct lwp_info * find_lwp_pid (ptid_t ptid); +static int +my_waitpid_record (int pid, int *status, int flags) +{ + int ret; + struct bp_location *bl; + struct breakpoint *b; + CORE_ADDR pc; + struct lwp_info *lp; + +wait_begin: + ret = my_waitpid (pid, status, flags); + if (ret == -1) + { + return ret; + } + + if (ret == 0) + { + goto wait_begin; + } + + if (WIFSTOPPED (*status) && WSTOPSIG (*status) == SIGTRAP) + { + /* Check if there is a breakpoint */ + pc = 0; + registers_changed (); + for (bl = bp_location_chain; bl; bl = bl->global_next) + { + b = bl->owner; + gdb_assert (b); + if (b->enable_state != bp_enabled + && b->enable_state != bp_permanent) + continue; + if (!pc) + { + pc = regcache_read_pc (get_thread_regcache (pid_to_ptid (ret))); + } + switch (b->type) + { + default: + if (bl->address == pc) + { + goto out; + } + break; + + case bp_watchpoint: + /*XXX teawater: I still not very clear how to deal with it. */ + goto out; + break; + + case bp_catch_fork: + if (inferior_has_forked (inferior_ptid, &b->forked_inferior_pid)) + { + goto out; + } + break; + + case bp_catch_vfork: + if (inferior_has_vforked (inferior_ptid, &b->forked_inferior_pid)) + { + goto out; + } + break; + + case bp_catch_exec: + if (inferior_has_execd (inferior_ptid, &b->exec_pathname)) + { + goto out; + } + break; + + case bp_hardware_watchpoint: + case bp_read_watchpoint: + case bp_access_watchpoint: + if (STOPPED_BY_WATCHPOINT (0)) + { + goto out; + } + break; + } + } + + lp = find_lwp_pid (pid_to_ptid (ret)); + if (lp) + lp->stopped = 1; + + /* record message */ + record_message (current_gdbarch); + + /* resume program */ + linux_ops->to_resume (pid_to_ptid (ret), 1, TARGET_SIGNAL_0); + goto wait_begin; + } + +out: + return ret; +} + /* Determine if PTRACE_O_TRACEFORK can be used to follow fork events. First, we try to enable fork tracing on ORIGINAL_PID. If this fails, @@ -2860,7 +2963,16 @@ retry: queued events. */ lwpid = queued_waitpid (pid, &status, options); else - lwpid = my_waitpid (pid, &status, options); + { + if (RECORD_IS_USED && !record_resume_step) + { + lwpid = my_waitpid_record (pid, &status, options); + } + else + { + lwpid = my_waitpid (pid, &status, options); + } + } if (lwpid > 0) { @@ -4441,6 +4553,9 @@ linux_nat_add_target (struct target_ops *t) add_target (t); + /* Point out that this target support record wait. */ + t->to_support_record_wait = 1; + /* TODO: Eliminate this and have libthread_db use find_target_beneath. */ thread_db_init (t); diff --git a/gdb/record.c b/gdb/record.c index dc7c55e87a4..c7a8acb6265 100644 --- a/gdb/record.c +++ b/gdb/record.c @@ -45,7 +45,6 @@ static int record_insn_num = 0; struct target_ops record_ops; int record_resume_step = 0; enum exec_direction_kind record_execdir = EXEC_FORWARD; -int record_linux_async_permitted = 0; static int record_get_sig = 0; static sigset_t record_maskall; static int record_not_record = 0; @@ -395,7 +394,7 @@ record_open (char *name, int from_tty) { error (_("Record: record target can't debug inferior in non-stop mode (non-stop).")); } - if (record_linux_async_permitted) + if (target_async_permitted) { error (_("Record: record target can't debug the GNU/Linux inferior in asynchronous mode (linux-async).")); } diff --git a/gdb/record.h b/gdb/record.h index 9e20013104c..174697576ae 100644 --- a/gdb/record.h +++ b/gdb/record.h @@ -77,7 +77,6 @@ extern struct target_ops record_ops; extern int record_resume_step; extern int record_regcache_raw_write_regnum; extern enum exec_direction_kind record_execdir; -extern int record_linux_async_permitted; extern int record_arch_list_add_reg (int num); extern int record_arch_list_add_mem (CORE_ADDR addr, int len); |