diff -ruNa --exclude=CVS gdb-6.6/gdb/gdbarch.c gdb-6.6-record/gdb/gdbarch.c --- gdb-6.6/gdb/gdbarch.c 2006-11-11 03:20:35.000000000 +0800 +++ gdb-6.6-record/gdb/gdbarch.c 2007-10-10 10:48:10.000000000 +0800 @@ -234,6 +234,10 @@ gdbarch_register_reggroup_p_ftype *register_reggroup_p; gdbarch_fetch_pointer_argument_ftype *fetch_pointer_argument; gdbarch_regset_from_core_section_ftype *regset_from_core_section; +/*teawater rec begin----------------------------------------------------------*/ + gdbarch_record_ftype *record; + gdbarch_record_dasm_ftype *record_dasm; +/*teawater rec end------------------------------------------------------------*/ }; @@ -359,6 +363,10 @@ default_register_reggroup_p, /* register_reggroup_p */ 0, /* fetch_pointer_argument */ 0, /* regset_from_core_section */ +/*teawater rec begin----------------------------------------------------------*/ + NULL, + NULL, +/*teawater rec end------------------------------------------------------------*/ /* startup_gdbarch() */ }; @@ -4154,6 +4162,47 @@ flush_cached_frames (); } +/*teawater rec begin----------------------------------------------------------*/ +int +gdbarch_record_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return (gdbarch->record != NULL); +} + +int +gdbarch_record (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->record != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_record called\n"); + return (gdbarch->record ()); +} + +void +set_gdbarch_record (struct gdbarch *gdbarch, gdbarch_record_ftype *record) +{ + gdbarch->record = record; +} + +void +gdbarch_record_dasm (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->record_dasm != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_record_dasm called\n"); + gdbarch->record_dasm (); +} + +void +set_gdbarch_record_dasm (struct gdbarch *gdbarch, gdbarch_record_dasm_ftype *record_dasm) +{ + gdbarch->record_dasm = record_dasm; +} +/*teawater rec end------------------------------------------------------------*/ + extern void _initialize_gdbarch (void); void diff -ruNa --exclude=CVS gdb-6.6/gdb/gdbarch.h gdb-6.6-record/gdb/gdbarch.h --- gdb-6.6/gdb/gdbarch.h 2006-11-11 03:20:36.000000000 +0800 +++ gdb-6.6-record/gdb/gdbarch.h 2007-10-10 10:53:36.000000000 +0800 @@ -1612,4 +1612,14 @@ extern void gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file); +/*teawater rec begin----------------------------------------------------------*/ +extern int gdbarch_record_p (struct gdbarch *gdbarch); +typedef int (gdbarch_record_ftype) (void); +extern int gdbarch_record (struct gdbarch *gdbarch); +extern void set_gdbarch_record (struct gdbarch *gdbarch, gdbarch_record_ftype *record); +typedef void (gdbarch_record_dasm_ftype) (void); +extern void gdbarch_record_dasm (struct gdbarch *gdbarch); +extern void set_gdbarch_record_dasm (struct gdbarch *gdbarch, gdbarch_record_dasm_ftype *record_dasm); +/*teawater rec end------------------------------------------------------------*/ + #endif diff -ruNa --exclude=CVS gdb-6.6/gdb/infrun.c gdb-6.6-record/gdb/infrun.c --- gdb-6.6/gdb/infrun.c 2006-10-19 00:56:13.000000000 +0800 +++ gdb-6.6-record/gdb/infrun.c 2007-10-11 16:36:41.000000000 +0800 @@ -52,6 +52,11 @@ #include "gdb_assert.h" #include "mi/mi-common.h" +/*teawater rec begin----------------------------------------------------------*/ +#include "record.h" +static int record_resume_step = 0; +/*teawater rec end------------------------------------------------------------*/ + /* Prototypes for local functions */ static void signals_info (char *, int); @@ -532,6 +537,20 @@ fprintf_unfiltered (gdb_stdlog, "infrun: resume (step=%d, signal=%d)\n", step, sig); +/*teawater rec begin----------------------------------------------------------*/ + if (gdb_is_recording) { + if (record_list && (record_list->next || gdb_is_reverse)) { + discard_cleanups (old_cleanups); + record_wait_step = step; + return; + } + else { + step = 1; + record_message (); + } + } +/*teawater rec end------------------------------------------------------------*/ + /* FIXME: calling breakpoint_here_p (read_pc ()) three times! */ @@ -1000,10 +1019,19 @@ while (1) { +/*teawater rec begin----------------------------------------------------------*/ + if (record_list && (record_list->next || gdb_is_reverse)) { + ecs->ptid = record_wait (ecs->waiton_ptid, ecs->wp); + } + else { +/*teawater rec end------------------------------------------------------------*/ if (deprecated_target_wait_hook) ecs->ptid = deprecated_target_wait_hook (ecs->waiton_ptid, ecs->wp); else ecs->ptid = target_wait (ecs->waiton_ptid, ecs->wp); +/*teawater rec begin----------------------------------------------------------*/ + } +/*teawater rec end------------------------------------------------------------*/ /* Now figure out what to do with the result of the result. */ handle_inferior_event (ecs); @@ -1916,11 +1944,19 @@ be necessary for call dummies on a non-executable stack on SPARC. */ - if (stop_signal == TARGET_SIGNAL_TRAP) - ecs->random_signal - = !(bpstat_explains_signal (stop_bpstat) - || trap_expected - || (step_range_end && step_resume_breakpoint == NULL)); +/*teawater rec begin----------------------------------------------------------*/ + if (stop_signal == TARGET_SIGNAL_TRAP) { + if (gdb_is_reverse || gdb_is_recording) { + ecs->random_signal = 0; + } + else { + ecs->random_signal + = !(bpstat_explains_signal (stop_bpstat) + || trap_expected + || (step_range_end && step_resume_breakpoint == NULL)); + } + } +/*teawater rec end------------------------------------------------------------*/ else { ecs->random_signal = !bpstat_explains_signal (stop_bpstat); @@ -2424,6 +2460,16 @@ /* We're doing a "next", set a breakpoint at callee's return address (the address at which the caller will resume). */ + +/*teawater rec begin----------------------------------------------------------*/ + if (gdb_is_reverse || gdb_is_recording) { + record_resume_step = 1; + keep_going (ecs); + record_resume_step = 0; + return; + } +/*teawater rec end------------------------------------------------------------*/ + insert_step_resume_breakpoint_at_caller (get_current_frame ()); keep_going (ecs); return; @@ -2485,6 +2531,15 @@ return; } +/*teawater rec begin----------------------------------------------------------*/ + if ((gdb_is_reverse || gdb_is_recording) && step_over_calls == STEP_OVER_UNDEBUGGABLE) { + record_resume_step = 1; + keep_going (ecs); + record_resume_step = 0; + return; + } +/*teawater rec end------------------------------------------------------------*/ + /* Set a breakpoint at callee's return address (the address at which the caller will resume). */ insert_step_resume_breakpoint_at_caller (get_current_frame ()); @@ -2526,6 +2581,19 @@ ecs->sal = find_pc_line (stop_pc, 0); +/*teawater rec begin----------------------------------------------------------*/ + if (!frame_id_eq (get_frame_id (get_current_frame ()), step_frame_id) && (gdb_is_reverse || gdb_is_recording)) { + if ((stop_pc != ecs->sal.pc && gdb_is_reverse) || ( step_over_calls == STEP_OVER_ALL && gdb_is_recording)) { + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: maybe stepped into subroutine\n"); + record_resume_step = 1; + keep_going (ecs); + record_resume_step = 0; + return; + } + } +/*teawater rec end------------------------------------------------------------*/ + /* NOTE: tausq/2004-05-24: This if block used to be done before all the trampoline processing logic, however, there are some trampolines that have no names, so we should do trampoline handling first. */ @@ -2536,6 +2604,15 @@ if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: stepped into undebuggable function\n"); +/*teawater rec begin----------------------------------------------------------*/ + if (gdb_is_reverse || gdb_is_recording) { + record_resume_step = 1; + keep_going (ecs); + record_resume_step = 0; + return; + } +/*teawater rec end------------------------------------------------------------*/ + /* The inferior just stepped into, or returned to, an undebuggable function (where there is no debugging information and no line number corresponding to the address where the @@ -2585,15 +2662,28 @@ or can this happen as a result of a return or longjmp?). */ if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: no line number info\n"); + +/*teawater rec begin----------------------------------------------------------*/ + if ((step_over_calls == STEP_OVER_ALL && gdb_is_reverse) || gdb_is_recording) { + record_resume_step = 1; + keep_going (ecs); + record_resume_step = 0; + return; + } +/*teawater rec end------------------------------------------------------------*/ + stop_step = 1; print_stop_reason (END_STEPPING_RANGE, 0); stop_stepping (ecs); return; } - if ((stop_pc == ecs->sal.pc) +/*teawater rec begin----------------------------------------------------------*/ + //if ((stop_pc == ecs->sal.pc) + if (((stop_pc == ecs->sal.pc && !gdb_is_reverse) || (stop_pc >= ecs->sal.pc && stop_pc < ecs->sal.end && gdb_is_reverse)) && (ecs->current_line != ecs->sal.line || ecs->current_symtab != ecs->sal.symtab)) +/*teawater rec end------------------------------------------------------------*/ { /* We are at the start of a different line. So stop. Note that we don't stop if we step into the middle of a different line. @@ -2623,6 +2713,12 @@ we will be in mid-line. */ if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: stepped to a different function\n"); +/*teawater rec begin----------------------------------------------------------*/ + if (gdb_is_recording) { + keep_going (ecs); + return; + } +/*teawater rec end------------------------------------------------------------*/ stop_step = 1; print_stop_reason (END_STEPPING_RANGE, 0); stop_stepping (ecs); @@ -2669,11 +2765,13 @@ static int currently_stepping (struct execution_control_state *ecs) { +/*teawater rec begin----------------------------------------------------------*/ return ((!ecs->handling_longjmp && ((step_range_end && step_resume_breakpoint == NULL) || trap_expected)) || ecs->stepping_through_solib_after_catch - || bpstat_should_step ()); + || bpstat_should_step () || record_resume_step); +/*teawater rec end------------------------------------------------------------*/ } /* Subroutine call with source code we should not step over. Do step diff -ruNa --exclude=CVS gdb-6.6/gdb/Makefile.in gdb-6.6-record/gdb/Makefile.in --- gdb-6.6/gdb/Makefile.in 2006-11-25 03:54:14.000000000 +0800 +++ gdb-6.6-record/gdb/Makefile.in 2007-08-09 16:01:56.000000000 +0800 @@ -515,6 +515,7 @@ # Links made at configuration time should not be specified here, since # SFILES is used in building the distribution archive. +#teawater rec begin------------------------------------------------------------- SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c \ ax-general.c ax-gdb.c \ bcache.c \ @@ -562,7 +563,9 @@ user-regs.c \ valarith.c valops.c valprint.c value.c varobj.c vec.c \ wrapper.c \ - xml-support.c + xml-support.c \ + record.c +#teawater rec end--------------------------------------------------------------- LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c @@ -919,6 +922,7 @@ $(CONFIG_SRCS) TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR) +#teawater rec begin------------------------------------------------------------- COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ version.o \ annotate.o \ @@ -967,7 +971,9 @@ trad-frame.o \ tramp-frame.o \ solib.o solib-null.o \ - prologue-value.o memory-map.o xml-support.o target-memory.o + prologue-value.o memory-map.o xml-support.o target-memory.o \ + record.o +#teawater rec end--------------------------------------------------------------- TSOBS = inflow.o diff -ruNa --exclude=CVS gdb-6.6/gdb/mips-tdep.c gdb-6.6-record/gdb/mips-tdep.c --- gdb-6.6/gdb/mips-tdep.c 2006-08-09 05:32:37.000000000 +0800 +++ gdb-6.6-record/gdb/mips-tdep.c 2007-10-15 17:16:36.000000000 +0800 @@ -56,6 +56,11 @@ #include "infcall.h" #include "floatformat.h" +/*teawater rec begin----------------------------------------------------------*/ +#include "record.h" +#include +/*teawater rec end------------------------------------------------------------*/ + static const struct objfile_data *mips_pdr_data; static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum); @@ -4711,6 +4716,591 @@ internal_error (__FILE__, __LINE__, _("unknown ABI string")); } +/*teawater rec begin----------------------------------------------------------*/ +static CORE_ADDR mips_delay_slot_addr; +static CORE_ADDR mips_target_addr; + +static int +mips_record_32 (CORE_ADDR pc) +{ + uint32_t insn = (uint32_t)mips_fetch_instruction (pc); + uint32_t opcode; + const struct mips_regnum *regnum = mips_regnum (current_gdbarch); + int add_pc = 1; + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: mips_record_32 insn = 0x%08x\n", (unsigned int)insn); + } + + opcode = insn >> 26; + switch (opcode) { + case 0x00: + switch ((insn >> 0) & 0x3f) { + /* sll */ + case 0x00: + /* srl */ + case 0x02: + /* sra */ + case 0x03: + /* sllv */ + case 0x04: + /* srlv */ + case 0x06: + /* srav */ + case 0x07: + /* movz */ + case 0x0a: + /* movn */ + case 0x0b: + /* mfhi */ + case 0x10: + /* mflo */ + case 0x12: + /* add */ + case 0x20: + /* addu */ + case 0x21: + /* sub */ + case 0x22: + /* subu */ + case 0x23: + /* and */ + case 0x24: + /* or */ + case 0x25: + /* xor */ + case 0x26: + /* nor */ + case 0x27: + /* slt */ + case 0x2a: + /* sltu */ + case 0x2b: + goto set_rd; + break; + /* jr */ + case 0x08: + mips_target_addr = read_register ((insn >> 21) & 0x1f); + goto set_delay_slot_pc; + break; + /* jalr */ + case 0x09: + { + uint32_t rd = (insn >> 11) & 0x1f; + if (rd != 0) { + if (record_arch_list_add_reg (rd)) { + return (-1); + } + } + mips_target_addr = read_register ((insn >> 21) & 0x1f); + goto set_delay_slot_pc; + } + break; + /* sync */ + case 0x0f: + break; + /* mthi */ + case 0x11: + if (record_arch_list_add_reg (regnum->hi)) { + return (-1); + } + break; + /* mtlo */ + case 0x13: + if (record_arch_list_add_reg (regnum->lo)) { + return (-1); + } + break; + /* mult */ + case 0x18: + /* multu */ + case 0x19: + /* div */ + case 0x1a: + /* divu */ + case 0x1b: + goto set_hi_lo; + break; + default: + goto no_support; + break; + } + break; + + case 0x01: + switch ((insn >> 16) & 0x1f) { + /* bltz */ + case 0x00: + if (read_register ((insn >> 21) & 0x1f) < 0) { + goto set_imm_delay_slot_pc; + } + break; + /* bgez */ + case 0x01: + if (read_register ((insn >> 21) & 0x1f) >= 0) { + goto set_imm_delay_slot_pc; + } + break; + /* bltzl */ + case 0x02: + if (read_register ((insn >> 21) & 0x1f) < 0) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + /* bgezl */ + case 0x03: + if (read_register ((insn >> 21) & 0x1f) >= 0) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + /* bltzal */ + case 0x10: + if (record_arch_list_add_reg (31)) { + return (-1); + } + if (read_register ((insn >> 21) & 0x1f) < 0) { + goto set_imm_delay_slot_pc; + } + break; + /* bgezal */ + case 0x11: + if (record_arch_list_add_reg (31)) { + return (-1); + } + if (read_register ((insn >> 21) & 0x1f) >= 0) { + goto set_imm_delay_slot_pc; + } + break; + /* bltzall */ + case 0x12: + if (record_arch_list_add_reg (31)) { + return (-1); + } + if (read_register ((insn >> 21) & 0x1f) < 0) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + /* bgezall */ + case 0x13: + if (record_arch_list_add_reg (31)) { + return (-1); + } + if (read_register ((insn >> 21) & 0x1f) >= 0) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + default: + goto no_support; + break; + } + break; + + /* j */ + case 0x02: + mips_target_addr = (pc & 0xf0000000) | (((insn >> 0) & 0x03ffffff) << 2); + goto set_delay_slot_pc; + break; + + /* beq */ + case 0x04: + if (read_register ((insn >> 21) & 0x1f) == read_register ((insn >> 16) & 0x1f)) { + goto set_imm_delay_slot_pc; + } + break; + + /* bne */ + case 0x05: + if (read_register ((insn >> 21) & 0x1f) != read_register ((insn >> 16) & 0x1f)) { + goto set_imm_delay_slot_pc; + } + break; + + /* blez */ + case 0x06: + if (read_register ((insn >> 21) & 0x1f) <= 0) { + goto set_imm_delay_slot_pc; + } + break; + + /* bgtz */ + case 0x07: + if (read_register ((insn >> 21) & 0x1f) > 0) { + goto set_imm_delay_slot_pc; + } + break; + + /* beql */ + case 0x14: + if (read_register ((insn >> 21) & 0x1f) == read_register ((insn >> 16) & 0x1f)) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + + /* bnel */ + case 0x15: + if (read_register ((insn >> 21) & 0x1f) != read_register ((insn >> 16) & 0x1f)) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + + /* blezl */ + case 0x16: + if (read_register ((insn >> 21) & 0x1f) <= 0) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + + /* bgtzl */ + case 0x17: + if (read_register ((insn >> 21) & 0x1f) > 0) { + goto set_imm_delay_slot_pc; + } + else { + goto set_pc; + } + break; + + /* jal */ + case 0x03: + if (record_arch_list_add_reg (31)) { + return (-1); + } + mips_target_addr = (pc & 0xf0000000) | (((insn >> 0) & 0x03ffffff) << 2); + goto set_delay_slot_pc; + break; + + /* jalx */ + case 0x1d: + goto no_support; + break; + + /* addi */ + case 0x08: + /* addiu */ + case 0x09: + /* slti */ + case 0x0a: + /* sltiu */ + case 0x0b: + /* andi */ + case 0x0c: + /* ori */ + case 0x0d: + /* xori */ + case 0x0e: + /* lui */ + case 0x0f: + goto set_rt; + break; + + /* COP0 */ + case 0x10: + if ((insn >> 25) & 0x1) { + switch ((insn >> 0) & 0x3f) { + /* eret */ + case 0x18: + goto set_pc; + break; + default: + goto no_support; + break; + } + } + else { + switch ((insn >> 21) & 0x1f) { + /* mfc0 */ + case 0x00: + goto set_rt; + break; + /* mtc0 */ + case 0x04: + { + switch ((insn >> 11) & 0x1f) { + case 13: + /* Cause */ + if (record_arch_list_add_reg (regnum->cause)) { + return (-1); + } + case 8: + /* badvaddr */ + if (record_arch_list_add_reg (regnum->badvaddr)) { + return (-1); + } + } + } + break; + default: + goto no_support; + break; + } + } + break; + + case 0x1c: + switch ((insn >> 0) & 0x3f) { + /* madd */ + case 0x00: + /* maddu */ + case 0x01: + /* msub */ + case 0x04: + /* msubu */ + case 0x05: + goto set_hi_lo; + break; + /* mul */ + case 0x02: + { + uint32_t rd = (insn >> 11) & 0x1f; + if (rd != 0) { + if (record_arch_list_add_reg (rd)) { + return (-1); + } + } + goto set_hi_lo; + } + break; + /* clo */ + case 0x21: + /* clz */ + case 0x20: + goto set_rd; + break; + default: + goto no_support; + break; + } + break; + + /* lb */ + case 0x20: + /* lh */ + case 0x21: + /* lwl */ + case 0x22: + /* lw */ + case 0x23: + /* lbu */ + case 0x24: + /* lhu */ + case 0x25: + /* lwr */ + case 0x26: + /* ll */ + case 0x30: + goto set_rt; + break; + + /* sb */ + case 0x28: + /* sh */ + case 0x29: + /* swl */ + case 0x2a: + /* sw */ + case 0x2b: + /* swr */ + case 0x2e: + /* sc */ + case 0x38: + { + uint32_t addr; + + /* addr */ + /* base */ + addr = (insn >> 21) & 0x1f; + addr = read_register (addr); + /* offset */ + addr += (insn >> 0) & 0xffff; + + switch (opcode) { + /* sb */ + case 0x28: + if (record_arch_list_add_mem (addr, 1)) { + return (-1); + } + break; + /* sh */ + case 0x29: + if (record_arch_list_add_mem (addr, 2)) { + return (-1); + } + break; + /* swl */ + case 0x2a: + /* swr */ + case 0x2e: + if (record_arch_list_add_mem (addr & 0xffffff00, 2)) { + return (-1); + } + break; + /* sw */ + case 0x2b: + if (record_arch_list_add_mem (addr, 4)) { + return (-1); + } + break; + /* sc */ + case 0x38: + if (record_arch_list_add_mem (addr, 4)) { + return (-1); + } + goto set_rt; + break; + } + } + break; + /* pref */ + case 0x33: + break; + + default: + goto no_support; + break; + } + +out: + if (record_delay_slot) { + if (add_pc) { + if (record_arch_list_add_reg (regnum->pc)) { + return (-1); + } + add_pc = 0; + } + } + if (record_arch_list_add_end (add_pc)) { + return (-1); + } + return (0); + +no_support: + printf_unfiltered (_("record: record and reverse function don't support 32 bits instruction 0x%08x.\n"), (unsigned int)insn); + return (-1); + +set_rd: + { + uint32_t rd = (insn >> 11) & 0x1f; + if (rd != 0) { + if (record_arch_list_add_reg (rd)) { + return (-1); + } + } + } + goto out; + +set_rt: + { + uint32_t rt = (insn >> 16) & 0x1f; + if (rt != 0) { + if (record_arch_list_add_reg (rt)) { + return (-1); + } + } + } + goto out; + +set_imm_delay_slot_pc: + { + uint32_t imm = (insn >> 0) & 0xffff; + if (imm >> 15) { + imm |= 0xffff0000; + } + imm <<= 2; + mips_target_addr = pc + 4 + imm; + } + goto set_delay_slot_pc; + +set_delay_slot_pc: + mips_delay_slot_addr = pc + 4; + record_delay_slot ++; + goto set_pc; + +set_pc: + if (record_arch_list_add_reg (regnum->pc)) { + return (-1); + } + add_pc = 0; + goto out; + +set_hi_lo: + if (record_arch_list_add_reg (regnum->hi)) { + return (-1); + } + if (record_arch_list_add_reg (regnum->lo)) { + return (-1); + } + goto out; +} + +static int +mips_record (void) +{ + CORE_ADDR pc = read_pc (); + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: mips_record pc = 0x%s\n", paddr_nz (pc)); + } + + if (mips_pc_is_mips16 (pc)) { + printf_unfiltered (_("record: record and reverse function don't support mips16.\n")); + return (-1); + } + + if (record_delay_slot) { + if (mips_record_32 (mips_delay_slot_addr)) { + return (-1); + } + if (mips_record_32 (mips_target_addr)) { + return (-1); + } + record_delay_slot --; + } + return (mips_record_32 (pc)); +} + +static void +mips_record_dasm (void) +{ + const struct mips_regnum *regnum; + ULONGEST pc; + + if (mips_pc_is_mips16 (read_pc ())) { + error (_("record: record and reverse function don't support mips16.\n")); + } + + regnum = mips_regnum (current_gdbarch); + regcache_cooked_read_unsigned (current_regcache, regnum->pc, &pc); + if (gdb_is_reverse) { + pc -= 4; + } + else { + pc += 4; + } + regcache_cooked_write_unsigned (current_regcache, regnum->pc, pc); +} +/*teawater rec end------------------------------------------------------------*/ + static struct gdbarch * mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { @@ -5163,6 +5753,11 @@ frame_base_append_sniffer (gdbarch, mips_insn16_frame_base_sniffer); frame_base_append_sniffer (gdbarch, mips_insn32_frame_base_sniffer); +/*teawater rec begin----------------------------------------------------------*/ + set_gdbarch_record (gdbarch, mips_record); + set_gdbarch_record_dasm (gdbarch, mips_record_dasm); +/*teawater rec end------------------------------------------------------------*/ + return gdbarch; } diff -ruNa --exclude=CVS gdb-6.6/gdb/record.c gdb-6.6-record/gdb/record.c --- gdb-6.6/gdb/record.c 1970-01-01 08:00:00.000000000 +0800 +++ gdb-6.6-record/gdb/record.c 2007-10-16 11:46:16.000000000 +0800 @@ -0,0 +1,432 @@ +/* Record v0.1.0 for GDB, the GNU debugger. + Written by Teawater Zhu + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "inferior.h" +#include "bfd.h" +#include "symfile.h" +#include "gdbcmd.h" +#include "gdbcore.h" +#include "serial.h" +#include "target.h" +#include "exceptions.h" +#include "remote-utils.h" +#include "gdb_string.h" +#include "gdb_stat.h" +#include "regcache.h" +#include +#include +#include "mips-tdep.h" +#include +#include +#include +#include +#include "frame-unwind.h" +#include "gdbthread.h" +#include "exceptions.h" +#include "infcall.h" +#include "source.h" +#include "record.h" + +extern struct bp_location *bp_location_chain; + +record_t *record_list = NULL; +record_t *record_arch_list_head = NULL; +record_t *record_arch_list_tail = NULL; +unsigned int gdb_is_recording = 0; +int gdb_is_reverse = 0; +int debug_record = 0; +int record_wait_step = 0; +int record_delay_slot = 0; +static sigset_t record_maskall; +static int record_get_sig = 0; + +static void +show_debug_record (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Record debugging is %s.\n"), value); +} + +static void +record_list_release (record_t *rec) +{ + record_t *tmp; + + while (rec) { + tmp = rec; + rec = rec->prev; + xfree (tmp); + } +} + +void +record_message (void) +{ + int ret; + int need_dasm = 0; + + record_arch_list_head = NULL; + record_arch_list_tail = NULL; + + if (gdbarch_record (current_gdbarch)) { + record_delay_slot = 0; + record_list_release (record_arch_list_tail); + error (_("record: record message error.")); + } + + if (record_list) { + record_list->next = record_arch_list_head; + record_arch_list_head->prev = record_list; + record_list = record_arch_list_tail; + } + else { + record_list = record_arch_list_tail; + } +} + +static void +record_arch_list_add (record_t *rec) +{ + if (record_arch_list_tail) { + record_arch_list_tail->next = rec; + rec->prev = record_arch_list_tail; + record_arch_list_tail = rec; + } + else { + record_arch_list_head = rec; + record_arch_list_tail = rec; + } +} + +int +record_arch_list_add_reg (int num) +{ + record_t *rec; + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: add reg num = %d to arch list.\n", num); + } + + rec = (record_t *)xmalloc (sizeof (record_t)); + if (!rec) { + fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n"); + return (-1); + } + rec->u.reg.val = (gdb_byte *)xmalloc (MAX_REGISTER_SIZE); + if (!rec->u.reg.val) { + fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n"); + xfree (rec); + return (-1); + } + rec->prev = NULL; + rec->next = NULL; + rec->type = 1; + rec->u.reg.num = num; + + regcache_cooked_read (current_regcache, num, rec->u.reg.val); + + record_arch_list_add (rec); + + return (0); +} + +int +record_arch_list_add_mem (CORE_ADDR addr, int len) +{ + record_t *rec; + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: add mem addr = 0x%s len = %d to arch list.\n", paddr_nz (addr), len); + } + + rec = (record_t *)xmalloc (sizeof (record_t)); + if (!rec) { + fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n"); + return (-1); + } + rec->u.mem.val = (gdb_byte *)xmalloc (len); + if (!rec->u.mem.val) { + fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n"); + xfree (rec); + return (-1); + } + rec->prev = NULL; + rec->next = NULL; + rec->type = 2; + rec->u.mem.addr = addr; + rec->u.mem.len = len; + + if (target_read_memory (addr, rec->u.mem.val, len)) { + xfree (rec->u.reg.val); + xfree (rec); + return (-1); + } + + record_arch_list_add (rec); + + return (0); +} + +int +record_arch_list_add_end (int need_dasm) +{ + record_t *rec; + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: add end need_dasm = %d to arch list.\n", need_dasm); + } + + rec = (record_t *)xmalloc (sizeof (record_t)); + if (!rec) { + fprintf_unfiltered (gdb_stdlog, "record: alloc memory error.\n"); + return (-1); + } + rec->prev = NULL; + rec->next = NULL; + rec->type = 0; + + rec->u.need_dasm = need_dasm; + + record_arch_list_add (rec); + + return (0); +} + +static void +record_sig_handler (int signo) +{ + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: get a signal\n"); + } + record_wait_step = 1; + record_get_sig = 1; +} + +ptid_t +record_wait (ptid_t ptid, struct target_waitstatus *status) +{ + struct sigaction act, old_act; + static int state = 0; /* 0 normal 1 to the end 2 to the begin */ + int con = 1; + int insn_end = 0; + int need_dasm = 0; + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: record_wait step = %d\n", record_wait_step); + } + + record_get_sig = 0; + act.sa_handler = record_sig_handler; + act.sa_mask = record_maskall; + act.sa_flags = SA_RESTART; + if (sigaction (SIGINT, &act, &old_act)) { + perror_with_name (_("sigaction")); + } + + do { + /* check state */ + if ((gdb_is_reverse && !record_list->prev && state == 2) || (!gdb_is_reverse && !record_list->next && state == 1)) { + if (debug_record) { + if (state == 1) { + fprintf_unfiltered (gdb_stdlog, "record: running to the end of record list.\n"); + } + else if (state == 2) { + fprintf_unfiltered (gdb_stdlog, "record: running to the begin of record list.\n"); + } + } + stop_soon = STOP_QUIETLY; + break; + } + state = 0; + + /* set register and memory according to record_list */ + if (record_list->type == 1) { + /* reg */ + gdb_byte reg[MAX_REGISTER_SIZE]; + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: record_list reg num = %d to arch list.\n", record_list->u.reg.num); + } + regcache_cooked_read (current_regcache, record_list->u.reg.num, reg); + regcache_cooked_write (current_regcache, record_list->u.reg.num, record_list->u.reg.val); + memcpy (record_list->u.reg.val, reg, MAX_REGISTER_SIZE); + } + else if (record_list->type == 2) { + /* mem */ + gdb_byte mem[record_list->u.mem.len]; + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: record_list mem addr = 0x%s len = %d to current.\n", paddr_nz (record_list->u.mem.addr), record_list->u.mem.len); + } + if (target_read_memory (record_list->u.mem.addr, mem, record_list->u.mem.len)) { + error (_("record: read memory addr = 0x%s len = %d error."), paddr_nz (record_list->u.mem.addr), record_list->u.mem.len); + } + if (target_write_memory (record_list->u.mem.addr, record_list->u.mem.val, record_list->u.mem.len)) { + error (_("record: write memory addr = 0x%s len = %d error."), paddr_nz (record_list->u.mem.addr), record_list->u.mem.len); + } + memcpy (record_list->u.mem.val, mem, record_list->u.mem.len); + } + else { + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: record_list end need_dasm = %d to current.\n", record_list->u.need_dasm); + } + + need_dasm = record_list->u.need_dasm; + if (!gdb_is_reverse) { + insn_end = 1; + } + } + + if (gdb_is_reverse) { + if (record_list->prev) { + record_list = record_list->prev; + if (!record_list->type) { + insn_end = 1; + } + } + else { + state = 2; + insn_end = 1; + } + } + else { + if (record_list->next) { + record_list = record_list->next; + } + else { + state = 1; + } + } + + if (insn_end) { + struct bp_location *b; + CORE_ADDR tmp_pc; + + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: insn end need_dasm = %d to current.\n", need_dasm); + } + + if (need_dasm) { + gdbarch_record_dasm (current_gdbarch); + } + + //registers_changed (); + tmp_pc = read_pc (); + + /* end */ + if (record_wait_step) { + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: step.\n"); + } + con = 0; + } + + /* check breakpoint */ + for (b = bp_location_chain; b; b = b->next) { + if (b->inserted) { + if (b->target_info.placed_address == tmp_pc) { + if (debug_record) { + fprintf_unfiltered (gdb_stdlog, "record: break at 0x%s.\n", paddr_nz (tmp_pc)); + } + con = 0; + break; + } + } + } + + insn_end = 0; + } + } while (con); + + if (sigaction (SIGALRM, &old_act, NULL)) { + perror_with_name (_("sigaction")); + } + + status->kind = TARGET_WAITKIND_STOPPED; + if (record_get_sig) { + status->value.sig = TARGET_SIGNAL_INT; + } + else { + status->value.sig = TARGET_SIGNAL_TRAP; + } + + return (inferior_ptid); +} + +void +record_close (void) +{ + gdb_is_recording = 0; + gdb_is_reverse = 0; + record_list_release (record_list); + record_list = NULL; + record_delay_slot = 0; + printf_unfiltered (_("record: record and reverse function is stopped.\n")); +} + +static void +cmd_record (char *args, int from_tty) +{ + /* check exec */ + if (!target_has_execution) { + error (_("record: the program is not being run.")); + } + + if (!gdbarch_record_p (current_gdbarch)) { + error (_("record: the current gdbarch don't support record function.")); + } + + if (gdb_is_recording) { + record_close (); + } + else { + gdb_is_recording = 1; + printf_unfiltered (_("record: record and reverse function is started.\n")); + } +} + +static void +cmd_reverse (char *args, int from_tty) +{ + if (gdb_is_reverse) { + gdb_is_reverse = 0; + printf_unfiltered (_("record: GDB is set to normal debug mode.\n")); + } + else { + if (!record_list) { + error (_("record: record and reverse function is not started.")); + } + gdb_is_reverse = 1; + printf_unfiltered (_("record: GDB is set to reverse debug mode.\n")); + } +} + +void +_initialize_record (void) +{ + /* init record_maskall */ + if (sigfillset (&record_maskall) == -1) { + perror_with_name (_("sigfillset")); + } + + add_setshow_zinteger_cmd ("record", class_maintenance, &debug_record, _("Set record debugging."), _("Show record debugging."), _("When non-zero, record specific debugging is enabled."), NULL, show_debug_record, &setdebuglist, &showdebuglist); + add_com ("record", class_obscure, cmd_record, _("Start or stop the record and reverse function.")); + add_com_alias ("rec", "record", class_obscure, 1); + add_com ("reverse", class_obscure, cmd_reverse, _("Set GDB to the reverse debug mode or the normal debug mode.")); + add_com_alias ("rev", "reverse", class_obscure, 1); +} diff -ruNa --exclude=CVS gdb-6.6/gdb/record.h gdb-6.6-record/gdb/record.h --- gdb-6.6/gdb/record.h 1970-01-01 08:00:00.000000000 +0800 +++ gdb-6.6-record/gdb/record.h 2007-10-16 11:46:41.000000000 +0800 @@ -0,0 +1,65 @@ +/* Record v0.1.0 for GDB, the GNU debugger. + Written by Teawater Zhu + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _RECORD_H_ +#define _RECORD_H_ + +typedef struct record_reg_s { + int num; + gdb_byte *val; +} record_reg_t; + +typedef struct record_mem_s { + CORE_ADDR addr; + int len; + gdb_byte *val; +} record_mem_t; + +typedef struct record_s { + struct record_s *prev; + struct record_s *next; + int type; /* 1 reg 2 mem 0 end */ + union { + /* reg */ + record_reg_t reg; + /* mem */ + record_mem_t mem; + /* end */ + int need_dasm; + } u; +} record_t; + +extern record_t *record_list; +extern record_t *record_arch_list_head; +extern record_t *record_arch_list_tail; +extern int record_arch_need_dasm; +extern unsigned int gdb_is_recording; +extern int gdb_is_reverse; +extern int debug_record; +extern int record_wait_step; +extern int record_delay_slot; + +extern void record_message (void); +extern int record_arch_list_add_reg (int num); +extern int record_arch_list_add_mem (CORE_ADDR addr, int len); +extern int record_arch_list_add_end (int need_dasm); +extern ptid_t record_wait (ptid_t ptid, struct target_waitstatus * status); +extern void record_close (void); +#endif //_RECORD_H_ diff -ruNa --exclude=CVS gdb-6.6/gdb/target.c gdb-6.6-record/gdb/target.c --- gdb-6.6/gdb/target.c 2006-10-18 05:55:23.000000000 +0800 +++ gdb-6.6-record/gdb/target.c 2007-10-16 11:49:47.000000000 +0800 @@ -40,6 +40,9 @@ #include "gdb_assert.h" #include "gdbcore.h" #include "exceptions.h" +/*teawater rec begin----------------------------------------------------------*/ +#include "record.h" +/*teawater rec end------------------------------------------------------------*/ static void target_info (char *, int); @@ -2034,6 +2037,11 @@ void target_close (struct target_ops *targ, int quitting) { +/*teawater rec begin----------------------------------------------------------*/ + if (gdb_is_recording) { + record_close (); + } +/*teawater rec end------------------------------------------------------------*/ if (targ->to_xclose != NULL) targ->to_xclose (targ, quitting); else if (targ->to_close != NULL)