singrdk/base/Windows/singx86/thread.cpp

316 lines
12 KiB
C++
Raw Normal View History

2008-03-05 09:52:00 -05:00
/////////////////////////////////////////////////////////////////////////////
//
// thread.cpp - Extension to select a Singularity thread.
//
2008-11-17 18:29:00 -05:00
// Copyright Microsoft Corporation. All rights reserved.
2008-03-05 09:52:00 -05:00
//
#include "singx86.h"
struct GDTE
{
USHORT limit;
USHORT base0_15;
BYTE base16_23;
BYTE access;
BYTE granularity;
BYTE base24_31;
};
static void Usage()
{
ExtOut("Usage:\n"
" !thread {options} thread_addr\n"
"Options:\n"
" -p show stack prior to interrupt or exception (if any)\n"
" -t show top stack (i.e. interrupt or exception (if any))\n"
"Notes:\n"
" There are potentially three contexts associated with a thread:\n"
" the scheduler context, the interrupt context, and the exception\n"
" context. The -p flag is only useful if an exception or interrupt\n"
" has occurred. Using -p -p always gets the scheduler context.");
}
static PCSTR ParseArguments(PCSTR args,
OUT PLONG plPriorStack,
OUT PLONG plTopStack)
{
*plPriorStack = 0;
*plTopStack = 0;
while (*args != '\0') {
while (*args == ' ' || *args == '\t') {
args++;
}
if (*args != '-' && *args != '/') {
break;
}
args++;
switch (*args++) {
case 'p':
*plPriorStack = *plPriorStack + 1;
break;
case 't':
*plTopStack = 1;
break;
default:
Usage();
return NULL;
}
}
return args;
}
EXT_DECL(thread) // Defines: PDEBUG_CLIENT Client, PCSTR args
{
EXT_ENTER(); // Defines: HRESULT status = S_OK;
Thread thread;
ThreadContext tc;
LONG priorStack = 0;
LONG topStack = 0;
ULONG64 address = 0;
if ((args = ParseArguments(args, &priorStack, &topStack)) == NULL) {
status = S_FALSE;
goto Exit;
}
status = ExtEvalU64(&args, &address);
if (status != S_OK) {
2008-11-17 18:29:00 -05:00
//// This code \/ needs to be replicated for ARM.
2008-03-05 09:52:00 -05:00
ULONG indexGdtr = 0;
ULONG indexGdtl = 0;
ULONG indexFs = 0;
EXT_CHECK(g_ExtRegisters->GetIndexByName("gdtr", &indexGdtr));
EXT_CHECK(g_ExtRegisters->GetIndexByName("gdtl", &indexGdtl));
2008-11-17 18:29:00 -05:00
if (TargetMachine == IMAGE_FILE_MACHINE_AMD64) {
EXT_CHECK(g_ExtRegisters->GetIndexByName("gs", &indexFs));
}
else if (TargetMachine == IMAGE_FILE_MACHINE_I386) {
EXT_CHECK(g_ExtRegisters->GetIndexByName("fs", &indexFs));
}
2008-03-05 09:52:00 -05:00
ExtVerb("gdtr: %04x\n", indexGdtr);
ExtVerb("gdtl: %04x\n", indexGdtl);
ExtVerb("fs: %04x\n", indexFs);
ULONG64 gdtr;
ULONG64 gdtl;
ULONG64 fs;
DEBUG_VALUE v;
EXT_CHECK(g_ExtRegisters->GetValue(indexGdtr, &v));
ExtVerb("gdtr: %04x -> %p\n", indexGdtr, v.I64);
gdtr = v.I64;
EXT_CHECK(g_ExtRegisters->GetValue(indexGdtl, &v));
gdtl = v.I64;
ExtVerb("gdtl: %04x -> %p\n", indexGdtl, v.I64);
EXT_CHECK(g_ExtRegisters->GetValue(indexFs, &v));
fs = v.I64;
ExtVerb("fs: %04x -> %p\n", indexFs, v.I64);
GDTE fse;
ZeroMemory(&fse, sizeof(fse));
2008-11-17 18:29:00 -05:00
EXT_CHECK(TraceRead(gdtr + fs, &fse, sizeof(fse)));
2008-03-05 09:52:00 -05:00
ULONG64 fs0 = ((ULONG64)fse.base0_15 +
((ULONG64)fse.base16_23 << 16) |
((ULONG64)fse.base24_31 << 24));
ExtVerb("fs[0] = %p\n", fs0);
2008-11-17 18:29:00 -05:00
// BUG: does not get fs offset from HAL!!!
ProcessorContext *ppc;
EXT_CHECK(TraceRead(fs0, &ppc, sizeof(ppc)));
2008-03-05 09:52:00 -05:00
ProcessorContext pc;
2008-11-17 18:29:00 -05:00
EXT_CHECK(ProcessorContextStruct.Read((ULONG64)ppc, &pc));
2008-03-05 09:52:00 -05:00
ExtVerb(" _processor: %p\n", pc._processor);
ExtVerb(" exception: %p\n", pc.exception);
2008-11-17 18:29:00 -05:00
ExtVerb(" cpuId: %p\n", pc.cpuRecord.id);
ExtOut("%d: Int Stack: %p..%p\n",
(int)pc.cpuRecord.id,
pc.cpuRecord.interruptStackLimit, pc.cpuRecord.interruptStackBegin - 1);
ThreadContext *ptc;
EXT_CHECK(TraceRead(fs0+sizeof(void*), &ptc, sizeof(ptc)));
2008-03-05 09:52:00 -05:00
ThreadContext tc;
2008-11-17 18:29:00 -05:00
EXT_CHECK(ProcessorContextStruct.Read((ULONG64)ptc, &tc));
ExtVerb(" threadContext: %p\n", ptc);
2008-03-05 09:52:00 -05:00
address = tc._thread;
2008-11-17 18:29:00 -05:00
//// This code /\ needs to be replicated for ARM.
2008-03-05 09:52:00 -05:00
}
if (address == 0) {
ExtErr("Null is invalid thread address.\n");
return S_FALSE;
}
2008-11-17 18:29:00 -05:00
EXT_CHECK(ThreadStruct->Read(address, &thread));
2008-03-05 09:52:00 -05:00
ULONG64 caddress[3];
int currentStack = 0;
2008-11-17 18:29:00 -05:00
caddress[0] = address + ThreadFields[0].offset; // Thread.context
2008-03-05 09:52:00 -05:00
if (thread.context.next) {
caddress[1] = thread.context.next;
currentStack++;
2008-11-17 18:29:00 -05:00
EXT_CHECK(ThreadContextStruct->Read(caddress[1], &tc));
2008-03-05 09:52:00 -05:00
if (tc.next) {
caddress[2] = tc.next;
2008-11-17 18:29:00 -05:00
EXT_CHECK(ThreadContextStruct->Read(caddress[2], &tc));
2008-03-05 09:52:00 -05:00
currentStack++;
}
}
if (topStack == 0) {
currentStack = 0;
}
else {
if (priorStack != 0) {
currentStack -= priorStack;
if (currentStack < 0) {
currentStack = 0;
}
}
}
2008-11-17 18:29:00 -05:00
EXT_CHECK(ThreadContextStruct->Read(caddress[currentStack], &tc));
if (TargetMachine == IMAGE_FILE_MACHINE_I386) {
ExtOut(" %p { tid=%03x pid=%03x eip=%p, ebp=%p, esp=%p %02x }\n",
address,
(ULONG)(tc.threadIndex == 0xffff ? 0xfff : tc.threadIndex),
(ULONG)(tc.processId == 0xffff ? 0xfff : tc.processId),
tc.threadRecord.spill.ip,
tc.threadRecord.spill.bp,
tc.threadRecord.spill.sp,
(ULONG)tc.gcStates);
X86_CONTEXT context;
PVOID mmxRegs = NULL;
PVOID stRegs = NULL;
EXT_CHECK(g_ExtSymbols->GetScope(NULL, NULL, &context, sizeof(context)));
EXT_CHECK(ThreadContextStruct->RawAccess(ThreadContextFields[0].offset, &mmxRegs));
EXT_CHECK(ThreadContextStruct->RawAccess(ThreadContextFields[1].offset, &stRegs));
context.Eip = (ULONG)tc.threadRecord.spill.ip;
context.Esp = (ULONG)tc.threadRecord.spill.sp;
context.Ebp = (ULONG)tc.threadRecord.spill.bp;
context.Eax = (ULONG)tc.threadRecord.spill.ax;
context.Ebx = (ULONG)tc.threadRecord.spill.bx;
context.Ecx = (ULONG)tc.threadRecord.spill.cx;
context.Edx = (ULONG)tc.threadRecord.spill.dx;
context.Esi = (ULONG)tc.threadRecord.spill.si;
context.Edi = (ULONG)tc.threadRecord.spill.di;
context.EFlags = (ULONG)tc.threadRecord.spill.fl;
// CONTEXT_FLOATING_POINT
context.FloatSave.ControlWord = (ULONG)tc.threadRecord.spill.mmx.fcw;
context.FloatSave.StatusWord = (ULONG)tc.threadRecord.spill.mmx.fsw;
context.FloatSave.TagWord = (ULONG)tc.threadRecord.spill.mmx.ftw;
context.FloatSave.ErrorOffset = (ULONG)tc.threadRecord.spill.mmx.ip;
context.FloatSave.ErrorSelector = (ULONG)tc.threadRecord.spill.mmx.cs;
context.FloatSave.DataOffset = (ULONG)tc.threadRecord.spill.mmx.dp;
context.FloatSave.DataSelector = (ULONG)tc.threadRecord.spill.mmx.ds;
memcpy((PBYTE)context.FloatSave.RegisterArea+0, (PBYTE)stRegs + 0x00, 10);
memcpy((PBYTE)context.FloatSave.RegisterArea+10, (PBYTE)stRegs + 0x10, 10);
memcpy((PBYTE)context.FloatSave.RegisterArea+20, (PBYTE)stRegs + 0x20, 10);
memcpy((PBYTE)context.FloatSave.RegisterArea+30, (PBYTE)stRegs + 0x30, 10);
memcpy((PBYTE)context.FloatSave.RegisterArea+40, (PBYTE)stRegs + 0x40, 10);
memcpy((PBYTE)context.FloatSave.RegisterArea+50, (PBYTE)stRegs + 0x50, 10);
memcpy((PBYTE)context.FloatSave.RegisterArea+60, (PBYTE)stRegs + 0x60, 10);
memcpy((PBYTE)context.FloatSave.RegisterArea+70, (PBYTE)stRegs + 0x70, 10);
memcpy(context.ExtendedRegisters, mmxRegs, 512);
EXT_CHECK(g_ExtSymbols->SetScope(0, NULL, &context, sizeof(context)));
}
else if (TargetMachine == IMAGE_FILE_MACHINE_AMD64) {
ExtOut(" %p { tid=%03x pid=%03x rip=%p, rbp=%p, rsp=%p %02x }\n",
address,
(ULONG)(tc.threadIndex == 0xffff ? 0xfff : tc.threadIndex),
(ULONG)(tc.processId == 0xffff ? 0xfff : tc.processId),
tc.threadRecord.spill.ip,
tc.threadRecord.spill.bp,
tc.threadRecord.spill.sp,
(ULONG)tc.gcStates);
X64_CONTEXT context;
PVOID mmxRegs = NULL;
EXT_CHECK(g_ExtSymbols->GetScope(NULL, NULL, &context, sizeof(context)));
EXT_CHECK(ThreadContextStruct->RawAccess(ThreadContextFields[0].offset, &mmxRegs));
// TODO: fix the extension to proper handle different architectures. Copy only
// these registers for now
context.Rip = tc.threadRecord.spill.ip;
context.Rsp = tc.threadRecord.spill.sp;
context.Rbp = tc.threadRecord.spill.bp;
context.Rax = tc.threadRecord.spill.ax;
context.Rbx = tc.threadRecord.spill.bx;
context.Rcx = tc.threadRecord.spill.cx;
context.Rdx = tc.threadRecord.spill.dx;
context.Rsi = tc.threadRecord.spill.si;
context.Rdi = tc.threadRecord.spill.di;
context.R8 = tc.threadRecord.spill.r8;
context.R9 = tc.threadRecord.spill.r9;
context.R10 = tc.threadRecord.spill.r10;
context.R11 = tc.threadRecord.spill.r11;
context.R12 = tc.threadRecord.spill.r12;
context.R13 = tc.threadRecord.spill.r13;
context.R14 = tc.threadRecord.spill.r14;
context.R15 = tc.threadRecord.spill.r15;
context.EFlags = (ULONG)tc.threadRecord.spill.fl;
// CONTEXT_FLOATING_POINT
memcpy(&context.FltSave, mmxRegs, 512);
EXT_CHECK(g_ExtSymbols->SetScope(0, NULL, &context, sizeof(context)));
}
else if (TargetMachine == IMAGE_FILE_MACHINE_ARM) {
ExtOut(" %p { tid=%03x pid=%03x pc=%p, sp=%p %02x }\n",
address,
(ULONG)(tc.threadIndex == 0xffff ? 0xfff : tc.threadIndex),
(ULONG)(tc.processId == 0xffff ? 0xfff : tc.processId),
tc.threadRecord.spill.pc,
tc.threadRecord.spill.sp,
(ULONG)tc.gcStates);
ARM_CONTEXT context;
EXT_CHECK(g_ExtSymbols->GetScope(NULL, NULL, &context, sizeof(context)));
// TODO: fix the extension to proper handle different architectures. Copy only
// these registers for now
context.R0 = (ULONG)tc.threadRecord.spill.r0;
context.R1 = (ULONG)tc.threadRecord.spill.r1;
context.R2 = (ULONG)tc.threadRecord.spill.r2;
context.R3 = (ULONG)tc.threadRecord.spill.r3;
context.R4 = (ULONG)tc.threadRecord.spill.r4;
context.R5 = (ULONG)tc.threadRecord.spill.r5;
context.R6 = (ULONG)tc.threadRecord.spill.r6;
context.R7 = (ULONG)tc.threadRecord.spill.r7;
context.R8 = (ULONG)tc.threadRecord.spill.r8;
context.R9 = (ULONG)tc.threadRecord.spill.r9;
context.R10 = (ULONG)tc.threadRecord.spill.r10;
context.R11 = (ULONG)tc.threadRecord.spill.r11;
context.R12 = (ULONG)tc.threadRecord.spill.r12;
context.Pc = (ULONG)tc.threadRecord.spill.pc;
context.Lr = (ULONG)tc.threadRecord.spill.lr;
context.Sp = (ULONG)tc.threadRecord.spill.sp;
context.Cpsr = (ULONG)tc.threadRecord.spill.cpsr;
EXT_CHECK(g_ExtSymbols->SetScope(0, NULL, &context, sizeof(context)));
}
2008-03-05 09:52:00 -05:00
EXT_LEAVE(); // Macro includes: return status;
}