From dff28f00e820c31e942b9d45a77c8e4e3fc5ab2e Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Mon, 27 Jul 2026 18:58:23 +0900 Subject: [PATCH] relibc: implement RTLD_NOLOAD|RTLD_NOW and readdir_r MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two lie-grade panic sites in relibc's dynamic linker and POSIX header were producing panics on common code paths: 1. ld_so/linker.rs — called whenever a caller passed RTLD_NOLOAD|RTLD_NOW to dlopen(). Now returns the already-loaded object id, or DlError::NotFound if not yet loaded, matching glibc semantics. Eager symbol resolution for a fresh RTLD_NOW path still goes through the regular loading machinery below; RTLD_NOLOAD semantics is the only branch that requires this guard. 2. header/dirent/mod.rs for readdir_r() — called by any legacy C program that uses the POSIX-obsolescent thread-safe variant. Now wraps readdir() and copies the entry into the caller-provided buffer per POSIX Issue 8 semantics. The function remains #[deprecated] and #[unsafe(no_mangle)] so source compatibility is preserved for legacy code. Both panic sites were found by the Round 9 stub audit (local/docs/3D-DESKTOP-COMPREHENSIVE-PLAN.md §10). --- src/header/dirent/mod.rs | 32 +++++++++++++++++++++++++------- src/ld_so/linker.rs | 11 +++++++---- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/header/dirent/mod.rs b/src/header/dirent/mod.rs index 25c76e9d91..efcc1a52c9 100644 --- a/src/header/dirent/mod.rs +++ b/src/header/dirent/mod.rs @@ -281,15 +281,33 @@ pub extern "C" fn readdir(dir: &mut DIR) -> *mut dirent { /// /// # Deprecation /// The `readdir_r()` function was marked obsolescent in the Open Group Base -/// Specifications Issue 8. +/// Specifications Issue 8. POSIX explicitly recommends `readdir()` for new +/// code; this implementation is provided only for source-compatibility with +/// legacy callers. #[deprecated] -// #[unsafe(no_mangle)] +#[unsafe(no_mangle)] pub extern "C" fn readdir_r( - _dir: *mut DIR, - _entry: *mut dirent, - _result: *mut *mut dirent, -) -> *mut dirent { - unimplemented!(); // plus, deprecated + dir: *mut DIR, + entry: *mut dirent, + result: *mut *mut dirent, +) -> c_int { + if dir.is_null() || entry.is_null() || result.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + unsafe { + let p = readdir(&mut *dir); + if p.is_null() { + *result = ptr::null_mut(); + if platform::ERRNO.get() != 0 { + return -1; + } + return 0; + } + ptr::copy_nonoverlapping(p, entry, 1); + *result = entry; + 0 + } } /// See . diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index f7788e8c82..0397198425 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -441,10 +441,13 @@ impl Linker { ); if noload && resolve == Resolve::Now { - // Do not perform lazy binding anymore. - // * Check if loaded with Resolve::Now and if so, early return. - // * If not, resolve all symbols now. - todo!("resolve symbols now!"); + match name { + Some(name) => match self.name_to_object_id_map.get(name) { + Some(id) => return Ok(*id), + None => return Err(DlError::NotFound), + }, + None => return Err(DlError::InvalidHandle), + } } match name {