From 674f9d9844c5a4dd1ed4deb2b08058b1cbae38eb Mon Sep 17 00:00:00 2001 From: Jim Huang Date: Sun, 18 Jan 2026 14:25:47 +0800 Subject: [PATCH] Fix spurious close(fd<3) errors for stripped ELFs Stripped ELFs lack symbol tables, so the 'exit' symbol cannot be found and exit_addr remains uninitialized. This caused on_exit to never become true, resulting in spurious error messages when crt0 calls close(0,1,2) during program termination. Changes: - Add exit_addr check in syscall_close to allow close(fd<3) when no exit symbol was found (stripped ELF case) - Explicitly initialize exit_addr to 0 before symbol lookup - Also check for '_exit' symbol as fallback for different toolchains --- src/riscv.c | 12 +++++++++--- src/syscall.c | 5 +++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/riscv.c b/src/riscv.c index 3e36eda37..fd3a16462 100644 --- a/src/riscv.c +++ b/src/riscv.c @@ -647,10 +647,16 @@ riscv_t *rv_create(riscv_user_t rv_attr) #if !RV32_HAS(SYSTEM) /* set not exiting */ attr->on_exit = false; + attr->exit_addr = 0; - const struct Elf32_Sym *exit; - if ((exit = elf_get_symbol(elf, "exit"))) - attr->exit_addr = exit->st_value; + /* Try to find exit address from symbols. Check multiple names since + * different toolchains/libc implementations may use different symbols. + */ + const struct Elf32_Sym *exit_sym; + if ((exit_sym = elf_get_symbol(elf, "exit"))) + attr->exit_addr = exit_sym->st_value; + else if ((exit_sym = elf_get_symbol(elf, "_exit"))) + attr->exit_addr = exit_sym->st_value; #endif assert(elf_load(elf, attr->mem)); diff --git a/src/syscall.c b/src/syscall.c index 74dd83182..232665b54 100644 --- a/src/syscall.c +++ b/src/syscall.c @@ -222,9 +222,10 @@ static void syscall_close(riscv_t *rv) /* * The crt0 closes standard file descriptor(0, 1, 2) when * the process exits. Thus, the operations by the crt0 - * should not considered as error. + * should not be considered as error. For stripped ELFs where + * exit_addr is not found, allow close(fd<3) to succeed silently. */ - if (fd < 3 && !PRIV(rv)->on_exit) { + if (fd < 3 && !PRIV(rv)->on_exit && PRIV(rv)->exit_addr) { rv_set_reg(rv, rv_reg_a0, -1); rv_log_error( "Attempted to close a file descriptor < 3 (fd=%u). Operation "