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