|
|
/***********************************************************************
* Microsoft (R) 32-Bit Incremental Linker * * Copyright (C) Microsoft Corp 1992-1996. All rights reserved. * * File: dmple.cpp * * File Comments: * * ***********************************************************************/
#include "link.h"
#include "exe_vxd.h"
#define Switch (pimageDump->Switch)
#ifdef DUMPLX
struct o32_map_lx { unsigned long o32_pagedataoffset; // File offset of page
unsigned short o32_pagesize; // Number of bytes of data
unsigned short o32_pageflags; };
#endif
static LONG foHdr; static struct e32_exe exe;
#if 0
#ifdef DUMPLX
const static char * const szLXModType[] = { "EXE", "DLL", "Unknown", "Protected DLL", "Physical Device Driver", "Virtual Device Driver", "Unknown", "Unknown" };
#endif
const static char * const szVXDType[] = { "Unknown", "Unknown", "Unknown", "Unknown", "Unknown", "Static", "Unknown", "Dynamic" }; #endif
struct { DWORD dwMask; const char *szName; } const rgo32flags[] = { { OBJRSRC, "Resource" }, { OBJDISCARD, "Discardable" }, { OBJSHARED, "Shared" }, { OBJPRELOAD, "Has preload pages" }, { OBJINVALID, "Has invalid pages" }, { OBJRESIDENT, "Resident" }, { OBJALIAS16, "16:16 alias" }, { OBJBIGDEF, "32-bit" }, { OBJCONFORM, "Conforming" }, { OBJIOPL, "Message" }, };
const char * const rgszLeAccess[] = { NULL, "Read Only", "Write Only", "Read Write", "Execute Only", "Execute Read", "Execute Write", "Execute Read Write", };
void DumpLeObjectHeader(size_t iobj, const o32_obj *pobj) { fprintf(InfoStream, "\n" "OBJECT HEADER #%X\n" "%8lX virtual size\n" "%8lX virtual address\n" "%8lX flags\n", iobj, O32_SIZE(*pobj), O32_BASE(*pobj), O32_FLAGS(*pobj));
if (O32_FLAGS(*pobj) & (OBJREAD | OBJWRITE | OBJEXEC)) { fprintf(InfoStream, " %s\n", rgszLeAccess[O32_FLAGS(*pobj) & 7]); }
for (size_t iflag = 0; iflag < sizeof(rgo32flags) / sizeof(rgo32flags[0]); iflag++) { if ((O32_FLAGS(*pobj) & rgo32flags[iflag].dwMask) == 0) { continue; }
const char *szName = rgo32flags[iflag].szName;
#ifdef DUMPLX
if ((dft == dftLX) && (rgo32flags[iflag].dwMask == OBJIOPL)) { szName = "IOPL"; } #endif // DUMPLX
fprintf(InfoStream, " %s\n", szName); }
fprintf(InfoStream, "%8lX map index\n" "%8lX map size\n" "%8lX reserved\n", O32_PAGEMAP(*pobj), O32_MAPSIZE(*pobj), O32_RESERVED(*pobj)); }
#ifdef DUMPLX
void DumpLxPageMap(size_t iobj, const o32_obj *pobj, const o32_map_lx *rgmap) { fprintf(InfoStream, " Logical File Page\n" " Page Offset Size Flags\n" " -------- -------- ---- ----------\n");
DWORD cmap = O32_MAPSIZE(*pobj);
const o32_map_lx *pmap = rgmap + O32_PAGEMAP(*pobj) - 1;
for (DWORD imap = 0; imap < cmap; imap++, pmap++) { DWORD fo = 0; const char *szType;
switch (pmap->o32_pageflags) { case VALID : fo = E32_DATAPAGE(exe); szType = "Valid"; break;
case ITERDATA : fo = E32_ITERMAP(exe); szType = "Iterated"; break;
case INVALID : szType = "Invalid"; break;
case ZEROED : szType = "Zeroed"; break;
case RANGE : szType = "Range"; break;
case 5 /* ITERDATA2 */ : fo = E32_DATAPAGE(exe); szType = "Compressed"; break;
default : szType = "Unknown"; break; }
if ((fo != 0) && (pmap->o32_pagedataoffset != 0)) { fo += pmap->o32_pagedataoffset << E32_LASTPAGESIZE(exe); }
fprintf(InfoStream, " %08lX %08lX %04lX %s\n", 1 + imap, fo, pmap->o32_pagesize, szType); } }
#endif // DUMPLX
void DumpLePageMap(size_t iobj, const o32_obj *pobj, const o32_map *rgmap) { fprintf(InfoStream, "\n" "OBJECT PAGE MAP #%X\n" "\n", iobj);
#ifdef DUMPLX
if (dft == dftLX) { DumpLxPageMap(iobj, pobj, (o32_map_lx *) rgmap); return; } #endif // DUMPLX
fprintf(InfoStream, " Logical Physical File Flags\n" " Page Page Offset Flags\n" " -------- -------- -------- --------\n");
DWORD cmap = O32_MAPSIZE(*pobj);
const o32_map *pmap = rgmap + O32_PAGEMAP(*pobj) - 1;
for (DWORD imap = 0; imap < cmap; imap++, pmap++) { DWORD fo = 0; const char *szType;
switch (PAGEFLAGS(*pmap)) { case VALID : fo = E32_DATAPAGE(exe); szType = "Valid"; break;
case ITERDATA : szType = "Iterated"; break;
case INVALID : szType = "Invalid"; break;
case ZEROED : szType = "Zeroed"; break;
case RANGE : szType = "Range"; break;
default : szType = "Unknown"; break; }
DWORD ippage = GETPAGEIDX(*pmap);
if ((fo != 0) && (ippage != 0)) { fo += (ippage - 1) * E32_PAGESIZE(exe); }
fprintf(InfoStream, " %08lX %08lX %08lX %s\n", 1 + imap, ippage, fo, szType); } }
#ifdef DUMPLX
void ReadLxIterData(INT FileReadHandle, BYTE *rgb, DWORD cbFile) { BYTE *pb = rgb;
while (cbFile > 0) { WORD wRepeat; WORD cb;
// Read the iteration record header
FileRead(FileReadHandle, &wRepeat, sizeof(WORD)); FileRead(FileReadHandle, &cb, sizeof(WORD));
cbFile -= sizeof(WORD) + sizeof(WORD);
if (cb == 0) { continue; }
if (wRepeat == 0) { FileSeek(FileReadHandle, cb, SEEK_CUR);
continue; }
const BYTE *pbSrc = pb;
FileRead(FileReadHandle, pb, cb); pb += cb;
while (--wRepeat > 0) { memcpy(pb, pbSrc, cb); pb += cb; }
cbFile -= cb; } }
void ReadLxIterData2(INT FileReadHandle, BYTE *rgb, DWORD cbFile) { BYTE *pb = rgb;
while (cbFile > 0) { BYTE bOpcode;
// Read opcode byte
FileRead(FileReadHandle, &bOpcode, sizeof(BYTE)); cbFile--;
switch (bOpcode & 3) { BYTE bCount; BYTE b; WORD w;
case 0 : if (bOpcode != 0) { bCount = bOpcode >> 2;
FileRead(FileReadHandle, pb, bCount); cbFile -= bCount;
pb += bCount; break; }
FileRead(FileReadHandle, &bCount, sizeof(BYTE)); cbFile--;
if (bCount == 0) { return; }
FileRead(FileReadHandle, &b, sizeof(BYTE)); cbFile--;
memset(pb, b, bCount); pb += bCount; break;
case 1 : FileRead(FileReadHandle, &b, sizeof(BYTE)); cbFile--;
w = ((WORD) b << 1) + ((bOpcode & 0x80) != 0x00);
bCount = (bOpcode >> 2) & 0x3; FileRead(FileReadHandle, pb, bCount); cbFile -= bCount;
pb += bCount;
bCount = ((bOpcode >> 4) & 0x7) + 3; memcpy(pb, pb - w, bCount); pb += bCount; break;
case 2 : FileRead(FileReadHandle, &b, sizeof(BYTE)); cbFile--;
w = ((WORD) b << 8) + bOpcode;
bCount = ((bOpcode >> 2) & 0x3) + 3; w >>= 4; memcpy(pb, pb - w, bCount); pb += bCount; break;
case 3 : FileRead(FileReadHandle, &w, sizeof(WORD)); cbFile -= sizeof(WORD);
bCount = (bOpcode >> 2) & 0xf; FileRead(FileReadHandle, pb, bCount); cbFile -= bCount;
pb += bCount;
bCount = ((bOpcode >> 6) & 0x3) + ((w << 2) & 0x3c); w >>= 4; memcpy(pb, pb - w, bCount); pb += bCount; break; } } }
void LoadLxObject(const o32_obj *pobj, const o32_map_lx *rgmap, BYTE *rgb) { DWORD cb = O32_SIZE(*pobj); DWORD cmap = O32_MAPSIZE(*pobj);
BYTE *pb = rgb;
const o32_map_lx *pmap = rgmap + O32_PAGEMAP(*pobj) - 1;
for (DWORD imap = 0; imap < cmap; imap++, pmap++, pb += E32_PAGESIZE(exe)) { DWORD fo;
switch (pmap->o32_pageflags) { case VALID : fo = E32_DATAPAGE(exe); break;
case ITERDATA : fo = E32_ITERMAP(exe); break;
case INVALID : case ZEROED : continue;
case 5 /* ITERDATA2 */ : fo = E32_DATAPAGE(exe); break;
default : printf("LINK : warning : Unknown page type (%u)\n", pmap->o32_pageflags); continue; }
fo += pmap->o32_pagedataoffset << E32_LASTPAGESIZE(exe);
if (FileSeek(FileReadHandle, fo, SEEK_SET) == -1) { Error(NULL, CANTSEEKFILE, fo); }
DWORD cbPage = pmap->o32_pagesize;
switch (pmap->o32_pageflags) { case VALID : FileRead(FileReadHandle, pb, cbPage); break;
case ITERDATA : ReadLxIterData(FileReadHandle, pb, cbPage); break;
case 5 /* ITERDATA2 */ : ReadLxIterData2(FileReadHandle, pb, cbPage); break; } } }
#endif // DUMPLX
DWORD CbLoadLeObject(const o32_obj *pobj, const o32_map *rgmap, BYTE **ppb) { *ppb = NULL;
DWORD cb = O32_SIZE(*pobj);
if (cb == 0) { return(0); }
DWORD cmap = O32_MAPSIZE(*pobj);
if (cmap == 0) { return(0); }
DWORD cbAlloc = (cb + E32_PAGESIZE(exe) - 1) & ~(E32_PAGESIZE(exe) - 1);
BYTE *pb = *ppb = (BYTE *) PvAllocZ(cbAlloc);
#ifdef DUMPLX
if (dft == dftLX) { LoadLxObject(pobj, (o32_map_lx *) rgmap, pb);
return(cb); } #endif // DUMPLX
const o32_map *pmap = rgmap + O32_PAGEMAP(*pobj) - 1;
for (DWORD imap = 0; imap < cmap; imap++, pmap++, pb += E32_PAGESIZE(exe)) { DWORD ippage = GETPAGEIDX(*pmap);
if (ippage == 0) { continue; }
if (PAGEFLAGS(*pmap) != VALID) { continue; }
DWORD fo = E32_DATAPAGE(exe) + (ippage - 1) * E32_PAGESIZE(exe);
if (FileSeek(FileReadHandle, fo, SEEK_SET) == -1) { Error(NULL, CANTSEEKFILE, fo); }
DWORD cbPage = E32_PAGESIZE(exe);
if (ippage == E32_MPAGES(exe)) { cbPage = E32_LASTPAGESIZE(exe); }
FileRead(FileReadHandle, pb, cbPage); }
return(cb); }
void DumpLeSections(void) { InternalError.Phase = "DumpLeSections";
o32_obj *rgobj = (o32_obj *) PvAlloc(E32_OBJCNT(exe) * sizeof(o32_obj));
FileSeek(FileReadHandle, foHdr + E32_OBJTAB(exe), SEEK_SET); FileRead(FileReadHandle, rgobj, E32_OBJCNT(exe) * sizeof(o32_obj));
size_t cbMap = E32_MPAGES(exe) * sizeof(o32_map);
#ifdef DUMPLX
if (dft == dftLX) { cbMap = E32_MPAGES(exe) * sizeof(o32_map_lx); } #endif // DUMPLX
o32_map *rgmap = (o32_map *) PvAlloc(cbMap);
FileSeek(FileReadHandle, foHdr + E32_OBJMAP(exe), SEEK_SET); FileRead(FileReadHandle, rgmap, cbMap);
const o32_obj *pobj = rgobj;
for (size_t iobj = 1; iobj <= E32_OBJCNT(exe); iobj++, pobj++) { if (Switch.Dump.Headers) { DumpLeObjectHeader(iobj, pobj);
if (O32_MAPSIZE(*pobj) != 0) { DumpLePageMap(iobj, pobj, rgmap); } }
BOOL fDisasm = Switch.Dump.Disasm && (O32_FLAGS(*pobj) & OBJEXEC); BOOL fRawData = Switch.Dump.RawData;
if (fDisasm || fRawData) { BYTE *pbRawData; DWORD cbRawData = CbLoadLeObject(pobj, rgmap, &pbRawData);
if (cbRawData != 0) { BOOL f16Bit = FALSE; DWORD addr = O32_BASE(*pobj);
if ((O32_FLAGS(*pobj) & OBJALIAS16) != 0) { f16Bit = TRUE; addr = ((DWORD) iobj) << 16; }
if (fDisasm) { fputc('\n', InfoStream);
DisasmBuffer(IMAGE_FILE_MACHINE_I386, f16Bit, addr, pbRawData, cbRawData, NULL, 0, 0, InfoStream); }
if (fRawData) { fprintf(InfoStream, "\nRAW DATA #%hX\n", iobj);
DumpRawData(addr, pbRawData, cbRawData); } }
FreePv(pbRawData); } }
FreePv(rgmap); FreePv(rgobj); }
void DumpLeFile(const char *szFilename) { foHdr = FileSeek(FileReadHandle, -(LONG) sizeof(DWORD), SEEK_CUR);
FileRead(FileReadHandle, &exe, sizeof(exe));
const char *szType;
if ((E32_OS(exe) == 4 /* NE_DEV386 */) && (E32_MFLAGS(exe) & E32NOTP) && (((E32_MFLAGS(exe) & E32MODMASK) == E32MODVDEV) || ((E32_MFLAGS(exe) & E32MODMASK) == E32MODVDEVDYN))) { szType = "VXD"; } else { szType = "LE Executable"; }
#ifdef DUMPLX
if (dft == dftLX) { szType = "LX Executable"; } #endif // DUMPLX
fprintf(InfoStream, "\nFile Type: %s\n", szType);
if (Switch.Dump.Headers) { fprintf(InfoStream, "\n" "%8hX magic number\n" "%8hX byte order\n" "%8hX word order\n" "%8lX executable format level\n" "%8hX CPU type (**)\n" "%8hX operating system (**)\n" "%8lX module version\n" "%8lX module flags\n" "%8lX number of memory pages\n" "%8lX object number of entry point\n" "%8lX offset of entry point\n" "%8lX object number of stack\n" "%8lX offset of stack\n" "%8lX memory page size\n", (E32_MAGIC2(exe) << 8) + E32_MAGIC1(exe), E32_BORDER(exe), E32_WORDER(exe), E32_LEVEL(exe), E32_CPU(exe), E32_OS(exe), E32_VER(exe), E32_MFLAGS(exe), E32_MPAGES(exe), E32_STARTOBJ(exe), E32_EIP(exe), E32_STACKOBJ(exe), E32_ESP(exe), E32_PAGESIZE(exe));
fprintf(InfoStream, #ifdef DUMPLX
(dft == dftLX) ? "%8lX page alignment shift\n" : #endif // DUMPLX
"%8lX bytes on last page\n", E32_LASTPAGESIZE(exe));
fprintf(InfoStream, "%8lX fixup section size\n" "%8lX fixup section checksum\n" "%8lX loader section size\n" "%8lX loader section checksum\n" "%8lX object table\n" "%8lX object table entries\n" "%8lX object map\n" "%8lX iterated data map\n" "%8lX resource table\n" "%8lX resource table entries\n" "%8lX resident names table\n" "%8lX entry table\n" "%8lX module directives table\n" "%8lX module directives entries\n" "%8lX fixup page table\n" "%8lX fixup record table\n" "%8lX imported modules name table\n" "%8lX imported modules\n" "%8lX imported procedures name table\n" "%8lX page checksum table\n" "%8lX enumerated data pages\n" "%8lX preload page count\n" "%8lX non-resident name table\n" "%8lX non-resident name table size\n" "%8lX non-resident name checksum\n" "%8lX automatic data object\n" "%8lX debug information\n" "%8lX debug information size\n" "%8lX preload instance page count\n" "%8lX demand instance page count\n" "%8lX extra heap allocation\n", E32_FIXUPSIZE(exe), E32_FIXUPSUM(exe), E32_LDRSIZE(exe), E32_LDRSUM(exe), E32_OBJTAB(exe), E32_OBJCNT(exe), E32_OBJMAP(exe), E32_ITERMAP(exe), E32_RSRCTAB(exe), E32_RSRCCNT(exe), E32_RESTAB(exe), E32_ENTTAB(exe), E32_DIRTAB(exe), E32_DIRCNT(exe), E32_FPAGETAB(exe), E32_FRECTAB(exe), E32_IMPMOD(exe), E32_IMPMODCNT(exe), E32_IMPPROC(exe), E32_PAGESUM(exe), E32_DATAPAGE(exe), E32_PRELOAD(exe), E32_NRESTAB(exe), E32_CBNRESTAB(exe), E32_NRESSUM(exe), E32_AUTODATA(exe), E32_DEBUGINFO(exe), E32_DEBUGLEN(exe), E32_INSTPRELOAD(exe), E32_INSTDEMAND(exe), E32_HEAPSIZE(exe));
BOOL fVXD = (E32_OS(exe) == 4 /* NE_DEV386 */) && (E32_MFLAGS(exe) & E32MODDLL);
#ifdef DUMPLX
if (dft == dftLX) { fVXD = FALSE; } #endif // DUMPLX
if (fVXD) { fprintf(InfoStream, "%8lX offset of Windows resources\n" "%8lX size of Windows resources\n" "%8hX device id\n" "%8hX DDK version\n", exe.e32_winresoff, exe.e32_winreslen, exe.Dev386_Device_ID, exe.Dev386_DDK_Version); } }
DumpLeSections(); }
|