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