better ps
This commit is contained in:
1 parent
325149006c
commit
c1a291c4c9
8 files changed
+226
-24
No files matched your search
Binary file not shown.
@@ -115,7 +115,9 @@ uint32_t KeGetHandleRights(PROCESS* process, uint32_t handle);
|
||||
LIST_ENTRY* KeGetProcessList(void);
|
||||
PROCESS* KeGetCurrentProcess(void);
|
||||
PROCESS* KeGetSystemProcess(void);
|
||||
/* Copy a snapshot of process IDs into caller-provided storage. */
|
||||
size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount);
|
||||
struct SYS_PROCESS_INFO;
|
||||
|
||||
/* Copy a snapshot of rich process information into caller-provided storage. */
|
||||
size_t KeCopyProcessInfo(struct SYS_PROCESS_INFO* infoOut, size_t maxCount);
|
||||
/* Find a live process by its ProcessId. Bumps refcount; caller must ObDereferenceObject. */
|
||||
PROCESS* KeGetProcessById(uint32_t pid);
|
||||
@@ -126,6 +126,7 @@ KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t
|
||||
KSTATUS MmDestroyUserRegion(PROCESS* process, void* base);
|
||||
void MmDestroyAllUserRegions(PROCESS* process);
|
||||
KSTATUS MmQueryUserRegion(PROCESS* process, const void* address, void** baseOut, size_t* sizeOut, uint64_t* pageFlagsOut, USER_REGION_TYPE* typeOut, uint32_t* regionFlagsOut);
|
||||
void MmQueryProcessUserMemory(PROCESS* process, size_t* regionCountOut, size_t* reservedBytesOut, size_t* committedBytesOut);
|
||||
size_t MmGetUserRegionSize(PROCESS* process, const void* base);
|
||||
size_t MmGetUserRegionSizeByBase(const void* base);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <kernel/ob_object.h>
|
||||
#include <kernel/ke_cpu.h>
|
||||
#include <kernel/hal/hal_apic.h>
|
||||
#include <ntlite/syscall.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Global process list
|
||||
@@ -64,15 +65,86 @@ KSTATUS KeCreateSystemProcess(PROCESS** out) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
size_t KeCopyProcessIds(uint32_t* pidsOut, size_t maxCount) {
|
||||
static uint32_t KiCountProcessHandlesLocked(PROCESS* process) {
|
||||
uint32_t count = 0;
|
||||
if (!process) return 0;
|
||||
|
||||
for (uint32_t i = 1; i < HANDLE_TABLE_SIZE; i++) {
|
||||
if (process->Handles[i].Object) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void KiCopyTruncatedString(char* dst, size_t dstSize, const char* src, size_t srcLen) {
|
||||
if (!dst || dstSize == 0) return;
|
||||
size_t n = 0;
|
||||
if (src) {
|
||||
while (n + 1 < dstSize && n < srcLen && src[n]) {
|
||||
dst[n] = src[n];
|
||||
n++;
|
||||
}
|
||||
}
|
||||
dst[n] = '\0';
|
||||
}
|
||||
|
||||
size_t KeCopyProcessInfo(struct SYS_PROCESS_INFO* infoOut, size_t maxCount) {
|
||||
KiProcessInit();
|
||||
|
||||
PROCESS* current = KeGetCurrentProcess();
|
||||
PROCESS* system = KeGetSystemProcess();
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gProcessListLock);
|
||||
size_t count = 0;
|
||||
LIST_ENTRY* head = &gProcessList;
|
||||
for (LIST_ENTRY* node = head->Fwd; node != head; node = node->Fwd) {
|
||||
PROCESS* p = CONTAINING_RECORD(node, PROCESS, GlobalLink);
|
||||
if (pidsOut && count < maxCount) pidsOut[count] = p->ProcessId;
|
||||
if (infoOut && count < maxCount) {
|
||||
SYS_PROCESS_INFO* info = &infoOut[count];
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->Size = sizeof(*info);
|
||||
info->ProcessId = p->ProcessId;
|
||||
info->ImageBase = p->ImageBase;
|
||||
info->ImageSize = p->ImageSize;
|
||||
info->PebBase = p->UserPebBase;
|
||||
info->ModuleCount = p->ModuleCount;
|
||||
|
||||
uintptr_t handleFlags = KeAcquireSpinlock(&p->HandleLock);
|
||||
uint32_t threadCount = p->ThreadCount;
|
||||
uint32_t handleCount = KiCountProcessHandlesLocked(p);
|
||||
int exitCode = p->ExitCode;
|
||||
long terminating = p->Terminating;
|
||||
long exited = p->Exited;
|
||||
KeReleaseSpinlock(&p->HandleLock, handleFlags);
|
||||
|
||||
info->ThreadCount = threadCount;
|
||||
info->HandleCount = handleCount;
|
||||
info->ExitCode = exitCode;
|
||||
|
||||
if (exited) {
|
||||
info->State = SYS_PROCESS_STATE_EXITED;
|
||||
info->Flags |= SYS_PROCESS_FLAG_EXITED;
|
||||
} else if (terminating) {
|
||||
info->State = SYS_PROCESS_STATE_TERMINATING;
|
||||
info->Flags |= SYS_PROCESS_FLAG_TERMINATING;
|
||||
} else {
|
||||
info->State = SYS_PROCESS_STATE_RUNNING;
|
||||
}
|
||||
|
||||
if (p == system) info->Flags |= SYS_PROCESS_FLAG_SYSTEM;
|
||||
if (p == current) info->Flags |= SYS_PROCESS_FLAG_CURRENT;
|
||||
|
||||
MmQueryProcessUserMemory(p, &info->UserRegionCount,
|
||||
&info->UserReservedBytes,
|
||||
&info->UserCommittedBytes);
|
||||
|
||||
KiCopyTruncatedString(info->Name, sizeof(info->Name), p->Name, sizeof(p->Name));
|
||||
|
||||
uintptr_t cwdFlags = KeAcquireSpinlock(&p->CwdLock);
|
||||
info->CurrentDrive = p->CurrentDrive;
|
||||
KiCopyTruncatedString(info->CurrentDirectory, sizeof(info->CurrentDirectory),
|
||||
p->CurrentDirectory, p->CurrentDirectoryLength);
|
||||
KeReleaseSpinlock(&p->CwdLock, cwdFlags);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
KeReleaseSpinlock(&gProcessListLock, flags);
|
||||
|
||||
@@ -2012,7 +2012,7 @@ static uint64_t SyscallKillProcess(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// SYS_GET_PROCESS_LIST (65) a0=*pidsOut a1=maxCount a2=*countOut
|
||||
// SYS_GET_PROCESS_LIST (6) a0=*SYS_PROCESS_INFO[] a1=maxCount a2=*countOut
|
||||
// ---------------------------------------------------------------------------
|
||||
static uint64_t SyscallGetProcessList(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
uint64_t a3, uint64_t a4, uint64_t a5) {
|
||||
@@ -2025,20 +2025,20 @@ static uint64_t SyscallGetProcessList(uint64_t a0, uint64_t a1, uint64_t a2,
|
||||
if (!KSUCCESS(s)) return s;
|
||||
}
|
||||
|
||||
size_t total = KeCopyProcessIds(NULL, 0);
|
||||
size_t total = KeCopyProcessInfo(NULL, 0);
|
||||
size_t toCopy = total < maxCount ? total : maxCount;
|
||||
|
||||
if (toCopy) {
|
||||
size_t bytes = 0;
|
||||
if (!KiMulSize(toCopy, sizeof(uint32_t), &bytes)) return STATUS_INVALID_PARAMETER;
|
||||
if (!KiMulSize(toCopy, sizeof(SYS_PROCESS_INFO), &bytes)) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
uint32_t* tmp = (uint32_t*)MmAllocatePool(bytes);
|
||||
SYS_PROCESS_INFO* tmp = (SYS_PROCESS_INFO*)MmAllocatePool(bytes);
|
||||
if (!tmp) return STATUS_NO_MEMORY;
|
||||
|
||||
size_t copied = KeCopyProcessIds(tmp, toCopy);
|
||||
size_t copied = KeCopyProcessInfo(tmp, toCopy);
|
||||
if (copied < toCopy) toCopy = copied;
|
||||
|
||||
KSTATUS s = CopyToUser((void*)(uintptr_t)a0, tmp, toCopy * sizeof(uint32_t));
|
||||
KSTATUS s = CopyToUser((void*)(uintptr_t)a0, tmp, toCopy * sizeof(SYS_PROCESS_INFO));
|
||||
MmFreePool(tmp);
|
||||
if (!KSUCCESS(s)) return s;
|
||||
}
|
||||
|
||||
@@ -1204,6 +1204,28 @@ KSTATUS MmQueryUserRegion(PROCESS* process, const void* address, void** baseOut,
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
void MmQueryProcessUserMemory(PROCESS* process, size_t* regionCountOut, size_t* reservedBytesOut, size_t* committedBytesOut) {
|
||||
size_t regions = 0;
|
||||
size_t reserved = 0;
|
||||
size_t committed = 0;
|
||||
|
||||
if (process) {
|
||||
uintptr_t flags = KeAcquireSpinlock(&process->UserRegionLock);
|
||||
for (LIST_ENTRY* node = process->UserRegions.Fwd; node != &process->UserRegions; node = node->Fwd) {
|
||||
USER_VA_REGION* r = CONTAINING_RECORD(node, USER_VA_REGION, ProcessLink);
|
||||
regions++;
|
||||
reserved += r->ReservationSize;
|
||||
committed += r->CommittedSize;
|
||||
}
|
||||
KeReleaseSpinlock(&process->UserRegionLock, flags);
|
||||
}
|
||||
|
||||
if (regionCountOut) *regionCountOut = regions;
|
||||
if (reservedBytesOut) *reservedBytesOut = reserved;
|
||||
if (committedBytesOut) *committedBytesOut = committed;
|
||||
}
|
||||
|
||||
size_t MmGetUserRegionSize(PROCESS* process, const void* base) {
|
||||
if (!process || !base) return 0;
|
||||
uintptr_t procFlags = KeAcquireSpinlock(&process->UserRegionLock);
|
||||
|
||||
@@ -193,7 +193,46 @@ uint32_t SysCreateProcess(const SYS_CREATE_PROCESS_REQUEST* request);
|
||||
uint32_t SysWaitForProcess(uint32_t handle);
|
||||
uint32_t SysGetProcessExitCode(uint32_t handle, int* exitCodeOut);
|
||||
uint32_t SysKillProcess(uint32_t pid, int exitCode);
|
||||
uint32_t SysGetProcessList(uint32_t* pidsOut, size_t maxCount, size_t* countOut);
|
||||
|
||||
#define SYS_PROCESS_NAME_MAX 64u
|
||||
#define SYS_PROCESS_CWD_MAX 128u
|
||||
|
||||
#define SYS_PROCESS_STATE_RUNNING 0u
|
||||
#define SYS_PROCESS_STATE_TERMINATING 1u
|
||||
#define SYS_PROCESS_STATE_EXITED 2u
|
||||
|
||||
#define SYS_PROCESS_FLAG_SYSTEM 0x00000001u
|
||||
#define SYS_PROCESS_FLAG_CURRENT 0x00000002u
|
||||
#define SYS_PROCESS_FLAG_TERMINATING 0x00000004u
|
||||
#define SYS_PROCESS_FLAG_EXITED 0x00000008u
|
||||
|
||||
typedef struct SYS_PROCESS_INFO {
|
||||
uint32_t Size;
|
||||
uint32_t ProcessId;
|
||||
uint32_t State;
|
||||
uint32_t Flags;
|
||||
|
||||
uint32_t ThreadCount;
|
||||
uint32_t HandleCount;
|
||||
uint32_t ModuleCount;
|
||||
uint32_t CurrentDrive;
|
||||
|
||||
int32_t ExitCode;
|
||||
uint32_t Reserved0;
|
||||
|
||||
uintptr_t ImageBase;
|
||||
size_t ImageSize;
|
||||
uintptr_t PebBase;
|
||||
|
||||
size_t UserRegionCount;
|
||||
size_t UserReservedBytes;
|
||||
size_t UserCommittedBytes;
|
||||
|
||||
char Name[SYS_PROCESS_NAME_MAX];
|
||||
char CurrentDirectory[SYS_PROCESS_CWD_MAX];
|
||||
} SYS_PROCESS_INFO;
|
||||
|
||||
uint32_t SysGetProcessList(SYS_PROCESS_INFO* processesOut, size_t maxCount, size_t* countOut);
|
||||
uint32_t SysGetProcessPid(uint32_t handle, uint32_t* pidOut);
|
||||
|
||||
uint32_t SysCreateThread(uintptr_t entry, uintptr_t arg, uint32_t priority, uint32_t* tidOut);
|
||||
|
||||
@@ -5,10 +5,7 @@
|
||||
#include <ntlite/syscall.h>
|
||||
|
||||
#define MAX_CMD 256
|
||||
#define MAX_PIDS 64 // Maximum number of PIDs we will fetch at once
|
||||
|
||||
// External Syscall Prototypes
|
||||
uint32_t SysGetProcessList(uint32_t* pidsOut, size_t maxCount, size_t* countOut);
|
||||
#define MAX_PROCS 64 // Maximum number of processes we will fetch at once
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Output helpers
|
||||
@@ -64,6 +61,34 @@ static void printUInt64(uint64_t n) {
|
||||
while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); }
|
||||
}
|
||||
|
||||
static uint32_t u64Digits(uint64_t n) {
|
||||
uint32_t digits = 1;
|
||||
while (n >= 10u) { n /= 10u; digits++; }
|
||||
return digits;
|
||||
}
|
||||
|
||||
static void printSpaces(size_t count) {
|
||||
while (count--) print(" ");
|
||||
}
|
||||
|
||||
static void printUIntWidth(uint32_t n, size_t width) {
|
||||
uint32_t digits = u64Digits(n);
|
||||
if (width > digits) printSpaces(width - digits);
|
||||
printUInt(n);
|
||||
}
|
||||
|
||||
static void printUInt64Width(uint64_t n, size_t width) {
|
||||
uint32_t digits = u64Digits(n);
|
||||
if (width > digits) printSpaces(width - digits);
|
||||
printUInt64(n);
|
||||
}
|
||||
|
||||
static void printStringWidth(const char* s, size_t width) {
|
||||
size_t len = s ? strlen(s) : 0;
|
||||
if (s) print(s);
|
||||
if (width > len) printSpaces(width - len);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Line editor
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -96,7 +121,7 @@ static void cmd_help() {
|
||||
" help - Show this list\n"
|
||||
" mem - Show memory usage\n"
|
||||
" stats - Show scheduler/CPU/PMM telemetry\n"
|
||||
" ps - List running process IDs\n"
|
||||
" ps - List processes\n"
|
||||
" dir [path] - List directory contents\n"
|
||||
" cd <path> - Change directory\n"
|
||||
" type <file> - Display file contents\n"
|
||||
@@ -218,30 +243,71 @@ static void cmd_mem(void) {
|
||||
print("\n");
|
||||
}
|
||||
|
||||
static const char* processStateName(uint32_t state) {
|
||||
switch (state) {
|
||||
case SYS_PROCESS_STATE_RUNNING: return "run";
|
||||
case SYS_PROCESS_STATE_TERMINATING: return "term";
|
||||
case SYS_PROCESS_STATE_EXITED: return "exit";
|
||||
default: return "?";
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_ps(void) {
|
||||
uint32_t pids[MAX_PIDS];
|
||||
SYS_PROCESS_INFO procs[MAX_PROCS];
|
||||
size_t count = 0;
|
||||
|
||||
uint32_t status = SysGetProcessList(pids, MAX_PIDS, &count);
|
||||
uint32_t status = SysGetProcessList(procs, MAX_PROCS, &count);
|
||||
if (status != 0) {
|
||||
print("ps: failed to retrieve process list\n");
|
||||
return;
|
||||
}
|
||||
|
||||
print("Running Processes (Count: ");
|
||||
print("Processes (Count: ");
|
||||
printUInt((uint32_t)count);
|
||||
print("):\n");
|
||||
print(" PID State Thr Hnd Mod UserKiB ImageKiB Flags Name\n");
|
||||
|
||||
size_t displayCount = count < MAX_PIDS ? count : MAX_PIDS;
|
||||
size_t displayCount = count < MAX_PROCS ? count : MAX_PROCS;
|
||||
for (size_t i = 0; i < displayCount; i++) {
|
||||
print(" PID: ");
|
||||
printUInt(pids[i]);
|
||||
SYS_PROCESS_INFO* p = &procs[i];
|
||||
char flags[5];
|
||||
size_t flagLen = 0;
|
||||
|
||||
if (p->Flags & SYS_PROCESS_FLAG_SYSTEM) flags[flagLen++] = 'S';
|
||||
if (p->Flags & SYS_PROCESS_FLAG_CURRENT) flags[flagLen++] = '*';
|
||||
if (p->Flags & SYS_PROCESS_FLAG_TERMINATING) flags[flagLen++] = 'T';
|
||||
if (p->Flags & SYS_PROCESS_FLAG_EXITED) flags[flagLen++] = 'X';
|
||||
if (flagLen == 0) flags[flagLen++] = '-';
|
||||
flags[flagLen] = '\0';
|
||||
|
||||
print(" ");
|
||||
printUIntWidth(p->ProcessId, 3);
|
||||
print(" ");
|
||||
printStringWidth(processStateName(p->State), 5);
|
||||
print(" ");
|
||||
printUIntWidth(p->ThreadCount, 3);
|
||||
print(" ");
|
||||
printUIntWidth(p->HandleCount, 3);
|
||||
print(" ");
|
||||
printUIntWidth(p->ModuleCount, 3);
|
||||
print(" ");
|
||||
printUInt64Width((uint64_t)p->UserCommittedBytes / 1024u, 7);
|
||||
print(" ");
|
||||
printUInt64Width((uint64_t)p->ImageSize / 1024u, 8);
|
||||
print(" ");
|
||||
printStringWidth(flags, 5);
|
||||
print(" ");
|
||||
print(p->Name);
|
||||
if (p->CurrentDirectory[0]) {
|
||||
print(" cwd=");
|
||||
print(p->CurrentDirectory);
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
|
||||
if (count > MAX_PIDS) {
|
||||
if (count > MAX_PROCS) {
|
||||
print(" ... and ");
|
||||
printUInt((uint32_t)(count - MAX_PIDS));
|
||||
printUInt((uint32_t)(count - MAX_PROCS));
|
||||
print(" more processes.\n");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user