Explorar o código

Preserve execution memory for debug instance (#1072)

During debugging, the debug client may request to malloc a memory space
to evaluate the user expressions. If we malloc memory from the linear memory,
it may fail when the thread is in stop status. We preserve a buffer during
creating debug instance, and use a simple bump pointer allocator to serve lldb's
memory request.
Xu Jun %!s(int64=3) %!d(string=hai) anos
pai
achega
24afd4e7cb

+ 9 - 0
core/config.h

@@ -155,6 +155,15 @@
 #define WASM_ENABLE_DEBUG_INTERP 0
 #endif
 
+#if WASM_ENABLE_DEBUG_INTERP != 0
+#ifndef DEBUG_EXECUTION_MEMORY_SIZE
+/* 0x85000 is the size required by lldb, if this is changed to a smaller value,
+ * then the debugger will not be able to evaluate user expressions, other
+ * functionality such as breakpoint and stepping are not influenced by this */
+#define DEBUG_EXECUTION_MEMORY_SIZE 0x85000
+#endif
+#endif /* end of WASM_ENABLE_DEBUG_INTERP != 0 */
+
 #ifndef WASM_ENABLE_DEBUG_AOT
 #define WASM_ENABLE_DEBUG_AOT 0
 #endif

+ 43 - 18
core/iwasm/libraries/debug-engine/debug_engine.c

@@ -345,7 +345,8 @@ WASMDebugInstance *
 wasm_debug_instance_create(WASMCluster *cluster)
 {
     WASMDebugInstance *instance;
-    WASMExecEnv *exec_env;
+    WASMExecEnv *exec_env = NULL;
+    wasm_module_inst_t module_inst = NULL;
 
     if (!g_debug_engine || !g_debug_engine->active) {
         return NULL;
@@ -373,6 +374,24 @@ wasm_debug_instance_create(WASMCluster *cluster)
 
     instance->current_tid = exec_env->handle;
 
+    module_inst = wasm_runtime_get_module_inst(exec_env);
+    bh_assert(module_inst);
+
+    /* Allocate linear memory for evaluating expressions during debugging. If
+     * the allocation failed, the debugger will not be able to evaluate
+     * expressions */
+    instance->exec_mem_info.size = DEBUG_EXECUTION_MEMORY_SIZE;
+    instance->exec_mem_info.start_offset = wasm_runtime_module_malloc(
+        module_inst, instance->exec_mem_info.size, NULL);
+    if (instance->exec_mem_info.start_offset == 0) {
+        LOG_WARNING(
+            "WASM Debug Engine warning: failed to allocate linear memory for "
+            "execution. \n"
+            "Will not be able to evaluate expressions during "
+            "debugging");
+    }
+    instance->exec_mem_info.current_pos = instance->exec_mem_info.start_offset;
+
     if (!wasm_debug_control_thread_create(instance)) {
         LOG_ERROR("WASM Debug Engine error: failed to create control thread");
         goto fail3;
@@ -1182,9 +1201,7 @@ wasm_debug_instance_mmap(WASMDebugInstance *instance, uint32 size,
                          int32 map_port)
 {
     WASMExecEnv *exec_env;
-    WASMModuleInstance *module_inst;
-    uint32 offset;
-    void *native_addr;
+    uint32 offset = 0;
     (void)map_port;
 
     if (!instance)
@@ -1194,15 +1211,23 @@ wasm_debug_instance_mmap(WASMDebugInstance *instance, uint32 size,
     if (!exec_env)
         return 0;
 
-    module_inst = (WASMModuleInstance *)exec_env->module_inst;
+    if (instance->exec_mem_info.start_offset == 0) {
+        return 0;
+    }
 
-    /* TODO: malloc in wasi libc maybe not be thread safe, we hope LLDB will
-             always ask for memory when threads stopped */
-    offset = wasm_runtime_module_malloc((wasm_module_inst_t)module_inst, size,
-                                        &native_addr);
-    if (!offset)
+    if ((uint64)instance->exec_mem_info.current_pos
+            - instance->exec_mem_info.start_offset + size
+        <= (uint64)instance->exec_mem_info.size) {
+        offset = instance->exec_mem_info.current_pos;
+        instance->exec_mem_info.current_pos += size;
+    }
+
+    if (offset == 0) {
         LOG_WARNING("the memory may be not enough for debug, try use larger "
                     "--heap-size");
+        return 0;
+    }
+
     return WASM_ADDR(WasmMemory, 0, offset);
 }
 
@@ -1210,8 +1235,6 @@ bool
 wasm_debug_instance_ummap(WASMDebugInstance *instance, uint64 addr)
 {
     WASMExecEnv *exec_env;
-    WASMModuleInstance *module_inst;
-    uint32 offset;
 
     if (!instance)
         return false;
@@ -1220,11 +1243,13 @@ wasm_debug_instance_ummap(WASMDebugInstance *instance, uint64 addr)
     if (!exec_env)
         return false;
 
-    module_inst = (WASMModuleInstance *)exec_env->module_inst;
-    if (WASM_ADDR_TYPE(addr) == WasmMemory) {
-        offset = WASM_ADDR_OFFSET(addr);
-        wasm_runtime_module_free((wasm_module_inst_t)module_inst, offset);
-        return true;
+    if (instance->exec_mem_info.start_offset == 0) {
+        return false;
     }
-    return false;
+
+    (void)addr;
+
+    /* Currently we don't support to free the execution memory, simply return
+     * true here */
+    return true;
 }

+ 11 - 0
core/iwasm/libraries/debug-engine/debug_engine.h

@@ -44,6 +44,12 @@ typedef enum debug_state_t {
     APP_STOPPED
 } debug_state_t;
 
+typedef struct WASMDebugExecutionMemory {
+    uint32 start_offset;
+    uint32 size;
+    uint32 current_pos;
+} WASMDebugExecutionMemory;
+
 typedef struct WASMDebugInstance {
     struct WASMDebugInstance *next;
     WASMDebugControlThread *control_thread;
@@ -60,6 +66,11 @@ typedef struct WASMDebugInstance {
      * RUNNING when receiving STEP/CONTINUE commands, and set to
      * STOPPED when any thread stopped */
     volatile debug_state_t current_state;
+    /* Execution memory info. During debugging, the debug client may request to
+     * malloc a memory space to evaluate user expressions. We preserve a buffer
+     * during creating debug instance, and use a simple bump pointer allocator
+     * to serve lldb's memory request */
+    WASMDebugExecutionMemory exec_mem_info;
 } WASMDebugInstance;
 
 typedef enum WASMDebugEventKind {