gdb: maybe unpush target from old inferior in inf_child_target::follow_exec
authorSimon Marchi <simon.marchi@efficios.com>
Thu, 13 May 2021 19:28:42 +0000 (15:28 -0400)
committerSimon Marchi <simon.marchi@polymtl.ca>
Thu, 13 May 2021 19:29:00 +0000 (15:29 -0400)
I realized that with "follow-exec-mode == new", the process target
stayed pushed in the original inferior.  This can cause a small
incoherence:

    $ ./gdb -q -nx --data-directory=data-directory -ex "set follow-exec-mode new" --args execer args-for-execer
    Reading symbols from execer...
    (gdb) r
    Starting program: /home/smarchi/build/binutils-gdb/gdb/execer args-for-execer
    I am execer and my argv[1] is: args-for-execer
    process 3562426 is executing new program: /home/smarchi/build/binutils-gdb/gdb/execee
    [New inferior 2]
    [New process 3562426]
    I am execee and my argv[1] is: arg-for-execee
    [Inferior 2 (process 3562426) exited normally]
    (gdb) info inferiors
      Num  Description       Connection           Executable
      1    <null>            1 (native)           /home/smarchi/build/binutils-gdb/gdb/execer
    * 2    <null>                                 /home/smarchi/build/binutils-gdb/gdb/execee
    (gdb) maintenance print target-stack
    The current target stack is:
      - exec (Local exec file)
      - None (None)
    (gdb) inferior 1
    [Switching to inferior 1 [<null>] (/home/smarchi/build/binutils-gdb/gdb/execer)]
    (gdb) maintenance print target-stack
    The current target stack is:
      - native (Native process)
      - exec (Local exec file)
      - None (None)

On exec, when execution continues into inferior 2, the native target
isn't unpushed from inferior 1.  When inferior 2's execution finishes
normally, inf_child_target::mourn_inferior unpushes the native target,
because the native target has been implicitly opened.

I think that if the native target was implicitly opened, it should be
unpushed from inferior 1, just like it is unpushed from an inferior
whose execution terminate.  This patch implements that.

gdb/ChangeLog:

* inf-child.h (inf_child_target) <follow_exec>: New.
* inf-child.c (inf_child_target::follow_exec): New.

Change-Id: I782cc08d73d93a990f4e53611107f68b2cb58af1

gdb/ChangeLog
gdb/inf-child.c
gdb/inf-child.h
gdb/testsuite/gdb.base/foll-exec-mode.exp

index ad6f3081285d44d181870e98f46e97046748f7b1..48a0e374729e81dff27e6fe6adf3435af3d71682 100644 (file)
@@ -1,3 +1,8 @@
+2021-05-13  Simon Marchi  <simon.marchi@efficios.com>
+
+       * inf-child.h (inf_child_target) <follow_exec>: New.
+       * inf-child.c (inf_child_target::follow_exec): New.
+
 2021-05-13  Simon Marchi  <simon.marchi@efficios.com>
 
        * target.h (struct target_ops) <follow_exec>: Add ptid_t
index 0e68a40d7c04a91fd7d35c674bbb0770fef65a6c..f690aa77913f33d2a53c3ab577b6f1b743980e01 100644 (file)
@@ -409,6 +409,24 @@ inf_child_target::can_use_agent ()
   return agent_loaded_p ();
 }
 
+void
+inf_child_target::follow_exec (inferior *follow_inf, ptid_t ptid,
+                              const char *execd_pathname)
+{
+  inferior *orig_inf = current_inferior ();
+
+  process_stratum_target::follow_exec (follow_inf, ptid, execd_pathname);
+
+  if (orig_inf != follow_inf)
+    {
+      /* If the target was implicitly push in the original inferior, unpush
+         it.  */
+      scoped_restore_current_thread restore_thread;
+      switch_to_inferior_no_thread (orig_inf);
+      maybe_unpush_target ();
+    }
+}
+
 /* See inf-child.h.  */
 
 void
index d697a3938ee64d242bb57bcafd14c8437649f60f..aa33c5381381103e27cc0ea3f4517fe1239d8894 100644 (file)
@@ -57,6 +57,9 @@ public:
 
   void post_startup_inferior (ptid_t) override;
 
+  void follow_exec (inferior *follow_inf, ptid_t ptid,
+                   const char *execd_pathname) override;
+
   void mourn_inferior () override;
 
   bool can_run () override;
index 7d7b6605dafb5322aca8d69e819346bdc7bda8f9..9087c8baf2c4c10a42661d89ed76aaa78270686f 100644 (file)
@@ -113,6 +113,8 @@ proc do_follow_exec_mode_tests { mode cmd infswitch } {
            return
        }
 
+       set target_is_native [gdb_is_target_native]
+
        # Set the follow-exec mode.
        #
        gdb_test_no_output "set follow-exec-mode $mode"
@@ -147,8 +149,18 @@ proc do_follow_exec_mode_tests { mode cmd infswitch } {
        #
        if {$mode == "same"} {
            set expected_re "\\* 1.*process.*"
+       } elseif { $mode == "new" } {
+           # If using the native target, we want to specifically check that the
+           # process target, which was automatically pushed when running, was
+           # automatically unpushed from inferior 1 on exec.  Use a
+           # different regexp that verifies the Connection field is empty.
+           if { $target_is_native } {
+               set expected_re "  1.*<null> +[string_to_regexp $binfile].*\r\n\\* 2.*process.*$testfile2 .*"
+           } else {
+               set expected_re "  1.*null.*$testfile.*\r\n\\* 2.*process.*$testfile2 .*"
+           }
        } else {
-           set expected_re "  1.*null.*$testfile.*\r\n\\* 2.*process.*$testfile2 .*"
+           error "Invalid mode: $mode"
        }
 
        # Check that the inferior list is correct: