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