diff options
author | Tom Tromey <tromey@redhat.com> | 2013-07-25 14:34:51 +0000 |
---|---|---|
committer | Tom Tromey <tromey@redhat.com> | 2013-07-25 14:34:51 +0000 |
commit | 7fdc15218d384617a3aad142cfeca0594a7c5ff2 (patch) | |
tree | 79400605229edd964c75d69e0fea1e966fcd3ea7 /gdb/target.c | |
parent | c22a2b88fe63d857110e9c86f3775e55197c9a04 (diff) | |
download | gdb-7fdc15218d384617a3aad142cfeca0594a7c5ff2.zip gdb-7fdc15218d384617a3aad142cfeca0594a7c5ff2.tar.gz gdb-7fdc15218d384617a3aad142cfeca0594a7c5ff2.tar.bz2 |
remove pop_target
This patch fixes the target double-close problem (PR remote/15266),
and in the process removes pop_target entire (PR remote/15256).
The first issue is that pop_target calls target_close. However, it
then calls unpush_target, which also calls target_close. This means
targets must be able to be closed twice. Not only is this strange,
but it also directly contradicts the contract of to_xclose targets.
(We currently have just a single such target, and it is never pushed;
but I plan to add more, and so this latent bug is triggered.)
The second issue is that it seems to me that calling pop_target is
often unsafe. This is what cropped up in 15256, where the remote
target assumed that it could pop_target -- but there was another
target higher on the stack, leading to confusion.
But, it is always just as easy to call unpush_target as it is to call
pop_target; and it is also safer. So, removing pop_target seemed like
an improvement.
Finally, this adds an assertion to target_close to ensure that no
currently-pushed target can be closed.
Built and regtested on x86-64 Fedora 18; both natively and using the
native-gdbserver board file.
PR remote/15256, PR remote/15266:
* bfd-target.c (target_bfd_reopen): Initialize to_magic.
* monitor.c (monitor_detach): Use unpush_target.
* remote-m32r-sdi.c (m32r_detach): Use unpush_target.
* remote-mips.c (mips_detach): Use unpush_target. Don't
call mips_close.
* remote-sim.c (gdbsim_detach): Use unpush_target.
* target.c (pop_target): Remove.
(pop_all_targets_above): Don't call target_close.
(target_close): Assert that the target is unpushed.
* target.h (pop_target): Don't declare.
* tracepoint.c (tfile_open): Use unpush_target.
Diffstat (limited to 'gdb/target.c')
-rw-r--r-- | gdb/target.c | 17 |
1 files changed, 2 insertions, 15 deletions
diff --git a/gdb/target.c b/gdb/target.c index 37b0a94..e3dcb47 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -1094,25 +1094,10 @@ unpush_target (struct target_ops *t) } void -pop_target (void) -{ - target_close (target_stack); /* Let it clean up. */ - if (unpush_target (target_stack) == 1) - return; - - fprintf_unfiltered (gdb_stderr, - "pop_target couldn't find target %s\n", - current_target.to_shortname); - internal_error (__FILE__, __LINE__, - _("failed internal consistency check")); -} - -void pop_all_targets_above (enum strata above_stratum) { while ((int) (current_target.to_stratum) > (int) above_stratum) { - target_close (target_stack); if (!unpush_target (target_stack)) { fprintf_unfiltered (gdb_stderr, @@ -3781,6 +3766,8 @@ debug_to_open (char *args, int from_tty) void target_close (struct target_ops *targ) { + gdb_assert (!target_is_pushed (targ)); + if (targ->to_xclose != NULL) targ->to_xclose (targ); else if (targ->to_close != NULL) |