/* Sysroff object format dumper. Copyright (C) 1994-2024 Free Software Foundation, Inc. This file is part of GNU Binutils. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Steve Chamberlain <sac@cygnus.com>. This program reads a SYSROFF object file and prints it in an almost human readable form to stdout. */ #include "sysdep.h" #include "bfd.h" #include "safe-ctype.h" #include "libiberty.h" #include "getopt.h" #include "bucomm.h" #include "sysroff.h" static int dump = 1; static int segmented_p; static int code; static int addrsize = 4; static FILE *file; static void derived_type (void); static char * getCHARS (unsigned char *ptr, int *idx, int size, int max) { int oc = *idx / 8; char *r; int b = size; if (b >= max) return _("*undefined*"); if (b == 0) { /* PR 17512: file: 13caced2. */ if (oc >= max) return _("*corrupt*"); /* Got to work out the length of the string from self. */ b = ptr[oc++]; (*idx) += 8; } if (oc + b > size) { /* PR 28564 */ return _("*corrupt*"); } *idx += b * 8; r = xcalloc (b + 1, 1); memcpy (r, ptr + oc, b); r[b] = 0; return r; } static void dh (unsigned char *ptr, int size) { int i; int j; int span = 16; printf ("\n************************************************************\n"); for (i = 0; i < size; i += span) { for (j = 0; j < span; j++) { if (j + i < size) printf ("%02x ", ptr[i + j]); else printf (" "); } for (j = 0; j < span && j + i < size; j++) { int c = ptr[i + j]; if (c < 32 || c > 127) c = '.'; printf ("%c", c); } printf ("\n"); } } static int fillup (unsigned char *ptr) { int size; int sum; int i; size = getc (file); if (size == EOF || size <= 2) return 0; size -= 2; if (fread (ptr, size, 1, file) != 1) return 0; sum = code + size + 2; for (i = 0; i < size; i++) sum += ptr[i]; if ((sum & 0xff) != 0xff) printf (_("SUM IS %x\n"), sum); if (dump) dh (ptr, size); return size; } static barray getBARRAY (unsigned char *ptr, int *idx, int dsize ATTRIBUTE_UNUSED, int max) { barray res; int i; int byte = *idx / 8; int size = 0; if (byte < max) size = ptr[byte++]; res.len = size; res.data = (unsigned char *) xmalloc (size); for (i = 0; i < size; i++) res.data[i] = byte < max ? ptr[byte++] : 0; return res; } static int getINT (unsigned char *ptr, int *idx, int size, int max) { int n = 0; int byte = *idx / 8; if (byte >= max) { /* PR 17512: file: id:000001,src:000002,op:flip1,pos:45. */ /* Prevent infinite loops re-reading beyond the end of the buffer. */ fatal (_("ICE: getINT: Out of buffer space")); return 0; } if (size == -2) size = addrsize; if (size == -1) size = 0; switch (size) { case 0: return 0; case 1: n = (ptr[byte]); break; case 2: n = (ptr[byte + 0] << 8) + ptr[byte + 1]; break; case 4: n = (((unsigned) ptr[byte + 0] << 24) + (ptr[byte + 1] << 16) + (ptr[byte + 2] << 8) + (ptr[byte + 3])); break; default: fatal (_("Unsupported read size: %d"), size); } *idx += size * 8; return n; } static int getBITS (unsigned char *ptr, int *idx, int size, int max) { int byte = *idx / 8; int bit = *idx % 8; if (byte >= max) return 0; *idx += size; return (ptr[byte] >> (8 - bit - size)) & ((1 << size) - 1); } static void itheader (char *name, int icode) { printf ("\n%s 0x%02x\n", name, icode); } static int indent; static void p (void) { int i; for (i = 0; i < indent; i++) printf ("| "); printf ("> "); } static void tabout (void) { p (); } static void pbarray (barray *y) { int x; printf ("%d (", y->len); for (x = 0; x < y->len; x++) printf ("(%02x %c)", y->data[x], ISPRINT (y->data[x]) ? y->data[x] : '.'); printf (")\n"); } #define SYSROFF_PRINT #define SYSROFF_SWAP_IN #include "sysroff.c" /* FIXME: sysinfo, which generates sysroff.[ch] from sysroff.info, can't hack the special case of the tr block, which has no contents. So we implement our own functions for reading in and printing out the tr block. */ #define IT_tr_CODE 0x7f static void sysroff_swap_tr_in (void) { unsigned char raw[255]; memset (raw, 0, 255); fillup (raw); } static void sysroff_print_tr_out (void) { itheader ("tr", IT_tr_CODE); } static int getone (int type) { int c = getc (file); code = c; if ((c & 0x7f) != type) { ungetc (c, file); return 0; } switch (c & 0x7f) { case IT_cs_CODE: { struct IT_cs dummy; sysroff_swap_cs_in (&dummy); sysroff_print_cs_out (&dummy); } break; case IT_dln_CODE: { struct IT_dln dummy; sysroff_swap_dln_in (&dummy); sysroff_print_dln_out (&dummy); } break; case IT_hd_CODE: { struct IT_hd dummy; sysroff_swap_hd_in (&dummy); addrsize = dummy.afl; sysroff_print_hd_out (&dummy); } break; case IT_dar_CODE: { struct IT_dar dummy; sysroff_swap_dar_in (&dummy); sysroff_print_dar_out (&dummy); } break; case IT_dsy_CODE: { struct IT_dsy dummy; sysroff_swap_dsy_in (&dummy); sysroff_print_dsy_out (&dummy); } break; case IT_dfp_CODE: { struct IT_dfp dummy; sysroff_swap_dfp_in (&dummy); sysroff_print_dfp_out (&dummy); } break; case IT_dso_CODE: { struct IT_dso dummy; sysroff_swap_dso_in (&dummy); sysroff_print_dso_out (&dummy); } break; case IT_dpt_CODE: { struct IT_dpt dummy; sysroff_swap_dpt_in (&dummy); sysroff_print_dpt_out (&dummy); } break; case IT_den_CODE: { struct IT_den dummy; sysroff_swap_den_in (&dummy); sysroff_print_den_out (&dummy); } break; case IT_dbt_CODE: { struct IT_dbt dummy; sysroff_swap_dbt_in (&dummy); sysroff_print_dbt_out (&dummy); } break; case IT_dty_CODE: { struct IT_dty dummy; sysroff_swap_dty_in (&dummy); sysroff_print_dty_out (&dummy); } break; case IT_un_CODE: { struct IT_un dummy; sysroff_swap_un_in (&dummy); sysroff_print_un_out (&dummy); } break; case IT_sc_CODE: { struct IT_sc dummy; sysroff_swap_sc_in (&dummy); sysroff_print_sc_out (&dummy); } break; case IT_er_CODE: { struct IT_er dummy; sysroff_swap_er_in (&dummy); sysroff_print_er_out (&dummy); } break; case IT_ed_CODE: { struct IT_ed dummy; sysroff_swap_ed_in (&dummy); sysroff_print_ed_out (&dummy); } break; case IT_sh_CODE: { struct IT_sh dummy; sysroff_swap_sh_in (&dummy); sysroff_print_sh_out (&dummy); } break; case IT_ob_CODE: { struct IT_ob dummy; sysroff_swap_ob_in (&dummy); sysroff_print_ob_out (&dummy); } break; case IT_rl_CODE: { struct IT_rl dummy; sysroff_swap_rl_in (&dummy); sysroff_print_rl_out (&dummy); } break; case IT_du_CODE: { struct IT_du dummy; sysroff_swap_du_in (&dummy); sysroff_print_du_out (&dummy); } break; case IT_dus_CODE: { struct IT_dus dummy; sysroff_swap_dus_in (&dummy); sysroff_print_dus_out (&dummy); } break; case IT_dul_CODE: { struct IT_dul dummy; sysroff_swap_dul_in (&dummy); sysroff_print_dul_out (&dummy); } break; case IT_dss_CODE: { struct IT_dss dummy; sysroff_swap_dss_in (&dummy); sysroff_print_dss_out (&dummy); } break; case IT_hs_CODE: { struct IT_hs dummy; sysroff_swap_hs_in (&dummy); sysroff_print_hs_out (&dummy); } break; case IT_dps_CODE: { struct IT_dps dummy; sysroff_swap_dps_in (&dummy); sysroff_print_dps_out (&dummy); } break; case IT_tr_CODE: sysroff_swap_tr_in (); sysroff_print_tr_out (); break; case IT_dds_CODE: { struct IT_dds dummy; sysroff_swap_dds_in (&dummy); sysroff_print_dds_out (&dummy); } break; default: printf (_("GOT A %x\n"), c); return 0; break; } return 1; } static int opt (int x) { return getone (x); } static void must (int x) { if (!getone (x)) printf (_("WANTED %x!!\n"), x); } static void tab (int i, char *s) { indent += i; if (s) { p (); puts (s); } } static void dump_symbol_info (void) { tab (1, _("SYMBOL INFO")); while (opt (IT_dsy_CODE)) { if (opt (IT_dty_CODE)) { must (IT_dbt_CODE); derived_type (); must (IT_dty_CODE); } } tab (-1, ""); } static void derived_type (void) { tab (1, _("DERIVED TYPE")); while (1) { if (opt (IT_dpp_CODE)) { dump_symbol_info (); must (IT_dpp_CODE); } else if (opt (IT_dfp_CODE)) { dump_symbol_info (); must (IT_dfp_CODE); } else if (opt (IT_den_CODE)) { dump_symbol_info (); must (IT_den_CODE); } else if (opt (IT_den_CODE)) { dump_symbol_info (); must (IT_den_CODE); } else if (opt (IT_dds_CODE)) { dump_symbol_info (); must (IT_dds_CODE); } else if (opt (IT_dar_CODE)) { } else if (opt (IT_dpt_CODE)) { } else if (opt (IT_dul_CODE)) { } else if (opt (IT_dse_CODE)) { } else if (opt (IT_dot_CODE)) { } else break; } tab (-1, ""); } static void module (void) { int c = 0; int l = 0; tab (1, _("MODULE***\n")); do { c = getc (file); if (c == EOF) break; ungetc (c, file); c &= 0x7f; } while (getone (c) && c != IT_tr_CODE); tab (-1, ""); c = getc (file); while (c != EOF) { printf ("%02x ", c); l++; if (l == 32) { printf ("\n"); l = 0; } c = getc (file); } } ATTRIBUTE_NORETURN static void show_usage (FILE *ffile, int status) { fprintf (ffile, _("Usage: %s [option(s)] in-file\n"), program_name); fprintf (ffile, _("Print a human readable interpretation of a SYSROFF object file\n")); fprintf (ffile, _(" The options are:\n\ -h --help Display this information\n\ -v --version Print the program's version number\n")); if (REPORT_BUGS_TO[0] && status == 0) fprintf (ffile, _("Report bugs to %s\n"), REPORT_BUGS_TO); exit (status); } int main (int ac, char **av) { char *input_file = NULL; int option; static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {NULL, no_argument, 0, 0} }; #ifdef HAVE_LC_MESSAGES setlocale (LC_MESSAGES, ""); #endif setlocale (LC_CTYPE, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); program_name = av[0]; xmalloc_set_program_name (program_name); bfd_set_error_program_name (program_name); expandargv (&ac, &av); while ((option = getopt_long (ac, av, "HhVv", long_options, (int *) NULL)) != EOF) { switch (option) { case 'H': case 'h': show_usage (stdout, 0); /*NOTREACHED*/ case 'v': case 'V': print_version ("sysdump"); exit (0); /*NOTREACHED*/ case 0: break; default: show_usage (stderr, 1); /*NOTREACHED*/ } } /* The input and output files may be named on the command line. */ if (optind < ac) input_file = av[optind]; if (!input_file) fatal (_("no input file specified")); file = fopen (input_file, FOPEN_RB); if (!file) fatal (_("cannot open input file %s"), input_file); module (); return 0; }