ソースを参照

Support emit specified custom sections into AoT file (#1207)

And add API to get the content of custom section with
section name for both wasm file and aot file.
Xu Jun 3 年 前
コミット
77595c9560

+ 1 - 0
.github/workflows/compilation_on_android_ubuntu_macos.yml

@@ -214,6 +214,7 @@ jobs:
             "-DWAMR_BUILD_SIMD=1",
             "-DWAMR_BUILD_TAIL_CALL=1",
             "-DWAMR_DISABLE_HW_BOUND_CHECK=1",
+            "-DWAMR_BUILD_LOAD_CUSTOM_SECTION=1",
           ]
         os: [ubuntu-18.04, ubuntu-20.04, macos-latest]
         platform: [android, linux, darwin]

+ 5 - 4
.github/workflows/compilation_on_sgx.yml

@@ -139,6 +139,7 @@ jobs:
             # "-DWAMR_BUILD_SIMD=1",
             "-DWAMR_BUILD_TAIL_CALL=1",
             "-DWAMR_DISABLE_HW_BOUND_CHECK=1",
+            "-DWAMR_BUILD_LOAD_CUSTOM_SECTION=1",
           ]
         os: [ubuntu-20.04]
         platform: [linux-sgx]
@@ -160,7 +161,7 @@ jobs:
       - name: install SGX SDK and necessary libraries
         if: ${{ matrix.light == 'green' }}
         run: |
-          mkdir -p /opt/intel 
+          mkdir -p /opt/intel
           cd /opt/intel
           wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin
           chmod +x sgx_linux_x64_sdk_2.15.100.3.bin
@@ -256,7 +257,7 @@ jobs:
       - name: install SGX SDK and necessary libraries
         if: ${{ matrix.light == 'green' }}
         run: |
-          mkdir -p /opt/intel 
+          mkdir -p /opt/intel
           cd /opt/intel
           wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin
           chmod +x sgx_linux_x64_sdk_2.15.100.3.bin
@@ -347,7 +348,7 @@ jobs:
       - name: install SGX SDK and necessary libraries
         if: ${{ matrix.light == 'green' }}
         run: |
-          mkdir -p /opt/intel 
+          mkdir -p /opt/intel
           cd /opt/intel
           wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin
           chmod +x sgx_linux_x64_sdk_2.15.100.3.bin
@@ -444,7 +445,7 @@ jobs:
       - name: install SGX SDK and necessary libraries
         if: ${{ matrix.light == 'green' }}
         run: |
-          mkdir -p /opt/intel 
+          mkdir -p /opt/intel
           cd /opt/intel
           wget https://download.01.org/intel-sgx/sgx-linux/2.15/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.15.100.3.bin
           chmod +x sgx_linux_x64_sdk_2.15.100.3.bin

+ 4 - 0
build-scripts/config_common.cmake

@@ -257,3 +257,7 @@ endif ()
 if (WAMR_BUILD_DEBUG_AOT EQUAL 1)
     message ("     Debug AOT enabled")
 endif ()
+if (WAMR_BUILD_LOAD_CUSTOM_SECTION EQUAL 1)
+    add_definitions (-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1)
+    message ("     Load custom section enabled")
+endif ()

+ 5 - 0
core/config.h

@@ -168,6 +168,11 @@
 #define WASM_ENABLE_DEBUG_AOT 0
 #endif
 
+/* Custom sections */
+#ifndef WASM_ENABLE_LOAD_CUSTOM_SECTION
+#define WASM_ENABLE_LOAD_CUSTOM_SECTION 0
+#endif
+
 /* WASM log system */
 #ifndef WASM_ENABLE_LOG
 #define WASM_ENABLE_LOG 1

+ 59 - 0
core/iwasm/aot/aot_loader.c

@@ -12,8 +12,12 @@
 #include "../compilation/aot.h"
 #if WASM_ENABLE_JIT != 0
 #include "../compilation/aot_llvm.h"
+#endif
+
+#if (WASM_ENABLE_JIT != 0) || (WASM_ENABLE_LOAD_CUSTOM_SECTION != 0)
 #include "../interpreter/wasm_loader.h"
 #endif
+
 #if WASM_ENABLE_DEBUG_AOT != 0
 #include "debug/elf_parser.h"
 #include "debug/jit_debug.h"
@@ -674,6 +678,36 @@ load_custom_section(const uint8 *buf, const uint8 *buf_end, AOTModule *module,
                                    error_buf, error_buf_size))
                 goto fail;
             break;
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+        case AOT_CUSTOM_SECTION_RAW:
+        {
+            const char *section_name;
+            WASMCustomSection *section;
+
+            if (p >= p_end) {
+                set_error_buf(error_buf, error_buf_size, "unexpected end");
+                goto fail;
+            }
+
+            read_string(p, p_end, section_name);
+
+            section = loader_malloc(sizeof(WASMCustomSection), error_buf,
+                                    error_buf_size);
+            if (!section) {
+                goto fail;
+            }
+
+            section->name_addr = (char *)section_name;
+            section->name_len = strlen(section_name);
+            section->content_addr = (uint8 *)p;
+            section->content_len = p_end - p;
+
+            section->next = module->custom_section_list;
+            module->custom_section_list = section;
+            LOG_VERBOSE("Load custom section [%s] success.", section_name);
+            break;
+        }
+#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 */
         default:
             break;
     }
@@ -3261,6 +3295,10 @@ aot_unload(AOTModule *module)
     }
 #endif
 
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+    wasm_loader_destroy_custom_sections(module->custom_section_list);
+#endif
+
     wasm_runtime_free(module);
 }
 
@@ -3269,3 +3307,24 @@ aot_get_plt_table_size()
 {
     return get_plt_table_size();
 }
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+const uint8 *
+aot_get_custom_section(const AOTModule *module, const char *name, uint32 *len)
+{
+    WASMCustomSection *section = module->custom_section_list;
+
+    while (section) {
+        if (strcmp(section->name_addr, name) == 0) {
+            if (len) {
+                *len = section->content_len;
+            }
+            return section->content_addr;
+        }
+
+        section = section->next;
+    }
+
+    return NULL;
+}
+#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION */

+ 7 - 0
core/iwasm/aot/aot_runtime.h

@@ -50,6 +50,7 @@ typedef enum AOTSectionType {
 } AOTSectionType;
 
 typedef enum AOTCustomSectionType {
+    AOT_CUSTOM_SECTION_RAW = 0,
     AOT_CUSTOM_SECTION_NATIVE_SYMBOL = 1,
     AOT_CUSTOM_SECTION_ACCESS_CONTROL = 2,
     AOT_CUSTOM_SECTION_NAME = 3,
@@ -268,6 +269,9 @@ typedef struct AOTModule {
     uint32 *aux_func_indexes;
     uint32 aux_func_name_count;
 #endif
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+    WASMCustomSection *custom_section_list;
+#endif
 } AOTModule;
 
 typedef union {
@@ -733,6 +737,9 @@ aot_dump_call_stack(WASMExecEnv *exec_env);
 void
 aot_dump_perf_profiling(const AOTModuleInstance *module_inst);
 
+const uint8 *
+aot_get_custom_section(const AOTModule *module, const char *name, uint32 *len);
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

+ 18 - 0
core/iwasm/common/wasm_runtime_common.c

@@ -2843,6 +2843,24 @@ wasm_exec_env_get_module(WASMExecEnv *exec_env)
     return NULL;
 }
 
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+const uint8 *
+wasm_runtime_get_custom_section(WASMModuleCommon *const module_comm,
+                                const char *name, uint32 *len)
+{
+#if WASM_ENABLE_INTERP != 0
+    if (module_comm->module_type == Wasm_Module_Bytecode)
+        return wasm_loader_get_custom_section((WASMModule *)module_comm, name,
+                                              len);
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (module_comm->module_type == Wasm_Module_AoT)
+        return aot_get_custom_section((AOTModule *)module_comm, name, len);
+#endif
+    return NULL;
+}
+#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION != 0 */
+
 static union {
     int a;
     char b;

+ 5 - 0
core/iwasm/common/wasm_runtime_common.h

@@ -658,6 +658,11 @@ wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst,
                                    uint8 **p_native_start_addr,
                                    uint8 **p_native_end_addr);
 
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN const uint8 *
+wasm_runtime_get_custom_section(WASMModuleCommon *const module_comm,
+                                const char *name, uint32 *len);
+
 uint32
 wasm_runtime_get_temp_ret(WASMModuleInstanceCommon *module_inst);
 

+ 78 - 1
core/iwasm/compilation/aot_emit_aot_file.c

@@ -877,11 +877,15 @@ get_native_symbol_list_size(AOTCompContext *comp_ctx)
 static uint32
 get_name_section_size(AOTCompData *comp_data);
 
+static uint32
+get_custom_sections_size(AOTCompContext *comp_ctx, AOTCompData *comp_data);
+
 static uint32
 get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
                   AOTObjectData *obj_data)
 {
     uint32 size = 0;
+    uint32 size_custom_section = 0;
 
     /* aot file header */
     size += get_file_header_size();
@@ -939,6 +943,12 @@ get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
                      get_name_section_size(comp_data));
     }
 
+    size_custom_section = get_custom_sections_size(comp_ctx, comp_data);
+    if (size_custom_section > 0) {
+        size = align_uint(size, 4);
+        size += size_custom_section;
+    }
+
     return size;
 }
 
@@ -1274,6 +1284,36 @@ fail:
     return 0;
 }
 
+static uint32
+get_custom_sections_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
+{
+    uint32 size = 0, i;
+
+    for (i = 0; i < comp_ctx->custom_sections_count; i++) {
+        const char *section_name = comp_ctx->custom_sections_wp[i];
+        const uint8 *content = NULL;
+        uint32 length = 0;
+
+        content = wasm_loader_get_custom_section(comp_data->wasm_module,
+                                                 section_name, &length);
+        if (!content) {
+            LOG_WARNING("Can't find custom section [%s], ignore it",
+                        section_name);
+            continue;
+        }
+
+        size = align_uint(size, 4);
+        /* section id + section size + sub section id */
+        size += (uint32)sizeof(uint32) * 3;
+        /* section name and len */
+        size += get_string_size(comp_ctx, section_name);
+        /* section content */
+        size += length;
+    }
+
+    return size;
+}
+
 static bool
 aot_emit_file_header(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
                      AOTCompData *comp_data, AOTObjectData *obj_data)
@@ -1897,6 +1937,41 @@ aot_emit_name_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
     return true;
 }
 
+static bool
+aot_emit_custom_sections(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
+                         AOTCompData *comp_data, AOTCompContext *comp_ctx)
+{
+    uint32 offset = *p_offset, i;
+
+    for (i = 0; i < comp_ctx->custom_sections_count; i++) {
+        const char *section_name = comp_ctx->custom_sections_wp[i];
+        const uint8 *content = NULL;
+        uint32 length = 0;
+
+        content = wasm_loader_get_custom_section(comp_data->wasm_module,
+                                                 section_name, &length);
+        if (!content) {
+            /* Warning has been reported during calculating size */
+            continue;
+        }
+
+        offset = align_uint(offset, 4);
+        EMIT_U32(AOT_SECTION_TYPE_CUSTOM);
+        /* sub section id + content */
+        EMIT_U32(sizeof(uint32) * 1 + get_string_size(comp_ctx, section_name)
+                 + length);
+        EMIT_U32(AOT_CUSTOM_SECTION_RAW);
+        EMIT_STR(section_name);
+        bh_memcpy_s((uint8 *)(buf + offset), (uint32)(buf_end - buf), content,
+                    length);
+        offset += length;
+    }
+
+    *p_offset = offset;
+
+    return true;
+}
+
 typedef uint32 U32;
 typedef int32 I32;
 typedef uint16 U16;
@@ -2751,7 +2826,9 @@ aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data,
         || !aot_emit_relocation_section(buf, buf_end, &offset, comp_ctx,
                                         comp_data, obj_data)
         || !aot_emit_native_symbol(buf, buf_end, &offset, comp_ctx)
-        || !aot_emit_name_section(buf, buf_end, &offset, comp_data, comp_ctx))
+        || !aot_emit_name_section(buf, buf_end, &offset, comp_data, comp_ctx)
+        || !aot_emit_custom_sections(buf, buf_end, &offset, comp_data,
+                                     comp_ctx))
         goto fail2;
 
 #if 0

+ 3 - 0
core/iwasm/compilation/aot_llvm.c

@@ -1587,6 +1587,9 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
     comp_ctx->opt_level = option->opt_level;
     comp_ctx->size_level = option->size_level;
 
+    comp_ctx->custom_sections_wp = option->custom_sections;
+    comp_ctx->custom_sections_count = option->custom_sections_count;
+
     if (option->is_jit_mode) {
         char *triple_jit = NULL;
 

+ 4 - 0
core/iwasm/compilation/aot_llvm.h

@@ -348,6 +348,8 @@ typedef struct AOTCompContext {
     /* Function contexts */
     AOTFuncContext **func_ctxes;
     uint32 func_ctx_count;
+    char **custom_sections_wp;
+    uint32 custom_sections_count;
 } AOTCompContext;
 
 enum {
@@ -378,6 +380,8 @@ typedef struct AOTCompOption {
     uint32 size_level;
     uint32 output_format;
     uint32 bounds_checks;
+    char **custom_sections;
+    uint32 custom_sections_count;
 } AOTCompOption, *aot_comp_option_t;
 
 AOTCompContext *

+ 2 - 0
core/iwasm/include/aot_export.h

@@ -59,6 +59,8 @@ typedef struct AOTCompOption {
     uint32_t size_level;
     uint32_t output_format;
     uint32_t bounds_checks;
+    char **custom_sections;
+    uint32_t custom_sections_count;
 } AOTCompOption, *aot_comp_option_t;
 
 aot_comp_context_t

+ 14 - 0
core/iwasm/include/wasm_export.h

@@ -1053,6 +1053,20 @@ wasm_externref_retain(uint32_t externref_idx);
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_dump_call_stack(wasm_exec_env_t exec_env);
 
+/**
+ * Get a custom section by name
+ *
+ * @param module_comm the module to find
+ * @param name name of the custom section
+ * @param len return the length of the content if found
+ *
+ * @return Custom section content (not including the name length
+ *         and name string) if found, NULL otherwise
+ */
+WASM_RUNTIME_API_EXTERN const uint8_t *
+wasm_runtime_get_custom_section(wasm_module_t const module_comm,
+                                const char *name, uint32_t *len);
+
 /* clang-format on */
 
 #ifdef __cplusplus

+ 17 - 0
core/iwasm/interpreter/wasm.h

@@ -335,6 +335,19 @@ typedef struct WASMFastOPCodeNode {
 } WASMFastOPCodeNode;
 #endif
 
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+typedef struct WASMCustomSection {
+    struct WASMCustomSection *next;
+    /* Start address of the section name */
+    char *name_addr;
+    /* Length of the section name decoded from leb */
+    uint32 name_len;
+    /* Start address of the content (name len and name skipped) */
+    uint8 *content_addr;
+    uint32 content_len;
+} WASMCustomSection;
+#endif
+
 struct WASMModule {
     /* Module type, for module loaded from WASM bytecode binary,
        this field is Wasm_Module_Bytecode;
@@ -453,6 +466,10 @@ struct WASMModule {
     const uint8 *name_section_buf;
     const uint8 *name_section_buf_end;
 #endif
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+    WASMCustomSection *custom_section_list;
+#endif
 };
 
 typedef struct BlockType {

+ 78 - 2
core/iwasm/interpreter/wasm_loader.c

@@ -2811,7 +2811,8 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
                   uint32 error_buf_size)
 {
     const uint8 *p = buf, *p_end = buf_end;
-    uint32 name_len;
+    char section_name[32];
+    uint32 name_len, buffer_len;
 
     if (p >= p_end) {
         set_error_buf(error_buf, error_buf_size, "unexpected end");
@@ -2830,6 +2831,16 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
         return false;
     }
 
+    buffer_len = sizeof(section_name);
+    memset(section_name, 0, buffer_len);
+    if (name_len < buffer_len) {
+        bh_memcpy_s(section_name, buffer_len, p, name_len);
+    }
+    else {
+        bh_memcpy_s(section_name, buffer_len, p, buffer_len - 4);
+        memset(section_name + buffer_len - 4, '.', 3);
+    }
+
 #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
     if (memcmp(p, "name", 4) == 0) {
         module->name_section_buf = buf;
@@ -2837,9 +2848,34 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
         p += name_len;
         handle_name_section(p, p_end, module, is_load_from_file_buf, error_buf,
                             error_buf_size);
+        LOG_VERBOSE("Load custom name section success.");
+        return true;
     }
 #endif
-    LOG_VERBOSE("Load custom section success.\n");
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+    {
+        WASMCustomSection *section =
+            loader_malloc(sizeof(WASMCustomSection), error_buf, error_buf_size);
+
+        if (!section) {
+            return false;
+        }
+
+        section->name_addr = (char *)p;
+        section->name_len = name_len;
+        section->content_addr = (uint8 *)(p + name_len);
+        section->content_len = p_end - p - name_len;
+
+        section->next = module->custom_section_list;
+        module->custom_section_list = section;
+        LOG_VERBOSE("Load custom section [%s] success.", section_name);
+        return true;
+    }
+#endif
+
+    LOG_VERBOSE("Ignore custom section [%s].", section_name);
+
     return true;
 fail:
     return false;
@@ -3739,6 +3775,7 @@ wasm_loader_unload(WASMModule *module)
         }
     }
 #endif
+
 #if WASM_ENABLE_DEBUG_INTERP != 0
     WASMFastOPCodeNode *fast_opcode =
         bh_list_first_elem(&module->fast_opcode_list);
@@ -3749,6 +3786,11 @@ wasm_loader_unload(WASMModule *module)
     }
     os_mutex_destroy(&module->ref_count_lock);
 #endif
+
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+    wasm_loader_destroy_custom_sections(module->custom_section_list);
+#endif
+
     wasm_runtime_free(module);
 }
 
@@ -6440,6 +6482,40 @@ get_table_seg_elem_type(const WASMModule *module, uint32 table_seg_idx,
 }
 #endif
 
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+const uint8 *
+wasm_loader_get_custom_section(WASMModule *module, const char *name,
+                               uint32 *len)
+{
+    WASMCustomSection *section = module->custom_section_list;
+
+    while (section) {
+        if ((section->name_len == strlen(name))
+            && (memcmp(section->name_addr, name, section->name_len) == 0)) {
+            if (len) {
+                *len = section->content_len;
+            }
+            return section->content_addr;
+        }
+
+        section = section->next;
+    }
+
+    return false;
+}
+
+void
+wasm_loader_destroy_custom_sections(WASMCustomSection *section_list)
+{
+    WASMCustomSection *section = section_list, *next;
+    while (section) {
+        next = section->next;
+        wasm_runtime_free(section);
+        section = next;
+    }
+}
+#endif /* end of WASM_ENABLE_LOAD_CUSTOM_SECTION */
+
 static bool
 wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
                              uint32 cur_func_idx, char *error_buf,

+ 5 - 0
core/iwasm/interpreter/wasm_loader.h

@@ -73,6 +73,11 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
                             uint8 block_type, uint8 **p_else_addr,
                             uint8 **p_end_addr);
 
+#if WASM_ENABLE_LOAD_CUSTOM_SECTION != 0
+void
+wasm_loader_destroy_custom_sections(WASMCustomSection *section_list);
+#endif
+
 #ifdef __cplusplus
 }
 #endif

+ 4 - 0
core/iwasm/interpreter/wasm_runtime.h

@@ -436,6 +436,10 @@ void
 wasm_interp_dump_call_stack(struct WASMExecEnv *exec_env);
 #endif
 
+const uint8 *
+wasm_loader_get_custom_section(WASMModule *module, const char *name,
+                               uint32 *len);
+
 #ifdef __cplusplus
 }
 #endif

+ 11 - 2
doc/build_wamr.md

@@ -148,6 +148,15 @@ Currently we only profile the memory consumption of module, module_instance and
 - **WAMR_BUILD_DEBUG_INTERP**=1/0, default to 0 if not set
 > Note: There are some other setup required by source debugging, please refer to [source_debugging.md](./source_debugging.md) for more details.
 
+#### **Enable load wasm custom sections**
+- **WAMR_BUILD_LOAD_CUSTOM_SECTION**=1/0, default to disable if not set
+
+> Note: By default, the custom sections are ignored. If the embedder wants to get custom sections from `wasm_module_t`, then `WAMR_BUILD_LOAD_CUSTOM_SECTION` should be enabled, and then `wasm_runtime_get_custom_section` can be used to get a custom section by name.
+
+> Note: If `WAMR_BUILD_CUSTOM_NAME_SECTION` is enabled, then the `custom name section` will be treated as a special section and consumed by the runtime, not available to the embedder.
+
+> For AoT file, must use `--emit-custom-sections` to specify which sections need to be emitted into AoT file, otherwise all custom sections (except custom name section) will be ignored.
+
 **Combination of configurations:**
 
 We can combine the configurations. For example, if we want to disable interpreter, enable AOT and WASI, we can run command:
@@ -546,13 +555,13 @@ WAMR is intergrated with NuttX, just enable the WAMR in Kconfig option (Applicat
 
 ESP-IDF
 -------------------------
-WAMR integrates with ESP-IDF both for the XTENSA and RISC-V chips (esp32x and esp32c3 respectively). 
+WAMR integrates with ESP-IDF both for the XTENSA and RISC-V chips (esp32x and esp32c3 respectively).
 
 In order to use this, you need at least version 4.3.1 of ESP-IDF.
 If you don't have it installed, follow the instructions [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/#get-started-get-prerequisites).
 ESP-IDF also installs the toolchains needed for compiling WAMR and ESP-IDF.
 A small demonstration of how to use WAMR and ESP-IDF can be found under [product_mini](/product-mini/platforms/esp-idf).
-The demo builds WAMR for ESP-IDF and runs a small wasm program. 
+The demo builds WAMR for ESP-IDF and runs a small wasm program.
 In order to run it for your specific Espressif chip, edit the ['build_and_run.sh'](/product-mini/platforms/esp-idf/build_and_run.sh) file and put the correct toolchain file (see #Cross-compilation) and `IDF_TARGET`.
 Before compiling it is also necessary to call ESP-IDF's `export.sh` script to bring all compile time relevant information in scope.
 

+ 6 - 4
product-mini/platforms/posix/main.c

@@ -98,7 +98,7 @@ app_instance_func(wasm_module_inst_t module_inst, const char *func_name)
 static char **
 split_string(char *str, int *count)
 {
-    char **res = NULL;
+    char **res = NULL, **res1;
     char *p;
     int idx = 0;
 
@@ -106,16 +106,18 @@ split_string(char *str, int *count)
     do {
         p = strtok(str, " ");
         str = NULL;
-        res = (char **)realloc(res, sizeof(char *) * (uint32)(idx + 1));
+        res1 = res;
+        res = (char **)realloc(res1, sizeof(char *) * (uint32)(idx + 1));
         if (res == NULL) {
+            free(res1);
             return NULL;
         }
         res[idx++] = p;
     } while (p);
 
     /**
-     * since the function name,
-     * res[0] might be contains a '\' to indicate a space
+     * Due to the function name,
+     * res[0] might contain a '\' to indicate a space
      * func\name -> func name
      */
     p = strchr(res[0], '\\');

+ 6 - 4
product-mini/platforms/windows/main.c

@@ -84,7 +84,7 @@ app_instance_func(wasm_module_inst_t module_inst, const char *func_name)
 static char **
 split_string(char *str, int *count)
 {
-    char **res = NULL;
+    char **res = NULL, **res1;
     char *p, *next_token;
     int idx = 0;
 
@@ -92,16 +92,18 @@ split_string(char *str, int *count)
     do {
         p = strtok_s(str, " ", &next_token);
         str = NULL;
-        res = (char **)realloc(res, sizeof(char *) * (uint32)(idx + 1));
+        res1 = res;
+        res = (char **)realloc(res1, sizeof(char *) * (uint32)(idx + 1));
         if (res == NULL) {
+            free(res1);
             return NULL;
         }
         res[idx++] = p;
     } while (p);
 
     /**
-     * since the function name,
-     * res[0] might be contains a '\' to indicate a space
+     * Due to the function name,
+     * res[0] might contain a '\' to indicate a space
      * func\name -> func name
      */
     p = strchr(res[0], '\\');

+ 1 - 0
wamr-compiler/CMakeLists.txt

@@ -35,6 +35,7 @@ add_definitions(-DWASM_ENABLE_REF_TYPES=1)
 add_definitions(-DWASM_ENABLE_CUSTOM_NAME_SECTION=1)
 add_definitions(-DWASM_ENABLE_DUMP_CALL_STACK=1)
 add_definitions(-DWASM_ENABLE_PERF_PROFILING=1)
+add_definitions(-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1)
 
 if (WAMR_BUILD_LLVM_LEGACY_PM EQUAL 1)
   add_definitions(-DWASM_ENABLE_LLVM_LEGACY_PM=1)

+ 87 - 14
wamr-compiler/main.c

@@ -10,7 +10,7 @@
 #include "aot_export.h"
 
 /* clang-format off */
-static int
+static void
 print_help()
 {
     printf("Usage: wamrc [options] -o output_file wasm_file\n");
@@ -58,14 +58,66 @@ print_help()
     printf("  --enable-indirect-mode    Enalbe call function through symbol table but not direct call\n");
     printf("  --disable-llvm-intrinsics Disable the LLVM built-in intrinsics\n");
     printf("  --disable-llvm-lto        Disable the LLVM link time optimization\n");
+    printf("  --emit-custom-sections=<section names>\n");
+    printf("                            Emit the specified custom sections to AoT file, using comma to separate\n");
+    printf("                            multiple names, e.g.\n");
+    printf("                                --emit-custom-sections=section1,section2,sectionN\n");
     printf("  -v=n                      Set log verbose level (0 to 5, default is 2), larger with more log\n");
     printf("Examples: wamrc -o test.aot test.wasm\n");
     printf("          wamrc --target=i386 -o test.aot test.wasm\n");
     printf("          wamrc --target=i386 --format=object -o test.o test.wasm\n");
-    return 1;
 }
 /* clang-format on */
 
+#define PRINT_HELP_AND_EXIT() \
+    do {                      \
+        print_help();         \
+        goto fail0;           \
+    } while (0)
+
+/**
+ * Split a strings into an array of strings
+ * Returns NULL on failure
+ * Memory must be freed by caller
+ * Based on: http://stackoverflow.com/a/11198630/471795
+ */
+static char **
+split_string(char *str, int *count, const char *delimer)
+{
+    char **res = NULL, **res1;
+    char *p;
+    int idx = 0;
+
+    /* split string and append tokens to 'res' */
+    do {
+        p = strtok(str, delimer);
+        str = NULL;
+        res1 = res;
+        res = (char **)realloc(res1, sizeof(char *) * (uint32)(idx + 1));
+        if (res == NULL) {
+            free(res1);
+            return NULL;
+        }
+        res[idx++] = p;
+    } while (p);
+
+    /**
+     * Due to the section name,
+     * res[0] might contain a '\' to indicate a space
+     * func\name -> func name
+     */
+    p = strchr(res[0], '\\');
+    while (p) {
+        *p = ' ';
+        p = strchr(p, '\\');
+    }
+
+    if (count) {
+        *count = idx - 1;
+    }
+    return res;
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -97,39 +149,39 @@ main(int argc, char *argv[])
         if (!strcmp(argv[0], "-o")) {
             argc--, argv++;
             if (argc < 2)
-                return print_help();
+                PRINT_HELP_AND_EXIT();
             out_file_name = argv[0];
         }
         else if (!strncmp(argv[0], "--target=", 9)) {
             if (argv[0][9] == '\0')
-                return print_help();
+                PRINT_HELP_AND_EXIT();
             option.target_arch = argv[0] + 9;
         }
         else if (!strncmp(argv[0], "--target-abi=", 13)) {
             if (argv[0][13] == '\0')
-                return print_help();
+                PRINT_HELP_AND_EXIT();
             option.target_abi = argv[0] + 13;
         }
         else if (!strncmp(argv[0], "--cpu=", 6)) {
             if (argv[0][6] == '\0')
-                return print_help();
+                PRINT_HELP_AND_EXIT();
             option.target_cpu = argv[0] + 6;
         }
         else if (!strncmp(argv[0], "--cpu-features=", 15)) {
             if (argv[0][15] == '\0')
-                return print_help();
+                PRINT_HELP_AND_EXIT();
             option.cpu_features = argv[0] + 15;
         }
         else if (!strncmp(argv[0], "--opt-level=", 12)) {
             if (argv[0][12] == '\0')
-                return print_help();
+                PRINT_HELP_AND_EXIT();
             option.opt_level = (uint32)atoi(argv[0] + 12);
             if (option.opt_level > 3)
                 option.opt_level = 3;
         }
         else if (!strncmp(argv[0], "--size-level=", 13)) {
             if (argv[0][13] == '\0')
-                return print_help();
+                PRINT_HELP_AND_EXIT();
             option.size_level = (uint32)atoi(argv[0] + 13);
             if (option.size_level > 3)
                 option.size_level = 3;
@@ -143,7 +195,7 @@ main(int argc, char *argv[])
         }
         else if (!strncmp(argv[0], "--format=", 9)) {
             if (argv[0][9] == '\0')
-                return print_help();
+                PRINT_HELP_AND_EXIT();
             if (!strcmp(argv[0] + 9, "aot"))
                 option.output_format = AOT_FORMAT_FILE;
             else if (!strcmp(argv[0] + 9, "object"))
@@ -154,13 +206,13 @@ main(int argc, char *argv[])
                 option.output_format = AOT_LLVMIR_OPT_FILE;
             else {
                 printf("Invalid format %s.\n", argv[0] + 9);
-                return print_help();
+                PRINT_HELP_AND_EXIT();
             }
         }
         else if (!strncmp(argv[0], "-v=", 3)) {
             log_verbose_level = atoi(argv[0] + 3);
             if (log_verbose_level < 0 || log_verbose_level > 5)
-                return print_help();
+                PRINT_HELP_AND_EXIT();
         }
         else if (!strcmp(argv[0], "--disable-bulk-memory")) {
             option.enable_bulk_memory = false;
@@ -201,12 +253,27 @@ main(int argc, char *argv[])
         else if (!strcmp(argv[0], "--disable-llvm-lto")) {
             option.disable_llvm_lto = true;
         }
+        else if (!strncmp(argv[0], "--emit-custom-sections=", 23)) {
+            int len = 0;
+            if (option.custom_sections) {
+                free(option.custom_sections);
+            }
+
+            option.custom_sections = split_string(argv[0] + 23, &len, ",");
+            if (!option.custom_sections) {
+                printf("Failed to process emit-custom-sections: alloc "
+                       "memory failed\n");
+                PRINT_HELP_AND_EXIT();
+            }
+
+            option.custom_sections_count = len;
+        }
         else
-            return print_help();
+            PRINT_HELP_AND_EXIT();
     }
 
     if (argc == 0 || !out_file_name)
-        return print_help();
+        PRINT_HELP_AND_EXIT();
 
     if (!size_level_set) {
         /**
@@ -348,6 +415,12 @@ fail1:
     /* Destroy runtime environment */
     wasm_runtime_destroy();
 
+fail0:
+    /* free option.custom_sections */
+    if (option.custom_sections) {
+        free(option.custom_sections);
+    }
+
     bh_print_time("wamrc return");
     return exit_status;
 }