home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.pdx.edu / 2014.02.ftp.ee.pdx.edu.tar / ftp.ee.pdx.edu / pub / users / Harry / Blitz / version-1-0 / Beta / dumpObj.c < prev    next >
C/C++ Source or Header  |  2007-09-04  |  14KB  |  548 lines

  1. /* Program to dump a BLITZ ".o" or "a.out" file
  2. **
  3. ** Copyright 2000-2007, Harry H. Porter III
  4. **
  5. ** This file may be freely copied, modified and compiled, on the sole
  6. ** condition that if you modify it...
  7. **   (1) Your name and the date of modification is added to this comment
  8. **       under "Modifications by", and
  9. **   (2) Your name and the date of modification is added to the printHelp()
  10. **       routine under "Modifications by".
  11. **
  12. ** Original Author:
  13. **   11/12/00 - Harry H. Porter III
  14. **
  15. ** Modifcations by:
  16. **   03/15/06 - Harry H. Porter III
  17. **   04/30/07 - Harry H. Porter III - Support for little endian added
  18. **
  19. */
  20.  
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <stdarg.h>
  24. #include <string.h>
  25.  
  26.  
  27. /* SWAP_BYTES (int)  -->  int
  28. **
  29. ** This macro is used to swap the bytes in a 32-bit int from Big Endian order
  30. ** to Little Endian order, or vice-versa.
  31. **
  32. ** For example:
  33. **     i = SWAP_BYTES (i);
  34. **
  35. ** This program was originally written for a Big Endian architecture so swapping
  36. ** bytes was never necessary.  When compiled on a Big Endian computer, this macro
  37. ** is a no-op; when compiled on a Little Endian machine, it will swap the bytes.
  38. **
  39. */
  40. #ifdef BLITZ_HOST_IS_LITTLE_ENDIAN
  41. #define SWAP_BYTES(x) \
  42.     ((int)((((int)(x) & 0xff000000) >> 24) | \
  43.            (((int)(x) & 0x00ff0000) >>  8) | \
  44.            (((int)(x) & 0x0000ff00) <<  8) | \
  45.            (((int)(x) & 0x000000ff) << 24)))
  46. #else
  47. #define SWAP_BYTES(x) (x)
  48. #endif
  49.  
  50.  
  51.  
  52. /*****  Global variables *****/
  53.  
  54. char * commandInFileName = NULL; /* The input filename, if provided */
  55. FILE * inputFile;                /* The input file */
  56. int textSize;
  57. int dataSize;
  58. int bssSize;
  59. int textAddr;
  60. int dataAddr;
  61. int bssAddr;
  62. int count;
  63. int row [16];
  64. int size;
  65. int symbolNum;
  66. int locationToUpdate;
  67. int value;
  68. int relativeTo;
  69. int len;
  70.  
  71.  
  72.  
  73. /* Function prototypes */
  74.  
  75. void processCommandLine (int argc, char ** argv);
  76. void printHelp ();
  77. int readInteger ();
  78. int readByte ();
  79. void printSegment (int startingAddr);
  80. void readline ();
  81. int getNext ();
  82. void putlong (int i);
  83. void printline ();
  84. void putbyt (int c);
  85. void fatalError (char * msg);
  86.  
  87.  
  88.  
  89. /* main()
  90. **
  91. ** Read and print .o file.
  92. */
  93. main (int argc, char ** argv) {
  94.     int i, lineNumber;
  95.     int magic;
  96.     int sawEntryLabel;
  97.     processCommandLine (argc, argv);
  98.     printf ("=====  HEADER INFO  =====\n\n");
  99.     magic = readInteger ();
  100.     if (magic == 0x424C5A6F) {
  101.       printf ("magic number = BLZo (This is a '.o' file.)\n");
  102.     } else if (magic == 0x424C5A78) {
  103.       printf ("magic number = BLZx (This is an 'a.out' file.)\n");
  104.     } else {
  105.       fatalError ("Magic number is not 'BLZo' or 'BLZx'");
  106.     }
  107.     if (magic == 0x424C5A78) {   /* if we have an a.out file... */
  108.       textSize = readInteger ();
  109.       dataSize = readInteger ();
  110.       bssSize = readInteger ();
  111.       printf (".text size = %08x (%d)\n", textSize, textSize);
  112.       printf (".data size = %08x (%d)\n", dataSize, dataSize);
  113.       printf (".bss size =  %08x (%d)\n", bssSize, bssSize);
  114.       textAddr = readInteger ();
  115.       dataAddr = readInteger ();
  116.       bssAddr = readInteger ();
  117.       printf (".text load addr = %08x (%d)\n", textAddr, textAddr);
  118.       printf (".data load addr = %08x (%d)\n", dataAddr, dataAddr);
  119.       printf (".bss load addr =  %08x (%d)\n", bssAddr, bssAddr);
  120.       magic = readInteger ();
  121.       if (magic != 0x2a2a2a2a) {
  122.         fatalError ("Invalid file format - missing \"****\" separator");
  123.       }
  124.       printf ("\n=====  TEXT SEGMENT  =====\n\n");
  125.       count = textSize;
  126.       printSegment (textAddr);
  127.       magic = readInteger ();
  128.       if (magic != 0x2a2a2a2a) {
  129.         fatalError ("Invalid file format - missing \"****\" separator");
  130.       }
  131.       printf ("\n=====  DATA SEGMENT  =====\n\n");
  132.       count = dataSize;
  133.       printSegment (dataAddr);
  134.       magic = readInteger ();
  135.       if (magic != 0x2a2a2a2a) {
  136.         fatalError ("Invalid file format - missing \"****\" separator");
  137.       }
  138.       printf ("\n=====  LABEL INFORMATION  =====\n\n");
  139.       printf ("Value   (in decimal)  Label\n");
  140.       printf ("====================  ==================\n");
  141.       while (1) {
  142.         len = readInteger ();
  143.         if (len <= 0) break;
  144.         value = readInteger ();
  145.         printf ("%08x%12d  ", value, value);
  146.         for (; len>0; len--) {
  147.           i = readByte ();
  148.           printf ("%c", i);
  149.         }
  150.         printf ("\n");
  151.       }
  152.   
  153.       magic = readInteger ();
  154.       if (magic != 0x2a2a2a2a) {
  155.         fatalError ("Invalid file format - missing \"****\" separator");
  156.       }
  157.   
  158.     } else {   /* if we have an .o file... */
  159.       sawEntryLabel = readInteger ();
  160.       if (sawEntryLabel == 1) {
  161.         printf (".text contains _entry = TRUE\n");
  162.       } else if (sawEntryLabel == 0) {
  163.         printf (".text contains _entry = FALSE\n");
  164.       } else {
  165.         fatalError ("sawEntryLabel has invalid value");
  166.       }
  167.       textSize = readInteger ();
  168.       dataSize = readInteger ();
  169.       bssSize = readInteger ();
  170.       printf (".text size = %08x (%d)\n", textSize, textSize);
  171.       printf (".data size = %08x (%d)\n", dataSize, dataSize);
  172.       printf (".bss size =  %08x (%d)\n", bssSize, bssSize);
  173.       printf ("\n=====  TEXT SEGMENT  =====\n\n");
  174.       count = textSize;
  175.       printSegment (0);
  176.       magic = readInteger ();
  177.       if (magic != 0x2a2a2a2a) {
  178.         fatalError ("Invalid file format - missing \"****\" separator");
  179.       }
  180.       printf ("\n=====  DATA SEGMENT  =====\n\n");
  181.       count = dataSize;
  182.       printSegment (0);
  183.   
  184.       magic = readInteger ();
  185.       if (magic != 0x2a2a2a2a) {
  186.         fatalError ("Invalid file format - missing \"****\" separator");
  187.       }
  188.   
  189.       printf ("\n=====  SYMBOL TABLE  =====\n\n");
  190.       printf ("Number  Value     Relative to   Symbol\n");
  191.       printf ("======  ========  ===========   ======\n");
  192.       while (1) {
  193.         symbolNum = readInteger ();
  194.         if (symbolNum == 0) break;
  195.         value = readInteger ();
  196.         relativeTo = readInteger ();
  197.         len = readInteger ();
  198.         printf ("%d\t%08x\t%d\t", symbolNum, value, relativeTo);
  199.         for (; len>0; len--) {
  200.           i = readByte ();
  201.           printf ("%c", i);
  202.         }
  203.         printf ("\n");
  204.       }
  205.   
  206.       magic = readInteger ();
  207.       if (magic != 0x2a2a2a2a) {
  208.         fatalError ("Invalid file format - missing \"****\" separator");
  209.       }
  210.   
  211.       printf ("\n=====  RELOCATION INFO  =====\n\n");
  212.       printf ("Type    Locatn-to-modify New-val  Rel-to Src-Line\n");
  213.       printf ("======= ================ ======== ====== ========\n");
  214.       while (1) {
  215.         i = readInteger ();
  216.         if (i == 0) {
  217.           break;
  218.         } else if (i == 1) {
  219.           printf ("8-bit\t");
  220.         } else if (i == 2) {
  221.           printf ("16-bit\t");
  222.         } else if (i == 3) {
  223.           printf ("24-bit\t");
  224.         } else if (i == 4) {
  225.           printf ("32-bit\t");
  226.         } else if (i == 5) {
  227.           printf ("set-hi\t");
  228.         } else if (i == 6) {
  229.           printf ("set-lo\t");
  230.         } else if (i == 7) {
  231.           printf ("ldaddr\t");
  232.         } else {
  233.           fatalError ("Invalid relocation record code");
  234.         }
  235.         value = readInteger ();
  236.         printf ("%08x ", value);
  237.         i = readInteger ();
  238.         if (i == 1) {
  239.           printf (".text\t");
  240.         } else if (i == 2) {
  241.           printf (".data\t");
  242.         } else {
  243.           printf ("*****\t");
  244.         }
  245.         value = readInteger ();
  246.         printf (" %08x ", value);
  247.         value = readInteger ();
  248.         printf ("%4d   ", value);
  249.         lineNumber = readInteger ();
  250.         printf ("%6d  \n", lineNumber);
  251.       }
  252.       magic = readInteger ();
  253.       if (magic != 0x2a2a2a2a) {
  254.         fatalError ("Invalid file format - missing \"****\" separator");
  255.       }
  256.   
  257.       printf ("\n=====  ADDRESS LABELS  =====\n\n");
  258.       printf ("Segment Offset    Label\n");
  259.       printf ("======= ========  =====\n");
  260.       while (1) {
  261.         i = readInteger ();
  262.         if (i == 0) break;
  263.         if (i == 1) printf (".text\t");
  264.         if (i == 2) printf (".data\t");
  265.         if (i == 3) printf (".bss\t");
  266.         value = readInteger ();
  267.         len = readInteger ();
  268.         printf ("%08x  ", value);
  269.         for (; len>0; len--) {
  270.           i = readByte ();
  271.           printf ("%c", i);
  272.         }
  273.         printf ("\n");
  274.       }
  275.   
  276.       magic = readInteger ();
  277.       if (magic != 0x2a2a2a2a) {
  278.         fatalError ("Invalid file format - missing \"****\" separator");
  279.       }
  280.     }
  281. }
  282.  
  283.  
  284.  
  285. /* processCommandLine (argc, argv)
  286. **
  287. ** This routine processes the command line options.
  288. */
  289. void processCommandLine (int argc, char ** argv) {
  290.   int argCount;
  291.   int len;
  292.   for (argc--, argv++; argc > 0; argc -= argCount, argv += argCount) {
  293.     argCount = 1;
  294.     /* Scan the -h option */
  295.     if (!strcmp (*argv, "-h")) {
  296.       printHelp ();
  297.       exit (1);
  298.     /* Scan an input file name */
  299.     } else if ((*argv)[0] != '-') {
  300.       if (commandInFileName == NULL) {
  301.         commandInFileName = *argv;
  302.       } else {
  303.         fprintf (stderr,
  304.           "dumpObj: Invalid command line;  Multiple input files;  Use -h for help display\n");
  305.         exit (1);
  306.       }
  307.     } else {
  308.       fprintf (stderr,
  309.         "dumpObj: Invalid command line option (%s);  Use -h for help display\n",
  310.         *argv);
  311.       exit (1);
  312.     }
  313.   }
  314.  
  315.   /* Open the input (.o) file */
  316.   if (commandInFileName == NULL) {
  317.     inputFile = stdin;
  318.   } else {
  319.     inputFile = fopen (commandInFileName, "r");
  320.     if (inputFile == NULL) {
  321.       fprintf (stderr,
  322.           "dumpObj: Input file \"%s\" could not be opened\n", commandInFileName);
  323.       exit (1);
  324.     }
  325.   }
  326. }
  327.  
  328.  
  329.  
  330. /* printHelp ()
  331. **
  332. ** This routine prints some documentation.  It is invoked whenever
  333. ** the -h option is used on the command line.
  334. */
  335. void printHelp () {
  336.   printf (
  337. "================================================\n"
  338. "=====                                      =====\n"
  339. "=====  The BLITZ Object File Dump Program  =====\n"
  340. "=====                                      =====\n"
  341. "================================================\n"
  342. "\n"
  343. "Copyright 2000-2007, Harry H. Porter III\n"
  344. "========================================\n"
  345. "  Original Author:\n"
  346. "    11/12/00 - Harry H. Porter III\n"
  347. "  Modifcations by:\n"
  348. "    03/15/06 - Harry H. Porter III\n"
  349. "    04/30/07 - Harry H. Porter III - Support for little endian added\n"
  350. "\n"
  351. "Overview\n"
  352. "========\n"
  353. "  This program prints out a BLITZ \".o\" or \"a.out\" file in human-readable\n"
  354. "  form.  This program does some (very limited) error checking on the file.\n"
  355. "\n"
  356. "Command Line Options\n"
  357. "====================\n"
  358. "  Command line options may be given in any order.\n"
  359. "    -h\n"
  360. "      Print this info.  The input source is ignored.\n"
  361. "    filename\n"
  362. "      The input source will come from this file.  (This file should be a\n"
  363. "      \".o\" or \"a.out\" file.)  If an input file is not named on the command\n"
  364. "      line, the source must come from stdin.  Only one input source is allowed.\n");
  365. }
  366.  
  367.  
  368.  
  369. /* readInteger ()
  370. **
  371. ** Read and return an integer.
  372. */
  373. int readInteger () {
  374.   int i, numBytesRead;
  375.   numBytesRead = fread (&i, 4, 1, inputFile);
  376.   if (numBytesRead != 1) {
  377.     fatalError ("Problem reading from input file");
  378.   }
  379.   return SWAP_BYTES (i);
  380. }
  381.  
  382.  
  383.  
  384. /* readByte ()
  385. **
  386. ** Read 1 byte and return an integer.
  387. */
  388. int readByte () {
  389.   int i, numBytesRead;
  390.   char c;
  391.   numBytesRead = fread (&c, 1, 1, inputFile);
  392.   if (numBytesRead != 1) {
  393.     fatalError ("Problem reading from input file");
  394.   }
  395.   i = c;
  396.   return i;
  397. }
  398.  
  399.  
  400.  
  401. /* printSegment (startingAddr)
  402. **
  403. ** This routine reads raw bytes from the input file and prints them
  404. ** out in a formatted way like this:
  405. **
  406. ** 00002000: 0000 0000 0000 0000 0000 0000 0000 0000   ................
  407. ** 00002010: 6162 6364 6566 6768 3400 0000 696A 6B6C   abcdefgh4...ijkl
  408. ** 00002020: 6D6E 6F70 7172 7374 7576 7778 797A 0000   mnopqrstuvwxyz..
  409. **
  410. ** It is passed the starting address; in this example it was 0x0000200.
  411. */
  412. void printSegment (int startingAddr) {
  413.    int addr;
  414.  
  415.    /* Each execution of this loop prints a single output line. */
  416.    addr = startingAddr;
  417.    readline ();
  418.    while (size > 0) {
  419.      putlong (addr);
  420.      printf (":  ");
  421.      printline ();
  422.      addr = addr + 16;
  423.      readline ();
  424.    }
  425.  
  426. }
  427.  
  428.  
  429.  
  430. /* readline ()
  431. **
  432. ** This routine reads in the next 16 bytes from the file and
  433. ** places them in the array named 'row', setting 'size' to
  434. ** be the number of bytes read in.  Size will be less than
  435. ** 16 if EOF was encountered, and may possibly be 0.
  436. */
  437. void readline () {
  438.   int c;
  439.   size = 0;
  440.   c = getNext ();
  441.   while (c != -999) {
  442.     row [size] = c;
  443.     size = size + 1;
  444.     if (size >= 16) break;
  445.     c = getNext ();
  446.   }
  447. }
  448.  
  449.  
  450.  
  451. /* getNext ()
  452. **
  453. ** Read next char, decrementing count.  Return it, or -999 if count <= 0.
  454. */
  455. int getNext () {
  456.   if (count <= 0) return -999;
  457.   count--;
  458.   return readByte();
  459. }
  460.  
  461.  
  462.  
  463. /* putlong ()
  464. **
  465. ** This routine is passed an integer, which it displays as 8 hex digits.
  466. */
  467. void putlong (int i) {
  468.   putbyt ((i>>24) & 0x000000ff);
  469.   putbyt ((i>>16) & 0x000000ff);
  470.   putbyt ((i>>8) & 0x000000ff);
  471.   putbyt ((i>>0) & 0x000000ff);
  472. }
  473.  
  474.  
  475.  
  476. /* printline ()
  477. **
  478. ** This routine prints the current 'row'.
  479. */
  480. void printline () {
  481.   int i, c;
  482.   if (size > 0) {
  483.     i = 0;
  484.     while (i<16) {
  485.       if (i < size) {
  486.         putbyt (row[i]);
  487.       } else {
  488.         printf ("  ");
  489.       }
  490.       i++;
  491.       if ((i%2) == 0) {
  492.         putchar (' ');
  493.       }
  494.       if ((i%4) == 0) {
  495.         putchar (' ');
  496.       }
  497.     }
  498.     printf ("  ");
  499.     for (i=0; i<size; i++) {
  500.       c = row[i];
  501.       if ((c>=' ') && (c <= '~')) {
  502.         putchar (c);
  503.       } else {
  504.         putchar ('.');
  505.       }
  506.     }
  507.     printf ("\n");
  508.   }
  509. }
  510.  
  511.  
  512.  
  513. /* putbyt ()
  514. **
  515. ** This routine is passed a byte (i.e., an integer -128..255) which
  516. ** it displays as 2 hex characters.  If passed a number out of that
  517. ** range, it outputs nothing.
  518. */
  519. void putbyt (int c) {
  520.   int i;
  521.   if (c<0) c = c + 256;
  522.   if ((c >= 0) && (c <= 255)) {
  523.     i = (c & 0x000000f0) >> 4;
  524.     if (i < 10) {
  525.       putchar ('0' + i);
  526.     } else {
  527.       putchar ('A' + i - 10);
  528.     }
  529.     i = (c & 0x0000000f) >> 0;
  530.     if (i < 10) {
  531.       putchar ('0' + i);
  532.     } else {
  533.       putchar ('A' + i - 10);
  534.     }
  535.   }
  536. }
  537.  
  538.  
  539.  
  540. /* fatalError (msg)
  541. **
  542. ** Print this message and abort.
  543. */
  544. void fatalError (char * msg) {
  545.   printf ("\n*****  ERROR: %s  *****\n", msg);
  546.   exit (1);
  547. }
  548.