X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gdb%2Frecord-full.c;h=e83ce01b71539445230379365ed6de57f97439c5;hb=e699d33164a59dcfe7ad4a5154e5c6c811c1f958;hp=58f4be4fea0a55e5a9895b195ede9816d6110e4e;hpb=57810aa7e8032c598897454daea14ed17df0f89d;p=external%2Fbinutils.git diff --git a/gdb/record-full.c b/gdb/record-full.c index 58f4be4..e83ce01 100644 --- a/gdb/record-full.c +++ b/gdb/record-full.c @@ -1,6 +1,6 @@ /* Process record and replay target for GDB, the GNU debugger. - Copyright (C) 2013-2018 Free Software Foundation, Inc. + Copyright (C) 2013-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -21,6 +21,7 @@ #include "gdbcmd.h" #include "regcache.h" #include "gdbthread.h" +#include "inferior.h" #include "event-top.h" #include "completer.h" #include "arch-utils.h" @@ -35,8 +36,8 @@ #include "gdb_bfd.h" #include "observable.h" #include "infrun.h" -#include "common/gdb_unlinker.h" -#include "common/byte-vector.h" +#include "gdbsupport/gdb_unlinker.h" +#include "gdbsupport/byte-vector.h" #include @@ -206,24 +207,21 @@ static unsigned int record_full_insn_num = 0; than count of insns presently in execution log). */ static ULONGEST record_full_insn_count; +static const char record_longname[] + = N_("Process record and replay target"); +static const char record_doc[] + = N_("Log program while executing and replay execution from log."); + /* Base class implementing functionality common to both the "record-full" and "record-core" targets. */ class record_full_base_target : public target_ops { public: - record_full_base_target () - { to_stratum = record_stratum; } - - const char *shortname () override = 0; - - const char *longname () override - { return _("Process record and replay target"); } + const target_info &info () const override = 0; - const char *doc () override - { return _("Log program while executing and replay execution from log."); } + strata stratum () const override { return record_stratum; } - void open (const char *, int) override; void close () override; void async (int) override; ptid_t wait (ptid_t, struct target_waitstatus *, int) override; @@ -257,11 +255,17 @@ public: /* The "record-full" target. */ +static const target_info record_full_target_info = { + "record-full", + record_longname, + record_doc, +}; + class record_full_target final : public record_full_base_target { public: - const char *shortname () override - { return "record-full"; } + const target_info &info () const override + { return record_full_target_info; } void commit_resume () override; void resume (ptid_t, int, enum gdb_signal) override; @@ -285,11 +289,17 @@ public: /* The "record-core" target. */ +static const target_info record_full_core_target_info = { + "record-core", + record_longname, + record_doc, +}; + class record_full_core_target final : public record_full_base_target { public: - const char *shortname () override - { return "record-core"; } + const target_info &info () const override + { return record_full_core_target_info; } void resume (ptid_t, int, enum gdb_signal) override; void disconnect (const char *, int) override; @@ -610,7 +620,7 @@ record_full_arch_list_add_reg (struct regcache *regcache, int regnum) rec = record_full_reg_alloc (regcache, regnum); - regcache_raw_read (regcache, regnum, record_full_get_loc (rec)); + regcache->raw_read (regnum, record_full_get_loc (rec)); record_full_arch_list_add (rec); @@ -686,12 +696,6 @@ record_full_check_insn_num (void) } } -static void -record_full_arch_list_cleanups (void *ignore) -{ - record_full_list_release (record_full_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_full_list. This function will call gdbarch_process_record to @@ -703,61 +707,66 @@ record_full_message (struct regcache *regcache, enum gdb_signal signal) { int ret; struct gdbarch *gdbarch = regcache->arch (); - struct cleanup *old_cleanups - = make_cleanup (record_full_arch_list_cleanups, 0); - record_full_arch_list_head = NULL; - record_full_arch_list_tail = NULL; + try + { + record_full_arch_list_head = NULL; + record_full_arch_list_tail = NULL; - /* Check record_full_insn_num. */ - record_full_check_insn_num (); + /* Check record_full_insn_num. */ + record_full_check_insn_num (); + + /* If gdb sends a signal value to target_resume, + save it in the 'end' field of the previous instruction. - /* If gdb sends a signal value to target_resume, - save it in the 'end' field of the previous instruction. + Maybe process record should record what really happened, + rather than what gdb pretends has happened. - 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. - 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). - 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. - 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_full_wait, not + record_full_resume. */ + if (record_full_list != &record_full_first) /* FIXME better way + to check */ + { + gdb_assert (record_full_list->type == record_full_end); + record_full_list->u.end.sigval = signal; + } - 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_full_wait, not - record_full_resume. */ - if (record_full_list != &record_full_first) /* FIXME better way to check */ + if (signal == GDB_SIGNAL_0 + || !gdbarch_process_record_signal_p (gdbarch)) + ret = gdbarch_process_record (gdbarch, + regcache, + regcache_read_pc (regcache)); + else + ret = gdbarch_process_record_signal (gdbarch, + regcache, + signal); + + if (ret > 0) + error (_("Process record: inferior program stopped.")); + if (ret < 0) + error (_("Process record: failed to record execution log.")); + } + catch (const gdb_exception &ex) { - gdb_assert (record_full_list->type == record_full_end); - record_full_list->u.end.sigval = signal; + record_full_list_release (record_full_arch_list_tail); + throw; } - if (signal == GDB_SIGNAL_0 - || !gdbarch_process_record_signal_p (gdbarch)) - ret = gdbarch_process_record (gdbarch, - regcache, - regcache_read_pc (regcache)); - else - ret = gdbarch_process_record_signal (gdbarch, - regcache, - signal); - - if (ret > 0) - error (_("Process record: inferior program stopped.")); - if (ret < 0) - error (_("Process record: failed to record execution log.")); - - discard_cleanups (old_cleanups); - record_full_list->next = record_full_arch_list_head; record_full_arch_list_head->prev = record_full_list; record_full_list = record_full_arch_list_tail; @@ -772,16 +781,15 @@ static bool record_full_message_wrapper_safe (struct regcache *regcache, enum gdb_signal signal) { - TRY + try { record_full_message (regcache, signal); } - CATCH (ex, RETURN_MASK_ALL) + catch (const gdb_exception &ex) { exception_print (gdb_stderr, ex); return false; } - END_CATCH return true; } @@ -823,9 +831,8 @@ record_full_exec_insn (struct regcache *regcache, host_address_to_string (entry), entry->u.reg.num); - regcache_cooked_read (regcache, entry->u.reg.num, reg.data ()); - regcache_cooked_write (regcache, entry->u.reg.num, - record_full_get_loc (entry)); + regcache->cooked_read (entry->u.reg.num, reg.data ()); + regcache->cooked_write (entry->u.reg.num, record_full_get_loc (entry)); memcpy (record_full_get_loc (entry), reg.data (), entry->u.reg.len); } break; @@ -900,7 +907,7 @@ record_full_async_inferior_event_handler (gdb_client_data data) inferior_event_handler (INF_REG_EVENT, NULL); } -/* Open the process record target. */ +/* Open the process record target for 'core' files. */ static void record_full_core_open_1 (const char *name, int from_tty) @@ -930,7 +937,7 @@ record_full_core_open_1 (const char *name, int from_tty) record_full_restore (); } -/* "open" target method for 'live' processes. */ +/* Open the process record target for 'live' processes. */ static void record_full_open_1 (const char *name, int from_tty) @@ -954,10 +961,10 @@ record_full_open_1 (const char *name, int from_tty) static void record_full_init_record_breakpoints (void); -/* "open" target method. Open the process record target. */ +/* Open the process record target. */ -void -record_full_base_target::open (const char *name, int from_tty) +static void +record_full_open (const char *name, int from_tty) { if (record_debug) fprintf_unfiltered (gdb_stdlog, "Process record: record_full_open\n"); @@ -1005,15 +1012,11 @@ record_full_base_target::close () } /* Release record_full_core_buf_list. */ - if (record_full_core_buf_list) + while (record_full_core_buf_list) { - for (entry = record_full_core_buf_list->prev; entry; - entry = entry->prev) - { - xfree (record_full_core_buf_list); - record_full_core_buf_list = entry; - } - record_full_core_buf_list = NULL; + entry = record_full_core_buf_list; + record_full_core_buf_list = record_full_core_buf_list->prev; + xfree (entry); } if (record_full_async_inferior_event_token) @@ -1030,7 +1033,7 @@ record_full_base_target::async (int enable) else clear_async_event_handler (record_full_async_inferior_event_token); - beneath->async (enable); + beneath ()->async (enable); } static int record_full_resume_step = 0; @@ -1093,9 +1096,9 @@ record_full_target::resume (ptid_t ptid, int step, enum gdb_signal signal) } /* Make sure the target beneath reports all signals. */ - target_pass_signals (0, NULL); + target_pass_signals ({}); - this->beneath->resume (ptid, step, signal); + this->beneath ()->resume (ptid, step, signal); } /* We are about to start executing the inferior (or simulate it), @@ -1110,7 +1113,7 @@ void record_full_target::commit_resume () { if (!RECORD_FULL_IS_REPLAY) - beneath->commit_resume (); + beneath ()->commit_resume (); } static int record_full_get_sig = 0; @@ -1131,18 +1134,6 @@ record_full_sig_handler (int signo) record_full_get_sig = 1; } -static void -record_full_wait_cleanups (void *ignore) -{ - if (execution_direction == EXEC_REVERSE) - { - if (record_full_list->next) - record_full_list = record_full_list->next; - } - else - record_full_list = record_full_list->prev; -} - /* "wait" target method for process record target. In record mode, the target is always run in singlestep mode @@ -1192,7 +1183,7 @@ record_full_wait_1 (struct target_ops *ops, if (record_full_resume_step) { /* This is a single step. */ - return ops->beneath->wait (ptid, status, options); + return ops->beneath ()->wait (ptid, status, options); } else { @@ -1203,9 +1194,7 @@ record_full_wait_1 (struct target_ops *ops, while (1) { - struct thread_info *tp; - - ret = ops->beneath->wait (ptid, status, options); + ret = ops->beneath ()->wait (ptid, status, options); if (status->kind == TARGET_WAITKIND_IGNORE) { if (record_debug) @@ -1215,7 +1204,7 @@ record_full_wait_1 (struct target_ops *ops, return ret; } - ALL_NON_EXITED_THREADS (tp) + for (thread_info *tp : all_non_exited_threads ()) delete_single_step_breakpoints (tp); if (record_full_resume_step) @@ -1281,8 +1270,8 @@ record_full_wait_1 (struct target_ops *ops, "Process record: record_full_wait " "issuing one more step in the " "target beneath\n"); - ops->beneath->resume (ptid, step, GDB_SIGNAL_0); - ops->beneath->commit_resume (); + ops->beneath ()->resume (ptid, step, GDB_SIGNAL_0); + ops->beneath ()->commit_resume (); continue; } } @@ -1301,144 +1290,162 @@ record_full_wait_1 (struct target_ops *ops, const struct address_space *aspace = regcache->aspace (); int continue_flag = 1; int first_record_full_end = 1; - struct cleanup *old_cleanups - = make_cleanup (record_full_wait_cleanups, 0); - CORE_ADDR tmp_pc; - record_full_stop_reason = TARGET_STOPPED_BY_NO_REASON; - status->kind = TARGET_WAITKIND_STOPPED; - - /* Check breakpoint when forward execute. */ - if (execution_direction == EXEC_FORWARD) + try { - tmp_pc = regcache_read_pc (regcache); - if (record_check_stopped_by_breakpoint (aspace, tmp_pc, - &record_full_stop_reason)) - { - if (record_debug) - fprintf_unfiltered (gdb_stdlog, - "Process record: break at %s.\n", - paddress (gdbarch, tmp_pc)); - goto replay_out; - } - } + CORE_ADDR tmp_pc; - /* If GDB is in terminal_inferior mode, it will not get the signal. - And in GDB replay mode, GDB doesn't need to be in terminal_inferior - mode, because inferior will not executed. - Then set it to terminal_ours to make GDB get the signal. */ - target_terminal::ours (); + record_full_stop_reason = TARGET_STOPPED_BY_NO_REASON; + status->kind = TARGET_WAITKIND_STOPPED; - /* In EXEC_FORWARD mode, record_full_list points to the tail of prev - instruction. */ - if (execution_direction == EXEC_FORWARD && record_full_list->next) - record_full_list = record_full_list->next; - - /* Loop over the record_full_list, looking for the next place to - stop. */ - do - { - /* Check for beginning and end of log. */ - if (execution_direction == EXEC_REVERSE - && record_full_list == &record_full_first) + /* Check breakpoint when forward execute. */ + if (execution_direction == EXEC_FORWARD) { - /* Hit beginning of record log in reverse. */ - status->kind = TARGET_WAITKIND_NO_HISTORY; - break; - } - if (execution_direction != EXEC_REVERSE && !record_full_list->next) - { - /* Hit end of record log going forward. */ - status->kind = TARGET_WAITKIND_NO_HISTORY; - break; + tmp_pc = regcache_read_pc (regcache); + if (record_check_stopped_by_breakpoint (aspace, tmp_pc, + &record_full_stop_reason)) + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, + "Process record: break at %s.\n", + paddress (gdbarch, tmp_pc)); + goto replay_out; + } } - record_full_exec_insn (regcache, gdbarch, record_full_list); - - if (record_full_list->type == record_full_end) + /* If GDB is in terminal_inferior mode, it will not get the + signal. And in GDB replay mode, GDB doesn't need to be + in terminal_inferior mode, because inferior will not + executed. Then set it to terminal_ours to make GDB get + the signal. */ + target_terminal::ours (); + + /* In EXEC_FORWARD mode, record_full_list points to the tail of prev + instruction. */ + if (execution_direction == EXEC_FORWARD && record_full_list->next) + record_full_list = record_full_list->next; + + /* Loop over the record_full_list, looking for the next place to + stop. */ + do { - if (record_debug > 1) - fprintf_unfiltered (gdb_stdlog, - "Process record: record_full_end %s to " - "inferior.\n", - host_address_to_string (record_full_list)); - - if (first_record_full_end && execution_direction == EXEC_REVERSE) + /* Check for beginning and end of log. */ + if (execution_direction == EXEC_REVERSE + && record_full_list == &record_full_first) { - /* When reverse excute, the first record_full_end is the - part of current instruction. */ - first_record_full_end = 0; + /* Hit beginning of record log in reverse. */ + status->kind = TARGET_WAITKIND_NO_HISTORY; + break; } - else + if (execution_direction != EXEC_REVERSE + && !record_full_list->next) { - /* In EXEC_REVERSE mode, this is the record_full_end of prev - instruction. - In EXEC_FORWARD mode, this is the record_full_end of - current instruction. */ - /* step */ - if (record_full_resume_step) + /* Hit end of record log going forward. */ + status->kind = TARGET_WAITKIND_NO_HISTORY; + break; + } + + record_full_exec_insn (regcache, gdbarch, record_full_list); + + if (record_full_list->type == record_full_end) + { + if (record_debug > 1) + fprintf_unfiltered + (gdb_stdlog, + "Process record: record_full_end %s to " + "inferior.\n", + host_address_to_string (record_full_list)); + + if (first_record_full_end + && execution_direction == EXEC_REVERSE) { - if (record_debug > 1) - fprintf_unfiltered (gdb_stdlog, - "Process record: step.\n"); - continue_flag = 0; + /* When reverse excute, the first + record_full_end is the part of current + instruction. */ + first_record_full_end = 0; } - - /* check breakpoint */ - tmp_pc = regcache_read_pc (regcache); - if (record_check_stopped_by_breakpoint (aspace, tmp_pc, - &record_full_stop_reason)) + else { - if (record_debug) - fprintf_unfiltered (gdb_stdlog, - "Process record: break " - "at %s.\n", - paddress (gdbarch, tmp_pc)); + /* In EXEC_REVERSE mode, this is the + record_full_end of prev instruction. In + EXEC_FORWARD mode, this is the + record_full_end of current instruction. */ + /* step */ + if (record_full_resume_step) + { + if (record_debug > 1) + fprintf_unfiltered (gdb_stdlog, + "Process record: step.\n"); + continue_flag = 0; + } - continue_flag = 0; - } + /* check breakpoint */ + tmp_pc = regcache_read_pc (regcache); + if (record_check_stopped_by_breakpoint + (aspace, tmp_pc, &record_full_stop_reason)) + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, + "Process record: break " + "at %s.\n", + paddress (gdbarch, tmp_pc)); - if (record_full_stop_reason == TARGET_STOPPED_BY_WATCHPOINT) - { - if (record_debug) - fprintf_unfiltered (gdb_stdlog, - "Process record: hit hw " - "watchpoint.\n"); - continue_flag = 0; + continue_flag = 0; + } + + if (record_full_stop_reason + == TARGET_STOPPED_BY_WATCHPOINT) + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, + "Process record: hit hw " + "watchpoint.\n"); + continue_flag = 0; + } + /* Check target signal */ + if (record_full_list->u.end.sigval != GDB_SIGNAL_0) + /* FIXME: better way to check */ + continue_flag = 0; } - /* Check target signal */ - if (record_full_list->u.end.sigval != GDB_SIGNAL_0) - /* FIXME: better way to check */ - continue_flag = 0; } - } - if (continue_flag) - { - if (execution_direction == EXEC_REVERSE) + if (continue_flag) { - if (record_full_list->prev) - record_full_list = record_full_list->prev; - } - else - { - if (record_full_list->next) - record_full_list = record_full_list->next; + if (execution_direction == EXEC_REVERSE) + { + if (record_full_list->prev) + record_full_list = record_full_list->prev; + } + else + { + if (record_full_list->next) + record_full_list = record_full_list->next; + } } } + while (continue_flag); + + replay_out: + if (record_full_get_sig) + status->value.sig = GDB_SIGNAL_INT; + else if (record_full_list->u.end.sigval != GDB_SIGNAL_0) + /* FIXME: better way to check */ + status->value.sig = record_full_list->u.end.sigval; + else + status->value.sig = GDB_SIGNAL_TRAP; } - while (continue_flag); - -replay_out: - if (record_full_get_sig) - status->value.sig = GDB_SIGNAL_INT; - else if (record_full_list->u.end.sigval != GDB_SIGNAL_0) - /* FIXME: better way to check */ - status->value.sig = record_full_list->u.end.sigval; - else - status->value.sig = GDB_SIGNAL_TRAP; + catch (const gdb_exception &ex) + { + if (execution_direction == EXEC_REVERSE) + { + if (record_full_list->next) + record_full_list = record_full_list->next; + } + else + record_full_list = record_full_list->prev; - discard_cleanups (old_cleanups); + throw; + } } signal (SIGINT, handle_sigint); @@ -1469,7 +1476,7 @@ record_full_base_target::stopped_by_watchpoint () if (RECORD_FULL_IS_REPLAY) return record_full_stop_reason == TARGET_STOPPED_BY_WATCHPOINT; else - return beneath->stopped_by_watchpoint (); + return beneath ()->stopped_by_watchpoint (); } bool @@ -1478,7 +1485,7 @@ record_full_base_target::stopped_data_address (CORE_ADDR *addr_p) if (RECORD_FULL_IS_REPLAY) return false; else - return this->beneath->stopped_data_address (addr_p); + return this->beneath ()->stopped_data_address (addr_p); } /* The stopped_by_sw_breakpoint method of target record-full. */ @@ -1599,10 +1606,10 @@ record_full_target::store_registers (struct regcache *regcache, int regno) for (i = 0; i < gdbarch_num_regs (regcache->arch ()); i++) - regcache_invalidate (regcache, i); + regcache->invalidate (i); } else - regcache_invalidate (regcache, regno); + regcache->invalidate (regno); error (_("Process record canceled the operation.")); } @@ -1613,7 +1620,7 @@ record_full_target::store_registers (struct regcache *regcache, int regno) record_full_registers_change (regcache, regno); } - this->beneath->store_registers (regcache, regno); + this->beneath ()->store_registers (regcache, regno); } /* "xfer_partial" method. Behavior is conditional on @@ -1678,8 +1685,8 @@ record_full_target::xfer_partial (enum target_object object, record_full_insn_num++; } - return this->beneath->xfer_partial (object, annex, readbuf, writebuf, offset, - len, xfered_len); + return this->beneath ()->xfer_partial (object, annex, readbuf, writebuf, + offset, len, xfered_len); } /* This structure represents a breakpoint inserted while the record @@ -1691,6 +1698,15 @@ record_full_target::xfer_partial (enum target_object object, struct record_full_breakpoint { + record_full_breakpoint (struct address_space *address_space_, + CORE_ADDR addr_, + bool in_target_beneath_) + : address_space (address_space_), + addr (addr_), + in_target_beneath (in_target_beneath_) + { + } + /* The address and address space the breakpoint was set at. */ struct address_space *address_space; CORE_ADDR addr; @@ -1698,15 +1714,12 @@ struct record_full_breakpoint /* True when the breakpoint has been also installed in the target beneath. This will be false for breakpoints set during replay or when recording. */ - int in_target_beneath; + bool in_target_beneath; }; -typedef struct record_full_breakpoint *record_full_breakpoint_p; -DEF_VEC_P(record_full_breakpoint_p); - /* The list of breakpoints inserted while the record target is active. */ -VEC(record_full_breakpoint_p) *record_full_breakpoints = NULL; +static std::vector record_full_breakpoints; static void record_full_sync_record_breakpoints (struct bp_location *loc, void *data) @@ -1716,14 +1729,10 @@ record_full_sync_record_breakpoints (struct bp_location *loc, void *data) if (loc->inserted) { - struct record_full_breakpoint *bp = XNEW (struct record_full_breakpoint); - - bp->addr = loc->target_info.placed_address; - bp->address_space = loc->target_info.placed_address_space; - - bp->in_target_beneath = 1; - - VEC_safe_push (record_full_breakpoint_p, record_full_breakpoints, bp); + record_full_breakpoints.emplace_back + (loc->target_info.placed_address_space, + loc->target_info.placed_address, + 1); } } @@ -1732,7 +1741,7 @@ record_full_sync_record_breakpoints (struct bp_location *loc, void *data) static void record_full_init_record_breakpoints (void) { - VEC_free (record_full_breakpoint_p, record_full_breakpoints); + record_full_breakpoints.clear (); iterate_over_bp_locations (record_full_sync_record_breakpoints); } @@ -1745,9 +1754,7 @@ int record_full_target::insert_breakpoint (struct gdbarch *gdbarch, struct bp_target_info *bp_tgt) { - struct record_full_breakpoint *bp; - int in_target_beneath = 0; - int ix; + bool in_target_beneath = false; if (!RECORD_FULL_IS_REPLAY) { @@ -1760,34 +1767,29 @@ record_full_target::insert_breakpoint (struct gdbarch *gdbarch, scoped_restore restore_operation_disable = record_full_gdb_operation_disable_set (); - int ret = this->beneath->insert_breakpoint (gdbarch, bp_tgt); + int ret = this->beneath ()->insert_breakpoint (gdbarch, bp_tgt); if (ret != 0) return ret; - in_target_beneath = 1; + in_target_beneath = true; } /* Use the existing entries if found in order to avoid duplication in record_full_breakpoints. */ - for (ix = 0; - VEC_iterate (record_full_breakpoint_p, - record_full_breakpoints, ix, bp); - ++ix) + for (const record_full_breakpoint &bp : record_full_breakpoints) { - if (bp->addr == bp_tgt->placed_address - && bp->address_space == bp_tgt->placed_address_space) + if (bp.addr == bp_tgt->placed_address + && bp.address_space == bp_tgt->placed_address_space) { - gdb_assert (bp->in_target_beneath == in_target_beneath); + gdb_assert (bp.in_target_beneath == in_target_beneath); return 0; } } - bp = XNEW (struct record_full_breakpoint); - bp->addr = bp_tgt->placed_address; - bp->address_space = bp_tgt->placed_address_space; - bp->in_target_beneath = in_target_beneath; - VEC_safe_push (record_full_breakpoint_p, record_full_breakpoints, bp); + record_full_breakpoints.emplace_back (bp_tgt->placed_address_space, + bp_tgt->placed_address, + in_target_beneath); return 0; } @@ -1798,33 +1800,28 @@ record_full_target::remove_breakpoint (struct gdbarch *gdbarch, struct bp_target_info *bp_tgt, enum remove_bp_reason reason) { - struct record_full_breakpoint *bp; - int ix; - - for (ix = 0; - VEC_iterate (record_full_breakpoint_p, - record_full_breakpoints, ix, bp); - ++ix) + for (auto iter = record_full_breakpoints.begin (); + iter != record_full_breakpoints.end (); + ++iter) { - if (bp->addr == bp_tgt->placed_address - && bp->address_space == bp_tgt->placed_address_space) + struct record_full_breakpoint &bp = *iter; + + if (bp.addr == bp_tgt->placed_address + && bp.address_space == bp_tgt->placed_address_space) { - if (bp->in_target_beneath) + if (bp.in_target_beneath) { scoped_restore restore_operation_disable = record_full_gdb_operation_disable_set (); - int ret = this->beneath->remove_breakpoint (gdbarch, bp_tgt, - reason); + int ret = this->beneath ()->remove_breakpoint (gdbarch, bp_tgt, + reason); if (ret != 0) return ret; } if (reason == REMOVE_BREAKPOINT) - { - VEC_unordered_remove (record_full_breakpoint_p, - record_full_breakpoints, ix); - } + unordered_remove (record_full_breakpoints, iter); return 0; } } @@ -2004,7 +2001,8 @@ record_full_goto_entry (struct record_full_entry *p) registers_changed (); reinit_frame_cache (); - stop_pc = regcache_read_pc (get_current_regcache ()); + inferior_thread ()->suspend.stop_pc + = regcache_read_pc (get_current_regcache ()); print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1); } @@ -2194,10 +2192,10 @@ record_full_core_target::xfer_partial (enum target_object object, else { if (!entry) - return this->beneath->xfer_partial (object, annex, - readbuf, writebuf, - offset, len, - xfered_len); + return this->beneath ()->xfer_partial (object, annex, + readbuf, writebuf, + offset, len, + xfered_len); memcpy (readbuf, entry->buf + sec_offset, (size_t) len); @@ -2214,9 +2212,9 @@ record_full_core_target::xfer_partial (enum target_object object, error (_("You can't do that without a process to debug.")); } - return this->beneath->xfer_partial (object, annex, - readbuf, writebuf, offset, len, - xfered_len); + return this->beneath ()->xfer_partial (object, annex, + readbuf, writebuf, offset, len, + xfered_len); } /* "insert_breakpoint" method for prec over corefile. */ @@ -2328,7 +2326,6 @@ static void record_full_restore (void) { uint32_t magic; - struct cleanup *old_cleanups; struct record_full_entry *rec; asection *osec; uint32_t osec_size; @@ -2373,108 +2370,114 @@ record_full_restore (void) record_full_arch_list_head = NULL; record_full_arch_list_tail = NULL; record_full_insn_num = 0; - old_cleanups = make_cleanup (record_full_arch_list_cleanups, 0); - regcache = get_current_regcache (); - while (1) + try { - uint8_t rectype; - uint32_t regnum, len, signal, count; - uint64_t addr; + regcache = get_current_regcache (); - /* We are finished when offset reaches osec_size. */ - if (bfd_offset >= osec_size) - break; - bfdcore_read (core_bfd, osec, &rectype, sizeof (rectype), &bfd_offset); + while (1) + { + uint8_t rectype; + uint32_t regnum, len, signal, count; + uint64_t addr; - switch (rectype) - { - case record_full_reg: /* reg */ - /* Get register number to regnum. */ - bfdcore_read (core_bfd, osec, ®num, - sizeof (regnum), &bfd_offset); - regnum = netorder32 (regnum); + /* We are finished when offset reaches osec_size. */ + if (bfd_offset >= osec_size) + break; + bfdcore_read (core_bfd, osec, &rectype, sizeof (rectype), &bfd_offset); - rec = record_full_reg_alloc (regcache, regnum); + switch (rectype) + { + case record_full_reg: /* reg */ + /* Get register number to regnum. */ + bfdcore_read (core_bfd, osec, ®num, + sizeof (regnum), &bfd_offset); + regnum = netorder32 (regnum); - /* Get val. */ - bfdcore_read (core_bfd, osec, record_full_get_loc (rec), - rec->u.reg.len, &bfd_offset); + rec = record_full_reg_alloc (regcache, regnum); - if (record_debug) - fprintf_unfiltered (gdb_stdlog, - " Reading register %d (1 " - "plus %lu plus %d bytes)\n", - rec->u.reg.num, - (unsigned long) sizeof (regnum), - rec->u.reg.len); - break; - - case record_full_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_full_mem_alloc (addr, len); - - /* Get val. */ - bfdcore_read (core_bfd, osec, record_full_get_loc (rec), - rec->u.mem.len, &bfd_offset); + /* Get val. */ + bfdcore_read (core_bfd, osec, record_full_get_loc (rec), + rec->u.reg.len, &bfd_offset); - if (record_debug) - fprintf_unfiltered (gdb_stdlog, - " Reading memory %s (1 plus " - "%lu plus %lu plus %d bytes)\n", - paddress (get_current_arch (), - rec->u.mem.addr), - (unsigned long) sizeof (addr), - (unsigned long) sizeof (len), - rec->u.mem.len); - break; - - case record_full_end: /* end */ - rec = record_full_end_alloc (); - record_full_insn_num ++; - - /* Get signal value. */ - bfdcore_read (core_bfd, osec, &signal, - sizeof (signal), &bfd_offset); - signal = netorder32 (signal); - rec->u.end.sigval = (enum gdb_signal) signal; - - /* Get insn count. */ - bfdcore_read (core_bfd, osec, &count, - sizeof (count), &bfd_offset); - count = netorder32 (count); - rec->u.end.insn_num = count; - record_full_insn_count = count + 1; - if (record_debug) - fprintf_unfiltered (gdb_stdlog, - " Reading record_full_end (1 + " - "%lu + %lu bytes), offset == %s\n", - (unsigned long) sizeof (signal), - (unsigned long) sizeof (count), - paddress (get_current_arch (), - bfd_offset)); - break; - - default: - error (_("Bad entry type in core file %s."), - bfd_get_filename (core_bfd)); - break; - } + if (record_debug) + fprintf_unfiltered (gdb_stdlog, + " Reading register %d (1 " + "plus %lu plus %d bytes)\n", + rec->u.reg.num, + (unsigned long) sizeof (regnum), + rec->u.reg.len); + break; - /* Add rec to record arch list. */ - record_full_arch_list_add (rec); - } + case record_full_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_full_mem_alloc (addr, len); + + /* Get val. */ + bfdcore_read (core_bfd, osec, record_full_get_loc (rec), + rec->u.mem.len, &bfd_offset); - discard_cleanups (old_cleanups); + if (record_debug) + fprintf_unfiltered (gdb_stdlog, + " Reading memory %s (1 plus " + "%lu plus %lu plus %d bytes)\n", + paddress (get_current_arch (), + rec->u.mem.addr), + (unsigned long) sizeof (addr), + (unsigned long) sizeof (len), + rec->u.mem.len); + break; + + case record_full_end: /* end */ + rec = record_full_end_alloc (); + record_full_insn_num ++; + + /* Get signal value. */ + bfdcore_read (core_bfd, osec, &signal, + sizeof (signal), &bfd_offset); + signal = netorder32 (signal); + rec->u.end.sigval = (enum gdb_signal) signal; + + /* Get insn count. */ + bfdcore_read (core_bfd, osec, &count, + sizeof (count), &bfd_offset); + count = netorder32 (count); + rec->u.end.insn_num = count; + record_full_insn_count = count + 1; + if (record_debug) + fprintf_unfiltered (gdb_stdlog, + " Reading record_full_end (1 + " + "%lu + %lu bytes), offset == %s\n", + (unsigned long) sizeof (signal), + (unsigned long) 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_full_arch_list_add (rec); + } + } + catch (const gdb_exception &ex) + { + record_full_list_release (record_full_arch_list_tail); + throw; + } /* Add record_full_arch_list_head to the end of record list. */ record_full_first.next = record_full_arch_list_head; @@ -2519,7 +2522,7 @@ static void cmd_record_full_restore (const char *args, int from_tty) { core_file_command (args, from_tty); - record_full_ops.open (args, from_tty); + record_full_open (args, from_tty); } /* Save the execution log to a file. We use a modified elf corefile @@ -2808,9 +2811,9 @@ _initialize_record_full (void) record_full_first.next = NULL; record_full_first.type = record_full_end; - add_target (&record_full_ops); - add_deprecated_target_alias (&record_full_ops, "record"); - add_target (&record_full_core_ops); + add_target (record_full_target_info, record_full_open); + add_deprecated_target_alias (record_full_target_info, "record"); + add_target (record_full_core_target_info, record_full_open); add_prefix_cmd ("full", class_obscure, cmd_record_full_start, _("Start full execution recording."), &record_full_cmdlist, @@ -2829,11 +2832,11 @@ Argument is filename. File must be created with 'record save'."), deprecate_cmd (c, "record full restore"); add_prefix_cmd ("full", class_support, set_record_full_command, - _("Set record options"), &set_record_full_cmdlist, + _("Set record options."), &set_record_full_cmdlist, "set record full ", 0, &set_record_cmdlist); add_prefix_cmd ("full", class_support, show_record_full_command, - _("Show record options"), &show_record_full_cmdlist, + _("Show record options."), &show_record_full_cmdlist, "show record full ", 0, &show_record_cmdlist); /* Record instructions number limit command. */