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