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