(root)/
glibc-2.38/
debug/
backtrace.c
       1  /* Return backtrace of current program state.
       2     Copyright (C) 2003-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 <stdlib.h>
      21  #include <unwind.h>
      22  #include <unwind-link.h>
      23  
      24  struct trace_arg
      25  {
      26    void **array;
      27    struct unwind_link *unwind_link;
      28    _Unwind_Word cfa;
      29    int cnt;
      30    int size;
      31  };
      32  
      33  static _Unwind_Reason_Code
      34  backtrace_helper (struct _Unwind_Context *ctx, void *a)
      35  {
      36    struct trace_arg *arg = a;
      37  
      38    /* We are first called with address in the __backtrace function.
      39       Skip it.  */
      40    if (arg->cnt != -1)
      41      {
      42        arg->array[arg->cnt]
      43  	= (void *) UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetIP) (ctx);
      44        if (arg->cnt > 0)
      45  	arg->array[arg->cnt]
      46  	  = unwind_arch_adjustment (arg->array[arg->cnt - 1],
      47  				    arg->array[arg->cnt]);
      48  
      49        /* Check whether we make any progress.  */
      50        _Unwind_Word cfa
      51  	= UNWIND_LINK_PTR (arg->unwind_link, _Unwind_GetCFA) (ctx);
      52  
      53        if (arg->cnt > 0 && arg->array[arg->cnt - 1] == arg->array[arg->cnt]
      54  	 && cfa == arg->cfa)
      55         return _URC_END_OF_STACK;
      56        arg->cfa = cfa;
      57      }
      58    if (++arg->cnt == arg->size)
      59      return _URC_END_OF_STACK;
      60    return _URC_NO_REASON;
      61  }
      62  
      63  int
      64  __backtrace (void **array, int size)
      65  {
      66    struct trace_arg arg =
      67      {
      68       .array = array,
      69       .unwind_link = __libc_unwind_link_get (),
      70       .cfa = 0,
      71       .size = size,
      72       .cnt = -1
      73      };
      74  
      75    if (size <= 0 || arg.unwind_link == NULL)
      76      return 0;
      77  
      78    UNWIND_LINK_PTR (arg.unwind_link, _Unwind_Backtrace)
      79      (backtrace_helper, &arg);
      80  
      81    /* _Unwind_Backtrace seems to put NULL address above
      82       _start.  Fix it up here.  */
      83    if (arg.cnt > 1 && arg.array[arg.cnt - 1] == NULL)
      84      --arg.cnt;
      85    return arg.cnt != -1 ? arg.cnt : 0;
      86  }
      87  weak_alias (__backtrace, backtrace)
      88  libc_hidden_def (__backtrace)