/*
    * CrashReportSyscall.hpp
    * SYS_CRASH_REPORT
    * Copyright (c) 2026 Daniel Hammer
*/

#pragma once
#include <cstdint>
#include "Syscall.hpp"
#include "../Sched/CrashReport.hpp"

namespace montauk::abi {

    static int64_t Sys_CrashReport(CrashReportInfo* out) {
        if (!out) return 0;

        // Pop the oldest report into a kernel-local copy under the ring lock,
        // then marshal into user memory with the lock released.
        CrashReport::Report rep;
        int had = CrashReport::TakeOldest(rep);
        if (had == 0) return 0;

        out->pid = rep.pid;
        int pn;
        for (pn = 0; pn < 63 && rep.processName[pn]; pn++) out->processName[pn] = rep.processName[pn];
        out->processName[pn] = '\0';
        out->exceptionVector = rep.exceptionVector;
        int en;
        for (en = 0; en < 31 && rep.exceptionName[en]; en++) out->exceptionName[en] = rep.exceptionName[en];
        out->exceptionName[en] = '\0';
        out->faultingAddress = rep.faultingAddress;
        out->instructionPointer = rep.instructionPointer;
        out->stackPointer = rep.stackPointer;
        out->codeSegment = rep.codeSegment;
        out->flags = rep.flags;
        out->stackSegment = rep.stackSegment;
        out->pfPresent = rep.pfPresent;
        out->pfWrite = rep.pfWrite;
        out->pfUser = rep.pfUser;
        out->pfReservedWrite = rep.pfReservedWrite;
        out->pfInstructionFetch = rep.pfInstructionFetch;
        out->pfProtectionKey = rep.pfProtectionKey;
        out->pfShadowStack = rep.pfShadowStack;
        out->pfSGX = rep.pfSGX;
        out->timestampTick = rep.timestampTick;

        // Preserve the original contract: count of reports present before this
        // call (i.e. including the one just returned).
        return had;
    }

}
