debug_engine.c 31 KB

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