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