1/* Sysroff object format dumper.
2   Copyright 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
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., 51 Franklin Street - Fifth Floor, Boston, MA
20   02110-1301, 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 "sysdep.h"
29#include "bfd.h"
30#include "safe-ctype.h"
31#include "libiberty.h"
32#include "getopt.h"
33#include "bucomm.h"
34#include "sysroff.h"
35
36static int dump = 1;
37static int segmented_p;
38static int code;
39static int addrsize = 4;
40static FILE *file;
41
42static void dh (unsigned char *, int);
43static void itheader (char *, int);
44static void p (void);
45static void tabout (void);
46static void pbarray (barray *);
47static int getone (int);
48static int opt (int);
49static void must (int);
50static void tab (int, char *);
51static void dump_symbol_info (void);
52static void derived_type (void);
53static void module (void);
54static void show_usage (FILE *, int);
55
56extern int main (int, char **);
57
58static char *
59getCHARS (unsigned char *ptr, int *idx, int size, int max)
60{
61  int oc = *idx / 8;
62  char *r;
63  int b = size;
64
65  if (b >= max)
66    return "*undefined*";
67
68  if (b == 0)
69    {
70      /* Got to work out the length of the string from self.  */
71      b = ptr[oc++];
72      (*idx) += 8;
73    }
74
75  *idx += b * 8;
76  r = xcalloc (b + 1, 1);
77  memcpy (r, ptr + oc, b);
78  r[b] = 0;
79
80  return r;
81}
82
83static void
84dh (unsigned char *ptr, int size)
85{
86  int i;
87  int j;
88  int span = 16;
89
90  printf ("\n************************************************************\n");
91
92  for (i = 0; i < size; i += span)
93    {
94      for (j = 0; j < span; j++)
95	{
96	  if (j + i < size)
97	    printf ("%02x ", ptr[i + j]);
98	  else
99	    printf ("   ");
100	}
101
102      for (j = 0; j < span && j + i < size; j++)
103	{
104	  int c = ptr[i + j];
105
106	  if (c < 32 || c > 127)
107	    c = '.';
108	  printf ("%c", c);
109	}
110
111      printf ("\n");
112    }
113}
114
115static int
116fillup (unsigned char *ptr)
117{
118  int size;
119  int sum;
120  int i;
121
122  size = getc (file) - 2;
123  fread (ptr, 1, size, file);
124  sum = code + size + 2;
125
126  for (i = 0; i < size; i++)
127    sum += ptr[i];
128
129  if ((sum & 0xff) != 0xff)
130    printf ("SUM IS %x\n", sum);
131
132  if (dump)
133    dh (ptr, size);
134
135  return size - 1;
136}
137
138static barray
139getBARRAY (unsigned char *ptr, int *idx, int dsize ATTRIBUTE_UNUSED,
140	   int max ATTRIBUTE_UNUSED)
141{
142  barray res;
143  int i;
144  int byte = *idx / 8;
145  int size = ptr[byte++];
146
147  res.len = size;
148  res.data = (unsigned char *) xmalloc (size);
149
150  for (i = 0; i < size; i++)
151    res.data[i] = ptr[byte++];
152
153  return res;
154}
155
156static int
157getINT (unsigned char *ptr, int *idx, int size, int max)
158{
159  int n = 0;
160  int byte = *idx / 8;
161
162  if (byte >= max)
163    return 0;
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      abort ();
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 code)
208{
209  printf ("\n%s 0x%02x\n", name, code);
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      printf (s);
526      printf ("\n");
527    }
528}
529
530static void
531dump_symbol_info (void)
532{
533  tab (1, "SYMBOL INFO");
534
535  while (opt (IT_dsy_CODE))
536    {
537      if (opt (IT_dty_CODE))
538	{
539	  must (IT_dbt_CODE);
540	  derived_type ();
541	  must (IT_dty_CODE);
542	}
543    }
544
545  tab (-1, "");
546}
547
548static void
549derived_type (void)
550{
551  tab (1, "DERIVED TYPE");
552
553  while (1)
554    {
555      if (opt (IT_dpp_CODE))
556	{
557	  dump_symbol_info ();
558	  must (IT_dpp_CODE);
559	}
560      else if (opt (IT_dfp_CODE))
561	{
562	  dump_symbol_info ();
563	  must (IT_dfp_CODE);
564	}
565      else if (opt (IT_den_CODE))
566	{
567	  dump_symbol_info ();
568	  must (IT_den_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_dds_CODE))
576	{
577	  dump_symbol_info ();
578	  must (IT_dds_CODE);
579	}
580      else if (opt (IT_dar_CODE))
581	{
582	}
583      else if (opt (IT_dpt_CODE))
584	{
585	}
586      else if (opt (IT_dul_CODE))
587	{
588	}
589      else if (opt (IT_dse_CODE))
590	{
591	}
592      else if (opt (IT_dot_CODE))
593	{
594	}
595      else
596	break;
597    }
598
599  tab (-1, "");
600}
601
602static void
603module (void)
604{
605  int c = 0;
606  int l = 0;
607
608  tab (1, "MODULE***\n");
609
610  do
611    {
612      c = getc (file);
613      ungetc (c, file);
614
615      c &= 0x7f;
616    }
617  while (getone (c) && c != IT_tr_CODE);
618
619  tab (-1, "");
620
621  c = getc (file);
622  while (c != EOF)
623    {
624      printf ("%02x ", c);
625      l++;
626      if (l == 32)
627	{
628	  printf ("\n");
629	  l = 0;
630	}
631      c = getc (file);
632    }
633}
634
635char *program_name;
636
637static void
638show_usage (FILE *file, int status)
639{
640  fprintf (file, _("Usage: %s [option(s)] in-file\n"), program_name);
641  fprintf (file, _("Print a human readable interpretation of a SYSROFF object file\n"));
642  fprintf (file, _(" The options are:\n\
643  -h --help        Display this information\n\
644  -v --version     Print the program's version number\n"));
645
646  if (REPORT_BUGS_TO[0] && status == 0)
647    fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
648  exit (status);
649}
650
651int
652main (int ac, char **av)
653{
654  char *input_file = NULL;
655  int opt;
656  static struct option long_options[] =
657  {
658    {"help", no_argument, 0, 'h'},
659    {"version", no_argument, 0, 'V'},
660    {NULL, no_argument, 0, 0}
661  };
662
663#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
664  setlocale (LC_MESSAGES, "");
665#endif
666#if defined (HAVE_SETLOCALE)
667  setlocale (LC_CTYPE, "");
668#endif
669  bindtextdomain (PACKAGE, LOCALEDIR);
670  textdomain (PACKAGE);
671
672  program_name = av[0];
673  xmalloc_set_program_name (program_name);
674
675  expandargv (&ac, &av);
676
677  while ((opt = getopt_long (ac, av, "HhVv", long_options, (int *) NULL)) != EOF)
678    {
679      switch (opt)
680	{
681	case 'H':
682	case 'h':
683	  show_usage (stdout, 0);
684	  /*NOTREACHED*/
685	case 'v':
686	case 'V':
687	  print_version ("sysdump");
688	  exit (0);
689	  /*NOTREACHED*/
690	case 0:
691	  break;
692	default:
693	  show_usage (stderr, 1);
694	  /*NOTREACHED*/
695	}
696    }
697
698  /* The input and output files may be named on the command line.  */
699
700  if (optind < ac)
701    input_file = av[optind];
702
703  if (!input_file)
704    fatal (_("no input file specified"));
705
706  file = fopen (input_file, FOPEN_RB);
707
708  if (!file)
709    fatal (_("cannot open input file %s"), input_file);
710
711  module ();
712  return 0;
713}
714