| 626 | #[cfg(not(windows))] |
| 627 | #[pyfunction] |
| 628 | fn dlsym( |
| 629 | handle: usize, |
| 630 | name: crate::builtins::PyUtf8StrRef, |
| 631 | vm: &VirtualMachine, |
| 632 | ) -> PyResult<usize> { |
| 633 | let symbol_name = alloc::ffi::CString::new(name.as_str()) |
| 634 | .map_err(|_| vm.new_value_error("symbol name contains null byte"))?; |
| 635 | |
| 636 | // Clear previous error |
| 637 | unsafe { libc::dlerror() }; |
| 638 | |
| 639 | let ptr = unsafe { libc::dlsym(handle as *mut libc::c_void, symbol_name.as_ptr()) }; |
| 640 | |
| 641 | // Check for error via dlerror first |
| 642 | let err = unsafe { libc::dlerror() }; |
| 643 | if !err.is_null() { |
| 644 | let msg = unsafe { |
| 645 | core::ffi::CStr::from_ptr(err) |
| 646 | .to_string_lossy() |
| 647 | .into_owned() |
| 648 | }; |
| 649 | return Err(vm.new_os_error(msg)); |
| 650 | } |
| 651 | |
| 652 | // Treat NULL symbol address as error |
| 653 | // This handles cases like GNU IFUNCs that resolve to NULL |
| 654 | if ptr.is_null() { |
| 655 | return Err(vm.new_os_error(format!("symbol '{}' not found", name.as_str()))); |
| 656 | } |
| 657 | |
| 658 | Ok(ptr as usize) |
| 659 | } |
| 660 | |
| 661 | #[pyfunction(name = "POINTER")] |
| 662 | fn create_pointer_type(cls: PyObjectRef, vm: &VirtualMachine) -> PyResult { |