tensor-0.1.0
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Enumerator Groups Pages
backtrace.cc
1 // -*- mode: c++; fill-column: 80; c-basic-offset: 2; indent-tabs-mode: nil -*-
2 /*
3  Copyright (c) 2010 Juan Jose Garcia Ripoll
4 
5  Tensor is free software; you can redistribute it and/or modify it
6  under the terms of the GNU Library General Public License as published
7  by the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program 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
13  GNU Library General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include <signal.h>
21 #include <cstdlib>
22 #include <cstdio>
23 #include <tensor/config.h>
24 #include <tensor/tools.h>
25 
26 #ifdef HAVE_DLADDR
27 # ifdef HAVE_DLFCN_H
28 # include <dlfcn.h>
29 # endif
30 #endif
31 
32 #if defined(HAVE_BACKTRACE) || defined(HAVE_BACKTRACE_SYMBOLS)
33 # include <execinfo.h>
34 #endif
35 
36 #if !defined(HAVE_BACKTRACE) && defined(HAVE___BUILTIN_RETURN_ADDRESS)
37 #define HAVE_BACKTRACE
38 static int
39 backtrace(void **buffer, int n)
40 {
41  int nframes = (n > 32)? 32 : n;
42  int i;
43  switch (nframes) {
44  case 32: buffer[31] = __builtin_return_address(31);
45  case 31: buffer[30] = __builtin_return_address(30);
46  case 30: buffer[29] = __builtin_return_address(29);
47  case 29: buffer[28] = __builtin_return_address(28);
48  case 28: buffer[27] = __builtin_return_address(27);
49  case 27: buffer[26] = __builtin_return_address(26);
50  case 26: buffer[25] = __builtin_return_address(25);
51  case 25: buffer[24] = __builtin_return_address(24);
52  case 24: buffer[23] = __builtin_return_address(23);
53  case 23: buffer[22] = __builtin_return_address(22);
54  case 22: buffer[21] = __builtin_return_address(21);
55  case 21: buffer[20] = __builtin_return_address(20);
56  case 20: buffer[19] = __builtin_return_address(19);
57  case 19: buffer[18] = __builtin_return_address(18);
58  case 18: buffer[17] = __builtin_return_address(17);
59  case 17: buffer[16] = __builtin_return_address(16);
60  case 16: buffer[15] = __builtin_return_address(15);
61  case 15: buffer[14] = __builtin_return_address(14);
62  case 14: buffer[13] = __builtin_return_address(13);
63  case 13: buffer[12] = __builtin_return_address(12);
64  case 12: buffer[11] = __builtin_return_address(11);
65  case 11: buffer[10] = __builtin_return_address(10);
66  case 10: buffer[9] = __builtin_return_address(9);
67  case 9: buffer[8] = __builtin_return_address(8);
68  case 8: buffer[7] = __builtin_return_address(7);
69  case 7: buffer[6] = __builtin_return_address(6);
70  case 6: buffer[5] = __builtin_return_address(5);
71  case 5: buffer[4] = __builtin_return_address(4);
72  case 4: buffer[3] = __builtin_return_address(3);
73  case 3: buffer[2] = __builtin_return_address(2);
74  case 2: buffer[1] = __builtin_return_address(1);
75  case 1: buffer[0] = __builtin_return_address(0);
76  }
77  return nframes;
78 }
79 #endif
80 
81 #if !defined(HAVE_BACKTRACE_SYMBOLS)
82 # if defined(HAVE_BACKTRACE) && defined(HAVE_DLADDR)
83 # define HAVE_BACKTRACE_SYMBOLS
84 # define BACKTRACE_SYMBOLS_SIMPLE
85 static char **
86 backtrace_symbols(void **buffer, int nframes)
87 {
88  Dl_info data[1];
89  int i;
90  char **strings = malloc(nframes * sizeof(char*));
91  for (i = 0; i < nframes; i++) {
92  if (dladdr(buffer[i], data)) {
93  strings[i] = data->dli_sname;
94  } else {
95  strings[i] = "unknown";
96  }
97  }
98  return strings;
99 }
100 # endif /* HAVE_BACKTRACE && HAVE_DLADDR */
101 #endif /* !HAVE_BACKTRACE_SYMBOLS */
102 
103 static void
104 dump_backtrace(int size)
105 {
106 #ifdef HAVE_BACKTRACE_SYMBOLS
107  {
108  void *pointers[32];
109  int nframes = backtrace(pointers, 32);
110  char **names = backtrace_symbols(pointers, nframes);
111  int i;
112  fprintf(stderr, "\n;;; ECL C Backtrace\n");
113  for (i = 0; i < nframes; i++) {
114 #ifdef BACKTRACE_SYMBOLS_SIMPLE
115  fprintf(stderr, ";;; %4d %s (%p) \n", i, names[i], pointers[i]);
116 #else
117  fprintf(stderr, ";;; %s\n", names[i]);
118 #endif
119  }
120  fflush(stderr);
121  free(names);
122  }
123 #else
124 #warning "No backtrace available"
125 #endif
126 }
127 
128 #undef abort
129 
130 static void
131 tensor_abort(int signal)
132 {
133  dump_backtrace(32);
134  exit(-1);
135 }
136 
137 void
138 tensor::tensor_abort_handler()
139 {
140  signal(SIGABRT, tensor_abort);
141 }