aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_proc_macro_srv/src/dylib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_proc_macro_srv/src/dylib.rs')
-rw-r--r--crates/ra_proc_macro_srv/src/dylib.rs54
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};
7use libloading::Library; 7use libloading::Library;
8use ra_proc_macro::ProcMacroKind; 8use ra_proc_macro::ProcMacroKind;
9 9
10static NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; 10use std::io::Error as IoError;
11use std::io::ErrorKind as IoErrorKind;
11 12
12fn get_symbols_from_lib(file: &Path) -> Option<Vec<String>> { 13const 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 { 15fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> IoError {
16 IoError::new(IoErrorKind::InvalidData, e)
17}
18
19fn 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
52fn is_derive_registrar_symbol(symbol: &str) -> bool { 59fn is_derive_registrar_symbol(symbol: &str) -> bool {
53 symbol.contains(NEW_REGISTRAR_SYMBOL) 60 symbol.contains(NEW_REGISTRAR_SYMBOL)
54} 61}
55 62
56fn find_registrar_symbol(file: &Path) -> Option<String> { 63fn 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
94impl ProcMacroLibraryLibloading { 100impl 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 })