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