Skip to content

Commit

Permalink
Rollup merge of rust-lang#109522 - bzEq:aix-current-dll-path, r=Nilst…
Browse files Browse the repository at this point in the history
…rieb

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.
  • Loading branch information
compiler-errors committed Mar 30, 2023
2 parents 987628e + 49f63eb commit bc7976e
Showing 1 changed file with 44 additions and 0 deletions.
44 changes: 44 additions & 0 deletions compiler/rustc_session/src/filesearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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)]
Expand Down

0 comments on commit bc7976e

Please sign in to comment.