debug_engine.c 29 KB

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