This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
| Other format: | [Raw text] | |
2008-08-19 Hui Zhu <teawater@gmail.com>
* record.c (arch-utils.h): Include file.
(record_skip_entry): New struct.
(record_skip, record_skip_list): New variables.
(record_open): Call "gdbarch_process_record_open".
Reset record_skip.
(record_close): Release record_skip_list.
Remove all record skip breakpoints.
(record_resume): Call record_beneath_to_resume directly
if record_skip is true.
(record_wait): Call record_beneath_to_wait directly
if record_skip is true.
(record_skip_entry_create): New function.
(record_skip_breakpoint_handler): New function.
(cmd_record_skip): New function.
(cmd_record_skip_enable): New function.
(cmd_record_skip_disable): New function.
(record_skip_cmdlist): New variable.
(_initialize_record): Add new command 'record skip',
'record skip enable' and 'record skip disable'.
* record.h (record_skip_entry_create): Extern.
(record_skip_breakpoint_handler): Extern.
---
record.c | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
record.h | 6 +
2 files changed, 277 insertions(+), 12 deletions(-)
--- a/record.c
+++ b/record.c
@@ -18,6 +18,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
+#include "arch-utils.h"
#include "gdbcmd.h"
#include "regcache.h"
#include "gdbthread.h"
@@ -78,6 +79,16 @@ struct record_entry
} u;
};
+struct record_skip_entry
+{
+ int id;
+ struct record_skip_entry *prev;
+ const char *name;
+ CORE_ADDR addr;
+ struct breakpoint *bp;
+ int (*record) (struct regcache *regcache);
+};
+
/* This is the debug switch for process record. */
int record_debug = 0;
@@ -92,6 +103,10 @@ static int record_stop_at_limit = 1;
static int record_insn_max_num = DEFAULT_RECORD_INSN_MAX_NUM;
static int record_insn_num = 0;
+/* Skip record if true. */
+static int record_skip = 0;
+static struct record_skip_entry *record_skip_list = NULL;
+
/* The target_ops of process record. */
static struct target_ops record_ops;
@@ -498,10 +513,14 @@ record_open (char *name, int from_tty)
push_target (&record_ops);
+ if (gdbarch_process_record_open_p (target_gdbarch))
+ gdbarch_process_record_open (target_gdbarch);
+
/* Reset */
record_insn_num = 0;
record_list = &record_first;
record_list->next = NULL;
+ record_skip = 0;
}
static void
@@ -511,6 +530,19 @@ record_close (int quitting)
fprintf_unfiltered (gdb_stdlog, "Process record: record_close\n");
record_list_release (record_list);
+
+ /* Release record_skip_list. */
+ if (record_skip_list)
+ {
+ struct record_skip_entry *entry;
+ for (entry = record_skip_list->prev; entry; entry = entry->prev)
+ {
+ xfree (record_skip_list);
+ record_skip_list = entry;
+ }
+ record_skip_list = NULL;
+ }
+ remove_record_skip_breakpoint (0, 1);
}
static int record_resume_step = 0;
@@ -526,17 +558,24 @@ record_resume (struct target_ops *ops, p
if (!RECORD_IS_REPLAY)
{
- if (do_record_message (get_current_regcache ()))
- {
- record_resume_error = 0;
- }
+ if (record_skip)
+ record_beneath_to_resume (record_beneath_to_resume_ops, ptid, step,
+ siggnal);
else
{
- record_resume_error = 1;
- return;
+ if (do_record_message (get_current_regcache ()))
+ {
+ record_resume_error = 0;
+ }
+ else
+ {
+ record_resume_error = 1;
+ return;
+ }
+ record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
+ siggnal);
}
- record_beneath_to_resume (record_beneath_to_resume_ops, ptid, 1,
- siggnal);
+
}
}
@@ -594,9 +633,10 @@ record_wait (struct target_ops *ops,
return inferior_ptid;
}
- if (record_resume_step)
+ if (record_resume_step || record_skip)
{
- /* This is a single step. */
+ /* This is a single step or record skip function is
+ enable. */
return record_beneath_to_wait (record_beneath_to_wait_ops,
ptid, status, 0);
}
@@ -1137,6 +1177,132 @@ init_record_ops (void)
record_ops.to_magic = OPS_MAGIC;
}
+void
+record_skip_entry_create (struct gdbarch *gdbarch, const char *name,
+ int (*record) (struct regcache *regcache))
+{
+ struct minimal_symbol *msym;
+ struct record_skip_entry *entry;
+
+ gdb_assert (record != NULL);
+
+ /* Get msym. */
+ msym = lookup_minimal_symbol (name, NULL, NULL);
+ if (!msym)
+ {
+ warning (_("Process record: failed to create record skip "
+ "breakpoint for '%s'."), name);
+ return;
+ }
+
+ /* Alloc entry. */
+ entry = xmalloc (sizeof (struct record_skip_entry));
+
+ /* Set entry->addr. */
+ entry->addr = SYMBOL_VALUE_ADDRESS (msym);
+
+ /* Set entry->bp. */
+ entry->bp = create_record_skip_breakpoint (gdbarch,
+ entry->addr,
+ bp_record_skip_start);
+
+ /* Set entry->name. */
+ entry->name = name;
+
+ /* Set entry->record. */
+ entry->record = record;
+
+ /* Set entry->id and add entry to record_skip_list. */
+ if (record_skip_list)
+ {
+ entry->id = record_skip_list->id + 1;
+ entry->prev = record_skip_list;
+ }
+ else
+ {
+ entry->id = 1;
+ entry->prev = NULL;
+ }
+ record_skip_list = entry;
+}
+
+void
+record_skip_breakpoint_handler (struct frame_info *frame, ptid_t ptid,
+ int skip_type)
+{
+ if (RECORD_IS_REPLAY)
+ return;
+
+ gdb_assert (skip_type == bp_record_skip_start
+ || skip_type == bp_record_skip_stop);
+
+ if (skip_type == bp_record_skip_start)
+ {
+ /* Skip start. */
+ struct regcache *regcache = get_thread_regcache (ptid);
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ CORE_ADDR caller_pc;
+ struct record_skip_entry *entry;
+ struct cleanup *old_cleanups = make_cleanup (record_message_cleanups, 0);
+
+ gdb_assert (record_skip == 0);
+
+ /* Get record_skip_entry. */
+ for (entry = record_skip_list; entry; entry = entry->prev)
+ if (entry->addr == stop_pc)
+ break;
+ if (entry == NULL)
+ {
+ warning (_("Failed to find record skip entry in address %s."),
+ paddress (gdbarch, stop_pc));
+ return;
+ }
+
+ /* Record the behavior of this function. */
+ record_arch_list_head = NULL;
+ record_arch_list_tail = NULL;
+ record_check_insn_num (0);
+ if (entry->record (regcache))
+ {
+ warning (_("Process record: failed to record execution log."));
+ record_list_release (record_arch_list_tail);
+ return;
+ }
+ gdb_assert (record_arch_list_head != NULL);
+ record_list->next = record_arch_list_head;
+ record_arch_list_head->prev = record_list;
+ record_list = record_arch_list_tail;
+ if (record_insn_num == record_insn_max_num && record_insn_max_num)
+ record_list_release_first ();
+ else
+ record_insn_num++;
+
+ /* Insert a bp_record_skip_stop to stop the skip. */
+ caller_pc = gdbarch_addr_bits_remove (gdbarch,
+ frame_unwind_caller_pc(frame));
+ create_record_skip_breakpoint (gdbarch, caller_pc, bp_record_skip_stop);
+
+ record_skip = 1;
+
+ if (record_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ _("Process record skip start in '%s'.\n"),
+ entry->name);
+ }
+ else
+ {
+ /* Skip stop. */
+ /* Remove this bp_record_skip_stop. */
+ remove_record_skip_breakpoint (stop_pc, 0);
+
+ record_skip = 0;
+
+ if (record_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ _("Process record skip stop.\n"));
+ }
+}
+
static void
show_record_debug (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
@@ -1191,6 +1357,89 @@ cmd_record_stop (char *args, int from_tt
printf_unfiltered (_("Process record is not started.\n"));
}
+static void
+cmd_record_skip (char *args, int from_tty)
+{
+ if (record_skip)
+ printf_unfiltered (_("Process record is skip.\n"));
+ else
+ printf_unfiltered (_("Process record is not skip.\n"));
+
+ if (record_skip_list)
+ {
+ int i;
+ struct record_skip_entry *entry;
+
+ printf_unfiltered (_("Id\tEnb\tAddress\t\tWhat\n"));
+ for (i = 1; 1; i++)
+ {
+ for (entry = record_skip_list; entry; entry = entry->prev)
+ if (entry->id == i)
+ break;
+ if (entry)
+ printf_unfiltered (_("%d\t%s\t%s\t%s\n"), entry->id,
+ (entry->bp->enable_state == bp_enabled)
+ ? "y" : "n",
+ paddress (get_current_arch (), entry->addr),
+ entry->name);
+ else
+ break;
+ }
+ }
+ else
+ printf_unfiltered (_("No record skip.\n"));
+}
+
+static void
+cmd_record_skip_enable (char *args, int from_tty)
+{
+ struct record_skip_entry *entry;
+
+ if (args && *args)
+ {
+ int id = atoi (args);
+
+ for (entry = record_skip_list; entry; entry = entry->prev)
+ if (entry->id == id)
+ break;
+
+ if (entry)
+ enable_breakpoint (entry->bp);
+ else
+ printf_unfiltered (_("No record skip id %s.\n"), args);
+ }
+ else
+ {
+ for (entry = record_skip_list; entry; entry = entry->prev)
+ enable_breakpoint (entry->bp);
+ }
+}
+
+static void
+cmd_record_skip_disable (char *args, int from_tty)
+{
+ struct record_skip_entry *entry;
+
+ if (args && *args)
+ {
+ int id = atoi (args);
+
+ for (entry = record_skip_list; entry; entry = entry->prev)
+ if (entry->id == id)
+ break;
+
+ if (entry)
+ disable_breakpoint (entry->bp);
+ else
+ printf_unfiltered (_("No record skip id %s.\n"), args);
+ }
+ else
+ {
+ for (entry = record_skip_list; entry; entry = entry->prev)
+ disable_breakpoint (entry->bp);
+ }
+}
+
/* Set upper limit of record log size. */
static void
@@ -1218,7 +1467,8 @@ show_record_insn_number (char *ignore, i
}
static struct cmd_list_element *record_cmdlist, *set_record_cmdlist,
- *show_record_cmdlist, *info_record_cmdlist;
+ *show_record_cmdlist, *info_record_cmdlist,
+ *record_skip_cmdlist;
static void
set_record_command (char *args, int from_tty)
@@ -1276,7 +1526,6 @@ _initialize_record (void)
"info record ", 0, &infolist);
add_alias_cmd ("rec", "record", class_obscure, 1, &infolist);
-
add_cmd ("delete", class_obscure, cmd_record_delete,
_("Delete the rest of execution log and start recording it anew."),
&record_cmdlist);
@@ -1288,6 +1537,16 @@ _initialize_record (void)
&record_cmdlist);
add_alias_cmd ("s", "stop", class_obscure, 1, &record_cmdlist);
+ add_prefix_cmd ("skip", class_obscure, cmd_record_skip,
+ _("Show the record skip status."),
+ &record_skip_cmdlist, "record ", 0, &record_cmdlist);
+ add_cmd ("enable", class_obscure, cmd_record_skip_enable,
+ _("Enable some record skip."),
+ &record_skip_cmdlist);
+ add_cmd ("disable", class_obscure, cmd_record_skip_disable,
+ _("Disable some record skip."),
+ &record_skip_cmdlist);
+
/* Record instructions number limit command. */
add_setshow_boolean_cmd ("stop-at-limit", no_class,
&record_stop_at_limit, _("\
--- a/record.h
+++ b/record.h
@@ -28,5 +28,11 @@ extern int record_arch_list_add_reg (str
extern int record_arch_list_add_mem (CORE_ADDR addr, int len);
extern int record_arch_list_add_end (void);
extern struct cleanup *record_gdb_operation_disable_set (void);
+extern void record_skip_entry_create (struct gdbarch *gdbarch,
+ const char *name,
+ int (*record) (struct regcache
*regcache));
+extern void record_skip_breakpoint_handler (struct frame_info *frame,
+ ptid_t ptid,
+ int skip_type);
#endif /* _RECORD_H_ */
Attachment:
3-skip-record-target.txt
Description: Text document
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |