Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1346 lines
32 KiB

#include <engexts.h>
//----------------------------------------------------------------------------
//
// StaticEventCallbacks.
//
//----------------------------------------------------------------------------
class StaticEventCallbacks : public DebugBaseEventCallbacks
{
public:
// IUnknown.
STDMETHOD_(ULONG, AddRef)(
THIS
);
STDMETHOD_(ULONG, Release)(
THIS
);
};
STDMETHODIMP_(ULONG)
StaticEventCallbacks::AddRef(
THIS
)
{
// This class is designed to be static so
// there's no true refcount.
return 1;
}
STDMETHODIMP_(ULONG)
StaticEventCallbacks::Release(
THIS
)
{
// This class is designed to be static so
// there's no true refcount.
return 0;
}
//----------------------------------------------------------------------------
//
// ExcepCallbacks.
//
//----------------------------------------------------------------------------
class ExcepCallbacks : public StaticEventCallbacks
{
public:
ExcepCallbacks(void)
{
m_Client = NULL;
m_Control = NULL;
}
// IDebugEventCallbacks.
STDMETHOD(GetInterestMask)(
THIS_
OUT PULONG Mask
);
STDMETHOD(Exception)(
THIS_
IN PEXCEPTION_RECORD64 Exception,
IN ULONG FirstChance
);
HRESULT Initialize(PDEBUG_CLIENT Client)
{
HRESULT Status;
m_Client = Client;
m_Client->AddRef();
if ((Status = m_Client->QueryInterface(__uuidof(IDebugControl),
(void**)&m_Control)) == S_OK)
{
// Turn off default breakin on breakpoint exceptions.
Status = m_Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
"sxd bpe", DEBUG_EXECUTE_DEFAULT);
}
return Status;
}
void Uninitialize(void)
{
EXT_RELEASE(m_Control);
EXT_RELEASE(m_Client);
}
private:
PDEBUG_CLIENT m_Client;
PDEBUG_CONTROL m_Control;
};
STDMETHODIMP
ExcepCallbacks::GetInterestMask(
THIS_
OUT PULONG Mask
)
{
*Mask = DEBUG_EVENT_EXCEPTION;
return S_OK;
}
STDMETHODIMP
ExcepCallbacks::Exception(
THIS_
IN PEXCEPTION_RECORD64 Exception,
IN ULONG FirstChance
)
{
m_Control->Output(DEBUG_OUTPUT_NORMAL, "Exception %X at %p, chance %d\n",
Exception->ExceptionCode, Exception->ExceptionAddress,
FirstChance ? 1 : 2);
return DEBUG_STATUS_GO_HANDLED;
}
ExcepCallbacks g_ExcepCallbacks;
//----------------------------------------------------------------------------
//
// FnProfCallbacks.
//
//----------------------------------------------------------------------------
class FnProfCallbacks : public StaticEventCallbacks
{
public:
FnProfCallbacks(void)
{
m_Client = NULL;
m_Control = NULL;
}
// IDebugEventCallbacks.
STDMETHOD(GetInterestMask)(
THIS_
OUT PULONG Mask
);
STDMETHOD(Breakpoint)(
THIS_
IN PDEBUG_BREAKPOINT Bp
);
HRESULT Initialize(PDEBUG_CLIENT Client, PDEBUG_CONTROL Control)
{
m_Hits = 0;
m_Client = Client;
m_Client->AddRef();
m_Control = Control;
m_Control->AddRef();
return S_OK;
}
void Uninitialize(void)
{
EXT_RELEASE(m_Control);
EXT_RELEASE(m_Client);
}
ULONG GetHits(void)
{
return m_Hits;
}
PDEBUG_CONTROL GetControl(void)
{
return m_Control;
}
private:
PDEBUG_CLIENT m_Client;
PDEBUG_CONTROL m_Control;
ULONG m_Hits;
};
STDMETHODIMP
FnProfCallbacks::GetInterestMask(
THIS_
OUT PULONG Mask
)
{
*Mask = DEBUG_EVENT_BREAKPOINT;
return S_OK;
}
STDMETHODIMP
FnProfCallbacks::Breakpoint(
THIS_
IN PDEBUG_BREAKPOINT Bp
)
{
PDEBUG_CLIENT Client;
HRESULT Status = DEBUG_STATUS_NO_CHANGE;
// If this is one of our profiling breakpoints
// record the function hit and continue on.
if (Bp->GetAdder(&Client) == S_OK)
{
if (Client == m_Client)
{
m_Hits++;
Status = DEBUG_STATUS_GO;
}
Client->Release();
}
Bp->Release();
return Status;
}
FnProfCallbacks g_FnProfCallbacks;
//----------------------------------------------------------------------------
//
// Extension entry points.
//
//----------------------------------------------------------------------------
extern "C" HRESULT CALLBACK
DebugExtensionInitialize(PULONG Version, PULONG Flags)
{
*Version = DEBUG_EXTENSION_VERSION(1, 0);
*Flags = 0;
return S_OK;
}
extern "C" void CALLBACK
DebugExtensionUninitialize(void)
{
g_ExcepCallbacks.Uninitialize();
g_FnProfCallbacks.Uninitialize();
}
#if 0
extern "C" HRESULT CALLBACK
teb(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
ULONG64 DataOffset;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
if (*Args)
{
sscanf(Args, "%I64x", &DataOffset);
}
else
{
g_ExtSystem->GetCurrentThreadDataOffset(&DataOffset);
}
ExtOut("TEB at %I64x\n", DataOffset);
TEB Teb;
Status = g_ExtData->ReadVirtual(DataOffset, &Teb, sizeof(Teb), NULL);
if (Status != S_OK)
{
ExtErr("* Unable to read TEB\n");
}
else
{
ExtOut(" ExceptionList: %x\n", Teb.NtTib.ExceptionList);
ExtOut(" Stack Base: %x\n", Teb.NtTib.StackBase);
ExtOut(" Stack Limit: %x\n", Teb.NtTib.StackLimit);
ExtOut(" SubSystemTib: %x\n", Teb.NtTib.SubSystemTib);
ExtOut(" FiberData: %x\n", Teb.NtTib.FiberData);
ExtOut(" ArbitraryUser: %x\n", Teb.NtTib.ArbitraryUserPointer);
ExtOut(" Self: %x\n", Teb.NtTib.Self);
ExtOut(" EnvironmentPtr: %x\n", Teb.EnvironmentPointer);
ExtOut(" ClientId: %x.%x\n",
Teb.ClientId.UniqueProcess, Teb.ClientId.UniqueThread);
if (Teb.ClientId.UniqueProcess != Teb.RealClientId.UniqueProcess ||
Teb.ClientId.UniqueThread != Teb.RealClientId.UniqueThread)
{
ExtOut(" Real ClientId: %x.%x\n",
Teb.RealClientId.UniqueProcess,
Teb.RealClientId.UniqueThread);
}
ExtOut(" Real ClientId: %x.%x\n",
Teb.RealClientId.UniqueProcess,
Teb.RealClientId.UniqueThread);
ExtOut(" RpcHandle: %x\n", Teb.ActiveRpcHandle);
ExtOut(" Tls Storage: %x\n", Teb.ThreadLocalStoragePointer);
ExtOut(" PEB Address: %x\n", Teb.ProcessEnvironmentBlock);
ExtOut(" LastErrorValue: %u\n", Teb.LastErrorValue);
ExtOut(" LastStatusValue: %x\n", Teb.LastStatusValue);
ExtOut(" Count Owned Locks:%u\n", Teb.CountOfOwnedCriticalSections);
ExtOut(" HardErrorMode: %u\n", Teb.HardErrorMode);
Status = S_OK;
}
ExtRelease();
return Status;
}
#endif
extern "C" HRESULT CALLBACK
outreg(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
g_ExtRegisters->OutputRegisters(DEBUG_OUTCTL_ALL_CLIENTS,
DEBUG_REGISTERS_ALL);
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
enumreg(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
ULONG Num;
g_ExtRegisters->GetNumberRegisters(&Num);
ExtOut("%d registers\n", Num);
ULONG i;
char Name[64];
DEBUG_REGISTER_DESCRIPTION Desc;
ULONG Reax, Rebx, Refl, Rsf, Rst0;
ULONG RegFound = 0;
for (i = 0; i < Num; i++)
{
g_ExtRegisters->GetDescription(i, Name, sizeof(Name), NULL, &Desc);
ExtOut(" %2d: \"%s\", type %d, flags %X\n",
i, Name, Desc.Type, Desc.Flags);
if (Desc.Flags & DEBUG_REGISTER_SUB_REGISTER)
{
ExtOut(" sub to %d, len %d, mask %I64X, shift %d\n",
Desc.SubregMaster, Desc.SubregLength,
Desc.SubregMask, Desc.SubregShift);
}
// XXX drewb - Hack for testing purposes.
if (!_strcmpi(Name, "eax"))
{
Reax = i;
RegFound++;
}
else if (!_strcmpi(Name, "ebx"))
{
Rebx = i;
RegFound++;
}
else if (!_strcmpi(Name, "efl"))
{
Refl = i;
RegFound++;
}
else if (!_strcmpi(Name, "sf"))
{
Rsf = i;
RegFound++;
}
else if (!_strcmpi(Name, "st0"))
{
Rst0 = i;
RegFound++;
}
}
ULONG ProcType;
g_ExtControl->GetExecutingProcessorType(&ProcType);
ExtOut("Processor type %d\n", ProcType);
if (ProcType == IMAGE_FILE_MACHINE_I386)
{
DEBUG_VALUE Val;
DEBUG_VALUE Coerce;
if (RegFound != 5)
{
ExtErr("** Only found %d registers\n", RegFound);
}
Val.Type = DEBUG_VALUE_INT32;
Val.I32 = 0x12345678;
g_ExtRegisters->SetValue(Reax, &Val);
Val.I32 = 12345678;
g_ExtRegisters->SetValue(Rst0, &Val);
g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
"r eax,st0", DEBUG_EXECUTE_NOT_LOGGED);
Val.Type = DEBUG_VALUE_FLOAT32;
Val.F32 = 1.2345f;
g_ExtRegisters->SetValue(Rst0, &Val);
g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
"r st0", DEBUG_EXECUTE_NOT_LOGGED);
g_ExtRegisters->GetValue(Rst0, &Val);
ExtOut("st0 type is %d\n", Val.Type);
g_ExtControl->CoerceValue(&Val, DEBUG_VALUE_FLOAT32, &Coerce);
Coerce.F32 *= 2.0f;
ExtOut("coerce type is %d, val*2 %hf\n", Coerce.Type, Coerce.F32);
g_ExtRegisters->SetValue(Reax, &Val);
g_ExtRegisters->SetValue(Rebx, &Coerce);
g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
"r eax,ebx", DEBUG_EXECUTE_NOT_LOGGED);
g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
"r efl", DEBUG_EXECUTE_NOT_LOGGED);
g_ExtRegisters->GetValue(Rsf, &Val);
ExtOut("sf type is %d, val %d\n", Val.Type, Val.I32);
Val.I32 ^= 1;
g_ExtRegisters->SetValue(Rsf, &Val);
g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
"r efl", DEBUG_EXECUTE_NOT_LOGGED);
g_ExtRegisters->GetValue(Rsf, &Val);
ExtOut("sf type is %d, val %d\n", Val.Type, Val.I32);
Val.I32 ^= 1;
g_ExtRegisters->SetValue(Rsf, &Val);
g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS,
"r efl", DEBUG_EXECUTE_NOT_LOGGED);
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
symnear(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
LONG Delta;
Delta = 0;
sscanf(Args, "%d", &Delta);
ULONG64 Instr;
char Name[128];
ULONG64 Disp;
g_ExtRegisters->GetInstructionOffset(&Instr);
if (g_ExtSymbols->GetNearNameByOffset(Instr, Delta,
Name, sizeof(Name), NULL,
&Disp) == S_OK)
{
ExtOut("Symbol %d away from %p is:\n %s + 0x%I64x\n",
Delta, Instr, Name, Disp);
if (g_ExtSymbols->GetOffsetByName(Name, &Instr) == S_OK)
{
ExtOut("Symbol %s has offset %p\n", Name, Instr);
}
else
{
ExtOut("Symbol %s has no offset\n", Name);
}
}
else
{
ExtOut("No symbol %d away from %p\n", Delta, Instr);
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
symname(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
ULONG64 Offs;
if (g_ExtSymbols->GetOffsetByName(Args, &Offs) == S_OK)
{
ExtOut("Symbol %s has offset %I64x\n",
Args, Offs);
}
else
{
ExtOut("Symbol %s has no offset\n", Args);
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
line(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
ULONG64 Instr;
ULONG Line;
char File[128];
ULONG64 Disp;
g_ExtRegisters->GetInstructionOffset(&Instr);
if (g_ExtSymbols->GetLineByOffset(Instr, &Line,
File, sizeof(File), NULL, &Disp) == S_OK)
{
ExtOut("Line at %p is:\n %s(%d) + 0x%I64x\n",
Instr, File, Line, Disp);
if (g_ExtSymbols->GetOffsetByLine(Line, File, &Instr) == S_OK)
{
ExtOut("Line %s(%d) has offset %p\n", File, Line, Instr);
}
else
{
ExtOut("Line %s(%d) has no offset\n", File, Line);
}
}
else
{
ExtOut("No line information for %p\n", Instr);
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
sympat(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
ULONG64 Match;
char Name[128];
ULONG64 Offset;
PCSTR Pattern;
while (*Args == ' ' || *Args == '\t')
{
Args++;
}
if (*Args)
{
Pattern = Args;
}
else
{
Pattern = "*";
}
Status = g_ExtSymbols->StartSymbolMatch(Pattern, &Match);
if (Status != S_OK)
{
ExtErr("Unable to match on '%s'\n", Pattern);
}
else
{
for (;;)
{
Status = g_ExtSymbols->
GetNextSymbolMatch(Match, Name, sizeof(Name), NULL, &Offset);
if (Status != S_OK)
{
break;
}
ExtOut("%p - %s\n", Offset, Name);
if (g_ExtControl->GetInterrupt() == S_OK)
{
ExtOut("** interrupt\n");
break;
}
}
g_ExtSymbols->EndSymbolMatch(Match);
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
stack(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
ULONG Flags;
while (*Args == ' ' || *Args == '\t')
{
Args++;
}
if (*Args)
{
sscanf(Args, "%d", &Flags);
}
else
{
Flags = 0;
}
DEBUG_STACK_FRAME Frames[4];
ULONG64 FrameOff, StackOff, InstrOff;
ULONG Filled;
g_ExtRegisters->GetFrameOffset(&FrameOff);
g_ExtRegisters->GetStackOffset(&StackOff);
g_ExtRegisters->GetInstructionOffset(&InstrOff);
if (g_ExtControl->GetStackTrace(FrameOff, StackOff, InstrOff,
Frames, sizeof(Frames) / sizeof(Frames[0]),
&Filled) != S_OK)
{
ExtErr("Unable to get stack trace\n");
}
else
{
ExtOut("Filled %d frames at %p\n", Filled, InstrOff);
g_ExtControl->OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS,
Frames, Filled, Flags);
}
ExtOut("\nDirect:\n");
g_ExtControl->OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS,
NULL, 20, Flags);
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
tyid(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
ULONG TypeId;
char Type[256];
ULONG TypeSize;
ULONG64 Module;
while (*Args == ' ' || *Args == '\t')
{
Args++;
}
if (*Args >= '0' && *Args <= '9')
{
DEBUG_VALUE IntVal;
g_ExtControl->Evaluate(Args, DEBUG_VALUE_INT64, &IntVal, NULL);
Status = g_ExtSymbols->GetOffsetTypeId(IntVal.I64, &TypeId, &Module);
}
else
{
Status = g_ExtSymbols->GetSymbolTypeId(Args, &TypeId, &Module);
}
if (Status == S_OK)
{
ExtOut("Type ID of '%s' is %d\n", Args, TypeId);
}
else
{
ExtErr("Unable to get type ID, %X\n", Status);
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
typeof(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
ULONG TypeId;
char Type[256];
ULONG TypeSize;
ULONG64 Module;
while (*Args == ' ' || *Args == '\t')
{
Args++;
}
if (*Args >= '0' && *Args <= '9')
{
DEBUG_VALUE IntVal;
g_ExtControl->Evaluate(Args, DEBUG_VALUE_INT64, &IntVal, NULL);
Status = g_ExtSymbols->GetOffsetTypeId(IntVal.I64, &TypeId, &Module);
}
else
{
Status = g_ExtSymbols->GetSymbolTypeId(Args, &TypeId, &Module);
}
if (Status == S_OK)
{
Status = g_ExtSymbols->GetTypeName(Module, TypeId, Type, sizeof(Type),
&TypeSize);
}
if (Status == S_OK)
{
ExtOut("Type of '%s' is '%s':%d (%d chars)\n",
Args, Type, TypeId, TypeSize);
}
else
{
ExtErr("Unable to get type, %X\n", Status);
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
tsizeof(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
PCSTR TypeName;
ULONG TypeId;
ULONG TypeSize;
while (*Args == ' ' || *Args == '\t')
{
Args++;
}
TypeName = strchr(Args, '!');
if (TypeName == NULL)
{
ExtErr("Must specify Module!Type\n");
Status = E_INVALIDARG;
}
else
{
ULONG64 Module;
Status = g_ExtSymbols->GetSymbolModule(Args, &Module);
if (Status == S_OK)
{
Status = g_ExtSymbols->GetTypeId(Module, TypeName, &TypeId);
}
if (Status == S_OK)
{
Status = g_ExtSymbols->GetTypeSize(Module, TypeId, &TypeSize);
}
if (Status == S_OK)
{
ExtOut("Type '%s':%d is %d bytes\n",
Args, TypeId, TypeSize);
}
else
{
ExtErr("Unable to get type size, %X\n", Status);
}
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
foff(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
ULONG TypeId;
char Type[256];
PCSTR Bang, Dot;
ULONG Offset;
while (*Args == ' ' || *Args == '\t')
{
Args++;
}
Bang = strchr(Args, '!');
if (Bang != NULL)
{
Dot = strchr(Bang + 1, '.');
}
if (Bang == NULL || Dot == NULL)
{
ExtErr("Syntax is Module!Type.Field\n");
Status = E_INVALIDARG;
}
else
{
ULONG64 Module;
memcpy(Type, Bang + 1, Dot - (Bang + 1));
Type[Dot - (Bang + 1)] = 0;
Dot++;
Status = g_ExtSymbols->GetSymbolModule(Args, &Module);
if (Status == S_OK)
{
Status = g_ExtSymbols->GetTypeId(Module, Type, &TypeId);
}
if (Status == S_OK)
{
Status = g_ExtSymbols->GetFieldOffset(Module, TypeId, Dot,
&Offset);
}
if (Status == S_OK)
{
ExtOut("Offset of %s is %d bytes\n",
Args, Offset);
}
else
{
ExtErr("Unable to get field offset, %X\n", Status);
}
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
otype(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
ULONG TypeId;
char Type[256];
PCSTR Bang, Space;
while (*Args == ' ' || *Args == '\t')
{
Args++;
}
Bang = strchr(Args, '!');
if (Bang != NULL)
{
Space = strchr(Bang + 1, ' ');
}
if (Bang == NULL || Space == NULL)
{
ExtErr("Syntax is Module!Type Address\n");
Status = E_INVALIDARG;
}
else
{
memcpy(Type, Bang + 1, Space - (Bang + 1));
Type[Space - (Bang + 1)] = 0;
Space++;
ULONG64 Module;
ULONG Flags = DEBUG_OUTTYPE_RECURSION_LEVEL(15);
DEBUG_VALUE IntVal;
g_ExtControl->Evaluate(Space, DEBUG_VALUE_INT64, &IntVal, NULL);
Status = g_ExtSymbols->GetSymbolModule(Args, &Module);
if (Status == S_OK)
{
Status = g_ExtSymbols->GetTypeId(Module, Type, &TypeId);
}
if (Status == S_OK)
{
Status = g_ExtSymbols->
OutputTypedDataVirtual(DEBUG_OUTCTL_ALL_CLIENTS,
IntVal.I64, Module, TypeId, Flags);
if (Status != S_OK)
{
ExtErr("Unable to output data, %X\n", Status);
}
}
else
{
ExtErr("Unable to get type ID, %X\n", Status);
}
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
vsearch(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
ULONG Start = 0, Len = 0;
ULONG Chars;
sscanf(Args, "%x %x%n", &Start, &Len, &Chars);
if (Start == 0 || Len == 0)
{
ExtErr("Syntax is Start Len Byte+\n");
Status = E_INVALIDARG;
}
else
{
UCHAR Pattern[32];
ULONG PatLen;
Args += Chars;
PatLen = 0;
for (;;)
{
while (*Args == ' ' || *Args == '\t')
{
Args++;
}
if (*Args == 0)
{
break;
}
sscanf(Args, "%x", &Pattern[PatLen]);
PatLen++;
while (*Args != 0 && *Args != ' ' && *Args != '\t')
{
Args++;
}
}
ULONG64 Match;
Status = g_ExtData->SearchVirtual(Start, Len, Pattern, PatLen, 1,
&Match);
if (Status == S_OK)
{
ExtOut("Match at %p\n", Match);
}
else
{
ExtErr("Search failed, 0x%X\n", Status);
}
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
vread(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
ULONG Start = 0, Len = 0;
sscanf(Args, "%x %x", &Start, &Len);
if (Start == 0 || Len == 0)
{
ExtErr("Syntax is Start Len\n");
Status = E_INVALIDARG;
}
else
{
UCHAR Buffer[16384];
ULONG Read;
if (Len > sizeof(Buffer))
{
ExtWarn("Buffer is only %X bytes, clamping\n", sizeof(Buffer));
Len = sizeof(Buffer);
}
Status = g_ExtData->ReadVirtual(Start, Buffer, Len, &Read);
if (Status == S_OK)
{
ExtOut("Read %X bytes\n", Read);
}
else
{
ExtErr("Read failed, 0x%X\n", Status);
}
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
watch(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
PDEBUG_CLIENT Watcher = NULL;
if ((Status = Client->CreateClient(&Watcher)) != S_OK)
{
goto Exit;
}
if ((Status = Watcher->SetEventCallbacks(&g_ExcepCallbacks)) != S_OK)
{
goto Exit;
}
g_ExcepCallbacks.Uninitialize();
Status = g_ExcepCallbacks.Initialize(Watcher);
Exit:
EXT_RELEASE(Watcher);
if (Status != S_OK)
{
ExtErr("Unable to watch, 0x%X\n", Status);
g_ExcepCallbacks.Uninitialize();
}
return Status;
}
extern "C" HRESULT CALLBACK
fnprof(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
PDEBUG_CLIENT Profiler = NULL;
PDEBUG_CONTROL ProfCtrl = NULL;
PDEBUG_BREAKPOINT Bp = NULL;
static ULONG s_BpId = DEBUG_ANY_ID;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
while (*Args == ' ' || *Args == '\t')
{
Args++;
}
if (!*Args)
{
goto Exit;
}
if (!_strcmpi(Args, "-end"))
{
ULONG64 Offset;
char OffsetExpr[512];
if (s_BpId == DEBUG_ANY_ID)
{
Status = E_UNEXPECTED;
goto Exit;
}
if ((Status = g_FnProfCallbacks.GetControl()->
GetBreakpointById(s_BpId, &Bp)) != S_OK)
{
goto Exit;
}
if ((Status = Bp->GetOffset(&Offset)) != S_OK)
{
Offset = DEBUG_INVALID_OFFSET;
}
if ((Status = Bp->GetOffsetExpression(OffsetExpr,
sizeof(OffsetExpr),
NULL)) != S_OK)
{
goto Exit;
}
ExtOut("%s ", OffsetExpr);
if (Offset != DEBUG_INVALID_OFFSET)
{
ExtOut("(%p) ", Offset);
}
ExtOut("was hit %d times\n", g_FnProfCallbacks.GetHits());
g_FnProfCallbacks.GetControl()->RemoveBreakpoint(Bp);
Bp = NULL;
s_BpId = DEBUG_ANY_ID;
g_FnProfCallbacks.Uninitialize();
}
else
{
if (s_BpId != DEBUG_ANY_ID)
{
Status = E_UNEXPECTED;
goto Exit;
}
if ((Status = Client->CreateClient(&Profiler)) != S_OK)
{
goto Exit;
}
if ((Status = Profiler->SetEventCallbacks(&g_FnProfCallbacks)) != S_OK)
{
goto Exit;
}
if ((Status = Profiler->QueryInterface(__uuidof(IDebugControl),
(void **)&ProfCtrl)) != S_OK)
{
goto Exit;
}
if ((Status = ProfCtrl->AddBreakpoint(DEBUG_BREAKPOINT_CODE,
DEBUG_ANY_ID, &Bp)) != S_OK)
{
goto Exit;
}
if ((Status = Bp->SetOffsetExpression(Args)) != S_OK)
{
goto Exit;
}
if ((Status = Bp->AddFlags(DEBUG_BREAKPOINT_ADDER_ONLY |
DEBUG_BREAKPOINT_ENABLED)) != S_OK)
{
goto Exit;
}
if ((Status = Bp->GetId(&s_BpId)) != S_OK)
{
goto Exit;
}
g_FnProfCallbacks.Uninitialize();
if ((Status = g_FnProfCallbacks.Initialize(Profiler,
ProfCtrl)) != S_OK)
{
goto Exit;
}
ExtOut("Added breakpoint %d on %s\n", s_BpId, Args);
Bp = NULL;
}
Exit:
if (Bp != NULL)
{
if (ProfCtrl != NULL)
{
ProfCtrl->RemoveBreakpoint(Bp);
}
else
{
Bp->Release();
}
}
EXT_RELEASE(ProfCtrl);
EXT_RELEASE(Profiler);
if (Status != S_OK)
{
ExtErr("Unable to profile, 0x%X\n", Status);
g_FnProfCallbacks.Uninitialize();
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
vtrans(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
if (g_ExtData2 != NULL)
{
ULONG64 PhysOffs[8];
ULONG Levels;
DEBUG_VALUE Virt;
if ((Status = g_ExtControl->
Evaluate(Args, DEBUG_VALUE_INT64, &Virt, NULL)) == S_OK)
{
Status = g_ExtData2->
GetVirtualTranslationPhysicalOffsets(Virt.I64, PhysOffs,
sizeof(PhysOffs) /
sizeof(PhysOffs[0]),
&Levels);
if (SUCCEEDED(Status))
{
ULONG i;
ExtOut("%I64X translates in %d levels:\n",
Virt.I64, Levels);
for (i = 0; i < Levels; i++)
{
ExtOut(" %I64X\n", PhysOffs[i]);
}
}
else
{
ExtErr("Unable to translate %I64X, 0x%X\n",
Virt.I64, Status);
}
}
else
{
ExtErr("Unable to evaluate '%s', 0x%X\n", Args, Status);
}
}
else
{
ExtErr("Debugger does not support IDebugDataSpaces2\n");
}
ExtRelease();
return Status;
}
extern "C" HRESULT CALLBACK
enummod(PDEBUG_CLIENT Client, PCSTR Args)
{
HRESULT Status;
if ((Status = ExtQuery(Client)) != S_OK)
{
return Status;
}
ULONG Num[2];
ULONG Type, i, Index;
DEBUG_MODULE_PARAMETERS Params;
if ((Status = g_ExtSymbols->GetNumberModules(&Num[0],
&Num[1])) != S_OK)
{
ExtErr("GetNumberModules failed, 0x%X\n", Status);
goto Exit;
}
ExtOut("%d modules, %d unloaded modules\n", Num[0], Num[1]);
Index = -1;
for (Type = 0; Type < 2; Type++)
{
if (!Num[Type])
{
continue;
}
switch(Type)
{
case 0:
ExtOut("Loaded:\n");
ExtOut("-------\n");
break;
case 1:
ExtOut("Unloaded:\n");
ExtOut("---------\n");
break;
}
for (i = 0; i < Num[Type]; i++)
{
if ((Status = g_ExtSymbols->
GetModuleParameters(1, NULL, ++Index, &Params)) != S_OK)
{
ExtErr(" GetModuleParameters failed, 0x%X\n", Status);
continue;
}
ExtOut(" Base %p, size %08x\n", Params.Base, Params.Size);
ExtOut(" Flags %08x\n", Params.Flags);
}
}
Exit:
ExtRelease();
return Status;
}