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