2013-01-18 Hafiz Abid Qadeer<abidh@codesourcery.com>
[deliverable/binutils-gdb.git] / binutils / addr2line.c
CommitLineData
252b5132 1/* addr2line.c -- convert addresses to line number and function name
3f5e193b
NC
2 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3 2007, 2009 Free Software Foundation, Inc.
c8c5888e 4 Contributed by Ulrich Lauther <Ulrich.Lauther@mchp.siemens.de>
252b5132
RH
5
6 This file is part of GNU Binutils.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
32866df7 10 the Free Software Foundation; either version 3, or (at your option)
252b5132
RH
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
32866df7
NC
20 Foundation, 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
22
252b5132 23
c8c5888e 24/* Derived from objdump.c and nm.c by Ulrich.Lauther@mchp.siemens.de
252b5132 25
f462a9ea 26 Usage:
252b5132
RH
27 addr2line [options] addr addr ...
28 or
f462a9ea 29 addr2line [options]
252b5132
RH
30
31 both forms write results to stdout, the second form reads addresses
32 to be converted from stdin. */
33
3db64b00 34#include "sysdep.h"
252b5132
RH
35#include "bfd.h"
36#include "getopt.h"
37#include "libiberty.h"
38#include "demangle.h"
39#include "bucomm.h"
877c169d 40#include "elf-bfd.h"
252b5132 41
0c552dc1 42static bfd_boolean unwind_inlines; /* -i, unwind inlined functions. */
be6f6493 43static bfd_boolean with_addresses; /* -a, show addresses. */
b34976b6
AM
44static bfd_boolean with_functions; /* -f, show function names. */
45static bfd_boolean do_demangle; /* -C, demangle names. */
68cdf72f 46static bfd_boolean pretty_print; /* -p, print on one line. */
b34976b6 47static bfd_boolean base_names; /* -s, strip directory names. */
252b5132
RH
48
49static int naddr; /* Number of addresses to process. */
50static char **addr; /* Hex addresses to process. */
51
52static asymbol **syms; /* Symbol table. */
53
54static struct option long_options[] =
55{
be6f6493 56 {"addresses", no_argument, NULL, 'a'},
252b5132 57 {"basenames", no_argument, NULL, 's'},
28c309a2 58 {"demangle", optional_argument, NULL, 'C'},
252b5132
RH
59 {"exe", required_argument, NULL, 'e'},
60 {"functions", no_argument, NULL, 'f'},
0c552dc1 61 {"inlines", no_argument, NULL, 'i'},
68cdf72f 62 {"pretty-print", no_argument, NULL, 'p'},
c5f8c388 63 {"section", required_argument, NULL, 'j'},
252b5132
RH
64 {"target", required_argument, NULL, 'b'},
65 {"help", no_argument, NULL, 'H'},
66 {"version", no_argument, NULL, 'V'},
67 {0, no_argument, 0, 0}
68};
69
2da42df6
AJ
70static void usage (FILE *, int);
71static void slurp_symtab (bfd *);
72static void find_address_in_section (bfd *, asection *, void *);
c5f8c388
EB
73static void find_offset_in_section (bfd *, asection *);
74static void translate_addresses (bfd *, asection *);
252b5132
RH
75\f
76/* Print a usage message to STREAM and exit with STATUS. */
77
78static void
2da42df6 79usage (FILE *stream, int status)
252b5132 80{
8b53311e
NC
81 fprintf (stream, _("Usage: %s [option(s)] [addr(s)]\n"), program_name);
82 fprintf (stream, _(" Convert addresses into line number/file name pairs.\n"));
83 fprintf (stream, _(" If no addresses are specified on the command line, they will be read from stdin\n"));
84 fprintf (stream, _(" The options are:\n\
07012eee 85 @<file> Read options from <file>\n\
be6f6493 86 -a --addresses Show addresses\n\
8b53311e
NC
87 -b --target=<bfdname> Set the binary file format\n\
88 -e --exe=<executable> Set the input file name (default is a.out)\n\
c5f8c388
EB
89 -i --inlines Unwind inlined functions\n\
90 -j --section=<name> Read section-relative offsets instead of addresses\n\
68cdf72f 91 -p --pretty-print Make the output easier to read for humans\n\
8b53311e
NC
92 -s --basenames Strip directory names\n\
93 -f --functions Show function names\n\
94 -C --demangle[=style] Demangle function names\n\
95 -h --help Display this information\n\
96 -v --version Display the program's version\n\
97\n"));
98
252b5132 99 list_supported_targets (program_name, stream);
92f01d61 100 if (REPORT_BUGS_TO[0] && status == 0)
8ad3436c 101 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
252b5132
RH
102 exit (status);
103}
104\f
105/* Read in the symbol table. */
106
107static void
2da42df6 108slurp_symtab (bfd *abfd)
252b5132 109{
d5e7ea07 110 long storage;
252b5132 111 long symcount;
d5e7ea07 112 bfd_boolean dynamic = FALSE;
252b5132
RH
113
114 if ((bfd_get_file_flags (abfd) & HAS_SYMS) == 0)
115 return;
116
d5e7ea07
AM
117 storage = bfd_get_symtab_upper_bound (abfd);
118 if (storage == 0)
119 {
120 storage = bfd_get_dynamic_symtab_upper_bound (abfd);
121 dynamic = TRUE;
122 }
123 if (storage < 0)
124 bfd_fatal (bfd_get_filename (abfd));
252b5132 125
d5e7ea07
AM
126 syms = (asymbol **) xmalloc (storage);
127 if (dynamic)
128 symcount = bfd_canonicalize_dynamic_symtab (abfd, syms);
129 else
130 symcount = bfd_canonicalize_symtab (abfd, syms);
252b5132
RH
131 if (symcount < 0)
132 bfd_fatal (bfd_get_filename (abfd));
133}
134\f
135/* These global variables are used to pass information between
136 translate_addresses and find_address_in_section. */
137
138static bfd_vma pc;
139static const char *filename;
140static const char *functionname;
141static unsigned int line;
9b8d1a36 142static unsigned int discriminator;
b34976b6 143static bfd_boolean found;
252b5132
RH
144
145/* Look for an address in a section. This is called via
146 bfd_map_over_sections. */
147
148static void
2da42df6
AJ
149find_address_in_section (bfd *abfd, asection *section,
150 void *data ATTRIBUTE_UNUSED)
252b5132
RH
151{
152 bfd_vma vma;
153 bfd_size_type size;
154
155 if (found)
156 return;
157
158 if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
159 return;
160
161 vma = bfd_get_section_vma (abfd, section);
162 if (pc < vma)
163 return;
164
135dfb4a 165 size = bfd_get_section_size (section);
252b5132
RH
166 if (pc >= vma + size)
167 return;
168
9b8d1a36
CC
169 found = bfd_find_nearest_line_discriminator (abfd, section, syms, pc - vma,
170 &filename, &functionname,
171 &line, &discriminator);
252b5132
RH
172}
173
c5f8c388
EB
174/* Look for an offset in a section. This is directly called. */
175
176static void
177find_offset_in_section (bfd *abfd, asection *section)
178{
179 bfd_size_type size;
180
181 if (found)
182 return;
183
184 if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
185 return;
186
187 size = bfd_get_section_size (section);
188 if (pc >= size)
189 return;
190
9b8d1a36
CC
191 found = bfd_find_nearest_line_discriminator (abfd, section, syms, pc,
192 &filename, &functionname,
193 &line, &discriminator);
c5f8c388
EB
194}
195
252b5132
RH
196/* Read hexadecimal addresses from stdin, translate into
197 file_name:line_number and optionally function name. */
198
199static void
c5f8c388 200translate_addresses (bfd *abfd, asection *section)
252b5132
RH
201{
202 int read_stdin = (naddr == 0);
203
204 for (;;)
205 {
206 if (read_stdin)
207 {
208 char addr_hex[100];
209
210 if (fgets (addr_hex, sizeof addr_hex, stdin) == NULL)
211 break;
212 pc = bfd_scan_vma (addr_hex, NULL, 16);
213 }
214 else
215 {
216 if (naddr <= 0)
217 break;
218 --naddr;
219 pc = bfd_scan_vma (*addr++, NULL, 16);
220 }
221
670b0bad
AM
222 if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
223 {
224 const struct elf_backend_data *bed = get_elf_backend_data (abfd);
225 bfd_vma sign = (bfd_vma) 1 << (bed->s->arch_size - 1);
226
227 pc &= (sign << 1) - 1;
228 if (bed->sign_extend_vma)
229 pc = (pc ^ sign) - sign;
230 }
877c169d 231
be6f6493
TG
232 if (with_addresses)
233 {
234 printf ("0x");
235 bfd_printf_vma (abfd, pc);
68cdf72f
TG
236
237 if (pretty_print)
238 printf (": ");
239 else
240 printf ("\n");
be6f6493
TG
241 }
242
b34976b6 243 found = FALSE;
c5f8c388
EB
244 if (section)
245 find_offset_in_section (abfd, section);
246 else
247 bfd_map_over_sections (abfd, find_address_in_section, NULL);
252b5132
RH
248
249 if (! found)
250 {
251 if (with_functions)
252 printf ("??\n");
253 printf ("??:0\n");
254 }
255 else
256 {
68cdf72f
TG
257 while (1)
258 {
259 if (with_functions)
260 {
261 const char *name;
262 char *alloc = NULL;
263
264 name = functionname;
265 if (name == NULL || *name == '\0')
266 name = "??";
267 else if (do_demangle)
268 {
269 alloc = bfd_demangle (abfd, name, DMGL_ANSI | DMGL_PARAMS);
270 if (alloc != NULL)
271 name = alloc;
272 }
273
274 printf ("%s", name);
275 if (pretty_print)
9cf03b7e
NC
276 /* Note for translators: This printf is used to join the
277 function name just printed above to the line number/
278 file name pair that is about to be printed below. Eg:
279
280 foo at 123:bar.c */
68cdf72f
TG
281 printf (_(" at "));
282 else
283 printf ("\n");
284
285 if (alloc != NULL)
286 free (alloc);
287 }
288
289 if (base_names && filename != NULL)
290 {
291 char *h;
292
293 h = strrchr (filename, '/');
294 if (h != NULL)
295 filename = h + 1;
296 }
297
670b0bad
AM
298 printf ("%s:", filename ? filename : "??");
299 if (line != 0)
9b8d1a36
CC
300 {
301 if (discriminator != 0)
302 printf ("%u (discriminator %u)\n", line, discriminator);
303 else
304 printf ("%u\n", line);
305 }
670b0bad
AM
306 else
307 printf ("?\n");
68cdf72f
TG
308 if (!unwind_inlines)
309 found = FALSE;
310 else
9cf03b7e
NC
311 found = bfd_find_inliner_info (abfd, &filename, &functionname,
312 &line);
68cdf72f
TG
313 if (! found)
314 break;
315 if (pretty_print)
9cf03b7e
NC
316 /* Note for translators: This printf is used to join the
317 line number/file name pair that has just been printed with
318 the line number/file name pair that is going to be printed
319 by the next iteration of the while loop. Eg:
320
321 123:bar.c (inlined by) 456:main.c */
68cdf72f
TG
322 printf (_(" (inlined by) "));
323 }
252b5132
RH
324 }
325
326 /* fflush() is essential for using this command as a server
327 child process that reads addresses from a pipe and responds
328 with line number information, processing one address at a
329 time. */
330 fflush (stdout);
331 }
332}
333
d68c385b 334/* Process a file. Returns an exit value for main(). */
252b5132 335
d68c385b 336static int
c5f8c388
EB
337process_file (const char *file_name, const char *section_name,
338 const char *target)
252b5132
RH
339{
340 bfd *abfd;
c5f8c388 341 asection *section;
252b5132
RH
342 char **matching;
343
f24ddbdd 344 if (get_file_size (file_name) < 1)
d68c385b 345 return 1;
f24ddbdd 346
47badb7b 347 abfd = bfd_openr (file_name, target);
252b5132 348 if (abfd == NULL)
47badb7b 349 bfd_fatal (file_name);
252b5132 350
4a114e3e
L
351 /* Decompress sections. */
352 abfd->flags |= BFD_DECOMPRESS;
353
252b5132 354 if (bfd_check_format (abfd, bfd_archive))
c5f8c388 355 fatal (_("%s: cannot get addresses from archive"), file_name);
252b5132
RH
356
357 if (! bfd_check_format_matches (abfd, bfd_object, &matching))
358 {
359 bfd_nonfatal (bfd_get_filename (abfd));
360 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
361 {
362 list_matching_formats (matching);
363 free (matching);
364 }
365 xexit (1);
366 }
367
c5f8c388
EB
368 if (section_name != NULL)
369 {
370 section = bfd_get_section_by_name (abfd, section_name);
371 if (section == NULL)
372 fatal (_("%s: cannot find section %s"), file_name, section_name);
373 }
374 else
375 section = NULL;
376
252b5132
RH
377 slurp_symtab (abfd);
378
c5f8c388 379 translate_addresses (abfd, section);
252b5132
RH
380
381 if (syms != NULL)
382 {
383 free (syms);
384 syms = NULL;
385 }
386
387 bfd_close (abfd);
d68c385b
NC
388
389 return 0;
252b5132
RH
390}
391\f
392int
2da42df6 393main (int argc, char **argv)
252b5132 394{
47badb7b 395 const char *file_name;
c5f8c388 396 const char *section_name;
252b5132
RH
397 char *target;
398 int c;
399
400#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
401 setlocale (LC_MESSAGES, "");
3882b010
L
402#endif
403#if defined (HAVE_SETLOCALE)
404 setlocale (LC_CTYPE, "");
252b5132
RH
405#endif
406 bindtextdomain (PACKAGE, LOCALEDIR);
407 textdomain (PACKAGE);
408
409 program_name = *argv;
410 xmalloc_set_program_name (program_name);
411
869b9d07
MM
412 expandargv (&argc, &argv);
413
252b5132
RH
414 bfd_init ();
415 set_default_bfd_target ();
416
47badb7b 417 file_name = NULL;
c5f8c388 418 section_name = NULL;
252b5132 419 target = NULL;
68cdf72f 420 while ((c = getopt_long (argc, argv, "ab:Ce:sfHhij:pVv", long_options, (int *) 0))
252b5132
RH
421 != EOF)
422 {
423 switch (c)
424 {
425 case 0:
8b53311e 426 break; /* We've been given a long option. */
be6f6493
TG
427 case 'a':
428 with_addresses = TRUE;
429 break;
252b5132
RH
430 case 'b':
431 target = optarg;
432 break;
433 case 'C':
b34976b6 434 do_demangle = TRUE;
28c309a2
NC
435 if (optarg != NULL)
436 {
437 enum demangling_styles style;
f462a9ea 438
28c309a2 439 style = cplus_demangle_name_to_style (optarg);
f462a9ea 440 if (style == unknown_demangling)
28c309a2
NC
441 fatal (_("unknown demangling style `%s'"),
442 optarg);
f462a9ea 443
28c309a2 444 cplus_demangle_set_style (style);
f462a9ea 445 }
252b5132
RH
446 break;
447 case 'e':
47badb7b 448 file_name = optarg;
252b5132
RH
449 break;
450 case 's':
b34976b6 451 base_names = TRUE;
252b5132
RH
452 break;
453 case 'f':
b34976b6 454 with_functions = TRUE;
252b5132 455 break;
68cdf72f
TG
456 case 'p':
457 pretty_print = TRUE;
458 break;
8b53311e 459 case 'v':
252b5132
RH
460 case 'V':
461 print_version ("addr2line");
462 break;
8b53311e 463 case 'h':
252b5132
RH
464 case 'H':
465 usage (stdout, 0);
466 break;
0c552dc1
FF
467 case 'i':
468 unwind_inlines = TRUE;
469 break;
c5f8c388
EB
470 case 'j':
471 section_name = optarg;
472 break;
252b5132
RH
473 default:
474 usage (stderr, 1);
475 break;
476 }
477 }
478
47badb7b
NC
479 if (file_name == NULL)
480 file_name = "a.out";
252b5132
RH
481
482 addr = argv + optind;
483 naddr = argc - optind;
484
d68c385b 485 return process_file (file_name, section_name, target);
252b5132 486}
This page took 0.526474 seconds and 4 git commands to generate.