-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathucc.cc
More file actions
191 lines (161 loc) · 5.59 KB
/
ucc.cc
File metadata and controls
191 lines (161 loc) · 5.59 KB
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
By JayWaves <jay.waves@qq.com>, 2025
Class for Uc Engine
*/
#include "ucc.h"
void ucc_hook::uninstall(ucc* uc) {
if (hh_) {
uc_hook_del(uc->c_ptr(), hh_);
hh_ = 0;
}
}
static const char* hook_type_to_str(int type) {
switch (type) {
case UC_HOOK_CODE: return "CODE";
case UC_HOOK_MEM_INVALID: return "MEM_INVALID";
case UC_HOOK_MEM_READ: return "MEM_READ";
case UC_HOOK_MEM_WRITE: return "MEM_WRITE";
case UC_HOOK_TLB_FILL: return "TLB_FILL";
case UC_HOOK_INTR: return "INTR";
case UC_HOOK_EDGE_GENERATED: return "EDGE_GEN";
default: return "UNKNOWN";
};
}
void ucc_hook::hook_add(ucc* uc, int type, void* cb, void *self,
uint64_t begin, uint64_t end) {
uc_err err =
uc_hook_add(uc->c_ptr(), &hh_, type, cb, self, begin, end);
if (err != UC_ERR_OK)
throw ucc_error("uc_hook_add failed", err);
LOG_INFO("Hook added: type={}", hook_type_to_str(type));
}
uint64_t ucc_mmio::mmio_r_cb_c(uc_engine *uc, uint64_t o, unsigned s, void *ud) {
auto* self = (ucc_mmio*) ud;
if (self && self->r_cb_) {
uint64_t val = 0;
self->r_cb_(o, s, &val);
return val;
}
return 0;
}
void ucc_mmio::mmio_w_cb_c(uc_engine *uc, uint64_t o, unsigned s, uint64_t v, void *ud) {
auto* self = (ucc_mmio*) ud;
if (self && self->w_cb_) {
self->w_cb_(o, s, &v);
}
}
void ucc_mmio::uninstall(ucc* uc) {
uc_err err =
uc_mmio_map(uc->c_ptr(), addr_, sz_, nullptr, nullptr, nullptr, nullptr);
if (err != UC_ERR_OK)
throw ucc_error("uc_mmio_map failed", err);
};
void ucc_mmio::install(ucc* uc) {
uc_err err =
uc_mmio_map(uc->c_ptr(), addr_, sz_, &mmio_r_cb_c, this, &mmio_w_cb_c, this);
if (err != UC_ERR_OK)
throw ucc_error("uc_mmio_map failed", err);
LOG_INFO("MMIO Map: addr=0x{:016x}, size=0x{:x}", addr_, sz_);
};
void ucc::mem_write(uint64_t address, const void *data, uint64_t size) {
uc_err err = uc_mem_write(uc_, address, data, size);
if (err != UC_ERR_OK) throw ucc_error(err);
}
void ucc::mem_read(uint64_t address, void *data, uint64_t size) {
uc_err err = uc_mem_read(uc_, address, data, size);
if (err != UC_ERR_OK) throw ucc_error(err);
}
void ucc::reg_write(int regid, const void *value) {
uc_err err = uc_reg_write(uc_, regid, value);
if (err != UC_ERR_OK) throw ucc_error(err);
}
void ucc::reg_read(int regid, void *value) {
uc_err err = uc_reg_read(uc_, regid, value);
if (err != UC_ERR_OK) throw ucc_error(err);
}
// 阻塞执行
void ucc::emu_start(uint64_t begin, uint64_t timeout, size_t count) {
if (!cas_running())
throw std::runtime_error("Emulation already running");
uc_err err = uc_emu_start(uc_, begin, 0, timeout, count);
running_.store(false);
if (err != UC_ERR_OK)
throw ucc_error(err);
}
// 后台持续运行
void ucc::emu_start_async(uint64_t begin) {
if (!cas_running()) {
throw std::runtime_error("Emulation already running");
}
LOG_INFO("Emulation started in background thread.");
runner_ = std::jthread([=, this](std::stop_token st) {
uint64_t pc = begin;
while (!st.stop_requested()) {
// 将 emu 分为 100ms 的时间片
uc_err err = uc_emu_start(uc_, pc, 0, 100, 0);
if (err != UC_ERR_OK) {
LOG_ERROR("uc_error in emu_start thread: {}", uc_strerror(err));
break;
}
// 更新 PC
uc_reg_read(uc_, UC_SPARC_REG_PC, &pc);
}
running_.store(false);
});
}
/*
在 CPU TB 块结束后, 异步触发中断请求.
*/
void ucc::raise_irq(int irq_num) {
ucc_raise_irq(uc_, irq_num);
}
void ucc::mem_map(uint64_t addr, uint64_t size, uint32_t perms) {
uc_err err = uc_mem_map(uc_, addr, size, perms);
if (err != UC_ERR_OK)
throw ucc_error(err);
LOG_INFO("Mem Map: addr=0x{:016x}, size=0x{:x}, perms=0x{:x}", addr, size, perms);
}
void ucc::emu_stop_async() {
if (runner_.joinable()) {
uc_emu_stop(uc_);
runner_.request_stop();
runner_.join();
}
}
/*
支持动态设置退出点
*/
void ucc::set_emu_exits(uint64_t* exits, size_t len) {
uc_ctl_set_exits(uc_, exits, len);
}
static const std::array<std::pair<int, const char*>, 37> regs = {{
{UC_SPARC_REG_G0, "g0"}, {UC_SPARC_REG_G1, "g1"},
{UC_SPARC_REG_G2, "g2"}, {UC_SPARC_REG_G3, "g3"},
{UC_SPARC_REG_G4, "g4"}, {UC_SPARC_REG_G5, "g5"},
{UC_SPARC_REG_G6, "g6"}, {UC_SPARC_REG_G7, "g7"},
{UC_SPARC_REG_O0, "o0"}, {UC_SPARC_REG_O1, "o1"},
{UC_SPARC_REG_O2, "o2"}, {UC_SPARC_REG_O3, "o3"},
{UC_SPARC_REG_O4, "o4"}, {UC_SPARC_REG_O5, "o5"},
{UC_SPARC_REG_O6, "o6"}, {UC_SPARC_REG_O7, "o7"},
{UC_SPARC_REG_L0, "l0"}, {UC_SPARC_REG_L1, "l1"},
{UC_SPARC_REG_L2, "l2"}, {UC_SPARC_REG_L3, "l3"},
{UC_SPARC_REG_L4, "l4"}, {UC_SPARC_REG_L5, "l5"},
{UC_SPARC_REG_L6, "l6"}, {UC_SPARC_REG_L7, "l7"},
{UC_SPARC_REG_I0, "i0"}, {UC_SPARC_REG_I1, "i1"},
{UC_SPARC_REG_I2, "i2"}, {UC_SPARC_REG_I3, "i3"},
{UC_SPARC_REG_I4, "i4"}, {UC_SPARC_REG_I5, "i5"},
{UC_SPARC_REG_I6, "i6"}, {UC_SPARC_REG_I7, "i7"},
{UC_SPARC_REG_PC, "pc"},
{UC_SPARC_REG_PSR, "psr"}, {UC_SPARC_REG_SP, "sp"},
{UC_SPARC_REG_TBR, "tbr"}, {UC_SPARC_REG_WIM, "wim"},
}};
void ucc::coredump() {
// uc_context *ctx;
// uc_context_alloc(uc_, &ctx);
// uc_context_save(uc_, ctx);
for (auto&[id, name] : regs) {
uint32_t val = 0;
uc_reg_read(uc_, id, &val);
LOG_INFO("{:>3} = 0x{:08x}", name, val);
}
}