133965Sjdp/* Coff file dumper.
2218822Sdim   Copyright 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
389857Sobrien   Free Software Foundation, Inc.
433965Sjdp
589857Sobrien   This file is part of GNU Binutils.
633965Sjdp
789857Sobrien   This program is free software; you can redistribute it and/or modify
889857Sobrien   it under the terms of the GNU General Public License as published by
989857Sobrien   the Free Software Foundation; either version 2 of the License, or (at
1089857Sobrien   your option) any later version.
1133965Sjdp
1289857Sobrien   This program is distributed in the hope that it will be useful,
1389857Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1489857Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1589857Sobrien   GNU General Public License for more details.
1633965Sjdp
1789857Sobrien   You should have received a copy of the GNU General Public License
1889857Sobrien   along with this program; if not, write to the Free Software
19218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2033965Sjdp
2133965Sjdp/* Written by Steve Chamberlain <sac@cygnus.com>
2233965Sjdp
2333965Sjdp   This module reads a type tree generated by coffgrok and prints
2489857Sobrien   it out so we can test the grokker.  */
2533965Sjdp
26218822Sdim#include "sysdep.h"
27104834Sobrien#include "bfd.h"
28104834Sobrien#include "libiberty.h"
29218822Sdim#include "bucomm.h"
3033965Sjdp
3133965Sjdp#include "coffgrok.h"
3291041Sobrien#include "getopt.h"
3333965Sjdp
3433965Sjdpstatic int atnl;
3533965Sjdp
36130561Sobrienstatic void tab (int);
37130561Sobrienstatic void nl (void);
38130561Sobrienstatic void dump_coff_lines (struct coff_line *);
39130561Sobrienstatic void dump_coff_type (struct coff_type *);
40130561Sobrienstatic void dump_coff_where (struct coff_where *);
41130561Sobrienstatic void dump_coff_visible (struct coff_visible *);
42130561Sobrienstatic void dump_coff_scope (struct coff_scope *);
43130561Sobrienstatic void dump_coff_sfile (struct coff_sfile *);
44130561Sobrienstatic void dump_coff_section (struct coff_section *);
45130561Sobrienstatic void show_usage (FILE *, int);
46130561Sobrienextern int main (int, char **);
4789857Sobrien
4833965Sjdpstatic void
49130561Sobrientab (int x)
5033965Sjdp{
5133965Sjdp  static int indent;
5233965Sjdp  int i;
5333965Sjdp
5433965Sjdp  if (atnl)
5533965Sjdp    {
5633965Sjdp      if (x < 0)
5733965Sjdp	{
5833965Sjdp	  printf (")");
5933965Sjdp	  indent += x;
6033965Sjdp
6133965Sjdp	  return;
6233965Sjdp	}
6333965Sjdp      else
6433965Sjdp	{
6533965Sjdp	  printf ("\n");
6633965Sjdp	  atnl = 0;
6733965Sjdp	}
6833965Sjdp    }
6933965Sjdp
7033965Sjdp  if (x == -1)
7133965Sjdp    {
7233965Sjdp      for (i = 0; i < indent; i++)
7333965Sjdp	printf ("   ");
7433965Sjdp
7533965Sjdp      indent += x;
7633965Sjdp      printf (")");
7733965Sjdp      return;
7833965Sjdp    }
7933965Sjdp
8033965Sjdp  indent += x;
8133965Sjdp
8233965Sjdp  for (i = 0; i < indent; i++)
8333965Sjdp    printf ("   ");
8433965Sjdp
8533965Sjdp  if (x)
8633965Sjdp    {
8733965Sjdp      printf ("(");
8833965Sjdp    }
8933965Sjdp}
9033965Sjdp
9189857Sobrienstatic void
92130561Sobriennl (void)
9333965Sjdp{
9433965Sjdp  atnl = 1;
9533965Sjdp}
9633965Sjdp
9733965Sjdpstatic void
98130561Sobriendump_coff_lines (struct coff_line *p)
9933965Sjdp{
10033965Sjdp  int i;
10133965Sjdp  int online = 0;
10289857Sobrien
10389857Sobrien  tab (1);
10489857Sobrien  printf (_("#lines %d "),p->nlines);
10589857Sobrien
106104834Sobrien  for (i = 0; i < p->nlines; i++)
10733965Sjdp    {
10889857Sobrien      printf ("(%d 0x%x)", p->lines[i], p->addresses[i]);
10989857Sobrien
11033965Sjdp      online++;
11189857Sobrien
11233965Sjdp      if (online > 6)
11333965Sjdp	{
11489857Sobrien	  nl ();
11589857Sobrien	  tab (0);
11633965Sjdp	  online = 0;
11733965Sjdp	}
11833965Sjdp    }
11989857Sobrien  nl ();
12089857Sobrien  tab (-1);
12133965Sjdp}
12233965Sjdp
12333965Sjdpstatic void
124130561Sobriendump_coff_type (struct coff_type *p)
12533965Sjdp{
12633965Sjdp  tab (1);
12733965Sjdp  printf ("size %d ", p->size);
12889857Sobrien
12933965Sjdp  switch (p->type)
13033965Sjdp    {
13133965Sjdp    case coff_secdef_type:
132104834Sobrien      printf ("section definition at %x size %x\n",
13333965Sjdp	      p->u.asecdef.address,
13433965Sjdp	      p->u.asecdef.size);
13589857Sobrien      nl ();
13633965Sjdp      break;
13733965Sjdp    case coff_pointer_type:
13833965Sjdp      printf ("pointer to");
13933965Sjdp      nl ();
14033965Sjdp      dump_coff_type (p->u.pointer.points_to);
14133965Sjdp      break;
14233965Sjdp    case coff_array_type:
14333965Sjdp      printf ("array [%d] of", p->u.array.dim);
14433965Sjdp      nl ();
14533965Sjdp      dump_coff_type (p->u.array.array_of);
14633965Sjdp      break;
14733965Sjdp    case coff_function_type:
14833965Sjdp      printf ("function returning");
14933965Sjdp      nl ();
15033965Sjdp      dump_coff_type (p->u.function.function_returns);
15133965Sjdp      dump_coff_lines (p->u.function.lines);
15233965Sjdp      printf ("arguments");
15333965Sjdp      nl ();
15433965Sjdp      dump_coff_scope (p->u.function.parameters);
15533965Sjdp      tab (0);
15633965Sjdp      printf ("code");
15733965Sjdp      nl ();
15833965Sjdp      dump_coff_scope (p->u.function.code);
15933965Sjdp      tab(0);
16033965Sjdp      break;
16133965Sjdp    case coff_structdef_type:
16233965Sjdp      printf ("structure definition");
16333965Sjdp      nl ();
16433965Sjdp      dump_coff_scope (p->u.astructdef.elements);
16533965Sjdp      break;
16633965Sjdp    case coff_structref_type:
16733965Sjdp      if (!p->u.aenumref.ref)
16833965Sjdp	printf ("structure ref to UNKNOWN struct");
16933965Sjdp      else
17033965Sjdp	printf ("structure ref to %s", p->u.aenumref.ref->name);
17133965Sjdp      break;
17233965Sjdp    case coff_enumref_type:
17333965Sjdp      printf ("enum ref to %s", p->u.astructref.ref->name);
17433965Sjdp      break;
17533965Sjdp    case coff_enumdef_type:
17633965Sjdp      printf ("enum definition");
17733965Sjdp      nl ();
17833965Sjdp      dump_coff_scope (p->u.aenumdef.elements);
17933965Sjdp      break;
18033965Sjdp    case coff_basic_type:
18133965Sjdp      switch (p->u.basic)
18233965Sjdp	{
18333965Sjdp	case T_NULL:
18433965Sjdp	  printf ("NULL");
18533965Sjdp	  break;
18633965Sjdp	case T_VOID:
18733965Sjdp	  printf ("VOID");
18833965Sjdp	  break;
18933965Sjdp	case T_CHAR:
19033965Sjdp	  printf ("CHAR");
19133965Sjdp	  break;
19233965Sjdp	case T_SHORT:
19333965Sjdp	  printf ("SHORT");
19433965Sjdp	  break;
19533965Sjdp	case T_INT:
19633965Sjdp	  printf ("INT ");
19733965Sjdp	  break;
19833965Sjdp	case T_LONG:
19933965Sjdp	  printf ("LONG");
20033965Sjdp	  break;
20133965Sjdp	case T_FLOAT:
20233965Sjdp	  printf ("FLOAT");
20333965Sjdp	  break;
20433965Sjdp	case T_DOUBLE:
20533965Sjdp	  printf ("DOUBLE");
20633965Sjdp	  break;
20733965Sjdp	case T_STRUCT:
20833965Sjdp	  printf ("STRUCT");
20933965Sjdp	  break;
21033965Sjdp	case T_UNION:
21133965Sjdp	  printf ("UNION");
21233965Sjdp	  break;
21333965Sjdp	case T_ENUM:
21433965Sjdp	  printf ("ENUM");
21533965Sjdp	  break;
21633965Sjdp	case T_MOE:
21733965Sjdp	  printf ("MOE ");
21833965Sjdp	  break;
21933965Sjdp	case T_UCHAR:
22033965Sjdp	  printf ("UCHAR");
22133965Sjdp	  break;
22233965Sjdp	case T_USHORT:
22333965Sjdp	  printf ("USHORT");
22433965Sjdp	  break;
22533965Sjdp	case T_UINT:
22633965Sjdp	  printf ("UINT");
22733965Sjdp	  break;
22833965Sjdp	case T_ULONG:
22933965Sjdp	  printf ("ULONG");
23033965Sjdp	  break;
23133965Sjdp	case T_LNGDBL:
23233965Sjdp	  printf ("LNGDBL");
23333965Sjdp	  break;
23433965Sjdp	default:
23533965Sjdp	  abort ();
23633965Sjdp	}
23733965Sjdp    }
23833965Sjdp  nl ();
23933965Sjdp  tab (-1);
24033965Sjdp}
24133965Sjdp
24233965Sjdpstatic void
243130561Sobriendump_coff_where (struct coff_where *p)
24433965Sjdp{
24533965Sjdp  tab (1);
24633965Sjdp  switch (p->where)
24733965Sjdp    {
24833965Sjdp    case coff_where_stack:
24933965Sjdp      printf ("Stack offset %x", p->offset);
25033965Sjdp      break;
25133965Sjdp    case coff_where_memory:
25233965Sjdp      printf ("Memory section %s+%x", p->section->name, p->offset);
25333965Sjdp      break;
25433965Sjdp    case coff_where_register:
25533965Sjdp      printf ("Register %d", p->offset);
25633965Sjdp      break;
25733965Sjdp    case coff_where_member_of_struct:
25833965Sjdp      printf ("Struct Member offset %x", p->offset);
25933965Sjdp      break;
26033965Sjdp    case coff_where_member_of_enum:
26133965Sjdp      printf ("Enum Member offset %x", p->offset);
26233965Sjdp      break;
26333965Sjdp    case coff_where_unknown:
26433965Sjdp      printf ("Undefined symbol");
26533965Sjdp      break;
26633965Sjdp    case coff_where_strtag:
26733965Sjdp      printf ("STRTAG");
26833965Sjdp    case coff_where_entag:
26933965Sjdp      printf ("ENTAG");
27033965Sjdp      break;
27133965Sjdp    case coff_where_typedef:
27233965Sjdp      printf ("TYPEDEF");
27333965Sjdp      break;
27433965Sjdp    default:
27533965Sjdp      abort ();
27633965Sjdp    }
27733965Sjdp  nl ();
27833965Sjdp  tab (-1);
27933965Sjdp}
28033965Sjdp
28133965Sjdpstatic void
282130561Sobriendump_coff_visible (struct coff_visible *p)
28333965Sjdp{
28433965Sjdp  tab (1);
28533965Sjdp  switch (p->type)
28633965Sjdp    {
28733965Sjdp    case coff_vis_ext_def:
28833965Sjdp      printf ("coff_vis_ext_def");
28933965Sjdp      break;
29033965Sjdp    case coff_vis_ext_ref:
29133965Sjdp      printf ("coff_vis_ext_ref");
29233965Sjdp      break;
29333965Sjdp    case coff_vis_int_def:
29433965Sjdp      printf ("coff_vis_int_def");
29533965Sjdp      break;
29633965Sjdp    case coff_vis_common:
29733965Sjdp      printf ("coff_vis_common");
29833965Sjdp      break;
29933965Sjdp    case coff_vis_auto:
30033965Sjdp      printf ("coff_vis_auto");
30133965Sjdp      break;
30233965Sjdp    case coff_vis_autoparam:
30333965Sjdp      printf ("coff_vis_autoparam");
30433965Sjdp      break;
30533965Sjdp    case coff_vis_regparam:
30633965Sjdp      printf ("coff_vis_regparam");
30733965Sjdp      break;
30833965Sjdp    case coff_vis_register:
30933965Sjdp      printf ("coff_vis_register");
31033965Sjdp      break;
31133965Sjdp    case coff_vis_tag:
31233965Sjdp      printf ("coff_vis_tag");
31333965Sjdp      break;
31433965Sjdp    case coff_vis_member_of_struct:
31533965Sjdp      printf ("coff_vis_member_of_struct");
31633965Sjdp      break;
31733965Sjdp    case coff_vis_member_of_enum:
31833965Sjdp      printf ("coff_vis_member_of_enum");
31933965Sjdp      break;
32033965Sjdp    default:
32133965Sjdp      abort ();
32233965Sjdp    }
32333965Sjdp  nl ();
32433965Sjdp  tab (-1);
32533965Sjdp}
32633965Sjdp
327218822Sdimstatic void
328130561Sobriendump_coff_symbol (struct coff_symbol *p)
32933965Sjdp{
33033965Sjdp  tab (1);
33133965Sjdp  printf ("List of symbols");
33233965Sjdp  nl ();
33389857Sobrien
33433965Sjdp  while (p)
33533965Sjdp    {
33633965Sjdp      tab (1);
33733965Sjdp      tab (1);
33833965Sjdp      printf ("Symbol  %s, tag %d, number %d", p->name, p->tag, p->number);
33933965Sjdp      nl ();
34033965Sjdp      tab (-1);
34133965Sjdp      tab (1);
34233965Sjdp      printf ("Type");
34333965Sjdp      nl ();
34433965Sjdp      dump_coff_type (p->type);
34533965Sjdp      tab (-1);
34633965Sjdp      tab (1);
34733965Sjdp      printf ("Where");
34833965Sjdp      dump_coff_where (p->where);
34933965Sjdp      tab (-1);
35033965Sjdp      tab (1);
35133965Sjdp      printf ("Visible");
35233965Sjdp      dump_coff_visible (p->visible);
35333965Sjdp      tab (-1);
35433965Sjdp      p = p->next;
35533965Sjdp      tab (-1);
35633965Sjdp    }
35733965Sjdp  tab (-1);
35833965Sjdp}
35933965Sjdp
36033965Sjdpstatic void
361130561Sobriendump_coff_scope (struct coff_scope *p)
36233965Sjdp{
36389857Sobrien  if (p)
36489857Sobrien    {
36589857Sobrien      tab (1);
36689857Sobrien      printf ("List of blocks %lx ",(unsigned long) p);
36733965Sjdp
36889857Sobrien      if (p->sec)
36989857Sobrien	printf( "  %s %x..%x",  p->sec->name,p->offset, p->offset + p->size -1);
37089857Sobrien
37189857Sobrien      nl ();
37233965Sjdp      tab (0);
37389857Sobrien      printf ("*****************");
37433965Sjdp      nl ();
37589857Sobrien
37689857Sobrien      while (p)
37789857Sobrien	{
37889857Sobrien	  tab (0);
37989857Sobrien	  printf ("vars %d", p->nvars);
38089857Sobrien	  nl ();
38189857Sobrien	  dump_coff_symbol (p->vars_head);
38289857Sobrien	  printf ("blocks");
38389857Sobrien	  nl ();
38489857Sobrien	  dump_coff_scope (p->list_head);
38589857Sobrien	  nl ();
38689857Sobrien	  p = p->next;
38789857Sobrien	}
38889857Sobrien
38989857Sobrien      tab (0);
39089857Sobrien      printf ("*****************");
39133965Sjdp      nl ();
39289857Sobrien      tab (-1);
39333965Sjdp    }
39433965Sjdp}
39533965Sjdp
39633965Sjdpstatic void
397130561Sobriendump_coff_sfile (struct coff_sfile *p)
39833965Sjdp{
39933965Sjdp  tab (1);
40033965Sjdp  printf ("List of source files");
40133965Sjdp  nl ();
40289857Sobrien
40333965Sjdp  while (p)
40433965Sjdp    {
40533965Sjdp      tab (0);
40633965Sjdp      printf ("Source file %s", p->name);
40733965Sjdp      nl ();
40833965Sjdp      dump_coff_scope (p->scope);
40933965Sjdp      p = p->next;
41033965Sjdp    }
41133965Sjdp  tab (-1);
41233965Sjdp}
41333965Sjdp
41433965Sjdpstatic void
415130561Sobriendump_coff_section (struct coff_section *ptr)
41633965Sjdp{
41733965Sjdp  int i;
41833965Sjdp
41989857Sobrien  tab (1);
420104834Sobrien  printf ("section %s %d %d address %x size %x number %d nrelocs %d",
42189857Sobrien	  ptr->name, ptr->code, ptr->data, ptr->address,ptr->size,
42289857Sobrien	  ptr->number, ptr->nrelocs);
42389857Sobrien  nl ();
42489857Sobrien
425104834Sobrien  for (i = 0; i < ptr->nrelocs; i++)
42633965Sjdp    {
427104834Sobrien      tab (0);
42889857Sobrien      printf ("(%x %s %x)",
42989857Sobrien	      ptr->relocs[i].offset,
43089857Sobrien	      ptr->relocs[i].symbol->name,
43189857Sobrien	      ptr->relocs[i].addend);
43289857Sobrien      nl ();
43333965Sjdp    }
43433965Sjdp
43589857Sobrien  tab (-1);
43633965Sjdp}
43733965Sjdp
438218822Sdimstatic void
439130561Sobriencoff_dump (struct coff_ofile *ptr)
44033965Sjdp{
44133965Sjdp  int i;
44289857Sobrien
44333965Sjdp  printf ("Coff dump");
44433965Sjdp  nl ();
44533965Sjdp  printf ("#souces %d", ptr->nsources);
44633965Sjdp  nl ();
44733965Sjdp  dump_coff_sfile (ptr->source_head);
44889857Sobrien
44933965Sjdp  for (i = 0; i < ptr->nsections; i++)
45089857Sobrien    dump_coff_section (ptr->sections + i);
45133965Sjdp}
45233965Sjdp
45333965Sjdpchar * program_name;
45433965Sjdp
45533965Sjdpstatic void
456130561Sobrienshow_usage (FILE *file, int status)
45733965Sjdp{
45889857Sobrien  fprintf (file, _("Usage: %s [option(s)] in-file\n"), program_name);
45989857Sobrien  fprintf (file, _(" Print a human readable interpretation of a SYSROFF object file\n"));
46089857Sobrien  fprintf (file, _(" The options are:\n\
461218822Sdim  @<file>                Read options from <file>\n\
46289857Sobrien  -h --help              Display this information\n\
46389857Sobrien  -v --version           Display the program's version\n\
46489857Sobrien\n"));
46589857Sobrien
466218822Sdim  if (REPORT_BUGS_TO[0] && status == 0)
46789857Sobrien    fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
46889857Sobrien
46933965Sjdp  exit (status);
47033965Sjdp}
47133965Sjdp
47233965Sjdpint
473130561Sobrienmain (int ac, char **av)
47433965Sjdp{
47533965Sjdp  bfd *abfd;
47633965Sjdp  struct coff_ofile *tree;
47733965Sjdp  char **matching;
47833965Sjdp  char *input_file = NULL;
47933965Sjdp  int opt;
48033965Sjdp  static struct option long_options[] =
48133965Sjdp    {
48233965Sjdp      { "help", no_argument, 0, 'h' },
48333965Sjdp      { "version", no_argument, 0, 'V' },
48433965Sjdp      { NULL, no_argument, 0, 0 }
48533965Sjdp    };
48633965Sjdp
48760484Sobrien#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
48860484Sobrien  setlocale (LC_MESSAGES, "");
48960484Sobrien#endif
49089857Sobrien#if defined (HAVE_SETLOCALE)
49189857Sobrien  setlocale (LC_CTYPE, "");
49289857Sobrien#endif
49360484Sobrien  bindtextdomain (PACKAGE, LOCALEDIR);
49460484Sobrien  textdomain (PACKAGE);
49560484Sobrien
49633965Sjdp  program_name = av[0];
49733965Sjdp  xmalloc_set_program_name (program_name);
49833965Sjdp
499218822Sdim  expandargv (&ac, &av);
500218822Sdim
50189857Sobrien  while ((opt = getopt_long (ac, av, "HhVv", long_options,
50233965Sjdp			     (int *) NULL))
50333965Sjdp	 != EOF)
50433965Sjdp    {
50533965Sjdp      switch (opt)
50633965Sjdp	{
50789857Sobrien	case 'H':
50833965Sjdp	case 'h':
50989857Sobrien	  show_usage (stdout, 0);
51089857Sobrien	  break;
51189857Sobrien	case 'v':
51233965Sjdp	case 'V':
51389857Sobrien	  print_version ("coffdump");
51433965Sjdp	  exit (0);
51533965Sjdp	case 0:
51633965Sjdp	  break;
51733965Sjdp	default:
51833965Sjdp	  show_usage (stderr, 1);
51989857Sobrien	  break;
52033965Sjdp	}
52133965Sjdp    }
52233965Sjdp
52333965Sjdp  if (optind < ac)
52433965Sjdp    {
52533965Sjdp      input_file = av[optind];
52633965Sjdp    }
52733965Sjdp
52833965Sjdp  if (!input_file)
52989857Sobrien    fatal (_("no input file specified"));
53089857Sobrien
53133965Sjdp  abfd = bfd_openr (input_file, 0);
53233965Sjdp
53333965Sjdp  if (!abfd)
53433965Sjdp    bfd_fatal (input_file);
53533965Sjdp
53633965Sjdp  if (! bfd_check_format_matches (abfd, bfd_object, &matching))
53733965Sjdp    {
53833965Sjdp      bfd_nonfatal (input_file);
53989857Sobrien
54033965Sjdp      if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
54133965Sjdp	{
54233965Sjdp	  list_matching_formats (matching);
54333965Sjdp	  free (matching);
54433965Sjdp	}
54533965Sjdp      exit (1);
54633965Sjdp    }
54733965Sjdp
54833965Sjdp  tree = coff_grok (abfd);
54933965Sjdp
55089857Sobrien  coff_dump (tree);
55189857Sobrien  printf ("\n");
55289857Sobrien
55333965Sjdp  return 0;
55433965Sjdp}
555