debug_engine.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166
  1. /*
  2. * Copyright (C) 2021 Ant Group. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "debug_engine.h"
  6. #include "gdbserver.h"
  7. #include "handler.h"
  8. #include "bh_platform.h"
  9. #include "wasm_interp.h"
  10. #include "wasm_opcode.h"
  11. #include "wasm_runtime.h"
  12. static uint8 break_instr[] = { DEBUG_OP_BREAK };
  13. typedef struct WASMDebugEngine {
  14. struct WASMDebugEngine *next;
  15. WASMDebugControlThread *control_thread;
  16. char ip_addr[128];
  17. int32 platform_port;
  18. int32 process_base_port;
  19. bh_list debug_instance_list;
  20. korp_mutex instance_list_lock;
  21. bool active;
  22. } WASMDebugEngine;
  23. static WASMDebugEngine *g_debug_engine;
  24. static uint32 current_instance_id = 1;
  25. static uint32
  26. allocate_instance_id()
  27. {
  28. uint32 id;
  29. bh_assert(g_debug_engine);
  30. os_mutex_lock(&g_debug_engine->instance_list_lock);
  31. id = current_instance_id++;
  32. os_mutex_unlock(&g_debug_engine->instance_list_lock);
  33. return id;
  34. }
  35. static bool
  36. should_stop(WASMDebugControlThread *control_thread)
  37. {
  38. return control_thread->status != RUNNING;
  39. }
  40. static void *
  41. control_thread_routine(void *arg)
  42. {
  43. WASMDebugInstance *debug_inst = (WASMDebugInstance *)arg;
  44. WASMDebugControlThread *control_thread = NULL;
  45. control_thread = debug_inst->control_thread;
  46. bh_assert(control_thread);
  47. os_mutex_lock(&debug_inst->wait_lock);
  48. control_thread->status = RUNNING;
  49. debug_inst->id = allocate_instance_id();
  50. control_thread->debug_engine = g_debug_engine;
  51. control_thread->debug_instance = debug_inst;
  52. bh_strcpy_s(control_thread->ip_addr, sizeof(control_thread->ip_addr),
  53. g_debug_engine->ip_addr);
  54. control_thread->port =
  55. (g_debug_engine->process_base_port == 0)
  56. ? 0
  57. : g_debug_engine->process_base_port + debug_inst->id;
  58. LOG_WARNING("control thread of debug object %p start\n", debug_inst);
  59. control_thread->server =
  60. wasm_create_gdbserver(control_thread->ip_addr, &control_thread->port);
  61. if (!control_thread->server) {
  62. LOG_ERROR("Failed to create debug server\n");
  63. os_cond_signal(&debug_inst->wait_cond);
  64. os_mutex_unlock(&debug_inst->wait_lock);
  65. return NULL;
  66. }
  67. control_thread->server->thread = control_thread;
  68. /*
  69. * wasm gdbserver created, the execution thread
  70. * doesn't need to wait for the debugger connection,
  71. * so we wake up the execution thread before listen
  72. */
  73. os_cond_signal(&debug_inst->wait_cond);
  74. os_mutex_unlock(&debug_inst->wait_lock);
  75. /* wait lldb client to connect */
  76. if (!wasm_gdbserver_listen(control_thread->server)) {
  77. LOG_ERROR("Failed while connecting debugger\n");
  78. wasm_runtime_free(control_thread->server);
  79. return NULL;
  80. }
  81. while (true) {
  82. os_mutex_lock(&control_thread->wait_lock);
  83. if (!should_stop(control_thread)) {
  84. if (!wasm_gdbserver_handle_packet(control_thread->server)) {
  85. control_thread->status = STOPPED;
  86. }
  87. }
  88. else {
  89. os_mutex_unlock(&control_thread->wait_lock);
  90. break;
  91. }
  92. os_mutex_unlock(&control_thread->wait_lock);
  93. }
  94. LOG_VERBOSE("control thread of debug object [%p] stopped\n", debug_inst);
  95. return NULL;
  96. }
  97. static WASMDebugControlThread *
  98. wasm_debug_control_thread_create(WASMDebugInstance *debug_instance)
  99. {
  100. WASMDebugControlThread *control_thread;
  101. if (!(control_thread =
  102. wasm_runtime_malloc(sizeof(WASMDebugControlThread)))) {
  103. LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
  104. return NULL;
  105. }
  106. memset(control_thread, 0, sizeof(WASMDebugControlThread));
  107. if (os_mutex_init(&control_thread->wait_lock) != 0)
  108. goto fail;
  109. debug_instance->control_thread = control_thread;
  110. os_mutex_lock(&debug_instance->wait_lock);
  111. if (0
  112. != os_thread_create(&control_thread->tid, control_thread_routine,
  113. debug_instance, APP_THREAD_STACK_SIZE_MAX)) {
  114. os_mutex_unlock(&debug_instance->wait_lock);
  115. goto fail1;
  116. }
  117. /* wait until the debug control thread ready */
  118. os_cond_wait(&debug_instance->wait_cond, &debug_instance->wait_lock);
  119. os_mutex_unlock(&debug_instance->wait_lock);
  120. if (!control_thread->server)
  121. goto fail1;
  122. os_mutex_lock(&g_debug_engine->instance_list_lock);
  123. /* create control thread success, append debug instance to debug engine */
  124. bh_list_insert(&g_debug_engine->debug_instance_list, debug_instance);
  125. os_mutex_unlock(&g_debug_engine->instance_list_lock);
  126. wasm_cluster_send_signal_all(debug_instance->cluster, WAMR_SIG_STOP);
  127. return control_thread;
  128. fail1:
  129. os_mutex_destroy(&control_thread->wait_lock);
  130. fail:
  131. wasm_runtime_free(control_thread);
  132. return NULL;
  133. }
  134. static void
  135. wasm_debug_control_thread_destroy(WASMDebugInstance *debug_instance)
  136. {
  137. WASMDebugControlThread *control_thread = debug_instance->control_thread;
  138. LOG_VERBOSE("stopping control thread of debug object [%p]\n",
  139. debug_instance);
  140. control_thread->status = STOPPED;
  141. os_mutex_lock(&control_thread->wait_lock);
  142. wasm_close_gdbserver(control_thread->server);
  143. os_mutex_unlock(&control_thread->wait_lock);
  144. os_thread_join(control_thread->tid, NULL);
  145. wasm_runtime_free(control_thread->server);
  146. os_mutex_destroy(&control_thread->wait_lock);
  147. wasm_runtime_free(control_thread);
  148. }
  149. static WASMDebugEngine *
  150. wasm_debug_engine_create()
  151. {
  152. WASMDebugEngine *engine;
  153. if (!(engine = wasm_runtime_malloc(sizeof(WASMDebugEngine)))) {
  154. LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
  155. return NULL;
  156. }
  157. memset(engine, 0, sizeof(WASMDebugEngine));
  158. if (os_mutex_init(&engine->instance_list_lock) != 0) {
  159. wasm_runtime_free(engine);
  160. LOG_ERROR("WASM Debug Engine error: failed to init mutex");
  161. return NULL;
  162. }
  163. /* reset current instance id */
  164. current_instance_id = 1;
  165. /* TODO: support Wasm platform in LLDB */
  166. /*
  167. engine->control_thread =
  168. wasm_debug_control_thread_create((WASMDebugObject *)engine);
  169. engine->control_thread->debug_engine = (WASMDebugObject *)engine;
  170. engine->control_thread->debug_instance = NULL;
  171. sprintf(engine->control_thread->ip_addr, "127.0.0.1");
  172. engine->control_thread->port = 1234;
  173. */
  174. bh_list_init(&engine->debug_instance_list);
  175. return engine;
  176. }
  177. void
  178. wasm_debug_engine_destroy()
  179. {
  180. if (g_debug_engine) {
  181. wasm_debug_handler_deinit();
  182. os_mutex_destroy(&g_debug_engine->instance_list_lock);
  183. wasm_runtime_free(g_debug_engine);
  184. g_debug_engine = NULL;
  185. }
  186. }
  187. bool
  188. wasm_debug_engine_init(char *ip_addr, int32 platform_port, int32 process_port)
  189. {
  190. if (wasm_debug_handler_init() != 0) {
  191. return false;
  192. }
  193. if (g_debug_engine == NULL) {
  194. g_debug_engine = wasm_debug_engine_create();
  195. }
  196. if (g_debug_engine) {
  197. process_port -= 1;
  198. g_debug_engine->platform_port =
  199. platform_port > 0 ? platform_port : 1234;
  200. g_debug_engine->process_base_port =
  201. (process_port > 0) ? process_port : 0;
  202. if (ip_addr)
  203. snprintf(g_debug_engine->ip_addr, sizeof(g_debug_engine->ip_addr),
  204. "%s", ip_addr);
  205. else
  206. snprintf(g_debug_engine->ip_addr, sizeof(g_debug_engine->ip_addr),
  207. "%s", "127.0.0.1");
  208. g_debug_engine->active = true;
  209. }
  210. else {
  211. wasm_debug_handler_deinit();
  212. }
  213. return g_debug_engine != NULL ? true : false;
  214. }
  215. void
  216. wasm_debug_set_engine_active(bool active)
  217. {
  218. if (g_debug_engine) {
  219. g_debug_engine->active = active;
  220. }
  221. }
  222. bool
  223. wasm_debug_get_engine_active(void)
  224. {
  225. if (g_debug_engine) {
  226. return g_debug_engine->active;
  227. }
  228. return false;
  229. }
  230. /* A debug Instance is a debug "process" in gdb remote protocol
  231. and bound to a runtime cluster */
  232. WASMDebugInstance *
  233. wasm_debug_instance_create(WASMCluster *cluster)
  234. {
  235. WASMDebugInstance *instance;
  236. WASMExecEnv *exec_env;
  237. if (!g_debug_engine || !g_debug_engine->active) {
  238. return NULL;
  239. }
  240. if (!(instance = wasm_runtime_malloc(sizeof(WASMDebugInstance)))) {
  241. LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
  242. return NULL;
  243. }
  244. memset(instance, 0, sizeof(WASMDebugInstance));
  245. if (os_mutex_init(&instance->wait_lock) != 0) {
  246. goto fail1;
  247. }
  248. if (os_cond_init(&instance->wait_cond) != 0) {
  249. goto fail2;
  250. }
  251. bh_list_init(&instance->break_point_list);
  252. instance->cluster = cluster;
  253. exec_env = bh_list_first_elem(&cluster->exec_env_list);
  254. bh_assert(exec_env);
  255. instance->current_tid = exec_env->handle;
  256. if (!wasm_debug_control_thread_create(instance)) {
  257. LOG_ERROR("WASM Debug Engine error: failed to create control thread");
  258. wasm_runtime_free(instance);
  259. goto fail3;
  260. }
  261. wasm_cluster_set_debug_inst(cluster, instance);
  262. return instance;
  263. fail3:
  264. os_cond_destroy(&instance->wait_cond);
  265. fail2:
  266. os_mutex_destroy(&instance->wait_lock);
  267. fail1:
  268. wasm_runtime_free(instance);
  269. return NULL;
  270. }
  271. static void
  272. wasm_debug_instance_destroy_breakpoints(WASMDebugInstance *instance)
  273. {
  274. WASMDebugBreakPoint *breakpoint, *next_bp;
  275. breakpoint = bh_list_first_elem(&instance->break_point_list);
  276. while (breakpoint) {
  277. next_bp = bh_list_elem_next(breakpoint);
  278. bh_list_remove(&instance->break_point_list, breakpoint);
  279. wasm_runtime_free(breakpoint);
  280. breakpoint = next_bp;
  281. }
  282. }
  283. void
  284. wasm_debug_instance_destroy(WASMCluster *cluster)
  285. {
  286. WASMDebugInstance *instance = NULL;
  287. if (!g_debug_engine) {
  288. return;
  289. }
  290. instance = cluster->debug_inst;
  291. if (instance) {
  292. /* destroy control thread */
  293. wasm_debug_control_thread_destroy(instance);
  294. os_mutex_lock(&g_debug_engine->instance_list_lock);
  295. bh_list_remove(&g_debug_engine->debug_instance_list, instance);
  296. os_mutex_unlock(&g_debug_engine->instance_list_lock);
  297. /* destroy all breakpoints */
  298. wasm_debug_instance_destroy_breakpoints(instance);
  299. os_mutex_destroy(&instance->wait_lock);
  300. os_cond_destroy(&instance->wait_cond);
  301. wasm_runtime_free(instance);
  302. cluster->debug_inst = NULL;
  303. }
  304. }
  305. static WASMExecEnv *
  306. wasm_debug_instance_get_current_env(WASMDebugInstance *instance)
  307. {
  308. WASMExecEnv *exec_env = NULL;
  309. if (instance) {
  310. exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
  311. while (exec_env) {
  312. if (exec_env->handle == instance->current_tid)
  313. break;
  314. exec_env = bh_list_elem_next(exec_env);
  315. }
  316. }
  317. return exec_env;
  318. }
  319. #if WASM_ENABLE_LIBC_WASI != 0
  320. bool
  321. wasm_debug_instance_get_current_object_name(WASMDebugInstance *instance,
  322. char name_buffer[], uint32 len)
  323. {
  324. WASMExecEnv *exec_env;
  325. WASIArguments *wasi_args;
  326. WASMModuleInstance *module_inst;
  327. if (!instance)
  328. return false;
  329. exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
  330. if (!exec_env)
  331. return false;
  332. module_inst = (WASMModuleInstance *)exec_env->module_inst;
  333. wasi_args = &module_inst->module->wasi_args;
  334. if (wasi_args && wasi_args->argc > 0) {
  335. char *argv_name = wasi_args->argv[0];
  336. uint32 name_len = (uint32)strlen(argv_name);
  337. printf("the module name is %s\n", argv_name);
  338. if (len - 1 >= name_len)
  339. bh_strcpy_s(name_buffer, len, argv_name);
  340. else
  341. bh_strcpy_s(name_buffer, len, argv_name + (name_len + 1 - len));
  342. return true;
  343. }
  344. return false;
  345. }
  346. #endif
  347. uint64
  348. wasm_debug_instance_get_pid(WASMDebugInstance *instance)
  349. {
  350. if (instance != NULL) {
  351. return (uint64)instance->id;
  352. }
  353. return (uint64)0;
  354. }
  355. korp_tid
  356. wasm_debug_instance_get_tid(WASMDebugInstance *instance)
  357. {
  358. if (instance != NULL) {
  359. return instance->current_tid;
  360. }
  361. return (korp_tid)(uintptr_t)0;
  362. }
  363. uint32
  364. wasm_debug_instance_get_tids(WASMDebugInstance *instance, korp_tid tids[],
  365. uint32 len)
  366. {
  367. WASMExecEnv *exec_env;
  368. uint32 i = 0, threads_num = 0;
  369. if (!instance)
  370. return 0;
  371. exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
  372. while (exec_env && i < len) {
  373. /* Some threads may not be ready */
  374. if (exec_env->handle != 0) {
  375. tids[i++] = exec_env->handle;
  376. threads_num++;
  377. }
  378. exec_env = bh_list_elem_next(exec_env);
  379. }
  380. LOG_VERBOSE("find %d tids\n", threads_num);
  381. return threads_num;
  382. }
  383. static WASMExecEnv *
  384. get_stopped_thread(WASMCluster *cluster)
  385. {
  386. WASMExecEnv *exec_env;
  387. exec_env = bh_list_first_elem(&cluster->exec_env_list);
  388. while (exec_env) {
  389. if (exec_env->current_status->running_status != STATUS_RUNNING) {
  390. return exec_env;
  391. }
  392. exec_env = bh_list_elem_next(exec_env);
  393. }
  394. return NULL;
  395. }
  396. korp_tid
  397. wasm_debug_instance_wait_thread(WASMDebugInstance *instance, korp_tid tid,
  398. uint32 *status)
  399. {
  400. WASMExecEnv *exec_env = NULL;
  401. os_mutex_lock(&instance->wait_lock);
  402. while ((instance->cluster->exec_env_list.len != 0)
  403. && ((exec_env = get_stopped_thread(instance->cluster)) == NULL)) {
  404. os_cond_wait(&instance->wait_cond, &instance->wait_lock);
  405. }
  406. os_mutex_unlock(&instance->wait_lock);
  407. /* If cluster has no exec_env, then this whole cluster is exiting */
  408. if (instance->cluster->exec_env_list.len == 0) {
  409. *status = 0;
  410. return 0;
  411. }
  412. instance->current_tid = exec_env->handle;
  413. *status = (uint32)exec_env->current_status->signal_flag;
  414. return exec_env->handle;
  415. }
  416. uint32
  417. wasm_debug_instance_get_thread_status(WASMDebugInstance *instance, korp_tid tid)
  418. {
  419. WASMExecEnv *exec_env = NULL;
  420. exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
  421. while (exec_env) {
  422. if (exec_env->handle == tid) {
  423. return (uint32)exec_env->current_status->signal_flag;
  424. }
  425. exec_env = bh_list_elem_next(exec_env);
  426. }
  427. return 0;
  428. }
  429. void
  430. wasm_debug_instance_set_cur_thread(WASMDebugInstance *instance, korp_tid tid)
  431. {
  432. instance->current_tid = tid;
  433. }
  434. uint64
  435. wasm_debug_instance_get_pc(WASMDebugInstance *instance)
  436. {
  437. WASMExecEnv *exec_env;
  438. if (!instance)
  439. return 0;
  440. exec_env = wasm_debug_instance_get_current_env(instance);
  441. if ((exec_env->cur_frame != NULL) && (exec_env->cur_frame->ip != NULL)) {
  442. WASMModuleInstance *module_inst =
  443. (WASMModuleInstance *)exec_env->module_inst;
  444. return WASM_ADDR(
  445. WasmObj, instance->id,
  446. (exec_env->cur_frame->ip - module_inst->module->load_addr));
  447. }
  448. return 0;
  449. }
  450. uint64
  451. wasm_debug_instance_get_load_addr(WASMDebugInstance *instance)
  452. {
  453. WASMExecEnv *exec_env;
  454. if (!instance)
  455. return WASM_ADDR(WasmInvalid, 0, 0);
  456. exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
  457. if (exec_env) {
  458. return WASM_ADDR(WasmObj, instance->id, 0);
  459. }
  460. return WASM_ADDR(WasmInvalid, 0, 0);
  461. }
  462. WASMDebugMemoryInfo *
  463. wasm_debug_instance_get_memregion(WASMDebugInstance *instance, uint64 addr)
  464. {
  465. WASMDebugMemoryInfo *mem_info;
  466. WASMExecEnv *exec_env;
  467. WASMModuleInstance *module_inst;
  468. WASMMemoryInstance *memory;
  469. uint32 num_bytes_per_page;
  470. uint32 linear_mem_size = 0;
  471. if (!instance)
  472. return NULL;
  473. exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
  474. if (!exec_env)
  475. return NULL;
  476. if (!(mem_info = wasm_runtime_malloc(sizeof(WASMDebugMemoryInfo)))) {
  477. LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
  478. return NULL;
  479. }
  480. memset(mem_info, 0, sizeof(WASMDebugMemoryInfo));
  481. mem_info->start = WASM_ADDR(WasmInvalid, 0, 0);
  482. mem_info->size = 0;
  483. mem_info->name[0] = '\0';
  484. mem_info->permisson[0] = '\0';
  485. module_inst = (WASMModuleInstance *)exec_env->module_inst;
  486. switch (WASM_ADDR_TYPE(addr)) {
  487. case WasmObj:
  488. if (WASM_ADDR_OFFSET(addr) < module_inst->module->load_size) {
  489. mem_info->start = WASM_ADDR(WasmObj, instance->id, 0);
  490. mem_info->size = module_inst->module->load_size;
  491. snprintf(mem_info->name, sizeof(mem_info->name), "%s",
  492. "module");
  493. snprintf(mem_info->permisson, sizeof(mem_info->permisson), "%s",
  494. "rx");
  495. }
  496. break;
  497. case WasmMemory:
  498. {
  499. memory = module_inst->default_memory;
  500. if (memory) {
  501. num_bytes_per_page = memory->num_bytes_per_page;
  502. linear_mem_size = num_bytes_per_page * memory->cur_page_count;
  503. }
  504. if (WASM_ADDR_OFFSET(addr) < linear_mem_size) {
  505. mem_info->start = WASM_ADDR(WasmMemory, instance->id, 0);
  506. mem_info->size = linear_mem_size;
  507. snprintf(mem_info->name, sizeof(mem_info->name), "%s",
  508. "memory");
  509. snprintf(mem_info->permisson, sizeof(mem_info->permisson), "%s",
  510. "rw");
  511. }
  512. break;
  513. }
  514. default:
  515. mem_info->start = WASM_ADDR(WasmInvalid, 0, 0);
  516. mem_info->size = 0;
  517. }
  518. return mem_info;
  519. }
  520. void
  521. wasm_debug_instance_destroy_memregion(WASMDebugInstance *instance,
  522. WASMDebugMemoryInfo *mem_info)
  523. {
  524. wasm_runtime_free(mem_info);
  525. }
  526. bool
  527. wasm_debug_instance_get_obj_mem(WASMDebugInstance *instance, uint64 offset,
  528. char *buf, uint64 *size)
  529. {
  530. WASMExecEnv *exec_env;
  531. WASMModuleInstance *module_inst;
  532. WASMDebugBreakPoint *breakpoint;
  533. WASMFastOPCodeNode *fast_opcode;
  534. if (!instance)
  535. return false;
  536. exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
  537. if (!exec_env)
  538. return false;
  539. module_inst = (WASMModuleInstance *)exec_env->module_inst;
  540. if (offset + *size > module_inst->module->load_size) {
  541. LOG_VERBOSE("wasm_debug_instance_get_data_mem size over flow!\n");
  542. *size = module_inst->module->load_size >= offset
  543. ? module_inst->module->load_size - offset
  544. : 0;
  545. }
  546. bh_memcpy_s(buf, (uint32)*size, module_inst->module->load_addr + offset,
  547. (uint32)*size);
  548. breakpoint = bh_list_first_elem(&instance->break_point_list);
  549. while (breakpoint) {
  550. if (offset <= breakpoint->addr && breakpoint->addr < offset + *size) {
  551. bh_memcpy_s(buf + (breakpoint->addr - offset), sizeof(break_instr),
  552. &breakpoint->orignal_data, sizeof(break_instr));
  553. }
  554. breakpoint = bh_list_elem_next(breakpoint);
  555. }
  556. fast_opcode = bh_list_first_elem(&module_inst->module->fast_opcode_list);
  557. while (fast_opcode) {
  558. if (offset <= fast_opcode->offset
  559. && fast_opcode->offset < offset + *size) {
  560. *(uint8 *)(buf + (fast_opcode->offset - offset)) =
  561. fast_opcode->orig_op;
  562. }
  563. fast_opcode = bh_list_elem_next(fast_opcode);
  564. }
  565. return true;
  566. }
  567. bool
  568. wasm_debug_instance_get_linear_mem(WASMDebugInstance *instance, uint64 offset,
  569. char *buf, uint64 *size)
  570. {
  571. WASMExecEnv *exec_env;
  572. WASMModuleInstance *module_inst;
  573. WASMMemoryInstance *memory;
  574. uint32 num_bytes_per_page;
  575. uint32 linear_mem_size;
  576. if (!instance)
  577. return false;
  578. exec_env = wasm_debug_instance_get_current_env(instance);
  579. if (!exec_env)
  580. return false;
  581. module_inst = (WASMModuleInstance *)exec_env->module_inst;
  582. memory = module_inst->default_memory;
  583. if (memory) {
  584. num_bytes_per_page = memory->num_bytes_per_page;
  585. linear_mem_size = num_bytes_per_page * memory->cur_page_count;
  586. if (offset + *size > linear_mem_size) {
  587. LOG_VERBOSE("wasm_debug_instance_get_linear_mem size over flow!\n");
  588. *size = linear_mem_size >= offset ? linear_mem_size - offset : 0;
  589. }
  590. bh_memcpy_s(buf, (uint32)*size, memory->memory_data + offset,
  591. (uint32)*size);
  592. return true;
  593. }
  594. return false;
  595. }
  596. bool
  597. wasm_debug_instance_set_linear_mem(WASMDebugInstance *instance, uint64 offset,
  598. char *buf, uint64 *size)
  599. {
  600. WASMExecEnv *exec_env;
  601. WASMModuleInstance *module_inst;
  602. WASMMemoryInstance *memory;
  603. uint32 num_bytes_per_page;
  604. uint32 linear_mem_size;
  605. if (!instance)
  606. return false;
  607. exec_env = wasm_debug_instance_get_current_env(instance);
  608. if (!exec_env)
  609. return false;
  610. module_inst = (WASMModuleInstance *)exec_env->module_inst;
  611. memory = module_inst->default_memory;
  612. if (memory) {
  613. num_bytes_per_page = memory->num_bytes_per_page;
  614. linear_mem_size = num_bytes_per_page * memory->cur_page_count;
  615. if (offset + *size > linear_mem_size) {
  616. LOG_VERBOSE("wasm_debug_instance_get_linear_mem size over flow!\n");
  617. *size = linear_mem_size >= offset ? linear_mem_size - offset : 0;
  618. }
  619. bh_memcpy_s(memory->memory_data + offset, (uint32)*size, buf,
  620. (uint32)*size);
  621. return true;
  622. }
  623. return false;
  624. }
  625. bool
  626. wasm_debug_instance_get_mem(WASMDebugInstance *instance, uint64 addr, char *buf,
  627. uint64 *size)
  628. {
  629. switch (WASM_ADDR_TYPE(addr)) {
  630. case WasmMemory:
  631. return wasm_debug_instance_get_linear_mem(
  632. instance, WASM_ADDR_OFFSET(addr), buf, size);
  633. break;
  634. case WasmObj:
  635. return wasm_debug_instance_get_obj_mem(
  636. instance, WASM_ADDR_OFFSET(addr), buf, size);
  637. break;
  638. default:
  639. return false;
  640. }
  641. }
  642. bool
  643. wasm_debug_instance_set_mem(WASMDebugInstance *instance, uint64 addr, char *buf,
  644. uint64 *size)
  645. {
  646. switch (WASM_ADDR_TYPE(addr)) {
  647. case WasmMemory:
  648. return wasm_debug_instance_set_linear_mem(
  649. instance, WASM_ADDR_OFFSET(addr), buf, size);
  650. break;
  651. case WasmObj:
  652. default:
  653. return false;
  654. }
  655. }
  656. WASMDebugInstance *
  657. wasm_exec_env_get_instance(WASMExecEnv *exec_env)
  658. {
  659. WASMDebugInstance *instance = NULL;
  660. bh_assert(g_debug_engine);
  661. os_mutex_lock(&g_debug_engine->instance_list_lock);
  662. instance = bh_list_first_elem(&g_debug_engine->debug_instance_list);
  663. while (instance) {
  664. if (instance->cluster == exec_env->cluster)
  665. break;
  666. instance = bh_list_elem_next(instance);
  667. }
  668. os_mutex_unlock(&g_debug_engine->instance_list_lock);
  669. return instance;
  670. }
  671. uint32
  672. wasm_debug_instance_get_call_stack_pcs(WASMDebugInstance *instance,
  673. korp_tid tid, uint64 buf[], uint64 size)
  674. {
  675. WASMExecEnv *exec_env;
  676. struct WASMInterpFrame *frame;
  677. uint32 i = 0;
  678. if (!instance)
  679. return 0;
  680. exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
  681. while (exec_env) {
  682. if (exec_env->handle == tid) {
  683. WASMModuleInstance *module_inst =
  684. (WASMModuleInstance *)exec_env->module_inst;
  685. frame = exec_env->cur_frame;
  686. while (frame && i < size) {
  687. if (frame->ip != NULL) {
  688. buf[i++] =
  689. WASM_ADDR(WasmObj, instance->id,
  690. (frame->ip - module_inst->module->load_addr));
  691. }
  692. frame = frame->prev_frame;
  693. }
  694. return i;
  695. }
  696. exec_env = bh_list_elem_next(exec_env);
  697. }
  698. return 0;
  699. }
  700. bool
  701. wasm_debug_instance_add_breakpoint(WASMDebugInstance *instance, uint64 addr,
  702. uint64 length)
  703. {
  704. WASMExecEnv *exec_env;
  705. WASMModuleInstance *module_inst;
  706. uint64 offset;
  707. if (!instance)
  708. return false;
  709. exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
  710. if (!exec_env)
  711. return false;
  712. module_inst = (WASMModuleInstance *)exec_env->module_inst;
  713. if (WASM_ADDR_TYPE(addr) != WasmObj)
  714. return false;
  715. offset = WASM_ADDR_OFFSET(addr);
  716. if (length >= sizeof(break_instr)) {
  717. if (offset + sizeof(break_instr) <= module_inst->module->load_size) {
  718. WASMDebugBreakPoint *breakpoint;
  719. if (!(breakpoint =
  720. wasm_runtime_malloc(sizeof(WASMDebugBreakPoint)))) {
  721. LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
  722. return false;
  723. }
  724. memset(breakpoint, 0, sizeof(WASMDebugBreakPoint));
  725. breakpoint->addr = offset;
  726. /* TODO: how to if more than one breakpoints are set
  727. at the same addr? */
  728. bh_memcpy_s(&breakpoint->orignal_data, (uint32)sizeof(break_instr),
  729. module_inst->module->load_addr + offset,
  730. (uint32)sizeof(break_instr));
  731. bh_memcpy_s(module_inst->module->load_addr + offset,
  732. (uint32)sizeof(break_instr), break_instr,
  733. (uint32)sizeof(break_instr));
  734. bh_list_insert(&instance->break_point_list, breakpoint);
  735. return true;
  736. }
  737. }
  738. return false;
  739. }
  740. bool
  741. wasm_debug_instance_remove_breakpoint(WASMDebugInstance *instance, uint64 addr,
  742. uint64 length)
  743. {
  744. WASMExecEnv *exec_env;
  745. WASMModuleInstance *module_inst;
  746. uint64 offset;
  747. if (!instance)
  748. return false;
  749. exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
  750. if (!exec_env)
  751. return false;
  752. module_inst = (WASMModuleInstance *)exec_env->module_inst;
  753. if (WASM_ADDR_TYPE(addr) != WasmObj)
  754. return false;
  755. offset = WASM_ADDR_OFFSET(addr);
  756. if (length >= sizeof(break_instr)) {
  757. if (offset + sizeof(break_instr) <= module_inst->module->load_size) {
  758. WASMDebugBreakPoint *breakpoint =
  759. bh_list_first_elem(&instance->break_point_list);
  760. while (breakpoint) {
  761. WASMDebugBreakPoint *next_break = bh_list_elem_next(breakpoint);
  762. if (breakpoint->addr == offset) {
  763. /* TODO: how to if more than one breakpoints are set
  764. at the same addr? */
  765. bh_memcpy_s(module_inst->module->load_addr + offset,
  766. (uint32)sizeof(break_instr),
  767. &breakpoint->orignal_data,
  768. (uint32)sizeof(break_instr));
  769. bh_list_remove(&instance->break_point_list, breakpoint);
  770. wasm_runtime_free(breakpoint);
  771. }
  772. breakpoint = next_break;
  773. }
  774. }
  775. }
  776. return true;
  777. }
  778. bool
  779. wasm_debug_instance_continue(WASMDebugInstance *instance)
  780. {
  781. WASMExecEnv *exec_env;
  782. if (!instance)
  783. return false;
  784. exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
  785. if (!exec_env)
  786. return false;
  787. while (exec_env) {
  788. wasm_cluster_thread_continue(exec_env);
  789. exec_env = bh_list_elem_next(exec_env);
  790. }
  791. return true;
  792. }
  793. bool
  794. wasm_debug_instance_kill(WASMDebugInstance *instance)
  795. {
  796. WASMExecEnv *exec_env;
  797. if (!instance)
  798. return false;
  799. exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
  800. if (!exec_env)
  801. return false;
  802. while (exec_env) {
  803. wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM);
  804. exec_env = bh_list_elem_next(exec_env);
  805. }
  806. return true;
  807. }
  808. bool
  809. wasm_debug_instance_singlestep(WASMDebugInstance *instance, korp_tid tid)
  810. {
  811. WASMExecEnv *exec_env;
  812. if (!instance)
  813. return false;
  814. exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
  815. if (!exec_env)
  816. return false;
  817. while (exec_env) {
  818. if (exec_env->handle == tid || tid == (korp_tid)(uintptr_t)~0LL) {
  819. wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_SINGSTEP);
  820. wasm_cluster_thread_step(exec_env);
  821. }
  822. exec_env = bh_list_elem_next(exec_env);
  823. }
  824. return true;
  825. }
  826. bool
  827. wasm_debug_instance_get_local(WASMDebugInstance *instance, int32 frame_index,
  828. int32 local_index, char buf[], int32 *size)
  829. {
  830. WASMExecEnv *exec_env;
  831. struct WASMInterpFrame *frame;
  832. WASMFunctionInstance *cur_func;
  833. uint8 local_type = 0xFF;
  834. uint32 local_offset;
  835. int32 param_count;
  836. int32 fi = 0;
  837. if (!instance)
  838. return false;
  839. exec_env = wasm_debug_instance_get_current_env(instance);
  840. if (!exec_env)
  841. return false;
  842. frame = exec_env->cur_frame;
  843. while (frame && fi++ != frame_index) {
  844. frame = frame->prev_frame;
  845. }
  846. if (!frame)
  847. return false;
  848. cur_func = frame->function;
  849. if (!cur_func)
  850. return false;
  851. param_count = cur_func->param_count;
  852. if (local_index >= param_count + cur_func->local_count)
  853. return false;
  854. local_offset = cur_func->local_offsets[local_index];
  855. if (local_index < param_count)
  856. local_type = cur_func->param_types[local_index];
  857. else if (local_index < cur_func->local_count + param_count)
  858. local_type = cur_func->local_types[local_index - param_count];
  859. switch (local_type) {
  860. case VALUE_TYPE_I32:
  861. case VALUE_TYPE_F32:
  862. *size = 4;
  863. bh_memcpy_s(buf, 4, (char *)(frame->lp + local_offset), 4);
  864. break;
  865. case VALUE_TYPE_I64:
  866. case VALUE_TYPE_F64:
  867. *size = 8;
  868. bh_memcpy_s(buf, 8, (char *)(frame->lp + local_offset), 8);
  869. break;
  870. default:
  871. *size = 0;
  872. break;
  873. }
  874. return true;
  875. }
  876. bool
  877. wasm_debug_instance_get_global(WASMDebugInstance *instance, int32 frame_index,
  878. int32 global_index, char buf[], int32 *size)
  879. {
  880. WASMExecEnv *exec_env;
  881. struct WASMInterpFrame *frame;
  882. WASMModuleInstance *module_inst;
  883. WASMGlobalInstance *globals, *global;
  884. uint8 *global_addr;
  885. uint8 global_type = 0xFF;
  886. uint8 *global_data;
  887. int32 fi = 0;
  888. if (!instance)
  889. return false;
  890. exec_env = wasm_debug_instance_get_current_env(instance);
  891. if (!exec_env)
  892. return false;
  893. frame = exec_env->cur_frame;
  894. while (frame && fi++ != frame_index) {
  895. frame = frame->prev_frame;
  896. }
  897. if (!frame)
  898. return false;
  899. module_inst = (WASMModuleInstance *)exec_env->module_inst;
  900. global_data = module_inst->global_data;
  901. globals = module_inst->globals;
  902. if ((global_index < 0)
  903. || ((uint32)global_index >= module_inst->global_count)) {
  904. return false;
  905. }
  906. global = globals + global_index;
  907. #if WASM_ENABLE_MULTI_MODULE == 0
  908. global_addr = global_data + global->data_offset;
  909. #else
  910. global_addr = global->import_global_inst
  911. ? global->import_module_inst->global_data
  912. + global->import_global_inst->data_offset
  913. : global_data + global->data_offset;
  914. #endif
  915. global_type = global->type;
  916. switch (global_type) {
  917. case VALUE_TYPE_I32:
  918. case VALUE_TYPE_F32:
  919. *size = 4;
  920. bh_memcpy_s(buf, 4, (char *)(global_addr), 4);
  921. break;
  922. case VALUE_TYPE_I64:
  923. case VALUE_TYPE_F64:
  924. *size = 8;
  925. bh_memcpy_s(buf, 8, (char *)(global_addr), 8);
  926. break;
  927. default:
  928. *size = 0;
  929. break;
  930. }
  931. return true;
  932. }
  933. uint64
  934. wasm_debug_instance_mmap(WASMDebugInstance *instance, uint32 size,
  935. int32 map_port)
  936. {
  937. WASMExecEnv *exec_env;
  938. WASMModuleInstance *module_inst;
  939. uint32 offset;
  940. void *native_addr;
  941. (void)map_port;
  942. if (!instance)
  943. return 0;
  944. exec_env = wasm_debug_instance_get_current_env(instance);
  945. if (!exec_env)
  946. return 0;
  947. module_inst = (WASMModuleInstance *)exec_env->module_inst;
  948. /* TODO: malloc in wasi libc maybe not be thread safe, we hope LLDB will
  949. always ask for memory when threads stopped */
  950. offset = wasm_runtime_module_malloc((wasm_module_inst_t)module_inst, size,
  951. &native_addr);
  952. if (!offset)
  953. LOG_WARNING("the memory may be not enough for debug, try use larger "
  954. "--heap-size");
  955. return WASM_ADDR(WasmMemory, 0, offset);
  956. }
  957. bool
  958. wasm_debug_instance_ummap(WASMDebugInstance *instance, uint64 addr)
  959. {
  960. WASMExecEnv *exec_env;
  961. WASMModuleInstance *module_inst;
  962. uint32 offset;
  963. if (!instance)
  964. return false;
  965. exec_env = wasm_debug_instance_get_current_env(instance);
  966. if (!exec_env)
  967. return false;
  968. module_inst = (WASMModuleInstance *)exec_env->module_inst;
  969. if (WASM_ADDR_TYPE(addr) == WasmMemory) {
  970. offset = WASM_ADDR_OFFSET(addr);
  971. wasm_runtime_module_free((wasm_module_inst_t)module_inst, offset);
  972. return true;
  973. }
  974. return false;
  975. }