diff options
Diffstat (limited to 'crates/ra_proc_macro_srv')
-rw-r--r-- | crates/ra_proc_macro_srv/src/dylib.rs | 54 |
1 files changed, 30 insertions, 24 deletions
diff --git a/crates/ra_proc_macro_srv/src/dylib.rs b/crates/ra_proc_macro_srv/src/dylib.rs index 8403187b9..ec63d587b 100644 --- a/crates/ra_proc_macro_srv/src/dylib.rs +++ b/crates/ra_proc_macro_srv/src/dylib.rs | |||
@@ -7,28 +7,35 @@ use goblin::{mach::Mach, Object}; | |||
7 | use libloading::Library; | 7 | use libloading::Library; |
8 | use ra_proc_macro::ProcMacroKind; | 8 | use ra_proc_macro::ProcMacroKind; |
9 | 9 | ||
10 | static NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; | 10 | use std::io::Error as IoError; |
11 | use std::io::ErrorKind as IoErrorKind; | ||
11 | 12 | ||
12 | fn get_symbols_from_lib(file: &Path) -> Option<Vec<String>> { | 13 | const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; |
13 | let buffer = std::fs::read(file).ok()?; | ||
14 | let object = Object::parse(&buffer).ok()?; | ||
15 | 14 | ||
16 | return match object { | 15 | fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> IoError { |
16 | IoError::new(IoErrorKind::InvalidData, e) | ||
17 | } | ||
18 | |||
19 | fn get_symbols_from_lib(file: &Path) -> Result<Vec<String>, IoError> { | ||
20 | let buffer = std::fs::read(file)?; | ||
21 | let object = Object::parse(&buffer).map_err(invalid_data_err)?; | ||
22 | |||
23 | match object { | ||
17 | Object::Elf(elf) => { | 24 | Object::Elf(elf) => { |
18 | let symbols = elf.dynstrtab.to_vec().ok()?; | 25 | let symbols = elf.dynstrtab.to_vec().map_err(invalid_data_err)?; |
19 | let names = symbols.iter().map(|s| s.to_string()).collect(); | 26 | let names = symbols.iter().map(|s| s.to_string()).collect(); |
20 | Some(names) | 27 | Ok(names) |
21 | } | 28 | } |
22 | Object::PE(pe) => { | 29 | Object::PE(pe) => { |
23 | let symbol_names = | 30 | let symbol_names = |
24 | pe.exports.iter().flat_map(|s| s.name).map(|n| n.to_string()).collect(); | 31 | pe.exports.iter().flat_map(|s| s.name).map(|n| n.to_string()).collect(); |
25 | Some(symbol_names) | 32 | Ok(symbol_names) |
26 | } | 33 | } |
27 | Object::Mach(mach) => match mach { | 34 | Object::Mach(mach) => match mach { |
28 | Mach::Binary(binary) => { | 35 | Mach::Binary(binary) => { |
29 | let exports = binary.exports().ok()?; | 36 | let exports = binary.exports().map_err(invalid_data_err)?; |
30 | let names = exports | 37 | let names = exports |
31 | .iter() | 38 | .into_iter() |
32 | .map(|s| { | 39 | .map(|s| { |
33 | // In macos doc: | 40 | // In macos doc: |
34 | // 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 |
@@ -37,26 +44,25 @@ fn get_symbols_from_lib(file: &Path) -> Option<Vec<String>> { | |||
37 | if s.name.starts_with("_") { | 44 | if s.name.starts_with("_") { |
38 | s.name[1..].to_string() | 45 | s.name[1..].to_string() |
39 | } else { | 46 | } else { |
40 | s.name.to_string() | 47 | s.name |
41 | } | 48 | } |
42 | }) | 49 | }) |
43 | .collect(); | 50 | .collect(); |
44 | Some(names) | 51 | Ok(names) |
45 | } | 52 | } |
46 | Mach::Fat(_) => None, | 53 | Mach::Fat(_) => Ok(vec![]), |
47 | }, | 54 | }, |
48 | Object::Archive(_) | Object::Unknown(_) => None, | 55 | Object::Archive(_) | Object::Unknown(_) => Ok(vec![]), |
49 | }; | 56 | } |
50 | } | 57 | } |
51 | 58 | ||
52 | fn is_derive_registrar_symbol(symbol: &str) -> bool { | 59 | fn is_derive_registrar_symbol(symbol: &str) -> bool { |
53 | symbol.contains(NEW_REGISTRAR_SYMBOL) | 60 | symbol.contains(NEW_REGISTRAR_SYMBOL) |
54 | } | 61 | } |
55 | 62 | ||
56 | fn find_registrar_symbol(file: &Path) -> Option<String> { | 63 | fn find_registrar_symbol(file: &Path) -> Result<Option<String>, IoError> { |
57 | let symbols = get_symbols_from_lib(file)?; | 64 | let symbols = get_symbols_from_lib(file)?; |
58 | 65 | Ok(symbols.into_iter().find(|s| is_derive_registrar_symbol(s))) | |
59 | symbols.iter().find(|s| is_derive_registrar_symbol(s)).map(|s| s.clone()) | ||
60 | } | 66 | } |
61 | 67 | ||
62 | /// Loads dynamic library in platform dependent manner. | 68 | /// Loads dynamic library in platform dependent manner. |
@@ -92,14 +98,14 @@ struct ProcMacroLibraryLibloading { | |||
92 | } | 98 | } |
93 | 99 | ||
94 | impl ProcMacroLibraryLibloading { | 100 | impl ProcMacroLibraryLibloading { |
95 | fn open(file: &Path) -> Result<Self, String> { | 101 | fn open(file: &Path) -> Result<Self, IoError> { |
96 | let symbol_name = find_registrar_symbol(file) | 102 | let symbol_name = find_registrar_symbol(file)? |
97 | .ok_or(format!("Cannot find registrar symbol in file {:?}", file))?; | 103 | .ok_or(invalid_data_err(format!("Cannot find registrar symbol in file {:?}", file)))?; |
98 | 104 | ||
99 | let lib = load_library(file).map_err(|e| e.to_string())?; | 105 | let lib = load_library(file).map_err(invalid_data_err)?; |
100 | let exported_macros = { | 106 | let exported_macros = { |
101 | let macros: libloading::Symbol<&&[bridge::client::ProcMacro]> = | 107 | let macros: libloading::Symbol<&&[bridge::client::ProcMacro]> = |
102 | unsafe { lib.get(symbol_name.as_bytes()) }.map_err(|e| e.to_string())?; | 108 | unsafe { lib.get(symbol_name.as_bytes()) }.map_err(invalid_data_err)?; |
103 | macros.to_vec() | 109 | macros.to_vec() |
104 | }; | 110 | }; |
105 | 111 | ||
@@ -122,7 +128,7 @@ impl Expander { | |||
122 | let lib = | 128 | let lib = |
123 | lib.as_ref().canonicalize().expect(&format!("Cannot canonicalize {:?}", lib.as_ref())); | 129 | lib.as_ref().canonicalize().expect(&format!("Cannot canonicalize {:?}", lib.as_ref())); |
124 | 130 | ||
125 | let library = ProcMacroLibraryImpl::open(&lib)?; | 131 | let library = ProcMacroLibraryImpl::open(&lib).map_err(|e| e.to_string())?; |
126 | libs.push(library); | 132 | libs.push(library); |
127 | 133 | ||
128 | Ok(Expander { libs }) | 134 | Ok(Expander { libs }) |