1
1
//! Handles dynamic library loading for proc macro
2
2
3
3
use crate :: { proc_macro:: bridge, rustc_server:: TokenStream } ;
4
- use std:: fs:: File ;
5
- use std:: io:: Read ;
6
4
use std:: path:: Path ;
7
5
8
6
use goblin:: { mach:: Mach , Object } ;
9
7
use libloading:: Library ;
10
8
use ra_proc_macro:: ProcMacroKind ;
11
9
12
- 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
- }
10
+ static NEW_REGISTRAR_SYMBOL : & str = "_rustc_proc_macro_decls_" ;
22
11
23
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
14
let object = Object :: parse ( & buffer) . ok ( ) ?;
26
15
27
16
return match object {
28
17
Object :: Elf ( elf) => {
29
18
let symbols = elf. dynstrtab . to_vec ( ) . ok ( ) ?;
30
19
let names = symbols. iter ( ) . map ( |s| s. to_string ( ) ) . collect ( ) ;
31
-
32
20
Some ( names)
33
21
}
34
-
35
22
Object :: PE ( pe) => {
36
23
let symbol_names =
37
24
pe. exports . iter ( ) . flat_map ( |s| s. name ) . map ( |n| n. to_string ( ) ) . collect ( ) ;
38
25
Some ( symbol_names)
39
26
}
40
-
41
27
Object :: Mach ( mach) => match mach {
42
28
Mach :: Binary ( binary) => {
43
29
let exports = binary. exports ( ) . ok ( ) ?;
44
- let names = exports. iter ( ) . map ( |s| s. name . clone ( ) ) . collect ( ) ;
45
-
30
+ let names = exports
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
44
Some ( names)
47
45
}
48
-
49
46
Mach :: Fat ( _) => None ,
50
47
} ,
51
-
52
48
Object :: Archive ( _) | Object :: Unknown ( _) => None ,
53
49
} ;
54
50
}
@@ -57,28 +53,10 @@ fn is_derive_registrar_symbol(symbol: &str) -> bool {
57
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
56
fn find_registrar_symbol ( file : & Path ) -> Option < String > {
79
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
62
/// Loads dynamic library in platform dependent manner.
@@ -119,11 +97,9 @@ impl ProcMacroLibraryLibloading {
119
97
. ok_or ( format ! ( "Cannot find registrar symbol in file {:?}" , file) ) ?;
120
98
121
99
let lib = load_library ( file) . map_err ( |e| e. to_string ( ) ) ?;
122
-
123
100
let exported_macros = {
124
101
let macros: libloading:: Symbol < & & [ bridge:: client:: ProcMacro ] > =
125
102
unsafe { lib. get ( symbol_name. as_bytes ( ) ) } . map_err ( |e| e. to_string ( ) ) ?;
126
-
127
103
macros. to_vec ( )
128
104
} ;
129
105
@@ -140,7 +116,6 @@ pub struct Expander {
140
116
impl Expander {
141
117
pub fn new < P : AsRef < Path > > ( lib : & P ) -> Result < Expander , String > {
142
118
let mut libs = vec ! [ ] ;
143
-
144
119
/* Some libraries for dynamic loading require canonicalized path (even when it is
145
120
already absolute
146
121
*/
@@ -177,20 +152,16 @@ impl Expander {
177
152
crate :: rustc_server:: Rustc :: default ( ) ,
178
153
parsed_body,
179
154
) ;
180
-
181
155
return res. map ( |it| it. subtree ) ;
182
156
}
183
-
184
157
bridge:: client:: ProcMacro :: Bang { name, client } if * name == macro_name => {
185
158
let res = client. run (
186
159
& crate :: proc_macro:: bridge:: server:: SameThread ,
187
160
crate :: rustc_server:: Rustc :: default ( ) ,
188
161
parsed_body,
189
162
) ;
190
-
191
163
return res. map ( |it| it. subtree ) ;
192
164
}
193
-
194
165
bridge:: client:: ProcMacro :: Attr { name, client } if * name == macro_name => {
195
166
let res = client. run (
196
167
& crate :: proc_macro:: bridge:: server:: SameThread ,
@@ -201,10 +172,7 @@ impl Expander {
201
172
202
173
return res. map ( |it| it. subtree ) ;
203
174
}
204
-
205
- _ => {
206
- continue ;
207
- }
175
+ _ => continue ,
208
176
}
209
177
}
210
178
}
0 commit comments