(root)/
glibc-2.38/
stdlib/
tst-makecontext-align.c
       1  /* Check stack alignment provided by makecontext.
       2     Copyright (C) 2018-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <stdint.h>
      20  #include <stdio.h>
      21  #include <stdlib.h>
      22  #include <support/check.h>
      23  #include <support/namespace.h>
      24  #include <support/xunistd.h>
      25  #include <sys/mman.h>
      26  #include <ucontext.h>
      27  
      28  /* Used for error reporting.  */
      29  static const char *context;
      30  
      31  /* Check that ADDRESS is aligned to ALIGNMENT bytes, behind a compiler
      32     barrier.  */
      33  __attribute__ ((noinline, noclone, weak))
      34  void
      35  check_align (void *address, size_t alignment)
      36  {
      37    uintptr_t uaddress = (uintptr_t) address;
      38    if ((uaddress % alignment) != 0)
      39      {
      40        support_record_failure ();
      41        printf ("error: %s: object at address %p is not aligned to %zu bytes\n",
      42                context, address, alignment);
      43      }
      44  }
      45  
      46  /* Various alignment checking functions.  */
      47  
      48  __attribute__ ((noinline, noclone, weak))
      49  void
      50  check_align_int (void)
      51  {
      52    int a;
      53    check_align (&a, __alignof__ (a));
      54  }
      55  
      56  __attribute__ ((noinline, noclone, weak))
      57  void
      58  check_align_long (void)
      59  {
      60    long a;
      61    check_align (&a, __alignof__ (a));
      62  }
      63  
      64  __attribute__ ((noinline, noclone, weak))
      65  void
      66  check_align_long_long (void)
      67  {
      68    long long a;
      69    check_align (&a, __alignof__ (a));
      70  }
      71  
      72  __attribute__ ((noinline, noclone, weak))
      73  void
      74  check_align_double (void)
      75  {
      76    double a;
      77    check_align (&a, __alignof__ (a));
      78  }
      79  
      80  __attribute__ ((noinline, noclone, weak))
      81  void
      82  check_align_4 (void)
      83  {
      84    int a __attribute__ ((aligned (4)));
      85    check_align (&a, 4);
      86  }
      87  
      88  __attribute__ ((noinline, noclone, weak))
      89  void
      90  check_align_8 (void)
      91  {
      92    double a __attribute__ ((aligned (8)));
      93    check_align (&a, 8);
      94  }
      95  
      96  __attribute__ ((noinline, noclone, weak))
      97  void
      98  check_align_16 (void)
      99  {
     100    struct aligned
     101    {
     102      double x0  __attribute__ ((aligned (16)));
     103      double x1;
     104    } a;
     105    check_align (&a, 16);
     106  }
     107  
     108  __attribute__ ((noinline, noclone, weak))
     109  void
     110  check_align_32 (void)
     111  {
     112    struct aligned
     113    {
     114      double x0  __attribute__ ((aligned (32)));
     115      double x1;
     116      double x2;
     117      double x3;
     118    } a;
     119    check_align (&a, 32);
     120  }
     121  
     122  /* Call all the alignment checking functions.  */
     123  __attribute__ ((noinline, noclone, weak))
     124  void
     125  check_alignments (void)
     126  {
     127    check_align_int ();
     128    check_align_long ();
     129    check_align_long_long ();
     130    check_align_double ();
     131    check_align_4 ();
     132    check_align_8 ();
     133    check_align_16 ();
     134    check_align_32 ();
     135  }
     136  
     137  /* Callback functions for makecontext and their invokers (to be used
     138     with support_isolate_in_subprocess).  */
     139  
     140  static ucontext_t ucp;
     141  
     142  static void
     143  callback_0 (void)
     144  {
     145    context = "callback_0";
     146    check_alignments ();
     147    context = "after return from callback_0";
     148  }
     149  
     150  static void
     151  invoke_callback_0 (void *closure)
     152  {
     153    makecontext (&ucp, (void *) callback_0, 0);
     154    if (setcontext (&ucp) != 0)
     155      FAIL_EXIT1 ("setcontext");
     156    FAIL_EXIT1 ("setcontext returned");
     157  }
     158  
     159  static void
     160  callback_1 (int arg1)
     161  {
     162    context = "callback_1";
     163    check_alignments ();
     164    TEST_COMPARE (arg1, 101);
     165    context = "after return from callback_1";
     166  }
     167  
     168  static void
     169  invoke_callback_1 (void *closure)
     170  {
     171    makecontext (&ucp, (void *) callback_1, 1, 101);
     172    if (setcontext (&ucp) != 0)
     173      FAIL_EXIT1 ("setcontext");
     174    FAIL_EXIT1 ("setcontext returned");
     175  }
     176  
     177  static void
     178  callback_2 (int arg1, int arg2)
     179  {
     180    context = "callback_2";
     181    check_alignments ();
     182    TEST_COMPARE (arg1, 201);
     183    TEST_COMPARE (arg2, 202);
     184    context = "after return from callback_2";
     185  }
     186  
     187  static void
     188  invoke_callback_2 (void *closure)
     189  {
     190    makecontext (&ucp, (void *) callback_2, 2, 201, 202);
     191    if (setcontext (&ucp) != 0)
     192      FAIL_EXIT1 ("setcontext");
     193    FAIL_EXIT1 ("setcontext returned");
     194  }
     195  
     196  static void
     197  callback_3 (int arg1, int arg2, int arg3)
     198  {
     199    context = "callback_3";
     200    check_alignments ();
     201    TEST_COMPARE (arg1, 301);
     202    TEST_COMPARE (arg2, 302);
     203    TEST_COMPARE (arg3, 303);
     204    context = "after return from callback_3";
     205  }
     206  
     207  static void
     208  invoke_callback_3 (void *closure)
     209  {
     210    makecontext (&ucp, (void *) callback_3, 3, 301, 302, 303);
     211    if (setcontext (&ucp) != 0)
     212      FAIL_EXIT1 ("setcontext");
     213    FAIL_EXIT1 ("setcontext returned");
     214  }
     215  
     216  static int
     217  do_test (void)
     218  {
     219    context = "direct call";
     220    check_alignments ();
     221  
     222    atexit (check_alignments);
     223  
     224    if (getcontext (&ucp) != 0)
     225      FAIL_UNSUPPORTED ("getcontext");
     226  
     227    ucp.uc_link = NULL;
     228    ucp.uc_stack.ss_size = 512 * 1024;
     229    ucp.uc_stack.ss_sp = xmmap (NULL, ucp.uc_stack.ss_size,
     230                                PROT_READ | PROT_WRITE,
     231                                MAP_PRIVATE | MAP_ANONYMOUS, -1);
     232  
     233    support_isolate_in_subprocess (invoke_callback_0, NULL);
     234    support_isolate_in_subprocess (invoke_callback_1, NULL);
     235    support_isolate_in_subprocess (invoke_callback_2, NULL);
     236    support_isolate_in_subprocess (invoke_callback_3, NULL);
     237  
     238    return 0;
     239  }
     240  
     241  #include <support/test-driver.c>