diff options
| author | Michael Goulet <michael@errs.io> | 2023-03-30 12:42:18 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-30 12:42:18 -0700 |
| commit | bc7976eee562546d6eff72d4227cea15a17afe01 (patch) | |
| tree | 7bebffc0a9b5ae7c4d4e96bc330c5dcfef27df39 /compiler/rustc_session/src | |
| parent | 987628e82b497efef5e0ff9d1865f16d282c54e9 (diff) | |
| parent | 49f63eb021e03b5bdd09645d5e0e68bbeae781ee (diff) | |
| download | rust-bc7976eee562546d6eff72d4227cea15a17afe01.tar.gz rust-bc7976eee562546d6eff72d4227cea15a17afe01.zip | |
Rollup merge of #109522 - bzEq:aix-current-dll-path, r=Nilstrieb
Implement current_dll_path for AIX AIX doesn't feature `dladdr`, use `loadquery` instead. `loadquery` is documented in https://www.ibm.com/docs/en/aix/7.2?topic=l-loadquery-subroutine.
Diffstat (limited to 'compiler/rustc_session/src')
| -rw-r--r-- | compiler/rustc_session/src/filesearch.rs | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 2404928b254..40879db49de 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -68,6 +68,7 @@ fn current_dll_path() -> Result<PathBuf, String> { use std::ffi::{CStr, OsStr}; use std::os::unix::prelude::*; + #[cfg(not(target_os = "aix"))] unsafe { let addr = current_dll_path as usize as *mut _; let mut info = std::mem::zeroed(); @@ -81,6 +82,49 @@ fn current_dll_path() -> Result<PathBuf, String> { let os = OsStr::from_bytes(bytes); Ok(PathBuf::from(os)) } + + #[cfg(target_os = "aix")] + unsafe { + // On AIX, the symbol `current_dll_path` references a function descriptor. + // A function descriptor is consisted of (See https://reviews.llvm.org/D62532) + // * The address of the entry point of the function. + // * The TOC base address for the function. + // * The environment pointer. + // The function descriptor is in the data section. + let addr = current_dll_path as u64; + let mut buffer = vec![std::mem::zeroed::<libc::ld_info>(); 64]; + loop { + if libc::loadquery( + libc::L_GETINFO, + buffer.as_mut_ptr() as *mut i8, + (std::mem::size_of::<libc::ld_info>() * buffer.len()) as u32, + ) >= 0 + { + break; + } else { + if std::io::Error::last_os_error().raw_os_error().unwrap() != libc::ENOMEM { + return Err("loadquery failed".into()); + } + buffer.resize(buffer.len() * 2, std::mem::zeroed::<libc::ld_info>()); + } + } + let mut current = buffer.as_mut_ptr() as *mut libc::ld_info; + loop { + let data_base = (*current).ldinfo_dataorg as u64; + let data_end = data_base + (*current).ldinfo_datasize; + if (data_base..data_end).contains(&addr) { + let bytes = CStr::from_ptr(&(*current).ldinfo_filename[0]).to_bytes(); + let os = OsStr::from_bytes(bytes); + return Ok(PathBuf::from(os)); + } + if (*current).ldinfo_next == 0 { + break; + } + current = + (current as *mut i8).offset((*current).ldinfo_next as isize) as *mut libc::ld_info; + } + return Err(format!("current dll's address {} is not in the load map", addr)); + } } #[cfg(windows)] |
