d871e1ebdb2c6e4c41d300458b203f279617d568
[external/binutils.git] / binutils / coffdump.c
1 /* Coff file dumper.
2    Copyright 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007,
3    2011 Free Software Foundation, Inc.
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 of the License, or (at
10    your option) 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21
22
23 /* Written by Steve Chamberlain <sac@cygnus.com>
24
25    This module reads a type tree generated by coffgrok and prints
26    it out so we can test the grokker.  */
27
28 #include "sysdep.h"
29 #include "bfd.h"
30 #include "bfd_stdint.h"
31 #include "libiberty.h"
32 #include "bucomm.h"
33
34 #include "coffgrok.h"
35 #include "getopt.h"
36
37 static int atnl;
38
39 static void tab (int);
40 static void nl (void);
41 static void dump_coff_lines (struct coff_line *);
42 static void dump_coff_type (struct coff_type *);
43 static void dump_coff_where (struct coff_where *);
44 static void dump_coff_visible (struct coff_visible *);
45 static void dump_coff_scope (struct coff_scope *);
46 static void dump_coff_sfile (struct coff_sfile *);
47 static void dump_coff_section (struct coff_section *);
48 static void show_usage (FILE *, int);
49 extern int main (int, char **);
50
51 static void
52 tab (int x)
53 {
54   static int indent;
55   int i;
56
57   if (atnl)
58     {
59       if (x < 0)
60         {
61           printf (")");
62           indent += x;
63
64           return;
65         }
66       else
67         {
68           printf ("\n");
69           atnl = 0;
70         }
71     }
72
73   if (x == -1)
74     {
75       for (i = 0; i < indent; i++)
76         printf ("   ");
77
78       indent += x;
79       printf (")");
80       return;
81     }
82
83   indent += x;
84
85   for (i = 0; i < indent; i++)
86     printf ("   ");
87
88   if (x)
89     {
90       printf ("(");
91     }
92 }
93
94 static void
95 nl (void)
96 {
97   atnl = 1;
98 }
99
100 static void
101 dump_coff_lines (struct coff_line *p)
102 {
103   int i;
104   int online = 0;
105
106   tab (1);
107   printf (_("#lines %d "),p->nlines);
108
109   for (i = 0; i < p->nlines; i++)
110     {
111       printf ("(%d 0x%x)", p->lines[i], p->addresses[i]);
112
113       online++;
114
115       if (online > 6)
116         {
117           nl ();
118           tab (0);
119           online = 0;
120         }
121     }
122   nl ();
123   tab (-1);
124 }
125
126 static void
127 dump_coff_type (struct coff_type *p)
128 {
129   tab (1);
130   printf (_("size %d "), p->size);
131
132   switch (p->type)
133     {
134     case coff_secdef_type:
135       printf (_("section definition at %x size %x\n"),
136               p->u.asecdef.address,
137               p->u.asecdef.size);
138       nl ();
139       break;
140     case coff_pointer_type:
141       printf (_("pointer to"));
142       nl ();
143       dump_coff_type (p->u.pointer.points_to);
144       break;
145     case coff_array_type:
146       printf (_("array [%d] of"), p->u.array.dim);
147       nl ();
148       dump_coff_type (p->u.array.array_of);
149       break;
150     case coff_function_type:
151       printf (_("function returning"));
152       nl ();
153       dump_coff_type (p->u.function.function_returns);
154       dump_coff_lines (p->u.function.lines);
155       printf (_("arguments"));
156       nl ();
157       dump_coff_scope (p->u.function.parameters);
158       tab (0);
159       printf (_("code"));
160       nl ();
161       dump_coff_scope (p->u.function.code);
162       tab(0);
163       break;
164     case coff_structdef_type:
165       printf (_("structure definition"));
166       nl ();
167       dump_coff_scope (p->u.astructdef.elements);
168       break;
169     case coff_structref_type:
170       if (!p->u.aenumref.ref)
171         printf (_("structure ref to UNKNOWN struct"));
172       else
173         printf (_("structure ref to %s"), p->u.aenumref.ref->name);
174       break;
175     case coff_enumref_type:
176       printf (_("enum ref to %s"), p->u.astructref.ref->name);
177       break;
178     case coff_enumdef_type:
179       printf (_("enum definition"));
180       nl ();
181       dump_coff_scope (p->u.aenumdef.elements);
182       break;
183     case coff_basic_type:
184       switch (p->u.basic)
185         {
186         case T_NULL:
187           printf ("NULL");
188           break;
189         case T_VOID:
190           printf ("VOID");
191           break;
192         case T_CHAR:
193           printf ("CHAR");
194           break;
195         case T_SHORT:
196           printf ("SHORT");
197           break;
198         case T_INT:
199           printf ("INT ");
200           break;
201         case T_LONG:
202           printf ("LONG");
203           break;
204         case T_FLOAT:
205           printf ("FLOAT");
206           break;
207         case T_DOUBLE:
208           printf ("DOUBLE");
209           break;
210         case T_STRUCT:
211           printf ("STRUCT");
212           break;
213         case T_UNION:
214           printf ("UNION");
215           break;
216         case T_ENUM:
217           printf ("ENUM");
218           break;
219         case T_MOE:
220           printf ("MOE ");
221           break;
222         case T_UCHAR:
223           printf ("UCHAR");
224           break;
225         case T_USHORT:
226           printf ("USHORT");
227           break;
228         case T_UINT:
229           printf ("UINT");
230           break;
231         case T_ULONG:
232           printf ("ULONG");
233           break;
234         case T_LNGDBL:
235           printf ("LNGDBL");
236           break;
237         default:
238           abort ();
239         }
240     }
241   nl ();
242   tab (-1);
243 }
244
245 static void
246 dump_coff_where (struct coff_where *p)
247 {
248   tab (1);
249   switch (p->where)
250     {
251     case coff_where_stack:
252       printf (_("Stack offset %x"), p->offset);
253       break;
254     case coff_where_memory:
255       printf (_("Memory section %s+%x"), p->section->name, p->offset);
256       break;
257     case coff_where_register:
258       printf (_("Register %d"), p->offset);
259       break;
260     case coff_where_member_of_struct:
261       printf (_("Struct Member offset %x"), p->offset);
262       break;
263     case coff_where_member_of_enum:
264       printf (_("Enum Member offset %x"), p->offset);
265       break;
266     case coff_where_unknown:
267       printf (_("Undefined symbol"));
268       break;
269     case coff_where_strtag:
270       printf ("STRTAG");
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   int i;
422
423   tab (1);
424   printf (_("section %s %d %d address %x size %x number %d nrelocs %d"),
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       tab (0);
432       printf ("(%x %s %x)",
433               ptr->relocs[i].offset,
434               ptr->relocs[i].symbol->name,
435               ptr->relocs[i].addend);
436       nl ();
437     }
438
439   tab (-1);
440 }
441
442 static void
443 coff_dump (struct coff_ofile *ptr)
444 {
445   int i;
446
447   printf ("Coff dump");
448   nl ();
449   printf (_("#sources %d"), ptr->nsources);
450   nl ();
451   dump_coff_sfile (ptr->source_head);
452
453   for (i = 0; i < ptr->nsections; i++)
454     dump_coff_section (ptr->sections + i);
455 }
456
457 char * program_name;
458
459 static void
460 show_usage (FILE *file, int status)
461 {
462   fprintf (file, _("Usage: %s [option(s)] in-file\n"), program_name);
463   fprintf (file, _(" Print a human readable interpretation of a COFF object file\n"));
464   fprintf (file, _(" The options are:\n\
465   @<file>                Read options from <file>\n\
466   -h --help              Display this information\n\
467   -v --version           Display the program's version\n\
468 \n"));
469
470   if (REPORT_BUGS_TO[0] && status == 0)
471     fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
472
473   exit (status);
474 }
475
476 int
477 main (int ac, char **av)
478 {
479   bfd *abfd;
480   struct coff_ofile *tree;
481   char **matching;
482   char *input_file = NULL;
483   int opt;
484   static struct option long_options[] =
485     {
486       { "help", no_argument, 0, 'h' },
487       { "version", no_argument, 0, 'V' },
488       { NULL, no_argument, 0, 0 }
489     };
490
491 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
492   setlocale (LC_MESSAGES, "");
493 #endif
494 #if defined (HAVE_SETLOCALE)
495   setlocale (LC_CTYPE, "");
496 #endif
497   bindtextdomain (PACKAGE, LOCALEDIR);
498   textdomain (PACKAGE);
499
500   program_name = av[0];
501   xmalloc_set_program_name (program_name);
502
503   expandargv (&ac, &av);
504
505   while ((opt = getopt_long (ac, av, "HhVv", long_options,
506                              (int *) NULL))
507          != EOF)
508     {
509       switch (opt)
510         {
511         case 'H':
512         case 'h':
513           show_usage (stdout, 0);
514           break;
515         case 'v':
516         case 'V':
517           print_version ("coffdump");
518           exit (0);
519         case 0:
520           break;
521         default:
522           show_usage (stderr, 1);
523           break;
524         }
525     }
526
527   if (optind < ac)
528     {
529       input_file = av[optind];
530     }
531
532   if (!input_file)
533     fatal (_("no input file specified"));
534
535   abfd = bfd_openr (input_file, 0);
536
537   if (!abfd)
538     bfd_fatal (input_file);
539
540   if (! bfd_check_format_matches (abfd, bfd_object, &matching))
541     {
542       bfd_nonfatal (input_file);
543
544       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
545         {
546           list_matching_formats (matching);
547           free (matching);
548         }
549       exit (1);
550     }
551
552   tree = coff_grok (abfd);
553
554   coff_dump (tree);
555   printf ("\n");
556
557   return 0;
558 }