166 lines
5.8 KiB
C++
166 lines
5.8 KiB
C++
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// sips.cpp - Extension to find Singularity SIPs.
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
#include "singx86.h"
|
||
|
|
||
|
HRESULT DumpSip(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(sips) // 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;
|
||
|
}
|