This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: check executable file's timestamp before running



It turns out that the logic for rereading debugging info when an
executable file has changed is completely separate from the logic for
re-opening `exec_bfd', the BFD the `exec' target layer uses for memory
reads.

This patch adds a test that detects the bug, and a fix.  The fix seems
reasonable, but I'm not sure it's right; there's too much stray state
in that portion of GDB for me to really understand.  But it does fix
the bug.


gdb/ChangeLog:
2001-12-07  Jim Blandy  <jimb@redhat.com>

	* infcmd.c (run_command): Check that the `exec' target layer's BFD
	is up-to-date before running the program, not just when a program
	exits.

gdb/testsuite/ChangeLog:
2001-12-07  Jim Blandy  <jimb@redhat.com>

	* gdb.base/reread.exp: Check that GDB properly re-reads the
	executable file when it changes while no inferior is running.

Index: gdb/infcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/infcmd.c,v
retrieving revision 1.35
diff -c -r1.35 infcmd.c
*** gdb/infcmd.c	2001/11/27 03:09:44	1.35
--- gdb/infcmd.c	2001/12/07 18:26:14
***************
*** 391,406 ****
  
    clear_breakpoint_hit_counts ();
  
-   exec_file = (char *) get_exec_file (0);
- 
    /* Purge old solib objfiles. */
    objfile_purge_solibs ();
  
    do_run_cleanups (NULL);
  
!   /* The exec file is re-read every time we do a generic_mourn_inferior, so
!      we just have to worry about the symbol file.  */
    reread_symbols ();
  
    /* We keep symbols from add-symbol-file, on the grounds that the
       user might want to add some symbols before running the program
--- 391,412 ----
  
    clear_breakpoint_hit_counts ();
  
    /* Purge old solib objfiles. */
    objfile_purge_solibs ();
  
    do_run_cleanups (NULL);
  
!   /* The comment here used to read, "The exec file is re-read every
!      time we do a generic_mourn_inferior, so we just have to worry
!      about the symbol file."  The `generic_mourn_inferior' function
!      gets called whenever the program exits.  However, suppose the
!      program exits, and *then* the executable file changes?  We need
!      to check again here.  Since reopen_exec_file doesn't do anything
!      if the timestamp hasn't changed, I don't see the harm.  */
!   reopen_exec_file ();
    reread_symbols ();
+ 
+   exec_file = (char *) get_exec_file (0);
  
    /* We keep symbols from add-symbol-file, on the grounds that the
       user might want to add some symbols before running the program
Index: gdb/testsuite/gdb.base/reread.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/reread.exp,v
retrieving revision 1.4
diff -c -r1.4 reread.exp
*** gdb/testsuite/gdb.base/reread.exp	2001/03/06 08:21:51	1.4
--- gdb/testsuite/gdb.base/reread.exp	2001/12/07 18:26:15
***************
*** 87,93 ****
  
  # Restore first executable to its original name, and move
  # second executable into its place.  Ensure that the new
! # executable is at least a second older than the old.
  
  gdb_test "shell mv ${binfile} ${binfile1}" "" ""
  gdb_test "shell mv ${binfile2} ${binfile}" "" ""
--- 87,93 ----
  
  # Restore first executable to its original name, and move
  # second executable into its place.  Ensure that the new
! # executable is at least a second newer than the old.
  
  gdb_test "shell mv ${binfile} ${binfile1}" "" ""
  gdb_test "shell mv ${binfile2} ${binfile}" "" ""
***************
*** 98,103 ****
--- 98,105 ----
  # and reset the breakpoints correctly.
  # Should see "Breakpoint 1, foo () at reread2.c:9"
  
+ set prms_id 0
+ 
  if ![isnative] {
      unsupported "run to foo() second time ";
  } else {
***************
*** 113,118 ****
--- 115,182 ----
  	}
  	timeout { 
  	    fail "run to foo() second time (timeout)" ; 
+ 	    gdb_suppress_tests 
+ 	}
+     }
+ }
+ 
+ 
+ ### Second pass: verify that GDB checks the executable file's
+ ### timestamp when the program is *restarted*, not just when it exits.
+ 
+ if ![isnative] {
+     unsupported "second pass: GDB should check for changes before running"
+ } else {
+ 
+     # Put the older executable back in place.
+     gdb_test "shell mv ${binfile} ${binfile2}" "" ""
+     gdb_test "shell mv ${binfile1} ${binfile}" "" ""
+ 
+     # Restart GDB entirely.
+     gdb_start
+     gdb_reinitialize_dir $srcdir/$subdir
+     gdb_load ${binfile}
+ 
+     # Set a breakpoint on foo and run to it.
+     gdb_test "break foo" \
+             "Breakpoint.*at.* file .*$srcfile1, line 14.*" \
+             "second pass: breakpoint foo in first file"
+     gdb_run_cmd
+     gdb_expect {
+         -re ".*Breakpoint.* foo .* at .*$srcfile1:14.*$gdb_prompt $"  {
+             pass "second pass: run to foo()";
+         }
+         -re ".*$gdb_prompt $" {
+             fail "second pass: run to foo()";
+             gdb_suppress_tests;
+         }
+         timeout {
+             fail "second pass: run to foo() (timeout)"
+             gdb_suppress_tests
+         }
+     }
+ 
+     # This time, let the program run to completion.  If GDB checks the
+     # executable file's timestamp now, it won't notice any change.
+     gdb_test "continue" ".*Program exited.*" \
+             "second pass: continue to completion"
+     
+     # Now move the newer executable into place, and re-run.  GDB
+     # should still notice that the executable file has changed,
+     # and still re-set the breakpoint appropriately.
+     gdb_test "shell mv ${binfile} ${binfile1}" "" ""
+     gdb_test "shell mv ${binfile2} ${binfile}" "" ""
+     gdb_run_cmd
+     gdb_expect {
+ 	-re ".*Breakpoint.* foo .* at .*:9.*$gdb_prompt $" {
+ 	    pass "second pass: run to foo() second time ";
+ 	}
+ 	-re ".*$gdb_prompt $" {
+ 	    fail "second pass: run to foo() second time";
+ 	    gdb_suppress_tests;
+ 	}
+ 	timeout { 
+ 	    fail "second pass: run to foo() second time (timeout)" ; 
  	    gdb_suppress_tests 
  	}
      }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]