mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-28 01:50:48 +00:00
gdb: Enable displaced stepping with shadow stack on amd64 linux.
Currently, if displaced stepping is active and the single stepped instruction is a call instruction, the return address atop the stack is the address following the copied instruction. However, to allow normal program execution it has to be the address following the original instruction. Due to that reason, the return address is corrected in amd64_displaced_step_fixup and i386_displaced_step_fixup. For programs that are shadow-stack enabled we see a control-protection exception, as the address on the shadow stack does not match the address atop the stack. Fix this by correcting the shadow stack top address as well. Approved-By: Andrew Burgess <aburgess@redhat.com> Approved-By: Luis Machado <luis.machado@arm.com> Reviewed-By: Eli Zaretskii <eliz@gnu.org>
This commit is contained in:
@@ -1939,8 +1939,10 @@ amd64_linux_shadow_stack_element_size_aligned (gdbarch *gdbarch)
|
||||
possible. */
|
||||
|
||||
static std::optional<CORE_ADDR>
|
||||
amd64_linux_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache)
|
||||
amd64_linux_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache,
|
||||
bool &shadow_stack_enabled)
|
||||
{
|
||||
shadow_stack_enabled = false;
|
||||
const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
|
||||
|
||||
if (tdep->ssp_regnum < 0)
|
||||
@@ -1958,6 +1960,9 @@ amd64_linux_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache)
|
||||
if (ssp == 0x0)
|
||||
return {};
|
||||
|
||||
/* In case there is a shadow stack pointer available which is non-null,
|
||||
the shadow stack feature is enabled. */
|
||||
shadow_stack_enabled = true;
|
||||
return ssp;
|
||||
}
|
||||
|
||||
@@ -1968,10 +1973,17 @@ static void
|
||||
amd64_linux_shadow_stack_push (gdbarch *gdbarch, CORE_ADDR new_addr,
|
||||
regcache *regcache)
|
||||
{
|
||||
bool shadow_stack_enabled;
|
||||
std::optional<CORE_ADDR> ssp
|
||||
= amd64_linux_get_shadow_stack_pointer (gdbarch, regcache);
|
||||
= amd64_linux_get_shadow_stack_pointer (gdbarch, regcache,
|
||||
shadow_stack_enabled);
|
||||
|
||||
/* For amd64/Linux, if SSP has a value that means shadow stack is
|
||||
enabled. */
|
||||
if (!ssp.has_value ())
|
||||
return;
|
||||
else
|
||||
gdb_assert (shadow_stack_enabled);
|
||||
|
||||
/* The shadow stack grows downwards. To push addresses to the stack,
|
||||
we need to decrement SSP. */
|
||||
@@ -2126,6 +2138,8 @@ amd64_linux_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch,
|
||||
(gdbarch, amd64_linux_remove_non_address_bits_watchpoint);
|
||||
|
||||
set_gdbarch_shadow_stack_push (gdbarch, amd64_linux_shadow_stack_push);
|
||||
set_gdbarch_get_shadow_stack_pointer (gdbarch,
|
||||
amd64_linux_get_shadow_stack_pointer);
|
||||
dwarf2_frame_set_init_reg (gdbarch, amd64_init_reg);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user