62 lines
1.7 KiB
C++
62 lines
1.7 KiB
C++
/*
|
|
* CrashReport.hpp
|
|
* Structured crash report for userspace process faults
|
|
* Copyright (c) 2026 Daniel Hammer
|
|
*/
|
|
|
|
#pragma once
|
|
#include <cstdint>
|
|
#include <cstddef>
|
|
|
|
namespace CrashReport {
|
|
|
|
static constexpr int MaxReports = 8;
|
|
static constexpr int StackSnapshotWords = 8;
|
|
|
|
struct Report {
|
|
int pid;
|
|
char processName[64];
|
|
uint8_t exceptionVector;
|
|
char exceptionName[32];
|
|
|
|
uint64_t faultingAddress;
|
|
uint64_t instructionPointer;
|
|
uint64_t stackPointer;
|
|
uint64_t codeSegment;
|
|
uint64_t flags;
|
|
uint64_t stackSegment;
|
|
uint64_t stackWords[StackSnapshotWords];
|
|
uint8_t stackWordCount;
|
|
|
|
// Page fault error code bits (vector 0xE / page fault only)
|
|
uint8_t pfPresent : 1;
|
|
uint8_t pfWrite : 1;
|
|
uint8_t pfUser : 1;
|
|
uint8_t pfReservedWrite : 1;
|
|
uint8_t pfInstructionFetch : 1;
|
|
uint8_t pfProtectionKey : 1;
|
|
uint8_t pfShadowStack : 1;
|
|
uint8_t pfSGX : 1;
|
|
|
|
uint64_t timestampTick;
|
|
bool valid;
|
|
};
|
|
|
|
// Kernel-side ring buffer (written by exception handlers, read by SYS_CRASH_REPORT).
|
|
// All access is serialized by an internal interrupt-disabling spinlock: the
|
|
// writer (AddReport) runs in exception/interrupt context and the reader
|
|
// (TakeOldest) runs in syscall context, possibly on different CPUs.
|
|
extern Report g_reports[MaxReports];
|
|
extern int g_reportHead;
|
|
extern int g_reportCount;
|
|
|
|
// Add a report to the kernel ring buffer (called from exception handlers).
|
|
void AddReport(const Report& report);
|
|
|
|
// Pop the oldest report into `out`. Returns the number of reports that were
|
|
// present before this call (0 if the buffer was empty, in which case `out` is
|
|
// left untouched). Safe against concurrent AddReport / TakeOldest.
|
|
int TakeOldest(Report& out);
|
|
|
|
} // namespace CrashReport
|