Update.
[glibc.git] / sysdeps / generic / elf / backtracesyms.c
blob100d94aa42934191ad5e4b401f84ac90381c2396
1 /* Return list with names for address in backtrace.
2 Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C 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 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include <execinfo.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
26 #include <elf/ldsodefs.h>
28 #if __ELF_NATIVE_CLASS == 32
29 # define WORD_WIDTH 8
30 #else
31 /* We assyme 64bits. */
32 # define WORD_WIDTH 16
33 #endif
36 char **
37 __backtrace_symbols (array, size)
38 void *const *array;
39 int size;
41 Dl_info info[size];
42 int status[size];
43 int cnt;
44 size_t total = 0;
45 char **result;
47 /* Fill in the information we can get from `dladdr'. */
48 for (cnt = 0; cnt < size; ++cnt)
50 status[cnt] = _dl_addr (array[cnt], &info[cnt]);
51 if (status[cnt] && info[cnt].dli_fname && info[cnt].dli_fname[0] != '\0')
52 /* We have some info, compute the length of the string which will be
53 "<fct-name>(<sym-name>)[+offset]. */
54 total += (strlen (info[cnt].dli_fname ?: "")
55 + (info[cnt].dli_sname
56 ? strlen (info[cnt].dli_sname) + 3 + WORD_WIDTH + 3
57 : 1)
58 + WORD_WIDTH + 5);
59 else
60 total += 5 + WORD_WIDTH;
63 /* Allocate memory for the result. */
64 result = malloc (size * sizeof (char *) + total);
65 if (result != NULL)
67 char *last = (char *) (result + size);
69 for (cnt = 0; cnt < size; ++cnt)
71 result[cnt] = last;
73 if (status[cnt] && info[cnt].dli_fname
74 && info[cnt].dli_fname[0] != '\0')
76 char buf[20];
78 if (array[cnt] >= (void *) info[cnt].dli_saddr)
79 sprintf (buf, "+%#lx",
80 (unsigned long)(array[cnt] - info[cnt].dli_saddr));
81 else
82 sprintf (buf, "-%#lx",
83 (unsigned long)(info[cnt].dli_saddr - array[cnt]));
85 last += 1 + sprintf (last, "%s%s%s%s%s[%p]",
86 info[cnt].dli_fname ?: "",
87 info[cnt].dli_sname ? "(" : "",
88 info[cnt].dli_sname ?: "",
89 info[cnt].dli_sname ? buf : "",
90 info[cnt].dli_sname ? ") " : " ",
91 array[cnt]);
93 else
94 last += 1 + sprintf (last, "[%p]", array[cnt]);
98 return result;
100 weak_alias (__backtrace_symbols, backtrace_symbols)