source: trunk/emx/src/emxomf/listomf.c

Last change on this file was 3653, checked in by bird, 17 years ago

listomf: Parse LPUBDEF (watcom emits them) and use symbolic constants where possible.

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