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