Don't error when adding a staticlib with bitcode files compiled by newer LLVM

This commit is contained in:
bjorn3 2025-02-14 09:19:10 +00:00
parent 905b1bf1cc
commit 736ef0a4ce

View File

@ -132,23 +132,39 @@ fn get_llvm_object_symbols(
if err.is_null() {
return Ok(true);
} else {
return Err(unsafe { *Box::from_raw(err as *mut io::Error) });
let error = unsafe { *Box::from_raw(err as *mut String) };
// These are the magic constants for LLVM bitcode files:
// https://github.com/llvm/llvm-project/blob/7eadc1960d199676f04add402bb0aa6f65b7b234/llvm/lib/BinaryFormat/Magic.cpp#L90-L97
if buf.starts_with(&[0xDE, 0xCE, 0x17, 0x0B]) || buf.starts_with(&[b'B', b'C', 0xC0, 0xDE])
{
// For LLVM bitcode, failure to read the symbols is not fatal. The bitcode may have been
// produced by a newer LLVM version that the one linked to rustc. This is fine provided
// that the linker does use said newer LLVM version. We skip writing the symbols for the
// bitcode to the symbol table of the archive. Traditional linkers don't like this, but
// newer linkers like lld, mold and wild ignore the symbol table anyway, so if they link
// against a new enough LLVM it will work out in the end.
// LLVM's archive writer also has this same behavior of only warning about invalid
// bitcode since https://github.com/llvm/llvm-project/pull/96848
// We don't have access to the DiagCtxt here to produce a nice warning in the correct format.
eprintln!("warning: Failed to read symbol table from LLVM bitcode: {}", error);
return Ok(true);
} else {
return Err(io::Error::new(io::ErrorKind::Other, format!("LLVM error: {}", error)));
}
}
unsafe extern "C" fn callback(state: *mut c_void, symbol_name: *const c_char) -> *mut c_void {
let f = unsafe { &mut *(state as *mut &mut dyn FnMut(&[u8]) -> io::Result<()>) };
match f(unsafe { CStr::from_ptr(symbol_name) }.to_bytes()) {
Ok(()) => std::ptr::null_mut(),
Err(err) => Box::into_raw(Box::new(err)) as *mut c_void,
Err(err) => Box::into_raw(Box::new(err.to_string()) as Box<String>) as *mut c_void,
}
}
unsafe extern "C" fn error_callback(error: *const c_char) -> *mut c_void {
let error = unsafe { CStr::from_ptr(error) };
Box::into_raw(Box::new(io::Error::new(
io::ErrorKind::Other,
format!("LLVM error: {}", error.to_string_lossy()),
))) as *mut c_void
Box::into_raw(Box::new(error.to_string_lossy().into_owned()) as Box<String>) as *mut c_void
}
}