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