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 
33 static int atnl;
34 
35 static void tab (int);
36 static void nl (void);
37 static void dump_coff_lines (struct coff_line *);
38 static void dump_coff_type (struct coff_type *);
39 static void dump_coff_where (struct coff_where *);
40 static void dump_coff_visible (struct coff_visible *);
41 static void dump_coff_scope (struct coff_scope *);
42 static void dump_coff_sfile (struct coff_sfile *);
43 static void dump_coff_section (struct coff_section *);
44 static void show_usage (FILE *, int);
45 extern int main (int, char **);
46 
47 static void
48 tab (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 
90 static void
91 nl (void)
92 {
93   atnl = 1;
94 }
95 
96 static void
97 dump_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 
122 static void
123 dump_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 
241 static void
242 dump_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 
280 static void
281 dump_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 
326 static void
327 dump_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 
359 static void
360 dump_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 
395 static void
396 dump_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 
413 static void
414 dump_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 
437 static void
438 coff_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 
452 char * program_name;
453 
454 static void
455 show_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 
471 int
472 main (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