From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id we03OrURBGlLahMAWB0awg (envelope-from ) for ; Thu, 30 Oct 2025 21:32:37 -0400 Authentication-Results: simark.ca; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=kPZou4ky; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id E055F1E0BC; Thu, 30 Oct 2025 21:32:37 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-2.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 92BCE1E057 for ; Thu, 30 Oct 2025 21:32:36 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id F1C393858C40 for ; Fri, 31 Oct 2025 01:32:35 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org F1C393858C40 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=kPZou4ky Received: from mail-pl1-x634.google.com (mail-pl1-x634.google.com [IPv6:2607:f8b0:4864:20::634]) by sourceware.org (Postfix) with ESMTPS id A39A03858C42 for ; Fri, 31 Oct 2025 01:31:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A39A03858C42 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A39A03858C42 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::634 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1761874300; cv=none; b=d6DwQEug6sZCQbU/xgWTxsKscmCm/zJ/v284fO8pIawN+lXSGaG/nGC0I1UXqwQ1HoC4VIY0tCGbvyOzUBd0eQnSoI+qrON2FXEVUaeYic2kSQMG2RmoePj612YM5+aU/XaZhBmUMzf4k7F8dnIS3EUYWfqZ9V3D8DfVRguxU9s= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1761874300; c=relaxed/simple; bh=bFXm9EWt+0seXNrNEGh/XcfEaHkOgLwKHiFVpSIrLAc=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=hU7zdnJqJZmrgo6vMkJPpT4pklpbu3VWg1HaVtDcPac2QAJwNd/mRSVJHIKzAzH3EMvKV6xFYbLYM22jxYbdGkYi4CgdRIB0wMikNKzPHoJgTXgNa1lz2893RB/twfkzbT2p9UI0l6+6mpN51YzU0pck2xbpeOdkKLx86XQ/Mps= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A39A03858C42 Received: by mail-pl1-x634.google.com with SMTP id d9443c01a7336-28a5b8b12a1so18661505ad.0 for ; Thu, 30 Oct 2025 18:31:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1761874299; x=1762479099; darn=sourceware.org; h=content-transfer-encoding:mime-version:message-id:date:user-agent :references:in-reply-to:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3HbMO8ICl++Hi8a18Iez3QVzACiLWgflVQ3fdmjTcgY=; b=kPZou4kyiduc2ftkFLBWlRuab9xiXWbzpBGTLuzDx9DJiM8DGzCWz9iSZKlpRZ2HaJ 2Fh46EdfnSk7ElV1wPZfGIT9SsQN01blD6r1lwOnX/8woVwOuiHc3l0ilf+xMit2BcxC s1dDPGtjkmzno1y6nUnCQnxlFPhQaAAkZsy6BJ2rNXGGlyNbe/JBUlCexv75+/Ouzt2W 5rkxqxrb0tdNltvktqaJZLgaL5KyLPQ2Laww6bXIVx4CEhCOD0pLlzXutbwn35zQShYb KzleDYZKa45JA1RY6mdNG1D0BAweA01v2usy1Wq7+iG7jSjtywAtt/tPy5RAuVIDi1cy gu4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761874299; x=1762479099; h=content-transfer-encoding:mime-version:message-id:date:user-agent :references:in-reply-to:subject:cc:to:from:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=3HbMO8ICl++Hi8a18Iez3QVzACiLWgflVQ3fdmjTcgY=; b=Yj71LGg7rqm1PI7ov0H2yP1TTikvMvxGYDkFjTB5EFZgBONEEfX6pTbfKpcHfc5fyP 6FHSwxfUvho3EjmgpJeoqipFT0j7IWBkjz4NBpv35X3LOg0QAwe/mGXxvjEBUqvgExjE xHRfgX0o5Vxr9iAtLrWxDv7U4eOwO/H211jSsfGhT+3a3aZwZs4CydAV/CnZqCKBL8QQ ZzZYN+VDUMtC9SWJcob+Sbv9OGVvbm9ZkTHEcgg2Ore65QObpdvkx3tE5rdTIAedNulg 9gWyHIC5VlyRofu5ZonY0IrvvB4cE+I8xQn2WYVBXjAYW4izhBM2OidvQMYPdF39QRdK d6lA== X-Gm-Message-State: AOJu0YyQuVPwKN5EzlVSroAdjep/sn5ud/fYB+mSlGpwvAxa5oFZrh4G G802V0YXN3o1DM2Ww409PDnUoUzNArhDuXZxisVULFiqZ9esfSlMST637xYfAxi+gwvCtwohaJ9 Mu7TZ X-Gm-Gg: ASbGncu/D7kIPqzFhKlwC8bJ6pj7fgoi16frqDpnnslBLejsuS34V/1P1TIL3GDqWj/ K69cl1QvT0bbX6acu1hw6uzdXydNgcr4hcVh0AF9OR81W63iYltgOMGh+bRlZnYgpTg9MlMCOqv Ob0ow/tmyoQyZ/cdSkkEsyJ08mb7i02HjMJ9N7UwQxNs4ldljQlLdaWxcoZPaQdn3s2roQcNCHn 8WVORfPqseevuEFnveuX5dR36KP6ZkMIVg3Vw3axhAwwxN9gkMLjQYYYl129Cr84IwGeKIGIZ8Z haD+vnb8QXym8kzGOzgcSEFuD/wr3EX91Hmndt2kkAft50QgGYDQk2UeZOVjlLTa2+XhiZ4EZGq TP3G3KmYQ19kOclKRl5buPwpKDgsEw1M7s+WTnBRJwsyvMajmpwFeMq+HkzRCD1u3qySr02pS4q 8874zTEejbfg== X-Google-Smtp-Source: AGHT+IGdfuyelYEiPM0CWQlppauqglB0tuMwpUCtE6mhSaZneSWCq/2jYlO6/pUlp3L/DqUvrUGC7A== X-Received: by 2002:a17:903:9ce:b0:294:98c4:41c8 with SMTP id d9443c01a7336-2951a4397a4mr25247295ad.34.1761874298413; Thu, 30 Oct 2025 18:31:38 -0700 (PDT) Received: from localhost ([2804:14d:7e39:88d6:dd80:7850:7b40:c343]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b93b8c8cdc0sm239300a12.13.2025.10.30.18.31.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Oct 2025 18:31:37 -0700 (PDT) From: Thiago Jung Bauermann To: Christina Schimpe Cc: gdb-patches@sourceware.org Subject: Re: [PATCH 1/9] gdb: Generalize handling of the shadow stack pointer. In-Reply-To: <20250923111842.4091694-2-christina.schimpe@intel.com> (Christina Schimpe's message of "Tue, 23 Sep 2025 11:18:34 +0000") References: <20250923111842.4091694-1-christina.schimpe@intel.com> <20250923111842.4091694-2-christina.schimpe@intel.com> User-Agent: mu4e 1.12.11; emacs 30.2 Date: Thu, 30 Oct 2025 22:31:34 -0300 Message-ID: <87bjlnvouh.fsf@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org Christina Schimpe writes: > Until now, handling of the shadow stack pointer has been done in the > target dependent implementations of the gdbarch hook > 'gdbarch_shadow_stack_push'. Also amd64 and aarch64 linux specific > unwinders for the shadow stack pointer are implemented. > In a following commit a subcommmand "backtrace shadow" of the ordinary Too mmany m's in "subcommand". > backtrace command will be added to print the shadow stack backtrace. > This requires more target-independent logic to handle the shadow stack > pointer. To avoid that we duplicate the logic, add new source and header > files "shadow-stack" for the implementation of shadow_stack_push and shad= ow > stack pointer unwinding in a target-independent way. > diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c > index 500ac77d75a..95af82c2632 100644 > --- a/gdb/aarch64-tdep.c > +++ b/gdb/aarch64-tdep.c As mentioned before, this change is also needed in aarch64-tdep.c to make this patch series work for AArch64: diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 95af82c26327..9e866fc319d4 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -4780,6 +4780,10 @@ aarch64_gdbarch_init (struct gdbarch_info info, stru= ct gdbarch_list *arches) /* Register a hook for converting a memory tag to a string. */ set_gdbarch_memtag_to_string (gdbarch, aarch64_memtag_to_string); =20 + if (tdep->has_gcs ()) + /* AArch64's shadow stack pointer is the GCSPR. */ + set_gdbarch_ssp_regnum (gdbarch, tdep->gcs_reg_base); + /* ABI */ set_gdbarch_short_bit (gdbarch, 16); set_gdbarch_int_bit (gdbarch, 32); > -static value * > -amd64_linux_dwarf2_prev_ssp (const frame_info_ptr &this_frame, > - void **this_cache, int regnum) > -{ > - value *v =3D frame_unwind_got_register (this_frame, regnum, regnum); > - gdb_assert (v !=3D nullptr); > - > - gdbarch *gdbarch =3D get_frame_arch (this_frame); > - > - if (v->entirely_available () && !v->optimized_out ()) > - { > - int size =3D register_size (gdbarch, regnum); > - bfd_endian byte_order =3D gdbarch_byte_order (gdbarch); > - CORE_ADDR ssp =3D extract_unsigned_integer (v->contents_all ().dat= a (), > - size, byte_order); > - > - /* Using /proc/PID/smaps we can only check if the current shadow > - stack pointer SSP points to shadow stack memory. Only if this is > - the case a valid previous shadow stack pointer can be > - calculated. */ > - std::pair range; > - if (linux_address_in_shadow_stack_mem_range (ssp, &range)) > - { > - /* The shadow stack grows downwards. To compute the previous > - shadow stack pointer, we need to increment SSP. */ > - CORE_ADDR new_ssp > - =3D ssp + amd64_linux_shadow_stack_element_size_aligned (gdbarch); > - > - /* There can be scenarios where we have a shadow stack pointer > - but the shadow stack is empty, as no call instruction has > - been executed yet. If NEW_SSP points to the end of or before > - (<=3D) the current shadow stack memory range we consider > - NEW_SSP as valid (but empty). */ > - if (new_ssp <=3D range.second) IIUC, the '<=3D' comparison above isn't preserved by this patch. This function is replaced by dwarf2_prev_ssp, which uses gdbarch_address_in_shadow_stack_memory_range for this if condition, whose comparison in find_addr_mem_range is: bool addr_in_mem_range =3D (addr >=3D map.start_address && addr < map.end_address); Is this intended? > - return frame_unwind_got_address (this_frame, regnum, new_ssp); > - } > - } > - > - /* Return a value which is marked as unavailable in case we could not > - calculate a valid previous shadow stack pointer. */ > - value *retval > - =3D value::allocate_register (get_next_frame_sentinel_okay (this_fra= me), > - regnum, register_type (gdbarch, regnum)); > - retval->mark_bytes_unavailable (0, retval->type ()->length ()); > - return retval; > -} > diff --git a/gdb/shadow-stack.c b/gdb/shadow-stack.c > new file mode 100644 > index 00000000000..d153d5fc846 > --- /dev/null > +++ b/gdb/shadow-stack.c > @@ -0,0 +1,167 @@ > +/* Manage a shadow stack pointer for GDB, the GNU debugger. > + > + Copyright (C) 2024-2025 Free Software Foundation, Inc. Should this really start at 2024? According to Andrew Burgess=C2=B9: > The start date should be when the patches were first posted to the list, > or otherwise made publicly available (e.g. Intel specific GDB release?). > The end date should be updated to 2025. Same question for other files created by this patch series. > + This file is part of GDB. > + > + This program is free software; you can redistribute it and/or modify > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see .= */ > + > +#include "defs.h" > +#include "arch-utils.h" > +#include "gdbcore.h" > +#include "extract-store-integer.h" > +#include "frame.h" > +#include "frame-unwind.h" > +#include "shadow-stack.h" > + > +enum class ssp_update_direction > +{ > + /* Update ssp towards the bottom of the shadow stack. */ > + bottom =3D 0, > + > + /* Update ssp towards the top of the shadow stack. */ > + top > +}; I find the bottom/top nomenclature confusing, especially because it's supposed to mean the same thing whether the stack grows up or down. In my mind, if the stack grow down then top means "oldest element", but if the stack grows up, then top means "newest element". But in this patch it seems that top means "newest element" regardless of the direction of stack growth. I would suggest changing the enum names above to something that's not related to the vertical axis, so that their meaning will be clear regardless of which direction the stack grows. A few suggestions: shrink/grow, older/younger, outer/inner. > +/* Return a new shadow stack pointer which is incremented or decremented > + by COUNT elements dependent on DIRECTION. */ > + > +static CORE_ADDR > +update_shadow_stack_pointer (gdbarch *gdbarch, CORE_ADDR ssp, > + const ssp_update_direction direction) > +{ > + bool increment =3D (gdbarch_stack_grows_down (gdbarch)) > + ? (direction =3D=3D ssp_update_direction::bottom) > + : (direction =3D=3D ssp_update_direction::top); All the parentheses above are superfluous and can be removed. > + CORE_ADDR new_ssp; This variable is unused and can be removed. Because by default GDB build with -Werror, this patch breaks the build with an "unused variable" error until patch 6 which removes this variable. > + if (increment) > + return ssp + gdbarch_shadow_stack_element_size_aligned (gdbarch); > + else > + return ssp - gdbarch_shadow_stack_element_size_aligned (gdbarch); > +} > + > +/* See shadow-stack.h. */ > + > +void shadow_stack_push (gdbarch *gdbarch, regcache *regcache, There's no need for a gdbarch argument. You can get it from the regcache. > + const CORE_ADDR new_addr) > +{ > + if (!gdbarch_address_in_shadow_stack_memory_range_p (gdbarch) > + || gdbarch_ssp_regnum (gdbarch) =3D=3D -1) > + return; > + > + bool shadow_stack_enabled; > + std::optional ssp > + =3D gdbarch_get_shadow_stack_pointer (gdbarch, regcache, > + shadow_stack_enabled); > + if (!ssp.has_value () || !shadow_stack_enabled) > + return; > + > + const CORE_ADDR new_ssp > + =3D update_shadow_stack_pointer (gdbarch, *ssp, > + ssp_update_direction::top); > + > + /* If NEW_SSP does not point to shadow stack memory, we assume the sta= ck > + is full. */ > + std::pair range; > + if (!gdbarch_address_in_shadow_stack_memory_range (gdbarch, > + new_ssp, > + &range)) Range isn't really needed by this function. I suggest changing gdbarch_address_in_shadow_stack_memory_range to allow for it to be nullptr and then pass nullptr here. Also, the line above fits in 80 columns and doesn't need to be broken, even if "&range" is changed to "nullptr". > + error (_("No space left on the shadow stack.")); > + > + /* On x86 there can be a shadow stack token at bit 63. For x32, the > + address size is only 32 bit. Always write back the full 8 bytes to > + include the shadow stack token. */ s/8 bytes/element size/ > + const int element_size > + =3D gdbarch_shadow_stack_element_size_aligned (gdbarch); > + > + const bfd_endian byte_order =3D gdbarch_byte_order (gdbarch); > + > + write_memory_unsigned_integer (new_ssp, element_size, byte_order, > + (ULONGEST) new_addr); > + > + regcache_raw_write_unsigned (regcache, > + gdbarch_ssp_regnum (gdbarch), > + new_ssp); The line above fits in 80 columns and doesn't need to be broken. > +} > + > +/* See shadow-stack.h. */ > + > +value * > +dwarf2_prev_ssp (const frame_info_ptr &this_frame, void **this_cache, > + int regnum) > +{ > + value *v =3D frame_unwind_got_register (this_frame, regnum, regnum); > + gdb_assert (v !=3D nullptr); > + > + gdbarch *gdbarch =3D get_frame_arch (this_frame); > + > + if (gdbarch_address_in_shadow_stack_memory_range_p (gdbarch) > + && v->entirely_available () && !v->optimized_out ()) > + { > + const int size =3D register_size (gdbarch, regnum); > + bfd_endian byte_order =3D gdbarch_byte_order (gdbarch); > + CORE_ADDR ssp =3D extract_unsigned_integer > + (v->contents_all ().data (), size, byte_order); > + > + /* Only if the current shadow stack pointer SSP points to shadow > + stack memory a valid previous shadow stack pointer can be > + calculated. */ > + std::pair range; > + if (gdbarch_address_in_shadow_stack_memory_range (gdbarch, ssp, > + &range)) This line fits in 80 columns and doesn't need to be broken. > + { > + /* Note that a shadow stack memory range can change, due to > + shadow stack switches for instance on x86 for an inter- > + privilege far call or when calling an interrupt/exception > + handler at a higher privilege level. Shadow stack for > + userspace is supported for amd64 linux starting with > + Linux kernel v6.6. However, shadow stack switches are not > + supported due to missing kernel space support. We therefore > + implement this unwinder without support for shadow stack > + switches for now. */ > + const CORE_ADDR new_ssp > + =3D update_shadow_stack_pointer (gdbarch, ssp, > + ssp_update_direction::bottom); > + > + /* On x86, if NEW_SSP points to the end of RANGE, it indicates > + that NEW_SSP is valid, but the shadow stack is empty. In > + contrast, on ARM's Guarded Control Stack, if NEW_SSP points > + to the end of RANGE, it means that the shadow stack pointer > + is invalid. */ > + bool is_top_addr_empty_shadow_stack > + =3D gdbarch_top_addr_empty_shadow_stack_p (gdbarch) > + && gdbarch_top_addr_empty_shadow_stack (gdbarch, new_ssp, range); > + > + /* Check whether the new SSP is valid. Depending on the > + architecture, this may rely on both > + IS_TOP_ADDR_EMPTY_SHADOW_STACK and the return value of > + gdbarch_address_in_shadow_stack_memory_range, or on the > + latter only. */ > + if (is_top_addr_empty_shadow_stack Considering that, as previously mentioned, gdbarch_address_in_shadow_stack_memory_range uses '<' rather than '<=3D' in the memory range check, AArch64 doesn't need gdbarch_top_addr_empty_shadow_stack. The way this if condition is written, I think it's x86_64 that would need to provide an gdbarch_top_addr_empty_shadow_stack implementation. I'm surprised it doesn't. > + || gdbarch_address_in_shadow_stack_memory_range (gdbarch, > + ssp, Shouldn't this argument be new_ssp? > + &range)) > + return frame_unwind_got_address (this_frame, regnum, new_ssp); > + } > + } > + > + /* Return a value which is marked as unavailable, in case we could not > + calculate a valid previous shadow stack pointer. */ > + value *retval > + =3D value::allocate_register (get_next_frame_sentinel_okay (this_fra= me), > + regnum, register_type (gdbarch, regnum)); > + retval->mark_bytes_unavailable (0, retval->type ()->length ()); > + return retval; > + Spurious empty line added here. > +} > diff --git a/gdb/shadow-stack.h b/gdb/shadow-stack.h > new file mode 100644 > index 00000000000..5c3ba80974e > --- /dev/null > +++ b/gdb/shadow-stack.h > @@ -0,0 +1,39 @@ > +/* Definitions to manage a shadow stack pointer for GDB, the GNU debugge= r. > + > + Copyright (C) 2024-2025 Free Software Foundation, Inc. > + > + This file is part of GDB. > + > + This program is free software; you can redistribute it and/or modify > + > + it under the terms of the GNU General Public License as published by > + the Free Software Foundation; either version 3 of the License, or > + (at your option) any later version. > + > + This program is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + GNU General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program. If not, see .= */ > + > +#ifndef GDB_SHADOW_STACK_H > +#define GDB_SHADOW_STACK_H > + > +/* If shadow stack is enabled, push the address NEW_ADDR on the shadow > + stack and update the shadow stack pointer accordingly. */ > + > +void shadow_stack_push (gdbarch *gdbarch, regcache *regcache, Recently, the project has been trying to make the header files contain all the headers and definitions that they need, for the benefit of IDE and language server users, so that these tools don't emit spurious errors when showing a header file. In this case, clangd is complaining here that regcache is unknown. There's no need to include regcache.h just for it, just adding a "class regcache" forward declaration at the beginning of the file is enough. > + const CORE_ADDR new_addr); > + > +/* Unwind the previous shadow stack pointer of THIS_FRAME's shadow stack > + pointer. REGNUM is the register number of the shadow stack pointer. > + Return a value that is unavailable in case we cannot unwind the > + previous shadow stack pointer. Otherwise, return a value containing > + the previous shadow stack pointer. */ > + > +value * dwarf2_prev_ssp (const frame_info_ptr &this_frame, The space after "value *" should be removed. > + void **this_cache, int regnum); > + > +#endif /* GDB_SHADOW_STACK_H */ --=20 Thiago =C2=B9 https://inbox.sourceware.org/gdb-patches/87ldo6c84t.fsf@redhat.com/