singrdk/base/Windows/singx86/structs.cpp

742 lines
27 KiB
C++

///////////////////////////////////////////////////////////////////////////////////////////////////
//
// structs.cpp - extensions to dump well-known structs.
//
// Copyright Microsoft Corporation. All rights reserved.
//
#include "singx86.h"
#include <strsafe.h>
///////////////////////////////////////////////////////////////////////////////////////////////////
//
FieldType *ThreadContextFields = NULL;
StructType *ThreadContextStruct = NULL;
FieldType X86ThreadContextFields[] = {
FIELD(ThreadContext, threadRecord.spill.mmx), // "mmx" must be ThreadContextFields[0]
FIELD(ThreadContext, threadRecord.spill.mmx.st0), // "st0" must be ThreadContextFields[1]
FIELD(ThreadContext, threadRecord.spill.mmx.st1),
FIELD(ThreadContext, threadRecord.spill.mmx.st2),
FIELD(ThreadContext, threadRecord.spill.mmx.st3),
FIELD(ThreadContext, threadRecord.spill.mmx.st4),
FIELD(ThreadContext, threadRecord.spill.mmx.st5),
FIELD(ThreadContext, threadRecord.spill.mmx.st6),
FIELD(ThreadContext, threadRecord.spill.mmx.st7),
FIELD(ThreadContext, threadRecord.spill.mmx.fcw),
FIELD(ThreadContext, threadRecord.spill.mmx.fsw),
FIELD(ThreadContext, threadRecord.spill.mmx.ftw),
FIELD(ThreadContext, threadRecord.spill.mmx.fop),
FIELD(ThreadContext, threadRecord.spill.mmx.ip),
FIELD(ThreadContext, threadRecord.spill.mmx.cs),
FIELD(ThreadContext, threadRecord.spill.mmx.dp),
FIELD(ThreadContext, threadRecord.spill.mmx.ds),
FIELD(ThreadContext, threadRecord.spill.mmx.mxcsr),
FIELD(ThreadContext, threadRecord.spill.mmx.mxcsrmask),
FIELD(ThreadContext, threadRecord.spill.ax),
FIELD(ThreadContext, threadRecord.spill.bx),
FIELD(ThreadContext, threadRecord.spill.cx),
FIELD(ThreadContext, threadRecord.spill.dx),
FIELD(ThreadContext, threadRecord.spill.di),
FIELD(ThreadContext, threadRecord.spill.si),
FIELD(ThreadContext, threadRecord.spill.sp),
FIELD(ThreadContext, threadRecord.spill.ip),
FIELD(ThreadContext, threadRecord.spill.bp),
FIELD(ThreadContext, threadRecord.spill.fl),
// Common Fields
FIELD(ThreadContext, threadRecord.activeStackLimit),
FIELD(ThreadContext, regs),
FIELD(ThreadContext, prev),
FIELD(ThreadContext, next),
FIELD(ThreadContext, stackBegin),
FIELD(ThreadContext, stackLimit),
FIELD(ThreadContext, processId),
FIELD(ThreadContext, uncaughtFlag),
FIELD(ThreadContext, suspendAlert),
FIELD(ThreadContext, _thread),
FIELD(ThreadContext, processThread),
FIELD(ThreadContext, stackMarkers),
FIELD(ThreadContext, processMarkers),
FIELD(ThreadContext, threadIndex),
FIELD(ThreadContext, processThreadIndex),
FIELD(ThreadContext, gcStates),
FIELDEND(),
};
FieldType X64ThreadContextFields[] = {
FIELD(ThreadContext, threadRecord.spill.mmx), // "mmx" must be ThreadContextFields[0]
FIELD(ThreadContext, threadRecord.spill.mmx.st0), // "st0" must be ThreadContextFields[1]
FIELD(ThreadContext, threadRecord.spill.mmx.st1),
FIELD(ThreadContext, threadRecord.spill.mmx.st2),
FIELD(ThreadContext, threadRecord.spill.mmx.st3),
FIELD(ThreadContext, threadRecord.spill.mmx.st4),
FIELD(ThreadContext, threadRecord.spill.mmx.st5),
FIELD(ThreadContext, threadRecord.spill.mmx.st6),
FIELD(ThreadContext, threadRecord.spill.mmx.st7),
FIELD(ThreadContext, threadRecord.spill.mmx.fcw),
FIELD(ThreadContext, threadRecord.spill.mmx.fsw),
FIELD(ThreadContext, threadRecord.spill.mmx.ftw),
FIELD(ThreadContext, threadRecord.spill.mmx.fop),
FIELD(ThreadContext, threadRecord.spill.mmx.ip),
FIELD(ThreadContext, threadRecord.spill.mmx.cs),
FIELD(ThreadContext, threadRecord.spill.mmx.dp),
FIELD(ThreadContext, threadRecord.spill.mmx.ds),
FIELD(ThreadContext, threadRecord.spill.mmx.mxcsr),
FIELD(ThreadContext, threadRecord.spill.mmx.mxcsrmask),
FIELD(ThreadContext, threadRecord.spill.ax),
FIELD(ThreadContext, threadRecord.spill.bx),
FIELD(ThreadContext, threadRecord.spill.cx),
FIELD(ThreadContext, threadRecord.spill.dx),
FIELD(ThreadContext, threadRecord.spill.di),
FIELD(ThreadContext, threadRecord.spill.si),
FIELD(ThreadContext, threadRecord.spill.sp),
FIELD(ThreadContext, threadRecord.spill.ip),
FIELD(ThreadContext, threadRecord.spill.bp),
FIELD(ThreadContext, threadRecord.spill.r8),
FIELD(ThreadContext, threadRecord.spill.r9),
FIELD(ThreadContext, threadRecord.spill.r10),
FIELD(ThreadContext, threadRecord.spill.r11),
FIELD(ThreadContext, threadRecord.spill.r12),
FIELD(ThreadContext, threadRecord.spill.r13),
FIELD(ThreadContext, threadRecord.spill.r14),
FIELD(ThreadContext, threadRecord.spill.r15),
FIELD(ThreadContext, threadRecord.spill.fl),
// Common Fields
FIELD(ThreadContext, threadRecord.activeStackLimit),
FIELD(ThreadContext, regs),
FIELD(ThreadContext, prev),
FIELD(ThreadContext, next),
FIELD(ThreadContext, stackBegin),
FIELD(ThreadContext, stackLimit),
FIELD(ThreadContext, processId),
FIELD(ThreadContext, uncaughtFlag),
FIELD(ThreadContext, suspendAlert),
FIELD(ThreadContext, _thread),
FIELD(ThreadContext, processThread),
FIELD(ThreadContext, stackMarkers),
FIELD(ThreadContext, processMarkers),
FIELD(ThreadContext, threadIndex),
FIELD(ThreadContext, processThreadIndex),
FIELD(ThreadContext, gcStates),
FIELDEND(),
};
FieldType ArmThreadContextFields[] = {
FIELD(ThreadContext, threadRecord.spill.r0),
FIELD(ThreadContext, threadRecord.spill.r1),
FIELD(ThreadContext, threadRecord.spill.r2),
FIELD(ThreadContext, threadRecord.spill.r3),
FIELD(ThreadContext, threadRecord.spill.r4),
FIELD(ThreadContext, threadRecord.spill.r5),
FIELD(ThreadContext, threadRecord.spill.r6),
FIELD(ThreadContext, threadRecord.spill.r7),
FIELD(ThreadContext, threadRecord.spill.r8),
FIELD(ThreadContext, threadRecord.spill.r9),
FIELD(ThreadContext, threadRecord.spill.r10),
FIELD(ThreadContext, threadRecord.spill.r11),
FIELD(ThreadContext, threadRecord.spill.r12),
FIELD(ThreadContext, threadRecord.spill.sp),
FIELD(ThreadContext, threadRecord.spill.lr),
FIELD(ThreadContext, threadRecord.spill.pc),
FIELD(ThreadContext, threadRecord.spill.cpsr),
// Common Fields
FIELD(ThreadContext, threadRecord.activeStackLimit),
FIELD(ThreadContext, regs),
FIELD(ThreadContext, prev),
FIELD(ThreadContext, next),
FIELD(ThreadContext, stackBegin),
FIELD(ThreadContext, stackLimit),
FIELD(ThreadContext, processId),
FIELD(ThreadContext, uncaughtFlag),
FIELD(ThreadContext, suspendAlert),
FIELD(ThreadContext, _thread),
FIELD(ThreadContext, processThread),
FIELD(ThreadContext, stackMarkers),
FIELD(ThreadContext, processMarkers),
FIELD(ThreadContext, threadIndex),
FIELD(ThreadContext, processThreadIndex),
FIELD(ThreadContext, gcStates),
FIELDEND(),
};
///////////////////////////////////////////////////////////////////////////////////////////////////
//
FieldType *ThreadFields = NULL;
StructType *ThreadStruct = NULL;
FieldType X86ThreadFields[] = {
FIELD(Thread, context), // "context" must be ThreadFields[0]
FIELD(Thread, context.threadRecord.spill.ax),
FIELD(Thread, context.threadRecord.spill.bx),
FIELD(Thread, context.threadRecord.spill.cx),
FIELD(Thread, context.threadRecord.spill.dx),
FIELD(Thread, context.threadRecord.spill.di),
FIELD(Thread, context.threadRecord.spill.si),
FIELD(Thread, context.threadRecord.spill.sp),
FIELD(Thread, context.threadRecord.spill.ip),
FIELD(Thread, context.threadRecord.spill.bp),
FIELD(Thread, context.threadRecord.spill.fl),
FIELD(Thread, context.threadRecord.spill.mmx.st0),
FIELD(Thread, context.threadRecord.spill.mmx.st1),
FIELD(Thread, context.threadRecord.spill.mmx.st2),
FIELD(Thread, context.threadRecord.spill.mmx.st3),
FIELD(Thread, context.threadRecord.spill.mmx.st4),
FIELD(Thread, context.threadRecord.spill.mmx.st5),
FIELD(Thread, context.threadRecord.spill.mmx.st6),
FIELD(Thread, context.threadRecord.spill.mmx.st7),
FIELD(Thread, context.threadRecord.spill.mmx.fcw),
FIELD(Thread, context.threadRecord.spill.mmx.fsw),
FIELD(Thread, context.threadRecord.spill.mmx.ftw),
FIELD(Thread, context.threadRecord.spill.mmx.fop),
FIELD(Thread, context.threadRecord.spill.mmx.ip),
FIELD(Thread, context.threadRecord.spill.mmx.cs),
FIELD(Thread, context.threadRecord.spill.mmx.dp),
FIELD(Thread, context.threadRecord.spill.mmx.ds),
FIELD(Thread, context.threadRecord.spill.mmx.mxcsr),
FIELD(Thread, context.threadRecord.spill.mmx.mxcsrmask),
// Common Fields
FIELD(Thread, context.threadRecord.activeStackLimit),
FIELD(Thread, context.regs),
FIELD(Thread, context.prev),
FIELD(Thread, context.next),
FIELD(Thread, context.stackBegin),
FIELD(Thread, context.stackLimit),
FIELD(Thread, context.processId),
FIELD(Thread, context.uncaughtFlag),
FIELD(Thread, context.suspendAlert),
FIELD(Thread, context._thread),
FIELD(Thread, context.processThread),
FIELD(Thread, context.stackMarkers),
FIELD(Thread, context.processMarkers),
FIELD(Thread, context.threadIndex),
FIELD(Thread, context.processThreadIndex),
FIELD(Thread, context.gcStates),
FIELD(Thread, blocked),
FIELD(Thread, blockedOn),
FIELD(Thread, blockedOnCount),
FIELD(Thread, blockedUntil),
FIELD(Thread, process),
FIELD(Thread, schedulerEntry),
FIELDEND(),
};
FieldType X64ThreadFields[] = {
FIELD(Thread, context), // "context" must be ThreadFields[0]
FIELD(Thread, context.threadRecord.spill.ax),
FIELD(Thread, context.threadRecord.spill.bx),
FIELD(Thread, context.threadRecord.spill.cx),
FIELD(Thread, context.threadRecord.spill.dx),
FIELD(Thread, context.threadRecord.spill.di),
FIELD(Thread, context.threadRecord.spill.si),
FIELD(Thread, context.threadRecord.spill.sp),
FIELD(Thread, context.threadRecord.spill.ip),
FIELD(Thread, context.threadRecord.spill.bp),
FIELD(Thread, context.threadRecord.spill.r8),
FIELD(Thread, context.threadRecord.spill.r9),
FIELD(Thread, context.threadRecord.spill.r10),
FIELD(Thread, context.threadRecord.spill.r11),
FIELD(Thread, context.threadRecord.spill.r12),
FIELD(Thread, context.threadRecord.spill.r13),
FIELD(Thread, context.threadRecord.spill.r14),
FIELD(Thread, context.threadRecord.spill.r15),
FIELD(Thread, context.threadRecord.spill.fl),
FIELD(Thread, context.threadRecord.spill.mmx.st0),
FIELD(Thread, context.threadRecord.spill.mmx.st1),
FIELD(Thread, context.threadRecord.spill.mmx.st2),
FIELD(Thread, context.threadRecord.spill.mmx.st3),
FIELD(Thread, context.threadRecord.spill.mmx.st4),
FIELD(Thread, context.threadRecord.spill.mmx.st5),
FIELD(Thread, context.threadRecord.spill.mmx.st6),
FIELD(Thread, context.threadRecord.spill.mmx.st7),
FIELD(Thread, context.threadRecord.spill.mmx.fcw),
FIELD(Thread, context.threadRecord.spill.mmx.fsw),
FIELD(Thread, context.threadRecord.spill.mmx.ftw),
FIELD(Thread, context.threadRecord.spill.mmx.fop),
FIELD(Thread, context.threadRecord.spill.mmx.ip),
FIELD(Thread, context.threadRecord.spill.mmx.cs),
FIELD(Thread, context.threadRecord.spill.mmx.dp),
FIELD(Thread, context.threadRecord.spill.mmx.ds),
FIELD(Thread, context.threadRecord.spill.mmx.mxcsr),
FIELD(Thread, context.threadRecord.spill.mmx.mxcsrmask),
// Common Fields
FIELD(Thread, context.threadRecord.activeStackLimit),
FIELD(Thread, context.regs),
FIELD(Thread, context.prev),
FIELD(Thread, context.next),
FIELD(Thread, context.stackBegin),
FIELD(Thread, context.stackLimit),
FIELD(Thread, context.processId),
FIELD(Thread, context.uncaughtFlag),
FIELD(Thread, context.suspendAlert),
FIELD(Thread, context._thread),
FIELD(Thread, context.processThread),
FIELD(Thread, context.stackMarkers),
FIELD(Thread, context.processMarkers),
FIELD(Thread, context.threadIndex),
FIELD(Thread, context.processThreadIndex),
FIELD(Thread, context.gcStates),
FIELD(Thread, blocked),
FIELD(Thread, blockedOn),
FIELD(Thread, blockedOnCount),
FIELD(Thread, blockedUntil),
FIELD(Thread, process),
FIELD(Thread, schedulerEntry),
FIELDEND(),
};
FieldType ArmThreadFields[] = {
FIELD(Thread, context), // "context" must be ThreadFields[0]
FIELD(Thread, context.threadRecord.spill.r0),
FIELD(Thread, context.threadRecord.spill.r1),
FIELD(Thread, context.threadRecord.spill.r2),
FIELD(Thread, context.threadRecord.spill.r3),
FIELD(Thread, context.threadRecord.spill.r4),
FIELD(Thread, context.threadRecord.spill.r5),
FIELD(Thread, context.threadRecord.spill.r6),
FIELD(Thread, context.threadRecord.spill.r7),
FIELD(Thread, context.threadRecord.spill.r8),
FIELD(Thread, context.threadRecord.spill.r9),
FIELD(Thread, context.threadRecord.spill.r10),
FIELD(Thread, context.threadRecord.spill.r11),
FIELD(Thread, context.threadRecord.spill.r12),
FIELD(Thread, context.threadRecord.spill.sp),
FIELD(Thread, context.threadRecord.spill.lr),
FIELD(Thread, context.threadRecord.spill.pc),
FIELD(Thread, context.threadRecord.spill.cpsr),
// Common Fields.
FIELD(Thread, context.threadRecord.activeStackLimit),
FIELD(Thread, context.regs),
FIELD(Thread, context.prev),
FIELD(Thread, context.next),
FIELD(Thread, context.stackBegin),
FIELD(Thread, context.stackLimit),
FIELD(Thread, context.processId),
FIELD(Thread, context.uncaughtFlag),
FIELD(Thread, context.suspendAlert),
FIELD(Thread, context._thread),
FIELD(Thread, context.processThread),
FIELD(Thread, context.stackMarkers),
FIELD(Thread, context.processMarkers),
FIELD(Thread, context.threadIndex),
FIELD(Thread, context.processThreadIndex),
FIELD(Thread, context.gcStates),
FIELD(Thread, blocked),
FIELD(Thread, blockedOn),
FIELD(Thread, blockedOnCount),
FIELD(Thread, blockedUntil),
FIELD(Thread, process),
FIELD(Thread, schedulerEntry),
FIELDEND(),
};
///////////////////////////////////////////////////////////////////////////////////////////////////
//
FieldType ThreadEntryFields[] = {
FIELD(ThreadEntry, queue),
FIELDEND(),
};
// kernel name is potentially fixed up in StructType::Initialize
StructType ThreadEntryStruct
= StructType(kernel_ThreadEntry,
sizeof(ThreadEntry), ThreadEntryFields);
FieldType StringFields[] = {
FIELD(String, m_firstChar), // Accessed directly as Field[0]
FIELD(String, m_stringLength),
FIELDEND(),
};
// kernel name is potentially fixed up in StructType::Initialize
StructType StringStruct = StructType(kernel_String,
sizeof(String), StringFields);
FieldType LogEntryFields[] = {
FIELD(LogEntry, _cycleCount),
FIELD(LogEntry, _eip),
FIELD(LogEntry, _cpuId),
FIELD(LogEntry, _threadId),
FIELD(LogEntry, _processId),
FIELD(LogEntry, _tag),
FIELD(LogEntry, _severity),
FIELD(LogEntry, _strings),
FIELD(LogEntry, _text),
FIELD(LogEntry, _arg0),
FIELD(LogEntry, _arg1),
FIELD(LogEntry, _arg2),
FIELD(LogEntry, _arg3),
FIELD(LogEntry, _arg4),
FIELD(LogEntry, _arg5),
FIELDEND(),
};
// kernel name is potentially fixed up in StructType::Initialize
StructType LogEntryStruct = StructType(kernel_Struct_Microsoft_Singularity_Tracing_LogEntry,
sizeof(LogEntry), LogEntryFields);
FieldType ProcessorContextFields[] = {
FIELD(ProcessorContext, cpuRecord.id),
FIELD(ProcessorContext, cpuRecord.interruptStackBegin),
FIELD(ProcessorContext, cpuRecord.interruptStackLimit),
FIELD(ProcessorContext, _processor),
FIELD(ProcessorContext, exception),
FIELD(ProcessorContext, nextProcessorContext),
FIELDEND(),
};
// kernel name is potentially fixed up in StructType::Initialize
StructType ProcessorContextStruct
= StructType(kernel_ProcessorContext,
sizeof(ProcessorContext), ProcessorContextFields);
FieldType ProcessorFields[] = {
FIELD(Processor, context),
FIELD(Processor, pic),
FIELD(Processor, timer),
FIELD(Processor, clock),
FIELD(Processor, timerInterrupt),
FIELD(Processor, clockInterrupt),
FIELD(Processor, inInterruptContext),
FIELD(Processor, halted),
FIELD(Processor, NumExceptions),
FIELD(Processor, NumInterrupts),
FIELD(Processor, NumContextSwitches),
FIELD(Processor, interruptCounts),
FIELDEND(),
};
// kernel name is potentially fixed up in StructType::Initialize
StructType ProcessorStruct
= StructType(kernel_Processor,
sizeof(Processor), ProcessorFields);
///////////////////////////////////// Remote to Local conversions for structs.
//
StructType * StructType::registered = NULL;
StructType::StructType(PSTR name, ULONG localSize, struct FieldType *fields)
{
this->next = registered;
registered = this;
this->name = name;
this->localSize = localSize;
this->fields = fields;
this->fieldCount = 0;
this->module = 0;
this->type = 0;
this->size = 0;
this->temp = NULL;
}
HRESULT StructType::InitializeRegistered()
{
if (TargetMachine == IMAGE_FILE_MACHINE_I386) {
ThreadContextFields = X86ThreadContextFields;
ThreadFields = X86ThreadFields;
ExtVerb("Selected X86 fields.\n");
}
else if (TargetMachine == IMAGE_FILE_MACHINE_AMD64) {
ThreadContextFields = X64ThreadContextFields;
ThreadFields = X64ThreadFields;
ExtVerb("Selected X64 fields.\n");
}
else if (TargetMachine == IMAGE_FILE_MACHINE_ARM) {
ThreadContextFields = ArmThreadContextFields;
ThreadFields = ArmThreadFields;
ExtVerb("Selected Arm fields.\n");
}
else {
ExtErr("Selected *NO* fields. [target:%08x]\n", TargetMachine);
}
// kernel name is potentially fixed up in StructType::Initialize
ThreadContextStruct = new StructType(kernel_ThreadContext,
sizeof(ThreadContext),
ThreadContextFields);
// kernel name is potentially fixed up in StructType::Initialize
ThreadStruct = new StructType(kernel_Thread,
sizeof(Thread),
ThreadFields);
for (StructType *next = registered; next != NULL; next = next->next) {
next->Initialize();
}
return S_OK;
}
HRESULT StructType::Initialize()
{
HRESULT status = S_OK;
ExtVerb("Initializing: %s [%p]\n", name, fields);
EXT_CHECK(g_ExtSymbols->GetSymbolTypeId(name, &type, &module));
EXT_CHECK(g_ExtSymbols->GetTypeSize(module, type, &size));
ExtVerb("Initializing: %s [size=%d]\n", name, size);
if (temp != NULL) {
delete[] temp;
}
temp = new BYTE [size];
ZeroMemory(temp, size);
fieldCount = 0;
for (FieldType *field = fields; field->name != NULL; field++) {
CHAR fieldName[512];
EXT_CHECK(StringCbPrintf(fieldName, sizeof(fieldName), "%s.%s", name, field->name));
status = g_ExtSymbols->GetSymbolTypeId(fieldName, &field->type, &field->module);
if (status == S_OK) {
EXT_CHECK(g_ExtSymbols->GetTypeSize(field->module, field->type, &field->size));
EXT_CHECK(g_ExtSymbols->GetFieldOffset(module, type, field->name, &field->offset));
ExtVerb("Initializing: %s [offset=%d,size=%d]\n", fieldName, field->offset, field->size);
}
else {
ExtErr("Can't find: %s\n", fieldName);
field->size = 0;
field->offset = 0;
}
field->parent = this;
fieldCount++;
}
Exit:
ExtVerb("** Exited with %08x\n", status);
return status;
}
HRESULT StructType::RemoteOffsetFromLocal(ULONG localOffset, ULONG *remoteOffset)
{
for (ULONG f = 0; f < fieldCount; f++) {
FieldType *field = &fields[f];
if (field->localOffset == localOffset) {
if (remoteOffset != NULL) {
*remoteOffset = field->offset;
return S_OK;
}
return S_FALSE;
}
}
return E_FAIL;
}
HRESULT StructType::RawAccess(ULONG remoteOffset, PVOID *raw)
{
*raw = temp + remoteOffset;
return S_OK;
}
HRESULT StructType::Read(ULONG64 address, PVOID local)
{
HRESULT status = S_OK;
ZeroMemory(temp, size);
ZeroMemory(local, localSize);
EXT_CHECK(TraceRead(address, temp, size));
for (ULONG f = 0; f < fieldCount; f++) {
FieldType *field = &fields[f];
PBYTE pbLocal = ((PBYTE)local) + field->localOffset;
PBYTE pbTemp = &temp[field->offset];
switch (field->size) {
case 1:
*(ULONG64 *)pbLocal = *(BYTE *)pbTemp;
break;
case 2:
*(ULONG64 *)pbLocal = *(USHORT *)pbTemp;
break;
case 4:
*(ULONG64 *)pbLocal = *(ULONG *)pbTemp;
break;
case 8:
*(ULONG64 *)pbLocal = *(ULONG64 *)pbTemp;
break;
default:
#if 0
// We allow bigger sizes, for raw access only.
ExtOut("Unknown size: %d, in field %s\n", field->size, field->name);
#endif
break;
}
}
Exit:
return status;
}
HRESULT StructType::Clear()
{
HRESULT status = S_OK;
ZeroMemory(temp, size);
return status;
}
HRESULT StructType::Update(PVOID local)
{
HRESULT status = S_OK;
for (ULONG f = 0; f < fieldCount; f++) {
FieldType *field = &fields[f];
PBYTE pbLocal = ((PBYTE)local) + field->localOffset;
PBYTE pbTemp = &temp[field->offset];
switch (field->size) {
case 1:
*(BYTE *)pbTemp = (BYTE)*(ULONG64 *)pbLocal;
break;
case 2:
*(USHORT *)pbTemp = (USHORT)*(ULONG64 *)pbLocal;
break;
case 4:
*(ULONG *)pbTemp = (ULONG)*(ULONG64 *)pbLocal;
break;
case 8:
*(ULONG64 *)pbTemp = *(ULONG64 *)pbLocal;
break;
}
}
return status;
}
HRESULT StructType::Flush(ULONG64 address)
{
HRESULT status = S_OK;
EXT_CHECK(g_ExtData->WriteVirtual(address, temp, size, NULL));
Exit:
return status;
}
/////////////////////////////////////////////////////////// KnownStructOutput.
//
const char* KnownStructs[] = {"String",
"Thread",
"System_String",
"System_Threading_Thread",
#if 0
"ProcessorContext",
"Microsoft_Singularity_X86_ProcessorContext"
#endif
};
HRESULT OnGetKnownStructNames(PDEBUG_CLIENT client,
PSTR buffer,
PULONG bufferSize)
{
EXT_ENTER(); // Defines: HRESULT status = S_OK;
//
// Return names of known structs in multi string
//
ULONG sizeRemaining = *bufferSize, SizeNeeded = 0, Length;
PCHAR copyAt = buffer;
for (ULONG i = 0; i < arrayof(KnownStructs); i++) {
if (sizeRemaining > (Length = (ULONG)strlen(KnownStructs[i]) + 1) &&
status == S_OK) {
status = StringCbCopy(copyAt, sizeRemaining, KnownStructs[i]);
sizeRemaining -= Length;
copyAt += Length;
}
else {
status = S_FALSE;
}
SizeNeeded += Length;
}
// Terminate multistring and return size copied
*copyAt = 0;
*bufferSize = SizeNeeded+1;
EXT_LEAVE(); // Macro includes: return status;
}
HRESULT OnGetSingleLineOutput(PDEBUG_CLIENT client,
ULONG64 address,
PSTR structName,
PSTR buffer,
PULONG bufferSize)
{
EXT_ENTER(); // Defines: HRESULT status = S_OK;
ExtVerb("OnGetSingleLineOutput [%s]\n", structName);
if (strcmp(structName, "System_String") == 0 ||
strcmp(structName, "String") == 0) {
String str;
ExtVerb("OnGetSingleLineOutput [%s] is string\n", structName);
EXT_CHECK(StringStruct.Read(address, &str));
ExtVerb("OnGetSingleLineOutput [%s] is still string\n", structName);
WCHAR data[256];
ULONG len;
len = (ULONG)str.m_stringLength;
if (len > arrayof(data)) {
len = arrayof(data);
}
if (len > *bufferSize - 20) {
len = *bufferSize - 20;
}
if (len > 0) {
EXT_CHECK(TraceRead(address + StringFields[0].offset,
data,
sizeof(data[0]) * len));
ExtVerb("OnGetSingleLineOutput [%s] read %d of %d chars to %p\n",
structName, len, *bufferSize, buffer);
}
status = StringCbPrintf(buffer, *bufferSize, " { [%d] \"%.*ls\" }",
(ULONG)str.m_stringLength, len, data);
ExtVerb("OnGetSingleLineOutput [%s] status = %x\n",
structName, status);
}
else if (!strcmp(structName, "System_Threading_Thread") ||
!strcmp(structName, "Thread")) {
Thread thread;
EXT_CHECK(ThreadStruct->Read(address, &thread));
status = StringCbPrintf(buffer, *bufferSize, " { eip=%I64x ebp=%I64x esp=%I64x }",
thread.context.threadRecord.spill.ip,
thread.context.threadRecord.spill.bp,
thread.context.threadRecord.spill.sp);
}
#if 0
else if (!strcmp(structName, "Microsoft_Singularity_ProcessorContext") ||
!strcmp(structName, "ProcessorContext")) {
ProcessorContext pc;
EXT_CHECK(ProcessorContext.Read(address, &pc));
status = StringCbPrintf(buffer, *bufferSize, " { eip=%I64x ebp=%I64x esp=%I64x }",
thread.context.threadRecord.spill.ip,
thread.context.threadRecord.spill.bp,
thread.context.threadRecord.spill.sp);
}
#endif
else {
status = E_INVALIDARG;
}
EXT_LEAVE(); // Macro includes: return status;
}
HRESULT OnGetSuppressTypeName(PDEBUG_CLIENT client, PSTR structName)
{
UNREFERENCED_PARAMETER(structName);
EXT_ENTER(); // Defines: HRESULT status = S_OK;
EXT_LEAVE(); // Macro includes: return status;
}