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