Skip to content

Commit eda30d6

Browse files
committed
Add memory watchpoint support
1 parent be7a4ab commit eda30d6

File tree

4 files changed

+268
-24
lines changed

4 files changed

+268
-24
lines changed

core/iwasm/interpreter/wasm_interp_classic.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,31 @@ typedef float64 CellType_F64;
7070
goto unaligned_atomic; \
7171
} while (0)
7272

73+
#if WASM_ENABLE_DEBUG_INTERP != 0
74+
#define TRIGGER_WATCHPOINT_SIGTRAP() \
75+
wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP); \
76+
CHECK_SUSPEND_FLAGS();
77+
78+
#define CHECK_WATCHPOINT(list, current_addr) \
79+
WASMDebugWatchPoint *watchpoint = bh_list_first_elem(list); \
80+
while (watchpoint) { \
81+
WASMDebugWatchPoint *next = bh_list_elem_next(watchpoint); \
82+
if (watchpoint->addr <= current_addr \
83+
&& watchpoint->addr + watchpoint->length > current_addr) { \
84+
TRIGGER_WATCHPOINT_SIGTRAP() \
85+
} \
86+
watchpoint = next; \
87+
}
88+
89+
#define CHECK_READ_WATCHPOINT(addr, offset) \
90+
CHECK_WATCHPOINT(watch_point_list_read, WASM_ADDR_OFFSET(addr + offset))
91+
#define CHECK_WRITE_WATCHPOINT(addr, offset) \
92+
CHECK_WATCHPOINT(watch_point_list_write, WASM_ADDR_OFFSET(addr + offset))
93+
#else
94+
#define CHECK_READ_WATCHPOINT(addr, offset)
95+
#define CHECK_WRITE_WATCHPOINT(addr, offset)
96+
#endif
97+
7398
static inline uint32
7499
rotl32(uint32 n, uint32 c)
75100
{
@@ -1120,6 +1145,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
11201145

11211146
#if WASM_ENABLE_DEBUG_INTERP != 0
11221147
uint8 *frame_ip_orig = NULL;
1148+
WASMDebugInstance *debug_instance = wasm_exec_env_get_instance(exec_env);
1149+
bh_list *watch_point_list_read = &debug_instance->watch_point_list_read;
1150+
bh_list *watch_point_list_write = &debug_instance->watch_point_list_write;
11231151
#endif
11241152

11251153
#if WASM_ENABLE_LABELS_AS_VALUES != 0
@@ -1786,6 +1814,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
17861814
CHECK_MEMORY_OVERFLOW(4);
17871815
PUSH_I32(LOAD_I32(maddr));
17881816
(void)flags;
1817+
CHECK_READ_WATCHPOINT(addr, offset);
17891818
HANDLE_OP_END();
17901819
}
17911820

@@ -1800,6 +1829,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
18001829
CHECK_MEMORY_OVERFLOW(8);
18011830
PUSH_I64(LOAD_I64(maddr));
18021831
(void)flags;
1832+
CHECK_READ_WATCHPOINT(addr, offset);
18031833
HANDLE_OP_END();
18041834
}
18051835

@@ -1813,6 +1843,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
18131843
CHECK_MEMORY_OVERFLOW(1);
18141844
PUSH_I32(sign_ext_8_32(*(int8 *)maddr));
18151845
(void)flags;
1846+
CHECK_READ_WATCHPOINT(addr, offset);
18161847
HANDLE_OP_END();
18171848
}
18181849

@@ -1826,6 +1857,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
18261857
CHECK_MEMORY_OVERFLOW(1);
18271858
PUSH_I32((uint32)(*(uint8 *)maddr));
18281859
(void)flags;
1860+
CHECK_READ_WATCHPOINT(addr, offset);
18291861
HANDLE_OP_END();
18301862
}
18311863

@@ -1839,6 +1871,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
18391871
CHECK_MEMORY_OVERFLOW(2);
18401872
PUSH_I32(sign_ext_16_32(LOAD_I16(maddr)));
18411873
(void)flags;
1874+
CHECK_READ_WATCHPOINT(addr, offset);
18421875
HANDLE_OP_END();
18431876
}
18441877

@@ -1852,6 +1885,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
18521885
CHECK_MEMORY_OVERFLOW(2);
18531886
PUSH_I32((uint32)(LOAD_U16(maddr)));
18541887
(void)flags;
1888+
CHECK_READ_WATCHPOINT(addr, offset);
18551889
HANDLE_OP_END();
18561890
}
18571891

@@ -1865,6 +1899,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
18651899
CHECK_MEMORY_OVERFLOW(1);
18661900
PUSH_I64(sign_ext_8_64(*(int8 *)maddr));
18671901
(void)flags;
1902+
CHECK_READ_WATCHPOINT(addr, offset);
18681903
HANDLE_OP_END();
18691904
}
18701905

@@ -1878,6 +1913,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
18781913
CHECK_MEMORY_OVERFLOW(1);
18791914
PUSH_I64((uint64)(*(uint8 *)maddr));
18801915
(void)flags;
1916+
CHECK_READ_WATCHPOINT(addr, offset);
18811917
HANDLE_OP_END();
18821918
}
18831919

@@ -1891,6 +1927,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
18911927
CHECK_MEMORY_OVERFLOW(2);
18921928
PUSH_I64(sign_ext_16_64(LOAD_I16(maddr)));
18931929
(void)flags;
1930+
CHECK_READ_WATCHPOINT(addr, offset);
18941931
HANDLE_OP_END();
18951932
}
18961933

@@ -1904,6 +1941,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
19041941
CHECK_MEMORY_OVERFLOW(2);
19051942
PUSH_I64((uint64)(LOAD_U16(maddr)));
19061943
(void)flags;
1944+
CHECK_READ_WATCHPOINT(addr, offset);
19071945
HANDLE_OP_END();
19081946
}
19091947

@@ -1918,6 +1956,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
19181956
CHECK_MEMORY_OVERFLOW(4);
19191957
PUSH_I64(sign_ext_32_64(LOAD_I32(maddr)));
19201958
(void)flags;
1959+
CHECK_READ_WATCHPOINT(addr, offset);
19211960
HANDLE_OP_END();
19221961
}
19231962

@@ -1931,6 +1970,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
19311970
CHECK_MEMORY_OVERFLOW(4);
19321971
PUSH_I64((uint64)(LOAD_U32(maddr)));
19331972
(void)flags;
1973+
CHECK_READ_WATCHPOINT(addr, offset);
19341974
HANDLE_OP_END();
19351975
}
19361976

@@ -1947,6 +1987,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
19471987
CHECK_MEMORY_OVERFLOW(4);
19481988
STORE_U32(maddr, frame_sp[1]);
19491989
(void)flags;
1990+
CHECK_WRITE_WATCHPOINT(addr, offset);
19501991
HANDLE_OP_END();
19511992
}
19521993

@@ -1963,6 +2004,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
19632004
PUT_I64_TO_ADDR((uint32 *)maddr,
19642005
GET_I64_FROM_ADDR(frame_sp + 1));
19652006
(void)flags;
2007+
CHECK_WRITE_WATCHPOINT(addr, offset);
19662008
HANDLE_OP_END();
19672009
}
19682010

@@ -1988,6 +2030,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
19882030
}
19892031

19902032
(void)flags;
2033+
CHECK_WRITE_WATCHPOINT(addr, offset);
19912034
HANDLE_OP_END();
19922035
}
19932036

@@ -2017,6 +2060,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
20172060
STORE_U32(maddr, (uint32)sval);
20182061
}
20192062
(void)flags;
2063+
CHECK_WRITE_WATCHPOINT(addr, offset);
20202064
HANDLE_OP_END();
20212065
}
20222066

core/iwasm/libraries/debug-engine/debug_engine.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,8 @@ wasm_debug_instance_create(WASMCluster *cluster, int32 port)
392392
}
393393

394394
bh_list_init(&instance->break_point_list);
395+
bh_list_init(&instance->watch_point_list_read);
396+
bh_list_init(&instance->watch_point_list_write);
395397

396398
instance->cluster = cluster;
397399
exec_env = bh_list_first_elem(&cluster->exec_env_list);
@@ -452,6 +454,23 @@ wasm_debug_instance_destroy_breakpoints(WASMDebugInstance *instance)
452454
}
453455
}
454456

457+
static void
458+
wasm_debug_instance_destroy_watchpoints(WASMDebugInstance *instance,
459+
bh_list *watchpoints)
460+
{
461+
WASMDebugWatchPoint *watchpoint, *next;
462+
463+
watchpoint = bh_list_first_elem(watchpoints);
464+
while (watchpoint) {
465+
next = bh_list_elem_next(watchpoint);
466+
467+
bh_list_remove(watchpoints, watchpoint);
468+
wasm_runtime_free(watchpoint);
469+
470+
watchpoint = next;
471+
}
472+
}
473+
455474
void
456475
wasm_debug_instance_destroy(WASMCluster *cluster)
457476
{
@@ -472,6 +491,10 @@ wasm_debug_instance_destroy(WASMCluster *cluster)
472491

473492
/* destroy all breakpoints */
474493
wasm_debug_instance_destroy_breakpoints(instance);
494+
wasm_debug_instance_destroy_watchpoints(
495+
instance, &instance->watch_point_list_read);
496+
wasm_debug_instance_destroy_watchpoints(
497+
instance, &instance->watch_point_list_write);
475498

476499
os_mutex_destroy(&instance->wait_lock);
477500
os_cond_destroy(&instance->wait_cond);
@@ -995,6 +1018,65 @@ wasm_debug_instance_remove_breakpoint(WASMDebugInstance *instance, uint64 addr,
9951018
return true;
9961019
}
9971020

1021+
static bool
1022+
add_watchpoint(bh_list *list, uint64 addr, uint64 length)
1023+
{
1024+
WASMDebugWatchPoint *watchpoint;
1025+
if (!(watchpoint = wasm_runtime_malloc(sizeof(WASMDebugWatchPoint)))) {
1026+
LOG_ERROR("WASM Debug Engine error: failed to allocate memory for "
1027+
"watchpoint");
1028+
return false;
1029+
}
1030+
memset(watchpoint, 0, sizeof(WASMDebugWatchPoint));
1031+
watchpoint->addr = addr;
1032+
watchpoint->length = length;
1033+
bh_list_insert(list, watchpoint);
1034+
return true;
1035+
}
1036+
1037+
static bool
1038+
remove_watchpoint(bh_list *list, uint64 addr, uint64 length)
1039+
{
1040+
WASMDebugWatchPoint *watchpoint = bh_list_first_elem(list);
1041+
while (watchpoint) {
1042+
WASMDebugWatchPoint *next = bh_list_elem_next(watchpoint);
1043+
if (watchpoint->addr == addr && watchpoint->length == length) {
1044+
bh_list_remove(list, watchpoint);
1045+
wasm_runtime_free(watchpoint);
1046+
}
1047+
watchpoint = next;
1048+
}
1049+
return true;
1050+
}
1051+
1052+
bool
1053+
wasm_debug_instance_watchpoint_write_add(WASMDebugInstance *instance,
1054+
uint64 addr, uint64 length)
1055+
{
1056+
return add_watchpoint(&instance->watch_point_list_write, addr, length);
1057+
}
1058+
1059+
bool
1060+
wasm_debug_instance_watchpoint_write_remove(WASMDebugInstance *instance,
1061+
uint64 addr, uint64 length)
1062+
{
1063+
return remove_watchpoint(&instance->watch_point_list_write, addr, length);
1064+
}
1065+
1066+
bool
1067+
wasm_debug_instance_watchpoint_read_add(WASMDebugInstance *instance,
1068+
uint64 addr, uint64 length)
1069+
{
1070+
return add_watchpoint(&instance->watch_point_list_read, addr, length);
1071+
}
1072+
1073+
bool
1074+
wasm_debug_instance_watchpoint_read_remove(WASMDebugInstance *instance,
1075+
uint64 addr, uint64 length)
1076+
{
1077+
return remove_watchpoint(&instance->watch_point_list_read, addr, length);
1078+
}
1079+
9981080
bool
9991081
wasm_debug_instance_on_failure(WASMDebugInstance *instance)
10001082
{

core/iwasm/libraries/debug-engine/debug_engine.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ typedef struct WASMDebugBreakPoint {
3636
uint64 orignal_data;
3737
} WASMDebugBreakPoint;
3838

39+
typedef struct WASMDebugWatchPoint {
40+
struct WASMDebugWatchPoint *next;
41+
uint64 addr;
42+
uint64 length;
43+
} WASMDebugWatchPoint;
44+
3945
typedef enum debug_state_t {
4046
/* Debugger state conversion sequence:
4147
* DBG_LAUNCHING ---> APP_STOPPED <---> APP_RUNNING
@@ -56,6 +62,8 @@ struct WASMDebugInstance {
5662
struct WASMDebugInstance *next;
5763
WASMDebugControlThread *control_thread;
5864
bh_list break_point_list;
65+
bh_list watch_point_list_read;
66+
bh_list watch_point_list_write;
5967
WASMCluster *cluster;
6068
uint32 id;
6169
korp_tid current_tid;
@@ -184,6 +192,22 @@ bool
184192
wasm_debug_instance_remove_breakpoint(WASMDebugInstance *instance, uint64 addr,
185193
uint64 length);
186194

195+
bool
196+
wasm_debug_instance_watchpoint_write_add(WASMDebugInstance *instance,
197+
uint64 addr, uint64 length);
198+
199+
bool
200+
wasm_debug_instance_watchpoint_write_remove(WASMDebugInstance *instance,
201+
uint64 addr, uint64 length);
202+
203+
bool
204+
wasm_debug_instance_watchpoint_read_add(WASMDebugInstance *instance,
205+
uint64 addr, uint64 length);
206+
207+
bool
208+
wasm_debug_instance_watchpoint_read_remove(WASMDebugInstance *instance,
209+
uint64 addr, uint64 length);
210+
187211
bool
188212
wasm_debug_instance_on_failure(WASMDebugInstance *instance);
189213

0 commit comments

Comments
 (0)