File: sample_m68k.c

package info (click to toggle)
unicorn-engine 2.1.4-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 23,912 kB
  • sloc: ansic: 379,830; python: 9,213; sh: 9,011; java: 8,609; ruby: 4,241; pascal: 1,805; haskell: 1,379; xml: 490; cs: 424; makefile: 348; cpp: 298; asm: 64
file content (151 lines) | stat: -rw-r--r-- 4,906 bytes parent folder | download | duplicates (3)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* Unicorn Emulator Engine */
/* By Loi Anh Tuan, 2015 */

/* Sample code to demonstrate how to emulate m68k code */

#include <unicorn/unicorn.h>
#include <string.h>

// code to be emulated
#define M68K_CODE "\x76\xed" // movq #-19, %d3

// memory address where emulation starts
#define ADDRESS 0x10000

static void hook_block(uc_engine *uc, uint64_t address, uint32_t size,
                       void *user_data)
{
    printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n",
           address, size);
}

static void hook_code(uc_engine *uc, uint64_t address, uint32_t size,
                      void *user_data)
{
    printf(">>> Tracing instruction at 0x%" PRIx64
           ", instruction size = 0x%x\n",
           address, size);
}

static void test_m68k(void)
{
    uc_engine *uc;
    uc_hook trace1, trace2;
    uc_err err;

    int d0 = 0x0000; // d0 data register
    int d1 = 0x0000; // d1 data register
    int d2 = 0x0000; // d2 data register
    int d3 = 0x0000; // d3 data register
    int d4 = 0x0000; // d4 data register
    int d5 = 0x0000; // d5 data register
    int d6 = 0x0000; // d6 data register
    int d7 = 0x0000; // d7 data register

    int a0 = 0x0000; // a0 address register
    int a1 = 0x0000; // a1 address register
    int a2 = 0x0000; // a2 address register
    int a3 = 0x0000; // a3 address register
    int a4 = 0x0000; // a4 address register
    int a5 = 0x0000; // a5 address register
    int a6 = 0x0000; // a6 address register
    int a7 = 0x0000; // a6 address register

    int pc = 0x0000; // program counter
    int sr = 0x0000; // status register

    printf("Emulate M68K code\n");

    // Initialize emulator in M68K mode
    err = uc_open(UC_ARCH_M68K, UC_MODE_BIG_ENDIAN, &uc);
    if (err) {
        printf("Failed on uc_open() with error returned: %u (%s)\n", err,
               uc_strerror(err));
        return;
    }

    // map 2MB memory for this emulation
    uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);

    // write machine code to be emulated to memory
    uc_mem_write(uc, ADDRESS, M68K_CODE, sizeof(M68K_CODE) - 1);

    // initialize machine registers
    uc_reg_write(uc, UC_M68K_REG_D0, &d0);
    uc_reg_write(uc, UC_M68K_REG_D1, &d1);
    uc_reg_write(uc, UC_M68K_REG_D2, &d2);
    uc_reg_write(uc, UC_M68K_REG_D3, &d3);
    uc_reg_write(uc, UC_M68K_REG_D4, &d4);
    uc_reg_write(uc, UC_M68K_REG_D5, &d5);
    uc_reg_write(uc, UC_M68K_REG_D6, &d6);
    uc_reg_write(uc, UC_M68K_REG_D7, &d7);

    uc_reg_write(uc, UC_M68K_REG_A0, &a0);
    uc_reg_write(uc, UC_M68K_REG_A1, &a1);
    uc_reg_write(uc, UC_M68K_REG_A2, &a2);
    uc_reg_write(uc, UC_M68K_REG_A3, &a3);
    uc_reg_write(uc, UC_M68K_REG_A4, &a4);
    uc_reg_write(uc, UC_M68K_REG_A5, &a5);
    uc_reg_write(uc, UC_M68K_REG_A6, &a6);
    uc_reg_write(uc, UC_M68K_REG_A7, &a7);

    uc_reg_write(uc, UC_M68K_REG_PC, &pc);
    uc_reg_write(uc, UC_M68K_REG_SR, &sr);

    // tracing all basic blocks with customized callback
    uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0);

    // tracing all instruction
    uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0);

    // emulate machine code in infinite time (last param = 0), or when
    // finishing all the code.
    err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(M68K_CODE) - 1, 0, 0);
    if (err) {
        printf("Failed on uc_emu_start() with error returned: %u\n", err);
    }

    // now print out some registers
    printf(">>> Emulation done. Below is the CPU context\n");

    uc_reg_read(uc, UC_M68K_REG_D0, &d0);
    uc_reg_read(uc, UC_M68K_REG_D1, &d1);
    uc_reg_read(uc, UC_M68K_REG_D2, &d2);
    uc_reg_read(uc, UC_M68K_REG_D3, &d3);
    uc_reg_read(uc, UC_M68K_REG_D4, &d4);
    uc_reg_read(uc, UC_M68K_REG_D5, &d5);
    uc_reg_read(uc, UC_M68K_REG_D6, &d6);
    uc_reg_read(uc, UC_M68K_REG_D7, &d7);

    uc_reg_read(uc, UC_M68K_REG_A0, &a0);
    uc_reg_read(uc, UC_M68K_REG_A1, &a1);
    uc_reg_read(uc, UC_M68K_REG_A2, &a2);
    uc_reg_read(uc, UC_M68K_REG_A3, &a3);
    uc_reg_read(uc, UC_M68K_REG_A4, &a4);
    uc_reg_read(uc, UC_M68K_REG_A5, &a5);
    uc_reg_read(uc, UC_M68K_REG_A6, &a6);
    uc_reg_read(uc, UC_M68K_REG_A7, &a7);

    uc_reg_read(uc, UC_M68K_REG_PC, &pc);
    uc_reg_read(uc, UC_M68K_REG_SR, &sr);

    printf(">>> A0 = 0x%x\t\t>>> D0 = 0x%x\n", a0, d0);
    printf(">>> A1 = 0x%x\t\t>>> D1 = 0x%x\n", a1, d1);
    printf(">>> A2 = 0x%x\t\t>>> D2 = 0x%x\n", a2, d2);
    printf(">>> A3 = 0x%x\t\t>>> D3 = 0x%x\n", a3, d3);
    printf(">>> A4 = 0x%x\t\t>>> D4 = 0x%x\n", a4, d4);
    printf(">>> A5 = 0x%x\t\t>>> D5 = 0x%x\n", a5, d5);
    printf(">>> A6 = 0x%x\t\t>>> D6 = 0x%x\n", a6, d6);
    printf(">>> A7 = 0x%x\t\t>>> D7 = 0x%x\n", a7, d7);
    printf(">>> PC = 0x%x\n", pc);
    printf(">>> SR = 0x%x\n", sr);

    uc_close(uc);
}

int main(int argc, char **argv, char **envp)
{
    test_m68k();

    return 0;
}