mirror of https://github.com/tongzx/nt5src
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.
483 lines
8.9 KiB
483 lines
8.9 KiB
/*++
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|