From: msnyder Date: Fri, 23 Oct 2009 04:32:10 +0000 (+0000) Subject: 2009-10-22 Hui Zhu X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=a595e583f3434d030aab11c4fc250d776f24a183;p=pf3gnuchains%2Fpf3gnuchains3x.git 2009-10-22 Hui Zhu Michael Snyder * record.c (record_core_ops): New ops target vector. (record_core_open_1): New function. Open core target. (record_open_1): New function. Open normal process record. (record_open): Call one of the above. (record_close): Allow for both core and normal targets. (record_core_resume): New function. (record_core_kill): New function. (record_core_fetch_registers): New function. (record_core_prepare_to_store): New function. (record_core_store_registers): New function. (record_core_xfer_partial): New function. (record_core_insert_breakpoint): New function. (record_core_remove_breakpoint): New function. (record_core_has_execution): New function. (init_record_core_ops): New function. (_initialize_record): Call init_record_core_ops, add_target. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index faa1d07641..7583f91d1c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,23 @@ +2009-10-22 Hui Zhu + Michael Snyder + + * record.c (record_core_ops): New ops target vector. + (record_core_open_1): New function. Open core target. + (record_open_1): New function. Open normal process record. + (record_open): Call one of the above. + (record_close): Allow for both core and normal targets. + (record_core_resume): New function. + (record_core_kill): New function. + (record_core_fetch_registers): New function. + (record_core_prepare_to_store): New function. + (record_core_store_registers): New function. + (record_core_xfer_partial): New function. + (record_core_insert_breakpoint): New function. + (record_core_remove_breakpoint): New function. + (record_core_has_execution): New function. + (init_record_core_ops): New function. + (_initialize_record): Call init_record_core_ops, add_target. + 2009-10-22 Tristan Gingold * i386-darwin-nat.c (i386_darwin_fetch_inferior_registers): Use diff --git a/gdb/record.c b/gdb/record.c index 2ff33d67fb..608673a68b 100644 --- a/gdb/record.c +++ b/gdb/record.c @@ -23,15 +23,10 @@ #include "gdbthread.h" #include "event-top.h" #include "exceptions.h" -#include "completer.h" -#include "arch-utils.h" #include "gdbcore.h" #include "exec.h" #include "record.h" -#include "elf-bfd.h" -#include "gcore.h" -#include #include /* This module implements "target record", also known as "process @@ -59,8 +54,6 @@ #define RECORD_IS_REPLAY \ (record_list->next || execution_direction == EXEC_REVERSE) -#define RECORD_FILE_MAGIC netorder32(0x20091016) - /* These are the core structs of the process record functionality. A record_entry is a record of the value change of a register @@ -552,24 +545,24 @@ record_check_insn_num (int set_terminal) if (q) record_stop_at_limit = 0; else - error (_("Process record: stopped by user.")); + error (_("Process record: inferior program stopped.")); } } } } -static void -record_arch_list_cleanups (void *ignore) -{ - record_list_release (record_arch_list_tail); -} - /* Before inferior step (when GDB record the running message, inferior only can step), GDB will call this function to record the values to record_list. This function will call gdbarch_process_record to record the running message of inferior and set them to record_arch_list, and add it to record_list. */ +static void +record_message_cleanups (void *ignore) +{ + record_list_release (record_arch_list_tail); +} + struct record_message_args { struct regcache *regcache; enum target_signal signal; @@ -581,7 +574,7 @@ record_message (void *args) int ret; struct record_message_args *myargs = args; struct gdbarch *gdbarch = get_regcache_arch (myargs->regcache); - struct cleanup *old_cleanups = make_cleanup (record_arch_list_cleanups, 0); + struct cleanup *old_cleanups = make_cleanup (record_message_cleanups, 0); record_arch_list_head = NULL; record_arch_list_tail = NULL; @@ -721,8 +714,8 @@ record_exec_insn (struct regcache *regcache, struct gdbarch *gdbarch, { entry->u.mem.mem_entry_not_accessible = 1; if (record_debug) - warning ("Process record: error reading memory at " - "addr = %s len = %d.", + warning (_("Process record: error reading memory at " + "addr = %s len = %d."), paddress (gdbarch, entry->u.mem.addr), entry->u.mem.len); } @@ -734,8 +727,8 @@ record_exec_insn (struct regcache *regcache, struct gdbarch *gdbarch, { entry->u.mem.mem_entry_not_accessible = 1; if (record_debug) - warning ("Process record: error writing memory at " - "addr = %s len = %d.", + warning (_("Process record: error writing memory at " + "addr = %s len = %d."), paddress (gdbarch, entry->u.mem.addr), entry->u.mem.len); } @@ -772,8 +765,6 @@ static int (*tmp_to_insert_breakpoint) (struct gdbarch *, static int (*tmp_to_remove_breakpoint) (struct gdbarch *, struct bp_target_info *); -static void record_restore (void); - /* Open the process record target. */ static void @@ -800,7 +791,6 @@ record_core_open_1 (char *name, int from_tty) } push_target (&record_core_ops); - record_restore (); } /* "to_open" target method for 'live' processes. */ @@ -1448,8 +1438,8 @@ record_xfer_partial (struct target_ops *ops, enum target_object object, record_list_release (record_arch_list_tail); if (record_debug) fprintf_unfiltered (gdb_stdlog, - "Process record: failed to record " - "execution log."); + _("Process record: failed to record " + "execution log.")); return -1; } if (record_arch_list_add_end ()) @@ -1457,8 +1447,8 @@ record_xfer_partial (struct target_ops *ops, enum target_object object, record_list_release (record_arch_list_tail); if (record_debug) fprintf_unfiltered (gdb_stdlog, - "Process record: failed to record " - "execution log."); + _("Process record: failed to record " + "execution log.")); return -1; } record_list->next = record_arch_list_head; @@ -1895,513 +1885,9 @@ info_record_command (char *args, int from_tty) record_insn_max_num); } -/* Record log save-file format - Version 1 (never released) - - Header: - 4 bytes: magic number htonl(0x20090829). - NOTE: be sure to change whenever this file format changes! - - Records: - record_end: - 1 byte: record type (record_end, see enum record_type). - record_reg: - 1 byte: record type (record_reg, see enum record_type). - 8 bytes: register id (network byte order). - MAX_REGISTER_SIZE bytes: register value. - record_mem: - 1 byte: record type (record_mem, see enum record_type). - 8 bytes: memory length (network byte order). - 8 bytes: memory address (network byte order). - n bytes: memory value (n == memory length). - - Version 2 - 4 bytes: magic number netorder32(0x20091016). - NOTE: be sure to change whenever this file format changes! - - Records: - record_end: - 1 byte: record type (record_end, see enum record_type). - 4 bytes: signal - 4 bytes: instruction count - record_reg: - 1 byte: record type (record_reg, see enum record_type). - 4 bytes: register id (network byte order). - n bytes: register value (n == actual register size). - (eg. 4 bytes for x86 general registers). - record_mem: - 1 byte: record type (record_mem, see enum record_type). - 4 bytes: memory length (network byte order). - 8 bytes: memory address (network byte order). - n bytes: memory value (n == memory length). - -*/ - -/* bfdcore_read -- read bytes from a core file section. */ - -static inline void -bfdcore_read (bfd *obfd, asection *osec, void *buf, int len, int *offset) -{ - int ret = bfd_get_section_contents (obfd, osec, buf, *offset, len); - - if (ret) - *offset += len; - else - error (_("Failed to read %d bytes from core file %s ('%s').\n"), - len, bfd_get_filename (obfd), - bfd_errmsg (bfd_get_error ())); -} - -static inline uint64_t -netorder64 (uint64_t fromfile) -{ - return (BYTE_ORDER == LITTLE_ENDIAN) - ? bswap_64 (fromfile) - : fromfile; -} - -static inline uint32_t -netorder32 (uint32_t fromfile) -{ - return (BYTE_ORDER == LITTLE_ENDIAN) - ? bswap_32 (fromfile) - : fromfile; -} - -static inline uint16_t -netorder16 (uint16_t fromfile) -{ - return (BYTE_ORDER == LITTLE_ENDIAN) - ? bswap_16 (fromfile) - : fromfile; -} - -/* Restore the execution log from a core_bfd file. */ -static void -record_restore (void) -{ - uint32_t magic; - struct cleanup *old_cleanups; - struct record_entry *rec; - asection *osec; - uint32_t osec_size; - int bfd_offset = 0; - struct regcache *regcache; - - /* We restore the execution log from the open core bfd, - if there is one. */ - if (core_bfd == NULL) - return; - - /* "record_restore" can only be called when record list is empty. */ - gdb_assert (record_first.next == NULL); - - if (record_debug) - printf_filtered ("Restoring recording from core file.\n"); - - /* Now need to find our special note section. */ - osec = bfd_get_section_by_name (core_bfd, "null0"); - osec_size = bfd_section_size (core_bfd, osec); - if (record_debug) - printf_filtered ("Find precord section %s.\n", - osec ? "succeeded" : "failed"); - if (!osec) - return; - if (record_debug) - printf_filtered ("%s", bfd_section_name (core_bfd, osec)); - - /* Check the magic code. */ - bfdcore_read (core_bfd, osec, &magic, sizeof (magic), &bfd_offset); - if (magic != RECORD_FILE_MAGIC) - error (_("Version mis-match or file format error in core file %s."), - bfd_get_filename (core_bfd)); - if (record_debug) - printf_filtered ("\ - Reading 4-byte magic cookie RECORD_FILE_MAGIC (0x%08x)\n", - netorder32 (magic)); - - /* Restore the entries in recfd into record_arch_list_head and - record_arch_list_tail. */ - record_arch_list_head = NULL; - record_arch_list_tail = NULL; - record_insn_num = 0; - old_cleanups = make_cleanup (record_arch_list_cleanups, 0); - regcache = get_current_regcache (); - - while (1) - { - int ret; - uint8_t tmpu8; - uint32_t regnum, len, signal, count; - uint64_t addr; - - /* We are finished when offset reaches osec_size. */ - if (bfd_offset >= osec_size) - break; - bfdcore_read (core_bfd, osec, &tmpu8, sizeof (tmpu8), &bfd_offset); - - switch (tmpu8) - { - case record_reg: /* reg */ - /* Get register number to regnum. */ - bfdcore_read (core_bfd, osec, ®num, - sizeof (regnum), &bfd_offset); - regnum = netorder32 (regnum); - - rec = record_reg_alloc (regcache, regnum); - - /* Get val. */ - bfdcore_read (core_bfd, osec, record_get_loc (rec), - rec->u.reg.len, &bfd_offset); - - if (record_debug) - printf_filtered ("\ - Reading register %d (1 plus %d plus %d bytes)\n", - rec->u.reg.num, - sizeof (regnum), - rec->u.reg.len); - break; - - case record_mem: /* mem */ - /* Get len. */ - bfdcore_read (core_bfd, osec, &len, - sizeof (len), &bfd_offset); - len = netorder32 (len); - - /* Get addr. */ - bfdcore_read (core_bfd, osec, &addr, - sizeof (addr), &bfd_offset); - addr = netorder64 (addr); - - rec = record_mem_alloc (addr, len); - - /* Get val. */ - bfdcore_read (core_bfd, osec, record_get_loc (rec), - rec->u.mem.len, &bfd_offset); - - if (record_debug) - printf_filtered ("\ - Reading memory %s (1 plus %d plus %d plus %d bytes)\n", - paddress (get_current_arch (), - rec->u.mem.addr), - sizeof (addr), - sizeof (len), - rec->u.mem.len); - break; - - case record_end: /* end */ - rec = record_end_alloc (); - record_insn_num ++; - - /* Get signal value. */ - bfdcore_read (core_bfd, osec, &signal, - sizeof (signal), &bfd_offset); - signal = netorder32 (signal); - rec->u.end.sigval = signal; - - /* Get insn count. */ - bfdcore_read (core_bfd, osec, &count, - sizeof (count), &bfd_offset); - count = netorder32 (count); - rec->u.end.insn_num = count; - record_insn_count = count + 1; - if (record_debug) - printf_filtered ("\ - Reading record_end (1 + %d + %d bytes), offset == %s\n", - sizeof (signal), - sizeof (count), - paddress (get_current_arch (), - bfd_offset)); - break; - - default: - error (_("Bad entry type in core file %s."), - bfd_get_filename (core_bfd)); - break; - } - - /* Add rec to record arch list. */ - record_arch_list_add (rec); - } - - discard_cleanups (old_cleanups); - - /* Add record_arch_list_head to the end of record list. */ - record_first.next = record_arch_list_head; - record_arch_list_head->prev = &record_first; - record_arch_list_tail->next = NULL; - record_list = &record_first; - - /* Update record_insn_max_num. */ - if (record_insn_num > record_insn_max_num) - { - record_insn_max_num = record_insn_num; - warning (_("Auto increase record/replay buffer limit to %d."), - record_insn_max_num); - } - - /* Succeeded. */ - printf_filtered (_("Restored records from core file %s.\n"), - bfd_get_filename (core_bfd)); - - print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC); -} - -/* bfdcore_write -- write bytes into a core file section. */ - -static inline void -bfdcore_write (bfd *obfd, asection *osec, void *buf, int len, int *offset) -{ - int ret = bfd_set_section_contents (obfd, osec, buf, *offset, len); - - if (ret) - *offset += len; - else - error (_("Failed to write %d bytes to core file %s ('%s').\n"), - len, bfd_get_filename (obfd), - bfd_errmsg (bfd_get_error ())); -} - -/* Restore the execution log from a file. We use a modified elf - corefile format, with an extra section for our data. */ - -static void -cmd_record_restore (char *args, int from_tty) -{ - core_file_command (args, from_tty); - record_open (args, from_tty); -} - -static void -record_save_cleanups (void *data) -{ - bfd *obfd = data; - char *pathname = xstrdup (bfd_get_filename (obfd)); - bfd_close (obfd); - unlink (pathname); - xfree (pathname); -} - -/* Save the execution log to a file. We use a modified elf corefile - format, with an extra section for our data. */ - -static void -cmd_record_save (char *args, int from_tty) -{ - char *recfilename, recfilename_buffer[40]; - int recfd; - struct record_entry *cur_record_list; - uint32_t magic; - struct regcache *regcache; - struct gdbarch *gdbarch; - struct cleanup *old_cleanups; - struct cleanup *set_cleanups; - bfd *obfd; - int save_size = 0; - asection *osec = NULL; - int bfd_offset = 0; - - if (strcmp (current_target.to_shortname, "record") != 0) - error (_("This command can only be used with target 'record'.\n" - "Use 'target record' first.\n")); - - if (args && *args) - recfilename = args; - else - { - /* Default recfile name is "gdb_record.PID". */ - snprintf (recfilename_buffer, sizeof (recfilename_buffer), - "gdb_record.%d", PIDGET (inferior_ptid)); - recfilename = recfilename_buffer; - } - - /* Open the save file. */ - if (record_debug) - printf_filtered ("Saving execution log to core file '%s'\n", recfilename); - - /* Open the output file. */ - obfd = create_gcore_bfd (recfilename); - old_cleanups = make_cleanup (record_save_cleanups, obfd); - - /* Save the current record entry to "cur_record_list". */ - cur_record_list = record_list; - - /* Get the values of regcache and gdbarch. */ - regcache = get_current_regcache (); - gdbarch = get_regcache_arch (regcache); - - /* Disable the GDB operation record. */ - set_cleanups = record_gdb_operation_disable_set (); - - /* Reverse execute to the begin of record list. */ - while (1) - { - /* Check for beginning and end of log. */ - if (record_list == &record_first) - break; - - record_exec_insn (regcache, gdbarch, record_list); - - if (record_list->prev) - record_list = record_list->prev; - } - - /* Compute the size needed for the extra bfd section. */ - save_size = 4; /* magic cookie */ - for (record_list = record_first.next; record_list; - record_list = record_list->next) - switch (record_list->type) - { - case record_end: - save_size += 1 + 4 + 4; - break; - case record_reg: - save_size += 1 + 4 + record_list->u.reg.len; - break; - case record_mem: - save_size += 1 + 4 + 8 + record_list->u.mem.len; - break; - } - - /* Make the new bfd section. */ - osec = bfd_make_section_anyway_with_flags (obfd, "precord", - SEC_HAS_CONTENTS - | SEC_READONLY); - if (osec == NULL) - error (_("Failed to create 'precord' section for corefile %s: %s"), - recfilename, - bfd_errmsg (bfd_get_error ())); - bfd_set_section_size (obfd, osec, save_size); - bfd_set_section_vma (obfd, osec, 0); - bfd_set_section_alignment (obfd, osec, 0); - bfd_section_lma (obfd, osec) = 0; - - /* Save corefile state. */ - write_gcore_file (obfd); - - /* Write out the record log. */ - /* Write the magic code. */ - magic = RECORD_FILE_MAGIC; - if (record_debug) - printf_filtered ("\ - Writing 4-byte magic cookie RECORD_FILE_MAGIC (0x%08x)\n", - magic); - bfdcore_write (obfd, osec, &magic, sizeof (magic), &bfd_offset); - - /* Save the entries to recfd and forward execute to the end of - record list. */ - record_list = &record_first; - while (1) - { - /* Save entry. */ - if (record_list != &record_first) - { - uint8_t type; - uint32_t regnum, len, signal, count; - uint64_t addr; - - type = record_list->type; - bfdcore_write (obfd, osec, &type, sizeof (type), &bfd_offset); - - switch (record_list->type) - { - case record_reg: /* reg */ - if (record_debug) - printf_filtered ("\ - Writing register %d (1 plus %d plus %d bytes)\n", - record_list->u.reg.num, - sizeof (regnum), - record_list->u.reg.len); - - /* Write regnum. */ - regnum = netorder32 (record_list->u.reg.num); - bfdcore_write (obfd, osec, ®num, - sizeof (regnum), &bfd_offset); - - /* Write regval. */ - bfdcore_write (obfd, osec, record_get_loc (record_list), - record_list->u.reg.len, &bfd_offset); - break; - - case record_mem: /* mem */ - if (record_debug) - printf_filtered ("\ - Writing memory %s (1 plus %d plus %d plus %d bytes)\n", - paddress (gdbarch, - record_list->u.mem.addr), - sizeof (addr), - sizeof (len), - record_list->u.mem.len); - - /* Write memlen. */ - len = netorder32 (record_list->u.mem.len); - bfdcore_write (obfd, osec, &len, sizeof (len), &bfd_offset); - - /* Write memaddr. */ - addr = netorder64 (record_list->u.mem.addr); - bfdcore_write (obfd, osec, &addr, - sizeof (addr), &bfd_offset); - - /* Write memval. */ - bfdcore_write (obfd, osec, record_get_loc (record_list), - record_list->u.mem.len, &bfd_offset); - break; - - case record_end: - if (record_debug) - printf_filtered ("\ - Writing record_end (1 + %d + %d bytes)\n", - sizeof (signal), - sizeof (count)); - /* Write signal value. */ - signal = netorder32 (record_list->u.end.sigval); - bfdcore_write (obfd, osec, &signal, - sizeof (signal), &bfd_offset); - - /* Write insn count. */ - count = netorder32 (record_list->u.end.insn_num); - bfdcore_write (obfd, osec, &count, - sizeof (count), &bfd_offset); - break; - } - } - - /* Execute entry. */ - record_exec_insn (regcache, gdbarch, record_list); - - if (record_list->next) - record_list = record_list->next; - else - break; - } - - /* Reverse execute to cur_record_list. */ - while (1) - { - /* Check for beginning and end of log. */ - if (record_list == cur_record_list) - break; - - record_exec_insn (regcache, gdbarch, record_list); - - if (record_list->prev) - record_list = record_list->prev; - } - - do_cleanups (set_cleanups); - bfd_close (obfd); - discard_cleanups (old_cleanups); - - /* Succeeded. */ - printf_filtered (_("Saved core file %s with execution log.\n"), - recfilename); -} - void _initialize_record (void) { - struct cmd_list_element *c; - /* Init record_first. */ record_first.prev = NULL; record_first.next = NULL; @@ -2420,11 +1906,9 @@ _initialize_record (void) NULL, show_record_debug, &setdebuglist, &showdebuglist); - c = add_prefix_cmd ("record", class_obscure, cmd_record_start, - _("Abbreviated form of \"target record\" command."), - &record_cmdlist, "record ", 0, &cmdlist); - set_cmd_completer (c, filename_completer); - + add_prefix_cmd ("record", class_obscure, cmd_record_start, + _("Abbreviated form of \"target record\" command."), + &record_cmdlist, "record ", 0, &cmdlist); add_com_alias ("rec", "record", class_obscure, 1); add_prefix_cmd ("record", class_support, set_record_command, _("Set record options"), &set_record_cmdlist, @@ -2439,18 +1923,6 @@ _initialize_record (void) "info record ", 0, &infolist); add_alias_cmd ("rec", "record", class_obscure, 1, &infolist); - c = add_cmd ("save", class_obscure, cmd_record_save, - _("Save the execution log to a file.\n\ -Argument is optional filename.\n\ -Default filename is 'gdb_record.'."), - &record_cmdlist); - set_cmd_completer (c, filename_completer); - - c = add_cmd ("restore", class_obscure, cmd_record_restore, - _("Restore the execution log from a file.\n\ -Argument is filename. File must be created with 'record save'."), - &record_cmdlist); - set_cmd_completer (c, filename_completer); add_cmd ("delete", class_obscure, cmd_record_delete, _("Delete the rest of execution log and start recording it anew."),