From 6e8a8282b8c131adb7f39909b9148687ea6c3b7b Mon Sep 17 00:00:00 2001 From: Kai Luo Date: Thu, 23 Mar 2023 16:50:49 +0800 Subject: [PATCH 1/4] Implement current_dll_path for AIX --- compiler/rustc_session/src/filesearch.rs | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) 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 { 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 { 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)] From 5aad51098d4bae73220aa58180cf562bccc4a213 Mon Sep 17 00:00:00 2001 From: Kai Luo Date: Fri, 24 Mar 2023 10:25:52 +0800 Subject: [PATCH 2/4] Avoid misalign --- compiler/rustc_session/src/filesearch.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 2c804f0f0a4..9c8a28a4a7e 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -85,15 +85,20 @@ fn current_dll_path() -> Result { #[cfg(target_os = "aix")] unsafe { let addr = current_dll_path as u64; - let mut buffer = vec![0i8; 4096]; + let mut buffer = vec![std::mem::zeroed::(); 64]; loop { - if libc::loadquery(libc::L_GETINFO, buffer.as_mut_ptr(), buffer.len() as u32) >= 0 { + if libc::loadquery( + libc::L_GETINFO, + buffer.as_mut_ptr() as *mut i8, + (std::mem::size_of::() * 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); + buffer.resize(buffer.len() * 2, std::mem::zeroed::()); } } let mut current = buffer.as_mut_ptr() as *mut libc::ld_info; From 82bfdc8aaa119b5d8484ae9c95f37c43509ef796 Mon Sep 17 00:00:00 2001 From: Kai Luo Date: Tue, 28 Mar 2023 10:50:23 +0800 Subject: [PATCH 3/4] Address comment --- compiler/rustc_session/src/filesearch.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 9c8a28a4a7e..5d8002b493e 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -84,7 +84,14 @@ fn current_dll_path() -> Result { #[cfg(target_os = "aix")] unsafe { - let addr = current_dll_path as u64; + // 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::(); 64]; loop { if libc::loadquery( @@ -103,11 +110,9 @@ fn current_dll_path() -> Result { } 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) { + if (text_base..text_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)); @@ -115,7 +120,8 @@ fn current_dll_path() -> Result { if (*current).ldinfo_next == 0 { break; } - current = ((current as u64) + ((*current).ldinfo_next) as u64) as *mut libc::ld_info; + 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)); } From 49f63eb021e03b5bdd09645d5e0e68bbeae781ee Mon Sep 17 00:00:00 2001 From: Kai Luo Date: Tue, 28 Mar 2023 17:53:34 +0800 Subject: [PATCH 4/4] Check data segment range --- compiler/rustc_session/src/filesearch.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 5d8002b493e..c6c910a3f4d 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -89,9 +89,8 @@ fn current_dll_path() -> Result { // * 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); + // The function descriptor is in the data section. + let addr = current_dll_path as u64; let mut buffer = vec![std::mem::zeroed::(); 64]; loop { if libc::loadquery( @@ -110,9 +109,9 @@ fn current_dll_path() -> Result { } 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) { + 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));