mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2026-04-18 10:17:38 +00:00
Add custom section sample and enable CI test
This commit is contained in:
parent
c3dda4a7d6
commit
c5ee306f2c
|
|
@ -628,6 +628,14 @@ jobs:
|
|||
cmake --build . --config Release --parallel 4
|
||||
./import-func-callback
|
||||
|
||||
- name: Build Sample [custom_section]
|
||||
run: |
|
||||
cd samples/custom-section
|
||||
./build.sh
|
||||
./run.sh
|
||||
./build.sh --aot
|
||||
./run.sh --aot
|
||||
|
||||
test:
|
||||
needs: [build_iwasm, build_llvm_libraries_on_ubuntu_2204, build_wamrc]
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
|
|
|||
8
.github/workflows/compilation_on_macos.yml
vendored
8
.github/workflows/compilation_on_macos.yml
vendored
|
|
@ -441,6 +441,14 @@ jobs:
|
|||
cmake --build . --config Release --parallel 4
|
||||
./import-func-callback
|
||||
|
||||
- name: Build Sample [custom_section]
|
||||
run: |
|
||||
cd samples/custom-section
|
||||
./build.sh
|
||||
./run.sh
|
||||
./build.sh --aot
|
||||
./run.sh --aot
|
||||
|
||||
- name: Test x18 register reservation (macOS ARM64 only)
|
||||
if: matrix.os == 'macos-15'
|
||||
run: |
|
||||
|
|
|
|||
8
.github/workflows/nightly_run.yml
vendored
8
.github/workflows/nightly_run.yml
vendored
|
|
@ -598,6 +598,14 @@ jobs:
|
|||
cmake --build . --config Release --parallel 4
|
||||
./import-func-callback
|
||||
|
||||
- name: Build Sample [custom_section]
|
||||
run: |
|
||||
cd samples/custom-section
|
||||
./build.sh
|
||||
./run.sh
|
||||
./build.sh --aot
|
||||
./run.sh --aot
|
||||
|
||||
test:
|
||||
needs: [build_iwasm, build_llvm_libraries_on_ubuntu, build_wamrc]
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# Samples
|
||||
|
||||
- [**basic**](./basic): Demonstrating how to use runtime exposed API's to call WASM functions, how to register native functions and call them, and how to call WASM function from native function.
|
||||
- [**custom_section**](./custom_section): Demonstrating how to embed a binary payload into a Wasm custom section, resolve it from native code with `wasm_runtime_get_custom_section`, and print it later through a handle-based native API.
|
||||
- **[file](./file/README.md)**: Demonstrating the supported file interaction API of WASI. This sample can also demonstrate the SGX IPFS (Intel Protected File System), enabling an enclave to seal and unseal data at rest.
|
||||
- **[multi-thread](./multi-thread/)**: Demonstrating how to run wasm application which creates multiple threads to execute wasm functions concurrently, and uses mutex/cond by calling pthread related API's.
|
||||
- **[spawn-thread](./spawn-thread)**: Demonstrating how to execute wasm functions of the same wasm application concurrently, in threads created by host embedder or runtime, but not the wasm application itself.
|
||||
|
|
|
|||
1
samples/custom-section/.gitignore
vendored
Normal file
1
samples/custom-section/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/out/
|
||||
81
samples/custom-section/CMakeLists.txt
Normal file
81
samples/custom-section/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
include(CheckPIESupported)
|
||||
|
||||
if(NOT WAMR_BUILD_PLATFORM STREQUAL "windows")
|
||||
project(custom_section)
|
||||
else()
|
||||
project(custom_section C ASM)
|
||||
endif()
|
||||
|
||||
# ############### runtime settings ################
|
||||
string(TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
|
||||
|
||||
if(APPLE)
|
||||
add_definitions(-DBH_PLATFORM_DARWIN)
|
||||
endif()
|
||||
|
||||
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
|
||||
|
||||
if(NOT DEFINED WAMR_BUILD_TARGET)
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)")
|
||||
set(WAMR_BUILD_TARGET "AARCH64")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
|
||||
set(WAMR_BUILD_TARGET "RISCV64")
|
||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(WAMR_BUILD_TARGET "X86_64")
|
||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(WAMR_BUILD_TARGET "X86_32")
|
||||
else()
|
||||
message(SEND_ERROR "Unsupported build target platform!")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Debug)
|
||||
endif()
|
||||
|
||||
set(WAMR_BUILD_MEMORY_PROFILING 1)
|
||||
set(WAMR_BUILD_INTERP 1)
|
||||
set(WAMR_BUILD_AOT 1)
|
||||
set(WAMR_BUILD_JIT 0)
|
||||
set(WAMR_BUILD_LIBC_BUILTIN 1)
|
||||
set(WAMR_BUILD_LOAD_CUSTOM_SECTION 1)
|
||||
|
||||
if(NOT MSVC)
|
||||
set(WAMR_BUILD_LIBC_WASI 1)
|
||||
endif()
|
||||
|
||||
if(NOT MSVC)
|
||||
if(NOT(CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
|
||||
include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
||||
|
||||
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
|
||||
# ############### application related ################
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
||||
include(${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
|
||||
|
||||
add_executable(custom_section
|
||||
src/main.c
|
||||
src/native_impl.c
|
||||
${UNCOMMON_SHARED_SOURCE}
|
||||
)
|
||||
|
||||
check_pie_supported()
|
||||
set_target_properties(custom_section PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if(APPLE)
|
||||
target_link_libraries(custom_section vmlib -lm -ldl -lpthread)
|
||||
else()
|
||||
target_link_libraries(custom_section vmlib -lm -ldl -lpthread -lrt)
|
||||
endif()
|
||||
69
samples/custom-section/README.md
Normal file
69
samples/custom-section/README.md
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
---
|
||||
description: "The related code/working directory of this example resides in directory {WAMR_DIR}/samples/custom_section"
|
||||
---
|
||||
|
||||
# The "custom_section" sample project
|
||||
|
||||
This sample demonstrates how to:
|
||||
|
||||
- embed a separate binary payload into a Wasm custom section through a `.s` file
|
||||
- load that Wasm module with `WAMR_BUILD_LOAD_CUSTOM_SECTION=1`
|
||||
- export native APIs that resolve a custom section name to a host-side handle
|
||||
- print the custom section bytes later through a second native API
|
||||
- optionally compile the Wasm module to AoT while preserving the `demo` custom section
|
||||
|
||||
The Wasm application is built from:
|
||||
|
||||
- `wasm-apps/custom_section.c`
|
||||
- `wasm-apps/custom_section_payload.s`
|
||||
- `wasm-apps/custom_section_payload.bin`
|
||||
|
||||
The assembler file emits a section named `.custom_section.demo`, which becomes a Wasm custom section named `demo` in the final `.wasm` file.
|
||||
|
||||
## Why use a custom section for this payload
|
||||
|
||||
The payload in this sample is treated as read-only metadata. Putting it in a custom section lets the embedder access the bytes directly from the loaded module through `wasm_runtime_get_custom_section`, instead of copying the data into Wasm linear memory per instance.
|
||||
|
||||
That matters when the data is large or rarely changed:
|
||||
|
||||
- the bytes stay in the module image as immutable data
|
||||
- the host can look them up by section name and use them in place
|
||||
- the Wasm app only needs to pass a small section name and receive a small handle
|
||||
- no extra application-level serialization or buffer duplication is needed for the read-only payload
|
||||
|
||||
This pattern is useful for embedded assets, lookup tables, model metadata, certificates, and other static blobs that the host wants to consume without treating them as mutable Wasm heap data.
|
||||
|
||||
## Build this sample
|
||||
|
||||
Execute the `build.sh` script. The host executable and the Wasm app are generated in `out`.
|
||||
|
||||
```sh
|
||||
./build.sh
|
||||
```
|
||||
|
||||
Build the AoT variant only when needed by passing `--aot`. This preserves the `demo` custom section in the generated AoT file by calling `wamrc --emit-custom-sections=demo`.
|
||||
|
||||
```sh
|
||||
./build.sh --aot
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
Enter the output directory and run the Wasm sample directly:
|
||||
|
||||
```sh
|
||||
cd ./out/
|
||||
./custom_section -f wasm-apps/custom_section.wasm
|
||||
```
|
||||
|
||||
Or run the helper script from `samples/custom_section`:
|
||||
|
||||
```sh
|
||||
./run.sh
|
||||
```
|
||||
|
||||
To run the AoT artifact instead, pass `--aot` to the helper script:
|
||||
|
||||
```sh
|
||||
./run.sh --aot
|
||||
```
|
||||
63
samples/custom-section/build.sh
Executable file
63
samples/custom-section/build.sh
Executable file
|
|
@ -0,0 +1,63 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
CURR_DIR=$PWD
|
||||
OUT_DIR=${PWD}/out
|
||||
WASM_APPS=${PWD}/wasm-apps
|
||||
WAMR_ROOT_DIR=${PWD}/../..
|
||||
WAMRC_CMD=${WAMR_ROOT_DIR}/wamr-compiler/build/wamrc
|
||||
BUILD_AOT=0
|
||||
|
||||
if [ $# -gt 1 ]; then
|
||||
echo "Usage: $0 [--aot]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -eq 1 ]; then
|
||||
if [ "$1" = "--aot" ]; then
|
||||
BUILD_AOT=1
|
||||
else
|
||||
echo "Usage: $0 [--aot]"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -rf ${OUT_DIR}
|
||||
mkdir -p ${OUT_DIR}/wasm-apps
|
||||
|
||||
printf '##################### build custom_section project\n'
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug
|
||||
make -j ${nproc}
|
||||
cp -a custom_section ${OUT_DIR}
|
||||
|
||||
printf '\n##################### build wasm app\n'
|
||||
cd ${WASM_APPS}
|
||||
/opt/wasi-sdk/bin/clang \
|
||||
--target=wasm32 \
|
||||
-O0 \
|
||||
-nostdlib \
|
||||
-Wl,--strip-all,--no-entry \
|
||||
-Wl,--allow-undefined \
|
||||
-Wl,--export=run_demo \
|
||||
-o ${OUT_DIR}/wasm-apps/custom_section.wasm \
|
||||
custom_section.c \
|
||||
custom_section_payload.s
|
||||
|
||||
printf '\nbuild custom_section.wasm success\n'
|
||||
|
||||
if [ ${BUILD_AOT} -eq 1 ]; then
|
||||
if [ ! -x ${WAMRC_CMD} ]; then
|
||||
echo "Error: wamrc not found at ${WAMRC_CMD}"
|
||||
echo "Please build wamrc first under ${WAMR_ROOT_DIR}/wamr-compiler"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '\n##################### build aot app\n'
|
||||
${WAMRC_CMD} --emit-custom-sections=demo -o ${OUT_DIR}/wasm-apps/custom_section.aot ${OUT_DIR}/wasm-apps/custom_section.wasm
|
||||
printf '\nbuild custom_section.aot success\n'
|
||||
fi
|
||||
|
||||
cd ${CURR_DIR}
|
||||
31
samples/custom-section/run.sh
Executable file
31
samples/custom-section/run.sh
Executable file
|
|
@ -0,0 +1,31 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ $# -gt 1 ]; then
|
||||
echo "Usage: $0 [--aot]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
APP=out/wasm-apps/custom_section.wasm
|
||||
|
||||
if [ $# -eq 1 ]; then
|
||||
if [ "$1" = "--aot" ]; then
|
||||
APP=out/wasm-apps/custom_section.aot
|
||||
else
|
||||
echo "Usage: $0 [--aot]"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f ${APP} ]; then
|
||||
echo "Error: ${APP} not found"
|
||||
if [ "$APP" = "out/wasm-apps/custom_section.aot" ]; then
|
||||
echo "Run ./build.sh --aot first"
|
||||
else
|
||||
echo "Run ./build.sh first"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
out/custom_section -f ${APP}
|
||||
141
samples/custom-section/src/main.c
Normal file
141
samples/custom-section/src/main.c
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "bh_getopt.h"
|
||||
#include "bh_read_file.h"
|
||||
#include "wasm_export.h"
|
||||
|
||||
int32_t
|
||||
get_custom_section_handle(wasm_exec_env_t exec_env, const char *section_name);
|
||||
void
|
||||
print_custom_section(wasm_exec_env_t exec_env, int32_t handle);
|
||||
void
|
||||
reset_custom_section_handles(void);
|
||||
|
||||
static void
|
||||
print_usage(void)
|
||||
{
|
||||
fprintf(stdout, "Options:\r\n");
|
||||
fprintf(stdout, " -f [path of wasm file]\n");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv_main[])
|
||||
{
|
||||
static char global_heap_buf[512 * 1024];
|
||||
RuntimeInitArgs init_args;
|
||||
wasm_module_t module = NULL;
|
||||
wasm_module_inst_t module_inst = NULL;
|
||||
wasm_exec_env_t exec_env = NULL;
|
||||
wasm_function_inst_t func = NULL;
|
||||
wasm_val_t results[1] = { { .kind = WASM_I32, .of.i32 = -1 } };
|
||||
char *buffer = NULL;
|
||||
char *wasm_path = NULL;
|
||||
char error_buf[128];
|
||||
int exit_code = 1;
|
||||
int opt;
|
||||
uint32_t buf_size;
|
||||
uint32_t stack_size = 8092;
|
||||
uint32_t heap_size = 8092;
|
||||
|
||||
memset(&init_args, 0, sizeof(RuntimeInitArgs));
|
||||
|
||||
while ((opt = getopt(argc, argv_main, "hf:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
wasm_path = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
print_usage();
|
||||
return 0;
|
||||
case '?':
|
||||
print_usage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == 1) {
|
||||
print_usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NativeSymbol native_symbols[] = {
|
||||
{ "get_custom_section_handle", get_custom_section_handle, "($)i",
|
||||
NULL },
|
||||
{ "print_custom_section", print_custom_section, "(i)", NULL },
|
||||
};
|
||||
|
||||
init_args.mem_alloc_type = Alloc_With_Pool;
|
||||
init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
|
||||
init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
|
||||
init_args.n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol);
|
||||
init_args.native_module_name = "env";
|
||||
init_args.native_symbols = native_symbols;
|
||||
|
||||
if (!wasm_runtime_full_init(&init_args)) {
|
||||
printf("Init runtime environment failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
reset_custom_section_handles();
|
||||
|
||||
buffer = bh_read_file_to_buffer(wasm_path, &buf_size);
|
||||
if (!buffer) {
|
||||
printf("Open wasm app file [%s] failed.\n", wasm_path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
module = wasm_runtime_load((uint8 *)buffer, buf_size, error_buf,
|
||||
sizeof(error_buf));
|
||||
if (!module) {
|
||||
printf("Load wasm module failed. error: %s\n", error_buf);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
module_inst = wasm_runtime_instantiate(module, stack_size, heap_size,
|
||||
error_buf, sizeof(error_buf));
|
||||
if (!module_inst) {
|
||||
printf("Instantiate wasm module failed. error: %s\n", error_buf);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
|
||||
if (!exec_env) {
|
||||
printf("Create wasm execution environment failed.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
func = wasm_runtime_lookup_function(module_inst, "run_demo");
|
||||
if (!func) {
|
||||
printf("The wasm function run_demo is not found.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!wasm_runtime_call_wasm_a(exec_env, func, 1, results, 0, NULL)) {
|
||||
printf("call wasm function run_demo failed. error: %s\n",
|
||||
wasm_runtime_get_exception(module_inst));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printf("Wasm returned custom section handle: %d\n", results[0].of.i32);
|
||||
exit_code = results[0].of.i32 >= 0 ? 0 : 1;
|
||||
|
||||
fail:
|
||||
if (exec_env) {
|
||||
wasm_runtime_destroy_exec_env(exec_env);
|
||||
}
|
||||
if (module_inst) {
|
||||
wasm_runtime_deinstantiate(module_inst);
|
||||
}
|
||||
if (module) {
|
||||
wasm_runtime_unload(module);
|
||||
}
|
||||
if (buffer) {
|
||||
BH_FREE(buffer);
|
||||
}
|
||||
reset_custom_section_handles();
|
||||
wasm_runtime_destroy();
|
||||
return exit_code;
|
||||
}
|
||||
95
samples/custom-section/src/native_impl.c
Normal file
95
samples/custom-section/src/native_impl.c
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "wasm_export.h"
|
||||
|
||||
#define MAX_CUSTOM_SECTION_HANDLES 8
|
||||
|
||||
typedef struct CustomSectionHandle {
|
||||
wasm_module_t module;
|
||||
const uint8_t *content;
|
||||
uint32_t length;
|
||||
} CustomSectionHandle;
|
||||
|
||||
static CustomSectionHandle custom_section_handles[MAX_CUSTOM_SECTION_HANDLES];
|
||||
|
||||
void
|
||||
reset_custom_section_handles(void)
|
||||
{
|
||||
memset(custom_section_handles, 0, sizeof(custom_section_handles));
|
||||
}
|
||||
|
||||
int32_t
|
||||
get_custom_section_handle(wasm_exec_env_t exec_env, const char *section_name)
|
||||
{
|
||||
wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env);
|
||||
wasm_module_t module = wasm_runtime_get_module(module_inst);
|
||||
const uint8_t *content = NULL;
|
||||
uint32_t length = 0;
|
||||
uint32_t i;
|
||||
|
||||
if (!section_name || section_name[0] == '\0') {
|
||||
printf("custom section name is empty\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
content = wasm_runtime_get_custom_section(module, section_name, &length);
|
||||
if (!content) {
|
||||
printf("custom section [%s] not found\n", section_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CUSTOM_SECTION_HANDLES; i++) {
|
||||
if (custom_section_handles[i].content == content
|
||||
&& custom_section_handles[i].module == module
|
||||
&& custom_section_handles[i].length == length) {
|
||||
return (int32_t)i;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CUSTOM_SECTION_HANDLES; i++) {
|
||||
if (!custom_section_handles[i].content) {
|
||||
custom_section_handles[i].module = module;
|
||||
custom_section_handles[i].content = content;
|
||||
custom_section_handles[i].length = length;
|
||||
printf("resolved custom section [%s] to handle %u (%u bytes)\n",
|
||||
section_name, i, length);
|
||||
return (int32_t)i;
|
||||
}
|
||||
}
|
||||
|
||||
printf("no free custom section handle slots remain\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
print_custom_section(wasm_exec_env_t exec_env, int32_t handle)
|
||||
{
|
||||
wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env);
|
||||
wasm_module_t module = wasm_runtime_get_module(module_inst);
|
||||
CustomSectionHandle *section_handle = NULL;
|
||||
|
||||
if (handle < 0 || handle >= MAX_CUSTOM_SECTION_HANDLES) {
|
||||
printf("invalid custom section handle %d\n", handle);
|
||||
return;
|
||||
}
|
||||
|
||||
section_handle = &custom_section_handles[handle];
|
||||
if (!section_handle->content || section_handle->module != module) {
|
||||
printf("custom section handle %d is not valid for this module\n",
|
||||
handle);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("custom section payload (%u bytes):\n", section_handle->length);
|
||||
fwrite(section_handle->content, 1, section_handle->length, stdout);
|
||||
if (section_handle->length == 0
|
||||
|| section_handle->content[section_handle->length - 1] != '\n') {
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
19
samples/custom-section/wasm-apps/custom_section.c
Normal file
19
samples/custom-section/wasm-apps/custom_section.c
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
__attribute__((import_module("env"),
|
||||
import_name("get_custom_section_handle"))) int
|
||||
get_custom_section_handle(const char *section_name);
|
||||
|
||||
__attribute__((import_module("env"), import_name("print_custom_section"))) void
|
||||
print_custom_section(int handle);
|
||||
|
||||
__attribute__((export_name("run_demo"))) int
|
||||
run_demo(void)
|
||||
{
|
||||
static const char section_name[] = "demo";
|
||||
int handle = get_custom_section_handle(section_name);
|
||||
|
||||
if (handle >= 0) {
|
||||
print_custom_section(handle);
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
This payload lives in a Wasm custom section.
|
||||
It is linked by custom_section_payload.s with .incbin.
|
||||
|
||||
The payload is read by custom_section.c, which is compiled to a Wasm module and executed by the host embedder.
|
||||
It can be arbitrarily data, and the host can resolve it with `wasm_runtime_get_custom_section` and print/use it later through a handle-based native API.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
.section .custom_section.demo,"",@
|
||||
.incbin "custom_section_payload.bin"
|
||||
Loading…
Reference in New Issue
Block a user