| use super::mystd::borrow::ToOwned; |
| use super::mystd::env; |
| use super::mystd::ffi::{CStr, OsStr}; |
| use super::mystd::io::Error; |
| use super::mystd::os::unix::prelude::*; |
| use super::xcoff; |
| use super::{Library, LibrarySegment, Vec}; |
| use alloc::vec; |
| use core::mem; |
| |
| const EXE_IMAGE_BASE: u64 = 0x100000000; |
| |
| /// On AIX, we use `loadquery` with `L_GETINFO` flag to query libraries mmapped. |
| /// See https://www.ibm.com/docs/en/aix/7.2?topic=l-loadquery-subroutine for |
| /// detailed information of `loadquery`. |
| pub(super) fn native_libraries() -> Vec<Library> { |
| let mut ret = Vec::new(); |
| unsafe { |
| let mut buffer = vec![mem::zeroed::<libc::ld_info>(); 64]; |
| loop { |
| if libc::loadquery( |
| libc::L_GETINFO, |
| buffer.as_mut_ptr() as *mut libc::c_char, |
| (mem::size_of::<libc::ld_info>() * buffer.len()) as u32, |
| ) != -1 |
| { |
| break; |
| } else { |
| match Error::last_os_error().raw_os_error() { |
| Some(libc::ENOMEM) => { |
| buffer.resize(buffer.len() * 2, mem::zeroed::<libc::ld_info>()); |
| } |
| Some(_) => { |
| // If other error occurs, return empty libraries. |
| return Vec::new(); |
| } |
| _ => unreachable!(), |
| } |
| } |
| } |
| let mut current = buffer.as_mut_ptr(); |
| loop { |
| let text_base = (*current).ldinfo_textorg as usize; |
| let filename_ptr: *const libc::c_char = &(*current).ldinfo_filename[0]; |
| let bytes = CStr::from_ptr(filename_ptr).to_bytes(); |
| let member_name_ptr = filename_ptr.offset((bytes.len() + 1) as isize); |
| let mut filename = OsStr::from_bytes(bytes).to_owned(); |
| if text_base == EXE_IMAGE_BASE as usize { |
| if let Ok(exe) = env::current_exe() { |
| filename = exe.into_os_string(); |
| } |
| } |
| let bytes = CStr::from_ptr(member_name_ptr).to_bytes(); |
| let member_name = OsStr::from_bytes(bytes).to_owned(); |
| if let Some(image) = xcoff::parse_image(filename.as_ref(), &member_name) { |
| ret.push(Library { |
| name: filename, |
| member_name, |
| segments: vec![LibrarySegment { |
| stated_virtual_memory_address: image.base as usize, |
| len: image.size, |
| }], |
| bias: (text_base + image.offset).wrapping_sub(image.base as usize), |
| }); |
| } |
| if (*current).ldinfo_next == 0 { |
| break; |
| } |
| current = (current as *mut libc::c_char).offset((*current).ldinfo_next as isize) |
| as *mut libc::ld_info; |
| } |
| } |
| return ret; |
| } |