* resbin.c (bin_to_res_version): Correct offset
[external/binutils.git] / binutils / sysdump.c
1 /* Sysroff object format dumper.
2    Copyright 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007,
3    2009, 2011  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
10    (at 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
20    02110-1301, USA.  */
21
22
23 /* Written by Steve Chamberlain <sac@cygnus.com>.
24
25  This program reads a SYSROFF object file and prints it in an
26  almost human readable form to stdout.  */
27
28 #include "sysdep.h"
29 #include "bfd.h"
30 #include "safe-ctype.h"
31 #include "libiberty.h"
32 #include "getopt.h"
33 #include "bucomm.h"
34 #include "sysroff.h"
35
36 static int dump = 1;
37 static int segmented_p;
38 static int code;
39 static int addrsize = 4;
40 static FILE *file;
41
42 static void dh (unsigned char *, int);
43 static void itheader (char *, int);
44 static void p (void);
45 static void tabout (void);
46 static void pbarray (barray *);
47 static int getone (int);
48 static int opt (int);
49 static void must (int);
50 static void tab (int, char *);
51 static void dump_symbol_info (void);
52 static void derived_type (void);
53 static void module (void);
54 static void show_usage (FILE *, int);
55
56 extern int main (int, char **);
57
58 static char *
59 getCHARS (unsigned char *ptr, int *idx, int size, int max)
60 {
61   int oc = *idx / 8;
62   char *r;
63   int b = size;
64
65   if (b >= max)
66     return _("*undefined*");
67
68   if (b == 0)
69     {
70       /* Got to work out the length of the string from self.  */
71       b = ptr[oc++];
72       (*idx) += 8;
73     }
74
75   *idx += b * 8;
76   r = xcalloc (b + 1, 1);
77   memcpy (r, ptr + oc, b);
78   r[b] = 0;
79
80   return r;
81 }
82
83 static void
84 dh (unsigned char *ptr, int size)
85 {
86   int i;
87   int j;
88   int span = 16;
89
90   printf ("\n************************************************************\n");
91
92   for (i = 0; i < size; i += span)
93     {
94       for (j = 0; j < span; j++)
95         {
96           if (j + i < size)
97             printf ("%02x ", ptr[i + j]);
98           else
99             printf ("   ");
100         }
101
102       for (j = 0; j < span && j + i < size; j++)
103         {
104           int c = ptr[i + j];
105
106           if (c < 32 || c > 127)
107             c = '.';
108           printf ("%c", c);
109         }
110
111       printf ("\n");
112     }
113 }
114
115 static int
116 fillup (unsigned char *ptr)
117 {
118   int size;
119   int sum;
120   int i;
121
122   size = getc (file);
123   if (size == EOF
124       || size <= 2)
125     return 0;
126
127   size -= 2;
128   if (fread (ptr, size, 1, file) != 1)
129     return 0;
130
131   sum = code + size + 2;
132
133   for (i = 0; i < size; i++)
134     sum += ptr[i];
135
136   if ((sum & 0xff) != 0xff)
137     printf (_("SUM IS %x\n"), sum);
138
139   if (dump)
140     dh (ptr, size);
141
142   return size;
143 }
144
145 static barray
146 getBARRAY (unsigned char *ptr, int *idx, int dsize ATTRIBUTE_UNUSED,
147            int max ATTRIBUTE_UNUSED)
148 {
149   barray res;
150   int i;
151   int byte = *idx / 8;
152   int size = ptr[byte++];
153
154   res.len = size;
155   res.data = (unsigned char *) xmalloc (size);
156
157   for (i = 0; i < size; i++)
158     res.data[i] = ptr[byte++];
159
160   return res;
161 }
162
163 static int
164 getINT (unsigned char *ptr, int *idx, int size, int max)
165 {
166   int n = 0;
167   int byte = *idx / 8;
168
169   if (byte >= max)
170     return 0;
171
172   if (size == -2)
173     size = addrsize;
174
175   if (size == -1)
176     size = 0;
177
178   switch (size)
179     {
180     case 0:
181       return 0;
182     case 1:
183       n = (ptr[byte]);
184       break;
185     case 2:
186       n = (ptr[byte + 0] << 8) + ptr[byte + 1];
187       break;
188     case 4:
189       n = (ptr[byte + 0] << 24) + (ptr[byte + 1] << 16) + (ptr[byte + 2] << 8) + (ptr[byte + 3]);
190       break;
191     default:
192       abort ();
193     }
194
195   *idx += size * 8;
196   return n;
197 }
198
199 static int
200 getBITS (unsigned char *ptr, int *idx, int size, int max)
201 {
202   int byte = *idx / 8;
203   int bit = *idx % 8;
204
205   if (byte >= max)
206     return 0;
207
208   *idx += size;
209
210   return (ptr[byte] >> (8 - bit - size)) & ((1 << size) - 1);
211 }
212
213 static void
214 itheader (char *name, int icode)
215 {
216   printf ("\n%s 0x%02x\n", name, icode);
217 }
218
219 static int indent;
220
221 static void
222 p (void)
223 {
224   int i;
225
226   for (i = 0; i < indent; i++)
227     printf ("| ");
228
229   printf ("> ");
230 }
231
232 static void
233 tabout (void)
234 {
235   p ();
236 }
237
238 static void
239 pbarray (barray *y)
240 {
241   int x;
242
243   printf ("%d (", y->len);
244
245   for (x = 0; x < y->len; x++)
246     printf ("(%02x %c)", y->data[x],
247             ISPRINT (y->data[x]) ? y->data[x] : '.');
248
249   printf (")\n");
250 }
251
252 #define SYSROFF_PRINT
253 #define SYSROFF_SWAP_IN
254
255 #include "sysroff.c"
256
257 /* FIXME: sysinfo, which generates sysroff.[ch] from sysroff.info, can't
258    hack the special case of the tr block, which has no contents.  So we
259    implement our own functions for reading in and printing out the tr
260    block.  */
261
262 #define IT_tr_CODE      0x7f
263
264 static void
265 sysroff_swap_tr_in (void)
266 {
267   unsigned char raw[255];
268
269   memset (raw, 0, 255);
270   fillup (raw);
271 }
272
273 static void
274 sysroff_print_tr_out (void)
275 {
276   itheader ("tr", IT_tr_CODE);
277 }
278
279 static int
280 getone (int type)
281 {
282   int c = getc (file);
283
284   code = c;
285
286   if ((c & 0x7f) != type)
287     {
288       ungetc (c, file);
289       return 0;
290     }
291
292   switch (c & 0x7f)
293     {
294     case IT_cs_CODE:
295       {
296         struct IT_cs dummy;
297         sysroff_swap_cs_in (&dummy);
298         sysroff_print_cs_out (&dummy);
299       }
300       break;
301
302     case IT_dln_CODE:
303       {
304         struct IT_dln dummy;
305         sysroff_swap_dln_in (&dummy);
306         sysroff_print_dln_out (&dummy);
307       }
308       break;
309
310     case IT_hd_CODE:
311       {
312         struct IT_hd dummy;
313         sysroff_swap_hd_in (&dummy);
314         addrsize = dummy.afl;
315         sysroff_print_hd_out (&dummy);
316       }
317       break;
318
319     case IT_dar_CODE:
320       {
321         struct IT_dar dummy;
322         sysroff_swap_dar_in (&dummy);
323         sysroff_print_dar_out (&dummy);
324       }
325       break;
326
327     case IT_dsy_CODE:
328       {
329         struct IT_dsy dummy;
330         sysroff_swap_dsy_in (&dummy);
331         sysroff_print_dsy_out (&dummy);
332       }
333       break;
334
335     case IT_dfp_CODE:
336       {
337         struct IT_dfp dummy;
338         sysroff_swap_dfp_in (&dummy);
339         sysroff_print_dfp_out (&dummy);
340       }
341       break;
342
343     case IT_dso_CODE:
344       {
345         struct IT_dso dummy;
346         sysroff_swap_dso_in (&dummy);
347         sysroff_print_dso_out (&dummy);
348       }
349       break;
350
351     case IT_dpt_CODE:
352       {
353         struct IT_dpt dummy;
354         sysroff_swap_dpt_in (&dummy);
355         sysroff_print_dpt_out (&dummy);
356       }
357       break;
358
359     case IT_den_CODE:
360       {
361         struct IT_den dummy;
362         sysroff_swap_den_in (&dummy);
363         sysroff_print_den_out (&dummy);
364       }
365       break;
366
367     case IT_dbt_CODE:
368       {
369         struct IT_dbt dummy;
370         sysroff_swap_dbt_in (&dummy);
371         sysroff_print_dbt_out (&dummy);
372       }
373       break;
374
375     case IT_dty_CODE:
376       {
377         struct IT_dty dummy;
378         sysroff_swap_dty_in (&dummy);
379         sysroff_print_dty_out (&dummy);
380       }
381       break;
382
383     case IT_un_CODE:
384       {
385         struct IT_un dummy;
386         sysroff_swap_un_in (&dummy);
387         sysroff_print_un_out (&dummy);
388       }
389       break;
390
391     case IT_sc_CODE:
392       {
393         struct IT_sc dummy;
394         sysroff_swap_sc_in (&dummy);
395         sysroff_print_sc_out (&dummy);
396       }
397       break;
398
399     case IT_er_CODE:
400       {
401         struct IT_er dummy;
402         sysroff_swap_er_in (&dummy);
403         sysroff_print_er_out (&dummy);
404       }
405       break;
406
407     case IT_ed_CODE:
408       {
409         struct IT_ed dummy;
410         sysroff_swap_ed_in (&dummy);
411         sysroff_print_ed_out (&dummy);
412       }
413       break;
414
415     case IT_sh_CODE:
416       {
417         struct IT_sh dummy;
418         sysroff_swap_sh_in (&dummy);
419         sysroff_print_sh_out (&dummy);
420       }
421       break;
422
423     case IT_ob_CODE:
424       {
425         struct IT_ob dummy;
426         sysroff_swap_ob_in (&dummy);
427         sysroff_print_ob_out (&dummy);
428       }
429       break;
430
431     case IT_rl_CODE:
432       {
433         struct IT_rl dummy;
434         sysroff_swap_rl_in (&dummy);
435         sysroff_print_rl_out (&dummy);
436       }
437       break;
438
439     case IT_du_CODE:
440       {
441         struct IT_du dummy;
442         sysroff_swap_du_in (&dummy);
443
444         sysroff_print_du_out (&dummy);
445       }
446       break;
447
448     case IT_dus_CODE:
449       {
450         struct IT_dus dummy;
451         sysroff_swap_dus_in (&dummy);
452         sysroff_print_dus_out (&dummy);
453       }
454       break;
455
456     case IT_dul_CODE:
457       {
458         struct IT_dul dummy;
459         sysroff_swap_dul_in (&dummy);
460         sysroff_print_dul_out (&dummy);
461       }
462       break;
463
464     case IT_dss_CODE:
465       {
466         struct IT_dss dummy;
467         sysroff_swap_dss_in (&dummy);
468         sysroff_print_dss_out (&dummy);
469       }
470       break;
471
472     case IT_hs_CODE:
473       {
474         struct IT_hs dummy;
475         sysroff_swap_hs_in (&dummy);
476         sysroff_print_hs_out (&dummy);
477       }
478       break;
479
480     case IT_dps_CODE:
481       {
482         struct IT_dps dummy;
483         sysroff_swap_dps_in (&dummy);
484         sysroff_print_dps_out (&dummy);
485       }
486       break;
487
488     case IT_tr_CODE:
489       sysroff_swap_tr_in ();
490       sysroff_print_tr_out ();
491       break;
492
493     case IT_dds_CODE:
494       {
495         struct IT_dds dummy;
496
497         sysroff_swap_dds_in (&dummy);
498         sysroff_print_dds_out (&dummy);
499       }
500       break;
501
502     default:
503       printf (_("GOT A %x\n"), c);
504       return 0;
505       break;
506     }
507
508   return 1;
509 }
510
511 static int
512 opt (int x)
513 {
514   return getone (x);
515 }
516
517 static void
518 must (int x)
519 {
520   if (!getone (x))
521     printf (_("WANTED %x!!\n"), x);
522 }
523
524 static void
525 tab (int i, char *s)
526 {
527   indent += i;
528
529   if (s)
530     {
531       p ();
532       puts (s);
533     }
534 }
535
536 static void
537 dump_symbol_info (void)
538 {
539   tab (1, _("SYMBOL INFO"));
540
541   while (opt (IT_dsy_CODE))
542     {
543       if (opt (IT_dty_CODE))
544         {
545           must (IT_dbt_CODE);
546           derived_type ();
547           must (IT_dty_CODE);
548         }
549     }
550
551   tab (-1, "");
552 }
553
554 static void
555 derived_type (void)
556 {
557   tab (1, _("DERIVED TYPE"));
558
559   while (1)
560     {
561       if (opt (IT_dpp_CODE))
562         {
563           dump_symbol_info ();
564           must (IT_dpp_CODE);
565         }
566       else if (opt (IT_dfp_CODE))
567         {
568           dump_symbol_info ();
569           must (IT_dfp_CODE);
570         }
571       else if (opt (IT_den_CODE))
572         {
573           dump_symbol_info ();
574           must (IT_den_CODE);
575         }
576       else if (opt (IT_den_CODE))
577         {
578           dump_symbol_info ();
579           must (IT_den_CODE);
580         }
581       else if (opt (IT_dds_CODE))
582         {
583           dump_symbol_info ();
584           must (IT_dds_CODE);
585         }
586       else if (opt (IT_dar_CODE))
587         {
588         }
589       else if (opt (IT_dpt_CODE))
590         {
591         }
592       else if (opt (IT_dul_CODE))
593         {
594         }
595       else if (opt (IT_dse_CODE))
596         {
597         }
598       else if (opt (IT_dot_CODE))
599         {
600         }
601       else
602         break;
603     }
604
605   tab (-1, "");
606 }
607
608 static void
609 module (void)
610 {
611   int c = 0;
612   int l = 0;
613
614   tab (1, _("MODULE***\n"));
615
616   do
617     {
618       c = getc (file);
619       ungetc (c, file);
620
621       c &= 0x7f;
622     }
623   while (getone (c) && c != IT_tr_CODE);
624
625   tab (-1, "");
626
627   c = getc (file);
628   while (c != EOF)
629     {
630       printf ("%02x ", c);
631       l++;
632       if (l == 32)
633         {
634           printf ("\n");
635           l = 0;
636         }
637       c = getc (file);
638     }
639 }
640
641 char *program_name;
642
643 static void
644 show_usage (FILE *ffile, int status)
645 {
646   fprintf (ffile, _("Usage: %s [option(s)] in-file\n"), program_name);
647   fprintf (ffile, _("Print a human readable interpretation of a SYSROFF object file\n"));
648   fprintf (ffile, _(" The options are:\n\
649   -h --help        Display this information\n\
650   -v --version     Print the program's version number\n"));
651
652   if (REPORT_BUGS_TO[0] && status == 0)
653     fprintf (ffile, _("Report bugs to %s\n"), REPORT_BUGS_TO);
654   exit (status);
655 }
656
657 int
658 main (int ac, char **av)
659 {
660   char *input_file = NULL;
661   int option;
662   static struct option long_options[] =
663   {
664     {"help", no_argument, 0, 'h'},
665     {"version", no_argument, 0, 'V'},
666     {NULL, no_argument, 0, 0}
667   };
668
669 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
670   setlocale (LC_MESSAGES, "");
671 #endif
672 #if defined (HAVE_SETLOCALE)
673   setlocale (LC_CTYPE, "");
674 #endif
675   bindtextdomain (PACKAGE, LOCALEDIR);
676   textdomain (PACKAGE);
677
678   program_name = av[0];
679   xmalloc_set_program_name (program_name);
680
681   expandargv (&ac, &av);
682
683   while ((option = getopt_long (ac, av, "HhVv", long_options, (int *) NULL)) != EOF)
684     {
685       switch (option)
686         {
687         case 'H':
688         case 'h':
689           show_usage (stdout, 0);
690           /*NOTREACHED*/
691         case 'v':
692         case 'V':
693           print_version ("sysdump");
694           exit (0);
695           /*NOTREACHED*/
696         case 0:
697           break;
698         default:
699           show_usage (stderr, 1);
700           /*NOTREACHED*/
701         }
702     }
703
704   /* The input and output files may be named on the command line.  */
705
706   if (optind < ac)
707     input_file = av[optind];
708
709   if (!input_file)
710     fatal (_("no input file specified"));
711
712   file = fopen (input_file, FOPEN_RB);
713
714   if (!file)
715     fatal (_("cannot open input file %s"), input_file);
716
717   module ();
718   return 0;
719 }