From aec38d983eac49bbf5f62c3280b6379ae5574271 Mon Sep 17 00:00:00 2001 From: Qianxi Chen Date: Wed, 20 Aug 2025 17:27:32 +0000 Subject: [PATCH] migrate temporary debug solution for libc fatal --- src/glibc/assert/__libc_assert_fail.c | 28 +++++++++++++++++----- src/glibc/malloc/malloc.c | 17 +++++++++++-- src/wasmtime/crates/lind-common/src/lib.rs | 27 +++++++++++++++++++++ 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/glibc/assert/__libc_assert_fail.c b/src/glibc/assert/__libc_assert_fail.c index 0204f9ea8..9fb805944 100644 --- a/src/glibc/assert/__libc_assert_fail.c +++ b/src/glibc/assert/__libc_assert_fail.c @@ -20,14 +20,30 @@ #include #include #include +#include + +#ifdef WASM_DEBUG_LIBC_FATAL +// TODO: For some reason, glibc's libc_assert_fail is not printing the error message when a fatal error is triggered. +// As a temporary workaround, we manually forward the message to Wasmtime and let Wasmtime handle the printing. +// Ideally, we should fix the issue and restore proper handling via glibc's native libc_assert_fail in the future. +void __imported__libc_assert_fail(const char *assertion, const char *file, unsigned int line, const char *function) __attribute__(( + __import_module__("debug"), + __import_name__("libc_assert_fail") +)); +#endif void __libc_assert_fail (const char *assertion, const char *file, unsigned int line, const char *function) { - char linebuf[INT_BUFSIZE_BOUND (unsigned int)]; - array_end (linebuf)[-1] = '\0'; - char *linestr = _itoa_word (line, array_end (linebuf) - 1, 10, 0); - __libc_message ("Fatal glibc error: %s:%s (%s): assertion failed: %s\n", - file, linestr, function, assertion); -} +#ifdef WASM_DEBUG_LIBC_FATAL + __imported__libc_assert_fail(assertion, file, line, function); + abort(); +#else + char linebuf[INT_BUFSIZE_BOUND (unsigned int)]; + array_end (linebuf)[-1] = '\0'; + char *linestr = _itoa_word (line, array_end (linebuf) - 1, 10, 0); + __libc_message ("Fatal glibc error: %s:%s (%s): assertion failed: %s\n", + file, linestr, function, assertion); +#endif +} \ No newline at end of file diff --git a/src/glibc/malloc/malloc.c b/src/glibc/malloc/malloc.c index b6ea1547f..07bed9500 100644 --- a/src/glibc/malloc/malloc.c +++ b/src/glibc/malloc/malloc.c @@ -5766,15 +5766,28 @@ libc_hidden_def (__libc_mallopt) extern char **__libc_argv attribute_hidden; +#ifdef WASM_DEBUG_MALLOC_ERR +// TODO: malloc_printerr is currently unable to print messages to the console correctly. +// This is a temporary workaround to ensure that error messages are printed. +void __imported__malloc_printerr(const char *str) __attribute__(( + __import_module__("debug"), + __import_name__("malloc_printerr") +)); +#endif + static void malloc_printerr (const char *str) { +#ifdef WASM_DEBUG_MALLOC_ERR + __imported__malloc_printerr(str); + __builtin_unreachable (); +#else #if IS_IN (libc) __libc_message ("%s\n", str); #else __libc_fatal (str); #endif - __builtin_unreachable (); +#endif } #if IS_IN (libc) @@ -6047,4 +6060,4 @@ compat_symbol (libc, __libc_free, cfree, GLIBC_2_0); * Local variables: * c-basic-offset: 2 * End: - */ + */ \ No newline at end of file diff --git a/src/wasmtime/crates/lind-common/src/lib.rs b/src/wasmtime/crates/lind-common/src/lib.rs index 78a158e89..8661ec261 100644 --- a/src/wasmtime/crates/lind-common/src/lib.rs +++ b/src/wasmtime/crates/lind-common/src/lib.rs @@ -218,6 +218,33 @@ pub fn add_to_linker< wasmtime_lind_multi_process::signal::signal_handler(&mut caller); }, )?; + + // a temporary solution to have libc_assert_fail correctly working + linker.func_wrap( + "debug", + "libc_assert_fail", + move |mut caller: Caller<'_, T>, assertion: i32, file: i32, line: i32, function: i32| { + let mem_base = get_memory_base(&caller); + let assertion = rawposix::interface::get_cstr(mem_base + assertion as u64).unwrap(); + let file = rawposix::interface::get_cstr(mem_base + file as u64).unwrap(); + let function = rawposix::interface::get_cstr(mem_base + function as u64).unwrap(); + eprintln!( + "Fatal glibc error: {}:{} ({}): assertion failed: {}\n", + assertion, file, line, function + ); + }, + )?; + + // a temporary solution to have malloc_printerr correctly working + linker.func_wrap( + "debug", + "malloc_printerr", + move |mut caller: Caller<'_, T>, msg: i32| { + let mem_base = get_memory_base(&caller); + let msg = rawposix::interface::get_cstr(mem_base + msg as u64).unwrap(); + eprintln!("malloc_printerr: {}", msg); + }, + )?; Ok(()) }