(root)/
glibc-2.38/
elf/
tst-align2.c
       1  /* Copyright (C) 2005-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <stdbool.h>
      20  #include <stdio.h>
      21  #include <stdlib.h>
      22  #include <sys/wait.h>
      23  #include <tst-stack-align.h>
      24  #include <unistd.h>
      25  
      26  static int res, fds[2], result;
      27  static bool test_destructors;
      28  
      29  extern void in_dso (int *, bool *, int *);
      30  
      31  static void __attribute__ ((constructor)) con (void)
      32  {
      33    res = TEST_STACK_ALIGN () ? -1 : 1;
      34  }
      35  
      36  static void __attribute__ ((destructor)) des (void)
      37  {
      38    if (!test_destructors)
      39      return;
      40  
      41    char c = TEST_STACK_ALIGN () ? 'B' : 'A';
      42    write (fds[1], &c, 1);
      43  }
      44  
      45  static int
      46  do_test (void)
      47  {
      48    if (!res)
      49      {
      50        puts ("binary's constructor has not been run");
      51        result = 1;
      52      }
      53    else if (res != 1)
      54      {
      55        puts ("binary's constructor has been run without sufficient alignment");
      56        result = 1;
      57      }
      58  
      59    if (TEST_STACK_ALIGN ())
      60      {
      61        puts ("insufficient stack alignment in do_test");
      62        result = 1;
      63      }
      64  
      65    in_dso (&result, &test_destructors, &fds[1]);
      66  
      67    if (pipe (fds) < 0)
      68      {
      69        printf ("couldn't create pipe: %m\n");
      70        return 1;
      71      }
      72  
      73    pid_t pid = fork ();
      74    if (pid < 0)
      75      {
      76        printf ("fork failed: %m\n");
      77        return 1;
      78      }
      79  
      80    if (!pid)
      81      {
      82        close (fds[0]);
      83        test_destructors = true;
      84        exit (0);
      85      }
      86  
      87    close (fds[1]);
      88  
      89    unsigned char c;
      90    ssize_t len;
      91    int des_seen = 0, dso_des_seen = 0;
      92    while ((len = TEMP_FAILURE_RETRY (read (fds[0], &c, 1))) > 0)
      93      {
      94        switch (c)
      95          {
      96          case 'B':
      97            puts ("insufficient alignment in binary's destructor");
      98            result = 1;
      99            /* FALLTHROUGH */
     100          case 'A':
     101            des_seen++;
     102            break;
     103          case 'D':
     104            puts ("insufficient alignment in DSO destructor");
     105            result = 1;
     106            /* FALLTHROUGH */
     107          case 'C':
     108            dso_des_seen++;
     109            break;
     110          default:
     111            printf ("unexpected character %x read from pipe", c);
     112            result = 1;
     113            break;
     114          }
     115      }
     116  
     117    close (fds[0]);
     118  
     119    if (des_seen != 1)
     120      {
     121        printf ("binary destructor run %d times instead of once\n", des_seen);
     122        result = 1;
     123      }
     124  
     125    if (dso_des_seen != 1)
     126      {
     127        printf ("DSO destructor run %d times instead of once\n", dso_des_seen);
     128        result = 1;
     129      }
     130  
     131    int status;
     132    pid_t termpid;
     133    termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
     134    if (termpid == -1)
     135      {
     136        printf ("waitpid failed: %m\n");
     137        result = 1;
     138      }
     139    else if (termpid != pid)
     140      {
     141        printf ("waitpid returned %ld != %ld\n",
     142  	      (long int) termpid, (long int) pid);
     143        result = 1;
     144      }
     145    else if (!WIFEXITED (status) || WEXITSTATUS (status))
     146      {
     147        puts ("child hasn't exited with exit status 0");
     148        result = 1;
     149      }
     150  
     151    return result;
     152  }
     153  
     154  #include <support/test-driver.c>