debug_engine.c 30 KB

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