[PATCH v5 3/6] x86/cet: Enable shadow stack during startup
H.J. Lu
hjl.tools@gmail.com
Fri Dec 29 15:24:20 GMT 2023
On Fri, Dec 29, 2023 at 6:55 AM Adhemerval Zanella Netto
<adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 22/12/23 13:58, H.J. Lu wrote:
> > Previously, CET was enabled by kernel before passing control to user
> > space and the startup code must disable CET if applications or shared
> > libraries aren't CET enabled. Since the current kernel only supports
> > shadow stack and won't enable shadow stack before passing control to
> > user space, we need to enable shadow stack during startup if the
> > application and all shared library are shadow stack enabled. There
> > is no need to disable shadow stack at startup. Shadow stack can only
> > be enabled in a function which will never return. Otherwise, shadow
> > stack will underflow at the function return.
> >
> > 1. GL(dl_x86_feature_1) is set to the CET features which are supported
> > by the processor and are not disabled by the tunable. Only non-zero
> > features in GL(dl_x86_feature_1) should be enabled. After enabling
> > shadow stack with ARCH_SHSTK_ENABLE, ARCH_SHSTK_STATUS is used to check
> > if shadow stack is really enabled.
> > 2. Use ARCH_SHSTK_ENABLE in RTLD_START in dynamic executable. It is
> > safe since RTLD_START never returns.
> > 3. Call arch_prctl (ARCH_SHSTK_ENABLE) from ARCH_SETUP_TLS in static
> > executable. Since the start function using ARCH_SETUP_TLS never returns,
> > it is safe to enable shadow stack in ARCH_SETUP_TLS.
> > ---
> > sysdeps/unix/sysv/linux/x86/cpu-features.c | 49 --------------
> > sysdeps/unix/sysv/linux/x86/dl-cet.h | 23 +++++++
> > sysdeps/unix/sysv/linux/x86_64/dl-cet.h | 47 +++++++++++++
> > sysdeps/x86/cpu-features-offsets.sym | 1 +
> > sysdeps/x86/cpu-features.c | 51 --------------
> > sysdeps/x86/dl-cet.c | 77 +++++++++++-----------
> > sysdeps/x86/get-cpuid-feature-leaf.c | 2 +-
> > sysdeps/x86/include/cpu-features.h | 3 +
> > sysdeps/x86/libc-start.h | 54 ++++++++++++++-
> > sysdeps/x86_64/dl-machine.h | 12 +++-
> > 10 files changed, 175 insertions(+), 144 deletions(-)
> > delete mode 100644 sysdeps/unix/sysv/linux/x86/cpu-features.c
> > create mode 100644 sysdeps/unix/sysv/linux/x86_64/dl-cet.h
> >
> > diff --git a/sysdeps/unix/sysv/linux/x86/cpu-features.c b/sysdeps/unix/sysv/linux/x86/cpu-features.c
> > deleted file mode 100644
> > index 0e6e2bf855..0000000000
> > --- a/sysdeps/unix/sysv/linux/x86/cpu-features.c
> > +++ /dev/null
> > @@ -1,49 +0,0 @@
> > -/* Initialize CPU feature data for Linux/x86.
> > - This file is part of the GNU C Library.
> > - Copyright (C) 2018-2023 Free Software Foundation, Inc.
> > -
> > - The GNU C Library is free software; you can redistribute it and/or
> > - modify it under the terms of the GNU Lesser General Public
> > - License as published by the Free Software Foundation; either
> > - version 2.1 of the License, or (at your option) any later version.
> > -
> > - The GNU C Library 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
> > - Lesser General Public License for more details.
> > -
> > - You should have received a copy of the GNU Lesser General Public
> > - License along with the GNU C Library; if not, see
> > - <https://www.gnu.org/licenses/>. */
> > -
> > -#if CET_ENABLED
> > -# include <sys/prctl.h>
> > -# include <asm/prctl.h>
> > -
> > -static inline int __attribute__ ((always_inline))
> > -get_cet_status (void)
> > -{
> > - unsigned long long kernel_feature;
> > - unsigned int status = 0;
> > - if (INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_STATUS,
> > - &kernel_feature) == 0)
> > - {
> > - if ((kernel_feature & ARCH_SHSTK_SHSTK) != 0)
> > - status = GNU_PROPERTY_X86_FEATURE_1_SHSTK;
> > - }
> > - return status;
> > -}
> > -
> > -# ifndef SHARED
> > -static inline void
> > -x86_setup_tls (void)
> > -{
> > - __libc_setup_tls ();
> > - THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1));
> > -}
> > -
> > -# define ARCH_SETUP_TLS() x86_setup_tls ()
> > -# endif
> > -#endif
> > -
> > -#include <sysdeps/x86/cpu-features.c>
> > diff --git a/sysdeps/unix/sysv/linux/x86/dl-cet.h b/sysdeps/unix/sysv/linux/x86/dl-cet.h
> > index da220ac627..634c885d33 100644
> > --- a/sysdeps/unix/sysv/linux/x86/dl-cet.h
> > +++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h
> > @@ -38,3 +38,26 @@ dl_cet_lock_cet (unsigned int cet_feature)
> > return (int) INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_LOCK,
> > kernel_feature);
> > }
> > +
> > +static inline unsigned int __attribute__ ((always_inline))
>
> You can use use 'static __always_inline unsigned int' here.
Fixed.
> > +dl_cet_get_cet_status (void)
> > +{
> > + unsigned long long kernel_feature;
> > + unsigned int status = 0;
> > + if (INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_STATUS,
> > + &kernel_feature) == 0)
> > + {
> > + if ((kernel_feature & ARCH_SHSTK_SHSTK) != 0)
> > + status = GNU_PROPERTY_X86_FEATURE_1_SHSTK;
> > + }
> > + return status;
> > +}
> > +
> > +/* Enable shadow stack with a macro to avoid shadow stack underflow. */
> > +#define ENABLE_X86_CET(cet_feature) \
> > + if ((cet_feature & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) \
> > + { \
> > + long long int kernel_feature = ARCH_SHSTK_SHSTK; \
> > + INTERNAL_SYSCALL_CALL (arch_prctl, ARCH_SHSTK_ENABLE, \
> > + kernel_feature); \
> > + }
>
> The Linux documentation Documentation/arch/x86/shstk.rst states the
> argument is a 'unsigned long'. I am not use it would matter though.
I have additional kernel and glibc patches to enable shadow stack on x32
which needs unsigned long long to match kernel syscall.
>
> > diff --git a/sysdeps/unix/sysv/linux/x86_64/dl-cet.h b/sysdeps/unix/sysv/linux/x86_64/dl-cet.h
> > new file mode 100644
> > index 0000000000..e23e05c6b8
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/x86_64/dl-cet.h
> > @@ -0,0 +1,47 @@
> > +/* Linux/x86-64 CET initializers function.
> > + Copyright (C) 2023 Free Software Foundation, Inc.
> > +
> > + The GNU C Library is free software; you can redistribute it and/or
> > + modify it under the terms of the GNU Lesser General Public
> > + License as published by the Free Software Foundation; either
> > + version 2.1 of the License, or (at your option) any later version.
> > +
> > + The GNU C Library 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
> > + Lesser General Public License for more details.
> > +
> > + You should have received a copy of the GNU Lesser General Public
> > + License along with the GNU C Library; if not, see
> > + <https://www.gnu.org/licenses/>. */
> > +
> > +#include <cpu-features-offsets.h>
> > +#include_next <dl-cet.h>
> > +
> > +#define X86_STRINGIFY_1(x) #x
> > +#define X86_STRINGIFY(x) X86_STRINGIFY_1 (x)
> > +
> > +/* Enable shadow stack before calling _dl_init if it is enabled in
> > + GL(dl_x86_feature_1). Call _dl_setup_x86_features to setup shadow
> > + stack. */
> > +#define RTLD_START_ENABLE_X86_FEATURES \
> > +"\
> > + # Check if shadow stack is enabled in GL(dl_x86_feature_1).\n\
> > + movl _rtld_local+" X86_STRINGIFY (RTLD_GLOBAL_DL_X86_FEATURE_1_OFFSET) "(%rip), %edx\n\
> > + testl $" X86_STRINGIFY (X86_FEATURE_1_SHSTK) ", %edx\n\
> > + jz 1f\n\
> > + # Enable shadow stack if enabled in GL(dl_x86_feature_1).\n\
> > + movl $" X86_STRINGIFY (ARCH_SHSTK_SHSTK) ", %esi\n\
> > + movl $" X86_STRINGIFY (ARCH_SHSTK_ENABLE) ", %edi\n\
> > + movl $" X86_STRINGIFY (__NR_arch_prctl) ", %eax\n\
> > + syscall\n\
> > +1:\n\
>
> It seems that the syscall might eventually fail if the shadow stack can not be
> allocated (alloc_shstk), although it seems really unlikely to happen on loader
> itself (maybe in a really constraint environment). Should we handle this case?
Enable shadow stack can fail on non-shadow stack kernels or legacy processors.
We may need to enable IBT in the future. Glibc will issue syscalls to
enable CET
features. _dl_cet_setup_features is called to check if CET features are truly
enabled.
> > + # Pass GL(dl_x86_feature_1) to _dl_cet_setup_features.\n\
> > + movl %edx, %edi\n\
> > + # Align stack for the _dl_cet_setup_features call.\n\
> > + andq $-16, %rsp\n\
> > + call _dl_cet_setup_features\n\
> > + # Restore %rax and %rsp from %r12 and %r13.\n\
> > + movq %r12, %rax\n\
> > + movq %r13, %rsp\n\
> > +"
> > diff --git a/sysdeps/x86/cpu-features-offsets.sym b/sysdeps/x86/cpu-features-offsets.sym
> > index 6d03cea8e8..5429f60632 100644
> > --- a/sysdeps/x86/cpu-features-offsets.sym
> > +++ b/sysdeps/x86/cpu-features-offsets.sym
> > @@ -4,3 +4,4 @@
> >
> > RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET offsetof (struct rtld_global_ro, _dl_x86_cpu_features)
> > XSAVE_STATE_SIZE_OFFSET offsetof (struct cpu_features, xsave_state_size)
> > +RTLD_GLOBAL_DL_X86_FEATURE_1_OFFSET offsetof (struct rtld_global, _dl_x86_feature_1)
> > diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
> > index f180f0d9a4..097868c1d9 100644
> > --- a/sysdeps/x86/cpu-features.c
> > +++ b/sysdeps/x86/cpu-features.c
> > @@ -1106,57 +1106,6 @@ no_cpuid:
> > TUNABLE_CALLBACK (set_x86_ibt));
> > TUNABLE_GET (x86_shstk, tunable_val_t *,
> > TUNABLE_CALLBACK (set_x86_shstk));
> > -
> > - /* Check CET status. */
> > - unsigned int cet_status = get_cet_status ();
> > -
> > - if ((cet_status & GNU_PROPERTY_X86_FEATURE_1_IBT) == 0)
> > - CPU_FEATURE_UNSET (cpu_features, IBT)
> > - if ((cet_status & GNU_PROPERTY_X86_FEATURE_1_SHSTK) == 0)
> > - CPU_FEATURE_UNSET (cpu_features, SHSTK)
> > -
> > - if (cet_status)
> > - {
> > - GL(dl_x86_feature_1) = cet_status;
> > -
> > -# ifndef SHARED
> > - /* Check if IBT and SHSTK are enabled by kernel. */
> > - if ((cet_status
> > - & (GNU_PROPERTY_X86_FEATURE_1_IBT
> > - | GNU_PROPERTY_X86_FEATURE_1_SHSTK)))
> > - {
> > - /* Disable IBT and/or SHSTK if they are enabled by kernel, but
> > - disabled by environment variable:
> > -
> > - GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK
> > - */
> > - unsigned int cet_feature = 0;
> > - if (!CPU_FEATURE_USABLE (IBT))
> > - cet_feature |= (cet_status
> > - & GNU_PROPERTY_X86_FEATURE_1_IBT);
> > - if (!CPU_FEATURE_USABLE (SHSTK))
> > - cet_feature |= (cet_status
> > - & GNU_PROPERTY_X86_FEATURE_1_SHSTK);
> > -
> > - if (cet_feature)
> > - {
> > - int res = dl_cet_disable_cet (cet_feature);
> > -
> > - /* Clear the disabled bits in dl_x86_feature_1. */
> > - if (res == 0)
> > - GL(dl_x86_feature_1) &= ~cet_feature;
> > - }
> > -
> > - /* Lock CET if IBT or SHSTK is enabled in executable. Don't
> > - lock CET if IBT or SHSTK is enabled permissively. */
> > - if (GL(dl_x86_feature_control).ibt != cet_permissive
> > - && GL(dl_x86_feature_control).shstk != cet_permissive)
> > - dl_cet_lock_cet (GL(dl_x86_feature_1)
> > - & (GNU_PROPERTY_X86_FEATURE_1_IBT
> > - | GNU_PROPERTY_X86_FEATURE_1_SHSTK));
> > - }
> > -# endif
> > - }
> > #endif
> >
> > #ifndef SHARED
> > diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c
> > index 66a78244d4..25add215f2 100644
> > --- a/sysdeps/x86/dl-cet.c
> > +++ b/sysdeps/x86/dl-cet.c
> > @@ -173,40 +173,11 @@ dl_cet_check_startup (struct link_map *m, struct dl_cet_info *info)
> > = info->enable_feature_1 ^ info->feature_1_enabled;
> > if (disable_feature_1 != 0)
> > {
> > - /* Disable features in the kernel because of legacy objects or
> > - cet_always_off. */
> > - if (dl_cet_disable_cet (disable_feature_1) != 0)
> > - _dl_fatal_printf ("%s: can't disable x86 Features\n",
> > - info->program);
> > -
> > /* Clear the disabled bits. Sync dl_x86_feature_1 and
> > info->feature_1_enabled with info->enable_feature_1. */
> > info->feature_1_enabled = info->enable_feature_1;
> > GL(dl_x86_feature_1) = info->enable_feature_1;
> > }
> > -
> > - if (HAS_CPU_FEATURE (IBT) || HAS_CPU_FEATURE (SHSTK))
> > - {
> > - /* Lock CET features only if IBT or SHSTK are enabled and are not
> > - enabled permissively. */
> > - unsigned int feature_1_lock = 0;
> > -
> > - if (((info->feature_1_enabled & GNU_PROPERTY_X86_FEATURE_1_IBT)
> > - != 0)
> > - && info->enable_ibt_type != cet_permissive)
> > - feature_1_lock |= GNU_PROPERTY_X86_FEATURE_1_IBT;
> > -
> > - if (((info->feature_1_enabled & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
> > - != 0)
> > - && info->enable_shstk_type != cet_permissive)
> > - feature_1_lock |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
> > -
> > - if (feature_1_lock != 0
> > - && dl_cet_lock_cet (feature_1_lock) != 0)
> > - _dl_fatal_printf ("%s: can't lock CET\n", info->program);
> > - }
> > -
> > - THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1));
> > }
> > #endif
> >
> > @@ -298,6 +269,15 @@ dl_cet_check (struct link_map *m, const char *program)
> > {
> > struct dl_cet_info info;
> >
> > + /* CET is enabled only if RTLD_START_ENABLE_X86_FEATURES is defined. */
> > +#if defined SHARED && defined RTLD_START_ENABLE_X86_FEATURES
> > + /* Set dl_x86_feature_1 to features enabled in the executable. */
> > + if (program != NULL)
> > + GL(dl_x86_feature_1) = (m->l_x86_feature_1_and
> > + & (X86_FEATURE_1_IBT
> > + | X86_FEATURE_1_SHSTK));
> > +#endif
> > +
> > /* Check how IBT and SHSTK should be enabled. */
> > info.enable_ibt_type = GL(dl_x86_feature_control).ibt;
> > info.enable_shstk_type = GL(dl_x86_feature_control).shstk;
> > @@ -307,17 +287,9 @@ dl_cet_check (struct link_map *m, const char *program)
> > /* No legacy object check if IBT and SHSTK are always on. */
> > if (info.enable_ibt_type == cet_always_on
> > && info.enable_shstk_type == cet_always_on)
> > - {
> > -#ifdef SHARED
> > - /* Set it only during startup. */
> > - if (program != NULL)
> > - THREAD_SETMEM (THREAD_SELF, header.feature_1,
> > - info.feature_1_enabled);
> > -#endif
> > - return;
> > - }
> > + return;
> >
> > - /* Check if IBT and SHSTK were enabled by kernel. */
> > + /* Check if IBT and SHSTK were enabled. */
> > if (info.feature_1_enabled == 0)
> > return;
> >
> > @@ -351,6 +323,33 @@ _dl_cet_open_check (struct link_map *l)
> > dl_cet_check (l, NULL);
> > }
> >
> > +/* Set GL(dl_x86_feature_1) to the enabled features and clear the
> > + active bits of the disabled features. */
> > +
> > +attribute_hidden
> > +void
>
> I think the code guideline states attribute should in the same line
> as the return type.
Fixed.
> > +_dl_cet_setup_features (unsigned int cet_feature)
> > +{
> > + /* NB: cet_feature == GL(dl_x86_feature_1) which is set to features
> > + enabled from executable, not necessarily supported by kernel. */
> > + if (cet_feature)
>
> No implicit check for integer types.
Fixed.
> > + {
> > + cet_feature = dl_cet_get_cet_status ();
> > + if (cet_feature)
> > + {
> > + THREAD_SETMEM (THREAD_SELF, header.feature_1, cet_feature);
> > +
> > + /* Lock CET if IBT or SHSTK is enabled in executable. Don't
> > + lock CET if IBT or SHSTK is enabled permissively. */
> > + if (GL(dl_x86_feature_control).ibt != cet_permissive
> > + && (GL(dl_x86_feature_control).shstk != cet_permissive))
> > + dl_cet_lock_cet (cet_feature);
> > + }
> > + /* Sync GL(dl_x86_feature_1) with kernel. */
> > + GL(dl_x86_feature_1) = cet_feature;
> > + }
> > +}
> > +
> > #ifdef SHARED
> >
> > # ifndef LINKAGE
> > diff --git a/sysdeps/x86/get-cpuid-feature-leaf.c b/sysdeps/x86/get-cpuid-feature-leaf.c
> > index 40a46cc79c..9317a6b494 100644
> > --- a/sysdeps/x86/get-cpuid-feature-leaf.c
> > +++ b/sysdeps/x86/get-cpuid-feature-leaf.c
> > @@ -24,7 +24,7 @@ __x86_get_cpuid_feature_leaf (unsigned int leaf)
> > static const struct cpuid_feature feature = {};
> > if (leaf < CPUID_INDEX_MAX)
> > return ((const struct cpuid_feature *)
> > - &GLRO(dl_x86_cpu_features).features[leaf]);
> > + &GLRO(dl_x86_cpu_features).features[leaf]);
> > else
> > return &feature;
> > }
> > diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
> > index 2d7427a6c0..23bd8146a2 100644
> > --- a/sysdeps/x86/include/cpu-features.h
> > +++ b/sysdeps/x86/include/cpu-features.h
> > @@ -990,6 +990,9 @@ extern const struct cpu_features *_dl_x86_get_cpu_features (void)
> > # define INIT_ARCH()
> > # define _dl_x86_get_cpu_features() (&GLRO(dl_x86_cpu_features))
> > extern void _dl_x86_init_cpu_features (void) attribute_hidden;
> > +
> > +extern void _dl_cet_setup_features (unsigned int)
> > + attribute_hidden;
> > #endif
> >
> > #ifdef __x86_64__
> > diff --git a/sysdeps/x86/libc-start.h b/sysdeps/x86/libc-start.h
> > index e93da6ef3d..856230daeb 100644
> > --- a/sysdeps/x86/libc-start.h
> > +++ b/sysdeps/x86/libc-start.h
> > @@ -19,7 +19,57 @@
> > #ifndef SHARED
> > # define ARCH_SETUP_IREL() apply_irel ()
> > # define ARCH_APPLY_IREL()
> > -# ifndef ARCH_SETUP_TLS
> > -# define ARCH_SETUP_TLS() __libc_setup_tls ()
> > +# ifdef __CET__
> > +/* Get CET features enabled in the static executable. */
> > +
> > +static inline unsigned int
> > +get_cet_feature (void)
> > +{
> > + /* Check if CET is supported and not disabled by tunables. */
> > + struct cpu_features *cpu_features
> > + = (struct cpu_features *) __get_cpu_features ();
>
> Would be better to add a proper function to return a non-const point
> to the cpu features? Casting like this does seems not a good approach.
Change it to
const struct cpu_features *cpu_features = __get_cpu_features ();
> > + unsigned int cet_feature = 0;
> > + if (CPU_FEATURE_USABLE_P (cpu_features, IBT))
> > + cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT;
> > + if (CPU_FEATURE_USABLE_P (cpu_features, SHSTK))
> > + cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
> > + if (!cet_feature)
> > + return cet_feature;
> > +
> > + struct link_map *main_map = _dl_get_dl_main_map ();
> > +
> > + /* Scan program headers backward to check PT_GNU_PROPERTY early for
> > + x86 feature bits on static executable. */
> > + const ElfW(Phdr) *phdr = GL(dl_phdr);
> > + const ElfW(Phdr) *ph;
> > + for (ph = phdr + GL(dl_phnum); ph != phdr; ph--)
> > + if (ph[-1].p_type == PT_GNU_PROPERTY)
> > + {
> > + _dl_process_pt_gnu_property (main_map, -1, &ph[-1]);
> > + /* Enable IBT and SHSTK only if they are enabled on static
> > + executable. */
> > + cet_feature &= (main_map->l_x86_feature_1_and
> > + & (GNU_PROPERTY_X86_FEATURE_1_IBT
> > + | GNU_PROPERTY_X86_FEATURE_1_SHSTK));
> > + /* Set GL(dl_x86_feature_1) to the enabled CET features. */
> > + GL(dl_x86_feature_1) = cet_feature;
> > + break;
> > + }
> > +
> > + return cet_feature;
> > +}
> > +
> > +/* The function using this macro to enable shadow stack must not return
> > + to avoid shadow stack underflow. */
> > +# define ARCH_SETUP_TLS() \
> > + { \
> > + __libc_setup_tls (); \
> > + \
> > + unsigned int cet_feature = get_cet_feature (); \
> > + ENABLE_X86_CET (cet_feature); \
> > + _dl_cet_setup_features (cet_feature); \
> > + }
> > +# else
> > +# define ARCH_SETUP_TLS() __libc_setup_tls ()
> > # endif
> > #endif /* !SHARED */
> > diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
> > index 581a2f1a9e..faeae723cb 100644
> > --- a/sysdeps/x86_64/dl-machine.h
> > +++ b/sysdeps/x86_64/dl-machine.h
> > @@ -29,6 +29,11 @@
> > #include <dl-static-tls.h>
> > #include <dl-machine-rel.h>
> > #include <isa-level.h>
> > +#ifdef __CET__
> > +# include <dl-cet.h>
> > +#else
> > +# define RTLD_START_ENABLE_X86_FEATURES
> > +#endif
> >
> > /* Return nonzero iff ELF header is compatible with the running host. */
> > static inline int __attribute__ ((unused))
> > @@ -146,13 +151,16 @@ _start:\n\
> > _dl_start_user:\n\
> > # Save the user entry point address in %r12.\n\
> > movq %rax, %r12\n\
> > + # Save %rsp value in %r13.\n\
> > + movq %rsp, %r13\n\
> > +"\
> > + RTLD_START_ENABLE_X86_FEATURES \
> > +"\
> > # Read the original argument count.\n\
> > movq (%rsp), %rdx\n\
> > # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env)\n\
> > # argc -> rsi\n\
> > movq %rdx, %rsi\n\
> > - # Save %rsp value in %r13.\n\
> > - movq %rsp, %r13\n\
> > # And align stack for the _dl_init call. \n\
> > andq $-16, %rsp\n\
> > # _dl_loaded -> rdi\n\
Thanks.
--
H.J.
More information about the Libc-alpha
mailing list