Skip to content

Commit bc7976e

Browse files
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.
2 parents 987628e + 49f63eb commit bc7976e

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

compiler/rustc_session/src/filesearch.rs

+44
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
6868
use std::ffi::{CStr, OsStr};
6969
use std::os::unix::prelude::*;
7070

71+
#[cfg(not(target_os = "aix"))]
7172
unsafe {
7273
let addr = current_dll_path as usize as *mut _;
7374
let mut info = std::mem::zeroed();
@@ -81,6 +82,49 @@ fn current_dll_path() -> Result<PathBuf, String> {
8182
let os = OsStr::from_bytes(bytes);
8283
Ok(PathBuf::from(os))
8384
}
85+
86+
#[cfg(target_os = "aix")]
87+
unsafe {
88+
// On AIX, the symbol `current_dll_path` references a function descriptor.
89+
// A function descriptor is consisted of (See https://reviews.llvm.org/D62532)
90+
// * The address of the entry point of the function.
91+
// * The TOC base address for the function.
92+
// * The environment pointer.
93+
// The function descriptor is in the data section.
94+
let addr = current_dll_path as u64;
95+
let mut buffer = vec![std::mem::zeroed::<libc::ld_info>(); 64];
96+
loop {
97+
if libc::loadquery(
98+
libc::L_GETINFO,
99+
buffer.as_mut_ptr() as *mut i8,
100+
(std::mem::size_of::<libc::ld_info>() * buffer.len()) as u32,
101+
) >= 0
102+
{
103+
break;
104+
} else {
105+
if std::io::Error::last_os_error().raw_os_error().unwrap() != libc::ENOMEM {
106+
return Err("loadquery failed".into());
107+
}
108+
buffer.resize(buffer.len() * 2, std::mem::zeroed::<libc::ld_info>());
109+
}
110+
}
111+
let mut current = buffer.as_mut_ptr() as *mut libc::ld_info;
112+
loop {
113+
let data_base = (*current).ldinfo_dataorg as u64;
114+
let data_end = data_base + (*current).ldinfo_datasize;
115+
if (data_base..data_end).contains(&addr) {
116+
let bytes = CStr::from_ptr(&(*current).ldinfo_filename[0]).to_bytes();
117+
let os = OsStr::from_bytes(bytes);
118+
return Ok(PathBuf::from(os));
119+
}
120+
if (*current).ldinfo_next == 0 {
121+
break;
122+
}
123+
current =
124+
(current as *mut i8).offset((*current).ldinfo_next as isize) as *mut libc::ld_info;
125+
}
126+
return Err(format!("current dll's address {} is not in the load map", addr));
127+
}
84128
}
85129

86130
#[cfg(windows)]

0 commit comments

Comments
 (0)