(root)/
glibc-2.38/
debug/
tst-backtrace4.c
       1  /* Test backtrace and backtrace_symbols for signal frames.
       2     Copyright (C) 2011-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 <execinfo.h>
      20  #include <search.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <string.h>
      24  #include <sys/types.h>
      25  #include <signal.h>
      26  #include <unistd.h>
      27  
      28  #include "tst-backtrace.h"
      29  
      30  /* The backtrace should include at least handle_signal, a signal
      31     trampoline, 3 * fn, and do_test.  */
      32  #define NUM_FUNCTIONS 6
      33  
      34  volatile int sig_handled = 0;
      35  
      36  void
      37  handle_signal (int signum)
      38  {
      39    void *addresses[NUM_FUNCTIONS];
      40    char **symbols;
      41    int n;
      42    int i;
      43  
      44    sig_handled = 1;
      45  
      46    /* Get the backtrace addresses.  */
      47    n = backtrace (addresses, sizeof (addresses) / sizeof (addresses[0]));
      48    printf ("Obtained backtrace with %d functions (want at least %d)\n",
      49  	  n, NUM_FUNCTIONS);
      50    /* Check that there are at least NUM_FUNCTIONS functions.  */
      51    if (n < NUM_FUNCTIONS)
      52      {
      53        FAIL ();
      54        /* Only return if we got no symbols at all.  The partial output is
      55  	 still useful for debugging failures.  */
      56        if (n <= 0)
      57  	return;
      58      }
      59    /* Convert them to symbols.  */
      60    symbols = backtrace_symbols (addresses, n);
      61    /* Check that symbols were obtained.  */
      62    if (symbols == NULL)
      63      {
      64        FAIL ();
      65        return;
      66      }
      67    for (i = 0; i < n; ++i)
      68      printf ("Function %d: %s\n", i, symbols[i]);
      69    /* Check that the function names obtained are accurate.  */
      70    if (!match (symbols[0], "handle_signal"))
      71      FAIL ();
      72    /* Do not check name for signal trampoline.  */
      73    for (i = 2; i < n - 1; i++)
      74      if (!match (symbols[i], "fn"))
      75        {
      76  	FAIL ();
      77  	return;
      78        }
      79    /* Symbol names are not available for static functions, so we do not
      80       check do_test.  */
      81  }
      82  
      83  NO_INLINE int
      84  fn (int c)
      85  {
      86    pid_t parent_pid, child_pid;
      87  
      88    if (c > 0)
      89      {
      90        fn (c - 1);
      91        return x;
      92      }
      93  
      94    signal (SIGUSR1, handle_signal);
      95    parent_pid = getpid ();
      96  
      97    child_pid = fork ();
      98    if (child_pid == (pid_t) -1)
      99      abort ();
     100    else if (child_pid == 0)
     101      {
     102        sleep (1);
     103        kill (parent_pid, SIGUSR1);
     104        _exit (0);
     105      }
     106  
     107    /* In the parent.  */
     108    while (sig_handled == 0)
     109      ;
     110  
     111    return 0;
     112  }
     113  
     114  NO_INLINE int
     115  do_test (void)
     116  {
     117    fn (2);
     118    return ret;
     119  }
     120  
     121  #include <support/test-driver.c>