(root)/
gcc-13.2.0/
gcc/
ada/
tracebak.c
       1  /****************************************************************************
       2   *                                                                          *
       3   *                         GNAT RUN-TIME COMPONENTS                         *
       4   *                                                                          *
       5   *                            T R A C E B A C K                             *
       6   *                                                                          *
       7   *                          C Implementation File                           *
       8   *                                                                          *
       9   *            Copyright (C) 2000-2023, Free Software Foundation, Inc.       *
      10   *                                                                          *
      11   * GNAT is free software;  you can  redistribute it  and/or modify it under *
      12   * terms of the  GNU General Public License as published  by the Free Soft- *
      13   * ware  Foundation;  either version 3,  or (at your option) any later ver- *
      14   * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
      15   * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
      16   * or FITNESS FOR A PARTICULAR PURPOSE.                                     *
      17   *                                                                          *
      18   * As a special exception under Section 7 of GPL version 3, you are granted *
      19   * additional permissions described in the GCC Runtime Library Exception,   *
      20   * version 3.1, as published by the Free Software Foundation.               *
      21   *                                                                          *
      22   * You should have received a copy of the GNU General Public License and    *
      23   * a copy of the GCC Runtime Library Exception along with this program;     *
      24   * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    *
      25   * <http://www.gnu.org/licenses/>.                                          *
      26   *                                                                          *
      27   * GNAT was originally developed  by the GNAT team at  New York University. *
      28   * Extensive contributions were provided by Ada Core Technologies Inc.      *
      29   *                                                                          *
      30   ****************************************************************************/
      31  
      32  /* This file contains low level support for stack unwinding using GCC intrinsic
      33     functions.
      34     It has been tested on the following configurations:
      35     PowerPC/AiX
      36     PowerPC/Darwin
      37     PowerPC/VxWorks
      38     PowerPC/LynxOS-178
      39     SPARC/Solaris
      40     i386/GNU/Linux
      41     i386/Solaris
      42     i386/NT
      43     i386/OS2
      44     i386/LynxOS
      45     Alpha/VxWorks
      46     Alpha/VMS
      47  */
      48  
      49  #ifdef __cplusplus
      50  extern "C" {
      51  #endif
      52  
      53  #ifdef IN_RTS
      54  #define POSIX
      55  #include "runtime.h"
      56  #include <stddef.h>
      57  #else
      58  #include "config.h"
      59  #include "system.h"
      60  /* We don't want fancy_abort here.  */
      61  #undef abort
      62  #endif
      63  
      64  extern int __gnat_backtrace (void **, int, void *, void *, int);
      65  
      66  /* The point is to provide an implementation of the __gnat_backtrace function
      67     above, called by the default implementation of the System.Traceback package.
      68  
      69     We first have a series of target specific implementations, each included
      70     from a separate C file for readability purposes.
      71  
      72     Then come two flavors of a generic implementation: one relying on static
      73     assumptions about the frame layout, and the other one using the GCC EH
      74     infrastructure.  The former uses a whole set of macros and structures which
      75     may be tailored on a per target basis, and is activated as soon as
      76     USE_GENERIC_UNWINDER is defined.  The latter uses a small subset of the
      77     macro definitions and is activated when USE_GCC_UNWINDER is defined. It is
      78     only available post GCC 3.3.
      79  
      80     Finally, there is a default dummy implementation, necessary to make the
      81     linker happy on platforms where the feature is not supported, but where the
      82     function is still referenced by the default System.Traceback.  */
      83  
      84  #define Lock_Task system__soft_links__lock_task
      85  extern void (*Lock_Task) (void);
      86  
      87  #define Unlock_Task system__soft_links__unlock_task
      88  extern void (*Unlock_Task) (void);
      89  
      90  /*-------------------------------------*
      91   *-- Target specific implementations --*
      92   *-------------------------------------*/
      93  
      94  #if defined (_WIN64) && defined (__SEH__)
      95  
      96  #define WIN32_LEAN_AND_MEAN
      97  #include <windows.h>
      98  
      99  #define IS_BAD_PTR(ptr) (IsBadCodePtr((FARPROC)ptr))
     100  
     101  int
     102  __gnat_backtrace (void **array,
     103                    int size,
     104                    void *exclude_min,
     105                    void *exclude_max,
     106                    int skip_frames)
     107  {
     108    CONTEXT context;
     109    UNWIND_HISTORY_TABLE history;
     110    int i;
     111  
     112    /* Get the context.  */
     113    RtlCaptureContext (&context);
     114  
     115    /* Setup unwind history table (a cached to speed-up unwinding).  */
     116    memset (&history, 0, sizeof (history));
     117  
     118    i = 0;
     119    while (1)
     120      {
     121        PRUNTIME_FUNCTION RuntimeFunction;
     122        KNONVOLATILE_CONTEXT_POINTERS NvContext;
     123        ULONG64 ImageBase;
     124        VOID *HandlerData;
     125        ULONG64 EstablisherFrame;
     126  
     127        /* Get function metadata.  */
     128        RuntimeFunction = RtlLookupFunctionEntry
     129  	(context.Rip, &ImageBase, &history);
     130  
     131        if (!RuntimeFunction)
     132  	{
     133  	  /* In case of failure, assume this is a leaf function.  */
     134  	  context.Rip = *(ULONG64 *) context.Rsp;
     135  	  context.Rsp += 8;
     136  	}
     137        else
     138  	{
     139  	  /* If the last unwinding step failed somehow, stop here.  */
     140  	  if (IS_BAD_PTR(context.Rip))
     141  	    break;
     142  
     143  	  /* Unwind.  */
     144  	  memset (&NvContext, 0, sizeof (KNONVOLATILE_CONTEXT_POINTERS));
     145  	  RtlVirtualUnwind (0, ImageBase, context.Rip, RuntimeFunction,
     146  			    &context, &HandlerData, &EstablisherFrame,
     147  			    &NvContext);
     148  	}
     149  
     150        /* 0 means bottom of the stack.  */
     151        if (context.Rip == 0)
     152  	break;
     153  
     154        /* Skip frames.  */
     155        if (skip_frames > 1)
     156  	{
     157  	  skip_frames--;
     158  	  continue;
     159  	}
     160        /* Excluded frames.  */
     161        if ((void *)context.Rip >= exclude_min
     162  	  && (void *)context.Rip <= exclude_max)
     163  	continue;
     164  
     165        array[i++] = (void *)(context.Rip - 2);
     166        if (i >= size)
     167  	break;
     168      }
     169    return i;
     170  }
     171  #else
     172  
     173  /* No target specific implementation.  */
     174  
     175  /*----------------------------------------------------------------*
     176   *-- Target specific definitions for the generic implementation --*
     177   *----------------------------------------------------------------*/
     178  
     179  /* The stack layout is specified by the target ABI. The "generic" scheme is
     180     based on the following assumption:
     181  
     182       The stack layout from some frame pointer is such that the information
     183       required to compute the backtrace is available at static offsets.
     184  
     185     For a given frame, the information we are interested in is the saved return
     186     address (somewhere after the call instruction in the caller) and a pointer
     187     to the caller's frame. The former is the base of the call chain information
     188     we store in the tracebacks array. The latter allows us to loop over the
     189     successive frames in the chain.
     190  
     191     To initiate the process, we retrieve an initial frame address using the
     192     appropriate GCC builtin (__builtin_frame_address).
     193  
     194     This scheme is unfortunately not applicable on every target because the
     195     stack layout is not necessarily regular (static) enough. On targets where
     196     this scheme applies, the implementation relies on the following items:
     197  
     198     o struct layout, describing the expected stack data layout relevant to the
     199       information we are interested in,
     200  
     201     o FRAME_OFFSET, the offset, from a given frame address or frame pointer
     202       value, at which this layout will be found,
     203  
     204     o FRAME_LEVEL, controls how many frames up we get at to start with,
     205       from the initial frame pointer we compute by way of the GCC builtin,
     206  
     207       0 is most often the appropriate value. 1 may be necessary on targets
     208       where return addresses are saved by a function in it's caller's frame
     209       (e.g. PPC).
     210  
     211     o PC_ADJUST, to account for the difference between a call point (address
     212       of a call instruction), which is what we want in the output array, and
     213       the associated return address, which is what we retrieve from the stack.
     214  
     215     o STOP_FRAME, to decide whether we reached the top of the call chain, and
     216       thus if the process shall stop.
     217  
     218  	   :
     219  	   :                   stack
     220  	   |             +----------------+
     221  	   |   +-------->|       :        |
     222  	   |   |         | (FRAME_OFFSET) |
     223  	   |   |         |       :        |  (PC_ADJUST)
     224  	   |   |  layout:| return_address ----------------+
     225  	   |   |         |     ....       |               |
     226  	   +---------------  next_frame   |               |
     227  	       |         |     ....       |               |
     228  	       |         |                |               |
     229  	       |         +----------------+               |  +-----+
     230  	       |         |       :        |<- Base fp     |  |  :  |
     231  	       |         | (FRAME_OFFSET) | (FRAME_LEVEL) |  |  :  |
     232  	       |         |       :        |               +--->    | [1]
     233  	       |  layout:| return_address -------------------->    | [0]
     234  	       |         |       ...      |  (PC_ADJUST)     +-----+
     235  	       +----------   next_frame   |                 traceback[]
     236  		         |       ...      |
     237  		         |                |
     238  		         +----------------+
     239  
     240     o BASE_SKIP,
     241  
     242     Since we inherently deal with return addresses, there is an implicit shift
     243     by at least one for the initial point we are able to observe in the chain.
     244  
     245     On some targets (e.g. sparc-solaris), the first return address we can
     246     easily get without special code is even our caller's return address, so
     247     there is a initial shift of two.
     248  
     249     BASE_SKIP represents this initial shift, which is the minimal "skip_frames"
     250     value we support. We could add special code for the skip_frames < BASE_SKIP
     251     cases. This is not done currently because there is virtually no situation
     252     in which this would be useful.
     253  
     254     Finally, to account for some ABI specificities, a target may (but does
     255     not have to) define:
     256  
     257     o FORCE_CALL, to force a call to a dummy function at the very beginning
     258       of the computation. See the PPC AIX target for an example where this
     259       is useful.
     260  
     261     o FETCH_UP_FRAME, to force an invocation of __builtin_frame_address with a
     262       positive argument right after a possibly forced call even if FRAME_LEVEL
     263       is 0. See the SPARC Solaris case for an example where this is useful.
     264  
     265    */
     266  
     267  /*------------------- Darwin 8 (OSX 10.4) or newer ----------------------*/
     268  #if defined (__APPLE__) \
     269      && defined (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) \
     270      && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040
     271  
     272  #define USE_GCC_UNWINDER
     273  
     274  #if defined (__i386__) || defined (__x86_64__)
     275  #define PC_ADJUST -2
     276  #elif defined (__ppc__) || defined (__ppc64__)
     277  #define PC_ADJUST -4
     278  #elif defined (__arm__)
     279  #define PC_ADJUST -2
     280  #elif defined (__arm64__)
     281  #define PC_ADJUST -4
     282  #else
     283  #error Unhandled darwin architecture.
     284  #endif
     285  
     286  /*---------------------------- x86 *BSD --------------------------------*/
     287  
     288  #elif defined (__i386__) &&   \
     289      ( defined (__NetBSD__) || defined (__FreeBSD__) || defined (__OpenBSD__) )
     290  
     291  #define USE_GCC_UNWINDER
     292  /* The generic unwinder is not used for this target because the default
     293     implementation doesn't unwind on the BSD platforms.  AMD64 targets use the
     294     gcc unwinder for all platforms, so let's keep i386 consistent with that.
     295  */
     296  
     297  #define PC_ADJUST -2
     298  /* The minimum size of call instructions on this architecture is 2 bytes */
     299  
     300  /*---------------------- ARM VxWorks ------------------------------------*/
     301  #elif (defined (ARMEL) && defined (__vxworks))
     302  
     303  #include "vxWorks.h"
     304  #include "version.h"
     305  
     306  #define USE_GCC_UNWINDER
     307  #define PC_ADJUST -2
     308  
     309  #if ((_WRS_VXWORKS_MAJOR >= 7) && (_VX_CPU != ARMARCH8A))
     310  #define USING_ARM_UNWINDING 1
     311  #endif
     312  
     313  /*---------------------- ARM Linux ------------------------------------ -*/
     314  #elif (defined (__ARMEL__) && defined (__linux))
     315  
     316  #define USE_GCC_UNWINDER
     317  #define PC_ADJUST -2
     318  #define USING_ARM_UNWINDING 1
     319  
     320  /*---------------------- ARM RTEMS ------------------------------------ -*/
     321  #elif (defined (__arm__) && defined (__rtems__))
     322  
     323  #define USE_GCC_UNWINDER
     324  #define PC_ADJUST -2
     325  #define USING_ARM_UNWINDING 1
     326  
     327  /*---------------------- PPC AIX/PPC Lynx 178/Older Darwin --------------*/
     328  #elif ((defined (_POWER) && defined (_AIX)) || \
     329         (defined (__powerpc__) && defined (__Lynx__) && !defined(__ELF__)) || \
     330         (defined (__ppc__) && defined (__APPLE__)))
     331  
     332  #define USE_GENERIC_UNWINDER
     333  
     334  struct layout
     335  {
     336    struct layout *next;
     337    void *pad;
     338    void *return_address;
     339  };
     340  
     341  #define FRAME_OFFSET(FP) 0
     342  #define PC_ADJUST -4
     343  
     344  /* Eventhough the base PPC ABI states that a toplevel frame entry
     345     should to feature a null backchain, AIX might expose a null return
     346     address instead.  */
     347  
     348  /* Then LynxOS-178 features yet another variation, with return_address
     349     == &<entrypoint>, with two possible entry points (one for the main
     350     process and one for threads). Beware that &bla returns the address
     351     of a descriptor when "bla" is a function.  Getting the code address
     352     requires an extra dereference.  */
     353  
     354  #if defined (__Lynx__)
     355  extern void __start();  /* process entry point.  */
     356  extern void __runnit(); /* thread entry point.  */
     357  #define EXTRA_STOP_CONDITION(CURRENT)                 \
     358    ((CURRENT)->return_address == *(void**)&__start     \
     359     || (CURRENT)->return_address == *(void**)&__runnit)
     360  #else
     361  #define EXTRA_STOP_CONDITION(CURRENT) (0)
     362  #endif
     363  
     364  #define STOP_FRAME(CURRENT, TOP_STACK) \
     365    (((void *) (CURRENT) < (TOP_STACK)) \
     366     || (CURRENT)->return_address == NULL \
     367     || EXTRA_STOP_CONDITION(CURRENT))
     368  
     369  /* The PPC ABI has an interesting specificity: the return address saved by a
     370     function is located in it's caller's frame, and the save operation only
     371     takes place if the function performs a call.
     372  
     373     To have __gnat_backtrace retrieve its own return address, we then
     374     define ... */
     375  
     376  #define FORCE_CALL 1
     377  #define FRAME_LEVEL 1
     378  
     379  #define BASE_SKIP 1
     380  
     381  /*----------- PPC ELF (GNU/Linux & VxWorks & Lynx178e & RTEMS ) ----------*/
     382  
     383  #elif (defined (_ARCH_PPC) && defined (__vxworks)) ||  \
     384    (defined (__powerpc__) && defined (__Lynx__) && defined(__ELF__)) || \
     385    (defined (__linux__) && defined (__powerpc__)) || \
     386    (defined (__powerpc__) && defined (__rtems__))
     387  
     388  #if defined (_ARCH_PPC64) && !defined (__USING_SJLJ_EXCEPTIONS__)
     389  #define USE_GCC_UNWINDER
     390  #else
     391  #define USE_GENERIC_UNWINDER
     392  #endif
     393  
     394  struct layout
     395  {
     396    struct layout *next;
     397    void *return_address;
     398  };
     399  
     400  #define FORCE_CALL 1
     401  #define FRAME_LEVEL 1
     402  /* See the PPC AIX case for an explanation of these values.  */
     403  
     404  #define FRAME_OFFSET(FP) 0
     405  #define PC_ADJUST -4
     406  
     407  /* According to the base PPC ABI, a toplevel frame entry should feature
     408     a null backchain.  What happens at signal handler frontiers isn't so
     409     well specified, so we add a safety guard on top.  */
     410  
     411  #define STOP_FRAME(CURRENT, TOP_STACK) \
     412   ((CURRENT)->next == 0 || ((long)(CURRENT)->next % __alignof__(void*)) != 0)
     413  
     414  #define BASE_SKIP 1
     415  
     416  /*-------------------------- SPARC Solaris or RTEMS --------------------*/
     417  
     418  #elif (defined (__sun__) || defined (__rtems__)) && defined (__sparc__)
     419  
     420  #define USE_GENERIC_UNWINDER
     421  
     422  /* These definitions are inspired from the Appendix D (Software
     423     Considerations) of the SPARC V8 architecture manual.  */
     424  
     425  struct layout
     426  {
     427    struct layout *next;
     428    void *return_address;
     429  };
     430  
     431  #ifdef __arch64__
     432  #define STACK_BIAS 2047 /* V9 ABI */
     433  #else
     434  #define STACK_BIAS 0    /* V8 ABI */
     435  #endif
     436  
     437  #define FRAME_LEVEL 0
     438  #define FRAME_OFFSET(FP) (14 * sizeof (void*) + (FP ? STACK_BIAS : 0))
     439  #define PC_ADJUST 0
     440  #define STOP_FRAME(CURRENT, TOP_STACK) \
     441    ((CURRENT)->return_address == 0|| (CURRENT)->next == 0 \
     442     || (void *) (CURRENT) < (TOP_STACK))
     443  
     444  /* The SPARC register windows need to be flushed before we may access them
     445     from the stack. This is achieved by way of builtin_frame_address only
     446     when the "count" argument is positive, so force at least one such call.  */
     447  #define FETCH_UP_FRAME_ADDRESS
     448  
     449  #define BASE_SKIP 2
     450  /* From the frame pointer of frame N, we are accessing the flushed register
     451     window of frame N-1 (positive offset from fp), in which we retrieve the
     452     saved return address. We then end up with our caller's return address.  */
     453  
     454  /*---------------------------- x86 & x86_64 ---------------------------------*/
     455  
     456  #elif defined (__i386__) || defined (__x86_64__)
     457  
     458  #if defined (__WIN32)
     459  #define WIN32_LEAN_AND_MEAN
     460  #include <windows.h>
     461  #define IS_BAD_PTR(ptr) (IsBadCodePtr((FARPROC)ptr))
     462  #elif defined (__sun__)
     463  #define IS_BAD_PTR(ptr) ((unsigned long)ptr == -1UL)
     464  #else
     465  #define IS_BAD_PTR(ptr) 0
     466  #endif
     467  
     468  /* Use the dwarf2 unwinder when we expect to have dwarf2 tables at
     469     hand. Backtraces will reliably stop on frames missing such tables,
     470     but our only alternative is the generic unwinder which requires
     471     compilation forcing a frame pointer to be reliable.  */
     472  
     473  #if (defined (__x86_64__) || defined (__linux__)) && !defined (__USING_SJLJ_EXCEPTIONS__)
     474  #define USE_GCC_UNWINDER
     475  #else
     476  #define USE_GENERIC_UNWINDER
     477  #endif
     478  
     479  struct layout
     480  {
     481    struct layout *next;
     482    void *return_address;
     483  };
     484  
     485  #define FRAME_LEVEL 1
     486  /* builtin_frame_address (1) is expected to work on this family of targets,
     487     and (0) might return the soft stack pointer, which does not designate a
     488     location where a backchain and a return address might be found.  */
     489  
     490  #define FRAME_OFFSET(FP) 0
     491  #define PC_ADJUST -2
     492  #define STOP_FRAME(CURRENT, TOP_STACK) \
     493    (IS_BAD_PTR((long)(CURRENT)) \
     494     || (void *) (CURRENT) < (TOP_STACK) \
     495     || IS_BAD_PTR((long)(CURRENT)->return_address) \
     496     || (CURRENT)->return_address == 0 \
     497     || (void *) ((CURRENT)->next) < (TOP_STACK)  \
     498     || EXTRA_STOP_CONDITION(CURRENT))
     499  
     500  #define BASE_SKIP (1+FRAME_LEVEL)
     501  
     502  /* On i386 architecture we check that at the call point we really have a call
     503     insn. Possible call instructions are:
     504  
     505     call  addr16        E8 xx xx xx xx
     506     call  reg           FF Dx
     507     call  off(reg)      FF xx xx
     508     lcall addr seg      9A xx xx xx xx xx xx
     509  
     510     This check will not catch all cases but it will increase the backtrace
     511     reliability on this architecture.
     512  */
     513  
     514  #define VALID_STACK_FRAME(ptr) \
     515     (!IS_BAD_PTR(ptr) \
     516      && (((*((ptr) - 3) & 0xff) == 0xe8) \
     517          || ((*((ptr) - 5) & 0xff) == 0x9a) \
     518          || ((*((ptr) - 1) & 0xff) == 0xff) \
     519          || (((*(ptr) & 0xd0ff) == 0xd0ff))))
     520  
     521  #if defined (__vxworks) && defined (__RTP__)
     522  
     523  /* For VxWorks following backchains past the "main" frame gets us into the
     524     kernel space, where it can't be dereferenced. So lets stop at the main
     525     symbol.  */
     526  extern void main();
     527  
     528  static int
     529  is_return_from(void *symbol_addr, void *ret_addr)
     530  {
     531    int ret = 0;
     532    char *ptr = (char *)ret_addr;
     533  
     534    if ((*(ptr - 5) & 0xff) == 0xe8)
     535      {
     536        /* call addr16  E8 xx xx xx xx  */
     537        int32_t offset = *(int32_t *)(ptr - 4);
     538        ret = (ptr + offset) == symbol_addr;
     539      }
     540  
     541    /* Others not implemented yet...  But it is very likely that call addr16
     542       is used here.  */
     543    return ret;
     544  }
     545  
     546  #define EXTRA_STOP_CONDITION(CURRENT) \
     547    (is_return_from(&main, (CURRENT)->return_address))
     548  #else /* not (defined (__vxworks) && defined (__RTP__)) */
     549  #define EXTRA_STOP_CONDITION(CURRENT) (0)
     550  #endif /* not (defined (__vxworks) && defined (__RTP__)) */
     551  
     552  /*----------------------------- qnx ----------------------------------*/
     553  
     554  #elif defined (__QNX__)
     555  
     556  #define USE_GCC_UNWINDER
     557  
     558  #if defined (__aarch64__)
     559  #define PC_ADJUST -4
     560  #elif defined (__ARMEL__)
     561  #define PC_ADJUST -2
     562  #define USING_ARM_UNWINDING 1
     563  #else
     564  #error Unhandled QNX architecture.
     565  #endif
     566  
     567  /*------------------- aarch64-linux or aarch64-rtems -----------------*/
     568  
     569  #elif (defined (__aarch64__) && (defined (__linux__) || defined (__rtems__)))
     570  
     571  #define USE_GCC_UNWINDER
     572  #define PC_ADJUST -4
     573  
     574  /*----------------------------- ia64 ---------------------------------*/
     575  
     576  #elif defined (__ia64__) && (defined (__linux__) || defined (__hpux__))
     577  
     578  #define USE_GCC_UNWINDER
     579  /* Use _Unwind_Backtrace driven exceptions on ia64 HP-UX and ia64
     580     GNU/Linux, where _Unwind_Backtrace is provided by the system unwind
     581     library. On HP-UX 11.23 this requires patch PHSS_33352, which adds
     582     _Unwind_Backtrace to the system unwind library. */
     583  
     584  #define PC_ADJUST -4
     585  
     586  
     587  #endif
     588  
     589  /*---------------------------------------------------------------------*
     590   *--      The post GCC 3.3 infrastructure based implementation       --*
     591   *---------------------------------------------------------------------*/
     592  
     593  #if defined (USE_GCC_UNWINDER) && (__GNUC__ * 10 + __GNUC_MINOR__ > 33)
     594  
     595  /* Conditioning the inclusion on the GCC version is useful to avoid bootstrap
     596     path problems, since the included file refers to post 3.3 functions in
     597     libgcc, and the stage1 compiler is unlikely to be linked against a post 3.3
     598     library.  It actually disables the support for backtraces in this compiler
     599     for targets defining USE_GCC_UNWINDER, which is OK since we don't use the
     600     traceback capability in the compiler anyway.
     601  
     602     The condition is expressed the way above because we cannot reliably rely on
     603     any other macro from the base compiler when compiling stage1.  */
     604  
     605  #ifdef USING_ARM_UNWINDING
     606  /* This value is not part of the enumerated reason codes defined in unwind.h
     607     for ARM style unwinding, but is used in the included "C" code, so we
     608     define it to a reasonable value to avoid a compilation error.  */
     609  #define _URC_NORMAL_STOP 0
     610  #endif
     611  
     612  /* This is an implementation of the __gnat_backtrace routine using the
     613     underlying GCC unwinding support associated with the exception handling
     614     infrastructure.  This will only work for ZCX based applications.  */
     615  
     616  #include <unwind.h>
     617  
     618  /* The implementation boils down to a call to _Unwind_Backtrace with a
     619     tailored callback and carried-on data structure to keep track of the
     620     input parameters we got as well as of the basic processing state.  */
     621  
     622  /******************
     623   * trace_callback *
     624   ******************/
     625  
     626  #if !defined (__USING_SJLJ_EXCEPTIONS__)
     627  
     628  typedef struct {
     629    void ** traceback;
     630    int max_len;
     631    void * exclude_min;
     632    void * exclude_max;
     633    int  n_frames_to_skip;
     634    int  n_frames_skipped;
     635    int  n_entries_filled;
     636  } uw_data_t;
     637  
     638  #if defined (__ia64__) && defined (__hpux__)
     639  #include <uwx.h>
     640  #endif
     641  
     642  static _Unwind_Reason_Code
     643  trace_callback (struct _Unwind_Context * uw_context, uw_data_t * uw_data)
     644  {
     645    char * pc;
     646  
     647  #if defined (__ia64__) && defined (__hpux__) && defined (USE_LIBUNWIND_EXCEPTIONS)
     648    /* Work around problem with _Unwind_GetIP on ia64 HP-UX. */
     649    uwx_get_reg ((struct uwx_env *) uw_context, UWX_REG_IP, (uint64_t *) &pc);
     650  #else
     651    pc = (char *) _Unwind_GetIP (uw_context);
     652  #endif
     653  
     654    if (uw_data->n_frames_skipped < uw_data->n_frames_to_skip)
     655      {
     656        uw_data->n_frames_skipped ++;
     657        return _URC_NO_REASON;
     658      }
     659  
     660    if (uw_data->n_entries_filled >= uw_data->max_len)
     661      return _URC_NORMAL_STOP;
     662  
     663    if (pc < (char *)uw_data->exclude_min || pc > (char *)uw_data->exclude_max)
     664      uw_data->traceback [uw_data->n_entries_filled ++] = pc + PC_ADJUST;
     665  
     666    return _URC_NO_REASON;
     667  }
     668  
     669  #endif
     670  
     671  /********************
     672   * __gnat_backtrace *
     673   ********************/
     674  
     675  int
     676  __gnat_backtrace (void ** traceback __attribute__((unused)),
     677  		  int max_len __attribute__((unused)),
     678  		  void * exclude_min __attribute__((unused)),
     679  		  void * exclude_max __attribute__((unused)),
     680  		  int skip_frames __attribute__((unused)))
     681  {
     682  #if defined (__USING_SJLJ_EXCEPTIONS__)
     683    /* We have no unwind material (tables) at hand with sjlj eh, and no
     684       way to retrieve complete and accurate call chain information from
     685       the context stack we maintain.  */
     686    return 0;
     687  #else
     688    uw_data_t uw_data;
     689    /* State carried over during the whole unwinding process.  */
     690  
     691    uw_data.traceback   = traceback;
     692    uw_data.max_len     = max_len;
     693    uw_data.exclude_min = exclude_min;
     694    uw_data.exclude_max = exclude_max;
     695  
     696    uw_data.n_frames_to_skip = skip_frames;
     697  
     698    uw_data.n_frames_skipped = 0;
     699    uw_data.n_entries_filled = 0;
     700  
     701    _Unwind_Backtrace ((_Unwind_Trace_Fn)trace_callback, &uw_data);
     702  
     703    return uw_data.n_entries_filled;
     704  #endif
     705  }
     706  
     707  /*------------------------------------------------------------------*
     708   *-- The generic implementation based on frame layout assumptions --*
     709   *------------------------------------------------------------------*/
     710  
     711  #elif defined (USE_GENERIC_UNWINDER)
     712  
     713  /* No warning since the cases where FRAME_LEVEL > 0 are known to work.  */
     714  #pragma GCC diagnostic ignored "-Wframe-address"
     715  
     716  #ifndef CURRENT_STACK_FRAME
     717  # define CURRENT_STACK_FRAME  ({ char __csf; &__csf; })
     718  #endif
     719  
     720  #ifndef VALID_STACK_FRAME
     721  #define VALID_STACK_FRAME(ptr) 1
     722  #endif
     723  
     724  #ifndef MAX
     725  #define MAX(x,y) ((x) > (y) ? (x) : (y))
     726  #endif
     727  
     728  #ifndef FORCE_CALL
     729  #define FORCE_CALL 0
     730  #endif
     731  
     732  /* Make sure the function is not inlined.  */
     733  static void forced_callee (void) __attribute__ ((noinline));
     734  
     735  static void forced_callee (void)
     736  {
     737    /* Make sure the function is not pure.  */
     738    volatile int i __attribute__ ((unused)) = 0;
     739  }
     740  
     741  int
     742  __gnat_backtrace (void **array,
     743                    int size,
     744                    void *exclude_min,
     745                    void *exclude_max,
     746                    int skip_frames)
     747  {
     748    struct layout *current;
     749    void *top_frame;
     750    void *top_stack ATTRIBUTE_UNUSED;
     751    int cnt = 0;
     752  
     753    if (FORCE_CALL)
     754      forced_callee ();
     755  
     756    /* Force a call to builtin_frame_address with a positive argument
     757       if required. This is necessary e.g. on SPARC to have the register
     758       windows flushed before we attempt to access them on the stack.  */
     759  #if defined (FETCH_UP_FRAME_ADDRESS) && (FRAME_LEVEL == 0)
     760    __builtin_frame_address (1);
     761  #endif
     762  
     763    top_frame = __builtin_frame_address (FRAME_LEVEL);
     764    top_stack = CURRENT_STACK_FRAME;
     765    current = (struct layout *) ((size_t) top_frame + FRAME_OFFSET (0));
     766  
     767    /* Skip the number of calls we have been requested to skip, accounting for
     768       the BASE_SKIP parameter.
     769  
     770       FRAME_LEVEL is meaningless for the count adjustment. It impacts where we
     771       start retrieving data from, but how many frames "up" we start at is in
     772       BASE_SKIP by definition.  */
     773  
     774    skip_frames = MAX (0, skip_frames - BASE_SKIP);
     775  
     776    while (cnt < skip_frames)
     777      {
     778        current = (struct layout *) ((size_t) current->next + FRAME_OFFSET (1));
     779        cnt++;
     780      }
     781  
     782    cnt = 0;
     783    while (cnt < size)
     784      {
     785        if (STOP_FRAME (current, top_stack) ||
     786  	  !VALID_STACK_FRAME(((char *) current->return_address) + PC_ADJUST))
     787          break;
     788  
     789        if (current->return_address < exclude_min
     790  	  || current->return_address > exclude_max)
     791          array[cnt++] = ((char *) current->return_address) + PC_ADJUST;
     792  
     793        current = (struct layout *) ((size_t) current->next + FRAME_OFFSET (1));
     794      }
     795  
     796    return cnt;
     797  }
     798  
     799  #else
     800  
     801  /* No target specific implementation and neither USE_GCC_UNWINDER nor
     802     USE_GENERIC_UNWINDER defined.  */
     803  
     804  /*------------------------------*
     805   *-- The dummy implementation --*
     806   *------------------------------*/
     807  
     808  int
     809  __gnat_backtrace (void **array ATTRIBUTE_UNUSED,
     810                    int size ATTRIBUTE_UNUSED,
     811                    void *exclude_min ATTRIBUTE_UNUSED,
     812                    void *exclude_max ATTRIBUTE_UNUSED,
     813                    int skip_frames ATTRIBUTE_UNUSED)
     814  {
     815    return 0;
     816  }
     817  
     818  #endif
     819  
     820  #endif
     821  
     822  #ifdef __cplusplus
     823  }
     824  #endif