Skip to content
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions compiler/rustc_session/src/filesearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -80,6 +81,50 @@ 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.
// Deref `current_dll_path` directly so that we can get the address of `current_dll_path`'s
// entry point in text section.
let addr = *(current_dll_path as *const 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 text_base = (*current).ldinfo_textorg as u64;
let text_end = text_base + (*current).ldinfo_textsize;
if (text_base..text_end).contains(&addr) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function descriptor lives in the data and not text segment, doesn't it? So we should look in there instead of text. (I wasn't aware of AIX function descriptors when I made the first comment asking why it would be in data).

Copy link
Copy Markdown
Contributor Author

@bzEq bzEq Mar 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the function descriptor lives in the data segment. In this context, the correctness should be the same for either using text or data segment. For sure, I'll update to use data segment which is less surprising than deferencing from the function descriptor.

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