///////////////////////////////////////////////////////////////////////////// // // procs.cpp - Extension to find Singularity Processes. // // Copyright (c) Microsoft Corporation. All rights reserved. // #include "singx86.h" HRESULT DumpProcess(ULONG64 address, bool stack, bool detail) { if (address == 0) { return S_FALSE; } HRESULT status = S_OK; Thread thread; EXT_CHECK(ThreadStruct.Read(address, &thread)); if (stack) { ExtOut(" thread=%p { tid=%03x pid=%03x ebp=%p, esp=%p, eip=%p }\n", address, (ULONG)(thread.context.threadIndex == 0xffff ? 0xfff : thread.context.threadIndex), (ULONG)(thread.context.processId == 0xffff ? 0xfff : thread.context.processId), thread.context.eip, thread.context.ebp, thread.context.esp); DEBUG_STACK_FRAME frames[10]; ULONG filled = 0; status = g_ExtControl->GetStackTrace(thread.context.ebp, thread.context.esp, thread.context.eip, frames, arrayof(frames), &filled); if (status == S_OK) { g_ExtClient->SetOutputLinePrefix(" "); g_ExtControl->OutputStackTrace(DEBUG_OUTPUT_NORMAL, frames, filled, detail ? (DEBUG_STACK_FRAME_ADDRESSES | DEBUG_STACK_COLUMN_NAMES | DEBUG_STACK_SOURCE_LINE) : 0); } } else { CHAR name[512]; ULONG64 displacement = 0; status = g_ExtSymbols->GetNameByOffset((ULONG64)thread.context.eip, name, arrayof(name), NULL, &displacement); if (status == S_OK) { ExtOut(" thread=%p { tid=%03x pid=%03x ebp=%p, esp=%p, eip=%p } %s+%I64d\n", address, (ULONG)(thread.context.threadIndex == 0xffff ? 0xfff : thread.context.threadIndex), (ULONG)(thread.context.processId == 0xffff ? 0xfff : thread.context.processId), thread.context.eip, thread.context.ebp, thread.context.esp, name, (LONG64)displacement); } else { ExtOut(" thread=%p { tid=%03x pid=%03x ebp=%p, esp=%p, eip=%p }\n", address, (ULONG)(thread.context.threadIndex == 0xffff ? 0xfff : thread.context.threadIndex), (ULONG)(thread.context.processId == 0xffff ? 0xfff : thread.context.processId), thread.context.eip, thread.context.ebp, thread.context.esp); } } Exit: return status; } EXT_DECL(procs) // Defines: PDEBUG_CLIENT Client, PCSTR args { EXT_ENTER(); // Defines: HRESULT status = S_OK; bool stack = false; bool detail = false; while (*args != '\0') { if (*args == '-' || *args == '/') { args++; switch (*args++) { case 'd': // detail case 'D': detail = !detail; break; case 's': // stack case 'S': stack = !stack; break; } while (*args != ' ') { args++; } } else { break; } } ULONG pointerSize = (g_ExtControl->IsPointer64Bit() == S_OK) ? 8 : 4; ULONG64 address = 0; ULONG64 procs = 0; ULONG type = 0; ULONG subtype = 0; ULONG64 module = 0; EXT_CHECK(g_ExtSymbols->GetOffsetByName("nt!Process::processTable", &address)); EXT_CHECK(g_ExtSymbols->GetOffsetTypeId(address, &type, &module)); EXT_CHECK(g_ExtData->ReadPointersVirtual(1, address, &procs)); ExtVerb("processTable: %p\n", procs); CHAR name[512]; EXT_CHECK(g_ExtSymbols->GetTypeName(module, type, name, arrayof(name), NULL)); ExtVerb(" processTable type: %s\n", name); int len = strlen(name); if (len > 3 && name[len-3] == '[' && name[len-2] == ']' && name[len-1] == '*') { name[len-3] = '\0'; EXT_CHECK(g_ExtSymbols->GetTypeId(module, name, &subtype)); EXT_CHECK(g_ExtSymbols->GetTypeName(module, subtype, name, arrayof(name), NULL)); ExtVerb(" processTable[] type: %s\n", name); } ULONG lengthOffset = 0; EXT_CHECK(g_ExtSymbols->GetFieldOffset(module, type, "overall_length", &lengthOffset)); ULONG valuesOffset = 0; EXT_CHECK(g_ExtSymbols->GetFieldOffset(module, type, "values", &valuesOffset)); ULONG length = 0; EXT_CHECK(g_ExtData->ReadVirtual(procs + lengthOffset, &length, sizeof(length), NULL)); ExtOut("processTable: %p [maximum %d entries]\n", procs, length); for (ULONG id = 0; id < length; id++) { ULONG64 process = 0; EXT_CHECK(g_ExtData->ReadPointersVirtual(1, procs + valuesOffset + id * pointerSize, &process)); if (process != 0) { if (detail) { ExtOut(" %p\n", process); } else { ExtOut(" %p\n", process); } } } EXT_LEAVE(); // Macro includes: return status; }