589bb4036244a16c0de14387e12cf82626a4026b
[external/binutils.git] / binutils / coffdump.c
1 /* Coff file dumper.
2    Copyright (C) 1994-2019 Free Software Foundation, Inc.
3
4    This file is part of GNU Binutils.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or (at
9    your option) any later version.
10
11    This program 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
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20
21
22 /* Written by Steve Chamberlain <sac@cygnus.com>
23
24    This module reads a type tree generated by coffgrok and prints
25    it out so we can test the grokker.  */
26
27 #include "sysdep.h"
28 #include "bfd.h"
29 #include "bfd_stdint.h"
30 #include "libiberty.h"
31 #include "bucomm.h"
32
33 #include "coffgrok.h"
34 #include "getopt.h"
35
36 static int atnl;
37
38 static void tab (int);
39 static void nl (void);
40 static void dump_coff_lines (struct coff_line *);
41 static void dump_coff_type (struct coff_type *);
42 static void dump_coff_where (struct coff_where *);
43 static void dump_coff_visible (struct coff_visible *);
44 static void dump_coff_scope (struct coff_scope *);
45 static void dump_coff_sfile (struct coff_sfile *);
46 static void dump_coff_section (struct coff_section *);
47 static void show_usage (FILE *, int);
48 extern int main (int, char **);
49
50 static void
51 tab (int x)
52 {
53   static int indent;
54   int i;
55
56   if (atnl)
57     {
58       if (x < 0)
59         {
60           printf (")");
61           indent += x;
62
63           return;
64         }
65       else
66         {
67           printf ("\n");
68           atnl = 0;
69         }
70     }
71
72   if (x == -1)
73     {
74       for (i = 0; i < indent; i++)
75         printf ("   ");
76
77       indent += x;
78       printf (")");
79       return;
80     }
81
82   indent += x;
83
84   for (i = 0; i < indent; i++)
85     printf ("   ");
86
87   if (x)
88     {
89       printf ("(");
90     }
91 }
92
93 static void
94 nl (void)
95 {
96   atnl = 1;
97 }
98
99 static void
100 dump_coff_lines (struct coff_line *p)
101 {
102   int i;
103   int online = 0;
104
105   tab (1);
106   printf (_("#lines %d "),p->nlines);
107
108   for (i = 0; i < p->nlines; i++)
109     {
110       printf ("(%d 0x%x)", p->lines[i], p->addresses[i]);
111
112       online++;
113
114       if (online > 6)
115         {
116           nl ();
117           tab (0);
118           online = 0;
119         }
120     }
121   nl ();
122   tab (-1);
123 }
124
125 static void
126 dump_coff_type (struct coff_type *p)
127 {
128   tab (1);
129   printf (_("size %d "), p->size);
130
131   switch (p->type)
132     {
133     case coff_secdef_type:
134       printf (_("section definition at %x size %x\n"),
135               p->u.asecdef.address,
136               p->u.asecdef.size);
137       nl ();
138       break;
139     case coff_pointer_type:
140       printf (_("pointer to"));
141       nl ();
142       dump_coff_type (p->u.pointer.points_to);
143       break;
144     case coff_array_type:
145       printf (_("array [%d] of"), p->u.array.dim);
146       nl ();
147       dump_coff_type (p->u.array.array_of);
148       break;
149     case coff_function_type:
150       printf (_("function returning"));
151       nl ();
152       dump_coff_type (p->u.function.function_returns);
153       dump_coff_lines (p->u.function.lines);
154       printf (_("arguments"));
155       nl ();
156       dump_coff_scope (p->u.function.parameters);
157       tab (0);
158       printf (_("code"));
159       nl ();
160       dump_coff_scope (p->u.function.code);
161       tab(0);
162       break;
163     case coff_structdef_type:
164       printf (_("structure definition"));
165       nl ();
166       dump_coff_scope (p->u.astructdef.elements);
167       break;
168     case coff_structref_type:
169       if (!p->u.aenumref.ref)
170         printf (_("structure ref to UNKNOWN struct"));
171       else
172         printf (_("structure ref to %s"), p->u.aenumref.ref->name);
173       break;
174     case coff_enumref_type:
175       printf (_("enum ref to %s"), p->u.astructref.ref->name);
176       break;
177     case coff_enumdef_type:
178       printf (_("enum definition"));
179       nl ();
180       dump_coff_scope (p->u.aenumdef.elements);
181       break;
182     case coff_basic_type:
183       switch (p->u.basic)
184         {
185         case T_NULL:
186           printf ("NULL");
187           break;
188         case T_VOID:
189           printf ("VOID");
190           break;
191         case T_CHAR:
192           printf ("CHAR");
193           break;
194         case T_SHORT:
195           printf ("SHORT");
196           break;
197         case T_INT:
198           printf ("INT ");
199           break;
200         case T_LONG:
201           printf ("LONG");
202           break;
203         case T_FLOAT:
204           printf ("FLOAT");
205           break;
206         case T_DOUBLE:
207           printf ("DOUBLE");
208           break;
209         case T_STRUCT:
210           printf ("STRUCT");
211           break;
212         case T_UNION:
213           printf ("UNION");
214           break;
215         case T_ENUM:
216           printf ("ENUM");
217           break;
218         case T_MOE:
219           printf ("MOE ");
220           break;
221         case T_UCHAR:
222           printf ("UCHAR");
223           break;
224         case T_USHORT:
225           printf ("USHORT");
226           break;
227         case T_UINT:
228           printf ("UINT");
229           break;
230         case T_ULONG:
231           printf ("ULONG");
232           break;
233         case T_LNGDBL:
234           printf ("LNGDBL");
235           break;
236         default:
237           abort ();
238         }
239     }
240   nl ();
241   tab (-1);
242 }
243
244 static void
245 dump_coff_where (struct coff_where *p)
246 {
247   tab (1);
248   switch (p->where)
249     {
250     case coff_where_stack:
251       printf (_("Stack offset %x"), p->offset);
252       break;
253     case coff_where_memory:
254       printf (_("Memory section %s+%x"), p->section->name, p->offset);
255       break;
256     case coff_where_register:
257       printf (_("Register %d"), p->offset);
258       break;
259     case coff_where_member_of_struct:
260       printf (_("Struct Member offset %x"), p->offset);
261       break;
262     case coff_where_member_of_enum:
263       printf (_("Enum Member offset %x"), p->offset);
264       break;
265     case coff_where_unknown:
266       printf (_("Undefined symbol"));
267       break;
268     case coff_where_strtag:
269       printf ("STRTAG");
270       break;
271     case coff_where_entag:
272       printf ("ENTAG");
273       break;
274     case coff_where_typedef:
275       printf ("TYPEDEF");
276       break;
277     default:
278       abort ();
279     }
280   nl ();
281   tab (-1);
282 }
283
284 static void
285 dump_coff_visible (struct coff_visible *p)
286 {
287   tab (1);
288   switch (p->type)
289     {
290     case coff_vis_ext_def:
291       printf ("coff_vis_ext_def");
292       break;
293     case coff_vis_ext_ref:
294       printf ("coff_vis_ext_ref");
295       break;
296     case coff_vis_int_def:
297       printf ("coff_vis_int_def");
298       break;
299     case coff_vis_common:
300       printf ("coff_vis_common");
301       break;
302     case coff_vis_auto:
303       printf ("coff_vis_auto");
304       break;
305     case coff_vis_autoparam:
306       printf ("coff_vis_autoparam");
307       break;
308     case coff_vis_regparam:
309       printf ("coff_vis_regparam");
310       break;
311     case coff_vis_register:
312       printf ("coff_vis_register");
313       break;
314     case coff_vis_tag:
315       printf ("coff_vis_tag");
316       break;
317     case coff_vis_member_of_struct:
318       printf ("coff_vis_member_of_struct");
319       break;
320     case coff_vis_member_of_enum:
321       printf ("coff_vis_member_of_enum");
322       break;
323     default:
324       abort ();
325     }
326   nl ();
327   tab (-1);
328 }
329
330 static void
331 dump_coff_symbol (struct coff_symbol *p)
332 {
333   tab (1);
334   printf (_("List of symbols"));
335   nl ();
336
337   while (p)
338     {
339       tab (1);
340       tab (1);
341       printf (_("Symbol  %s, tag %d, number %d"), p->name, p->tag, p->number);
342       nl ();
343       tab (-1);
344       tab (1);
345       printf (_("Type"));
346       nl ();
347       dump_coff_type (p->type);
348       tab (-1);
349       tab (1);
350       printf (_("Where"));
351       dump_coff_where (p->where);
352       tab (-1);
353       tab (1);
354       printf (_("Visible"));
355       dump_coff_visible (p->visible);
356       tab (-1);
357       p = p->next;
358       tab (-1);
359     }
360   tab (-1);
361 }
362
363 static void
364 dump_coff_scope (struct coff_scope *p)
365 {
366   if (p)
367     {
368       tab (1);
369       printf ("%s %" BFD_VMA_FMT "x ",
370               _("List of blocks "), (bfd_vma) (uintptr_t) p);
371
372       if (p->sec)
373         printf( "  %s %x..%x",  p->sec->name,p->offset, p->offset + p->size -1);
374
375       nl ();
376       tab (0);
377       printf ("*****************");
378       nl ();
379
380       while (p)
381         {
382           tab (0);
383           printf (_("vars %d"), p->nvars);
384           nl ();
385           dump_coff_symbol (p->vars_head);
386           printf (_("blocks"));
387           nl ();
388           dump_coff_scope (p->list_head);
389           nl ();
390           p = p->next;
391         }
392
393       tab (0);
394       printf ("*****************");
395       nl ();
396       tab (-1);
397     }
398 }
399
400 static void
401 dump_coff_sfile (struct coff_sfile *p)
402 {
403   tab (1);
404   printf (_("List of source files"));
405   nl ();
406
407   while (p)
408     {
409       tab (0);
410       printf (_("Source file %s"), p->name);
411       nl ();
412       dump_coff_scope (p->scope);
413       p = p->next;
414     }
415   tab (-1);
416 }
417
418 static void
419 dump_coff_section (struct coff_section *ptr)
420 {
421   unsigned int i;
422
423   tab (1);
424   printf (_("section %s %d %d address %x size %x number %d nrelocs %u"),
425           ptr->name, ptr->code, ptr->data, ptr->address,ptr->size,
426           ptr->number, ptr->nrelocs);
427   nl ();
428
429   for (i = 0; i < ptr->nrelocs; i++)
430     {
431       struct coff_reloc * r = ptr->relocs + i;
432       tab (0);
433       printf ("(%x %s %x)",
434               r->offset,
435               /* PR 17512: file: 0a38fb7c.  */
436               r->symbol == NULL ? _("<no sym>") : r->symbol->name,
437               r->addend);
438       nl ();
439     }
440
441   tab (-1);
442 }
443
444 static void
445 coff_dump (struct coff_ofile *ptr)
446 {
447   int i;
448
449   printf ("Coff dump");
450   nl ();
451   printf (_("#sources %d"), ptr->nsources);
452   nl ();
453   dump_coff_sfile (ptr->source_head);
454
455   for (i = 0; i < ptr->nsections; i++)
456     dump_coff_section (ptr->sections + i);
457 }
458
459 char * program_name;
460
461 static void
462 show_usage (FILE *file, int status)
463 {
464   fprintf (file, _("Usage: %s [option(s)] in-file\n"), program_name);
465   fprintf (file, _(" Print a human readable interpretation of a COFF object file\n"));
466   fprintf (file, _(" The options are:\n\
467   @<file>                Read options from <file>\n\
468   -h --help              Display this information\n\
469   -v --version           Display the program's version\n\
470 \n"));
471
472   if (REPORT_BUGS_TO[0] && status == 0)
473     fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
474
475   exit (status);
476 }
477
478 int
479 main (int ac, char **av)
480 {
481   bfd *abfd;
482   struct coff_ofile *tree;
483   char **matching;
484   char *input_file = NULL;
485   int opt;
486   static struct option long_options[] =
487     {
488       { "help", no_argument, 0, 'h' },
489       { "version", no_argument, 0, 'V' },
490       { NULL, no_argument, 0, 0 }
491     };
492
493 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
494   setlocale (LC_MESSAGES, "");
495 #endif
496 #if defined (HAVE_SETLOCALE)
497   setlocale (LC_CTYPE, "");
498 #endif
499   bindtextdomain (PACKAGE, LOCALEDIR);
500   textdomain (PACKAGE);
501
502   program_name = av[0];
503   xmalloc_set_program_name (program_name);
504   bfd_set_error_program_name (program_name);
505
506   expandargv (&ac, &av);
507
508   while ((opt = getopt_long (ac, av, "HhVv", long_options,
509                              (int *) NULL))
510          != EOF)
511     {
512       switch (opt)
513         {
514         case 'H':
515         case 'h':
516           show_usage (stdout, 0);
517           break;
518         case 'v':
519         case 'V':
520           print_version ("coffdump");
521           exit (0);
522         case 0:
523           break;
524         default:
525           show_usage (stderr, 1);
526           break;
527         }
528     }
529
530   if (optind < ac)
531     {
532       input_file = av[optind];
533     }
534
535   if (!input_file)
536     fatal (_("no input file specified"));
537
538   abfd = bfd_openr (input_file, 0);
539
540   if (!abfd)
541     bfd_fatal (input_file);
542
543   if (! bfd_check_format_matches (abfd, bfd_object, &matching))
544     {
545       bfd_nonfatal (input_file);
546
547       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
548         {
549           list_matching_formats (matching);
550           free (matching);
551         }
552       exit (1);
553     }
554
555   tree = coff_grok (abfd);
556   if (tree)
557     {
558       coff_dump (tree);
559       printf ("\n");
560     }
561
562   return 0;
563 }