1/**************************************************************************** 2 * * 3 * GNAT RUN-TIME COMPONENTS * 4 * * 5 * T R A C E B A C K - G C C t a b l e s * 6 * * 7 * C Implementation File * 8 * * 9 * Copyright (C) 2004-2012, 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 is an implementation of the __gnat_backtrace routine using the 33 underlying GCC unwinding support associated with the exception handling 34 infrastructure. This will only work for ZCX based applications. */ 35 36#include <unwind.h> 37 38/* The implementation boils down to a call to _Unwind_Backtrace with a 39 tailored callback and carried-on data structure to keep track of the 40 input parameters we got as well as of the basic processing state. */ 41 42/****************** 43 * trace_callback * 44 ******************/ 45 46#if !defined (__USING_SJLJ_EXCEPTIONS__) 47 48typedef struct { 49 void ** traceback; 50 int max_len; 51 void * exclude_min; 52 void * exclude_max; 53 int n_frames_to_skip; 54 int n_frames_skipped; 55 int n_entries_filled; 56} uw_data_t; 57 58#if defined (__ia64__) && defined (__hpux__) 59#include <uwx.h> 60#endif 61 62static _Unwind_Reason_Code 63trace_callback (struct _Unwind_Context * uw_context, uw_data_t * uw_data) 64{ 65 char * pc; 66 67#if defined (__ia64__) && defined (__hpux__) && defined (USE_LIBUNWIND_EXCEPTIONS) 68 /* Work around problem with _Unwind_GetIP on ia64 HP-UX. */ 69 uwx_get_reg ((struct uwx_env *) uw_context, UWX_REG_IP, (uint64_t *) &pc); 70#else 71 pc = (char *) _Unwind_GetIP (uw_context); 72#endif 73 74 if (uw_data->n_frames_skipped < uw_data->n_frames_to_skip) 75 { 76 uw_data->n_frames_skipped ++; 77 return _URC_NO_REASON; 78 } 79 80 if (uw_data->n_entries_filled >= uw_data->max_len) 81 return _URC_NORMAL_STOP; 82 83 if (pc < (char *)uw_data->exclude_min || pc > (char *)uw_data->exclude_max) 84 uw_data->traceback [uw_data->n_entries_filled ++] = pc + PC_ADJUST; 85 86 return _URC_NO_REASON; 87} 88 89#endif 90 91/******************** 92 * __gnat_backtrace * 93 ********************/ 94 95int 96__gnat_backtrace (void ** traceback __attribute__((unused)), 97 int max_len __attribute__((unused)), 98 void * exclude_min __attribute__((unused)), 99 void * exclude_max __attribute__((unused)), 100 int skip_frames __attribute__((unused))) 101{ 102#if defined (__USING_SJLJ_EXCEPTIONS__) 103 /* We have no unwind material (tables) at hand with sjlj eh, and no 104 way to retrieve complete and accurate call chain information from 105 the context stack we maintain. */ 106 return 0; 107#else 108 uw_data_t uw_data; 109 /* State carried over during the whole unwinding process. */ 110 111 uw_data.traceback = traceback; 112 uw_data.max_len = max_len; 113 uw_data.exclude_min = exclude_min; 114 uw_data.exclude_max = exclude_max; 115 116 uw_data.n_frames_to_skip = skip_frames; 117 118 uw_data.n_frames_skipped = 0; 119 uw_data.n_entries_filled = 0; 120 121 _Unwind_Backtrace ((_Unwind_Trace_Fn)trace_callback, &uw_data); 122 123 return uw_data.n_entries_filled; 124#endif 125} 126