aboutsummaryrefslogtreecommitdiff
path: root/mirai/crimson/corpse/generate.zig
blob: c859c158388c64e9dcba08aadbe0defa518a5220 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! Generate Corpse

const asm_cpu = @import("../../asm/cpu/cpu.zig");
const types = @import("../types/types.zig");
const context_ops = @import("../context/context.zig");

const Corpse = types.Corpse;
const Exception = types.Exception;
const Context = types.Context;
const FloatState = types.FloatState;
const DebugState = types.DebugState;
const Identity = types.Identity;

pub fn generate(exception: *const Exception) Corpse {
    var corpse: Corpse = undefined;
    corpse.clear();

    corpse.kata_id = exception.kata_id;
    corpse.thread_id = exception.thread_id;
    corpse.exception_type = exception.exception_type;
    corpse.exception_code = exception.code;
    corpse.exception_subcode = exception.subcode;
    corpse.fault_address = exception.address;

    corpse.context = exception.context.*;

    capture_float_state(&corpse.float_state);
    capture_debug_state(&corpse.debug_state);

    capture_stack_snapshot(&corpse, exception.context.rsp);

    if (exception.address != 0) {
        capture_memory_snapshot(&corpse, exception.address);
    }

    corpse.timestamp = asm_cpu.rdtsc();
    corpse.mark_valid();

    return corpse;
}

fn capture_float_state(state: *FloatState) void {
    context_ops.capture_float(state);
}

fn capture_debug_state(state: *DebugState) void {
    context_ops.capture_debug(state);
}

fn capture_stack_snapshot(corpse: *Corpse, rsp: u64) void {
    if (rsp == 0) {
        corpse.stack_snapshot_size = 0;
        return;
    }

    const stack_ptr: [*]const u8 = @ptrFromInt(rsp);
    const copy_size: usize = 4096;

    for (0..copy_size) |i| {
        corpse.stack_snapshot[i] = stack_ptr[i];
    }
    corpse.stack_snapshot_size = copy_size;
}

fn capture_memory_snapshot(corpse: *Corpse, address: u64) void {
    const page_start = address & ~@as(u64, 0xFFF);
    const offset = address - page_start;

    const start = if (offset >= 2048) address - 2048 else page_start;
    const copy_size: usize = 4096;

    const mem_ptr: [*]const u8 = @ptrFromInt(start);
    for (0..copy_size) |i| {
        corpse.memory_snapshot[i] = mem_ptr[i];
    }
    corpse.memory_snapshot_address = start;
    corpse.memory_snapshot_size = copy_size;
}