windows-nt/Source/XPSP1/NT/sdktools/debuggers/exts/kextdll/physical.cpp
2020-09-26 16:20:57 +08:00

484 lines
8.9 KiB
C++

/*++
Copyright (c) 1992-2000 Microsoft Corporation
Module Name:
physical.cpp
Abstract:
Extensions to read/display physocal memory
Environment:
User Mode.
Revision History:
Kshitiz K. Sharma (kksharma) 5/9/2001
--*/
#include "precomp.h"
#pragma hdrstop
ULONG64 g_LastAddress = 0;
/*++
Routine Description:
Dumps specified range of physical memory in given format
Arguments:
Address - Address to start
NumEntries - Number of entries to dump
EntrySize - Size of each entry
ShowAsAscii - print corresponding ascii chars
Return Value:
None.
--*/
BOOL
DumpPhysicalMemory(
ULONG64 Address,
ULONG NumEntries,
ULONG EntrySize,
BOOL ShowAsAscii
)
{
#define NumberBytesToRead 32*4
UCHAR Buffer[NumberBytesToRead];
ULONG ActualRead=0;
if ((EntrySize != 1) && (EntrySize != 2) && (EntrySize != 4) && (EntrySize != 8)) {
EntrySize=4;
}
while (1) {
if (CheckControlC()) {
break;
}
ReadPhysical(Address,Buffer,sizeof(Buffer),&ActualRead);
if (ActualRead != sizeof(Buffer)) {
dprintf("Physical memory read at %I64lx failed\n", Address);
return FALSE;
} else {
PCHAR DumpByte = (PCHAR)&Buffer[0], pRow;
ULONG cnt;
pRow = DumpByte;
for(cnt=0;cnt<NumberBytesToRead;DumpByte+=EntrySize) {
if (!(cnt & 0xf)) {
dprintf("#%8I64lx", Address+cnt);
}
switch (EntrySize) {
case 1:
dprintf("%c%02lx", ((cnt&0xf) == 8 ? '-' : ' '),*((PUCHAR)DumpByte));
break;
case 2:
dprintf(" %04lx", *((PUSHORT) DumpByte));
break;
case 4:
dprintf(" %08lx", *((PULONG) DumpByte));
break;
case 8:
dprintf(" %08lx'%08lx", *((PULONG) DumpByte), *((PULONG) (DumpByte+4)));
break;
}
cnt+=EntrySize, NumEntries--;
if ((cnt && !(cnt & 0xf)) || !NumEntries) {
if (ShowAsAscii) {
char ch;
dprintf(" ");
for (ULONG d=0; d < 16; d++) {
ch = pRow[d];
if (ch < 0x20 || ch > 0x7e) {
ch = '.';
}
dprintf("%c", ch);
}
}
dprintf("\n");
pRow = DumpByte;
}
if (!NumEntries) {
break;
}
}
Address += cnt;
if (!NumEntries) {
break;
}
}
}
g_LastAddress = Address;
return TRUE;
}
/*++
Routine Description:
Reverse sign extension of the value returned by GetExpression()
based on the assumption that no physical address may be bigger
than 0xfffffff00000000.
Arguments:
Val - points to the value to reverse sign extension
Return Value:
None.
--*/
void
ReverseSignExtension(ULONG64* Val)
{
if ((*Val & 0xffffffff00000000) == 0xffffffff00000000)
{
*Val &= 0x00000000ffffffff;
}
}
void
GetPhyDumpArgs(
PCSTR Args,
PULONG64 Address,
PULONG Range
)
{
CHAR Buffer[100]={0};
if(*Args == '\0') {
*Address=g_LastAddress;
} else {
sscanf(Args, "%s", Buffer);
*Address = GetExpression((PCSTR) &Buffer[0]);
ReverseSignExtension(Address);
*Address &= (~0x3); // Truncate to dword boundary
g_LastAddress=*Address;
Args += strlen(&Buffer[0]);
while (*Args && (*Args == ' ' || *Args == '\t')) {
++Args;
}
if (*Args == 'l' || *Args == 'L') {
++Args;
*Range = (ULONG) GetExpression(Args);
}
}
return;
}
DECLARE_API( db )
/*++
Routine Description:
Does a read of 16 ULONGS from the physical memory of the target machine
Arguments:
args - Supplies physical address
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Range = 0;
GetPhyDumpArgs(args, &Address, &Range);
if (!Range) {
Range = 128;
}
DumpPhysicalMemory(Address, Range, 1, TRUE);
return S_OK;
}
DECLARE_API( dd )
/*++
Routine Description:
Does a read of 16 ULONGS from the physical memory of the target machine
Arguments:
args - Supplies physical address
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Range = 0;
GetPhyDumpArgs(args, &Address, &Range);
if (!Range) {
Range = 32;
}
DumpPhysicalMemory(Address, Range, 4, FALSE);
return S_OK;
}
DECLARE_API( dw )
/*++
Routine Description:
Does a read of 16 ULONGS from the physical memory of the target machine
Arguments:
args - Supplies physical address
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Range = 0;
GetPhyDumpArgs(args, &Address, &Range);
if (!Range) {
Range = 64;
}
DumpPhysicalMemory(Address, Range, 2, FALSE);
return S_OK;
}
DECLARE_API( dp )
/*++
Routine Description:
Does a read of 16 ULONGS from the physical memory of the target machine
Arguments:
args - Supplies physical address
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Range = 0;
GetPhyDumpArgs(args, &Address, &Range);
if (!Range) {
Range = IsPtr64() ? 16 : 32;
}
DumpPhysicalMemory(Address, Range, IsPtr64() ? 8 : 4, FALSE);
return S_OK;
}
DECLARE_API( dc )
/*++
Routine Description:
Does a read of N ULONGS from the physical memory of the target machine,
dumping both hex and ASCII.
Arguments:
args - Supplies physical address
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Range = 0;
GetPhyDumpArgs(args, &Address, &Range);
if (!Range) {
Range = 32;
}
DumpPhysicalMemory(Address, Range, 4, TRUE);
return S_OK;
}
DECLARE_API( du )
/*++
Routine Description:
Does a read of 16 ULONGS from the physical memory of the target machine
Arguments:
args - Supplies physical address
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Range = 0, ActualRead;
WCHAR Buffer[MAX_PATH]={0};
GetPhyDumpArgs(args, &Address, &Range);
if (Range>MAX_PATH) {
Range = MAX_PATH;
}
if (!Range) {
Range = 16;
}
ReadPhysical(Address,Buffer,Range,&ActualRead);
if (ActualRead != Range) {
dprintf("Physical memory read at %I64lx failed\n", Address);
return FALSE;
} else {
ULONG cnt;
dprintf("#%8I64lx \"", Address);
for (ULONG d=0; d < Range; d++) {
WCHAR ch = Buffer[d];
if (ch < 0x20 || ch > 0x7e) {
ch = '.';
}
dprintf("%wc", ch);
}
dprintf("\"\n", Address);
}
return S_OK;
}
DECLARE_API( ed )
/*++
Routine Description:
Writes a sequence of ULONGs into a given physical address on the
target machine.
Arguments:
arg - Supplies both the target address and the data in the form of
"PHYSICAL_ADDRESS ULONG [ULONG, ULONG,...]"
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Buffer;
ULONG ActualWritten=0;
PCHAR NextToken;
Address = GetExpression(args);
strtok((PSTR)args," \t,"); // The first token is the address
// Since we're picking off one ULONG at a time, we'll make
// one DbgKdWritePhysicalMemoryAddress call per ULONG. This
// is slow, but easy to code.
while((NextToken=strtok(NULL," \t,")) != NULL) {
if (!sscanf(NextToken,"%lx",&Buffer)) {
break;
}
WritePhysical(Address,&Buffer,sizeof(Buffer),&ActualWritten);
Address+=sizeof(Buffer);
}
return S_OK;
}
DECLARE_API( eb )
/*++
Routine Description:
Writes a sequence of BYTEs into a given physical address on the
target machine.
Arguments:
arg - Supplies both the target address and the data in the form of
"PHYSICAL_ADDRESS ULONG [ULONG, ULONG,...]"
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Buffer;
UCHAR c;
ULONG ActualWritten;
PCHAR NextToken;
UNREFERENCED_PARAMETER (Client);
Address = GetExpression(args);
strtok((PSTR)args," \t,"); // The first token is the address
// Since we're picking off one BYTE at a time, we'll make
// one DbgKdWritePhysicalMemoryAddress call per BYTE. This
// is slow, but easy to code.
while((NextToken=strtok(NULL," \t,")) != NULL) {
if (!sscanf(NextToken,"%lx",&Buffer)) {
break;
}
c = (UCHAR)Buffer;
WritePhysical(Address,&c,sizeof(UCHAR),&ActualWritten);
Address+=sizeof(UCHAR);
}
return S_OK;
}