diff options
Diffstat (limited to 'elf/tst-align2.c')
-rw-r--r-- | elf/tst-align2.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/elf/tst-align2.c b/elf/tst-align2.c new file mode 100644 index 0000000..4fc0330 --- /dev/null +++ b/elf/tst-align2.c @@ -0,0 +1,157 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2005. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <tst-stack-align.h> +#include <unistd.h> + +static int res, fds[2], result; +static bool test_destructors; + +extern void in_dso (int *, bool *, int *); + +static void __attribute__ ((constructor)) con (void) +{ + res = TEST_STACK_ALIGN () ? -1 : 1; +} + +static void __attribute__ ((destructor)) des (void) +{ + if (!test_destructors) + return; + + char c = TEST_STACK_ALIGN () ? 'B' : 'A'; + write (fds[1], &c, 1); +} + +static int +do_test (void) +{ + if (!res) + { + puts ("binary's constructor has not been run"); + result = 1; + } + else if (res != 1) + { + puts ("binary's constructor has been run without sufficient alignment"); + result = 1; + } + + if (TEST_STACK_ALIGN ()) + { + puts ("insufficient stack alignment in do_test"); + result = 1; + } + + in_dso (&result, &test_destructors, &fds[1]); + + if (pipe (fds) < 0) + { + printf ("couldn't create pipe: %m\n"); + return 1; + } + + pid_t pid = fork (); + if (pid < 0) + { + printf ("fork failed: %m\n"); + return 1; + } + + if (!pid) + { + close (fds[0]); + test_destructors = true; + exit (0); + } + + close (fds[1]); + + unsigned char c; + ssize_t len; + int des_seen = 0, dso_des_seen = 0; + while ((len = TEMP_FAILURE_RETRY (read (fds[0], &c, 1))) > 0) + { + switch (c) + { + case 'B': + puts ("insufficient alignment in binary's destructor"); + result = 1; + /* FALLTHROUGH */ + case 'A': + des_seen++; + break; + case 'D': + puts ("insufficient alignment in DSO destructor"); + result = 1; + /* FALLTHROUGH */ + case 'C': + dso_des_seen++; + break; + default: + printf ("unexpected character %x read from pipe", c); + result = 1; + break; + } + } + + close (fds[0]); + + if (des_seen != 1) + { + printf ("binary destructor run %d times instead of once\n", des_seen); + result = 1; + } + + if (dso_des_seen != 1) + { + printf ("DSO destructor run %d times instead of once\n", dso_des_seen); + result = 1; + } + + int status; + pid_t termpid; + termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); + if (termpid == -1) + { + printf ("waitpid failed: %m\n"); + result = 1; + } + else if (termpid != pid) + { + printf ("waitpid returned %ld != %ld\n", + (long int) termpid, (long int) pid); + result = 1; + } + else if (!WIFEXITED (status) || WEXITSTATUS (status)) + { + puts ("child hasn't exited with exit status 0"); + result = 1; + } + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |