debug_engine.c 37 KB

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