* objdump.c (print_line): Check fwrite return value.
[external/binutils.git] / binutils / sysdump.c
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 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
36 static int dump = 1;
37 static int segmented_p;
38 static int code;
39 static int addrsize = 4;
40 static FILE *file;
41
42 static void dh (unsigned char *, int);
43 static void itheader (char *, int);
44 static void p (void);
45 static void tabout (void);
46 static void pbarray (barray *);
47 static int getone (int);
48 static int opt (int);
49 static void must (int);
50 static void tab (int, char *);
51 static void dump_symbol_info (void);
52 static void derived_type (void);
53 static void module (void);
54 static void show_usage (FILE *, int);
55
56 extern int main (int, char **);
57
58 static char *
59 getCHARS (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
83 static void
84 dh (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
115 static int
116 fillup (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
145 static barray
146 getBARRAY (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
163 static int
164 getINT (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
199 static int
200 getBITS (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
213 static void
214 itheader (char *name, int code)
215 {
216   printf ("\n%s 0x%02x\n", name, code);
217 }
218
219 static int indent;
220
221 static void
222 p (void)
223 {
224   int i;
225
226   for (i = 0; i < indent; i++)
227     printf ("| ");
228
229   printf ("> ");
230 }
231
232 static void
233 tabout (void)
234 {
235   p ();
236 }
237
238 static void
239 pbarray (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
264 static void
265 sysroff_swap_tr_in (void)
266 {
267   unsigned char raw[255];
268
269   memset (raw, 0, 255);
270   fillup (raw);
271 }
272
273 static void
274 sysroff_print_tr_out (void)
275 {
276   itheader ("tr", IT_tr_CODE);
277 }
278
279 static int
280 getone (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
511 static int
512 opt (int x)
513 {
514   return getone (x);
515 }
516
517 static void
518 must (int x)
519 {
520   if (!getone (x))
521     printf ("WANTED %x!!\n", x);
522 }
523
524 static void
525 tab (int i, char *s)
526 {
527   indent += i;
528
529   if (s)
530     {
531       p ();
532       printf (s);
533       printf ("\n");
534     }
535 }
536
537 static void
538 dump_symbol_info (void)
539 {
540   tab (1, "SYMBOL INFO");
541
542   while (opt (IT_dsy_CODE))
543     {
544       if (opt (IT_dty_CODE))
545         {
546           must (IT_dbt_CODE);
547           derived_type ();
548           must (IT_dty_CODE);
549         }
550     }
551
552   tab (-1, "");
553 }
554
555 static void
556 derived_type (void)
557 {
558   tab (1, "DERIVED TYPE");
559
560   while (1)
561     {
562       if (opt (IT_dpp_CODE))
563         {
564           dump_symbol_info ();
565           must (IT_dpp_CODE);
566         }
567       else if (opt (IT_dfp_CODE))
568         {
569           dump_symbol_info ();
570           must (IT_dfp_CODE);
571         }
572       else if (opt (IT_den_CODE))
573         {
574           dump_symbol_info ();
575           must (IT_den_CODE);
576         }
577       else if (opt (IT_den_CODE))
578         {
579           dump_symbol_info ();
580           must (IT_den_CODE);
581         }
582       else if (opt (IT_dds_CODE))
583         {
584           dump_symbol_info ();
585           must (IT_dds_CODE);
586         }
587       else if (opt (IT_dar_CODE))
588         {
589         }
590       else if (opt (IT_dpt_CODE))
591         {
592         }
593       else if (opt (IT_dul_CODE))
594         {
595         }
596       else if (opt (IT_dse_CODE))
597         {
598         }
599       else if (opt (IT_dot_CODE))
600         {
601         }
602       else
603         break;
604     }
605
606   tab (-1, "");
607 }
608
609 static void
610 module (void)
611 {
612   int c = 0;
613   int l = 0;
614
615   tab (1, "MODULE***\n");
616
617   do
618     {
619       c = getc (file);
620       ungetc (c, file);
621
622       c &= 0x7f;
623     }
624   while (getone (c) && c != IT_tr_CODE);
625
626   tab (-1, "");
627
628   c = getc (file);
629   while (c != EOF)
630     {
631       printf ("%02x ", c);
632       l++;
633       if (l == 32)
634         {
635           printf ("\n");
636           l = 0;
637         }
638       c = getc (file);
639     }
640 }
641
642 char *program_name;
643
644 static void
645 show_usage (FILE *file, int status)
646 {
647   fprintf (file, _("Usage: %s [option(s)] in-file\n"), program_name);
648   fprintf (file, _("Print a human readable interpretation of a SYSROFF object file\n"));
649   fprintf (file, _(" The options are:\n\
650   -h --help        Display this information\n\
651   -v --version     Print the program's version number\n"));
652
653   if (REPORT_BUGS_TO[0] && status == 0)
654     fprintf (file, _("Report bugs to %s\n"), REPORT_BUGS_TO);
655   exit (status);
656 }
657
658 int
659 main (int ac, char **av)
660 {
661   char *input_file = NULL;
662   int opt;
663   static struct option long_options[] =
664   {
665     {"help", no_argument, 0, 'h'},
666     {"version", no_argument, 0, 'V'},
667     {NULL, no_argument, 0, 0}
668   };
669
670 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
671   setlocale (LC_MESSAGES, "");
672 #endif
673 #if defined (HAVE_SETLOCALE)
674   setlocale (LC_CTYPE, "");
675 #endif
676   bindtextdomain (PACKAGE, LOCALEDIR);
677   textdomain (PACKAGE);
678
679   program_name = av[0];
680   xmalloc_set_program_name (program_name);
681
682   expandargv (&ac, &av);
683
684   while ((opt = getopt_long (ac, av, "HhVv", long_options, (int *) NULL)) != EOF)
685     {
686       switch (opt)
687         {
688         case 'H':
689         case 'h':
690           show_usage (stdout, 0);
691           /*NOTREACHED*/
692         case 'v':
693         case 'V':
694           print_version ("sysdump");
695           exit (0);
696           /*NOTREACHED*/
697         case 0:
698           break;
699         default:
700           show_usage (stderr, 1);
701           /*NOTREACHED*/
702         }
703     }
704
705   /* The input and output files may be named on the command line.  */
706
707   if (optind < ac)
708     input_file = av[optind];
709
710   if (!input_file)
711     fatal (_("no input file specified"));
712
713   file = fopen (input_file, FOPEN_RB);
714
715   if (!file)
716     fatal (_("cannot open input file %s"), input_file);
717
718   module ();
719   return 0;
720 }