about summary refs log tree commit diff
path: root/compiler/rustc_session
diff options
context:
space:
mode:
authorKai Luo <lkail@cn.ibm.com>2023-03-23 16:50:49 +0800
committerKai Luo <lkail@cn.ibm.com>2023-03-23 16:50:49 +0800
commit6e8a8282b8c131adb7f39909b9148687ea6c3b7b (patch)
treef3f8e8cc7059a84ca73e4533852536f4fa121b07 /compiler/rustc_session
parent1c771fec3329ef1d8c66697daf9517501d0c129a (diff)
downloadrust-6e8a8282b8c131adb7f39909b9148687ea6c3b7b.tar.gz
rust-6e8a8282b8c131adb7f39909b9148687ea6c3b7b.zip
Implement current_dll_path for AIX
Diffstat (limited to 'compiler/rustc_session')
-rw-r--r--compiler/rustc_session/src/filesearch.rs34
1 files changed, 34 insertions, 0 deletions
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index e734599cbfc..2c804f0f0a4 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -67,6 +67,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();
@@ -80,6 +81,39 @@ fn current_dll_path() -> Result<PathBuf, String> {
         let os = OsStr::from_bytes(bytes);
         Ok(PathBuf::from(os))
     }
+
+    #[cfg(target_os = "aix")]
+    unsafe {
+        let addr = current_dll_path as u64;
+        let mut buffer = vec![0i8; 4096];
+        loop {
+            if libc::loadquery(libc::L_GETINFO, buffer.as_mut_ptr(), 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, 0i8);
+            }
+        }
+        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;
+            let text_base = (*current).ldinfo_textorg as u64;
+            let text_end = text_base + (*current).ldinfo_textsize;
+            if (data_base <= addr && addr < data_end) || (text_base <= addr && addr < text_end) {
+                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 u64) + ((*current).ldinfo_next) as u64) as *mut libc::ld_info;
+        }
+        return Err(format!("current dll's address {} is not in the load map", addr));
+    }
 }
 
 #[cfg(windows)]