From: Christina Schimpe Date: Tue, 27 Feb 2024 16:48:00 +0000 (-0500) Subject: gdb, gdbarch: Introduce gdbarch method to get the shadow stack pointer. X-Git-Tag: gdb-17-branchpoint~120 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=66dee5a4f05b8f0ac84d354ec5102c0be31a8148;p=thirdparty%2Fbinutils-gdb.git gdb, gdbarch: Introduce gdbarch method to get the shadow stack pointer. This patch is required by the following commit "gdb: Enable displaced stepping with shadow stack on amd64 linux." Reviewed-By: Thiago Jung Bauermann Approved-By: Luis Machado Approved-By: Andrew Burgess --- diff --git a/gdb/arch-utils.c b/gdb/arch-utils.c index 96fb2c4836e..f2af80e7040 100644 --- a/gdb/arch-utils.c +++ b/gdb/arch-utils.c @@ -1218,6 +1218,16 @@ default_gdbarch_return_value readbuf, writebuf); } +/* See arch-utils.h. */ + +std::optional +default_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache, + bool &shadow_stack_enabled) +{ + shadow_stack_enabled = false; + return {}; +} + obstack *gdbarch_obstack (gdbarch *arch) { return &arch->obstack; diff --git a/gdb/arch-utils.h b/gdb/arch-utils.h index 1509cb7441e..14a84b74733 100644 --- a/gdb/arch-utils.h +++ b/gdb/arch-utils.h @@ -414,4 +414,9 @@ extern enum return_value_convention default_gdbarch_return_value struct regcache *regcache, struct value **read_value, const gdb_byte *writebuf); +/* Default implementation of gdbarch default_get_shadow_stack_pointer + method. */ +extern std::optional default_get_shadow_stack_pointer + (gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled); + #endif /* GDB_ARCH_UTILS_H */ diff --git a/gdb/gdbarch-gen.c b/gdb/gdbarch-gen.c index a77f9b7d265..09bb4804c43 100644 --- a/gdb/gdbarch-gen.c +++ b/gdb/gdbarch-gen.c @@ -262,6 +262,7 @@ struct gdbarch gdbarch_use_target_description_from_corefile_notes_ftype *use_target_description_from_corefile_notes = default_use_target_description_from_corefile_notes; gdbarch_core_parse_exec_context_ftype *core_parse_exec_context = default_core_parse_exec_context; gdbarch_shadow_stack_push_ftype *shadow_stack_push = nullptr; + gdbarch_get_shadow_stack_pointer_ftype *get_shadow_stack_pointer = default_get_shadow_stack_pointer; }; /* Create a new ``struct gdbarch'' based on information provided by @@ -535,6 +536,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of use_target_description_from_corefile_notes, invalid_p == 0. */ /* Skip verify of core_parse_exec_context, invalid_p == 0. */ /* Skip verify of shadow_stack_push, has predicate. */ + /* Skip verify of get_shadow_stack_pointer, invalid_p == 0. */ if (!log.empty ()) internal_error (_("verify_gdbarch: the following are invalid ...%s"), log.c_str ()); @@ -1409,6 +1411,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) gdb_printf (file, "gdbarch_dump: shadow_stack_push = <%s>\n", host_address_to_string (gdbarch->shadow_stack_push)); + gdb_printf (file, + "gdbarch_dump: get_shadow_stack_pointer = <%s>\n", + host_address_to_string (gdbarch->get_shadow_stack_pointer)); if (gdbarch->dump_tdep != NULL) gdbarch->dump_tdep (gdbarch, file); } @@ -5561,3 +5566,20 @@ set_gdbarch_shadow_stack_push (struct gdbarch *gdbarch, { gdbarch->shadow_stack_push = shadow_stack_push; } + +std::optional +gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->get_shadow_stack_pointer != NULL); + if (gdbarch_debug >= 2) + gdb_printf (gdb_stdlog, "gdbarch_get_shadow_stack_pointer called\n"); + return gdbarch->get_shadow_stack_pointer (gdbarch, regcache, shadow_stack_enabled); +} + +void +set_gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch, + gdbarch_get_shadow_stack_pointer_ftype get_shadow_stack_pointer) +{ + gdbarch->get_shadow_stack_pointer = get_shadow_stack_pointer; +} diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h index 701e9f099b1..7171c42fb63 100644 --- a/gdb/gdbarch-gen.h +++ b/gdb/gdbarch-gen.h @@ -1794,7 +1794,8 @@ extern void set_gdbarch_core_parse_exec_context (struct gdbarch *gdbarch, gdbarc technologies. For example, the Intel Control-Flow Enforcement Technology (Intel CET) on x86 provides a shadow stack and indirect branch tracking. To enable shadow stack support for inferior calls the shadow_stack_push - gdbarch hook has to be provided. + gdbarch hook has to be provided. The get_shadow_stack_pointer gdbarch + hook has to be provided to enable displaced stepping. Push NEW_ADDR to the shadow stack and update the shadow stack pointer. */ @@ -1803,3 +1804,16 @@ extern bool gdbarch_shadow_stack_push_p (struct gdbarch *gdbarch); typedef void (gdbarch_shadow_stack_push_ftype) (struct gdbarch *gdbarch, CORE_ADDR new_addr, regcache *regcache); extern void gdbarch_shadow_stack_push (struct gdbarch *gdbarch, CORE_ADDR new_addr, regcache *regcache); extern void set_gdbarch_shadow_stack_push (struct gdbarch *gdbarch, gdbarch_shadow_stack_push_ftype *shadow_stack_push); + +/* If possible, return the shadow stack pointer. If the shadow stack + feature is enabled then set SHADOW_STACK_ENABLED to true, otherwise + set SHADOW_STACK_ENABLED to false. This hook has to be provided to enable + displaced stepping for shadow stack enabled programs. + On some architectures, the shadow stack pointer is available even if the + feature is disabled. So dependent on the target, an implementation of + this function may return a valid shadow stack pointer, but set + SHADOW_STACK_ENABLED to false. */ + +typedef std::optional (gdbarch_get_shadow_stack_pointer_ftype) (struct gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled); +extern std::optional gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch, regcache *regcache, bool &shadow_stack_enabled); +extern void set_gdbarch_get_shadow_stack_pointer (struct gdbarch *gdbarch, gdbarch_get_shadow_stack_pointer_ftype *get_shadow_stack_pointer); diff --git a/gdb/gdbarch_components.py b/gdb/gdbarch_components.py index 3ae79e44c1e..f933a09c0fa 100644 --- a/gdb/gdbarch_components.py +++ b/gdb/gdbarch_components.py @@ -2838,7 +2838,8 @@ Some targets support special hardware-assisted control-flow protection technologies. For example, the Intel Control-Flow Enforcement Technology (Intel CET) on x86 provides a shadow stack and indirect branch tracking. To enable shadow stack support for inferior calls the shadow_stack_push -gdbarch hook has to be provided. +gdbarch hook has to be provided. The get_shadow_stack_pointer gdbarch +hook has to be provided to enable displaced stepping. Push NEW_ADDR to the shadow stack and update the shadow stack pointer. """, @@ -2847,3 +2848,21 @@ Push NEW_ADDR to the shadow stack and update the shadow stack pointer. params=[("CORE_ADDR", "new_addr"), ("regcache *", "regcache")], predicate=True, ) + +Method( + comment=""" +If possible, return the shadow stack pointer. If the shadow stack +feature is enabled then set SHADOW_STACK_ENABLED to true, otherwise +set SHADOW_STACK_ENABLED to false. This hook has to be provided to enable +displaced stepping for shadow stack enabled programs. +On some architectures, the shadow stack pointer is available even if the +feature is disabled. So dependent on the target, an implementation of +this function may return a valid shadow stack pointer, but set +SHADOW_STACK_ENABLED to false. +""", + type="std::optional", + name="get_shadow_stack_pointer", + params=[("regcache *", "regcache"), ("bool &", "shadow_stack_enabled")], + predefault="default_get_shadow_stack_pointer", + invalid=False, +)