debug_engine.c 35 KB

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