|
|
/*++
Copyright (c) 1992-2000 Microsoft Corporation
Module Name:
dlls.c
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
VOID DllsExtension( PCSTR lpArgumentString, ULONG64 ProcessPeb );
DECLARE_API( dlls )
/*++
Routine Description:
Dump user mode dlls (Kernel debugging)
Arguments:
args - [address [detail]]
Return Value:
None
--*/
{ ULONG64 Process, Peb; INIT_API(); Peb = GetExpression("@$peb"); DllsExtension( args, Peb ); EXIT_API(); return S_OK;
}
void ShowImageVersionInfo( ULONG64 DllBase ) { VS_FIXEDFILEINFO FixedVer; ULONG SizeRead; CHAR VersionBuffer[100]; CHAR FileStr[MAX_PATH]= {0}; BOOL ResFileVerStrOk = FALSE; BOOL ResProdVerStrOk = FALSE; struct LANGANDCODEPAGE { WORD wLanguage; WORD wCodePage; } Translate; if (g_ExtSymbols->GetModuleVersionInformation(DEBUG_ANY_ID, DllBase, "\\VarFileInfo\\Translation", (PVOID) &Translate, sizeof(Translate), &SizeRead) == S_OK) { sprintf(VersionBuffer, "\\StringFileInfo\\%04X%04X\\CompanyName", Translate.wLanguage, Translate.wCodePage);
if (g_ExtSymbols->GetModuleVersionInformation(DEBUG_ANY_ID, DllBase, VersionBuffer, (PVOID) FileStr, sizeof(FileStr), &SizeRead) == S_OK) { FileStr[SizeRead] = 0; dprintf(" Company Name %s\n", FileStr); } sprintf(VersionBuffer, "\\StringFileInfo\\%04X%04X\\ProductName", Translate.wLanguage, Translate.wCodePage);
if (g_ExtSymbols->GetModuleVersionInformation(DEBUG_ANY_ID, DllBase, VersionBuffer, (PVOID) FileStr, sizeof(FileStr), &SizeRead) == S_OK) { FileStr[SizeRead] = 0; dprintf(" Product Name %s\n", FileStr); } sprintf(VersionBuffer, "\\StringFileInfo\\%04X%04X\\ProductVersion", Translate.wLanguage, Translate.wCodePage);
if (g_ExtSymbols->GetModuleVersionInformation(DEBUG_ANY_ID, DllBase, VersionBuffer, (PVOID) FileStr, sizeof(FileStr), &SizeRead) == S_OK) { ResProdVerStrOk = TRUE; FileStr[SizeRead] = 0; dprintf(" Product Version %s\n", FileStr); } sprintf(VersionBuffer, "\\StringFileInfo\\%04X%04X\\OriginalFilename", Translate.wLanguage, Translate.wCodePage);
if (g_ExtSymbols->GetModuleVersionInformation(DEBUG_ANY_ID, DllBase, VersionBuffer, (PVOID) FileStr, sizeof(FileStr), &SizeRead) == S_OK) { FileStr[SizeRead] = 0; dprintf(" Original Filename %s\n", FileStr); } sprintf(VersionBuffer, "\\StringFileInfo\\%04X%04X\\FileDescription", Translate.wLanguage, Translate.wCodePage);
if (g_ExtSymbols->GetModuleVersionInformation(DEBUG_ANY_ID, DllBase, VersionBuffer, (PVOID) FileStr, sizeof(FileStr), &SizeRead) == S_OK) { FileStr[SizeRead] = 0; dprintf(" File Description %s\n", FileStr); } sprintf(VersionBuffer, "\\StringFileInfo\\%04X%04X\\FileVersion", Translate.wLanguage, Translate.wCodePage); if (g_ExtSymbols->GetModuleVersionInformation(DEBUG_ANY_ID, DllBase, VersionBuffer, (PVOID) FileStr, sizeof(FileStr), &SizeRead) == S_OK) { FileStr[SizeRead] = 0; dprintf(" File Version %s\n", FileStr); ResFileVerStrOk = TRUE; } }
if (g_ExtSymbols->GetModuleVersionInformation(DEBUG_ANY_ID, DllBase, "\\", &FixedVer, sizeof(FixedVer), &SizeRead) == S_OK) { if (!ResFileVerStrOk) { dprintf(" File version %d.%d.%d.%d\n", FixedVer.dwFileVersionMS >> 16, FixedVer.dwFileVersionMS & 0xFFFF, FixedVer.dwFileVersionLS >> 16, FixedVer.dwFileVersionLS & 0xFFFF);
} if (!ResProdVerStrOk) { dprintf(" Product Version %d.%d.%d.%d\n", FixedVer.dwProductVersionMS >> 16, FixedVer.dwProductVersionMS & 0xFFFF, FixedVer.dwProductVersionLS >> 16, FixedVer.dwProductVersionLS & 0xFFFF); } } }
typedef enum { Memory = 1, Load = 2, Init = 3 } ELOAD_ORDER;
VOID DllsExtension( PCSTR lpArgumentString, ULONG64 ProcessPeb ) { BOOL b; ULONG64 pLdrEntry; ULONG64 PebLdrAddress; ULONG Offset; ULONG64 Next; WCHAR StringData[MAX_PATH+1]; BOOL SingleEntry; BOOL DoHeaders; BOOL DoSections; BOOL DoAll; BOOL ShowVersionInfo; PSTR lpArgs = (PSTR)lpArgumentString; PSTR p; ULONG64 addrContaining = 0; ELOAD_ORDER OrderList = Load; ULONG64 OrderModuleListStart; ULONG64 DllBase;
SingleEntry = FALSE; DoAll = FALSE; DoHeaders = FALSE; DoSections = FALSE; ShowVersionInfo = FALSE;
#if 0
while ( lpArgumentString != NULL && *lpArgumentString ) { if (*lpArgumentString != ' ') { sscanf(lpArgumentString,"%lx",&pLdrEntry); SingleEntry = TRUE; goto dumpsingleentry; }
lpArgumentString++; } #endif
while (*lpArgs) {
while (isspace(*lpArgs)) { lpArgs++; }
if (*lpArgs == '/' || *lpArgs == '-') {
// process switch
switch (*++lpArgs) {
case 'a': // dump everything we can
case 'A': ++lpArgs; DoAll = TRUE; break;
case 'c': // dump only the dll containing the specified address
case 'C': lpArgs += 2; // step over the c and the space.
addrContaining = GetExpression(lpArgs);
while (*lpArgs && (!isspace(*lpArgs))) { lpArgs++; }
if (addrContaining != 0) { dprintf("Dump dll containing 0x%p:\n", addrContaining); } else { dprintf("-c flag requires and address arguement\n"); return; } break;
default: // invalid switch
case 'h': // help
case 'H': case '?':
dprintf("Usage: dlls [options] [address]\n"); dprintf("\n"); dprintf("Displays loader table entries. Optionally\n"); dprintf("dumps image and section headers.\n"); dprintf("\n"); dprintf("Options:\n"); dprintf("\n"); dprintf(" -a Dump everything\n"); dprintf(" -c nnn Dump dll containing address nnn\n"); dprintf(" -f Dump file headers\n"); dprintf(" -i Dump dll's in Init order\n"); dprintf(" -l Dump dll's in Load order (the default)\n"); dprintf(" -m Dump dll's in Memory order\n"); dprintf(" -s Dump section headers\n"); dprintf(" -v Dump version info from resource section\n"); dprintf("\n");
return;
case 'f': case 'F': ++lpArgs; DoAll = FALSE; DoHeaders = TRUE; break;
case 'm': // dump in memory order
case 'M': ++lpArgs; OrderList = Memory; break;
case 'i': // dump in init order
case 'I': ++lpArgs; OrderList = Init; break;
case 'l': // dump in load order
case 'L': ++lpArgs; OrderList = Load; break;
case 's': case 'S': ++lpArgs; DoAll = FALSE; DoSections = TRUE; break; case 'v': case 'V': ++lpArgs; ShowVersionInfo = TRUE; break; }
} else if (*lpArgs) { CHAR c;
if (SingleEntry) { dprintf("Invalid extra argument\n"); return; }
p = lpArgs; while (*p && !isspace(*p)) { p++; } c = *p; *p = 0;
pLdrEntry = GetExpression(lpArgs); SingleEntry = TRUE;
*p = c; lpArgs=p;
}
}
if (SingleEntry) { goto dumpsingleentry; }
//
// Capture PebLdrData
//
GetFieldValue(ProcessPeb, "nt!_PEB", "Ldr", PebLdrAddress); if (InitTypeRead(PebLdrAddress, nt!_PEB_LDR_DATA)) { dprintf( " Unable to read nt!_PEB_LDR_DATA type at %p\n", PebLdrAddress ); return; }
//
// Walk through the loaded module table and display all ldr data
//
switch (OrderList) { case Memory: GetFieldOffset("nt!_PEB_LDR_DATA","InMemoryOrderModuleList", &Offset); OrderModuleListStart = PebLdrAddress + Offset; Next = ReadField(InMemoryOrderModuleList.Flink); break;
case Init: GetFieldOffset("nt!_PEB_LDR_DATA","InInitializationOrderModuleList", &Offset); OrderModuleListStart = PebLdrAddress + Offset; Next = ReadField(InInitializationOrderModuleList.Flink); break;
default: case Load: GetFieldOffset("nt!_PEB_LDR_DATA","InLoadOrderModuleList", &Offset); OrderModuleListStart = PebLdrAddress + Offset; Next = ReadField(InLoadOrderModuleList.Flink); break; }
while (Next != OrderModuleListStart) { ULONG Length;
if (CheckControlC()) { return; }
switch (OrderList) { case Memory: GetFieldOffset("nt!_LDR_DATA_TABLE_ENTRY","InMemoryOrderLinks", &Offset); pLdrEntry = Next - Offset; break;
case Init: GetFieldOffset("nt!_LDR_DATA_TABLE_ENTRY","InInitializationOrderLinks", &Offset); pLdrEntry = Next - Offset; break;
default: case Load: GetFieldOffset("nt!_LDR_DATA_TABLE_ENTRY","InLoadOrderLinks", &Offset); pLdrEntry = Next - Offset; break; }
//
// Capture LdrEntry
//
dumpsingleentry:
if (InitTypeRead(pLdrEntry, nt!_LDR_DATA_TABLE_ENTRY)) { dprintf( " Unable to read Ldr Entry at %p\n", pLdrEntry ); return; }
Length = (ULONG) ReadField(FullDllName.Length); if (Length >= sizeof(StringData)) { Length = sizeof(StringData) -1; } ZeroMemory( StringData, sizeof( StringData ) ); b = ReadMemory( ReadField(FullDllName.Buffer), StringData, Length, NULL ); if (!b) { dprintf( " Unable to read Module Name\n" ); ZeroMemory( StringData, sizeof( StringData ) ); }
//
// Dump the ldr entry data
// (dump all the entries if no containing address specified)
//
if ((addrContaining == 0) || ((ReadField(DllBase) <= addrContaining) && (addrContaining <= (ReadField(DllBase) + ReadField(SizeOfImage))) ) ) { ULONG Flags;
dprintf( "\n" ); dprintf( "0x%08p: %ws\n", pLdrEntry, StringData[0] ? StringData : L"Unknown Module" ); dprintf( " Base 0x%08p EntryPoint 0x%08p Size 0x%08p\n", DllBase = ReadField(DllBase), ReadField(EntryPoint), ReadField(SizeOfImage) ); dprintf( " Flags 0x%08x LoadCount 0x%08x TlsIndex 0x%08x\n", Flags = (ULONG) ReadField(Flags), (ULONG) ReadField(LoadCount), (ULONG) ReadField(TlsIndex) );
if (Flags & LDRP_STATIC_LINK) { dprintf( " LDRP_STATIC_LINK\n" ); } if (Flags & LDRP_IMAGE_DLL) { dprintf( " LDRP_IMAGE_DLL\n" ); } if (Flags & LDRP_LOAD_IN_PROGRESS) { dprintf( " LDRP_LOAD_IN_PROGRESS\n" ); } if (Flags & LDRP_UNLOAD_IN_PROGRESS) { dprintf( " LDRP_UNLOAD_IN_PROGRESS\n" ); } if (Flags & LDRP_ENTRY_PROCESSED) { dprintf( " LDRP_ENTRY_PROCESSED\n" ); } if (Flags & LDRP_ENTRY_INSERTED) { dprintf( " LDRP_ENTRY_INSERTED\n" ); } if (Flags & LDRP_CURRENT_LOAD) { dprintf( " LDRP_CURRENT_LOAD\n" ); } if (Flags & LDRP_FAILED_BUILTIN_LOAD) { dprintf( " LDRP_FAILED_BUILTIN_LOAD\n" ); } if (Flags & LDRP_DONT_CALL_FOR_THREADS) { dprintf( " LDRP_DONT_CALL_FOR_THREADS\n" ); } if (Flags & LDRP_PROCESS_ATTACH_CALLED) { dprintf( " LDRP_PROCESS_ATTACH_CALLED\n" ); } if (Flags & LDRP_DEBUG_SYMBOLS_LOADED) { dprintf( " LDRP_DEBUG_SYMBOLS_LOADED\n" ); } if (Flags & LDRP_IMAGE_NOT_AT_BASE) { dprintf( " LDRP_IMAGE_NOT_AT_BASE\n" ); } if (Flags & LDRP_COR_IMAGE) { dprintf( " LDRP_COR_IMAGE\n" ); } if (Flags & LDRP_COR_OWNS_UNMAP) { dprintf( " LDR_COR_OWNS_UNMAP\n" ); } if (ShowVersionInfo) { ShowImageVersionInfo(DllBase); } }
switch (OrderList) { case Memory: Next = ReadField(InMemoryOrderLinks.Flink); break;
case Init: Next = ReadField(InInitializationOrderLinks.Flink); break;
default: case Load: Next = ReadField(InLoadOrderLinks.Flink); break; } if (DoAll || DoHeaders || DoSections) { DumpImage( ReadField(DllBase), DoAll || DoHeaders, DoAll || DoSections ); }
if (SingleEntry) { return; } } }
|