1 /* Sysroff object format dumper.
2    Copyright 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2005
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 (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 }
715