windows-nt/Source/XPSP1/NT/sdktools/debuggers/exts/extsdll/dlls.cpp
2020-09-26 16:20:57 +08:00

521 lines
15 KiB
C++

/*++
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();
GetPebAddress( 0, &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, "\\",
(PVOID) &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, "PEB", "Ldr", PebLdrAddress);
if (InitTypeRead(PebLdrAddress, PEB_LDR_DATA)) {
dprintf( " Unable to read 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("PEB_LDR_DATA","InMemoryOrderModuleList", &Offset);
OrderModuleListStart = PebLdrAddress + Offset;
Next = ReadField(InMemoryOrderModuleList.Flink);
break;
case Init:
GetFieldOffset("PEB_LDR_DATA","InInitializationOrderModuleList", &Offset);
OrderModuleListStart = PebLdrAddress + Offset;
Next = ReadField(InInitializationOrderModuleList.Flink);
break;
default:
case Load:
GetFieldOffset("PEB_LDR_DATA","InLoadOrderModuleList", &Offset);
OrderModuleListStart = PebLdrAddress + Offset;
Next = ReadField(InLoadOrderModuleList.Flink);
break;
}
while (Next != OrderModuleListStart) {
if (CheckControlC()) {
return;
}
switch (OrderList) {
case Memory:
GetFieldOffset("LDR_DATA_TABLE_ENTRY","InMemoryOrderLinks", &Offset);
pLdrEntry = Next - Offset;
break;
case Init:
GetFieldOffset("LDR_DATA_TABLE_ENTRY","InInitializationOrderLinks", &Offset);
pLdrEntry = Next - Offset;
break;
default:
case Load:
GetFieldOffset("LDR_DATA_TABLE_ENTRY","InLoadOrderLinks", &Offset);
pLdrEntry = Next - Offset;
break;
}
//
// Capture LdrEntry
//
dumpsingleentry:
if (InitTypeRead(pLdrEntry, LDR_DATA_TABLE_ENTRY)) {
dprintf( " Unable to read Ldr Entry at %p\n", pLdrEntry );
return;
}
ZeroMemory( StringData, sizeof( StringData ) );
b = ReadMemory( ReadField(FullDllName.Buffer),
StringData,
(ULONG) ReadField(FullDllName.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;
}
}
}