home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / emxtutor.zip / emxsrcd1.zip / emx / src / emxomf / listomf.c < prev    next >
C/C++ Source or Header  |  1998-12-19  |  58KB  |  2,381 lines

  1. /* listomf.c -- List OMF files (.obj and .lib files)
  2.    Copyright (c) 1993-1998 Eberhard Mattes
  3.  
  4. This file is part of listomf.
  5.  
  6. listomf 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 2, or (at your option)
  9. any later version.
  10.  
  11. listomf 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 listomf; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 59 Temple Place - Suite 330,
  19. Boston, MA 02111-1307, USA.  */
  20.  
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #ifdef __EMX__
  26. #include <io.h>
  27. #endif /* __EMX__ */
  28. #include <getopt.h>
  29. #include "defs.h"
  30.  
  31. #define VERSION "0.9d"
  32.  
  33. #pragma pack(1)
  34.  
  35. struct timestamp
  36. {
  37.   byte hours;
  38.   byte minutes;
  39.   byte seconds;
  40.   byte hundredths;
  41.   byte day;
  42.   byte month;
  43.   word year;
  44. };
  45.  
  46. #pragma pack()
  47.  
  48. struct segment
  49. {
  50.   int name;
  51.   int class;
  52.   dword length;
  53. };
  54.  
  55. struct group
  56. {
  57.   int name;
  58. };
  59.  
  60. struct ext
  61. {
  62.   char *name;
  63. };
  64.  
  65. enum debug
  66. {
  67.   debug_default,
  68.   debug_cv,
  69.   debug_hll
  70. };
  71.  
  72.  
  73. static int lname_count;
  74. static int lname_alloc;
  75. static char **lname_list;
  76. static int segment_count;
  77. static int segment_alloc;
  78. static struct segment *segment_list;
  79. static int group_count;
  80. static int group_alloc;
  81. static struct group *group_list;
  82. static int ext_count;
  83. static int ext_alloc;
  84. static struct ext *ext_list;
  85. static int pub_count;
  86. static int debug_type_index;
  87. static int done;
  88. static int rec_type;
  89. static int rec_len;
  90. static int rec_idx;
  91. static long rec_pos;
  92. static byte rec_buf[MAX_REC_SIZE+8];
  93. static enum debug debug_info;
  94. static int hll_style;
  95. static word line_count;
  96. static dword names_length;
  97. static int linnum_started;
  98. static byte linnum_entry_type;
  99. static word page_size;
  100. static word dict_blocks;
  101. static dword dict_offset;
  102.  
  103. static char list_debug = TRUE;
  104. static char show_addr = FALSE;
  105.  
  106.  
  107. static void out_of_mem (void)
  108. {
  109.   fputs ("Out of memory\n", stderr);
  110.   exit (2);
  111. }
  112.  
  113.  
  114. static void *xmalloc (size_t n)
  115. {
  116.   void *p;
  117.  
  118.   p = malloc (n);
  119.   if (p == NULL)
  120.     out_of_mem ();
  121.   return p;
  122. }
  123.  
  124.  
  125. static void *xrealloc (void *src, size_t n)
  126. {
  127.   void *p;
  128.  
  129.   p = realloc (src, n);
  130.   if (p == NULL)
  131.     out_of_mem ();
  132.   return p;
  133. }
  134.  
  135.  
  136. static char *xstrdup (const char *src)
  137. {
  138.   char *p;
  139.  
  140.   p = strdup (src);
  141.   if (p == NULL)
  142.     out_of_mem ();
  143.   return p;
  144. }
  145.  
  146.  
  147. static void show_record (const char *name)
  148. {
  149.   if (show_addr)
  150.     printf ("%ld: %s", rec_pos, name);
  151.   else
  152.     printf ("%s", name);
  153.   if (rec_type & REC32)
  154.     printf ("32");
  155. }
  156.  
  157.  
  158. static void get_mem (void *dst, int len)
  159. {
  160.   if (rec_idx + len > rec_len)
  161.     {
  162.       fprintf (stderr, "\nString at %d beyond end of record\n", rec_idx);
  163.       exit (2);
  164.     }
  165.   memcpy (dst, rec_buf + rec_idx, len);
  166.   rec_idx += len;
  167. }
  168.  
  169.  
  170. static void get_string (byte *dst)
  171. {
  172.   int len;
  173.  
  174.   if (rec_idx >= rec_len)
  175.     {
  176.       fprintf (stderr, "\nString at %d beyond end of record\n", rec_idx);
  177.       exit (2);
  178.     }
  179.   len = rec_buf[rec_idx++];
  180.   get_mem (dst, len);
  181.   dst[len] = 0;
  182. }
  183.  
  184.  
  185. static byte *get_cpp_string (void)
  186. {
  187.   int len;
  188.   byte *p;
  189.  
  190.   if (rec_idx >= rec_len)
  191.     {
  192.       fprintf (stderr, "\nString at %d beyond end of record\n", rec_idx);
  193.       exit (2);
  194.     }
  195.   len = rec_buf[rec_idx++];
  196.   if (len & 0x80)
  197.     len = ((len & 0x7f) << 8) + rec_buf[rec_idx++];
  198.   p = xmalloc (len + 1);
  199.   get_mem (p, len);
  200.   p[len] = 0;
  201.   return p;
  202. }
  203.  
  204.  
  205. static int get_index (void)
  206. {
  207.   int result;
  208.  
  209.   if (rec_idx >= rec_len)
  210.     {
  211.       fprintf (stderr, "\nIndex at %d beyond end of record\n", rec_idx);
  212.       exit (2);
  213.     }
  214.   result = rec_buf[rec_idx++];
  215.   if (result & 0x80)
  216.     {
  217.       if (rec_idx >= rec_len)
  218.         {
  219.           fprintf (stderr, "\nIndex at %d beyond end of record\n", rec_idx);
  220.           exit (2);
  221.         }
  222.       result = ((result & 0x7f) << 8) | rec_buf[rec_idx++];
  223.     }
  224.   return result;
  225. }
  226.  
  227.  
  228. static dword get_dword (void)
  229. {
  230.   dword result;
  231.  
  232.   if (rec_idx + 4 > rec_len)
  233.     {
  234.       fprintf (stderr, "\nDword at %d beyond end of record\n", rec_idx);
  235.       exit (2);
  236.     }
  237.   result = rec_buf[rec_idx++];
  238.   result |= rec_buf[rec_idx++] << 8;
  239.   result |= rec_buf[rec_idx++] << 16;
  240.   result |= rec_buf[rec_idx++] << 24;
  241.   return result;
  242. }
  243.  
  244.  
  245. static word get_word (void)
  246. {
  247.   word result;
  248.  
  249.   if (rec_idx + 2 > rec_len)
  250.     {
  251.       fprintf (stderr, "\nWord at %d beyond end of record\n", rec_idx);
  252.       exit (2);
  253.     }
  254.   result = rec_buf[rec_idx++];
  255.   result |= rec_buf[rec_idx++] << 8;
  256.   return result;
  257. }
  258.  
  259.  
  260. static word get_byte (void)
  261. {
  262.   if (rec_idx + 1 > rec_len)
  263.     {
  264.       fprintf (stderr, "\nByte at %d beyond end of record\n", rec_idx);
  265.       exit (2);
  266.     }
  267.   return rec_buf[rec_idx++];
  268. }
  269.  
  270.  
  271. static dword get_word_or_dword (void)
  272. {
  273.   return (rec_type & REC32 ? get_dword () : get_word ());
  274. }
  275.  
  276.  
  277. static dword get_commlen (void)
  278. {
  279.   dword result;
  280.  
  281.   result = get_byte ();
  282.   if (result <= 0x80)
  283.     return result;
  284.   switch (result)
  285.     {
  286.     case 0x81:
  287.       return get_word ();
  288.     case 0x84:
  289.       result = get_byte ();
  290.       result |= get_byte () << 8;
  291.       result |= get_byte () << 16;
  292.       return result;
  293.     case 0x88:
  294.       return get_dword ();
  295.     default:
  296.       fprintf (stderr, "\nUnknown COMDAT length prefix\n");
  297.       exit (2);
  298.     }
  299. }
  300.  
  301.  
  302. static void show_char (byte c)
  303. {
  304.   if (c == '\\')
  305.     printf ("\\\\");
  306.   else if (c < 0x20 || c > 0x7f)
  307.     printf ("\\%.3o", c);
  308.   else
  309.     putchar (c);
  310. }
  311.  
  312.  
  313. static void show_string (const byte *p)
  314. {
  315.   printf ("\"");
  316.   while (*p != 0)
  317.     show_char (*p++);
  318.   printf ("\"");
  319. }
  320.  
  321.  
  322. static void show_name (int index)
  323. {
  324.   if (index < 1 || index > lname_count)
  325.     printf ("#%d", index);
  326.   else
  327.     show_string (lname_list[index-1]);
  328. }
  329.  
  330.  
  331. static void show_seg (int index)
  332. {
  333.   if (index < 1 || index > segment_count)
  334.     printf ("#%d", index);
  335.   else
  336.     show_name (segment_list[index-1].name);
  337. }
  338.  
  339.  
  340. static void show_group (int index)
  341. {
  342.   if (index < 1 || index > group_count)
  343.     printf ("#%d", index);
  344.   else
  345.     show_name (group_list[index-1].name);
  346. }
  347.  
  348.  
  349. static void show_ext (int index)
  350. {
  351.   if (index < 1 || index > ext_count)
  352.     printf ("#%d", index);
  353.   else
  354.     show_string (ext_list[index-1].name);
  355. }
  356.  
  357.  
  358. static void show_enc (void)
  359. {
  360.   byte *p;
  361.  
  362.   p = get_cpp_string ();
  363.   show_string (p);
  364.   free (p);
  365. }
  366.  
  367.  
  368. static void dump_block (int count, int indent)
  369. {
  370.   int x;
  371.  
  372.   x = 0;
  373.   while (rec_idx < rec_len && count > 0)
  374.     {
  375.       --count;
  376.       if (x >= 16)
  377.         {
  378.           printf ("\n");
  379.           x = 0;
  380.         }
  381.       if (x == 0)
  382.         printf ("%*s", indent, "");
  383.       printf (" %.2x", rec_buf[rec_idx++]);
  384.       ++x;
  385.     }
  386.   if (x != 0)
  387.     printf ("\n");
  388. }
  389.  
  390.  
  391. static void dump_rest (void)
  392. {
  393.   dump_block (rec_len - rec_idx, 2);
  394. }
  395.  
  396.  
  397. static void add_ext (const byte *name)
  398. {
  399.   if (ext_count >= ext_alloc)
  400.     {
  401.       ext_alloc += 16;
  402.       ext_list = xrealloc (ext_list, ext_alloc * sizeof (*ext_list));
  403.     }
  404.   ext_list[ext_count++].name = xstrdup (name);
  405. }
  406.  
  407.  
  408. static void list_libhdr (void)
  409. {
  410.   byte flags;
  411.  
  412.   printf ("LIBHDR:\n");
  413.   page_size = rec_len + 1 + 3;
  414.   printf ("  Page size: %u\n", page_size);
  415.   dict_offset = get_dword ();
  416.   printf ("  Dictionary offset: 0x%lx\n", dict_offset);
  417.   dict_blocks = get_word ();
  418.   printf ("  Dictionary blocks: %u\n", dict_blocks);
  419.   flags = get_byte ();
  420.   printf ("  Flags: 0x%.2x", flags);
  421.   if (flags & 0x01)
  422.     printf (" (case-sensitive)");
  423.   printf ("\n");
  424. }
  425.  
  426.  
  427. static void list_theadr (void)
  428. {
  429.   byte string[256];
  430.  
  431.   if (page_size != 0)
  432.     printf ("------------------------------------------------------------\n");
  433.   show_record ("THEADR");
  434.   printf (" ");
  435.   get_string (string);
  436.   show_string (string);
  437.   printf ("\n");
  438.   lname_count = 0; segment_count = 0; group_count = 0;
  439.   ext_count = 0; pub_count = 0;
  440.   debug_type_index = 512;
  441.   debug_info = debug_default; hll_style = 0; linnum_started = FALSE;
  442. }
  443.  
  444.  
  445. static void list_coment (void)
  446. {
  447.   byte string[256], string2[256], string3[256];
  448.   byte flag, rec, subrec, c1, c2;
  449.   word ord = 0;
  450.   int len, ext1, ext2;
  451.  
  452.   show_record ("COMENT");
  453.   printf (": ");
  454.   get_byte ();                  /* Comment type */
  455.   rec = get_byte ();
  456.   switch (rec)
  457.     {
  458.     case 0x9e:
  459.       printf ("DOSSEG\n");
  460.       break;
  461.  
  462.     case 0x9f:
  463.       len = rec_len - rec_idx;
  464.       get_mem (string, len);
  465.       string[len] = 0;
  466.       printf ("Default library: ");
  467.       show_string (string);
  468.       break;
  469.  
  470.     case 0xa0:
  471.       subrec = get_byte ();
  472.       switch (subrec)
  473.         {
  474.         case 0x01:
  475.           printf ("IMPDEF ");
  476.           flag = get_byte ();
  477.           get_string (string);
  478.           get_string (string2);
  479.           if (flag != 0)
  480.             {
  481.               ord = get_word ();
  482.               printf ("%s %s.%u", string, string2, ord);
  483.             }
  484.           else
  485.             {
  486.               get_string (string3);
  487.               if (string3[0] == 0)
  488.                 strcpy (string3, string);
  489.               printf ("%s %s.%s", string, string2, string3);
  490.             }
  491.           break;
  492.  
  493.         case 0x02:
  494.           printf ("EXPDEF ");
  495.           flag = get_byte ();
  496.           get_string (string);
  497.           get_string (string2);
  498.           if (flag & 0x80)
  499.             ord = get_word ();
  500.           show_string (string);
  501.           printf (" (");
  502.           show_string (string2);
  503.           printf (")");
  504.           if (flag & 0x80)
  505.             printf (" @%u", ord);
  506.           if (flag & 0x40)
  507.             printf (", resident");
  508.           if (flag & 0x20)
  509.             printf (", no data");
  510.           if (flag & 0x1f)
  511.             printf (", %u parameters", flag & 0x1f);
  512.           break;
  513.  
  514.         case 0x04:
  515.           printf ("Protected DLL\n");
  516.           break;
  517.  
  518.         default:
  519.           printf ("unknown comment class: %.2x\n", (unsigned)subrec);
  520.           dump_rest ();
  521.           return;               /* Don't print a newline */
  522.         }
  523.       break;
  524.  
  525.     case 0xa1:
  526.       if (rec_idx + 3 > rec_len) /* Borland vs. IBM clash */
  527.         goto generic;
  528.       flag = get_byte ();
  529.       c1 = get_byte ();
  530.       c2 = get_byte ();
  531.       if (c1 == 'C' && c2 == 'V')
  532.         {
  533.           debug_info = debug_cv;
  534.           printf ("CodeView style (%u) debug tables", flag);
  535.         }
  536.       else if (c1 == 'H' && c2 == 'L')
  537.         {
  538.           debug_info = debug_hll;
  539.           hll_style = flag;
  540.           printf ("HLL style (%u) debug tables", flag);
  541.         }
  542.       else
  543.         printf ("New OMF extension");
  544.       break;
  545.  
  546.     case 0xa2:
  547.       flag = get_byte ();
  548.       if (flag == 1)
  549.         printf ("Link pass separator");
  550.       else
  551.         printf ("Unknown link pass: %.2x", flag);
  552.       break;
  553.  
  554.     case 0xa3:
  555.       get_string (string);
  556.       printf ("LIBMOD ");
  557.       show_string (string);
  558.       break;
  559.  
  560.     case 0xa8:
  561.       ext1 = get_index ();
  562.       ext2 = get_index ();
  563.       printf ("WKEXT ");
  564.       show_ext (ext1);
  565.       printf (" ");
  566.       show_ext (ext2);
  567.       break;
  568.  
  569.     case 0xaf:
  570.       get_string (string);
  571.       printf ("Identifier manipulator DLL: ");
  572.       show_string (string);
  573.       get_string (string);
  574.       printf (", initialization parameter: ");
  575.       show_string (string);
  576.       break;
  577.  
  578.     default:
  579. generic:
  580.       printf ("unknown comment class: %.2x\n", rec);
  581.       dump_rest ();
  582.       return;                   /* Don't print a newline */
  583.     }
  584.   printf ("\n");
  585. }
  586.  
  587.  
  588. static void list_lnames (void)
  589. {
  590.   byte string[256];
  591.  
  592.   show_record ("LNAMES");
  593.   printf (":\n");
  594.   while (rec_idx < rec_len)
  595.     {
  596.       get_string (string);
  597.       if (lname_count >= lname_alloc)
  598.         {
  599.           lname_alloc += 16;
  600.           lname_list = xrealloc (lname_list,
  601.                                  lname_alloc * sizeof (*lname_list));
  602.         }
  603.       lname_list[lname_count] = xstrdup (string);
  604.       ++lname_count;
  605.       printf ("  #%d: ", lname_count);
  606.       show_string (string);
  607.       printf ("\n");
  608.     }
  609. }
  610.  
  611.  
  612. static void list_segdef (void)
  613. {
  614.   int attributes, alignment, combination, frame, offset, name, class, overlay;
  615.   dword length;
  616.   struct segment *p;
  617.  
  618.   frame = 0;                    /* Keep the compiler happy */
  619.  
  620.   show_record ("SEGDEF");
  621.   printf (" #%d ", segment_count + 1);
  622.  
  623.   attributes = get_byte ();
  624.   alignment = attributes >> 5;
  625.   combination = (attributes >> 2) & 7;
  626.   if (alignment == 0)
  627.     {
  628.       frame = get_word ();
  629.       offset = get_byte ();
  630.     }
  631.   length = get_word_or_dword ();
  632.   name = get_index ();
  633.   class = get_index ();
  634.   overlay = get_index ();
  635.   if (!(rec_type & REC32) && (attributes & 2))
  636.     length = 1L << 16;
  637.  
  638.   if (segment_count >= segment_alloc)
  639.     {
  640.       segment_alloc += 8;
  641.       segment_list = xrealloc (segment_list,
  642.                                segment_alloc * sizeof (*segment_list));
  643.     }
  644.   p = &segment_list[segment_count++];
  645.   p->name = name;
  646.   p->class = class;
  647.   p->length = length;
  648.  
  649.   show_name (name);
  650.   printf ("  ");
  651.   switch (alignment)
  652.     {
  653.     case 0:
  654.       printf ("AT %#.4x", frame);
  655.       break;
  656.     case 1:
  657.       printf ("BYTE");
  658.       break;
  659.     case 2:
  660.       printf ("WORD");
  661.       break;
  662.     case 3:
  663.       printf ("PARA");
  664.       break;
  665.     case 4:
  666.       printf ("PAGE");
  667.       break;
  668.     case 5:
  669.       printf ("DWORD");
  670.       break;
  671.     case 6:
  672.       printf ("unknown alignment: %d", alignment);
  673.       break;
  674.     }
  675.   printf (" ");
  676.   switch (combination)
  677.     {
  678.     case 0:
  679.       printf ("PRIVATE");
  680.       break;
  681.     case 2:
  682.     case 4:
  683.     case 7:
  684.       printf ("PUBLIC");
  685.       break;
  686.     case 5:
  687.       printf ("STACK");
  688.       break;
  689.     case 6:
  690.       printf ("COMMON");
  691.       break;
  692.     default:
  693.       printf ("unknown combination: %d", combination);
  694.       break;
  695.     }
  696.   if (attributes & 1)
  697.     printf (" USE32");
  698.   printf (" Length: %#lx", length);
  699.   printf (" CLASS ");
  700.   show_name (class);
  701.   printf ("\n");
  702. }
  703.  
  704.  
  705. static void list_grpdef (void)
  706. {
  707.   int name, type, seg;
  708.  
  709.   show_record ("GRPDEF");
  710.   printf (" #%d ", group_count + 1);
  711.  
  712.   name = get_index ();
  713.   if (group_count >= group_alloc)
  714.     {
  715.       group_alloc += 8;
  716.       group_list = xrealloc (group_list,
  717.                              group_alloc * sizeof (*group_list));
  718.     }
  719.   group_list[group_count++].name = name;
  720.   show_name (name);
  721.   printf (":");
  722.   while (rec_idx < rec_len)
  723.     {
  724.       type = get_byte ();
  725.       if (type != 0xff)
  726.         printf (" [unknown type: %#x] ", type);
  727.       seg = get_index ();
  728.       printf (" ");
  729.       show_seg (seg);
  730.     }
  731.   printf ("\n");
  732. }
  733.  
  734.  
  735. static void list_extdef (void)
  736. {
  737.   int type;
  738.   byte name[256];
  739.  
  740.   show_record ("EXTDEF");
  741.   printf (":\n");
  742.  
  743.   while (rec_idx < rec_len)
  744.     {
  745.       printf ("  #%d: ", ext_count + 1);
  746.       get_string (name);
  747.       show_string (name);
  748.       type = get_index ();
  749.       printf (", type: %d\n", type);
  750.       add_ext (name);
  751.     }
  752. }
  753.  
  754.  
  755. static void list_pubdef (void)
  756. {
  757.   int type, group, seg;
  758.   dword offset;
  759.   byte name[256];
  760.  
  761.   show_record ("PUBDEF");
  762.   group = get_index ();
  763.   seg = get_index ();
  764.   printf (" base group: ");
  765.   show_group (group);
  766.   printf (", base seg: ");
  767.   show_seg (seg);
  768.   if (seg == 0)
  769.     printf (", frame=0x%.4x", get_word ());
  770.   printf ("\n");
  771.  
  772.   while (rec_idx < rec_len)
  773.     {
  774.       printf ("  #%d: ", pub_count + 1);
  775.       get_string (name);
  776.       show_string (name);
  777.       offset = get_word_or_dword ();
  778.       type = get_index ();
  779.       printf (", offset: %#lx, type: %d\n", offset, type);
  780.       ++pub_count;
  781.     }
  782. }
  783.  
  784.  
  785. static void list_comdef (void)
  786. {
  787.   int type_index, data_type;
  788.   byte name[256];
  789.   dword comm_len, comm_count;
  790.  
  791.   show_record ("COMDEF");
  792.   printf ("\n");
  793.   while (rec_idx < rec_len)
  794.     {
  795.       get_string (name);
  796.       type_index = get_index ();
  797.       data_type = get_byte ();
  798.       printf ("  #%d: ", ext_count + 1);
  799.       show_string (name);
  800.       printf (", type index: %d, ", type_index);
  801.       switch (data_type)
  802.         {
  803.         case 0x61:
  804.           comm_count = get_commlen ();
  805.           comm_len = get_commlen ();
  806.           printf ("FAR, %lu times %lu bytes\n", comm_count, comm_len);
  807.           break;
  808.         case 0x62:
  809.           comm_len = get_commlen ();
  810.           printf ("NEAR, %lu bytes\n", comm_len);
  811.           break;
  812.         default:
  813.           printf ("unknown data type: %#x\n", data_type);
  814.           dump_rest ();
  815.           return;
  816.         }
  817.       add_ext (name);
  818.     }
  819.   dump_rest ();
  820. }
  821.  
  822.  
  823. static void list_alias (void)
  824. {
  825.   byte name[256];
  826.  
  827.   show_record ("ALIAS");
  828.   printf (": ");
  829.   get_string (name);
  830.   show_string (name);
  831.   printf (" ");
  832.   get_string (name);
  833.   show_string (name);
  834.   printf ("\n");
  835.   dump_rest ();
  836. }
  837.  
  838.  
  839. static void list_symbols (void)
  840. {
  841.   int len, next, total_rec_len, sst, location, loc_base, start;
  842.   word seg, file;
  843.   dword offset, length, reg, line;
  844.   dword type, prologue, body, reserved, near_far, compiler_id, class_type;
  845.   byte name[256];
  846.   struct timestamp ts;
  847.  
  848.   total_rec_len = rec_len;
  849.   loc_base = rec_idx;
  850.   while (rec_idx < rec_len)
  851.     {
  852.       start = rec_idx;
  853.       len = get_byte ();
  854.       if (len == 0)
  855.         {
  856.           printf ("Length of SST entry is 0\n");
  857.           break;
  858.         }
  859.       --len;
  860.       sst = get_byte ();
  861.       next = rec_idx + len;
  862.       rec_len = next;
  863.       printf ("  ");
  864.       switch (sst)
  865.         {
  866.         case 0x00:
  867.           printf ("Begin ");
  868.           location = rec_idx - loc_base;
  869.           offset = get_dword ();
  870.           length = get_dword ();
  871.           printf ("offset: %#lx [@%#x], length: %#lx",
  872.                   offset, location, length);
  873.           if (rec_idx < rec_len)
  874.             {
  875.               get_string (name);
  876.               printf (" ");
  877.               show_string (name);
  878.             }
  879.           break;
  880.         case 0x01:
  881.         case 0x0f:
  882.         case 0x1a:
  883.         case 0x1d:
  884.           switch (sst)
  885.             {
  886.             case 0x01:
  887.               printf ("Proc ");
  888.               break;
  889.             case 0x0f:
  890.               printf ("Entry ");
  891.               break;
  892.             case 0x1a:
  893.               printf ("MemFunc ");
  894.               break;
  895.             case 0x1d:
  896.               printf ("C++Proc ");
  897.               break;
  898.             default:
  899.               abort ();
  900.             }
  901.           location = rec_idx - loc_base;
  902.           offset = get_dword ();
  903.           type = get_word ();
  904.           length = get_dword ();
  905.           prologue = get_word ();
  906.           body = get_dword ();
  907.           class_type = get_word ();
  908.           near_far = get_byte ();
  909.           if (sst == 0x1a || sst == 0x1d)
  910.             show_enc ();
  911.           else
  912.             {
  913.               get_string (name);
  914.               show_string (name);
  915.             }
  916.           printf (", offset: %#lx [@%#x], type: #%lu\n",
  917.                   offset, location, type);
  918.           printf ("       length: %#lx, pro: %#lx, pro+body: %#lx, ",
  919.                   length, prologue, body);
  920.           switch (near_far)
  921.             {
  922.             case 0x00:
  923.               printf ("16-bit near");
  924.               break;
  925.             case 0x04:
  926.               printf ("16-bit far");
  927.               break;
  928.             case 0x08:
  929.               printf ("32-bit near");
  930.               break;
  931.             case 0x0c:
  932.               printf ("32-bit far");
  933.               break;
  934.             default:
  935.               printf ("nf: %#lx", near_far);
  936.               break;
  937.             }
  938.           if (sst == 0x1a)      /* Member function */
  939.             printf ("\n       class type: #%lu", class_type);
  940.           break;
  941.         case 0x02:
  942.           printf ("End");
  943.           break;
  944.         case 0x04:
  945.           printf ("Auto ");
  946.           offset = get_dword ();
  947.           type = get_word ();
  948.           get_string (name);
  949.           show_string (name);
  950.           printf (", offset: %#lx, type: #%lu", offset, type);
  951.           break;
  952.         case 0x05:
  953.         case 0x1e:
  954.           if (sst == 0x1e)
  955.             printf ("C++Static ");
  956.           else
  957.             printf ("Static ");
  958.           location = rec_idx - loc_base;
  959.           offset = get_dword ();
  960.           seg = get_word ();
  961.           type = get_word ();
  962.           if (sst == 0x1e)
  963.             show_enc ();
  964.           else
  965.             {
  966.               get_string (name);
  967.               show_string (name);
  968.             }
  969.           printf (", offset: %#lx [@%#x], seg: %u [@%#x], type: #%lu",
  970.                   offset, location, seg, location + 4, type);
  971.           break;
  972.         case 0x0b:
  973.           printf ("CodeLabel ");
  974.           location = rec_idx - loc_base;
  975.           offset = get_dword ();
  976.           near_far = get_byte ();
  977.           get_string (name);
  978.           printf ("offset: %#lx [@%#x]", offset, location);
  979.           show_string (name);
  980.           break;
  981.         case 0x0c:
  982.           printf ("With");
  983.           break;
  984.         case 0x0d:
  985.           printf ("Reg ");
  986.           type = get_word ();
  987.           reg = get_byte ();
  988.           get_string (name);
  989.           show_string (name);
  990.           printf (", ");
  991.           switch (reg)
  992.             {
  993.             case 0x00:
  994.               printf ("AL");
  995.               break;
  996.             case 0x01:
  997.               printf ("CL");
  998.               break;
  999.             case 0x02:
  1000.               printf ("DL");
  1001.               break;
  1002.             case 0x03:
  1003.               printf ("BL");
  1004.               break;
  1005.             case 0x04:
  1006.               printf ("AH");
  1007.               break;
  1008.             case 0x05:
  1009.               printf ("CH");
  1010.               break;
  1011.             case 0x06:
  1012.               printf ("DH");
  1013.               break;
  1014.             case 0x07:
  1015.               printf ("BH");
  1016.               break;
  1017.             case 0x08:
  1018.               printf ("AX");
  1019.               break;
  1020.             case 0x09:
  1021.               printf ("CX");
  1022.               break;
  1023.             case 0x0a:
  1024.               printf ("DX");
  1025.               break;
  1026.             case 0x0b:
  1027.               printf ("BX");
  1028.               break;
  1029.             case 0x0c:
  1030.               printf ("SP");
  1031.               break;
  1032.             case 0x0d:
  1033.               printf ("BP");
  1034.               break;
  1035.             case 0x0e:
  1036.               printf ("SI");
  1037.               break;
  1038.             case 0x0f:
  1039.               printf ("DI");
  1040.               break;
  1041.             case 0x10:
  1042.               printf ("EAX");
  1043.               break;
  1044.             case 0x11:
  1045.               printf ("ECX");
  1046.               break;
  1047.             case 0x12:
  1048.               printf ("EDX");
  1049.               break;
  1050.             case 0x13:
  1051.               printf ("EBX");
  1052.               break;
  1053.             case 0x14:
  1054.               printf ("ESP");
  1055.               break;
  1056.             case 0x15:
  1057.               printf ("EBP");
  1058.               break;
  1059.             case 0x16:
  1060.               printf ("ESI");
  1061.               break;
  1062.             case 0x17:
  1063.               printf ("EDI");
  1064.               break;
  1065.             case 0x18:
  1066.               printf ("ES"); /* error in documentation */
  1067.               break;
  1068.             case 0x19:
  1069.               printf ("CS");
  1070.               break;
  1071.             case 0x1a:
  1072.               printf ("SS");
  1073.               break;
  1074.             case 0x1b:
  1075.               printf ("DS");
  1076.               break;
  1077.             case 0x1c:
  1078.               printf ("FS");
  1079.               break;
  1080.             case 0x1d:
  1081.               printf ("GS");
  1082.               break;
  1083.             case 0x20:
  1084.               printf ("DX:AX");
  1085.               break;
  1086.             case 0x21:
  1087.               printf ("ES:BX");
  1088.               break;
  1089.             case 0x22:
  1090.               printf ("IP");
  1091.               break;
  1092.             case 0x23:
  1093.               printf ("FLAGS");
  1094.               break;
  1095.             case 0x24:
  1096.               printf ("EFLAGS");
  1097.               break;
  1098.             case 0x80:
  1099.             case 0x81:
  1100.             case 0x82:
  1101.             case 0x83:
  1102.             case 0x84:
  1103.             case 0x85:
  1104.             case 0x86:
  1105.             case 0x87:
  1106.               printf ("ST(%lu)", reg - 0x80);
  1107.               break;
  1108.             default:
  1109.               printf ("unknown register: %#.2lx", reg);
  1110.             }
  1111.           break;
  1112.         case 0x0e:
  1113.           printf ("Constant");
  1114.           break;
  1115.         case 0x10:
  1116.           printf ("Skip");
  1117.           break;
  1118.         case 0x11:
  1119.           printf ("ChangSeg ");
  1120.           location = rec_idx - loc_base;
  1121.           seg = get_word ();
  1122.           reserved = get_word ();
  1123.           printf ("segment: %u [@%#x]", seg, location);
  1124.           printf (", reserved: %#lx", reserved);
  1125.           break;
  1126.         case 0x12:
  1127.           printf ("Typedef");
  1128.           break;
  1129.         case 0x13:
  1130.           printf ("Public");
  1131.           break;
  1132.         case 0x14:
  1133.           printf ("Member ");
  1134.           offset = get_dword ();
  1135.           printf ("offset: %#lx, name: ", offset);
  1136.           get_string (name);
  1137.           show_string (name);
  1138.           break;
  1139.         case 0x15:
  1140.           printf ("Based ");
  1141.           offset = get_dword ();
  1142.           type = get_word ();
  1143.           printf ("offset: %#lx, type: #%lu, name: ", offset, type);
  1144.           get_string (name);
  1145.           show_string (name);
  1146.           break;
  1147.         case 0x16:
  1148.           printf ("Tag ");
  1149.           type = get_word ();
  1150.           printf ("type: #%lu, name: ", type);
  1151.           get_string (name);
  1152.           show_string (name);
  1153.           break;
  1154.         case 0x17:
  1155.           printf ("Table");
  1156.           break;
  1157.         case 0x18:
  1158.           printf ("Map ");
  1159.           get_string (name);
  1160.           show_string (name);
  1161.           printf (" to external ");
  1162.           get_string (name);
  1163.           show_string (name);
  1164.           break;
  1165.         case 0x19:
  1166.           printf ("Class ");
  1167.           type = get_word ();
  1168.           printf ("type: #%lu, name: ", type);
  1169.           show_enc ();
  1170.           break;
  1171.         case 0x1b:
  1172.           printf ("AutoScoped ");
  1173.           offset = get_dword ();
  1174.           file = get_word ();
  1175.           line = get_dword ();
  1176.           type = get_word ();
  1177.           get_string (name);
  1178.           printf ("offset: %#lx, source file: %u, line: %lu, type: #%lu\n",
  1179.                   offset, file, line, type);
  1180.           printf ("    name: ");
  1181.           show_string (name);
  1182.           break;
  1183.         case 0x1c:
  1184.           printf ("StaticScoped ");
  1185.           offset = get_dword ();
  1186.           seg = get_word ();
  1187.           file = get_word ();
  1188.           line = get_dword ();
  1189.           type = get_word ();
  1190.           get_string (name);
  1191.           printf ("offset: %#lx, segment: %u, source file: %u, "
  1192.                   "line: %lu, type: %lu\n",
  1193.                   offset, seg, file, line, type);
  1194.           printf ("    name: ");
  1195.           show_string (name);
  1196.           break;
  1197.         case 0x40:
  1198.           printf ("CuInfo: ");
  1199.           compiler_id = get_byte ();
  1200.           switch (compiler_id)
  1201.             {
  1202.             case 0x01:
  1203.               printf ("C");
  1204.               break;
  1205.             case 0x02:
  1206.               printf ("C++");
  1207.               break;
  1208.             case 0x03:
  1209.               printf ("PL/X-86");
  1210.               break;
  1211.             case 0x04:
  1212.               printf ("PL/I");
  1213.               break;
  1214.             default:
  1215.               printf ("unknown compiler id: %#lx", compiler_id);
  1216.               break;
  1217.             }
  1218.           printf (", options: ");
  1219.           get_string (name);
  1220.           show_string (name);
  1221.           printf (", compiler date: ");
  1222.           get_string (name);
  1223.           show_string (name);
  1224.           printf ("\n    time stamp: ");
  1225.           get_mem (&ts, sizeof (ts));
  1226.           printf ("%d/%.2d/%.2d %.2d:%.2d:%.2d.%.2d",
  1227.                   ts.year, ts.month, ts.day, ts.hours,
  1228.                   ts.minutes, ts.seconds, ts.hundredths);
  1229.           break;
  1230.         default:
  1231.           printf ("unknown SST type %#.2x at %d", sst, start);
  1232.           break;
  1233.         }
  1234.       printf ("\n");
  1235.       rec_idx = next;
  1236.       rec_len = total_rec_len;
  1237.     }
  1238. }
  1239.  
  1240.  
  1241.  
  1242. static void show_fid (void)
  1243. {
  1244.   int fid, index, i;
  1245.   byte str[256];
  1246.   dword d;
  1247.  
  1248.   fid = get_byte ();
  1249.   switch (fid)
  1250.     {
  1251.     case 0x80:
  1252.       printf ("(nil)");
  1253.       break;
  1254.     case 0x81:
  1255.       printf ("void");
  1256.       break;
  1257.     case 0x82:
  1258.       get_string (str);
  1259.       show_string (str);
  1260.       break;
  1261.     case 0x83:
  1262.       index = get_word ();
  1263.       switch (index)
  1264.         {
  1265.         case 0x80:
  1266.           printf ("signed char");
  1267.           break;
  1268.         case 0x81:
  1269.           printf ("signed short");
  1270.           break;
  1271.         case 0x82:
  1272.           printf ("signed long");
  1273.           break;
  1274.         case 0x84:
  1275.           printf ("unsigned char");
  1276.           break;
  1277.         case 0x85:
  1278.           printf ("unsigned short");
  1279.           break;
  1280.         case 0x86:
  1281.           printf ("unsigned long");
  1282.           break;
  1283.         case 0x88:
  1284.           printf ("float");
  1285.           break;
  1286.         case 0x89:
  1287.           printf ("double");
  1288.           break;
  1289.         case 0x8a:
  1290.           printf ("long double");
  1291.           break;
  1292.         case 0x97:
  1293.           printf ("void");
  1294.           break;
  1295.         case 0xa0:
  1296.           printf ("signed char *");
  1297.           break;
  1298.         case 0xa1:
  1299.           printf ("signed short *");
  1300.           break;
  1301.         case 0xa2:
  1302.           printf ("signed long *");
  1303.           break;
  1304.         case 0xa4:
  1305.           printf ("signed char *");
  1306.           break;
  1307.         case 0xa5:
  1308.           printf ("signed short *");
  1309.           break;
  1310.         case 0xa6:
  1311.           printf ("signed long *");
  1312.           break;
  1313.         case 0xa8:
  1314.           printf ("float *");
  1315.           break;
  1316.         case 0xa9:
  1317.           printf ("double *");
  1318.           break;
  1319.         case 0xaa:
  1320.           printf ("long double *");
  1321.           break;
  1322.         case 0xb7:
  1323.           printf ("void *");
  1324.           break;
  1325.         default:
  1326.           printf ("#%d", index);
  1327.           break;
  1328.         }
  1329.       break;
  1330.     case 0x85:
  1331.       i = get_word ();
  1332.       printf ("%u", i);
  1333.       break;
  1334.     case 0x86:
  1335.       d = get_dword ();
  1336.       printf ("%lu", d);
  1337.       break;
  1338.     case 0x88:
  1339.       i = get_byte ();
  1340.       if (i >= 0x80)
  1341.         i -= 0x80;
  1342.       printf ("%d", i);
  1343.       break;
  1344.     case 0x89:
  1345.       i = get_word ();
  1346.       if (i >= 0x8000)
  1347.         i -= 0x8000;
  1348.       printf ("%d", i);
  1349.       break;
  1350.     case 0x8a:
  1351.       d = get_dword ();
  1352.       printf ("%ld", d);
  1353.       break;
  1354.     case 0x8b:
  1355.       i = get_byte ();
  1356.       printf ("%u", i);
  1357.       break;
  1358.     default:
  1359.       fprintf (stderr, "unknown FID: %#.2x\n", fid);
  1360.       exit (2);
  1361.     }
  1362. }
  1363.  
  1364.  
  1365. static void list_protection (void)
  1366. {
  1367.   int flags;
  1368.  
  1369.   flags = get_byte ();
  1370.   switch (flags)
  1371.     {
  1372.     case 0x00:
  1373.       printf ("private");
  1374.       break;
  1375.     case 0x01:
  1376.       printf ("protected ");
  1377.       break;
  1378.     case 0x02:
  1379.       printf ("public");
  1380.       break;
  1381.     default:
  1382.       printf ("unknown protection: %#x", flags);
  1383.       break;
  1384.     }
  1385. }
  1386.  
  1387.  
  1388. static void list_types (void)
  1389. {
  1390.   int total_rec_len, type, qual, len, next, flags;
  1391.   int args, max_args, fields;
  1392.   dword size;
  1393.  
  1394.   flags = 0;                    /* Keep the optimizer happy */
  1395.   total_rec_len = rec_len;
  1396.   while (rec_idx < rec_len)
  1397.     {
  1398.       len = get_word ();
  1399.       next = rec_idx + len;
  1400.       type = get_byte ();
  1401.       qual = get_byte ();
  1402.       printf ("  #%d: ", debug_type_index++);
  1403.       if (next < total_rec_len)
  1404.         rec_len = next;
  1405.       switch (type)
  1406.         {
  1407.         case 0x40:
  1408.           printf ("Class: ");
  1409.           if (qual & 1)
  1410.             printf ("is_struct ");
  1411.           if (qual & ~1)
  1412.             printf ("(qual: %#x) ", qual);
  1413.           size = get_dword ();
  1414.           fields = get_word ();
  1415.           printf ("size: %#lx, %d items: ", size, fields);
  1416.           printf ("#%u, name: ", get_word());
  1417.           show_enc ();
  1418.           printf ("\n");
  1419.           dump_rest ();
  1420.           break;
  1421.  
  1422.         case 0x41:
  1423.           printf ("Base Class: ");
  1424.           if (qual & 1)
  1425.             printf ("virtual, ");
  1426.           if ((qual & ~1))
  1427.             printf ("(qual: %#x) ", qual);
  1428.           list_protection ();
  1429.           printf (", class: #%u, offset: ", get_word ());
  1430.           show_fid ();
  1431.           printf ("\n");
  1432.           dump_rest ();
  1433.           break;
  1434.  
  1435.         case 0x42:
  1436.           printf ("Friend: ");
  1437.           if (qual & 1)
  1438.             printf ("class ");
  1439.           else
  1440.             printf ("function ");
  1441.           if (qual & ~1)
  1442.             printf ("(qual: %#x) ", qual);
  1443.           printf ("type: #%u ", get_word ());
  1444.           printf (", name: ");
  1445.           show_enc ();
  1446.           printf ("\n");
  1447.           dump_rest ();
  1448.           break;
  1449.  
  1450.         case 0x43:
  1451.           printf ("Class Definition: ");
  1452.           if (qual != 0)
  1453.             printf ("(qual: %#x) ", qual);
  1454.           list_protection ();
  1455.           printf (", typedef #%u", get_word ());
  1456.           printf (", class #%u\n", get_word ());
  1457.           dump_rest ();
  1458.           break;
  1459.  
  1460.         case 0x45:
  1461.           printf ("Member function: ");
  1462.           if (qual & 0x01)
  1463.             printf ("static ");
  1464.           if (qual & 0x02)
  1465.             printf ("inline ");
  1466.           if (qual & 0x04)
  1467.             printf ("const ");
  1468.           if (qual & 0x08)
  1469.             printf ("volatile ");
  1470.           if (qual & 0x10)
  1471.             printf ("virtual ");
  1472.           if (qual & ~0x1f)
  1473.             printf ("(qual: %#x) ", qual);
  1474.           list_protection ();
  1475.           type = get_byte ();
  1476.           switch (type)
  1477.             {
  1478.             case 0:
  1479.               break;
  1480.             case 1:
  1481.               printf (", constructor");
  1482.               break;
  1483.             case 2:
  1484.               printf (", destructor");
  1485.               break;
  1486.             default:
  1487.               printf (", unknown type: %#x", type);
  1488.               break;
  1489.             }
  1490.           type = get_word ();
  1491.           printf (", type: #%u", type);
  1492.           if (qual & 0x10)
  1493.             {
  1494.               printf (", virtual table index: ");
  1495.               show_fid ();
  1496.             }
  1497.           printf ("\n    name: ");
  1498.           show_enc ();
  1499.           printf ("\n");
  1500.           dump_rest ();
  1501.           break;
  1502.  
  1503.         case 0x46:
  1504.           printf ("Class Member: ");
  1505.           if (qual & 0x01)
  1506.             printf ("static ");
  1507.           if (qual & 0x02)
  1508.             printf ("vtbl_ptr ");
  1509.           if (qual & 0x04)
  1510.             printf ("vbase_ptr ");
  1511.           if (qual & 0x08)
  1512.             printf ("const ");
  1513.           if (qual & 0x10)
  1514.             printf ("volatile ");
  1515.           if (qual & 0x20)
  1516.             printf ("self_ptr ");
  1517.           if ((qual & ~0x3f) != 0)
  1518.             printf ("(qual: %#x) ", qual);
  1519.           list_protection ();
  1520.           printf (", type: #%u, offset: ", get_word ());
  1521.           show_fid ();
  1522.           printf (",\n    static name: ");
  1523.           show_enc ();
  1524.           printf (", name: ");
  1525.           show_enc ();
  1526.           printf ("\n");
  1527.           dump_rest ();
  1528.           break;
  1529.  
  1530.         case 0x48:
  1531.           printf ("Reference: ");
  1532.           if (qual != 0)
  1533.             printf ("(qual: %#x) ", qual);
  1534.           printf ("type: #%u\n", get_word ());
  1535.           dump_rest ();
  1536.           break;
  1537.  
  1538.         case 0x49:
  1539.           printf ("Member Pointer: ");
  1540.           if (qual & 0x01)
  1541.             printf ("has vbases, ");
  1542.           if (qual & 0x02)
  1543.             printf ("has mult-inh, ");
  1544.           if (qual & 0x04)
  1545.             printf ("const ");
  1546.           if (qual & 0x08)
  1547.             printf ("volatile ");
  1548.           if (qual & ~0x0f)
  1549.             printf ("qual: %#x, ", qual);
  1550.           printf ("child type: #%u, ", get_word ());
  1551.           printf ("class type: #%u, ", get_word ());
  1552.           printf ("representation type: #%u\n", get_word ());
  1553.           dump_rest ();
  1554.           break;
  1555.  
  1556.         case 0x52:
  1557.           printf ("Set: ");
  1558.           if (qual != 0)
  1559.             printf ("qual: %#x, ", qual);
  1560.           printf ("type: ");
  1561.           show_fid ();
  1562.           printf (", name: ");
  1563.           show_fid ();
  1564.           printf ("\n");
  1565.           dump_rest ();
  1566.           break;
  1567.  
  1568.         case 0x54:
  1569.           printf ("Function: ");
  1570.           args = get_word ();
  1571.           max_args = get_word ();
  1572.           printf ("qual: %#x, %d argument%s (%d maximum), returns ",
  1573.                   qual, args, (args == 1 ? "" : "s"), max_args);
  1574.           show_fid ();
  1575.           printf (",\n    argument list: ");
  1576.           show_fid ();
  1577.           printf ("\n");
  1578.           dump_rest ();
  1579.           break;
  1580.  
  1581.         case 0x57:
  1582.           printf ("Stack: ");
  1583.           if (qual & 0x01)
  1584.             printf ("32-bit ");
  1585.           if (qual & 0x02)
  1586.             printf ("far ");
  1587.           if (qual & ~0x03)
  1588.             printf ("qual: %#x, ", qual);
  1589.           size = get_dword ();
  1590.           printf ("size: %#lx, name: ", size);
  1591.           show_fid ();
  1592.           printf ("\n");
  1593.           dump_rest ();
  1594.           break;
  1595.  
  1596.         case 0x5c:
  1597.           printf ("Bit string: ");
  1598.           if (qual & 1)
  1599.             printf ("varying, ");
  1600.           if (qual & 2)
  1601.             printf ("signed, ");
  1602.           if (qual & 4)
  1603.             printf ("word alignment, ");
  1604.           if (qual & 8)
  1605.             printf ("display as value, ");
  1606.           if (qual & 0x10)
  1607.             printf ("descriptor, ");
  1608.           if (qual & ~0x1f)
  1609.             printf ("qual: %#x, ", qual);
  1610.           printf ("offset: %d, size: ", get_byte ());
  1611.           show_fid ();
  1612.           printf ("\n");
  1613.           dump_rest ();
  1614.           break;
  1615.  
  1616.         case 0x5d:
  1617.           printf ("User defined type: ");
  1618.           if (qual != 0)
  1619.             printf ("qual: %#x, ", qual);
  1620.           printf ("type: ");
  1621.           show_fid ();
  1622.           printf (", name: ");
  1623.           show_fid ();
  1624.           printf ("\n");
  1625.           dump_rest ();
  1626.           break;
  1627.  
  1628.         case 0x6f:
  1629.           printf ("Subrange: ");
  1630.           if (qual != 0)
  1631.             printf ("qual: %#x, ", qual);
  1632.           printf ("type: ");
  1633.           show_fid ();
  1634.           printf (", start: ");
  1635.           show_fid ();
  1636.           printf (", end: ");
  1637.           show_fid ();
  1638.           printf (", name: ");
  1639.           show_fid ();
  1640.           printf ("\n");
  1641.           dump_rest ();
  1642.           break;
  1643.  
  1644.         case 0x72:
  1645.           printf ("Code Label: ");
  1646.           if (qual & 1)
  1647.             printf ("32-bit ");
  1648.           else
  1649.             printf ("16-bit ");
  1650.           if (qual & 2)
  1651.             printf ("far");
  1652.           else
  1653.             printf ("near");
  1654.           if (qual & ~3)
  1655.             printf (" (qual: %#x)", qual);
  1656.           printf ("\n");
  1657.           dump_rest ();
  1658.           break;
  1659.  
  1660.         case 0x78:
  1661.           printf ("Array: ");
  1662.           if (qual & 1)
  1663.             printf ("col-maj ");
  1664.           else
  1665.             printf ("row-maj ");
  1666.           if (qual & 2)
  1667.             printf ("(packed) ");
  1668.           if (qual & 4)
  1669.             printf ("desc provided) ");
  1670.           if (qual & ~7)
  1671.             printf ("(qual: %#x) ", qual);
  1672.           size = get_dword ();
  1673.           printf ("size: %#lx, bounds type: ", size);
  1674.           show_fid ();
  1675.           printf (", elements type: ");
  1676.           show_fid ();
  1677.           printf (", name: ");
  1678.           show_fid ();
  1679.           printf ("\n");
  1680.           dump_rest ();
  1681.           break;
  1682.  
  1683.         case 0x79:
  1684.           printf ("Structure: ");
  1685.           if (qual != 0)
  1686.             printf ("(qual: %#x) ", qual);
  1687.           size = get_dword ();
  1688.           fields = get_word ();
  1689.           printf ("size: %#lx, %d fields: ", size, fields);
  1690.           show_fid ();
  1691.           printf (", names: ");
  1692.           show_fid ();
  1693.           printf (", tag: ");
  1694.           show_fid ();
  1695.           printf ("\n");
  1696.           dump_rest ();
  1697.           break;
  1698.  
  1699.         case 0x7a:
  1700.           printf ("Pointer: ");
  1701.           show_fid ();
  1702.           if (rec_idx < rec_len)
  1703.             {
  1704.               printf (", name: ");
  1705.               show_fid ();
  1706.             }
  1707.           printf ("\n");
  1708.           dump_rest ();
  1709.           break;
  1710.  
  1711.         case 0x7b:
  1712.           printf ("Enum: ");
  1713.           if (qual != 0)
  1714.             printf ("(qual: %#x) ", qual);
  1715.           printf ("type: ");
  1716.           show_fid ();
  1717.           printf (", values: ");
  1718.           show_fid ();
  1719.           printf (", minimum: ");
  1720.           show_fid ();
  1721.           printf (", maximum: ");
  1722.           show_fid ();
  1723.           printf ("\n");
  1724.           dump_rest ();
  1725.           break;
  1726.  
  1727.         case 0x7f:
  1728.           printf ("List");
  1729.           switch (qual)
  1730.             {
  1731.             case 0x01:
  1732.               printf (" (field types)");
  1733.               break;
  1734.             case 0x02:
  1735.               printf (" (field names and offsets)");
  1736.               break;
  1737.             case 0x03:
  1738.               printf (" (enumeration)");
  1739.               break;
  1740.             case 0x04:
  1741.               printf (" (arguments)");
  1742.               break;
  1743.             }
  1744.           printf (":\n");
  1745.           while (rec_idx < rec_len)
  1746.             {
  1747.               printf ("    ");
  1748.               if (qual == 0x04)
  1749.                 flags = get_byte ();
  1750.               show_fid ();
  1751.               switch (qual)
  1752.                 {
  1753.                 case 0x02:
  1754.                   printf (", offset: ");
  1755.                   show_fid ();
  1756.                   break;
  1757.                 case 0x03:
  1758.                   printf (", value: ");
  1759.                   show_fid ();
  1760.                   break;
  1761.                 case 0x04:
  1762.                   if (flags & 0x01)
  1763.                     printf (" by value");
  1764.                   else
  1765.                     printf (" by address");
  1766.                   if (flags & 0x02)
  1767.                     printf (", descriptor provided");
  1768.                   if (flags & ~0x03)
  1769.                     printf (" (flags: %#x)", flags);
  1770.                   break;
  1771.                 }
  1772.               printf ("\n");
  1773.             }
  1774.           dump_rest ();
  1775.           break;
  1776.  
  1777.         default:
  1778.           printf ("unknown complex type: %#.2x\n", type);
  1779.           dump_rest ();
  1780.           break;
  1781.         }
  1782.       rec_idx = next;
  1783.       rec_len = total_rec_len;
  1784.     }
  1785. }
  1786.  
  1787.  
  1788. static void list_ledata (void)
  1789. {
  1790.   int len;
  1791.   dword offset, seg;
  1792.   char *name;
  1793.  
  1794.   show_record ("LEDATA");
  1795.  
  1796.   seg = get_index ();
  1797.   offset = get_word_or_dword ();
  1798.   len = rec_len - rec_idx;
  1799.  
  1800.   printf (" ");
  1801.   show_seg (seg);
  1802.   printf (" offset: %#lx length: %#x\n", offset, len);
  1803.   name = lname_list[segment_list[seg-1].name-1];
  1804.   if (strcmp (name, "$$SYMBOLS") == 0 && list_debug
  1805.       && debug_info == debug_hll && hll_style >= 3)
  1806.     list_symbols ();
  1807.   else if (strcmp (name, "$$TYPES") == 0 && list_debug
  1808.            && debug_info == debug_hll && hll_style >= 3)
  1809.     list_types ();
  1810.   else
  1811.     dump_rest ();
  1812. }
  1813.  
  1814.  
  1815. static void list_block (int level)
  1816. {
  1817.   dword rep_count, block_count;
  1818.   int indent, len;
  1819.  
  1820.   indent = (level + 1) * 2;
  1821.   rep_count = get_word_or_dword ();
  1822.   block_count = get_word ();
  1823.   if (block_count == 0)
  1824.     {
  1825.       len = get_byte ();
  1826.       printf ("%*sRepeat count: %lu, data length: %d\n",
  1827.               indent, "", rep_count, len);
  1828.       dump_block (len, indent + 2);
  1829.     }
  1830.   else
  1831.     {
  1832.       printf ("%*sRepeat count: %lu, block count: %lu\n",
  1833.               indent, "", rep_count, block_count);
  1834.       while (block_count > 0)
  1835.         {
  1836.           list_block (level + 1);
  1837.           --block_count;
  1838.         }
  1839.     }
  1840. }
  1841.  
  1842.  
  1843. static void list_lidata (void)
  1844. {
  1845.   dword offset, seg;
  1846.  
  1847.   show_record ("LIDATA");
  1848.  
  1849.   seg = get_index ();
  1850.   offset = get_word_or_dword ();
  1851.  
  1852.   printf (" ");
  1853.   show_seg (seg);
  1854.   printf (" offset: %#lx length: %#x\n", offset, rec_len - rec_idx);
  1855.   while (rec_len - rec_idx >= 4)
  1856.     list_block (0);
  1857.   dump_rest ();
  1858. }
  1859.  
  1860.  
  1861. static void list_target (int method)
  1862. {
  1863.   switch (method)
  1864.     {
  1865.     case 0:
  1866.       printf ("T0 (seg ");
  1867.       show_seg (get_index ());
  1868.       printf (")");
  1869.       break;
  1870.     case 1:
  1871.       printf ("T1 (group ");
  1872.       show_group (get_index ());
  1873.       printf (")");
  1874.       break;
  1875.     case 2:
  1876.       printf ("T2 (ext ");
  1877.       show_ext (get_index ());
  1878.       printf (")");
  1879.       break;
  1880.     default:
  1881.       printf ("T%d (index #%d)", method & 3, get_index ());
  1882.                 break;
  1883.     }
  1884. }
  1885.  
  1886.  
  1887. static void list_frame (int method)
  1888. {
  1889.   switch (method)
  1890.     {
  1891.     case 0:
  1892.       printf ("F0 (seg ");
  1893.       show_seg (get_index ());
  1894.       printf (")");
  1895.       break;
  1896.     case 1:
  1897.       printf ("F1 (group ");
  1898.       show_group (get_index ());
  1899.       printf (")");
  1900.       break;
  1901.     case 2:
  1902.       printf ("F2 (ext");
  1903.       show_ext (get_index ());
  1904.       printf (")");
  1905.       break;
  1906.     case 4:
  1907.       printf ("F4 (cur seg)");
  1908.       break;
  1909.     case 5:
  1910.       printf ("F5 (target)");
  1911.       break;
  1912.     default:
  1913.       printf ("F%d", method);
  1914.       if (method <= 2)
  1915.         printf (" (index #%d)", get_index ());
  1916.       break;
  1917.     }
  1918. }
  1919.  
  1920.  
  1921. static void list_fixupp (void)
  1922. {
  1923.   int first, locat, method, offset, fix_data;
  1924.  
  1925.   show_record ("FIXUPP");
  1926.   printf (":\n");
  1927.   while (rec_idx < rec_len)
  1928.     {
  1929.       first = get_byte ();
  1930.       if (first & 0x80)
  1931.         {
  1932.           printf ("  FIXUP ");
  1933.           if (first & 0x40)
  1934.             printf ("seg-rel, ");
  1935.           else
  1936.             printf ("self-rel, ");
  1937.           locat = (first >> 2) & 0x0f;
  1938.           switch (locat)
  1939.             {
  1940.             case 0:
  1941.               printf ("LOW-8");
  1942.               break;
  1943.             case 1:
  1944.               printf ("OFFSET-16");
  1945.               break;
  1946.             case 2:
  1947.               printf ("SEL-16");
  1948.               break;
  1949.             case 3:
  1950.               printf ("FAR-16:16");
  1951.               break;
  1952.             case 4:
  1953.               printf ("HIGH-8");
  1954.               break;
  1955.             case 5:
  1956.               printf ("OFFSET-16(LR)");
  1957.               break;
  1958.             case 9:
  1959.               printf ("OFFSET-32");
  1960.               break;
  1961.             case 11:
  1962.               printf ("FAR-16:32");
  1963.               break;
  1964.             case 13:
  1965.               printf ("OFFSET-32(LR)");
  1966.               break;
  1967.             default:
  1968.               printf ("unknown location: %d", locat);
  1969.               break;
  1970.             }
  1971.           offset = get_byte ();
  1972.           offset |= (first & 3) << 8;
  1973.           printf (", offset: %#x, ", offset);
  1974.           fix_data = get_byte ();
  1975.           if (fix_data & 0x80)
  1976.             printf ("frame thread %d", (fix_data >> 4) & 3);
  1977.           else
  1978.             list_frame ((fix_data >> 4) & 7);
  1979.           if (fix_data & 0x08)
  1980.             printf (", target thread %d P=%d",
  1981.                     fix_data & 3, (fix_data >> 2) & 1);
  1982.           else
  1983.             {
  1984.               printf (", ");
  1985.               list_target (fix_data & 3);
  1986.             }
  1987.           if (!(fix_data & 0x04))
  1988.             printf (", disp: %#lx", get_word_or_dword ());
  1989.         }
  1990.       else
  1991.         {
  1992.           method = (first >> 2) & 7;
  1993.           printf ("  THREAD %d ", first & 3);
  1994.           if (first & 0x40)
  1995.             {
  1996.               list_frame (method);
  1997.               printf (", P=%d", (first >> 4) & 1);
  1998.             }
  1999.           else
  2000.             list_target (method & 3);
  2001.         }
  2002.       printf ("\n");
  2003.     }
  2004. }
  2005.  
  2006.  
  2007. static void list_hll_linnum (void)
  2008. {
  2009.   int group, segment;
  2010.   dword i, addr, files, line, stmt, lst_line, first_col, num_cols;
  2011.   word src_line, index;
  2012.   byte reserved;
  2013.   byte name[256];
  2014.  
  2015.   group = get_index ();
  2016.   segment = get_index ();
  2017.   printf (": group: %d, segment: ", group);
  2018.   show_seg (segment);
  2019.   if (!linnum_started)
  2020.     {
  2021.       printf (", ");
  2022.       line = get_word ();
  2023.       if (line != 0)
  2024.         printf ("must_be_zero: %ld, ", line);
  2025.       linnum_entry_type = get_byte ();
  2026.       switch (linnum_entry_type)
  2027.         {
  2028.         case 0x00:
  2029.           printf ("source file");
  2030.           break;
  2031.         case 0x01:
  2032.           printf ("listing file");
  2033.           break;
  2034.         case 0x02:
  2035.           printf ("source & listing file");
  2036.           break;
  2037.         default:
  2038.           printf ("undefined entry type: %#x", linnum_entry_type);
  2039.           break;
  2040.         }
  2041.       reserved = get_byte ();
  2042.       printf (", reserved=%#x\n", reserved);
  2043.       line_count = get_word ();
  2044.       segment = get_word ();
  2045.       names_length = get_dword ();
  2046.       printf ("%d line%s, segment: %u, name table length: %#lx",
  2047.               line_count, (line_count == 1 ? "" : "s"), segment, names_length);
  2048.       linnum_started = TRUE;
  2049.     }
  2050.   printf ("\n");
  2051.   while (rec_idx < rec_len && line_count != 0)
  2052.     {
  2053.       switch (linnum_entry_type)
  2054.         {
  2055.         case 0x00:
  2056.           src_line = get_word ();
  2057.           index = get_word ();
  2058.           addr = get_dword ();
  2059.           printf ("  Line %6u of file %u at 0x%.8lx", src_line, index, addr);
  2060.           break;
  2061.         case 0x01:
  2062.           lst_line = get_dword ();
  2063.           stmt = get_dword ();
  2064.           addr = get_dword ();
  2065.           printf ("  Line %6lu, statement %6lu at 0x%.8lx",
  2066.                   lst_line, stmt, addr);
  2067.           break;
  2068.         case 0x02:
  2069.           src_line = get_word ();
  2070.           index = get_word ();
  2071.           lst_line = get_dword ();
  2072.           stmt = get_dword ();
  2073.           addr = get_dword ();
  2074.           printf ("  Line %6u of file %u, ", src_line, index);
  2075.           printf ("listing line %6lu, statement %6lu at 0x%.8lx",
  2076.                   lst_line, stmt, addr);
  2077.           break;
  2078.         default:
  2079.           printf ("  ????");
  2080.           break;
  2081.         }
  2082.       printf ("\n");
  2083.       --line_count;
  2084.     }
  2085.  
  2086.   /* Path table comes next, ignored... */
  2087.  
  2088.   /* Note: this will fail if the name table is split */
  2089.  
  2090.   if (rec_idx < rec_len)
  2091.     {
  2092.       first_col = get_dword ();
  2093.       num_cols = get_dword ();
  2094.       files = get_dword ();
  2095.       printf ("  first column: %lu, columns: %lu, number of files: %ld\n",
  2096.               first_col, num_cols, files);
  2097.       for (i = 0; i < files; ++i)
  2098.         {
  2099.           printf ("  #%lu: ", i + 1);
  2100.           get_string (name);
  2101.           show_string (name);
  2102.           printf ("\n");
  2103.         }
  2104.     }
  2105.   if (line_count == 0)
  2106.     linnum_started = FALSE;
  2107. }
  2108.  
  2109.  
  2110. static void list_modend (FILE *f)
  2111. {
  2112.   int type, end_data;
  2113.   long pos;
  2114.  
  2115.   show_record ("MODEND");
  2116.   printf (": ");
  2117.   type = get_byte ();
  2118.   if (type & 0x80)
  2119.     printf ("main ");
  2120.   if (type & 0x40)
  2121.     {
  2122.       if (type & 0x01)
  2123.         printf ("rel-");
  2124.       printf ("start: ");
  2125.       end_data = get_byte ();
  2126.       if (end_data & 0x80)
  2127.         printf ("frame thread %d", (end_data >> 4) & 3);
  2128.       else
  2129.         list_frame ((end_data >> 4) & 7);
  2130.       if (end_data & 0x08)
  2131.         printf (", target thread %d P=%d",
  2132.                 end_data & 3, (end_data >> 2) & 1);
  2133.       else
  2134.         {
  2135.           printf (", ");
  2136.           list_target (end_data & 3);
  2137.         }
  2138.       if (!(end_data & 0x04))   /* This bit must always be clear! */
  2139.         printf (", disp: %#lx", get_word_or_dword ());
  2140.     }
  2141.   printf ("\n");
  2142.   dump_rest ();
  2143.   if (page_size == 0)
  2144.     done = TRUE;
  2145.   else
  2146.     {
  2147.       pos = ftell (f);
  2148.       if (pos % page_size != 0)
  2149.         fseek (f, page_size * (1 + pos / page_size), SEEK_SET);
  2150.     }
  2151. }
  2152.  
  2153.  
  2154. static int list_libend (FILE *f)
  2155. {
  2156.   byte dblock[512];
  2157.   unsigned dblockno, offset, bn;
  2158.   int bucket, i, len;
  2159.  
  2160.   done = TRUE;
  2161.   printf ("LIBEND\n");
  2162.   fseek (f, dict_offset, SEEK_SET);
  2163.   for (dblockno = 0; dblockno < dict_blocks; ++dblockno)
  2164.     {
  2165.       printf ("Dictionary block %u: ", dblockno);
  2166.       if (fread (dblock, 512, 1, f) != 1)
  2167.         {
  2168.           putchar ('\n');
  2169.           return -1;
  2170.         }
  2171.       if (dblock[37] == 0xff)
  2172.         printf ("full\n");
  2173.       else
  2174.         printf ("free space at 0x%.3x\n", dblock[37] * 2);
  2175.       for (bucket = 0; bucket < 37; ++bucket)
  2176.         if (dblock[bucket] != 0)
  2177.           {
  2178.             offset = dblock[bucket] * 2;
  2179.             printf ("  Bucket %2u: offset=0x%.3x", bucket, offset);
  2180.             if (offset < 38)
  2181.               putchar ('\n');
  2182.             else
  2183.               {
  2184.                 len = dblock[offset];
  2185.                 ++offset;
  2186.                 if (offset + len + 2 > 512)
  2187.                   printf (" (record extends beyond end of block)\n");
  2188.                 else
  2189.                   {
  2190.                     printf (" name=\"");
  2191.                     for (i = 0; i < len; ++i)
  2192.                       show_char (dblock[offset++]);
  2193.                     bn = dblock[offset++];
  2194.                     bn |= dblock[offset++] << 8;
  2195.                     printf ("\" block=%u\n", bn);
  2196.                   }
  2197.               }
  2198.           }
  2199.     }
  2200.   return 0;
  2201. }
  2202.  
  2203.  
  2204. static void list_omf (const char *fname)
  2205. {
  2206.   FILE *f;
  2207.   struct omf_rec rec;
  2208.  
  2209.   f = fopen (fname, "rb");
  2210.   if (f == NULL)
  2211.     {
  2212.       perror (fname);
  2213.       exit (2);
  2214.     }
  2215.   lname_count = 0; lname_alloc = 0; lname_list = NULL;
  2216.   segment_count = 0; segment_alloc = 0; segment_list = NULL;
  2217.   group_count = 0; group_alloc = 0; group_list = NULL;
  2218.   ext_count = 0; ext_alloc = 0; ext_list = NULL;
  2219.   pub_count = 0;
  2220.   debug_type_index = 512; page_size = 0; done = FALSE;
  2221.   debug_info = debug_default; hll_style = 0; linnum_started = FALSE;
  2222.   do
  2223.     {
  2224.       if (show_addr)
  2225.         rec_pos = ftell (f);
  2226.       if (fread (&rec, sizeof (rec), 1, f) != 1)
  2227.         goto failure;
  2228.       rec_type = rec.rec_type;
  2229.       rec_len = rec.rec_len;
  2230.       rec_idx = 0;
  2231.       if (rec_len > sizeof (rec_buf))
  2232.         {
  2233.           fprintf (stderr, "%s: Record too long", fname);
  2234.           exit (2);
  2235.         }
  2236.       if (fread (rec_buf, rec_len, 1, f) != 1)
  2237.         goto failure;
  2238.       /*...check checksum...*/
  2239.       --rec_len;
  2240.       switch (rec_type)
  2241.         {
  2242.         case LIBHDR:
  2243.           list_libhdr ();
  2244.           break;
  2245.         case LIBEND:
  2246.           if (list_libend (f) != 0)
  2247.             goto failure;
  2248.           break;
  2249.         case THEADR:
  2250.           list_theadr ();
  2251.           break;
  2252.         case COMENT:
  2253.           list_coment ();
  2254.           break;
  2255.         case MODEND:
  2256.         case MODEND|REC32:
  2257.           list_modend (f);
  2258.           break;
  2259.         case EXTDEF:
  2260.           list_extdef ();
  2261.           break;
  2262.         case TYPDEF:
  2263.           show_record ("TYPDEF");
  2264.           printf ("\n");
  2265.           dump_rest ();
  2266.           break;
  2267.         case PUBDEF:
  2268.         case PUBDEF|REC32:
  2269.           list_pubdef ();
  2270.           break;
  2271.         case LINNUM:
  2272.         case LINNUM|REC32:
  2273.           show_record ("LINNUM");
  2274.           if (debug_info == debug_hll)
  2275.             list_hll_linnum ();
  2276.           else
  2277.             {
  2278.               printf ("\n");
  2279.               dump_rest ();
  2280.             }
  2281.           break;
  2282.         case LNAMES:
  2283.           list_lnames ();
  2284.           break;
  2285.         case SEGDEF:
  2286.         case SEGDEF|REC32:
  2287.           list_segdef ();
  2288.           break;
  2289.         case GRPDEF:
  2290.           list_grpdef ();
  2291.           break;
  2292.           break;
  2293.         case FIXUPP:
  2294.         case FIXUPP|REC32:
  2295.           list_fixupp ();
  2296.           break;
  2297.         case LEDATA:
  2298.         case LEDATA|REC32:
  2299.           list_ledata ();
  2300.           break;
  2301.         case LIDATA:
  2302.         case LIDATA|REC32:
  2303.           list_lidata ();
  2304.           break;
  2305.         case COMDEF:
  2306.           list_comdef ();
  2307.           break;
  2308.         case COMDAT:
  2309.         case COMDAT|REC32:
  2310.           show_record ("COMDAT");
  2311.           printf ("\n");
  2312.           dump_rest ();
  2313.           break;
  2314.         case ALIAS:
  2315.           list_alias ();
  2316.           break;
  2317.         default:
  2318.           printf ("Unknown record type at %ld: %.2x\n",
  2319.                   ftell (f) - (sizeof (rec) + rec_len + 1), rec.rec_type);
  2320.           dump_rest ();
  2321.           break;
  2322.         }
  2323.     } while (!done);
  2324.   fclose (f);
  2325.   if (lname_list != NULL)
  2326.     free (lname_list);
  2327.   return;
  2328.  
  2329. failure:
  2330.   if (ferror (f))
  2331.     perror (fname);
  2332.   else
  2333.     fprintf (stderr, "%s: Unexpected end of file", fname);
  2334.   exit (2);
  2335. }
  2336.  
  2337.  
  2338. static void usage (void)
  2339. {
  2340.   fputs ("listomf " VERSION " -- "
  2341.          "Copyright (c) 1993-1996 by Eberhard Mattes\n\n"
  2342.          "Usage: listomf [-a] [-d] <input_file>\n\n"
  2343.          "Options:\n"
  2344.          "  -a    Show addresses of records\n"
  2345.          "  -d    Don't interpret $$TYPES and $$SYMBOLS segments\n", stderr);
  2346.   exit (1);
  2347. }
  2348.  
  2349.  
  2350. int main (int argc, char *argv[])
  2351. {
  2352.   int c;
  2353.  
  2354.   opterr = 0;
  2355.   while ((c = getopt (argc, argv, "ad")) != EOF)
  2356.     switch (c)
  2357.       {
  2358.       case 'a':
  2359.         show_addr = TRUE;
  2360.         break;
  2361.       case 'd':
  2362.         list_debug = FALSE;
  2363.         break;
  2364.       default:
  2365.         usage ();
  2366.       }
  2367.  
  2368.   if (argc - optind != 1)
  2369.     usage ();
  2370.  
  2371. #ifdef __EMX__
  2372.   if (_isterm (1))
  2373.     setvbuf (stdout, NULL, _IOLBF, BUFSIZ);
  2374.   else
  2375.     setvbuf (stdout, NULL, _IOFBF, BUFSIZ);
  2376. #endif /* __EMX__ */
  2377.  
  2378.   list_omf (argv[optind]);
  2379.   return 0;
  2380. }
  2381.