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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use crate::emu::fpu::FPU;
use crate::emu::regs64::Regs64;
use crate::emu::maps::Maps;

pub struct Context32 {
    ctx_flags:u32,
    dr0:u32,
    dr1:u32,
    dr2:u32,
    dr3:u32,
    dr6:u32,
    dr7:u32,
    fpu:FPU,
    seg_gs:u32,
    seg_fd:u32,
    seg_es:u32,
    seg_ds:u32,
    edi:u32,  // +9c
    esi:u32,  // +a0
    ebx:u32,  // +a4
    edx:u32,  // +a8
    ecx:u32,  // +ac
    eax:u32,  // +b0
    ebp:u32,  // +b4
    eip:u32,  // +b8
    seg_cs:u32, // +bc
    eflags:u32, // +c0
    esp:u32, // +c4
    seg_ss:u32,
}

impl Context32 {
    pub fn new(regs:&Regs64) -> Context32 {
        Context32 {
            ctx_flags: 0,
            dr0: 0,
            dr1: 0,
            dr2: 0,
            dr3: 0,
            dr6: 0,
            dr7: 0,
            fpu: FPU::new(),
            seg_gs: 0,
            seg_fd: 0,
            seg_es: 0,
            seg_ds: 0,
            edi: regs.get_edi() as u32,
            esi: regs.get_esi() as u32,
            ebx: regs.get_ebx() as u32,
            edx: regs.get_edx() as u32,
            ecx: regs.get_ecx() as u32,
            eax: regs.get_eax() as u32,
            ebp: regs.get_ebp() as u32,
            eip: regs.get_eip() as u32,
            seg_cs: 0,
            eflags: 0,
            esp: regs.get_esp() as u32,
            seg_ss: 0,
        }
    }

    pub fn save(&self, addr:u32, maps:&mut Maps) {
        maps.write_dword((addr+4) as u64, self.dr0);
        maps.write_dword((addr+8) as u64, self.dr1);
        maps.write_dword((addr+12) as u64, self.dr2);
        maps.write_dword((addr+16) as u64, self.dr3);
        maps.write_dword((addr+20) as u64, self.dr6);
        maps.write_dword((addr+24) as u64, self.dr7);

        maps.write_dword((addr+0x9c) as u64, self.edi);
        maps.write_dword((addr+0xa0) as u64, self.esi);
        maps.write_dword((addr+0xa4) as u64, self.ebx);
        maps.write_dword((addr+0xa8) as u64, self.edx);
        maps.write_dword((addr+0xac) as u64, self.ecx);
        maps.write_dword((addr+0xb0) as u64, self.eax);
        maps.write_dword((addr+0xb4) as u64, self.ebp);
        maps.write_dword((addr+0xb8) as u64, self.eip);
        maps.write_dword((addr+0xc4) as u64, self.esp);        
    }

    pub fn load(&mut self, addr:u32, maps:&mut Maps) {
        self.dr0 = maps.read_dword((addr+4) as u64).expect("cannot read dr0 from ctx");
        self.dr1 = maps.read_dword((addr+8) as u64).expect("cannot read dr1 from ctx");
        self.dr2 = maps.read_dword((addr+12) as u64).expect("cannot read dr2 from ctx");
        self.dr3 = maps.read_dword((addr+16) as u64).expect("cannot read dr3 from ctx");
        self.dr6 = maps.read_dword((addr+20) as u64).expect("cannot read dr6 from ctx");
        self.dr7 = maps.read_dword((addr+24) as u64).expect("cannot read dr7 from ctx");

        self.edi = maps.read_dword((addr+0x9c) as u64).expect("cannot read edi from ctx");
        self.esi = maps.read_dword((addr+0xa0) as u64).expect("cannot read esi from ctx");
        self.ebx = maps.read_dword((addr+0xa4) as u64).expect("cannot read ebx from ctx");
        self.edx = maps.read_dword((addr+0xa8) as u64).expect("cannot read edx from ctx");
        self.ecx = maps.read_dword((addr+0xac) as u64).expect("cannot read ecx from ctx");
        self.eax = maps.read_dword((addr+0xb0) as u64).expect("cannot read eax from ctx");
        self.ebp = maps.read_dword((addr+0xb4) as u64).expect("cannot read ebp from ctx");
        self.eip = maps.read_dword((addr+0xb8) as u64).expect("cannot read eip from ctx");
        self.esp = maps.read_dword((addr+0xc4) as u64).expect("cannot read esp from ctx");
    }

    pub fn sync(&self, regs:&mut Regs64) {
        regs.set_eax(self.eax as u64);
        regs.set_ebx(self.ebx as u64);
        regs.set_ecx(self.ecx as u64);
        regs.set_edx(self.edx as u64);
        regs.set_esi(self.esi as u64);
        regs.set_edi(self.edi as u64);
        regs.set_esp(self.esp as u64);
        regs.set_ebp(self.ebp as u64);
        regs.set_eip(self.eip as u64);
    }

}