mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-15 04:31:49 +08:00
2009-09-21 Hui Zhu <teawater@gmail.com>
Michael Snyder <msnyder@vmware.com> * record.c (record_end_entry): New struct. (record_type): Add end. (record_arch_list_add_end): Set rec->u.end.sigval to TARGET_SIGNAL_0. (record_message_args): New struct. (record_message): Call gdbarch_process_record_signal. (do_record_message): Add argument "signal". (record_resume): Ditto. (record_wait): Ditto. Check record_list->u.end.sigval in replay mode.
This commit is contained in:
parent
3846b520e4
commit
8b739a963c
@ -1,3 +1,17 @@
|
|||||||
|
2009-09-21 Hui Zhu <teawater@gmail.com>
|
||||||
|
Michael Snyder <msnyder@vmware.com>
|
||||||
|
|
||||||
|
* record.c (record_end_entry): New struct.
|
||||||
|
(record_type): Add end.
|
||||||
|
(record_arch_list_add_end): Set rec->u.end.sigval to
|
||||||
|
TARGET_SIGNAL_0.
|
||||||
|
(record_message_args): New struct.
|
||||||
|
(record_message): Call gdbarch_process_record_signal.
|
||||||
|
(do_record_message): Add argument "signal".
|
||||||
|
(record_resume): Ditto.
|
||||||
|
(record_wait): Ditto. Check record_list->u.end.sigval
|
||||||
|
in replay mode.
|
||||||
|
|
||||||
2009-09-21 Hui Zhu <teawater@gmail.com>
|
2009-09-21 Hui Zhu <teawater@gmail.com>
|
||||||
Michael Snyder <msnyder@vmware.com>
|
Michael Snyder <msnyder@vmware.com>
|
||||||
|
|
||||||
|
92
gdb/record.c
92
gdb/record.c
@ -59,6 +59,11 @@ struct record_mem_entry
|
|||||||
gdb_byte *val;
|
gdb_byte *val;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct record_end_entry
|
||||||
|
{
|
||||||
|
enum target_signal sigval;
|
||||||
|
};
|
||||||
|
|
||||||
enum record_type
|
enum record_type
|
||||||
{
|
{
|
||||||
record_end = 0,
|
record_end = 0,
|
||||||
@ -77,6 +82,8 @@ struct record_entry
|
|||||||
struct record_reg_entry reg;
|
struct record_reg_entry reg;
|
||||||
/* mem */
|
/* mem */
|
||||||
struct record_mem_entry mem;
|
struct record_mem_entry mem;
|
||||||
|
/* end */
|
||||||
|
struct record_end_entry end;
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -314,6 +321,7 @@ record_arch_list_add_end (void)
|
|||||||
rec->prev = NULL;
|
rec->prev = NULL;
|
||||||
rec->next = NULL;
|
rec->next = NULL;
|
||||||
rec->type = record_end;
|
rec->type = record_end;
|
||||||
|
rec->u.end.sigval = TARGET_SIGNAL_0;
|
||||||
|
|
||||||
record_arch_list_add (rec);
|
record_arch_list_add (rec);
|
||||||
|
|
||||||
@ -360,11 +368,17 @@ record_message_cleanups (void *ignore)
|
|||||||
record_list_release (record_arch_list_tail);
|
record_list_release (record_arch_list_tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct record_message_args {
|
||||||
|
struct regcache *regcache;
|
||||||
|
enum target_signal signal;
|
||||||
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
record_message (void *args)
|
record_message (void *args)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct regcache *regcache = args;
|
struct record_message_args *myargs = args;
|
||||||
|
struct gdbarch *gdbarch = get_regcache_arch (myargs->regcache);
|
||||||
struct cleanup *old_cleanups = make_cleanup (record_message_cleanups, 0);
|
struct cleanup *old_cleanups = make_cleanup (record_message_cleanups, 0);
|
||||||
|
|
||||||
record_arch_list_head = NULL;
|
record_arch_list_head = NULL;
|
||||||
@ -373,9 +387,44 @@ record_message (void *args)
|
|||||||
/* Check record_insn_num. */
|
/* Check record_insn_num. */
|
||||||
record_check_insn_num (1);
|
record_check_insn_num (1);
|
||||||
|
|
||||||
ret = gdbarch_process_record (get_regcache_arch (regcache),
|
/* If gdb sends a signal value to target_resume,
|
||||||
regcache,
|
save it in the 'end' field of the previous instruction.
|
||||||
regcache_read_pc (regcache));
|
|
||||||
|
Maybe process record should record what really happened,
|
||||||
|
rather than what gdb pretends has happened.
|
||||||
|
|
||||||
|
So if Linux delivered the signal to the child process during
|
||||||
|
the record mode, we will record it and deliver it again in
|
||||||
|
the replay mode.
|
||||||
|
|
||||||
|
If user says "ignore this signal" during the record mode, then
|
||||||
|
it will be ignored again during the replay mode (no matter if
|
||||||
|
the user says something different, like "deliver this signal"
|
||||||
|
during the replay mode).
|
||||||
|
|
||||||
|
User should understand that nothing he does during the replay
|
||||||
|
mode will change the behavior of the child. If he tries,
|
||||||
|
then that is a user error.
|
||||||
|
|
||||||
|
But we should still deliver the signal to gdb during the replay,
|
||||||
|
if we delivered it during the recording. Therefore we should
|
||||||
|
record the signal during record_wait, not record_resume. */
|
||||||
|
if (record_list != &record_first) /* FIXME better way to check */
|
||||||
|
{
|
||||||
|
gdb_assert (record_list->type == record_end);
|
||||||
|
record_list->u.end.sigval = myargs->signal;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (myargs->signal == TARGET_SIGNAL_0
|
||||||
|
|| !gdbarch_process_record_signal_p (gdbarch))
|
||||||
|
ret = gdbarch_process_record (gdbarch,
|
||||||
|
myargs->regcache,
|
||||||
|
regcache_read_pc (myargs->regcache));
|
||||||
|
else
|
||||||
|
ret = gdbarch_process_record_signal (gdbarch,
|
||||||
|
myargs->regcache,
|
||||||
|
myargs->signal);
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
error (_("Process record: inferior program stopped."));
|
error (_("Process record: inferior program stopped."));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -396,9 +445,14 @@ record_message (void *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_record_message (struct regcache *regcache)
|
do_record_message (struct regcache *regcache,
|
||||||
|
enum target_signal signal)
|
||||||
{
|
{
|
||||||
return catch_errors (record_message, regcache, NULL, RETURN_MASK_ALL);
|
struct record_message_args args;
|
||||||
|
|
||||||
|
args.regcache = regcache;
|
||||||
|
args.signal = signal;
|
||||||
|
return catch_errors (record_message, &args, NULL, RETURN_MASK_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set to 1 if record_store_registers and record_xfer_partial
|
/* Set to 1 if record_store_registers and record_xfer_partial
|
||||||
@ -520,13 +574,13 @@ static int record_resume_error;
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
record_resume (struct target_ops *ops, ptid_t ptid, int step,
|
record_resume (struct target_ops *ops, ptid_t ptid, int step,
|
||||||
enum target_signal siggnal)
|
enum target_signal signal)
|
||||||
{
|
{
|
||||||
record_resume_step = step;
|
record_resume_step = step;
|
||||||
|
|
||||||
if (!RECORD_IS_REPLAY)
|
if (!RECORD_IS_REPLAY)
|
||||||
{
|
{
|
||||||
if (do_record_message (get_current_regcache ()))
|
if (do_record_message (get_current_regcache (), signal))
|
||||||
{
|
{
|
||||||
record_resume_error = 0;
|
record_resume_error = 0;
|
||||||
}
|
}
|
||||||
@ -536,7 +590,7 @@ record_resume (struct target_ops *ops, ptid_t ptid, int step,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
|
record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
|
||||||
siggnal);
|
signal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,15 +665,16 @@ record_wait (struct target_ops *ops,
|
|||||||
ret = record_beneath_to_wait (record_beneath_to_wait_ops,
|
ret = record_beneath_to_wait (record_beneath_to_wait_ops,
|
||||||
ptid, status, options);
|
ptid, status, options);
|
||||||
|
|
||||||
|
/* Is this a SIGTRAP? */
|
||||||
if (status->kind == TARGET_WAITKIND_STOPPED
|
if (status->kind == TARGET_WAITKIND_STOPPED
|
||||||
&& status->value.sig == TARGET_SIGNAL_TRAP)
|
&& status->value.sig == TARGET_SIGNAL_TRAP)
|
||||||
{
|
{
|
||||||
/* Check if there is a breakpoint. */
|
/* Yes -- check if there is a breakpoint. */
|
||||||
registers_changed ();
|
registers_changed ();
|
||||||
tmp_pc = regcache_read_pc (get_current_regcache ());
|
tmp_pc = regcache_read_pc (get_current_regcache ());
|
||||||
if (breakpoint_inserted_here_p (tmp_pc))
|
if (breakpoint_inserted_here_p (tmp_pc))
|
||||||
{
|
{
|
||||||
/* There is a breakpoint. */
|
/* There is a breakpoint. GDB will want to stop. */
|
||||||
CORE_ADDR decr_pc_after_break =
|
CORE_ADDR decr_pc_after_break =
|
||||||
gdbarch_decr_pc_after_break
|
gdbarch_decr_pc_after_break
|
||||||
(get_regcache_arch (get_current_regcache ()));
|
(get_regcache_arch (get_current_regcache ()));
|
||||||
@ -631,8 +686,12 @@ record_wait (struct target_ops *ops,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* There is not a breakpoint. */
|
/* There is not a breakpoint, and gdb is not
|
||||||
if (!do_record_message (get_current_regcache ()))
|
stepping, therefore gdb will not stop.
|
||||||
|
Therefore we will not return to gdb.
|
||||||
|
Record the insn and resume. */
|
||||||
|
if (!do_record_message (get_current_regcache (),
|
||||||
|
TARGET_SIGNAL_0))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -827,6 +886,10 @@ record_wait (struct target_ops *ops,
|
|||||||
gdbarch_decr_pc_after_break (gdbarch));
|
gdbarch_decr_pc_after_break (gdbarch));
|
||||||
continue_flag = 0;
|
continue_flag = 0;
|
||||||
}
|
}
|
||||||
|
/* Check target signal */
|
||||||
|
if (record_list->u.end.sigval != TARGET_SIGNAL_0)
|
||||||
|
/* FIXME: better way to check */
|
||||||
|
continue_flag = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -851,6 +914,9 @@ record_wait (struct target_ops *ops,
|
|||||||
replay_out:
|
replay_out:
|
||||||
if (record_get_sig)
|
if (record_get_sig)
|
||||||
status->value.sig = TARGET_SIGNAL_INT;
|
status->value.sig = TARGET_SIGNAL_INT;
|
||||||
|
else if (record_list->u.end.sigval != TARGET_SIGNAL_0)
|
||||||
|
/* FIXME: better way to check */
|
||||||
|
status->value.sig = record_list->u.end.sigval;
|
||||||
else
|
else
|
||||||
status->value.sig = TARGET_SIGNAL_TRAP;
|
status->value.sig = TARGET_SIGNAL_TRAP;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user