Update the address of the Free Software Foundation.
[wine] / tools / winedump / le.c
1 /*
2  * Dumping of LE binaries
3  *
4  * Copyright 2004 Robert Reif
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <fcntl.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wine/winbase16.h"
34 #include "winedump.h"
35
36 struct o32_obj
37 {
38     unsigned long       o32_size;
39     unsigned long       o32_base;
40     unsigned long       o32_flags;
41     unsigned long       o32_pagemap;
42     unsigned long       o32_mapsize;
43     char                o32_name[4];
44 };
45
46 struct o32_map
47 {
48     unsigned short      o32_pagedataoffset;
49     unsigned char       o32_pagesize;
50     unsigned char       o32_pageflags;
51 };
52
53 struct b32_bundle
54 {
55     unsigned char       b32_cnt;
56     unsigned char       b32_type;
57 };
58
59 struct vxd_descriptor
60 {
61     unsigned long       next;
62     unsigned short      sdk_version;
63     unsigned short      device_number;
64     unsigned char       version_major;
65     unsigned char       version_minor;
66     unsigned short      flags;
67     char                name[8];
68     unsigned long       init_order;
69     unsigned long       ctrl_ofs;
70     unsigned long       v86_ctrl_ofs;
71     unsigned long       pm_ctrl_ofs;
72     unsigned long       v86_ctrl_csip;
73     unsigned long       pm_ctrl_csip;
74     unsigned long       rm_ref_data;
75     unsigned long       service_table_ofs;
76     unsigned long       service_table_size;
77     unsigned long       win32_service_table_ofs;
78     unsigned long       prev;
79     unsigned long       size;
80     unsigned long       reserved0;
81     unsigned long       reserved1;
82     unsigned long       reserved2;
83 };
84
85 static inline WORD get_word( const BYTE *ptr )
86 {
87     return ptr[0] | (ptr[1] << 8);
88 }
89
90 static void dump_le_header( const IMAGE_VXD_HEADER *le )
91 {
92     printf( "File header:\n" );
93     printf( "    Magic:                                %04x (%c%c)\n",
94             le->e32_magic, LOBYTE(le->e32_magic), HIBYTE(le->e32_magic));
95     printf( "    Byte order:                           %s\n",
96             le->e32_border == 0 ? "little-indian" : "big-endian");
97     printf( "    Word order:                           %s\n",
98             le->e32_worder ==  0 ? "little-indian" : "big-endian");
99     printf( "    Executable format level:              %ld\n",
100             le->e32_level);
101     printf( "    CPU type:                             %s\n",
102             le->e32_cpu == 0x01 ? "Intel 80286" :
103             le->e32_cpu == 0x02 ? "Intel 80386" :
104             le->e32_cpu == 0x03 ? "Intel 80486" :
105             le->e32_cpu == 0x04 ? "Intel 80586" :
106             le->e32_cpu == 0x20 ? "Intel i860 (N10)" :
107             le->e32_cpu == 0x21 ? "Intel i860 (N11)" :
108             le->e32_cpu == 0x40 ? "MIPS Mark I" :
109             le->e32_cpu == 0x41 ? "MIPS Mark II" :
110             le->e32_cpu == 0x42 ? "MIPS Mark III" :
111             "Unknown");
112     printf( "    Target operating system:              %s\n",
113             le->e32_os == 0x01 ? "OS/2" :
114             le->e32_os == 0x02 ? "Windows" :
115             le->e32_os == 0x03 ? "DOS 4.x" :
116             le->e32_os == 0x04 ? "Windows 386" :
117             "Unknown");
118     printf( "    Module version:                       %ld\n",
119             le->e32_ver);
120     printf( "    Module type flags:                    %08lx\n",
121             le->e32_mflags);
122     if (le->e32_mflags & 0x8000)
123     {
124         if (le->e32_mflags & 0x0004)
125             printf( "        Global initialization\n");
126         else
127             printf( "        Per-Process initialization\n");
128         if (le->e32_mflags & 0x0010)
129             printf( "        No internal fixup\n");
130         if (le->e32_mflags & 0x0020)
131             printf( "        No external fixup\n");
132         if ((le->e32_mflags & 0x0700) == 0x0100)
133             printf( "        Incompatible with PM windowing\n");
134         else if ((le->e32_mflags & 0x0700) == 0x0200)
135             printf( "        Compatible with PM windowing\n");
136         else if ((le->e32_mflags & 0x0700) == 0x0300)
137             printf( "        Uses PM windowing API\n");
138         if (le->e32_mflags & 0x2000)
139             printf( "        Module not loadable\n");
140         if (le->e32_mflags & 0x8000)
141             printf( "        Module is DLL\n");
142     }
143     printf( "    Number of memory pages:               %ld\n",
144             le->e32_mpages);
145     printf( "    Initial object CS number:             %08lx\n",
146             le->e32_startobj);
147     printf( "    Initial EIP:                          %08lx\n",
148             le->e32_eip);
149     printf( "    Initial object SS number:             %08lx\n",
150             le->e32_stackobj);
151     printf( "    Initial ESP:                          %08lx\n",
152             le->e32_esp);
153     printf( "    Memory page size:                     %ld\n",
154             le->e32_pagesize);
155     printf( "    Bytes on last page:                   %ld\n",
156             le->e32_lastpagesize);
157     printf( "    Fix-up section size:                  %ld\n",
158             le->e32_fixupsize);
159     printf( "    Fix-up section checksum:              %08lx\n",
160             le->e32_fixupsum);
161     printf( "    Loader section size:                  %ld\n",
162             le->e32_ldrsize);
163     printf( "    Loader section checksum:              %08lx\n",
164             le->e32_ldrsum);
165     printf( "    Offset of object table:               %08lx\n",
166             le->e32_objtab);
167     printf( "    Object table entries:                 %ld\n",
168             le->e32_objcnt);
169     printf( "    Object page map offset:               %08lx\n",
170             le->e32_objmap);
171     printf( "    Object iterate data map offset:       %08lx\n",
172             le->e32_itermap);
173     printf( "    Resource table offset:                %08lx\n",
174             le->e32_rsrctab);
175     printf( "    Resource table entries:               %ld\n",
176             le->e32_rsrccnt);
177     printf( "    Resident names table offset:          %08lx\n",
178             le->e32_restab);
179     printf( "    Entry table offset:                   %08lx\n",
180             le->e32_enttab);
181     printf( "    Module directives table offset:       %08lx\n",
182             le->e32_dirtab);
183     printf( "    Module directives entries:            %ld\n",
184             le->e32_dircnt);
185     printf( "    Fix-up page table offset:             %08lx\n",
186             le->e32_fpagetab);
187     printf( "    Fix-up record table offset:           %08lx\n",
188             le->e32_frectab);
189     printf( "    Imported modules name table offset:   %08lx\n",
190             le->e32_impmod);
191     printf( "    Imported modules count:               %ld\n",
192             le->e32_impmodcnt);
193     printf( "    Imported procedure name table offset: %08lx\n",
194             le->e32_impproc);
195     printf( "    Per-page checksum table offset:       %08lx\n",
196             le->e32_pagesum);
197     printf( "    Data pages offset from top of table:  %08lx\n",
198             le->e32_datapage);
199     printf( "    Preload page count:                   %08lx\n",
200             le->e32_preload);
201     printf( "    Non-resident names table offset:      %08lx\n",
202             le->e32_nrestab);
203     printf( "    Non-resident names table length:      %ld\n",
204             le->e32_cbnrestab);
205     printf( "    Non-resident names table checksum:    %08lx\n",
206             le->e32_nressum);
207     printf( "    Automatic data object:                %08lx\n",
208             le->e32_autodata);
209     printf( "    Debug information offset:             %08lx\n",
210             le->e32_debuginfo);
211     printf( "    Debug information length:             %ld\n",
212             le->e32_debuglen);
213     printf( "    Preload instance pages number:        %ld\n",
214             le->e32_instpreload);
215     printf( "    Demand instance pages number:         %ld\n",
216             le->e32_instdemand);
217     printf( "    Extra heap allocation:                %ld\n",
218             le->e32_heapsize);
219     printf( "    VxD resource table offset:            %08lx\n",
220             le->e32_winresoff);
221     printf( "    Size of VxD resource table:           %ld\n",
222             le->e32_winreslen);
223     printf( "    VxD identifier:                       %x\n",
224             le->e32_devid);
225     printf( "    VxD DDK version:                      %x\n",
226             le->e32_ddkver);
227 }
228
229 static void dump_le_objects( const void *base, const IMAGE_VXD_HEADER *le )
230 {
231     const struct o32_obj *pobj;
232     unsigned int i;
233
234     printf("\nObject table:\n");
235     pobj = (const struct o32_obj *)((const unsigned char *)le + le->e32_objtab);
236     for (i = 0; i < le->e32_objcnt; i++)
237     {
238         unsigned int j;
239         const struct o32_map *pmap=0;
240
241         printf("    Obj. Rel.Base Codesize Flags    Tableidx Tablesize Name\n");
242         printf("    %04X %08lx %08lx %08lx %08lx %08lx  ", i + 1,
243                pobj->o32_base, pobj->o32_size, pobj->o32_flags,
244                pobj->o32_pagemap, pobj->o32_mapsize);
245         for (j = 0; j < 4; j++)
246         {
247            if  (isprint(pobj->o32_name[j]))
248                 printf("%c", pobj->o32_name[j]);
249            else
250                 printf(".");
251         }
252         printf("\n");
253
254         if(pobj->o32_flags & 0x0001)
255             printf("\tReadable\n");
256         if(pobj->o32_flags & 0x0002)
257             printf("\tWriteable\n");
258         if(pobj->o32_flags & 0x0004)
259             printf("\tExecutable\n");
260         if(pobj->o32_flags & 0x0008)
261             printf("\tResource\n");
262         if(pobj->o32_flags & 0x0010)
263             printf("\tDiscardable\n");
264         if(pobj->o32_flags & 0x0020)
265             printf("\tShared\n");
266         if(pobj->o32_flags & 0x0040)
267             printf("\tPreloaded\n");
268         if(pobj->o32_flags & 0x0080)
269             printf("\tInvalid\n");
270         if(pobj->o32_flags & 0x2000)
271             printf("\tUse 32\n");
272
273         printf("    Page tables:\n");
274         printf("        Tableidx Offset Flags\n");
275         pmap = (const struct o32_map *)((const unsigned char *)le + le->e32_objmap);
276         pmap = &(pmap[pobj->o32_pagemap - 1]);
277         for (j = 0; j < pobj->o32_mapsize; j++)
278         {
279             printf("        %08lx %06x %02x\n",
280                    pobj->o32_pagemap + j,
281                    (pmap->o32_pagedataoffset << 8) + pmap->o32_pagesize,
282                    (int)pmap->o32_pageflags);
283             pmap++;
284         }
285         pobj++;
286     }
287 }
288
289 static void dump_le_names( const void *base, const IMAGE_VXD_HEADER *le )
290 {
291     const unsigned char *pstr = (const unsigned char *)le + le->e32_restab;
292
293     printf( "\nResident name table:\n" );
294     while (*pstr)
295     {
296         printf( " %4d: %*.*s\n", get_word(pstr + *pstr + 1), *pstr, *pstr,
297                 pstr + 1 );
298         pstr += *pstr + 1 + sizeof(WORD);
299     }
300     if (le->e32_cbnrestab)
301     {
302         printf( "\nNon-resident name table:\n" );
303         pstr = (const unsigned char *)base + le->e32_nrestab;
304         while (*pstr)
305         {
306             printf( " %4d: %*.*s\n", get_word(pstr + *pstr + 1), *pstr, *pstr,
307                     pstr + 1 );
308             pstr += *pstr + 1 + sizeof(WORD);
309         }
310     }
311 }
312
313 static void dump_le_resources( const void *base, const IMAGE_VXD_HEADER *le )
314 {
315     printf( "\nResources:\n" );
316     printf( "    Not Implemented\n" );
317 }
318
319 static void dump_le_modules( const void *base, const IMAGE_VXD_HEADER *le )
320 {
321     printf( "\nImported modulename table:\n" );
322     printf( "    Not Implemented\n" );
323 }
324
325 static void dump_le_entries( const void *base, const IMAGE_VXD_HEADER *le )
326 {
327     printf( "\nEntry table:\n" );
328     printf( "    Not Implemented\n" );
329 }
330
331 static void dump_le_fixups( const void *base, const IMAGE_VXD_HEADER *le )
332 {
333     printf( "\nFixup table:\n" );
334     printf( "    Not Implemented\n" );
335 }
336
337 static void dump_le_VxD( const void *base, const IMAGE_VXD_HEADER *le )
338 {
339     printf( "\nVxD descriptor:\n" );
340     printf( "    Not Implemented\n" );
341 }
342
343 void le_dump( const void *exe, size_t exe_size )
344 {
345     const IMAGE_DOS_HEADER *dos = exe;
346     const IMAGE_VXD_HEADER *le;
347
348     le = (const IMAGE_VXD_HEADER*)((const char *)dos + dos->e_lfanew);
349
350     dump_le_header( le );
351     dump_le_objects( exe, le );
352     dump_le_resources( exe, le );
353     dump_le_names( exe, le );
354     dump_le_entries( exe, le );
355     dump_le_modules( exe, le );
356     dump_le_fixups( exe, le );
357     dump_le_VxD( exe, le );
358 }