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