[binutils-gdb] gdb: delete some unnecessary code from core_target::detach

Andrew Burgess via Gdb-cvs <[email protected]>
Newsgroups gmane.comp.gdb.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=eecd9f4cece1b7c89c6c3ac188e1a29152b2be7a

commit eecd9f4cece1b7c89c6c3ac188e1a29152b2be7a
Author: Andrew Burgess <[email protected]>
Date:   Sun Mar 29 20:19:55 2026 +0100

    gdb: delete some unnecessary code from core_target::detach
    
    This commit removes some unnecessary code from core_target::detach.
    
    When a core_target is created the core BFD (m_core_bfd) is set, and
    will never be NULL.  The m_core_bfd remains set until either
    core_target::detach or core_target::close is called.
    
    The core_target::close function is only called when the refcount of a
    core_target reaches zero, the core_target::close function deletes the
    core_target, so we know that after calling core_target::close no other
    core_target member functions will be called (as the core_target will
    have been deleted).
    
    The core_target::detach function is called as a result of calling
    target_detach, which is called as a result of either the 'detach'
    command, or the 'core-file' command (without passing a file name).
    
    As a core_target is not shareable (see
    process_stratum_target::is_shareable), once a core_target is detached,
    its reference count will eventually reduce to zero (a reference is
    temporarily held in target_detach), and then it will be closed and
    deleted.
    
    What this means is that there is absolutely no way that a core_target
    can ever be detached twice, not that such a thing would make much
    sense, but it cannot happen.
    
    Understanding this we can know that when core_target::detach is called
    m_core_bfd will never be NULL, I've added an assert for this case.
    
    Given this assert, if we look at core_target::clear_core, which
    core_target::detach calls, we can see that exit_inferior will always
    be called.  If we look at exit_inferior (in inferior.c) we see that
    the last two actions of that function are:
    
      /* Clear the register cache and the frame cache.  */
      registers_changed ();
      reinit_frame_cache ();
    
    Which are also two of the last three actions of core_target::detach.
    Clearly the calls in core_target::detach are redundant.
    
    Just for good measure, if we look in target_detach, from where
    core_target::detach will have been called, just before the function
    returns we have:
    
      registers_changed_ptid (proc_target, save_pid_ptid);
      reinit_frame_cache ();
    
    The registers_changed_ptid call is slightly more restrictive, only
    clearing the register cache for the target being detached, but that
    should be good enough -- I think exit_inferior could probably be
    changed to call registers_changed_ptid for the inferior that exited,
    but that's a problem for another day.
    
    What this all tells me is that the registers_changed call and the
    reinit_frame_cache call in core_target::detach are unnecessary, and
    can be deleted, which is what this patch does.
    
    Given I was making changes in core_target::detach, I've taken this
    opportunity to update an out of date comment.  The comment talked
    about 'this' possibly becoming dangling, however, this was never the
    case as target_detach holds a reference to the target, preventing it
    from being deleted until target_detach returns.
    
    There should be no user visible changes after this commit.

Diff:
---
 gdb/corelow.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/gdb/corelow.c b/gdb/corelow.c
index 8548311b906..c66ff50cbc2 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -1241,20 +1241,28 @@ core_target_open (const char *arg, int from_tty)
 void
 core_target::detach (inferior *inf, int from_tty)
 {
+  /* The core BFD is set when the core_target is created and attached to
+     the inferior.  It is only cleared during detach or close.  After
+     detaching the core target will be closed and deleted, so detach can
+     never be called twice.  What this means is that detach will never be
+     called without the core BFD being set.  */
+  gdb_assert (this->core_bfd () != nullptr);
+
   /* Get rid of the core.  Don't rely on core_target::close doing it,
      because target_detach may be called with core_target's refcount > 1,
      meaning core_target::close may not be called yet by the
      unpush_target call below.  */
   clear_core ();
 
-  /* Note that 'this' may be dangling after this call.  unpush_target
-     closes the target if the refcount reaches 0, and our close
-     implementation deletes 'this'.  */
+  /* This detach method should only be called from target_detach, which
+     holds a reference to this core_target.  As such, this core_target will
+     not be deleted when it is unpushed from INF's target stack.  Instead
+     this core_target will be deleted when target_detach returns, at which
+     point the reference count on this core_target will reach 0, and our
+     close method will delete 'this'.  */
   inf->unpush_target (this);
 
-  /* Clear the register cache and the frame cache.  */
-  registers_changed ();
-  reinit_frame_cache ();
+  /* Inform the user.  */
   maybe_say_no_core_file_now (from_tty);
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.