From a1568825e85f010cec27e0cf6e88617846481d9b Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Sat, 6 Mar 2021 08:29:58 -0600 Subject: [PATCH] Enable to use BH_VPRINTF macro to redirect stdout output (#560) Enable to use BH_VPRINTF macro for platform Linux/Windows/Darwin/VxWorks to redirect the stdout output from platform os_printf/os_vprintf, or the wasi output from wasm app to the vprintf like callback function specified by BH_VPRINTF macro of cmake WAMR_BH_VPRINTF variable. Signed-off-by: Wenyong Huang --- build-scripts/config_common.cmake | 3 +++ .../libc-uvwasi/libc_uvwasi_wrapper.c | 27 +++++++++++++++++-- .../sandboxed-system-primitives/src/posix.c | 22 +++++++++++++++ core/shared/platform/darwin/platform_init.c | 8 ++++++ .../shared/platform/include/platform_common.h | 12 +++++++-- core/shared/platform/linux/platform_init.c | 8 ++++++ core/shared/platform/vxworks/platform_init.c | 8 ++++++ core/shared/platform/windows/platform_init.c | 27 +++++++++++++++++++ .../platform/windows/platform_internal.h | 3 --- doc/build_wamr.md | 21 +++++++++++++++ 10 files changed, 132 insertions(+), 7 deletions(-) diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index b296f89f..e0ecc540 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -202,4 +202,7 @@ if (WAMR_BUILD_TAIL_CALL EQUAL 1) add_definitions (-DWASM_ENABLE_TAIL_CALL=1) message (" Tail call enabled") endif () +if (DEFINED WAMR_BH_VPRINTF) + add_definitions (-DBH_VPRINTF=${WAMR_BH_VPRINTF}) +endif () diff --git a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c index 1263b0dc..af6e0de3 100644 --- a/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c +++ b/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c @@ -604,8 +604,31 @@ wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, ciovec->buf_len = iovec_app->buf_len; } - err = uvwasi_fd_write(uvwasi, fd, - ciovec_begin, iovs_len, &nwritten); +#ifndef BH_VPRINTF + err = uvwasi_fd_write(uvwasi, fd, ciovec_begin, iovs_len, &nwritten); +#else + /* redirect stdout/stderr output to BH_VPRINTF function */ + if (fd == 1 || fd == 2) { + int i; + const struct iovec *iov1 = (const struct iovec *)ciovec_begin; + + nwritten = 0; + for (i = 0; i < (int)iovs_len; i++, iov1++) { + if (iov1->iov_len > 0 && iov1->iov_base) { + char format[16]; + + /* make up format string "%.ns" */ + snprintf(format, sizeof(format), "%%.%ds", (int)iov1->iov_len); + nwritten += (uvwasi_size_t)os_printf(format, iov1->iov_base); + } + } + err = 0; + } + else { + err = uvwasi_fd_write(uvwasi, fd, ciovec_begin, iovs_len, &nwritten); + } +#endif /* end of BH_VPRINTF */ + if (err) goto fail; diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 9e4d989f..6b4cbe20 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -1237,7 +1237,29 @@ __wasi_errno_t wasmtime_ssp_fd_write( if (error != 0) return error; +#ifndef BH_VPRINTF ssize_t len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); +#else + ssize_t len = 0; + /* redirect stdout/stderr output to BH_VPRINTF function */ + if (fd_number(fo) == 1 || fd_number(fo) == 2) { + int i; + const struct iovec *iov1 = (const struct iovec *)iov; + + for (i = 0; i < (int)iovcnt; i++, iov1++) { + if (iov1->iov_len > 0 && iov1->iov_base) { + char format[16]; + + /* make up format string "%.ns" */ + snprintf(format, sizeof(format), "%%.%ds", (int)iov1->iov_len); + len += (ssize_t)os_printf(format, iov1->iov_base); + } + } + } + else { + len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt); + } +#endif /* end of BH_VPRINTF */ fd_object_release(fo); if (len < 0) return convert_errno(errno); diff --git a/core/shared/platform/darwin/platform_init.c b/core/shared/platform/darwin/platform_init.c index 4f806083..17aeb8ba 100644 --- a/core/shared/platform/darwin/platform_init.c +++ b/core/shared/platform/darwin/platform_init.c @@ -23,7 +23,11 @@ os_printf(const char *format, ...) va_list ap; va_start(ap, format); +#ifndef BH_VPRINTF ret += vprintf(format, ap); +#else + ret += BH_VPRINTF(format, ap); +#endif va_end(ap); return ret; @@ -32,6 +36,10 @@ os_printf(const char *format, ...) int os_vprintf(const char *format, va_list ap) { +#ifndef BH_VPRINTF return vprintf(format, ap); +#else + return BH_VPRINTF(format, ap); +#endif } diff --git a/core/shared/platform/include/platform_common.h b/core/shared/platform/include/platform_common.h index 57b20912..ca278020 100644 --- a/core/shared/platform/include/platform_common.h +++ b/core/shared/platform/include/platform_common.h @@ -34,13 +34,21 @@ extern "C" { #endif #if defined(MSVC) -__declspec(dllimport) void *BH_MALLOC(unsigned int size); -__declspec(dllimport) void BH_FREE(void *ptr); +__declspec(dllimport) void *BH_MALLOC(unsigned int size); +__declspec(dllimport) void BH_FREE(void *ptr); #else void *BH_MALLOC(unsigned int size); void BH_FREE(void *ptr); #endif +#if defined(BH_VPRINTF) +#if defined(MSVC) +__declspec(dllimport) int BH_VPRINTF(const char *format, va_list ap); +#else +int BH_VPRINTF(const char *format, va_list ap); +#endif +#endif + #ifndef NULL #define NULL (void*)0 #endif diff --git a/core/shared/platform/linux/platform_init.c b/core/shared/platform/linux/platform_init.c index 4f806083..17aeb8ba 100644 --- a/core/shared/platform/linux/platform_init.c +++ b/core/shared/platform/linux/platform_init.c @@ -23,7 +23,11 @@ os_printf(const char *format, ...) va_list ap; va_start(ap, format); +#ifndef BH_VPRINTF ret += vprintf(format, ap); +#else + ret += BH_VPRINTF(format, ap); +#endif va_end(ap); return ret; @@ -32,6 +36,10 @@ os_printf(const char *format, ...) int os_vprintf(const char *format, va_list ap) { +#ifndef BH_VPRINTF return vprintf(format, ap); +#else + return BH_VPRINTF(format, ap); +#endif } diff --git a/core/shared/platform/vxworks/platform_init.c b/core/shared/platform/vxworks/platform_init.c index 4f806083..17aeb8ba 100644 --- a/core/shared/platform/vxworks/platform_init.c +++ b/core/shared/platform/vxworks/platform_init.c @@ -23,7 +23,11 @@ os_printf(const char *format, ...) va_list ap; va_start(ap, format); +#ifndef BH_VPRINTF ret += vprintf(format, ap); +#else + ret += BH_VPRINTF(format, ap); +#endif va_end(ap); return ret; @@ -32,6 +36,10 @@ os_printf(const char *format, ...) int os_vprintf(const char *format, va_list ap) { +#ifndef BH_VPRINTF return vprintf(format, ap); +#else + return BH_VPRINTF(format, ap); +#endif } diff --git a/core/shared/platform/windows/platform_init.c b/core/shared/platform/windows/platform_init.c index 76594b81..17aeb8ba 100644 --- a/core/shared/platform/windows/platform_init.c +++ b/core/shared/platform/windows/platform_init.c @@ -16,3 +16,30 @@ bh_platform_destroy() { } +int +os_printf(const char *format, ...) +{ + int ret = 0; + va_list ap; + + va_start(ap, format); +#ifndef BH_VPRINTF + ret += vprintf(format, ap); +#else + ret += BH_VPRINTF(format, ap); +#endif + va_end(ap); + + return ret; +} + +int +os_vprintf(const char *format, va_list ap) +{ +#ifndef BH_VPRINTF + return vprintf(format, ap); +#else + return BH_VPRINTF(format, ap); +#endif +} + diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h index 65a933ac..877336be 100644 --- a/core/shared/platform/windows/platform_internal.h +++ b/core/shared/platform/windows/platform_internal.h @@ -49,9 +49,6 @@ typedef struct { unsigned int waiting_count; } korp_cond; -#define os_printf printf -#define os_vprintf vprintf - static inline size_t getpagesize() { diff --git a/doc/build_wamr.md b/doc/build_wamr.md index 92f04a7b..c18fbcb2 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -114,6 +114,27 @@ Currently we only profile the memory consumption of module, module_instance and - **WAMR_APP_THREAD_STACK_SIZE_MAX**=n, default to 8 MB (8388608) if not set > Note: the AOT boundary check with hardware trap mechanism might consume large stack since the OS may lazily grow the stack mapping as a guard page is hit, we may use this configuration to reduce the total stack usage, e.g. -DWAMR_APP_THREAD_STACK_SIZE_MAX=131072 (128 KB). +#### **WAMR_BH_VPRINTF**=, default to disable if not set +> Note: if the vprintf_callback function is provided by developer, the os_printf() and os_vprintf() in Linux, Darwin, Windows and VxWorks platforms, besides WASI Libc output will call the callback function instead of libc vprintf() function to redirect the stdout output. For example, developer can define the callback function like below outside runtime lib: +> +> ```C +> int my_vprintf(const char *format, va_list ap) +> { +> /* output to pre-opened file stream */ +> FILE *my_file = ...; +> return vfprintf(my_file, format, ap); +> /* or output to pre-opened file descriptor */ +> int my_fd = ...; +> return vdprintf(my_fd, format, ap); +> /* or output to string buffer and print the string */ +> char buf[128]; +> vsnprintf(buf, sizeof(buf), format, ap); +> return my_printf("%s", buf); +> } +> ``` +> +> and then use `cmake -DWAMR_BH_VPRINTF=my_vprintf ..` to pass the callback function, or add `BH_VPRINTF=my_vprintf` macro for the compiler, e.g. add line `add_defintions(-DBH_VPRINTF=my_vprintf)` in CMakeListst.txt. + **Combination of configurations:** We can combine the configurations. For example, if we want to disable interpreter, enable AOT and WASI, we can run command: