PowerPC64 segfault in ppc64_elf_edit_toc
[external/binutils.git] / binutils / sysdump.c
1 /* Sysroff object format dumper.
2    Copyright (C) 1994-2019 Free Software Foundation, Inc.
3
4    This file is part of GNU Binutils.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19    02110-1301, USA.  */
20
21
22 /* Written by Steve Chamberlain <sac@cygnus.com>.
23
24  This program reads a SYSROFF object file and prints it in an
25  almost human readable form to stdout.  */
26
27 #include "sysdep.h"
28 #include "bfd.h"
29 #include "safe-ctype.h"
30 #include "libiberty.h"
31 #include "getopt.h"
32 #include "bucomm.h"
33 #include "sysroff.h"
34
35 static int dump = 1;
36 static int segmented_p;
37 static int code;
38 static int addrsize = 4;
39 static FILE *file;
40
41 static void derived_type (void);
42
43 static char *
44 getCHARS (unsigned char *ptr, int *idx, int size, int max)
45 {
46   int oc = *idx / 8;
47   char *r;
48   int b = size;
49
50   if (b >= max)
51     return _("*undefined*");
52
53   if (b == 0)
54     {
55       /* PR 17512: file: 13caced2.  */
56       if (oc >= max)
57         return _("*corrupt*");
58       /* Got to work out the length of the string from self.  */
59       b = ptr[oc++];
60       (*idx) += 8;
61     }
62
63   *idx += b * 8;
64   r = xcalloc (b + 1, 1);
65   memcpy (r, ptr + oc, b);
66   r[b] = 0;
67
68   return r;
69 }
70
71 static void
72 dh (unsigned char *ptr, int size)
73 {
74   int i;
75   int j;
76   int span = 16;
77
78   printf ("\n************************************************************\n");
79
80   for (i = 0; i < size; i += span)
81     {
82       for (j = 0; j < span; j++)
83         {
84           if (j + i < size)
85             printf ("%02x ", ptr[i + j]);
86           else
87             printf ("   ");
88         }
89
90       for (j = 0; j < span && j + i < size; j++)
91         {
92           int c = ptr[i + j];
93
94           if (c < 32 || c > 127)
95             c = '.';
96           printf ("%c", c);
97         }
98
99       printf ("\n");
100     }
101 }
102
103 static int
104 fillup (unsigned char *ptr)
105 {
106   int size;
107   int sum;
108   int i;
109
110   size = getc (file);
111   if (size == EOF
112       || size <= 2)
113     return 0;
114
115   size -= 2;
116   if (fread (ptr, size, 1, file) != 1)
117     return 0;
118
119   sum = code + size + 2;
120
121   for (i = 0; i < size; i++)
122     sum += ptr[i];
123
124   if ((sum & 0xff) != 0xff)
125     printf (_("SUM IS %x\n"), sum);
126
127   if (dump)
128     dh (ptr, size);
129
130   return size;
131 }
132
133 static barray
134 getBARRAY (unsigned char *ptr, int *idx, int dsize ATTRIBUTE_UNUSED,
135            int max ATTRIBUTE_UNUSED)
136 {
137   barray res;
138   int i;
139   int byte = *idx / 8;
140   int size = ptr[byte++];
141
142   res.len = size;
143   res.data = (unsigned char *) xmalloc (size);
144
145   for (i = 0; i < size; i++)
146     res.data[i] = ptr[byte++];
147
148   return res;
149 }
150
151 static int
152 getINT (unsigned char *ptr, int *idx, int size, int max)
153 {
154   int n = 0;
155   int byte = *idx / 8;
156
157   if (byte >= max)
158     {
159       /* PR 17512: file: id:000001,src:000002,op:flip1,pos:45.  */
160       /* Prevent infinite loops re-reading beyond the end of the buffer.  */
161       fatal (_("ICE: getINT: Out of buffer space"));
162       return 0;
163     }
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       fatal (_("Unsupported read size: %d"), size);
186     }
187
188   *idx += size * 8;
189   return n;
190 }
191
192 static int
193 getBITS (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
206 static void
207 itheader (char *name, int icode)
208 {
209   printf ("\n%s 0x%02x\n", name, icode);
210 }
211
212 static int indent;
213
214 static void
215 p (void)
216 {
217   int i;
218
219   for (i = 0; i < indent; i++)
220     printf ("| ");
221
222   printf ("> ");
223 }
224
225 static void
226 tabout (void)
227 {
228   p ();
229 }
230
231 static void
232 pbarray (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
257 static void
258 sysroff_swap_tr_in (void)
259 {
260   unsigned char raw[255];
261
262   memset (raw, 0, 255);
263   fillup (raw);
264 }
265
266 static void
267 sysroff_print_tr_out (void)
268 {
269   itheader ("tr", IT_tr_CODE);
270 }
271
272 static int
273 getone (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
504 static int
505 opt (int x)
506 {
507   return getone (x);
508 }
509
510 static void
511 must (int x)
512 {
513   if (!getone (x))
514     printf (_("WANTED %x!!\n"), x);
515 }
516
517 static void
518 tab (int i, char *s)
519 {
520   indent += i;
521
522   if (s)
523     {
524       p ();
525       puts (s);
526     }
527 }
528
529 static void
530 dump_symbol_info (void)
531 {
532   tab (1, _("SYMBOL INFO"));
533
534   while (opt (IT_dsy_CODE))
535     {
536       if (opt (IT_dty_CODE))
537         {
538           must (IT_dbt_CODE);
539           derived_type ();
540           must (IT_dty_CODE);
541         }
542     }
543
544   tab (-1, "");
545 }
546
547 static void
548 derived_type (void)
549 {
550   tab (1, _("DERIVED TYPE"));
551
552   while (1)
553     {
554       if (opt (IT_dpp_CODE))
555         {
556           dump_symbol_info ();
557           must (IT_dpp_CODE);
558         }
559       else if (opt (IT_dfp_CODE))
560         {
561           dump_symbol_info ();
562           must (IT_dfp_CODE);
563         }
564       else if (opt (IT_den_CODE))
565         {
566           dump_symbol_info ();
567           must (IT_den_CODE);
568         }
569       else if (opt (IT_den_CODE))
570         {
571           dump_symbol_info ();
572           must (IT_den_CODE);
573         }
574       else if (opt (IT_dds_CODE))
575         {
576           dump_symbol_info ();
577           must (IT_dds_CODE);
578         }
579       else if (opt (IT_dar_CODE))
580         {
581         }
582       else if (opt (IT_dpt_CODE))
583         {
584         }
585       else if (opt (IT_dul_CODE))
586         {
587         }
588       else if (opt (IT_dse_CODE))
589         {
590         }
591       else if (opt (IT_dot_CODE))
592         {
593         }
594       else
595         break;
596     }
597
598   tab (-1, "");
599 }
600
601 static void
602 module (void)
603 {
604   int c = 0;
605   int l = 0;
606
607   tab (1, _("MODULE***\n"));
608
609   do
610     {
611       c = getc (file);
612       if (c == EOF)
613         break;
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
636 char *program_name;
637
638 ATTRIBUTE_NORETURN static void
639 show_usage (FILE *ffile, int status)
640 {
641   fprintf (ffile, _("Usage: %s [option(s)] in-file\n"), program_name);
642   fprintf (ffile, _("Print a human readable interpretation of a SYSROFF object file\n"));
643   fprintf (ffile, _(" The options are:\n\
644   -h --help        Display this information\n\
645   -v --version     Print the program's version number\n"));
646
647   if (REPORT_BUGS_TO[0] && status == 0)
648     fprintf (ffile, _("Report bugs to %s\n"), REPORT_BUGS_TO);
649   exit (status);
650 }
651
652 int
653 main (int ac, char **av)
654 {
655   char *input_file = NULL;
656   int option;
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   bfd_set_error_program_name (program_name);
676
677   expandargv (&ac, &av);
678
679   while ((option = getopt_long (ac, av, "HhVv", long_options, (int *) NULL)) != EOF)
680     {
681       switch (option)
682         {
683         case 'H':
684         case 'h':
685           show_usage (stdout, 0);
686           /*NOTREACHED*/
687         case 'v':
688         case 'V':
689           print_version ("sysdump");
690           exit (0);
691           /*NOTREACHED*/
692         case 0:
693           break;
694         default:
695           show_usage (stderr, 1);
696           /*NOTREACHED*/
697         }
698     }
699
700   /* The input and output files may be named on the command line.  */
701
702   if (optind < ac)
703     input_file = av[optind];
704
705   if (!input_file)
706     fatal (_("no input file specified"));
707
708   file = fopen (input_file, FOPEN_RB);
709
710   if (!file)
711     fatal (_("cannot open input file %s"), input_file);
712
713   module ();
714   return 0;
715 }