aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_proc_macro_srv/src/dylib.rs68
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
3use crate::{proc_macro::bridge, rustc_server::TokenStream}; 3use crate::{proc_macro::bridge, rustc_server::TokenStream};
4use std::fs::File;
5use std::io::Read;
6use std::path::Path; 4use std::path::Path;
7 5
8use goblin::{mach::Mach, Object}; 6use goblin::{mach::Mach, Object};
9use libloading::Library; 7use libloading::Library;
10use ra_proc_macro::ProcMacroKind; 8use ra_proc_macro::ProcMacroKind;
11 9
12static NEW_REGISTRAR_SYMBOL: &str = "__rustc_proc_macro_decls_"; 10static NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
13static _OLD_REGISTRAR_SYMBOL: &str = "__rustc_derive_registrar_";
14
15fn 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
23fn get_symbols_from_lib(file: &Path) -> Option<Vec<String>> { 12fn 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"))]
61fn adjust_symbol_name(name: &str) -> String {
62 name.to_string()
63}
64
65#[cfg(target_os = "macos")]
66fn 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
78fn find_registrar_symbol(file: &Path) -> Option<String> { 56fn 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 {
140impl Expander { 116impl 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 }