This is the mail archive of the gdb-patches@sourceware.org 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]

[patch] Fix gdb.cp/gdb2495.exp regression with gcc-4.7 #2


On Wed, 28 Dec 2011 17:12:08 +0100, Jan Kratochvil wrote:
> I will yet try to adjust it somehow.

This one may work.

displaced_step_at_entry_point has been already assuming after

  gdbarch_breakpoint_from_pc (gdbarch, &addr, &bp_len);
  addr += bp_len * 2;

ADDR can be used as an executable instruction address.  Therefore the
gdb_buffered_insn_length adjustment was possibly needlessly strong
(and needlessly expensive).

Expecting _start is at least as long as 2 * BP_LEN looks definitely valid and
on archs supporting displaced stepping the assumption of _start length 3 *
BP_LEN + gdbarch_max_insn_length looks also safe (also these archs have
properly set gdbarch_max_insn_length which is therefore small enough).

I am not convinced it works on each arch but it works at least on something so
special like ia64 so it really may work everywhere.  Displaced stepping is not
implemented on each arch so the displaced_step_at_entry_point does not prove it
works on every arch.  While this proposed code applies to (almost -
AT_ENTRY_POINT) any arch, so there is still a regression risk.

No regressions on {x86_64,x86_64-m32,i686}-fedorarawhide-linux-gnu.


Thanks,
Jan


2011-12-28  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Fix regression for gdb.cp/gdb2495.exp with gcc-4.7.
	* arch-utils.c (displaced_step_at_entry_point): Incrase BP_LEN skip to
	3 times.
	* infcall.c (call_function_by_hand) <ON_STACK>: New comment on stack
	executability.
	(call_function_by_hand) <AT_SYMBOL>: Drop comment on ON_STACK
	preference.  Move it upwards and fall through into AT_ENTRY_POINT.
	(call_function_by_hand) <AT_ENTRY_POINT>: New variable bp_len.  Adjust
	DUMMY_ADDR with it.
	* ppc-linux-tdep.c (ppc_linux_displaced_step_location): Increase
	PPC_INSN_SIZE skip to 3 times.

--- a/gdb/arch-utils.c
+++ b/gdb/arch-utils.c
@@ -86,7 +86,7 @@ displaced_step_at_entry_point (struct gdbarch *gdbarch)
      We don't want displaced stepping to interfere with those
      breakpoints, so leave space.  */
   gdbarch_breakpoint_from_pc (gdbarch, &addr, &bp_len);
-  addr += bp_len * 2;
+  addr += bp_len * 3;
 
   return addr;
 }
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -627,26 +628,16 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
   switch (gdbarch_call_dummy_location (gdbarch))
     {
     case ON_STACK:
+      /* ON_STACK has problems on some targets featuring security policies
+	 disabling target stack executability.  */
       sp = push_dummy_code (gdbarch, sp, funaddr,
 				args, nargs, target_values_type,
 				&real_pc, &bp_addr, get_current_regcache ());
       break;
-    case AT_ENTRY_POINT:
-      {
-	CORE_ADDR dummy_addr;
-
-	real_pc = funaddr;
-	dummy_addr = entry_point_address ();
-	/* A call dummy always consists of just a single breakpoint, so
-	   its address is the same as the address of the dummy.  */
-	bp_addr = dummy_addr;
-	break;
-      }
     case AT_SYMBOL:
       /* Some executables define a symbol __CALL_DUMMY_ADDRESS whose
 	 address is the location where the breakpoint should be
-	 placed.  Once all targets are using the overhauled frame code
-	 this can be deleted - ON_STACK is a better option.  */
+	 placed.  */
       {
 	struct minimal_symbol *sym;
 	CORE_ADDR dummy_addr;
@@ -661,11 +652,41 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
 	    dummy_addr = gdbarch_convert_from_func_ptr_addr (gdbarch,
 							     dummy_addr,
 							     &current_target);
+	    /* A call dummy always consists of just a single breakpoint,
+	       so it's address is the same as the address of the dummy.  */
+	    bp_addr = dummy_addr;
+	    break;
 	  }
-	else
-	  dummy_addr = entry_point_address ();
-	/* A call dummy always consists of just a single breakpoint,
-	   so it's address is the same as the address of the dummy.  */
+	break;
+      }
+      /* FALLTHROUGH */
+    case AT_ENTRY_POINT:
+      {
+	CORE_ADDR dummy_addr;
+	int bp_len;
+
+	real_pc = funaddr;
+	dummy_addr = entry_point_address ();
+
+	/* If the inferior call throws an uncaught C++ exception,
+	   the inferior unwinder tries to unwind all frames, including
+	   our dummy frame.  The unwinder determines the address of
+	   the calling instruction by subtracting 1 to the return
+	   address.  So, using the entry point's address as the return
+	   address would lead the unwinder to use the unwinding
+	   information of the code immediately preceding the entry
+	   point.  This information, if found, is invalid for the dummy
+	   frame, and can potentially crash the inferior's unwinder.
+	   Therefore, we use the second byte (approximately,
+	   alignments depending on GDBARCH).  It does not matter if it
+	   is placed inside the very first instruction, nothing tries
+	   to execute it.  */
+
+	gdbarch_breakpoint_from_pc (gdbarch, &dummy_addr, &bp_len);
+	dummy_addr += bp_len;
+
+	/* A call dummy always consists of just a single breakpoint, so
+	   its address is the same as the address of the dummy.  */
 	bp_addr = dummy_addr;
 	break;
       }
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -1075,7 +1075,7 @@ ppc_linux_displaced_step_location (struct gdbarch *gdbarch)
       /* Inferior calls also use the entry point as a breakpoint location.
 	 We don't want displaced stepping to interfere with those
 	 breakpoints, so leave space.  */
-      ppc_linux_entry_point_addr = addr + 2 * PPC_INSN_SIZE;
+      ppc_linux_entry_point_addr = addr + 3 * PPC_INSN_SIZE;
     }
 
   return ppc_linux_entry_point_addr;


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