From: Christina Schimpe Date: Tue, 17 Jun 2025 12:11:43 +0000 (+0000) Subject: GDB: Linux: Add function linux_address_in_shadow_stack_mem_range X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5cc9cddc3028d8e630395044c3ea3cde6687550d;p=thirdparty%2Fbinutils-gdb.git GDB: Linux: Add function linux_address_in_shadow_stack_mem_range 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 --- diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index 1e339b59e2e..c532b8758bf 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -47,6 +47,7 @@ #include "gdbsupport/unordered_map.h" #include +#include /* 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 *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 data + = target_fileio_read_stralloc (nullptr, smaps_file.c_str ()); + + if (data == nullptr) + return false; + + const std::vector 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. diff --git a/gdb/linux-tdep.h b/gdb/linux-tdep.h index 7485fc132a6..7083635b976 100644 --- a/gdb/linux-tdep.h +++ b/gdb/linux-tdep.h @@ -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 *range); + #endif /* GDB_LINUX_TDEP_H */