2.9
[glibc/nacl-glibc.git] / sysdeps / generic / elf / backtracesyms.c
blobb31be6ac5d5bca91bca0eee4be7cdf88a274b622
1 /* Return list with names for address in backtrace.
2 Copyright (C) 1998,1999,2000,2001,2003 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 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 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 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
21 #include <assert.h>
22 #include <execinfo.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
27 #include <ldsodefs.h>
29 #if __ELF_NATIVE_CLASS == 32
30 # define WORD_WIDTH 8
31 #else
32 /* We assyme 64bits. */
33 # define WORD_WIDTH 16
34 #endif
37 char **
38 __backtrace_symbols (array, size)
39 void *const *array;
40 int size;
42 Dl_info info[size];
43 int status[size];
44 int cnt;
45 size_t total = 0;
46 char **result;
48 /* Fill in the information we can get from `dladdr'. */
49 for (cnt = 0; cnt < size; ++cnt)
51 status[cnt] = _dl_addr (array[cnt], &info[cnt], NULL, NULL);
52 if (status[cnt] && info[cnt].dli_fname && info[cnt].dli_fname[0] != '\0')
53 /* We have some info, compute the length of the string which will be
54 "<file-name>(<sym-name>) [+offset]. */
55 total += (strlen (info[cnt].dli_fname ?: "")
56 + (info[cnt].dli_sname
57 ? strlen (info[cnt].dli_sname) + 3 + WORD_WIDTH + 3
58 : 1)
59 + WORD_WIDTH + 5);
60 else
61 total += 5 + WORD_WIDTH;
64 /* Allocate memory for the result. */
65 result = (char **) malloc (size * sizeof (char *) + total);
66 if (result != NULL)
68 char *last = (char *) (result + size);
70 for (cnt = 0; cnt < size; ++cnt)
72 result[cnt] = last;
74 if (status[cnt] && info[cnt].dli_fname
75 && info[cnt].dli_fname[0] != '\0')
77 char buf[20];
79 if (array[cnt] >= (void *) info[cnt].dli_saddr)
80 sprintf (buf, "+%#lx",
81 (unsigned long)(array[cnt] - info[cnt].dli_saddr));
82 else
83 sprintf (buf, "-%#lx",
84 (unsigned long)(info[cnt].dli_saddr - array[cnt]));
86 last += 1 + sprintf (last, "%s%s%s%s%s[%p]",
87 info[cnt].dli_fname ?: "",
88 info[cnt].dli_sname ? "(" : "",
89 info[cnt].dli_sname ?: "",
90 info[cnt].dli_sname ? buf : "",
91 info[cnt].dli_sname ? ") " : " ",
92 array[cnt]);
94 else
95 last += 1 + sprintf (last, "[%p]", array[cnt]);
97 assert (last <= (char *) result + size * sizeof (char *) + total);
100 return result;
102 weak_alias (__backtrace_symbols, backtrace_symbols)