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

Jan Kratochvil
2011-12-29T23:13:32Z

On Wed, 28 Dec 2011 21:09:21 +0100, Mark Kettenis wrote:
> Hmm, did you actually try using ON_STACK?

No.

> We specifically treat
> SIGSEGV as a potential breakpoint to deal with non-executable stacks.

I can confirm at least on RHEL-6.2 x86_64 a breakpoint on non-executable stack
gets properly recognized by GDB.

I have dropped those comments change. I understand it was incorrect from me
to include it into that mostly unrelated patch.

As ON_STACK is a valid option sure one may prefer to convert all the archs to
ON_STACK instead of fixing AT_ENTRY_POINT; not preferred by me TBH.

Thanks,
Jan

2011-12-30 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) <AT_SYMBOL>: 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,17 +628,6 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
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
@@ -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;