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