home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / dumphunks-1.0-src.tgz / tar.out / contrib / dumphunks / dumphunks.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  12KB  |  565 lines

  1. /*
  2.  *    A quick and dirty program to dump the contents of an
  3.  *    AmigaOS format object file or executable file in a
  4.  *    human readable form, for people doing maintenance on
  5.  *    tools that generate or read such formats.
  6.  *
  7.  *    Fred Fish, March 1995
  8.  *
  9.  *    FIXME:    Use macros to access data in endian independant
  10.  *        manner so can be used in cross environment.
  11.  *
  12.  */
  13.  
  14.  
  15. #include <stdio.h>
  16.  
  17. int code_flag;            /* Don't dump code hunk */
  18. int data_flag;            /* Don't dump data hunk */
  19. int debug_flag;            /* Don't dump debug hunks */
  20. int reloc_flag;            /* Don't dump reloc hunks */
  21. int symbol_flag;        /* Don't dump symbol hunks */
  22. int error_flag;            /* Set if error occurs */
  23.  
  24. char *filename;            /* Name of current input file */
  25. int hunkcount;
  26.  
  27. #ifdef __STDC__
  28. #  define PARAMS(a) a
  29. #else
  30. #  define PARAMS(a) ()
  31. #endif
  32.  
  33. static void dump_file PARAMS ((FILE *fp));
  34. static long readlong PARAMS ((FILE *fp));
  35. static void dump_hunk_header PARAMS ((FILE *fp));
  36. static void dump_string PARAMS ((FILE *fp, long count, int suppress));
  37. static void dump_hunk PARAMS ((FILE *fp, long hunkid));
  38. static void dump_counted_data PARAMS ((FILE *fp, long count, char* desc, int suppress));
  39. static void dump_reloc_hunk PARAMS ((FILE *fp));
  40. static void dump_symbols PARAMS ((FILE *fp));
  41. static void dump_hunk_bss PARAMS ((FILE *fp));
  42. static void dump_debug PARAMS ((FILE *fp));
  43. static void dump_hunk_unit PARAMS ((FILE *fp));
  44. static void dump_hunk_name PARAMS ((FILE *fp));
  45.  
  46. #define EMIT_OFFSET(fp) printf ("%8.8x: ", ftell (fp) - sizeof (long))
  47. #define EMIT_VALUE(fp, val) EMIT_OFFSET (fp); printf ("%8.8x ", val)
  48.  
  49. #define HUNK_UNIT    0x03e7
  50. #define HUNK_NAME    0x03e8
  51. #define HUNK_CODE    0x03e9
  52. #define HUNK_DATA    0x03ea
  53. #define HUNK_BSS     0x03eb
  54. #define HUNK_RELOC32 0x03ec
  55. #define HUNK_RELOC16 0x03ed
  56. #define HUNK_RELOC8  0x03ee
  57. #define HUNK_EXT     0x03ef
  58. #define HUNK_SYMBOL  0x03f0
  59. #define HUNK_DEBUG   0x03f1
  60. #define HUNK_END     0x03f2
  61. #define HUNK_HEADER  0x03f3
  62. #define HUNK_OVERLAY 0x03f5
  63. #define HUNK_BREAK   0x03f6
  64.  
  65. #define SYMBOL_HUNK_TERMINATOR 0
  66.  
  67. #define EXT_SYMB     0x00
  68. #define EXT_DEF      0x01
  69. #define EXT_ABS      0x02
  70. #define EXT_RES         0x03
  71. #define EXT_REF32    0x81
  72. #define EXT_COMMON   0x82
  73. #define EXT_REF16    0x83
  74. #define EXT_REF8     0x84
  75. #define EXT_SASC86   0x86
  76.  
  77. int main (argc, argv)
  78. int argc;
  79. char *argv[];
  80. {
  81.   int ch;
  82.   FILE *fp;
  83.   extern int optind;
  84.   extern char *optarg;
  85.  
  86.   /* Process all command line arguments. */
  87.  
  88.   while ((ch = getopt (argc, argv, "cdDhr")) != EOF)
  89.     {
  90.       switch (ch)
  91.     {
  92.     case 'c':
  93.       code_flag++;
  94.       break;
  95.     case 'd':
  96.       data_flag++;
  97.       break;
  98.         case 'D':
  99.       debug_flag++;
  100.       break;
  101.     case 'h':
  102.       code_flag++;
  103.       data_flag++;
  104.       debug_flag++;
  105.       reloc_flag++;
  106.       symbol_flag++;
  107.       break;
  108.     case 'r':
  109.       reloc_flag++;
  110.       break;
  111.     case 's':
  112.       symbol_flag++;
  113.       break;
  114.     case '?':
  115.       error_flag++;
  116.       break;
  117.     }
  118.     }
  119.  
  120.   /* If error during command line argument parsing, give
  121.      usage message and exit with error. */
  122.  
  123.   if (error_flag)
  124.     {
  125.       fflush (stdout);
  126.       fprintf (stderr, "usage: dumphunks [-cdDhr] <filetodump\n");
  127.       exit (1);
  128.     }
  129.  
  130.   /* If there are arguments remaining on the command line, they
  131.      are filenames to process, so process each one.  Otherwise,
  132.      process stdin. */
  133.  
  134.   if (optind < argc)
  135.     {
  136.       for (; optind < argc; optind++)
  137.     {
  138.       filename = argv[optind];
  139.       fp = fopen (filename, "r");
  140.       if (fp != NULL)
  141.         {
  142.           dump_file (fp);
  143.         }
  144.       else
  145.         {
  146.           fprintf (stderr, "dumphunks: %s: can't open for read: ",
  147.                filename);
  148.           perror ("");
  149.         }
  150.     }
  151.     }
  152.   else
  153.     {
  154.       filename = "<stdin>";
  155.       dump_file (stdin);
  156.     }
  157.  
  158.   /* All done, return success. */
  159.  
  160.   return (0);
  161. }
  162.  
  163. /*
  164.  *    Dump the file.  The first hunk has to be a HUNK_HEADER
  165.  *    or HUNK_UNIT type hunk.  Simply loop, dumping each
  166.  *    hunk's contents.
  167.  */
  168.  
  169. static void dump_file (fp)
  170. FILE *fp;
  171. {
  172.   long HunkID;
  173.  
  174.   printf ("Dump of '%s':\n\n", filename);
  175.   HunkID = readlong (fp);
  176.   if ((HunkID != HUNK_HEADER) && (HunkID != HUNK_UNIT))
  177.     {
  178.       fflush (stdout);
  179.       fprintf (stderr, "dumphunks: %s: not correct format\n", filename);
  180.       exit (1);
  181.     }
  182.   do
  183.     {
  184.       dump_hunk (fp, HunkID);
  185.       if (hunkcount > 0)
  186.     {
  187.       HunkID = readlong (fp);
  188.     }
  189.     } while (hunkcount > 0);
  190. }
  191.  
  192. static void dump_hunk (fp, HunkID)
  193. FILE *fp;
  194. long HunkID;
  195. {
  196.   EMIT_VALUE (fp, HunkID);
  197.   switch (HunkID)
  198.     {
  199.     case HUNK_UNIT:
  200.       printf ("HUNK_UNIT\n");
  201.       dump_hunk_unit (fp);
  202.       break;
  203.     case HUNK_NAME:
  204.       printf ("HUNK_NAME\n");
  205.       dump_hunk_name (fp);
  206.       break;
  207.     case HUNK_CODE:
  208.       printf ("HUNK_CODE\n");
  209.       dump_counted_data (fp, 0, "code", code_flag);
  210.       break;
  211.     case HUNK_DATA:
  212.       printf ("HUNK_DATA\n");
  213.       dump_counted_data (fp, 0, "data", data_flag);
  214.       break;
  215.     case HUNK_BSS:
  216.       printf ("HUNK_BSS\n");
  217.       dump_hunk_bss (fp);
  218.       break;
  219.     case HUNK_RELOC32:
  220.       printf ("HUNK_RELOC32\n");
  221.       dump_reloc_hunk (fp);
  222.       break;
  223.     case HUNK_RELOC16:
  224.       printf ("HUNK_RELOC16\n");
  225.       dump_reloc_hunk (fp);
  226.       break;
  227.     case HUNK_RELOC8:
  228.       printf ("HUNK_RELOC8\n");
  229.       dump_reloc_hunk (fp);
  230.       break;
  231.     case HUNK_EXT:
  232.       printf ("HUNK_EXT\n");
  233.       dump_symbols (fp); 
  234.       break;
  235.     case HUNK_SYMBOL:
  236.       printf ("HUNK_SYMBOL\n");
  237.       dump_symbols (fp); 
  238.       break;
  239.     case HUNK_DEBUG:
  240.       printf ("HUNK_DEBUG\n");
  241.       dump_debug (fp); 
  242.       break;
  243.     case HUNK_END:
  244.       printf ("HUNK_END\n");
  245.       hunkcount--;
  246.       break;
  247.     case HUNK_HEADER:
  248.       printf ("HUNK_HEADER\n");
  249.       dump_hunk_header (fp);
  250.       break;
  251.     case HUNK_OVERLAY:
  252.       printf ("HUNK_OVERLAY\n");
  253.       fflush (stdout);
  254.       fprintf (stderr, "can't handle HUNK_OVERLAY yet\n");
  255.       exit (1);
  256.       break;
  257.     case HUNK_BREAK:
  258.       printf ("HUNK_BREAK\n");
  259.       fflush (stdout);
  260.       fprintf (stderr, "can't handle HUNK_BREAK yet\n");
  261.       exit (1);
  262.       break;
  263.     default:
  264.       fflush (stdout);
  265.       fprintf (stderr, "unrecognized hunk id %x\n", HunkID);
  266.       exit (1);
  267.     }
  268. }
  269.  
  270. static void dump_hunk_header (fp)
  271. FILE *fp;
  272. {
  273.   long val;
  274.   long tablesize;
  275.   int index;
  276.  
  277.   while ((val = readlong (fp)) != 0)
  278.     {
  279.       EMIT_VALUE (fp, val);
  280.       printf ("Number of longwords of name\n");
  281.       dump_string (fp, val, 0);
  282.     }
  283.   EMIT_VALUE (fp, val);
  284.   printf ("Name list terminator\n");
  285.  
  286.   hunkcount = tablesize = readlong (fp);
  287.   EMIT_VALUE (fp, tablesize);
  288.   printf ("Table size\n");
  289.  
  290.   val = readlong (fp);
  291.   EMIT_VALUE (fp, val);
  292.   printf ("First Hunk F\n");
  293.  
  294.   val = readlong (fp);
  295.   EMIT_VALUE (fp, val);
  296.   printf ("Last Hunk L\n");
  297.  
  298.   for (index = 0; index < tablesize; index++)
  299.     {
  300.       val = readlong (fp);
  301.       EMIT_VALUE (fp, val);
  302.       printf ("Hunk[%d] size (%d)\n", index, val);
  303.     }
  304. }
  305.  
  306.  
  307. static long readlong (fp)
  308. FILE *fp;
  309. {
  310.   long temp;
  311.   char buf [256];
  312.  
  313.   if (fread ((char *) &temp, sizeof (temp), 1, fp) != 1)
  314.     {
  315.       sprintf (buf, "dumphunks: can't read data at %x", ftell (fp));
  316.       perror (buf);
  317.       exit (1);
  318.     }
  319.   return (temp);
  320. }
  321.  
  322. static void dump_string (fp, count, suppress)
  323. FILE *fp;
  324. long count;
  325. int suppress;
  326. {
  327.   union {
  328.     long longval;
  329.     char buf[4];
  330.   } val;
  331.   int chi;
  332.  
  333.   for (; count > 0; count--)
  334.     {
  335.       val.longval = readlong (fp);
  336.       if (!suppress)
  337.     {
  338.       EMIT_VALUE (fp, val);
  339.       for (chi = 0; chi < 4; chi++)
  340.         {
  341.           if (isprint (val.buf[chi]))
  342.         {
  343.           printf ("'%c' ", val.buf[chi]);
  344.         }
  345.           else
  346.         {
  347.           printf ("'\\%3.3o' ", val.buf[chi]);
  348.         }
  349.         }
  350.       printf ("\n");
  351.     }
  352.     }
  353. }
  354.  
  355. static void dump_counted_data (fp, count, desc, suppress)
  356. FILE *fp;
  357. long count;
  358. char *desc;
  359. int suppress;
  360. {
  361.   long val;
  362.   int index;
  363.  
  364.   if (count == 0)
  365.     {
  366.       count = readlong (fp);
  367.       if (!suppress)
  368.     {
  369.       EMIT_VALUE (fp, count);
  370.       printf ("Number of longwords of %s\n", desc);
  371.     }
  372.     }
  373.  
  374.   for (index = 0; index < count; index++)
  375.     {
  376.       val = readlong (fp);
  377.       if (!suppress)
  378.     {
  379.       if ((index % 8) == 0)
  380.         {
  381.           if (index > 0)
  382.         {
  383.           printf ("\n");
  384.         }
  385.           EMIT_OFFSET (fp);
  386.         }
  387.       printf ("%8.8x ", val);
  388.     }
  389.     }
  390.   if (!suppress)
  391.     {
  392.       printf ("\n");
  393.     }
  394. }
  395.  
  396. static void dump_reloc_hunk (fp)
  397. FILE *fp;
  398. {
  399.   long count;
  400.   long val;
  401.   int index;
  402.  
  403.   while ((val = readlong (fp)) != 0)
  404.     {
  405.       count = val;
  406.       EMIT_VALUE (fp, count);
  407.       printf ("Number of relocations (%d)\n", count);
  408.  
  409.       val = readlong (fp);
  410.       EMIT_VALUE (fp, val);
  411.       printf ("Relocate relative to hunk %d\n", val);
  412.  
  413.       /* FIXME:  Dump relocations in human readable form. */
  414.       dump_counted_data (fp, count, "relocation data", reloc_flag);
  415.     }
  416.   EMIT_VALUE (fp, val);
  417.   printf ("Reloc hunk terminator\n");
  418. }
  419.  
  420. static void dump_symbols (fp)
  421. FILE *fp;
  422. {
  423.   long val;
  424.   int namelength;
  425.   int symtype;
  426.   int count;
  427.   int index;
  428.   unsigned long symcount = 0;
  429.  
  430.   while ((val = readlong (fp)) != SYMBOL_HUNK_TERMINATOR)
  431.     {
  432.       symcount++;
  433.       /* First longword is type in upper byte and name length
  434.      (in longwords) in lower 3 bytes. */
  435.       namelength = val & 0xFFFFFF;
  436.       symtype = (val >> 24) & 0xFF;
  437.       if (!symbol_flag)
  438.     {
  439.       EMIT_VALUE (fp, val);
  440.       switch (symtype)
  441.         {
  442.         case EXT_SYMB:
  443.           printf ("EXT_SYMB");
  444.           break;
  445.         case EXT_DEF:
  446.           printf ("EXT_DEF");
  447.           break;
  448.         case EXT_ABS:
  449.           printf ("EXT_ABS");
  450.           break;
  451.         case EXT_RES:
  452.           printf ("EXT_RES");
  453.           break;
  454.         case EXT_REF32:
  455.           printf ("EXT_REF32");
  456.           break;
  457.         case EXT_COMMON:
  458.           printf ("EXT_COMMON");
  459.           break;
  460.         case EXT_REF16:
  461.           printf ("EXT_REF16");
  462.           break;
  463.         case EXT_REF8:
  464.           printf ("EXT_REF8");
  465.           break;
  466.         case EXT_SASC86:
  467.           printf ("EXT_SASC86");
  468.           break;
  469.         default:
  470.           fflush (stdout);
  471.           fprintf (stderr, "dumphunks: unknown symbol type %x\n", symtype);
  472.           exit (1);
  473.         }
  474.       printf ("; %d longwords of symbol name\n", namelength);
  475.     }
  476.       dump_string (fp, namelength, symbol_flag);
  477.       switch (symtype)
  478.     {
  479.     case EXT_SYMB:
  480.     case EXT_DEF:
  481.     case EXT_ABS:
  482.     case EXT_RES:
  483.       val = readlong (fp);
  484.       if (!symbol_flag)
  485.         {
  486.           EMIT_VALUE (fp, val);
  487.           printf ("Symbol value\n");
  488.         }
  489.       break;
  490.     case EXT_COMMON:
  491.       val = readlong (fp);
  492.       if (!symbol_flag)
  493.         {
  494.           EMIT_VALUE (fp, val);
  495.           printf ("Size of common block\n");
  496.         }
  497.       /* FALL THROUGH */
  498.     case EXT_REF32:
  499.     case EXT_REF16:
  500.     case EXT_REF8:
  501.       count = readlong (fp);
  502.       for (index = 0; index < count; index++)
  503.         {
  504.           val = readlong (fp);
  505.           if (!symbol_flag)
  506.         {
  507.           EMIT_VALUE (fp, val);
  508.           printf ("Symbol reference %d\n", index);
  509.         }
  510.         }
  511.       break;
  512.     case EXT_SASC86:
  513.       dump_counted_data (fp, 2, "sasc86", symbol_flag);
  514.       break;
  515.     }
  516.     }
  517.   EMIT_VALUE (fp, val);
  518.   printf ("Symbol hunk terminator (%lu symbols)\n", symcount);
  519. }
  520.  
  521. static void dump_hunk_bss (fp)
  522. FILE *fp;
  523. {
  524.   long val;
  525.  
  526.   val = readlong (fp);
  527.   EMIT_VALUE (fp, val);
  528.   printf ("Size of BSS block in longwords\n");
  529. }
  530.  
  531. static void dump_debug (fp)
  532. FILE *fp;
  533. {
  534.   long val;
  535.  
  536.   val = readlong (fp);
  537.   EMIT_VALUE (fp, val);
  538.   printf ("%d longwords of debugging data\n", val);
  539.   /* FIXME:  Dump in human readable form. */
  540.   dump_counted_data (fp, val, "debugging data", debug_flag);
  541. }
  542.  
  543. static void dump_hunk_unit (fp)
  544. FILE *fp;
  545. {
  546.   long val;
  547.  
  548.   hunkcount++;
  549.   val = readlong (fp);
  550.   EMIT_VALUE (fp, val);
  551.   printf ("%d longwords of hunk unit name\n");
  552.   dump_string (fp, val, 0);
  553. }
  554.  
  555. static void dump_hunk_name (fp)
  556. FILE *fp;
  557. {
  558.   long val;
  559.  
  560.   val = readlong (fp);
  561.   EMIT_VALUE (fp, val);
  562.   printf ("%d longwords of hunk name\n");
  563.   dump_string (fp, val, 0);
  564. }
  565.