Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <4376f75c-6cd4-413b-a5a7-162eb3bb5165@foss.arm.com>
Date: Mon, 24 Aug 2026 11:13:25 -0500
From: Bill Roberts <bill.roberts@...s.arm.com>
To: musl@...ts.openwall.com
Subject: Re: [PATCH] x86_64: add CET shadow stack support


On 8/10/26 3:18 PM, Khosro Moeini wrote:
> Enable CET shadow stack on x86_64 when the executable and
> all loaded shared objects have the GNU_PROPERTY_X86_FEATURE_1_SHSTK bit set
> in their .note.gnu.property note. If shadow stack is enabled for a process,
> dlopen of an object without the shadow stack property note fails.

This is similar to aarch64, I cannot speak for x86, but ti would be 
interesting
if this code could be made generic except for the part that introspects 
the ELF
for the bit indicating the feature is enabled.

> Unlike glibc, this implementation does not check environment variables,
> but this could be changed.
>
> The patch enables the shadow stack and locks it using the arch_prctl syscall.
> The function that enables the shadow stack cannot return, so SHSTK_ENABLE
> is defined as a macro and used in libc_start_main_stage2.

FYI, I have patches on the kernel mailing list to combine the interface 
to prctl as used
by aarch64 and riscv, so if musl doesn't need to support older kernels, 
the enabling code
could be made generic.

I found a link to the v2 patch, note there is a v3, I don't know why it 
didn't turn up,
but Shashiko pointed out a bug so I nacked it. But the concept is the same.

https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg2649547.html

>
> setjmp and sigsetjmp are modified to store the shadow stack pointer in __ss[2].
> longjmp restores the shadow stack pointer.
>
> In vfork, in child, jmp to caller to avoid changing the shadow stack
> which is shared with parent.
>
> All the changes are guarded by SHSTK_ENABLED which is set through
> the --enable-cet configuration option.
>
> Please CC on reply.
> ---
>   Makefile                                      |  11 +-
>   arch/x86_64/note.s                            |  12 ++
>   configure                                     |  29 ++++
>   include/elf.h                                 |   5 +
>   ldso/dynlink.c                                |  25 +++
>   src/env/__libc_start_main.c                   |  11 ++
>   src/internal/shstk.h                          |  39 +++++
>   src/ldso/x86_64/shstk.c                       | 143 ++++++++++++++++++
>   src/process/x86_64/{vfork.s => vfork.S}       |  13 ++
>   src/setjmp/x86_64/{longjmp.s => longjmp.S}    |  24 +++
>   src/setjmp/x86_64/{setjmp.s => setjmp.S}      |   6 +
>   .../x86_64/{sigsetjmp.s => sigsetjmp.S}       |  17 +++
>   12 files changed, 331 insertions(+), 4 deletions(-)
>   create mode 100644 arch/x86_64/note.s
>   create mode 100644 src/internal/shstk.h
>   create mode 100644 src/ldso/x86_64/shstk.c
>   rename src/process/x86_64/{vfork.s => vfork.S} (35%)
>   rename src/setjmp/x86_64/{longjmp.s => longjmp.S} (52%)
>   rename src/setjmp/x86_64/{setjmp.s => setjmp.S} (82%)
>   rename src/signal/x86_64/{sigsetjmp.s => sigsetjmp.S} (56%)
>
> diff --git a/Makefile b/Makefile
> index 3ad88b3..2d69328 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -45,6 +45,7 @@ CPPFLAGS =
>   CFLAGS =
>   CFLAGS_AUTO = -Os -pipe
>   CFLAGS_C99FSE = -std=c99 -ffreestanding -nostdinc
> +ASM_NOTE =
>   
>   CFLAGS_ALL = $(CFLAGS_C99FSE)
>   CFLAGS_ALL += -D_XOPEN_SOURCE=700 -I$(srcdir)/arch/$(ARCH) -I$(srcdir)/arch/generic -Iobj/src/internal -I$(srcdir)/src/include -I$(srcdir)/src/internal -Iobj/include -I$(srcdir)/include
> @@ -135,16 +136,18 @@ CC_CMD = $(CC) $(CFLAGS_ALL) -c -o $@ $<
>   
>   # Choose invocation of assembler to be used
>   ifeq ($(ADD_CFI),yes)
> -	AS_CMD = LC_ALL=C awk -f $(srcdir)/tools/add-cfi.common.awk -f $(srcdir)/tools/add-cfi.$(ARCH).awk $< | $(CC) $(CFLAGS_ALL) -x assembler -c -o $@ -
> +	AS_CMD = LC_ALL=C awk -f $(srcdir)/tools/add-cfi.common.awk -f $(srcdir)/tools/add-cfi.$(ARCH).awk $< $(ASM_NOTE) | $(CC) $(CFLAGS_ALL) -x assembler -c -o $@ -
>   else
> -	AS_CMD = $(CC_CMD)
> +	AS_CMD = cat $< $(ASM_NOTE) | $(CC) $(CFLAGS_ALL) -x assembler -c -o $@ -
>   endif
>   
> +ASCPP_CMD = cat $< $(ASM_NOTE) | $(CC) $(CFLAGS_ALL) -x assembler-with-cpp -c -o $@ -
> +
>   obj/%.o: $(srcdir)/%.s
>   	$(AS_CMD)
>   
>   obj/%.o: $(srcdir)/%.S
> -	$(CC_CMD)
> +	$(ASCPP_CMD)
>   
>   obj/%.o: $(srcdir)/%.c $(GENH) $(IMPH)
>   	$(CC_CMD)
> @@ -153,7 +156,7 @@ obj/%.lo: $(srcdir)/%.s
>   	$(AS_CMD)
>   
>   obj/%.lo: $(srcdir)/%.S
> -	$(CC_CMD)
> +	$(ASCPP_CMD)
>   
>   obj/%.lo: $(srcdir)/%.c $(GENH) $(IMPH)
>   	$(CC_CMD)
> diff --git a/arch/x86_64/note.s b/arch/x86_64/note.s
> new file mode 100644
> index 0000000..cb03e5a
> --- /dev/null
> +++ b/arch/x86_64/note.s
> @@ -0,0 +1,12 @@
> +/* .note.gnu.property is 8-byte aligned in 64-bit objects */
> +.section .note.gnu.property,"a"
> +.balign 8
> +.long 4          /* n_namesz: sizeof "GNU" */
> +.long 16         /* n_descsz: one 8-byte-padded property */
> +.long 5          /* n_type: NT_GNU_PROPERTY_TYPE_0 */
> +.asciz "GNU"
> +.long 0xc0000002 /* pr_type: GNU_PROPERTY_X86_FEATURE_1_AND */
> +.long 4          /* pr_datasz */
> +.long 2          /* GNU_PROPERTY_X86_FEATURE_1_SHSTK */
> +.long 0          /* padding to 8-byte alignment */
> +.previous
> diff --git a/configure b/configure
> index bc9fbe4..a278c81 100755
> --- a/configure
> +++ b/configure
> @@ -34,6 +34,7 @@ Optional features:
>     --enable-wrapper=...    build given musl toolchain wrapper [auto]
>     --disable-shared        inhibit building shared library [enabled]
>     --disable-static        inhibit building static library [enabled]
> +  --enable-cet            build with CET shadow stack support [disabled]
>   
>   Optional packages:
>     --with-malloc=...       choose malloc implementation [mallocng]
> @@ -142,6 +143,7 @@ static=yes
>   wrapper=auto
>   gcc_wrapper=no
>   clang_wrapper=no
> +cet=no
>   malloc_dir=mallocng
>   
>   for arg ; do
> @@ -172,6 +174,8 @@ case "$arg" in
>   --disable-wrapper|--enable-wrapper=no) wrapper=no ;;
>   --enable-gcc-wrapper|--enable-gcc-wrapper=yes) wrapper=yes ; gcc_wrapper=yes ;;
>   --disable-gcc-wrapper|--enable-gcc-wrapper=no) wrapper=no ;;
> +--enable-cet|--enable-cet=yes) cet=yes ;;
> +--disable-cet|--enable-cet=no) cet=no ;;
>   --with-malloc=*) malloc_dir=${arg#*=} ;;
>   --enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;;
>   --host=*|--target=*) target=${arg#*=} ;;
> @@ -759,6 +763,30 @@ fi
>   test "$SUBARCH" \
>   && printf "configured for %s variant: %s\n" "$ARCH" "$ARCH$SUBARCH"
>   
> +ASM_NOTE=
> +if test "$cet" = yes ; then
> +
> +if test "$ARCH" != "x86_64" ; then
> +fail "$0: error: --enable-cet is only supported on x86_64"
> +fi
> +
> +tryflag CFLAGS_AUTO -fcf-protection=return \
> +|| fail "$0: error: --enable-cet requires compiler support for -fcf-protection"
> +
> +printf "checking whether assembler supports rdssp/incssp instructions... "
> +echo "__asm__(\"xor %eax,%eax ; rdsspq %rax ; incsspq %rax\");" > "$tmpc"
> +if $CC -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
> +printf "yes\n"
> +else
> +printf "no\n"
> +fail "$0: error: --enable-cet requires assembler support for rdssp/incssp"
> +fi
> +
> +CFLAGS_AUTO="$CFLAGS_AUTO -DSHSTK_ENABLED=1"
> +
> +ASM_NOTE="arch/$ARCH/note.s"
> +fi
> +
>   #
>   # Some archs (powerpc) have different possible long double formats
>   # that the compiler can be configured for. The logic for whether this
> @@ -820,6 +848,7 @@ CFLAGS_AUTO = $CFLAGS_AUTO
>   CFLAGS_C99FSE = $CFLAGS_C99FSE
>   CFLAGS_MEMOPS = $CFLAGS_MEMOPS
>   CFLAGS_NOSSP = $CFLAGS_NOSSP
> +ASM_NOTE = $ASM_NOTE
>   CPPFLAGS = $CPPFLAGS
>   LDFLAGS = $LDFLAGS
>   LDFLAGS_AUTO = $LDFLAGS_AUTO
> diff --git a/include/elf.h b/include/elf.h
> index 2555b90..622d1e0 100644
> --- a/include/elf.h
> +++ b/include/elf.h
> @@ -1112,6 +1112,11 @@ typedef struct {
>   #define NT_GNU_GOLD_VERSION	4
>   #define NT_GNU_PROPERTY_TYPE_0	5
>   
> +#define GNU_PROPERTY_X86_FEATURE_1_AND   0xc0000002
> +
> +#define GNU_PROPERTY_X86_FEATURE_1_IBT   (1U << 0)
> +#define GNU_PROPERTY_X86_FEATURE_1_SHSTK (1U << 1)
> +
>   
>   
>   typedef struct {
> diff --git a/ldso/dynlink.c b/ldso/dynlink.c
> index 10471b2..292af2a 100644
> --- a/ldso/dynlink.c
> +++ b/ldso/dynlink.c
> @@ -23,6 +23,7 @@
>   #include "fork_impl.h"
>   #include "libc.h"
>   #include "dynlink.h"
> +#include "shstk.h"
>   
>   static size_t ldso_page_size;
>   /* libc.h may have defined a macro for dynamic PAGE_SIZE already, but
> @@ -702,6 +703,9 @@ static void *map_library(int fd, struct dso *dso)
>   	size_t dyn=0;
>   	size_t tls_image=0;
>   	size_t i;
> +#if SHSTK_ENABLED
> +	Phdr *gnu_prop_ph=0;
> +#endif
>   
>   	ssize_t l = read(fd, buf, sizeof buf);
>   	eh = buf;
> @@ -741,6 +745,10 @@ static void *map_library(int fd, struct dso *dso)
>   					ph->p_memsz < DEFAULT_STACK_MAX ?
>   					ph->p_memsz : DEFAULT_STACK_MAX;
>   			}
> +#if SHSTK_ENABLED
> +		} else if (ph->p_type == PT_GNU_PROPERTY) {
> +			gnu_prop_ph = ph;
> +#endif
>   		}
>   		if (ph->p_type != PT_LOAD) continue;
>   		nsegs++;
> @@ -862,6 +870,13 @@ done_mapping:
>   	dso->base = base;
>   	dso->dynv = laddr(dso, dyn);
>   	if (dso->tls.size) dso->tls.image = laddr(dso, tls_image);
> +#if SHSTK_ENABLED
> +	int ret = __try_update_x86_feature_1_and((size_t)base, gnu_prop_ph);
> +	if (ret) {
> +		errno = ret;
> +		goto error;
> +	}
> +#endif
>   	free(allocated_buf);
>   	return map;
>   noexec:
> @@ -1455,6 +1470,10 @@ static void kernel_mapped_dso(struct dso *p)
>   					ph->p_memsz < DEFAULT_STACK_MAX ?
>   					ph->p_memsz : DEFAULT_STACK_MAX;
>   			}
> +#if SHSTK_ENABLED
> +		} else if (ph->p_type == PT_GNU_PROPERTY) {
> +			__update_x86_feature_1_and((size_t)p->base, ph);
> +#endif
>   		}
>   		if (ph->p_type != PT_LOAD) continue;
>   		if (ph->p_vaddr < min_addr)
> @@ -1637,6 +1656,12 @@ void __init_tls(size_t *auxv)
>   {
>   }
>   
> +#if SHSTK_ENABLED
> +void __init_x86_feature_1_and(void)
> +{
> +}
> +#endif
> +
>   static void update_tls_size()
>   {
>   	libc.tls_cnt = tls_cnt;
> diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c
> index c5b277b..968f128 100644
> --- a/src/env/__libc_start_main.c
> +++ b/src/env/__libc_start_main.c
> @@ -6,6 +6,7 @@
>   #include "syscall.h"
>   #include "atomic.h"
>   #include "libc.h"
> +#include "shstk.h"
>   
>   static void dummy(void) {}
>   weak_alias(dummy, _init);
> @@ -89,6 +90,16 @@ int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv,
>   static int libc_start_main_stage2(int (*main)(int,char **,char **), int argc, char **argv)
>   {
>   	char **envp = argv+argc+1;
> +
> +#if SHSTK_ENABLED
> +	__init_x86_feature_1_and();
> +	if (__x86_feature_1_and & GNU_PROPERTY_X86_FEATURE_1_SHSTK) {
> +		SHSTK_ENABLE();
> +		__lock_shstk();
> +	}
> +	__init_shstk_status();
> +#endif
> +
>   	__libc_start_init();
>   
>   	/* Pass control to the application */
> diff --git a/src/internal/shstk.h b/src/internal/shstk.h
> new file mode 100644
> index 0000000..8495a51
> --- /dev/null
> +++ b/src/internal/shstk.h
> @@ -0,0 +1,39 @@
> +#ifndef SHSTK_H
> +#define SHSTK_H
> +
> +#if SHSTK_ENABLED
> +
> +#include <elf.h>
> +#include <stddef.h>
> +#include <features.h>
> +
> +#define ARCH_SHSTK_ENABLE 0x5001
> +#define ARCH_SHSTK_LOCK   0x5003
> +#define ARCH_SHSTK_STATUS 0x5005
> +
> +#define ARCH_SHSTK_SHSTK  1
> +
> +extern hidden unsigned __x86_feature_1_and;
> +extern hidden unsigned long __shstk_status;
> +
> +hidden void __init_x86_feature_1_and(void);
> +
> +hidden void __update_x86_feature_1_and(size_t base, Elf64_Phdr *ph);
> +
> +hidden int __try_update_x86_feature_1_and(size_t base, Elf64_Phdr *ph);
> +
> +hidden int __init_shstk_status(void);
> +
> +hidden int __lock_shstk(void);
> +
> +#define SHSTK_ENABLE() do { \
> +	unsigned long ret; \
> +	__asm__ __volatile__ ( "syscall" \
> +		: "=a"(ret) \
> +		: "a"(SYS_arch_prctl), "D"(ARCH_SHSTK_ENABLE), "S"(ARCH_SHSTK_SHSTK) \
> +		: "rcx", "r11", "memory" ); \
> +	} while (0)
> +
> +#endif
> +
> +#endif
> diff --git a/src/ldso/x86_64/shstk.c b/src/ldso/x86_64/shstk.c
> new file mode 100644
> index 0000000..91d0044
> --- /dev/null
> +++ b/src/ldso/x86_64/shstk.c
> @@ -0,0 +1,143 @@
> +#if SHSTK_ENABLED
> +
> +#include <elf.h>
> +#include <errno.h>
> +#include <stdint.h>
> +#include <string.h>
> +#include "libc.h"
> +#include "shstk.h"
> +#include "syscall.h"
> +
> +hidden unsigned __x86_feature_1_and = -1;
> +hidden unsigned long __shstk_status = 0;
> +
> +#define ALIGNMENT sizeof(Elf64_Addr)
> +#define ALIGN_UP(x,y) ((x)+(y)-1 & -(y))
> +
> +/* gnu properties are a sequence of type/size/value */
> +static unsigned feature_from_desc(const unsigned char *p, size_t len)
> +{
> +	while (len >= 8) {
> +		uint32_t type, datasz;
> +		type = *(uint32_t *)p;
> +		p += sizeof(uint32_t);
> +		datasz = *(uint32_t *)p;
> +		p += sizeof(uint32_t);
> +		len -= 2*sizeof(uint32_t);
> +		if (datasz > len) return 0;
> +		if (type == GNU_PROPERTY_X86_FEATURE_1_AND) {
> +			uint32_t feature;
> +			if (datasz != 4) return 0;
> +			feature = *(uint32_t *)p;
> +			return feature;
> +		}
> +		if (type > GNU_PROPERTY_X86_FEATURE_1_AND) return 0;
> +		size_t adv = ALIGN_UP(datasz, ALIGNMENT);
> +		if (adv > len) return 0;
> +		p += adv;
> +		len -= adv;
> +	}
> +	return 0;
> +}
> +
> +static unsigned feature_from_segment(const unsigned char *p, size_t len)
> +{
> +	while (len >= sizeof(Elf64_Nhdr)) {
> +		Elf64_Nhdr *nh = (Elf64_Nhdr *)p;
> +		size_t skip;
> +
> +		size_t desc_offset = ALIGN_UP(sizeof(Elf64_Nhdr) + nh->n_namesz, ALIGNMENT);
> +		if (nh->n_namesz == 4
> +		    && nh->n_type == NT_GNU_PROPERTY_TYPE_0
> +		    && len >= desc_offset
> +		    && !memcmp(p + sizeof(Elf64_Nhdr), "GNU", 4)) {
> +			if (nh->n_descsz < ALIGNMENT || nh->n_descsz % ALIGNMENT
> +			    || nh->n_descsz > len - desc_offset)
> +				return 0;
> +			return feature_from_desc(p + desc_offset, nh->n_descsz);
> +		}
> +
> +		skip = ALIGN_UP(sizeof(Elf64_Nhdr) + (size_t)nh->n_namesz, ALIGNMENT);
> +		if (skip > len) return 0;
> +		len -= skip;
> +		p += skip;
> +		skip = ALIGN_UP((size_t)nh->n_descsz, ALIGNMENT);
> +		if (skip > len) return 0;
> +		len -= skip;
> +		p += skip;
> +	}
> +	return 0;
> +}
> +
> +static unsigned get_feature_from_header(size_t base, void *ph0)
> +{
> +	Elf64_Phdr *ph = ph0;
> +	if (!ph || ph->p_align != ALIGNMENT) return 0;
> +	return feature_from_segment((void *)(base + ph->p_vaddr), ph->p_memsz);
> +}
> +
> +/* four cases here:
> + * (1) feature set, shstk set -> dlopen, should fail if no shstk note
> + * (2) feature set, shstk not set -> initial loading, should update feature
> + * (3) feature not set, shstk not set -> no update needed
> + * (4) feature not set, shstk set -> impossible */
> +hidden int __try_update_x86_feature_1_and(size_t base, Elf64_Phdr *ph)
> +{
> +	if (!(__x86_feature_1_and & GNU_PROPERTY_X86_FEATURE_1_SHSTK))
> +		return 0;
> +	/* feature is set */
> +	unsigned long dso_features = get_feature_from_header(base, ph);
> +	if (!(__shstk_status & ARCH_SHSTK_SHSTK)) {
> +		__x86_feature_1_and &= dso_features;
> +		return 0;
> +	}
> +	/* feature and shstk are set */
> +	if (dso_features & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
> +		return 0;
> +	return ENOTSUP;
> +}
> +
> +hidden void __update_x86_feature_1_and(size_t base, Elf64_Phdr *ph)
> +{
> +	__x86_feature_1_and &= get_feature_from_header(base, ph);
> +}
> +
> +#define AUX_CNT 38
> +extern weak hidden const size_t _DYNAMIC[];
> +
> +static void static_init_x86_feature_1_and(void)
> +{
> +	size_t i, aux[AUX_CNT] = { 0 };
> +	unsigned char *p;
> +	size_t n, base = 0;
> +	Elf64_Phdr *gnu_prop_ph = 0;
> +
> +	for (i=0; libc.auxv[i]; i+=2)
> +		if (libc.auxv[i]<AUX_CNT) aux[libc.auxv[i]] = libc.auxv[i+1];
> +
> +	for (p=(void *)aux[AT_PHDR], n=aux[AT_PHNUM]; n; n--, p+=aux[AT_PHENT]) {
> +		Elf64_Phdr *ph = (void *)p;
> +		if (ph->p_type == PT_PHDR)
> +			base = aux[AT_PHDR] - ph->p_vaddr;
> +		if (ph->p_type == PT_DYNAMIC && _DYNAMIC)
> +			base = (size_t)_DYNAMIC - ph->p_vaddr;
> +		if (ph->p_type == PT_GNU_PROPERTY)
> +			gnu_prop_ph = ph;
> +	}
> +
> +	__x86_feature_1_and = get_feature_from_header(base, gnu_prop_ph);
> +}
> +
> +weak_alias(static_init_x86_feature_1_and, __init_x86_feature_1_and);
> +
> +hidden int __init_shstk_status(void)
> +{
> +	return syscall(SYS_arch_prctl, ARCH_SHSTK_STATUS, &__shstk_status);
> +}
> +
> +hidden int __lock_shstk(void)
> +{
> +	return syscall(SYS_arch_prctl, ARCH_SHSTK_LOCK, -1UL);
> +}
> +
> +#endif
> diff --git a/src/process/x86_64/vfork.s b/src/process/x86_64/vfork.S
> similarity index 35%
> rename from src/process/x86_64/vfork.s
> rename to src/process/x86_64/vfork.S
> index 9114439..da4aea5 100644
> --- a/src/process/x86_64/vfork.s
> +++ b/src/process/x86_64/vfork.S
> @@ -4,6 +4,19 @@ vfork:
>   	pop %rdx
>   	mov $58,%eax
>   	syscall
> +#if SHSTK_ENABLED
> +	/* If parent normal return */
> +	test %eax,%eax
> +	jnz 1f
> +	/* If child and no shstk normal return */
> +	xor %ecx,%ecx
> +	rdsspq %rcx
> +	test %rcx,%rcx
> +	jz 1f
> +	/* If child and shstk jmp instead, no need to call __syscall_ret */
> +	jmp *%rdx
> +1:
> +#endif
>   	push %rdx
>   	mov %rax,%rdi
>   	.hidden __syscall_ret
> diff --git a/src/setjmp/x86_64/longjmp.s b/src/setjmp/x86_64/longjmp.S
> similarity index 52%
> rename from src/setjmp/x86_64/longjmp.s
> rename to src/setjmp/x86_64/longjmp.S
> index 1b2661c..9169996 100644
> --- a/src/setjmp/x86_64/longjmp.s
> +++ b/src/setjmp/x86_64/longjmp.S
> @@ -5,6 +5,30 @@
>   .type longjmp,@function
>   _longjmp:
>   longjmp:
> +#if SHSTK_ENABLED
> +	xor %ecx,%ecx
> +	rdsspq %rcx
> +	test %rcx,%rcx
> +	jz 2f
> +	/* if shstk is active */
> +	mov 88(%rdi),%rdx       /* shadow stack pointer saved by setjmp */
> +	sub %rcx,%rdx
> +	/* target below current */
> +	jb 2f
> +	/* slots between current and target */
> +	/* 3^2 = 8 = q in incsspq */
> +	shr $3,%rdx
> +	/* plus the slot setjmp itself returned to */
> +	add $1,%rdx
> +	/* incssp pops at most 255 slots at a time */
> +1:	mov $255,%rcx
> +	cmp %rcx,%rdx
> +	cmovb %rdx,%rcx
> +	incsspq %rcx
> +	sub %rcx,%rdx
> +	ja 1b
> +2:
> +#endif
>   	xor %eax,%eax
>   	cmp $1,%esi             /* CF = val ? 0 : 1 */
>   	adc %esi,%eax           /* eax = val + !val */
> diff --git a/src/setjmp/x86_64/setjmp.s b/src/setjmp/x86_64/setjmp.S
> similarity index 82%
> rename from src/setjmp/x86_64/setjmp.s
> rename to src/setjmp/x86_64/setjmp.S
> index d95e485..47ce57a 100644
> --- a/src/setjmp/x86_64/setjmp.s
> +++ b/src/setjmp/x86_64/setjmp.S
> @@ -18,5 +18,11 @@ setjmp:
>   	mov %rdx,48(%rdi)
>   	mov (%rsp),%rdx         /* save return addr ptr for new rip */
>   	mov %rdx,56(%rdi)
> +#if SHSTK_ENABLED
> +	/* store shstk pointer in __ss[2] = (72 + 2*8) = 88 */
> +	xor %eax,%eax
> +	rdsspq %rax
> +	mov %rax,88(%rdi)
> +#endif
>   	xor %eax,%eax           /* always return 0 */
>   	ret
> diff --git a/src/signal/x86_64/sigsetjmp.s b/src/signal/x86_64/sigsetjmp.S
> similarity index 56%
> rename from src/signal/x86_64/sigsetjmp.s
> rename to src/signal/x86_64/sigsetjmp.S
> index 9a7695f..e88d277 100644
> --- a/src/signal/x86_64/sigsetjmp.s
> +++ b/src/signal/x86_64/sigsetjmp.S
> @@ -18,7 +18,24 @@ __sigsetjmp:
>   	mov %eax,%esi
>   	mov 72+8(%rbx),%rbx
>   
> +#if SHSTK_ENABLED
> +	test %eax,%eax
> +	jnz 2f
> +
> +	/* original call */
> +	xor %edx,%edx
> +	rdsspq %rdx
> +	/* store shstk pointer in __ss[2] */
> +	/* rdi holds the jmp_buf now */
> +	mov %rdx,88(%rdi)
> +#endif
>   .hidden __sigsetjmp_tail
>   	jmp __sigsetjmp_tail
>   
> +#if SHSTK_ENABLED
> +2:	call __sigsetjmp_tail
> +	pop %rdx
> +	jmp *%rdx
> +#endif
> +
>   1:	jmp setjmp@PLT

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.