// Other Unix (e.g. Linux) platforms use ELF as an object file format // and typically implement an API called `dl_iterate_phdr` to load // native libraries. use super::mystd::borrow::ToOwned; use super::mystd::env; use super::mystd::ffi::{CStr, OsStr}; use super::mystd::os::unix::prelude::*; use super::{Library, LibrarySegment, OsString, Vec}; use core::slice; pub(super) fn native_libraries() -> Vec { let mut ret = Vec::new(); unsafe { libc::dl_iterate_phdr(Some(callback), &mut ret as *mut Vec<_> as *mut _); } return ret; } // `info` should be a valid pointers. // `vec` should be a valid pointer to a `std::Vec`. unsafe extern "C" fn callback( info: *mut libc::dl_phdr_info, _size: libc::size_t, vec: *mut libc::c_void, ) -> libc::c_int { let info = &*info; let libs = &mut *(vec as *mut Vec); let is_main_prog = info.dlpi_name.is_null() || *info.dlpi_name == 0; let name = if is_main_prog { if libs.is_empty() { env::current_exe().map(|e| e.into()).unwrap_or_default() } else { OsString::new() } } else { let bytes = CStr::from_ptr(info.dlpi_name).to_bytes(); OsStr::from_bytes(bytes).to_owned() }; let headers = slice::from_raw_parts(info.dlpi_phdr, info.dlpi_phnum as usize); libs.push(Library { name, segments: headers .iter() .map(|header| LibrarySegment { len: (*header).p_memsz as usize, stated_virtual_memory_address: (*header).p_vaddr as usize, }) .collect(), bias: info.dlpi_addr as usize, }); 0 }