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

Jan Kratochvil
2011-12-28T18:02:39Z

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;