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