xref: /netbsd-src/external/gpl3/binutils.old/dist/binutils/coffdump.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
1 /* Coff file dumper.
2    Copyright (C) 1994-2022 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 3 of the License, or (at
9    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., 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20 
21 
22 /* Written by Steve Chamberlain <sac@cygnus.com>
23 
24    This module reads a type tree generated by coffgrok and prints
25    it out so we can test the grokker.  */
26 
27 #include "sysdep.h"
28 #include "bfd.h"
29 #include <stdint.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
tab(int x)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
nl(void)94 nl (void)
95 {
96   atnl = 1;
97 }
98 
99 static void
dump_coff_lines(struct coff_line * p)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
dump_coff_type(struct coff_type * p)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
dump_coff_where(struct coff_where * p)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       break;
271     case coff_where_entag:
272       printf ("ENTAG");
273       break;
274     case coff_where_typedef:
275       printf ("TYPEDEF");
276       break;
277     default:
278       abort ();
279     }
280   nl ();
281   tab (-1);
282 }
283 
284 static void
dump_coff_visible(struct coff_visible * p)285 dump_coff_visible (struct coff_visible *p)
286 {
287   tab (1);
288   switch (p->type)
289     {
290     case coff_vis_ext_def:
291       printf ("coff_vis_ext_def");
292       break;
293     case coff_vis_ext_ref:
294       printf ("coff_vis_ext_ref");
295       break;
296     case coff_vis_int_def:
297       printf ("coff_vis_int_def");
298       break;
299     case coff_vis_common:
300       printf ("coff_vis_common");
301       break;
302     case coff_vis_auto:
303       printf ("coff_vis_auto");
304       break;
305     case coff_vis_autoparam:
306       printf ("coff_vis_autoparam");
307       break;
308     case coff_vis_regparam:
309       printf ("coff_vis_regparam");
310       break;
311     case coff_vis_register:
312       printf ("coff_vis_register");
313       break;
314     case coff_vis_tag:
315       printf ("coff_vis_tag");
316       break;
317     case coff_vis_member_of_struct:
318       printf ("coff_vis_member_of_struct");
319       break;
320     case coff_vis_member_of_enum:
321       printf ("coff_vis_member_of_enum");
322       break;
323     default:
324       abort ();
325     }
326   nl ();
327   tab (-1);
328 }
329 
330 static void
dump_coff_symbol(struct coff_symbol * p)331 dump_coff_symbol (struct coff_symbol *p)
332 {
333   tab (1);
334   printf (_("List of symbols"));
335   nl ();
336 
337   while (p)
338     {
339       tab (1);
340       tab (1);
341       printf (_("Symbol  %s, tag %d, number %d"), p->name, p->tag, p->number);
342       nl ();
343       tab (-1);
344       tab (1);
345       printf (_("Type"));
346       nl ();
347       dump_coff_type (p->type);
348       tab (-1);
349       tab (1);
350       printf (_("Where"));
351       dump_coff_where (p->where);
352       tab (-1);
353       tab (1);
354       printf (_("Visible"));
355       dump_coff_visible (p->visible);
356       tab (-1);
357       p = p->next;
358       tab (-1);
359     }
360   tab (-1);
361 }
362 
363 static void
dump_coff_scope(struct coff_scope * p)364 dump_coff_scope (struct coff_scope *p)
365 {
366   if (p)
367     {
368       tab (1);
369       printf ("%s %" BFD_VMA_FMT "x ",
370 	      _("List of blocks "), (bfd_vma) (uintptr_t) p);
371 
372       if (p->sec)
373 	printf( "  %s %x..%x",  p->sec->name,p->offset, p->offset + p->size -1);
374 
375       nl ();
376       tab (0);
377       printf ("*****************");
378       nl ();
379 
380       while (p)
381 	{
382 	  tab (0);
383 	  printf (_("vars %d"), p->nvars);
384 	  nl ();
385 	  dump_coff_symbol (p->vars_head);
386 	  printf (_("blocks"));
387 	  nl ();
388 	  dump_coff_scope (p->list_head);
389 	  nl ();
390 	  p = p->next;
391 	}
392 
393       tab (0);
394       printf ("*****************");
395       nl ();
396       tab (-1);
397     }
398 }
399 
400 static void
dump_coff_sfile(struct coff_sfile * p)401 dump_coff_sfile (struct coff_sfile *p)
402 {
403   tab (1);
404   printf (_("List of source files"));
405   nl ();
406 
407   while (p)
408     {
409       tab (0);
410       printf (_("Source file %s"), p->name);
411       nl ();
412       dump_coff_scope (p->scope);
413       p = p->next;
414     }
415   tab (-1);
416 }
417 
418 static void
dump_coff_section(struct coff_section * ptr)419 dump_coff_section (struct coff_section *ptr)
420 {
421   unsigned int i;
422 
423   tab (1);
424   printf (_("section %s %d %d address %x size %x number %d nrelocs %u"),
425 	  ptr->name, ptr->code, ptr->data, ptr->address,ptr->size,
426 	  ptr->number, ptr->nrelocs);
427   nl ();
428 
429   for (i = 0; i < ptr->nrelocs; i++)
430     {
431       struct coff_reloc * r = ptr->relocs + i;
432       tab (0);
433       printf ("(%x %s %x)",
434 	      r->offset,
435 	      /* PR 17512: file: 0a38fb7c.  */
436 	      r->symbol == NULL ? _("<no sym>") : r->symbol->name,
437 	      r->addend);
438       nl ();
439     }
440 
441   tab (-1);
442 }
443 
444 static void
coff_dump(struct coff_ofile * ptr)445 coff_dump (struct coff_ofile *ptr)
446 {
447   int i;
448 
449   printf ("Coff dump");
450   nl ();
451   printf (_("#sources %d"), ptr->nsources);
452   nl ();
453   dump_coff_sfile (ptr->source_head);
454 
455   for (i = 0; i < ptr->nsections; i++)
456     dump_coff_section (ptr->sections + i);
457 }
458 
459 static void
show_usage(FILE * file,int status)460 show_usage (FILE *file, int status)
461 {
462   fprintf (file, _("Usage: %s [option(s)] in-file\n"), program_name);
463   fprintf (file, _(" Print a human readable interpretation of a COFF object file\n"));
464   fprintf (file, _(" The options are:\n\
465   @<file>                Read options from <file>\n\
466   -h --help              Display this information\n\
467   -v --version           Display the program's version\n\
468 \n"));
469 
470   if (REPORT_BUGS_TO[0] && status == 0)
471     fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
472 
473   exit (status);
474 }
475 
476 int
main(int ac,char ** av)477 main (int ac, char **av)
478 {
479   bfd *abfd;
480   struct coff_ofile *tree;
481   char **matching;
482   char *input_file = NULL;
483   int opt;
484   static struct option long_options[] =
485     {
486       { "help", no_argument, 0, 'h' },
487       { "version", no_argument, 0, 'V' },
488       { NULL, no_argument, 0, 0 }
489     };
490 
491 #ifdef HAVE_LC_MESSAGES
492   setlocale (LC_MESSAGES, "");
493 #endif
494   setlocale (LC_CTYPE, "");
495   bindtextdomain (PACKAGE, LOCALEDIR);
496   textdomain (PACKAGE);
497 
498   program_name = av[0];
499   xmalloc_set_program_name (program_name);
500   bfd_set_error_program_name (program_name);
501 
502   expandargv (&ac, &av);
503 
504   while ((opt = getopt_long (ac, av, "HhVv", long_options,
505 			     (int *) NULL))
506 	 != EOF)
507     {
508       switch (opt)
509 	{
510 	case 'H':
511 	case 'h':
512 	  show_usage (stdout, 0);
513 	  break;
514 	case 'v':
515 	case 'V':
516 	  print_version ("coffdump");
517 	  exit (0);
518 	case 0:
519 	  break;
520 	default:
521 	  show_usage (stderr, 1);
522 	  break;
523 	}
524     }
525 
526   if (optind < ac)
527     {
528       input_file = av[optind];
529     }
530 
531   if (!input_file)
532     fatal (_("no input file specified"));
533 
534   abfd = bfd_openr (input_file, 0);
535 
536   if (!abfd)
537     bfd_fatal (input_file);
538 
539   if (! bfd_check_format_matches (abfd, bfd_object, &matching))
540     {
541       bfd_nonfatal (input_file);
542 
543       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
544 	list_matching_formats (matching);
545       exit (1);
546     }
547 
548   tree = coff_grok (abfd);
549   if (tree)
550     {
551       coff_dump (tree);
552       printf ("\n");
553     }
554 
555   return 0;
556 }
557