summaryrefslogtreecommitdiff
path: root/gdb/infrun.h
diff options
context:
space:
mode:
authorSimon Marchi <simon.marchi@efficios.com>2020-02-14 15:11:58 -0500
committerSimon Marchi <simon.marchi@efficios.com>2020-02-14 15:11:58 -0500
commitd8d83535e6d3dbb3fb8664f6a98a37470c091f01 (patch)
treeb578e96844a2ba6f67f890ea902690281ba56cca /gdb/infrun.h
parent5f661e03972e3412778c0bee8d20522b9bffea76 (diff)
gdb: cleanup of displaced_step_inferior_state::reset/displaced_step_clear
displaced_step_inferior_state::reset and displaced_step_clear appear to have the same goal, but they don't do the same thing. displaced_step_inferior_state::reset clears more things than displaced_step_clear, but it misses free'ing the closure, which displaced_step_clear does. This patch replaces displaced_step_clear's implementation with just a call to displaced_step_inferior_state::reset. It then changes displaced_step_inferior_state::step_closure to be a unique_ptr, to indicate the fact that displaced_step_inferior_state owns the closure (and so that it is automatically freed when the field is reset). The test gdb.base/step-over-syscall.exp caught a problem when doing this, which I consider to be a latent bug which my cleanup exposes. In handle_inferior_event, in the TARGET_WAITKIND_FORKED case, if we displaced-step over a fork syscall, we make sure to restore the memory that we used as a displaced-stepping buffer in the child. We do so using the displaced_step_inferior_state of the parent. However, we do it after calling displaced_step_fixup for the parent, which clears the information in the parent's displaced_step_inferior_state. It worked fine before, because displaced_step_clear didn't completely clear the displaced_step_inferior_state structure, so the required information (in this case the gdbarch) was still available after clearing. I fixed it by making GDB restore the child's memory before calling the displaced_step_fixup on the parent. This way, the data in the displaced_step_inferior_state structure is still valid when we use it for the child. This is the error you would get in gdb.base/step-over-syscall.exp without this fix: /home/smarchi/src/binutils-gdb/gdb/gdbarch.c:3911: internal-error: ULONGEST gdbarch_max_insn_length(gdbarch*): Assertion `gdbarch != NULL' failed. gdb/ChangeLog: * infrun.c (get_displaced_step_closure_by_addr): Adjust to std::unique_ptr. (displaced_step_clear): Rename to... (displaced_step_reset): ... this. Just call displaced->reset (). (displaced_step_clear_cleanup): Rename to... (displaced_step_reset_cleanup): ... this. (displaced_step_prepare_throw): Adjust to std::unique_ptr. (displaced_step_fixup): Likewise. (resume_1): Likewise. (handle_inferior_event): Restore child's memory before calling displaced_step_fixup on the parent. * infrun.h (displaced_step_inferior_state) <reset>: Adjust to std::unique_ptr. <step_closure>: Change type to std::unique_ptr.
Diffstat (limited to 'gdb/infrun.h')
-rw-r--r--gdb/infrun.h4
1 files changed, 2 insertions, 2 deletions
diff --git a/gdb/infrun.h b/gdb/infrun.h
index 8040b28f01..c6329c844d 100644
--- a/gdb/infrun.h
+++ b/gdb/infrun.h
@@ -290,7 +290,7 @@ struct displaced_step_inferior_state
failed_before = 0;
step_thread = nullptr;
step_gdbarch = nullptr;
- step_closure = nullptr;
+ step_closure.reset ();
step_original = 0;
step_copy = 0;
step_saved_copy.clear ();
@@ -310,7 +310,7 @@ struct displaced_step_inferior_state
/* The closure provided gdbarch_displaced_step_copy_insn, to be used
for post-step cleanup. */
- displaced_step_closure *step_closure;
+ std::unique_ptr<displaced_step_closure> step_closure;
/* The address of the original instruction, and the copy we
made. */