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