rustc_codegen_llvm/back/
archive.rs1use std::ffi::{CStr, c_char, c_void};
4use std::io;
5
6use rustc_codegen_ssa::back::archive::{
7 ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER, ObjectReader,
8};
9use rustc_session::Session;
10
11use crate::llvm;
12
13pub(crate) struct LlvmArchiveBuilderBuilder;
14
15impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
16 fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> {
17 Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER))
19 }
20}
21
22static LLVM_OBJECT_READER: ObjectReader = ObjectReader {
26 get_symbols: get_llvm_object_symbols,
27 is_64_bit_object_file: llvm_is_64_bit_object_file,
28 is_ec_object_file: llvm_is_ec_object_file,
29 is_any_arm64_coff: llvm_is_any_arm64_coff,
30 get_xcoff_member_alignment: DEFAULT_OBJECT_READER.get_xcoff_member_alignment,
31};
32
33#[deny(unsafe_op_in_unsafe_fn)]
34fn get_llvm_object_symbols(
35 buf: &[u8],
36 f: &mut dyn FnMut(&[u8]) -> io::Result<()>,
37) -> io::Result<bool> {
38 let mut state = Box::new(f);
39
40 let err = unsafe {
41 llvm::LLVMRustGetSymbols(
42 buf.as_ptr(),
43 buf.len(),
44 (&raw mut *state) as *mut c_void,
45 callback,
46 error_callback,
47 )
48 };
49
50 if err.is_null() {
51 return Ok(true);
52 } else {
53 let error = unsafe { *Box::from_raw(err as *mut io::Error) };
54 if buf.starts_with(&[0xDE, 0xCE, 0x17, 0x0B]) || buf.starts_with(&[b'B', b'C', 0xC0, 0xDE])
57 {
58 eprintln!("warning: Failed to read symbol table from LLVM bitcode: {}", error);
69 return Ok(true);
70 } else {
71 return Err(error);
72 }
73 }
74
75 unsafe extern "C" fn callback(state: *mut c_void, symbol_name: *const c_char) -> *mut c_void {
76 let f = unsafe { &mut *(state as *mut &mut dyn FnMut(&[u8]) -> io::Result<()>) };
77 match f(unsafe { CStr::from_ptr(symbol_name) }.to_bytes()) {
78 Ok(()) => std::ptr::null_mut(),
79 Err(err) => Box::into_raw(Box::new(err) as Box<io::Error>) as *mut c_void,
80 }
81 }
82
83 unsafe extern "C" fn error_callback(error: *const c_char) -> *mut c_void {
84 let error = unsafe { CStr::from_ptr(error) };
85 Box::into_raw(Box::new(io::Error::new(
86 io::ErrorKind::Other,
87 format!("LLVM error: {}", error.to_string_lossy()),
88 )) as Box<io::Error>) as *mut c_void
89 }
90}
91
92fn llvm_is_64_bit_object_file(buf: &[u8]) -> bool {
93 unsafe { llvm::LLVMRustIs64BitSymbolicFile(buf.as_ptr(), buf.len()) }
94}
95
96fn llvm_is_ec_object_file(buf: &[u8]) -> bool {
97 unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) }
98}
99
100fn llvm_is_any_arm64_coff(buf: &[u8]) -> bool {
101 unsafe { llvm::LLVMRustIsAnyArm64Coff(buf.as_ptr(), buf.len()) }
102}