Skip to content

Commit 93322cc

Browse files
committed
Unrolled build for #161788 in rollup 162028
Rollup merge of #161788 - jnkel:check-llvm-version, r=saethlin Check to ensure we're running against the correct LLVM version The recent LLVM version bump exposed several cases of mishandling LLVM versions, both in-tree and downstream (#161335, #161377, #161572, #162013, https://rust-lang.zulipchat.com/#narrow/channel/122651-general/topic/opt-dist.20pipeline.20failure.20in.20MSYS2.20CI.20when.20compiling.2E.2E.2E/with/619077952). If the compiler is run against an incompatible LLVM version, the most common failure mode is a segfault within LLVM, often when looking up target information. This is not obvious to debug, so this PR adds an LLVM version check before initializing LLVM so that we can produce a clearer error. The second commit in this PR performs a `dladdr` lookup to print the path to the LLVM we're using. We already have code to do this for finding the sysroot, which I repurposed. However, I don't mind reverting this if it's too complex/risky. I would appreciate if someone with permissions could trigger a try build on AIX, Windows, and WASI as the second commit touches platform-specific code that I can't test locally. Before: ``` error: rustc interrupted by SIGSEGV, printing backtrace 0 librustc_driver-18049a207bb38ba8.dy 0x000000010e09e9b8 _RNvNtCsfNrGi27GPxl_17rustc_driver_impl14signal_handler17print_stack_trace + 140 1 libsystem_platform.dylib 0x0000000184c7d744 _sigtramp + 56 2 libLLVM.dylib 0x000000011a9e22e0 _ZNK4llvm15MCSubtargetInfo13checkFeaturesENS_9StringRefE + 40 3 librustc_driver-18049a207bb38ba8.dy 0x000000010e44c798 LLVMRustHasFeature + 104 4 librustc_driver-18049a207bb38ba8.dy 0x000000010e3c4e34 _RINvXs0_NtNtNtCsk8HLZXaYIk4_4core4iter8adapters3mapINtB6_3MapINtNtB8_7flatten7FlatMapINtNtB8_6filter6FilterINtNtNtBc_5slice4iter4IterTReNtNtCs79s86CIooN0_12rustc_target15target_features9StabilityRSB28_EENCINvNtCses5MBT5CPFU_17rustc_codegen_ssa15target_features24internal_target_featuresKj2_NCNvNtCsgXm2bqwPj4W_18rustc_codegen_llvm9llvm_util13target_config0NCB4G_s_0E0EIBO_INtNtNtNtCs99cPMl0y5Ob_3std11collections4hash3set8IntoIterB28_ENCNCB3h_s_00ENCB3h_s_0ENCINvXs8_NtCsdLs5ZkLaCXa_9hashbrown3setINtB7v_7HashSetNtNtCsSGoTcZpb2F_10rustc_span6symbol6SymbolNtCs5ZGGmiYplBm_10rustc_hash13FxBuildHasherEINtNtNtBa_6traits7collect6ExtendB8e_E6extendBX_E0ENtNtB9I_8iterator8Iterator4folduNCINvNvBar_8for_each4callTB8e_uENCINvXs1i_NtB7x_3mapINtBbD_7HashMapB8e_uB8V_EIB9E_Bbm_E6extendBN_E0E0EB4K_ + 880 5 librustc_driver-18049a207bb38ba8.dy 0x000000010e2ad884 _RINvXs1i_NtCsdLs5ZkLaCXa_9hashbrown3mapINtB7_7HashMapNtNtCsSGoTcZpb2F_10rustc_span6symbol6SymboluNtCs5ZGGmiYplBm_10rustc_hash13FxBuildHasherEINtNtNtNtCsk8HLZXaYIk4_4core4iter6traits7collect6ExtendTBP_uEE6extendINtNtNtB2m_8adapters3map3MapINtNtB3r_7flatten7FlatMapINtNtB3r_6filter6FilterINtNtNtB2o_5slice4iter4IterTReNtNtCs79s86CIooN0_12rustc_target15target_features9StabilityRSB52_EENCINvNtCses5MBT5CPFU_17rustc_codegen_ssa15target_features24internal_target_featuresKj2_NCNvNtCsgXm2bqwPj4W_18rustc_codegen_llvm9llvm_util13target_config0NCB7A_s_0E0EIB3n_INtNtNtNtCs99cPMl0y5Ob_3std11collections4hash3set8IntoIterB52_ENCNCB6b_s_00ENCB6b_s_0ENCINvXs8_NtB9_3setINtBaq_7HashSetBP_B1x_EIB2g_BP_E6extendB3O_E0EEB7E_ + 344 6 librustc_driver-18049a207bb38ba8.dy 0x000000010e2b1ec4 _RINvXs8_NtCsdLs5ZkLaCXa_9hashbrown3setINtB6_7HashSetNtNtCsSGoTcZpb2F_10rustc_span6symbol6SymbolNtCs5ZGGmiYplBm_10rustc_hash13FxBuildHasherEINtNtNtNtCsk8HLZXaYIk4_4core4iter6traits7collect6ExtendBO_E6extendINtNtNtB2k_8adapters7flatten7FlatMapINtNtB3m_6filter6FilterINtNtNtB2m_5slice4iter4IterTReNtNtCs79s86CIooN0_12rustc_target15target_features9StabilityRSB4G_EENCINvNtCses5MBT5CPFU_17rustc_codegen_ssa15target_features24internal_target_featuresKj2_NCNvNtCsgXm2bqwPj4W_18rustc_codegen_llvm9llvm_util13target_config0NCB7e_s_0E0EINtNtB3m_3map3MapINtNtNtNtCs99cPMl0y5Ob_3std11collections4hash3set8IntoIterB4G_ENCNCB5P_s_00ENCB5P_s_0EEB7i_ + 68 7 librustc_driver-18049a207bb38ba8.dy 0x000000010e2bfa90 _RINvNtCses5MBT5CPFU_17rustc_codegen_ssa15target_features24internal_target_featuresKj2_NCNvNtCsgXm2bqwPj4W_18rustc_codegen_llvm9llvm_util13target_config0NCB1o_s_0EB1s_ + 148 8 librustc_driver-18049a207bb38ba8.dy 0x000000010e2fb918 _RNvNtCsgXm2bqwPj4W_18rustc_codegen_llvm9llvm_util13target_config + 68 9 librustc_driver-18049a207bb38ba8.dy 0x000000010e292fb0 _RNvNtCs6x0lOIkloew_15rustc_interface4util17add_configuration + 48 10 librustc_driver-18049a207bb38ba8.dy 0x000000010e06b204 _RINvMs_Csfkr8sXZt4uY_10scoped_tlsINtB5_9ScopedKeyNtCsSGoTcZpb2F_10rustc_span14SessionGlobalsE3setNCNCNCINvNtCs6x0lOIkloew_15rustc_interface4util26run_in_thread_with_globalsNCINvB1G_31run_in_thread_pool_with_globalsNCINvNtB1I_9interface12run_compileruNCNvCsfNrGi27GPxl_17rustc_driver_impl12run_compiler0Es0_0uE0uE000uEB44_ + 1112 11 librustc_driver-18049a207bb38ba8.dy 0x000000010e090914 _RINvCsSGoTcZpb2F_10rustc_span27create_session_globals_thenuNCNCNCINvNtCs6x0lOIkloew_15rustc_interface4util26run_in_thread_with_globalsNCINvB14_31run_in_thread_pool_with_globalsNCINvNtB16_9interface12run_compileruNCNvCsfNrGi27GPxl_17rustc_driver_impl12run_compiler0Es0_0uE0uE000EB3s_ + 168 12 librustc_driver-18049a207bb38ba8.dy 0x000000010e07823c _RINvNtNtCs99cPMl0y5Ob_3std3sys9backtrace28___rust_begin_short_backtraceNCNCINvNtCs6x0lOIkloew_15rustc_interface4util26run_in_thread_with_globalsNCINvB1e_31run_in_thread_pool_with_globalsNCINvNtB1g_9interface12run_compileruNCNvCsfNrGi27GPxl_17rustc_driver_impl12run_compiler0Es0_0uE0uE00uEB3C_ + 112 13 librustc_driver-18049a207bb38ba8.dy 0x000000010e04efa4 _RNSNvYNCINvNtNtCs99cPMl0y5Ob_3std6thread9lifecycle15spawn_uncheckedNCNCINvNtCs6x0lOIkloew_15rustc_interface4util26run_in_thread_with_globalsNCINvB1a_31run_in_thread_pool_with_globalsNCINvNtB1c_9interface12run_compileruNCNvCsfNrGi27GPxl_17rustc_driver_impl12run_compiler0Es0_0uE0uE00uEs_0INtNtNtCsk8HLZXaYIk4_4core3ops8function6FnOnceuE9call_once6vtableB3y_ + 208 14 librustc_driver-18049a207bb38ba8.dy 0x0000000111697118 _RNvNvMs0_NtNtNtCs99cPMl0y5Ob_3std3sys6thread4unixNtB7_6Thread3new12thread_start + 392 15 libsystem_pthread.dylib 0x0000000184c73c58 _pthread_start + 136 16 libsystem_pthread.dylib 0x0000000184c6ec1c thread_start + 8 note: we would appreciate a report at https://github.com/rust-lang/rust help: you can increase rustc's stack size by setting RUST_MIN_STACK=33554432 ``` After: ``` thread 'rustc' (3568488) panicked at compiler/rustc_codegen_llvm/src/llvm_util.rs:59:13: LLVM version mismatch: this compiler was built for LLVM 23, but LLVM 22.1.8 was found at /Users/keljonathan/code/rust/build/aarch64-apple-darwin/stage0/lib/libLLVM.dylib stack backtrace: 0: __rustc::rust_begin_unwind at /rustc/08d5b675a9b2abdca5e2fe4eabe0e07bbda15d49/library/std/src/panicking.rs:679:5 1: core::panicking::panic_fmt at /rustc/08d5b675a9b2abdca5e2fe4eabe0e07bbda15d49/library/core/src/panicking.rs:80:14 2: configure_llvm at ./compiler/rustc_codegen_llvm/src/llvm_util.rs:59:13 3: {closure#0} at ./compiler/rustc_codegen_llvm/src/llvm_util.rs:35:13 4: {closure#0}<rustc_codegen_llvm::llvm_util::init::{closure_env#0}> at /rustc/08d5b675a9b2abdca5e2fe4eabe0e07bbda15d49/library/std/src/sync/once.rs:166:41 5: <std::sys::sync::once::queue::Once>::call at /rustc/08d5b675a9b2abdca5e2fe4eabe0e07bbda15d49/library/std/src/sys/sync/once/queue.rs:225:21 6: call_once<rustc_codegen_llvm::llvm_util::init::{closure_env#0}> at /rustc/08d5b675a9b2abdca5e2fe4eabe0e07bbda15d49/library/std/src/sync/once.rs:166:20 7: init at ./compiler/rustc_codegen_llvm/src/llvm_util.rs:34:14 8: init at ./compiler/rustc_codegen_llvm/src/lib.rs:223:9 9: {closure#2}<(), rustc_driver_impl::run_compiler::{closure_env#0}> at ./compiler/rustc_interface/src/interface.rs:440:29 10: {closure#0}<rustc_interface::interface::run_compiler::{closure_env#2}<(), rustc_driver_impl::run_compiler::{closure_env#0}>, ()> at ./compiler/rustc_interface/src/util.rs:223:17 11: {closure#0}<rustc_interface::util::run_in_thread_pool_with_globals::{closure_env#0}<rustc_interface::interface::run_compiler::{closure_env#2}<(), rustc_driver_impl::run_compiler::{closure_env#0}>, ()>, ()> at ./compiler/rustc_interface/src/util.rs:180:24 12: set<rustc_span::SessionGlobals, rustc_interface::util::run_in_thread_with_globals::{closure#0}::{closure#0}::{closure_env#0}<rustc_interface::util::run_in_thread_pool_with_globals::{closure_env#0}<rustc_interface::interface::run_compiler::{closure_env#2}<(), rustc_driver_impl::run_compiler::{closure_env#0}>, ()>, ()>, ()> at /Users/keljonathan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scoped-tls-1.0.1/src/lib.rs:137:9 13: create_session_globals_then<(), rustc_interface::util::run_in_thread_with_globals::{closure#0}::{closure#0}::{closure_env#0}<rustc_interface::util::run_in_thread_pool_with_globals::{closure_env#0}<rustc_interface::interface::run_compiler::{closure_env#2}<(), rustc_driver_impl::run_compiler::{closure_env#0}>, ()>, ()>> at ./compiler/rustc_span/src/lib.rs:156:21 14: {closure#0}<rustc_interface::util::run_in_thread_pool_with_globals::{closure_env#0}<rustc_interface::interface::run_compiler::{closure_env#2}<(), rustc_driver_impl::run_compiler::{closure_env#0}>, ()>, ()> at ./compiler/rustc_interface/src/util.rs:176:17 note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. error: the compiler unexpectedly panicked. This is a bug note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md note: please make sure that you have updated to the latest nightly note: please attach the file at `/Users/keljonathan/code/rust/rustc-ice-2026-08-25T22_23_11-1423.txt` to your bug report note: rustc 1.100.0-dev running on aarch64-apple-darwin note: compiler flags: -C rpath -C debuginfo=0 -Z unstable-options query stack during panic: end of query stack ```
2 parents 9085017 + 5841e10 commit 93322cc

3 files changed

Lines changed: 104 additions & 76 deletions

File tree

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,8 @@ unsafe extern "C" {
894894
SLen: c_uint,
895895
) -> MetadataKindId;
896896

897+
pub(crate) fn LLVMGetVersion(major: &mut c_uint, minor: &mut c_uint, patch: &mut c_uint);
898+
897899
pub(crate) fn LLVMDisposeTargetMachine(T: ptr::NonNull<TargetMachine>);
898900

899901
// Create modules.

compiler/rustc_codegen_llvm/src/llvm_util.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,31 @@ unsafe fn configure_llvm(sess: &Session) {
4848
let mut llvm_c_strs = Vec::with_capacity(n_args + 1);
4949
let mut llvm_args = Vec::with_capacity(n_args + 1);
5050

51+
// Check to ensure we're running against the correct LLVM version.
52+
unsafe {
53+
let mut llvm_major = 0;
54+
let mut llvm_minor = 0;
55+
let mut llvm_patch = 0;
56+
llvm::LLVMGetVersion(&mut llvm_major, &mut llvm_minor, &mut llvm_patch);
57+
let expected_version = llvm::LLVMRustVersionMajor();
58+
if llvm_major != expected_version {
59+
panic!(
60+
concat!(
61+
"LLVM version mismatch: this compiler was built for LLVM {}, ",
62+
"but LLVM {}.{}.{} was found{}"
63+
),
64+
expected_version,
65+
llvm_major,
66+
llvm_minor,
67+
llvm_patch,
68+
match rustc_session::filesearch::dll_path(llvm::LLVMGetVersion as *mut _) {
69+
Ok(path) => format!(" at {}", path.display()),
70+
Err(_) => String::new(),
71+
}
72+
);
73+
}
74+
}
75+
5176
unsafe {
5277
llvm::LLVMRustInstallErrorHandlers();
5378
}

compiler/rustc_session/src/filesearch.rs

Lines changed: 77 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -146,86 +146,78 @@ pub fn make_target_bin_path(sysroot: &Path, target_triple: &str) -> PathBuf {
146146
sysroot.join(rustlib_path).join("bin")
147147
}
148148

149+
/// Attempts to find the path to the dynamic library containing a function.
150+
///
151+
/// SAFETY: `function` must be a valid pointer to some function.
149152
#[cfg(unix)]
150-
fn current_dll_path() -> Result<PathBuf, String> {
151-
use std::sync::OnceLock;
153+
pub unsafe fn dll_path(function: *mut std::ffi::c_void) -> Result<PathBuf, String> {
154+
use std::ffi::{CStr, OsStr};
155+
use std::os::unix::prelude::*;
152156

153-
// This is somewhat expensive relative to other work when compiling `fn main() {}` as `dladdr`
154-
// needs to iterate over the symbol table of librustc_driver.so until it finds a match.
155-
// As such cache this to avoid recomputing if we try to get the sysroot in multiple places.
156-
static CURRENT_DLL_PATH: OnceLock<Result<PathBuf, String>> = OnceLock::new();
157-
CURRENT_DLL_PATH
158-
.get_or_init(|| {
159-
use std::ffi::{CStr, OsStr};
160-
use std::os::unix::prelude::*;
161-
162-
#[cfg(not(target_os = "aix"))]
163-
unsafe {
164-
let addr = current_dll_path as fn() -> Result<PathBuf, String> as *mut _;
165-
let mut info = std::mem::zeroed();
166-
if libc::dladdr(addr, &mut info) == 0 {
167-
return Err("dladdr failed".into());
157+
#[cfg(not(target_os = "aix"))]
158+
unsafe {
159+
let mut info = std::mem::zeroed();
160+
if libc::dladdr(function, &mut info) == 0 {
161+
return Err("dladdr failed".into());
162+
}
163+
#[cfg(target_os = "cygwin")]
164+
let fname_ptr = info.dli_fname.as_ptr();
165+
#[cfg(not(target_os = "cygwin"))]
166+
let fname_ptr = {
167+
assert!(!info.dli_fname.is_null(), "dli_fname cannot be null");
168+
info.dli_fname
169+
};
170+
let bytes = CStr::from_ptr(fname_ptr).to_bytes();
171+
let os = OsStr::from_bytes(bytes);
172+
try_canonicalize(Path::new(os)).map_err(|e| e.to_string())
173+
}
174+
175+
#[cfg(target_os = "aix")]
176+
unsafe {
177+
// On AIX, the symbol references a function descriptor.
178+
// A function descriptor is consisted of (See https://reviews.llvm.org/D62532)
179+
// * The address of the entry point of the function.
180+
// * The TOC base address for the function.
181+
// * The environment pointer.
182+
// The function descriptor is in the data section.
183+
let addr = function as u64;
184+
let mut buffer = vec![std::mem::zeroed::<libc::ld_info>(); 64];
185+
loop {
186+
if libc::loadquery(
187+
libc::L_GETINFO,
188+
buffer.as_mut_ptr() as *mut libc::c_void,
189+
(size_of::<libc::ld_info>() * buffer.len()) as u32,
190+
) >= 0
191+
{
192+
break;
193+
} else {
194+
if std::io::Error::last_os_error().raw_os_error().unwrap() != libc::ENOMEM {
195+
return Err("loadquery failed".into());
168196
}
169-
#[cfg(target_os = "cygwin")]
170-
let fname_ptr = info.dli_fname.as_ptr();
171-
#[cfg(not(target_os = "cygwin"))]
172-
let fname_ptr = {
173-
assert!(!info.dli_fname.is_null(), "dli_fname cannot be null");
174-
info.dli_fname
175-
};
176-
let bytes = CStr::from_ptr(fname_ptr).to_bytes();
197+
buffer.resize(buffer.len() * 2, std::mem::zeroed::<libc::ld_info>());
198+
}
199+
}
200+
let mut current = buffer.as_mut_ptr() as *mut libc::ld_info;
201+
loop {
202+
let data_base = (*current).ldinfo_dataorg as u64;
203+
let data_end = data_base + (*current).ldinfo_datasize;
204+
if (data_base..data_end).contains(&addr) {
205+
let bytes = CStr::from_ptr(&(*current).ldinfo_filename[0]).to_bytes();
177206
let os = OsStr::from_bytes(bytes);
178-
try_canonicalize(Path::new(os)).map_err(|e| e.to_string())
207+
return try_canonicalize(Path::new(os)).map_err(|e| e.to_string());
179208
}
180-
181-
#[cfg(target_os = "aix")]
182-
unsafe {
183-
// On AIX, the symbol `current_dll_path` references a function descriptor.
184-
// A function descriptor is consisted of (See https://reviews.llvm.org/D62532)
185-
// * The address of the entry point of the function.
186-
// * The TOC base address for the function.
187-
// * The environment pointer.
188-
// The function descriptor is in the data section.
189-
let addr = current_dll_path as u64;
190-
let mut buffer = vec![std::mem::zeroed::<libc::ld_info>(); 64];
191-
loop {
192-
if libc::loadquery(
193-
libc::L_GETINFO,
194-
buffer.as_mut_ptr() as *mut libc::c_void,
195-
(size_of::<libc::ld_info>() * buffer.len()) as u32,
196-
) >= 0
197-
{
198-
break;
199-
} else {
200-
if std::io::Error::last_os_error().raw_os_error().unwrap() != libc::ENOMEM {
201-
return Err("loadquery failed".into());
202-
}
203-
buffer.resize(buffer.len() * 2, std::mem::zeroed::<libc::ld_info>());
204-
}
205-
}
206-
let mut current = buffer.as_mut_ptr() as *mut libc::ld_info;
207-
loop {
208-
let data_base = (*current).ldinfo_dataorg as u64;
209-
let data_end = data_base + (*current).ldinfo_datasize;
210-
if (data_base..data_end).contains(&addr) {
211-
let bytes = CStr::from_ptr(&(*current).ldinfo_filename[0]).to_bytes();
212-
let os = OsStr::from_bytes(bytes);
213-
return try_canonicalize(Path::new(os)).map_err(|e| e.to_string());
214-
}
215-
if (*current).ldinfo_next == 0 {
216-
break;
217-
}
218-
current = (current as *mut i8).offset((*current).ldinfo_next as isize)
219-
as *mut libc::ld_info;
220-
}
221-
return Err(format!("current dll's address {} is not in the load map", addr));
209+
if (*current).ldinfo_next == 0 {
210+
break;
222211
}
223-
})
224-
.clone()
212+
current =
213+
(current as *mut i8).offset((*current).ldinfo_next as isize) as *mut libc::ld_info;
214+
}
215+
return Err(format!("current dll's address {} is not in the load map", addr));
216+
}
225217
}
226218

227219
#[cfg(windows)]
228-
fn current_dll_path() -> Result<PathBuf, String> {
220+
pub unsafe fn dll_path(function: *mut std::ffi::c_void) -> Result<PathBuf, String> {
229221
use std::ffi::OsString;
230222
use std::io;
231223
use std::os::windows::prelude::*;
@@ -240,10 +232,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
240232
unsafe {
241233
GetModuleHandleExW(
242234
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
243-
PCWSTR(
244-
current_dll_path as fn() -> Result<std::path::PathBuf, std::string::String>
245-
as *mut u16,
246-
),
235+
PCWSTR(function as *mut u16),
247236
&mut module,
248237
)
249238
}
@@ -269,8 +258,20 @@ fn current_dll_path() -> Result<PathBuf, String> {
269258
}
270259

271260
#[cfg(target_os = "wasi")]
261+
pub unsafe fn dll_path(function: *mut std::ffi::c_void) -> Result<PathBuf, String> {
262+
Err("dll_path is not supported on WASI".to_string())
263+
}
264+
272265
fn current_dll_path() -> Result<PathBuf, String> {
273-
Err("current_dll_path is not supported on WASI".to_string())
266+
use std::sync::OnceLock;
267+
268+
// This is somewhat expensive relative to other work when compiling `fn main() {}` as `dladdr`
269+
// needs to iterate over the symbol table of librustc_driver.so until it finds a match.
270+
// As such cache this to avoid recomputing if we try to get the sysroot in multiple places.
271+
static CURRENT_DLL_PATH: OnceLock<Result<PathBuf, String>> = OnceLock::new();
272+
CURRENT_DLL_PATH
273+
.get_or_init(|| unsafe { dll_path(current_dll_path as fn() -> _ as *mut _) })
274+
.clone()
274275
}
275276

276277
/// This function checks if sysroot is found using env::args().next(), and if it

0 commit comments

Comments
 (0)