]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
GDB: Linux: Add function linux_address_in_shadow_stack_mem_range
authorChristina Schimpe <christina.schimpe@intel.com>
Tue, 17 Jun 2025 12:11:43 +0000 (12:11 +0000)
committerThiago Jung Bauermann <thiago.bauermann@linaro.org>
Wed, 18 Jun 2025 03:20:45 +0000 (00:20 -0300)
The function comes from the following patch from the Intel CET shadow
stack support series:

[PATCH v4 07/11] gdb: Handle shadow stack pointer register unwinding for amd64 linux.

AArch64 also needs the function for unwinding the GCSPR, so include it
in this patch series.

Abridged-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
gdb/linux-tdep.c
gdb/linux-tdep.h

index 1e339b59e2e8caba57771211f0bb400666d30dba..c532b8758bfab3659f34b489b80b540ab8708e56 100644 (file)
@@ -47,6 +47,7 @@
 #include "gdbsupport/unordered_map.h"
 
 #include <ctype.h>
+#include <algorithm>
 
 /* This enum represents the values that the user can choose when
    informing the Linux kernel about which memory mappings will be
@@ -96,6 +97,10 @@ struct smaps_vmflags
     /* Memory map has memory tagging enabled.  */
 
     unsigned int memory_tagging : 1;
+
+    /* Memory map used for shadow stack.  */
+
+    unsigned int shadow_stack_memory : 1;
   };
 
 /* Data structure that holds the information contained in the
@@ -537,6 +542,8 @@ decode_vmflags (char *p, struct smaps_vmflags *v)
        v->shared_mapping = 1;
       else if (strcmp (s, "mt") == 0)
        v->memory_tagging = 1;
+      else if (strcmp (s, "ss") == 0)
+       v->shadow_stack_memory = 1;
     }
 }
 
@@ -3036,6 +3043,46 @@ show_dump_excluded_mappings (struct ui_file *file, int from_tty,
                      " flag is %s.\n"), value);
 }
 
+/* See linux-tdep.h.  */
+
+bool
+linux_address_in_shadow_stack_mem_range
+  (CORE_ADDR addr, std::pair<CORE_ADDR, CORE_ADDR> *range)
+{
+  if (!target_has_execution () || current_inferior ()->fake_pid_p)
+    return false;
+
+  const int pid = current_inferior ()->pid;
+
+  std::string smaps_file = string_printf ("/proc/%d/smaps", pid);
+
+  gdb::unique_xmalloc_ptr<char> data
+    = target_fileio_read_stralloc (nullptr, smaps_file.c_str ());
+
+  if (data == nullptr)
+    return false;
+
+  const std::vector<smaps_data> smaps
+    = parse_smaps_data (data.get (), std::move (smaps_file));
+
+  auto find_addr_mem_range = [&addr] (const smaps_data &map)
+    {
+      bool addr_in_mem_range
+       = (addr >= map.start_address && addr < map.end_address);
+      return (addr_in_mem_range && map.vmflags.shadow_stack_memory);
+    };
+  auto it = std::find_if (smaps.begin (), smaps.end (), find_addr_mem_range);
+
+  if (it != smaps.end ())
+    {
+      range->first = it->start_address;
+      range->second = it->end_address;
+      return true;
+    }
+
+  return false;
+}
+
 /* To be called from the various GDB_OSABI_LINUX handlers for the
    various GNU/Linux architectures and machine types.
 
index 7485fc132a6390102b4709bd743b61ab1ae74dd2..7083635b976c9a33334ce7e0e19189d8bd77706d 100644 (file)
@@ -117,4 +117,11 @@ extern CORE_ADDR linux_get_hwcap2 ();
 extern struct link_map_offsets *linux_ilp32_fetch_link_map_offsets ();
 extern struct link_map_offsets *linux_lp64_fetch_link_map_offsets ();
 
+/* Returns true if ADDR belongs to a shadow stack memory range.  If this
+   is the case, assign the shadow stack memory range to RANGE
+   [start_address, end_address).  */
+
+extern bool linux_address_in_shadow_stack_mem_range
+  (CORE_ADDR addr, std::pair<CORE_ADDR, CORE_ADDR> *range);
+
 #endif /* GDB_LINUX_TDEP_H */