| /* | |
| * Dumping of LE binaries | |
| * | |
| * Copyright 2004 Robert Reif | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #include "config.h" | |
| #include "wine/port.h" | |
| #include <fcntl.h> | |
| #include <stdarg.h> | |
| #include <stdio.h> | |
| #ifdef HAVE_UNISTD_H | |
| #include <unistd.h> | |
| #endif | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "winedump.h" | |
| struct o32_obj | |
| { | |
| unsigned long o32_size; | |
| unsigned long o32_base; | |
| unsigned long o32_flags; | |
| unsigned long o32_pagemap; | |
| unsigned long o32_mapsize; | |
| char o32_name[4]; | |
| }; | |
| struct o32_map | |
| { | |
| unsigned short o32_pagedataoffset; | |
| unsigned char o32_pagesize; | |
| unsigned char o32_pageflags; | |
| }; | |
| struct b32_bundle | |
| { | |
| unsigned char b32_cnt; | |
| unsigned char b32_type; | |
| }; | |
| struct vxd_descriptor | |
| { | |
| unsigned long next; | |
| unsigned short sdk_version; | |
| unsigned short device_number; | |
| unsigned char version_major; | |
| unsigned char version_minor; | |
| unsigned short flags; | |
| char name[8]; | |
| unsigned long init_order; | |
| unsigned long ctrl_ofs; | |
| unsigned long v86_ctrl_ofs; | |
| unsigned long pm_ctrl_ofs; | |
| unsigned long v86_ctrl_csip; | |
| unsigned long pm_ctrl_csip; | |
| unsigned long rm_ref_data; | |
| unsigned long service_table_ofs; | |
| unsigned long service_table_size; | |
| unsigned long win32_service_table_ofs; | |
| unsigned long prev; | |
| unsigned long size; | |
| unsigned long reserved0; | |
| unsigned long reserved1; | |
| unsigned long reserved2; | |
| }; | |
| static inline WORD get_word( const BYTE *ptr ) | |
| { | |
| return ptr[0] | (ptr[1] << 8); | |
| } | |
| static void dump_le_header( const IMAGE_VXD_HEADER *le ) | |
| { | |
| printf( "File header:\n" ); | |
| printf( " Magic: %04x (%c%c)\n", | |
| le->e32_magic, LOBYTE(le->e32_magic), HIBYTE(le->e32_magic)); | |
| printf( " Byte order: %s\n", | |
| le->e32_border == 0 ? "little-indian" : "big-endian"); | |
| printf( " Word order: %s\n", | |
| le->e32_worder == 0 ? "little-indian" : "big-endian"); | |
| printf( " Executable format level: %d\n", | |
| le->e32_level); | |
| printf( " CPU type: %s\n", | |
| le->e32_cpu == 0x01 ? "Intel 80286" : | |
| le->e32_cpu == 0x02 ? "Intel 80386" : | |
| le->e32_cpu == 0x03 ? "Intel 80486" : | |
| le->e32_cpu == 0x04 ? "Intel 80586" : | |
| le->e32_cpu == 0x20 ? "Intel i860 (N10)" : | |
| le->e32_cpu == 0x21 ? "Intel i860 (N11)" : | |
| le->e32_cpu == 0x40 ? "MIPS Mark I" : | |
| le->e32_cpu == 0x41 ? "MIPS Mark II" : | |
| le->e32_cpu == 0x42 ? "MIPS Mark III" : | |
| "Unknown"); | |
| printf( " Target operating system: %s\n", | |
| le->e32_os == 0x01 ? "OS/2" : | |
| le->e32_os == 0x02 ? "Windows" : | |
| le->e32_os == 0x03 ? "DOS 4.x" : | |
| le->e32_os == 0x04 ? "Windows 386" : | |
| "Unknown"); | |
| printf( " Module version: %d\n", | |
| le->e32_ver); | |
| printf( " Module type flags: %08x\n", | |
| le->e32_mflags); | |
| if (le->e32_mflags & 0x8000) | |
| { | |
| if (le->e32_mflags & 0x0004) | |
| printf( " Global initialization\n"); | |
| else | |
| printf( " Per-Process initialization\n"); | |
| if (le->e32_mflags & 0x0010) | |
| printf( " No internal fixup\n"); | |
| if (le->e32_mflags & 0x0020) | |
| printf( " No external fixup\n"); | |
| if ((le->e32_mflags & 0x0700) == 0x0100) | |
| printf( " Incompatible with PM windowing\n"); | |
| else if ((le->e32_mflags & 0x0700) == 0x0200) | |
| printf( " Compatible with PM windowing\n"); | |
| else if ((le->e32_mflags & 0x0700) == 0x0300) | |
| printf( " Uses PM windowing API\n"); | |
| if (le->e32_mflags & 0x2000) | |
| printf( " Module not loadable\n"); | |
| if (le->e32_mflags & 0x8000) | |
| printf( " Module is DLL\n"); | |
| } | |
| printf( " Number of memory pages: %d\n", | |
| le->e32_mpages); | |
| printf( " Initial object CS number: %08x\n", | |
| le->e32_startobj); | |
| printf( " Initial EIP: %08x\n", | |
| le->e32_eip); | |
| printf( " Initial object SS number: %08x\n", | |
| le->e32_stackobj); | |
| printf( " Initial ESP: %08x\n", | |
| le->e32_esp); | |
| printf( " Memory page size: %d\n", | |
| le->e32_pagesize); | |
| printf( " Bytes on last page: %d\n", | |
| le->e32_lastpagesize); | |
| printf( " Fix-up section size: %d\n", | |
| le->e32_fixupsize); | |
| printf( " Fix-up section checksum: %08x\n", | |
| le->e32_fixupsum); | |
| printf( " Loader section size: %d\n", | |
| le->e32_ldrsize); | |
| printf( " Loader section checksum: %08x\n", | |
| le->e32_ldrsum); | |
| printf( " Offset of object table: %08x\n", | |
| le->e32_objtab); | |
| printf( " Object table entries: %d\n", | |
| le->e32_objcnt); | |
| printf( " Object page map offset: %08x\n", | |
| le->e32_objmap); | |
| printf( " Object iterate data map offset: %08x\n", | |
| le->e32_itermap); | |
| printf( " Resource table offset: %08x\n", | |
| le->e32_rsrctab); | |
| printf( " Resource table entries: %d\n", | |
| le->e32_rsrccnt); | |
| printf( " Resident names table offset: %08x\n", | |
| le->e32_restab); | |
| printf( " Entry table offset: %08x\n", | |
| le->e32_enttab); | |
| printf( " Module directives table offset: %08x\n", | |
| le->e32_dirtab); | |
| printf( " Module directives entries: %d\n", | |
| le->e32_dircnt); | |
| printf( " Fix-up page table offset: %08x\n", | |
| le->e32_fpagetab); | |
| printf( " Fix-up record table offset: %08x\n", | |
| le->e32_frectab); | |
| printf( " Imported modules name table offset: %08x\n", | |
| le->e32_impmod); | |
| printf( " Imported modules count: %d\n", | |
| le->e32_impmodcnt); | |
| printf( " Imported procedure name table offset: %08x\n", | |
| le->e32_impproc); | |
| printf( " Per-page checksum table offset: %08x\n", | |
| le->e32_pagesum); | |
| printf( " Data pages offset from top of table: %08x\n", | |
| le->e32_datapage); | |
| printf( " Preload page count: %08x\n", | |
| le->e32_preload); | |
| printf( " Non-resident names table offset: %08x\n", | |
| le->e32_nrestab); | |
| printf( " Non-resident names table length: %d\n", | |
| le->e32_cbnrestab); | |
| printf( " Non-resident names table checksum: %08x\n", | |
| le->e32_nressum); | |
| printf( " Automatic data object: %08x\n", | |
| le->e32_autodata); | |
| printf( " Debug information offset: %08x\n", | |
| le->e32_debuginfo); | |
| printf( " Debug information length: %d\n", | |
| le->e32_debuglen); | |
| printf( " Preload instance pages number: %d\n", | |
| le->e32_instpreload); | |
| printf( " Demand instance pages number: %d\n", | |
| le->e32_instdemand); | |
| printf( " Extra heap allocation: %d\n", | |
| le->e32_heapsize); | |
| printf( " VxD resource table offset: %08x\n", | |
| le->e32_winresoff); | |
| printf( " Size of VxD resource table: %d\n", | |
| le->e32_winreslen); | |
| printf( " VxD identifier: %x\n", | |
| le->e32_devid); | |
| printf( " VxD DDK version: %x\n", | |
| le->e32_ddkver); | |
| } | |
| static void dump_le_objects( const IMAGE_VXD_HEADER *le ) | |
| { | |
| const struct o32_obj *pobj; | |
| unsigned int i; | |
| printf("\nObject table:\n"); | |
| pobj = (const struct o32_obj *)((const unsigned char *)le + le->e32_objtab); | |
| for (i = 0; i < le->e32_objcnt; i++) | |
| { | |
| unsigned int j; | |
| const struct o32_map *pmap=0; | |
| printf(" Obj. Rel.Base Codesize Flags Tableidx Tablesize Name\n"); | |
| printf(" %04X %08lx %08lx %08lx %08lx %08lx ", i + 1, | |
| pobj->o32_base, pobj->o32_size, pobj->o32_flags, | |
| pobj->o32_pagemap, pobj->o32_mapsize); | |
| for (j = 0; j < 4; j++) | |
| { | |
| if (isprint(pobj->o32_name[j])) | |
| printf("%c", pobj->o32_name[j]); | |
| else | |
| printf("."); | |
| } | |
| printf("\n"); | |
| if(pobj->o32_flags & 0x0001) | |
| printf("\tReadable\n"); | |
| if(pobj->o32_flags & 0x0002) | |
| printf("\tWritable\n"); | |
| if(pobj->o32_flags & 0x0004) | |
| printf("\tExecutable\n"); | |
| if(pobj->o32_flags & 0x0008) | |
| printf("\tResource\n"); | |
| if(pobj->o32_flags & 0x0010) | |
| printf("\tDiscardable\n"); | |
| if(pobj->o32_flags & 0x0020) | |
| printf("\tShared\n"); | |
| if(pobj->o32_flags & 0x0040) | |
| printf("\tPreloaded\n"); | |
| if(pobj->o32_flags & 0x0080) | |
| printf("\tInvalid\n"); | |
| if(pobj->o32_flags & 0x2000) | |
| printf("\tUse 32\n"); | |
| printf(" Page tables:\n"); | |
| printf(" Tableidx Offset Flags\n"); | |
| pmap = (const struct o32_map *)((const unsigned char *)le + le->e32_objmap); | |
| pmap = &(pmap[pobj->o32_pagemap - 1]); | |
| for (j = 0; j < pobj->o32_mapsize; j++) | |
| { | |
| printf(" %08lx %06x %02x\n", | |
| pobj->o32_pagemap + j, | |
| (pmap->o32_pagedataoffset << 8) + pmap->o32_pagesize, | |
| (int)pmap->o32_pageflags); | |
| pmap++; | |
| } | |
| pobj++; | |
| } | |
| } | |
| static void dump_le_names( const IMAGE_VXD_HEADER *le ) | |
| { | |
| const unsigned char *pstr = (const unsigned char *)le + le->e32_restab; | |
| printf( "\nResident name table:\n" ); | |
| while (*pstr) | |
| { | |
| printf( " %4d: %*.*s\n", get_word(pstr + *pstr + 1), *pstr, *pstr, | |
| pstr + 1 ); | |
| pstr += *pstr + 1 + sizeof(WORD); | |
| } | |
| if (le->e32_cbnrestab) | |
| { | |
| printf( "\nNon-resident name table:\n" ); | |
| pstr = PRD(le->e32_nrestab, 0); | |
| while (*pstr) | |
| { | |
| printf( " %4d: %*.*s\n", get_word(pstr + *pstr + 1), *pstr, *pstr, | |
| pstr + 1 ); | |
| pstr += *pstr + 1 + sizeof(WORD); | |
| } | |
| } | |
| } | |
| static void dump_le_resources( const IMAGE_VXD_HEADER *le ) | |
| { | |
| printf( "\nResources:\n" ); | |
| printf( " Not Implemented\n" ); | |
| } | |
| static void dump_le_modules( const IMAGE_VXD_HEADER *le ) | |
| { | |
| printf( "\nImported modulename table:\n" ); | |
| printf( " Not Implemented\n" ); | |
| } | |
| static void dump_le_entries( const IMAGE_VXD_HEADER *le ) | |
| { | |
| printf( "\nEntry table:\n" ); | |
| printf( " Not Implemented\n" ); | |
| } | |
| static void dump_le_fixups( const IMAGE_VXD_HEADER *le ) | |
| { | |
| printf( "\nFixup table:\n" ); | |
| printf( " Not Implemented\n" ); | |
| } | |
| static void dump_le_VxD( const IMAGE_VXD_HEADER *le ) | |
| { | |
| printf( "\nVxD descriptor:\n" ); | |
| printf( " Not Implemented\n" ); | |
| } | |
| void le_dump( void ) | |
| { | |
| const IMAGE_DOS_HEADER *dos; | |
| const IMAGE_VXD_HEADER *le; | |
| dos = PRD(0, sizeof(*dos)); | |
| if (!dos) return; | |
| le = PRD(dos->e_lfanew, sizeof(*le)); | |
| dump_le_header( le ); | |
| dump_le_objects( le ); | |
| dump_le_resources( le ); | |
| dump_le_names( le ); | |
| dump_le_entries( le ); | |
| dump_le_modules( le ); | |
| dump_le_fixups( le ); | |
| dump_le_VxD( le ); | |
| } |