2 Copyright (C) 2006 EDF - Code Saturne
3 Copyright (C) 2011 - DIGITEO - Sylvestre LEDRU. Adapted for Scilab
4 Copyright (C) 2011 - DIGITEO - Bruno JOFRET. Trace parse algorithm rewrite.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 #include "sci_malloc.h"
30 #if defined(HAVE_GLIBC_BACKTRACE)
35 #if defined(HAVE_GLIBC_BACKTRACE) && defined(__GNUC__)
44 #include "backtrace.h"
46 /*-----------------------------------------------------------------------------
47 * Local type definitions
48 *-----------------------------------------------------------------------------*/
51 * BFT backtrace descriptor
54 struct _sci_backtrace_t
57 int size; /* Total depth of backtrace */
59 char **s_file; /* File names */
60 char **s_func; /* Function names */
61 char **s_addr; /* Addresses */
65 /* Associated typedef documentation (for backtrace.h) */
67 /*============================================================================
68 * Public function definitions
69 *============================================================================*/
72 * Build a backtrace description structure.
74 * @return pointer to sci_backtrace_t backtrace descriptor (NULL in case of
75 * error, or if backtracing is unavailable on this architecture).
78 sci_backtrace_t *sci_backtrace_create(void)
80 #if defined(HAVE_GLIBC_BACKTRACE)
82 sci_backtrace_t *bt = NULL;
84 /* Create backtrace structure */
86 bt = malloc(sizeof(sci_backtrace_t));
92 int tr_size = backtrace(tr_array, 200);
94 Dl_info * infos = NULL;
96 /* Create arrays; we use malloc() here instead of BFT_MALLOC, as a
97 * backtrace is useful mainly in case of severe errors, so we avoid
98 * higher level constructs as much as possible at this stage. */
100 if (tr_size < 2)// || tr_strings == NULL)
108 bt->s_file = malloc(tr_size * sizeof(char *));
109 bt->s_func = malloc(tr_size * sizeof(char *));
110 bt->s_addr = malloc(tr_size * sizeof(char *));
112 /* If allocation has failed, free other allocated arrays, and return NULL */
114 if (bt->s_file == NULL || bt->s_func == NULL || bt->s_addr == NULL)
117 if (bt->s_file != NULL)
121 if (bt->s_func != NULL)
125 if (bt->s_addr != NULL)
135 infos = (Dl_info *)MALLOC(sizeof(Dl_info));
137 for (i = 0; i < bt->size; i++)
140 void * p = tr_array[i];
142 bt->s_file[i] = NULL;
143 bt->s_func[i] = NULL;
144 bt->s_addr[i] = NULL;
146 if (dladdr(p, infos))
148 bt->s_func[i] = infos->dli_sname ? strdup(infos->dli_sname) : strdup(" ");
149 bt->s_file[i] = infos->dli_fname ? strdup(infos->dli_fname) : strdup(" ");
151 // we calculate the relative address in the library
152 snprintf(buffer, 32, "%p", (void*)(p - infos->dli_fbase));
153 bt->s_addr[i] = strdup(buffer);
163 #else /* defined(HAVE_GLIBC_BACKTRACE) */
169 * Free a backtrace description structure.
171 * @param [in, out] bt pointer to backtrace description structure.
172 * @return NULL pointer.
175 sci_backtrace_t *sci_backtrace_destroy(sci_backtrace_t * bt)
182 for (i = 0; i < bt->size; i++)
185 if (bt->s_file[i] != NULL)
189 if (bt->s_func[i] != NULL)
193 if (bt->s_addr[i] != NULL)
200 if (bt->s_file != NULL)
204 if (bt->s_func != NULL)
208 if (bt->s_addr != NULL)
221 * Demangle a backtrace description structure (for C++).
223 * @param [in, out] bt pointer to backtrace description structure.
226 void sci_backtrace_demangle(sci_backtrace_t * bt)
228 #if defined(HAVE_GLIBC_BACKTRACE) && defined(HAVE_CPLUS_DEMANGLE)
233 for (i = 0; i < bt->size; i++)
236 char *s_cplus_func_p = NULL;
237 char *s_cplus_func = NULL;
238 size_t funcnamesize = 0;
241 if (bt->s_func[i] == NULL)
246 s_cplus_func_p = sci_demangle(bt->s_func[i], NULL, &funcnamesize, &status);
248 if (s_cplus_func_p == NULL)
255 free(s_cplus_func_p);
259 l = strlen(s_cplus_func_p);
263 free(s_cplus_func_p);
267 s_cplus_func = malloc(l + 1);
269 if (s_cplus_func != NULL)
271 strncpy(s_cplus_func, s_cplus_func_p, l + 1);
272 s_cplus_func[l] = '\0';
274 bt->s_func[i] = s_cplus_func;
277 free(s_cplus_func_p);
282 #endif /* defined(HAVE_GLIBC_BACKTRACE) && defined(HAVE_CPLUS_DEMANGLE) */
286 * Return the depth of a backtrace.
288 * @param [in] bt pointer to backtrace description structure.
289 * @return backtrace depth.
292 int sci_backtrace_size(const sci_backtrace_t * bt)
298 * Return file name associated with a backtrace at a given depth.
300 * @param [in] bt pointer to backtrace description structure.
301 * @param [in] depth index in backtrace structure (< sci_backtrace_size(bt)).
302 * @return file name at the given depth, or NULL.
305 const char *sci_backtrace_file(sci_backtrace_t * bt, int depth)
307 const char *retval = NULL;
311 if (depth < bt->size)
313 retval = bt->s_file[depth];
321 * Return function name associated with a backtrace at a given depth.
323 * @param [in] bt pointer to backtrace description structure.
324 * @param [in] depth index in backtrace structure (< sci_backtrace_size(bt)).
325 * @return function name at the given depth, or NULL.
328 const char *sci_backtrace_function(sci_backtrace_t * bt, int depth)
330 const char *retval = NULL;
334 if (depth < bt->size)
336 retval = bt->s_func[depth];
344 * Return address associated with a backtrace at a given depth.
346 * @param [in] bt pointer to backtrace description structure.
347 * @param [in] depth index in backtrace structure (< sci_backtrace_size(bt)).
348 * @return address at the given depth, or NULL.
351 const char *sci_backtrace_address(sci_backtrace_t * bt, int depth)
353 const char *retval = NULL;
357 if (depth < bt->size)
359 retval = bt->s_addr[depth];