diff options
-rw-r--r-- | crates/ra_proc_macro_srv/src/dylib.rs | 68 |
1 files changed, 18 insertions, 50 deletions
diff --git a/crates/ra_proc_macro_srv/src/dylib.rs b/crates/ra_proc_macro_srv/src/dylib.rs index eca9c8576..8403187b9 100644 --- a/crates/ra_proc_macro_srv/src/dylib.rs +++ b/crates/ra_proc_macro_srv/src/dylib.rs | |||
@@ -1,54 +1,50 @@ | |||
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; | ||
5 | use std::io::Read; | ||
6 | use std::path::Path; | 4 | use std::path::Path; |
7 | 5 | ||
8 | use goblin::{mach::Mach, Object}; | 6 | use goblin::{mach::Mach, Object}; |
9 | use libloading::Library; | 7 | use libloading::Library; |
10 | use ra_proc_macro::ProcMacroKind; | 8 | use ra_proc_macro::ProcMacroKind; |
11 | 9 | ||
12 | static NEW_REGISTRAR_SYMBOL: &str = "__rustc_proc_macro_decls_"; | 10 | static NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; |
13 | static _OLD_REGISTRAR_SYMBOL: &str = "__rustc_derive_registrar_"; | ||
14 | |||
15 | fn read_bytes(file: &Path) -> Option<Vec<u8>> { | ||
16 | let mut fd = File::open(file).ok()?; | ||
17 | let mut buffer = Vec::new(); | ||
18 | fd.read_to_end(&mut buffer).ok()?; | ||
19 | |||
20 | Some(buffer) | ||
21 | } | ||
22 | 11 | ||
23 | fn get_symbols_from_lib(file: &Path) -> Option<Vec<String>> { | 12 | fn get_symbols_from_lib(file: &Path) -> Option<Vec<String>> { |
24 | let buffer = read_bytes(file)?; | 13 | let buffer = std::fs::read(file).ok()?; |
25 | let object = Object::parse(&buffer).ok()?; | 14 | let object = Object::parse(&buffer).ok()?; |
26 | 15 | ||
27 | return match object { | 16 | return match object { |
28 | Object::Elf(elf) => { | 17 | Object::Elf(elf) => { |
29 | let symbols = elf.dynstrtab.to_vec().ok()?; | 18 | let symbols = elf.dynstrtab.to_vec().ok()?; |
30 | let names = symbols.iter().map(|s| s.to_string()).collect(); | 19 | let names = symbols.iter().map(|s| s.to_string()).collect(); |
31 | |||
32 | Some(names) | 20 | Some(names) |
33 | } | 21 | } |
34 | |||
35 | Object::PE(pe) => { | 22 | Object::PE(pe) => { |
36 | let symbol_names = | 23 | let symbol_names = |
37 | pe.exports.iter().flat_map(|s| s.name).map(|n| n.to_string()).collect(); | 24 | pe.exports.iter().flat_map(|s| s.name).map(|n| n.to_string()).collect(); |
38 | Some(symbol_names) | 25 | Some(symbol_names) |
39 | } | 26 | } |
40 | |||
41 | Object::Mach(mach) => match mach { | 27 | Object::Mach(mach) => match mach { |
42 | Mach::Binary(binary) => { | 28 | Mach::Binary(binary) => { |
43 | let exports = binary.exports().ok()?; | 29 | let exports = binary.exports().ok()?; |
44 | let names = exports.iter().map(|s| s.name.clone()).collect(); | 30 | let names = exports |
45 | 31 | .iter() | |
32 | .map(|s| { | ||
33 | // In macos doc: | ||
34 | // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html | ||
35 | // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be | ||
36 | // prepended with an underscore. | ||
37 | if s.name.starts_with("_") { | ||
38 | s.name[1..].to_string() | ||
39 | } else { | ||
40 | s.name.to_string() | ||
41 | } | ||
42 | }) | ||
43 | .collect(); | ||
46 | Some(names) | 44 | Some(names) |
47 | } | 45 | } |
48 | |||
49 | Mach::Fat(_) => None, | 46 | Mach::Fat(_) => None, |
50 | }, | 47 | }, |
51 | |||
52 | Object::Archive(_) | Object::Unknown(_) => None, | 48 | Object::Archive(_) | Object::Unknown(_) => None, |
53 | }; | 49 | }; |
54 | } | 50 | } |
@@ -57,28 +53,10 @@ fn is_derive_registrar_symbol(symbol: &str) -> bool { | |||
57 | symbol.contains(NEW_REGISTRAR_SYMBOL) | 53 | symbol.contains(NEW_REGISTRAR_SYMBOL) |
58 | } | 54 | } |
59 | 55 | ||
60 | #[cfg(not(target_os = "macos"))] | ||
61 | fn adjust_symbol_name(name: &str) -> String { | ||
62 | name.to_string() | ||
63 | } | ||
64 | |||
65 | #[cfg(target_os = "macos")] | ||
66 | fn adjust_symbol_name(s: &str) -> String { | ||
67 | // In macos doc: | ||
68 | // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html | ||
69 | // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be | ||
70 | // prepended with an underscore. | ||
71 | if s.starts_with("_") { | ||
72 | s[1..s.len()].to_string() | ||
73 | } else { | ||
74 | s.to_string() | ||
75 | } | ||
76 | } | ||
77 | |||
78 | fn find_registrar_symbol(file: &Path) -> Option<String> { | 56 | fn find_registrar_symbol(file: &Path) -> Option<String> { |
79 | let symbols = get_symbols_from_lib(file)?; | 57 | let symbols = get_symbols_from_lib(file)?; |
80 | 58 | ||
81 | symbols.iter().find(|s| is_derive_registrar_symbol(s)).map(|s| adjust_symbol_name(&s)) | 59 | symbols.iter().find(|s| is_derive_registrar_symbol(s)).map(|s| s.clone()) |
82 | } | 60 | } |
83 | 61 | ||
84 | /// Loads dynamic library in platform dependent manner. | 62 | /// Loads dynamic library in platform dependent manner. |
@@ -119,11 +97,9 @@ impl ProcMacroLibraryLibloading { | |||
119 | .ok_or(format!("Cannot find registrar symbol in file {:?}", file))?; | 97 | .ok_or(format!("Cannot find registrar symbol in file {:?}", file))?; |
120 | 98 | ||
121 | let lib = load_library(file).map_err(|e| e.to_string())?; | 99 | let lib = load_library(file).map_err(|e| e.to_string())?; |
122 | |||
123 | let exported_macros = { | 100 | let exported_macros = { |
124 | let macros: libloading::Symbol<&&[bridge::client::ProcMacro]> = | 101 | let macros: libloading::Symbol<&&[bridge::client::ProcMacro]> = |
125 | unsafe { lib.get(symbol_name.as_bytes()) }.map_err(|e| e.to_string())?; | 102 | unsafe { lib.get(symbol_name.as_bytes()) }.map_err(|e| e.to_string())?; |
126 | |||
127 | macros.to_vec() | 103 | macros.to_vec() |
128 | }; | 104 | }; |
129 | 105 | ||
@@ -140,7 +116,6 @@ pub struct Expander { | |||
140 | impl Expander { | 116 | impl Expander { |
141 | pub fn new<P: AsRef<Path>>(lib: &P) -> Result<Expander, String> { | 117 | pub fn new<P: AsRef<Path>>(lib: &P) -> Result<Expander, String> { |
142 | let mut libs = vec![]; | 118 | let mut libs = vec![]; |
143 | |||
144 | /* Some libraries for dynamic loading require canonicalized path (even when it is | 119 | /* Some libraries for dynamic loading require canonicalized path (even when it is |
145 | already absolute | 120 | already absolute |
146 | */ | 121 | */ |
@@ -177,20 +152,16 @@ impl Expander { | |||
177 | crate::rustc_server::Rustc::default(), | 152 | crate::rustc_server::Rustc::default(), |
178 | parsed_body, | 153 | parsed_body, |
179 | ); | 154 | ); |
180 | |||
181 | return res.map(|it| it.subtree); | 155 | return res.map(|it| it.subtree); |
182 | } | 156 | } |
183 | |||
184 | bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => { | 157 | bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => { |
185 | let res = client.run( | 158 | let res = client.run( |
186 | &crate::proc_macro::bridge::server::SameThread, | 159 | &crate::proc_macro::bridge::server::SameThread, |
187 | crate::rustc_server::Rustc::default(), | 160 | crate::rustc_server::Rustc::default(), |
188 | parsed_body, | 161 | parsed_body, |
189 | ); | 162 | ); |
190 | |||
191 | return res.map(|it| it.subtree); | 163 | return res.map(|it| it.subtree); |
192 | } | 164 | } |
193 | |||
194 | bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => { | 165 | bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => { |
195 | let res = client.run( | 166 | let res = client.run( |
196 | &crate::proc_macro::bridge::server::SameThread, | 167 | &crate::proc_macro::bridge::server::SameThread, |
@@ -201,10 +172,7 @@ impl Expander { | |||
201 | 172 | ||
202 | return res.map(|it| it.subtree); | 173 | return res.map(|it| it.subtree); |
203 | } | 174 | } |
204 | 175 | _ => continue, | |
205 | _ => { | ||
206 | continue; | ||
207 | } | ||
208 | } | 176 | } |
209 | } | 177 | } |
210 | } | 178 | } |