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