diff options
Diffstat (limited to 'crates/ra_proc_macro_srv/src/dylib.rs')
-rw-r--r-- | crates/ra_proc_macro_srv/src/dylib.rs | 77 |
1 files changed, 39 insertions, 38 deletions
diff --git a/crates/ra_proc_macro_srv/src/dylib.rs b/crates/ra_proc_macro_srv/src/dylib.rs index ec63d587b..16bd7466e 100644 --- a/crates/ra_proc_macro_srv/src/dylib.rs +++ b/crates/ra_proc_macro_srv/src/dylib.rs | |||
@@ -1,10 +1,12 @@ | |||
1 | //! Handles dynamic library loading for proc macro | 1 | //! Handles dynamic library loading for proc macro |
2 | 2 | ||
3 | use crate::{proc_macro::bridge, rustc_server::TokenStream}; | 3 | use crate::{proc_macro::bridge, rustc_server::TokenStream}; |
4 | use std::fs::File; | ||
4 | use std::path::Path; | 5 | use std::path::Path; |
5 | 6 | ||
6 | use goblin::{mach::Mach, Object}; | 7 | use goblin::{mach::Mach, Object}; |
7 | use libloading::Library; | 8 | use libloading::Library; |
9 | use memmap::Mmap; | ||
8 | use ra_proc_macro::ProcMacroKind; | 10 | use ra_proc_macro::ProcMacroKind; |
9 | 11 | ||
10 | use std::io::Error as IoError; | 12 | use std::io::Error as IoError; |
@@ -16,55 +18,54 @@ fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> I | |||
16 | IoError::new(IoErrorKind::InvalidData, e) | 18 | IoError::new(IoErrorKind::InvalidData, e) |
17 | } | 19 | } |
18 | 20 | ||
19 | fn get_symbols_from_lib(file: &Path) -> Result<Vec<String>, IoError> { | 21 | fn is_derive_registrar_symbol(symbol: &str) -> bool { |
20 | let buffer = std::fs::read(file)?; | 22 | symbol.contains(NEW_REGISTRAR_SYMBOL) |
23 | } | ||
24 | |||
25 | fn find_registrar_symbol(file: &Path) -> Result<Option<String>, IoError> { | ||
26 | let file = File::open(file)?; | ||
27 | let buffer = unsafe { Mmap::map(&file)? }; | ||
21 | let object = Object::parse(&buffer).map_err(invalid_data_err)?; | 28 | let object = Object::parse(&buffer).map_err(invalid_data_err)?; |
22 | 29 | ||
23 | match object { | 30 | match object { |
24 | Object::Elf(elf) => { | 31 | Object::Elf(elf) => { |
25 | let symbols = elf.dynstrtab.to_vec().map_err(invalid_data_err)?; | 32 | let symbols = elf.dynstrtab.to_vec().map_err(invalid_data_err)?; |
26 | let names = symbols.iter().map(|s| s.to_string()).collect(); | 33 | let name = |
27 | Ok(names) | 34 | symbols.iter().find(|s| is_derive_registrar_symbol(s)).map(|s| s.to_string()); |
35 | Ok(name) | ||
28 | } | 36 | } |
29 | Object::PE(pe) => { | 37 | Object::PE(pe) => { |
30 | let symbol_names = | 38 | let name = pe |
31 | pe.exports.iter().flat_map(|s| s.name).map(|n| n.to_string()).collect(); | 39 | .exports |
32 | Ok(symbol_names) | 40 | .iter() |
41 | .flat_map(|s| s.name) | ||
42 | .find(|s| is_derive_registrar_symbol(s)) | ||
43 | .map(|s| s.to_string()); | ||
44 | Ok(name) | ||
33 | } | 45 | } |
34 | Object::Mach(mach) => match mach { | 46 | Object::Mach(Mach::Binary(binary)) => { |
35 | Mach::Binary(binary) => { | 47 | let exports = binary.exports().map_err(invalid_data_err)?; |
36 | let exports = binary.exports().map_err(invalid_data_err)?; | 48 | let name = exports |
37 | let names = exports | 49 | .iter() |
38 | .into_iter() | 50 | .map(|s| { |
39 | .map(|s| { | 51 | // In macos doc: |
40 | // In macos doc: | 52 | // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html |
41 | // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html | 53 | // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be |
42 | // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be | 54 | // prepended with an underscore. |
43 | // prepended with an underscore. | 55 | if s.name.starts_with("_") { |
44 | if s.name.starts_with("_") { | 56 | &s.name[1..] |
45 | s.name[1..].to_string() | 57 | } else { |
46 | } else { | 58 | &s.name |
47 | s.name | 59 | } |
48 | } | 60 | }) |
49 | }) | 61 | .find(|s| is_derive_registrar_symbol(s)) |
50 | .collect(); | 62 | .map(|s| s.to_string()); |
51 | Ok(names) | 63 | Ok(name) |
52 | } | 64 | } |
53 | Mach::Fat(_) => Ok(vec![]), | 65 | _ => Ok(None), |
54 | }, | ||
55 | Object::Archive(_) | Object::Unknown(_) => Ok(vec![]), | ||
56 | } | 66 | } |
57 | } | 67 | } |
58 | 68 | ||
59 | fn is_derive_registrar_symbol(symbol: &str) -> bool { | ||
60 | symbol.contains(NEW_REGISTRAR_SYMBOL) | ||
61 | } | ||
62 | |||
63 | fn find_registrar_symbol(file: &Path) -> Result<Option<String>, IoError> { | ||
64 | let symbols = get_symbols_from_lib(file)?; | ||
65 | Ok(symbols.into_iter().find(|s| is_derive_registrar_symbol(s))) | ||
66 | } | ||
67 | |||
68 | /// Loads dynamic library in platform dependent manner. | 69 | /// Loads dynamic library in platform dependent manner. |
69 | /// | 70 | /// |
70 | /// For unix, you have to use RTLD_DEEPBIND flag to escape problems described | 71 | /// For unix, you have to use RTLD_DEEPBIND flag to escape problems described |