@@ -58,7 +58,9 @@ pub fn read_assembly<P: AsRef<Path>>(path: P) -> io::Result<String> {
58
58
// they're uninteresting for out use-case.
59
59
//
60
60
// See https://github.com/rust-lang/rust/blob/1.59.0/compiler/rustc_codegen_llvm/src/back/write.rs#L978-L1074
61
- Ok ( strip_section ( & s, "__LLVM" ) )
61
+ let s = strip_section ( & s, "__LLVM" ) ;
62
+ let s = demangle_assembly ( & s) ;
63
+ Ok ( s)
62
64
}
63
65
64
66
#[ cfg( feature = "run" ) ]
@@ -89,3 +91,170 @@ pub fn get_artifact(result_stream: &[u8], package: &str) -> PathBuf {
89
91
pub fn get_artifact ( _result_stream : & [ u8 ] , _package : & str ) -> PathBuf {
90
92
panic ! ( "`run` feature must be enabled" )
91
93
}
94
+
95
+ /// VERY BRITTLE!
96
+ #[ cfg( feature = "run" ) ]
97
+ fn demangle_assembly ( assembly : & str ) -> String {
98
+ use std:: collections:: HashMap ;
99
+
100
+ use lazy_static:: lazy_static;
101
+ use regex:: Captures ;
102
+ use regex:: Regex ;
103
+
104
+ lazy_static ! {
105
+ // All identifiers
106
+ static ref RE_IDENT : Regex = Regex :: new( r"[a-zA-Z_][a-zA-Z_0-9]*" ) . unwrap( ) ;
107
+
108
+ // Replace crate ID that the compiler inserts
109
+ //
110
+ // Example: test_msg_send_static_sel[f7bb0e08e35403f3]::handle_with_sel::NAME_DATA
111
+ // Becomes: test_msg_send_static_sel[CRATE_ID]::handle_with_sel::NAME_DATA
112
+ static ref RE_CRATE_ID : Regex = Regex :: new( r"\[.*\]" ) . unwrap( ) ;
113
+
114
+ // Replace last part of symbol if it looks to be autogenerated
115
+ //
116
+ // Example: objc2_foundation::__string_macro::CFStringUtf16::as_ptr::hbadb49a829a98ec7
117
+ // Becomes: objc2_foundation::__string_macro::CFStringUtf16::as_ptr::GENERATED_ID
118
+ static ref RE_LAST : Regex = Regex :: new( r"[a-z0-9]{17}$" ) . unwrap( ) ;
119
+ }
120
+
121
+ // Demangled name -> List of seen mangled names for this demangled name
122
+ let mut demangle_unique: HashMap < String , Vec < String > > = HashMap :: new ( ) ;
123
+
124
+ // Find all identifiers, and attempt to demangle them
125
+ RE_IDENT
126
+ . replace_all ( assembly, |caps : & Captures | {
127
+ let ident = caps. get ( 0 ) . unwrap ( ) . as_str ( ) ;
128
+ match rustc_demangle:: try_demangle ( ident) {
129
+ Ok ( s) => {
130
+ let s = s. to_string ( ) ;
131
+ let s = RE_CRATE_ID . replace_all ( & s, "[CRATE_ID]" ) ;
132
+ let s = RE_LAST . replace ( & s, "GENERATED_ID" ) ;
133
+ let list_for_this_symbol = demangle_unique
134
+ . entry ( s. to_string ( ) )
135
+ . or_insert_with ( || vec ! [ ident. to_string( ) ] ) ;
136
+ let unique_identifier = list_for_this_symbol
137
+ . iter ( )
138
+ . position ( |x| x == ident)
139
+ . unwrap_or_else ( || {
140
+ list_for_this_symbol. push ( ident. to_string ( ) ) ;
141
+ list_for_this_symbol. len ( ) - 1
142
+ } ) ;
143
+
144
+ format ! ( "SYM({}, {})" , s, unique_identifier)
145
+ }
146
+ Err ( _) => ident. to_string ( ) ,
147
+ }
148
+ } )
149
+ . to_string ( )
150
+ }
151
+
152
+ #[ cfg( not( feature = "run" ) ) ]
153
+ fn demangle_assembly ( _s : & str ) -> String {
154
+ panic ! ( "`run` feature must be enabled" )
155
+ }
156
+
157
+ #[ cfg( test) ]
158
+ mod tests {
159
+ #[ cfg( feature = "run" ) ]
160
+ #[ test]
161
+ fn test_demangle ( ) {
162
+ use super :: * ;
163
+
164
+ let before = r#"
165
+ .section __TEXT,__text,regular,pure_instructions
166
+ .intel_syntax noprefix
167
+ .globl _handle_with_sel
168
+ .p2align 4, 0x90
169
+ _handle_with_sel:
170
+ push rbp
171
+ mov rbp, rsp
172
+ lea rsi, [rip + __RNvNvCslgFcLFxF7mp_24test_msg_send_static_sel15handle_with_sel9NAME_DATA]
173
+ pop rbp
174
+ jmp _objc_msgSend
175
+
176
+ .section __TEXT,__objc_methname,cstring_literals
177
+ __RNvNvCslgFcLFxF7mp_24test_msg_send_static_sel15handle_with_sel9NAME_DATA:
178
+ .asciz "someSelector"
179
+ "# ;
180
+
181
+ let after = r#"
182
+ .section __TEXT,__text,regular,pure_instructions
183
+ .intel_syntax noprefix
184
+ .globl _handle_with_sel
185
+ .p2align 4, 0x90
186
+ _handle_with_sel:
187
+ push rbp
188
+ mov rbp, rsp
189
+ lea rsi, [rip + SYM(test_msg_send_static_sel[CRATE_ID]::handle_with_sel::NAME_DATA, 0)]
190
+ pop rbp
191
+ jmp _objc_msgSend
192
+
193
+ .section __TEXT,__objc_methname,cstring_literals
194
+ SYM(test_msg_send_static_sel[CRATE_ID]::handle_with_sel::NAME_DATA, 0):
195
+ .asciz "someSelector"
196
+ "# ;
197
+ let output = demangle_assembly ( before) ;
198
+ assert_eq ! ( output, after, "Got {}" , output) ;
199
+
200
+ let before = r#"
201
+ _get_ascii:
202
+ stp x29, x30, [sp, #-16]!
203
+ mov x29, sp
204
+ Lloh0:
205
+ adrp x0, l___unnamed_1@PAGE
206
+ Lloh1:
207
+ add x0, x0, l___unnamed_1@PAGEOFF
208
+ mov w1, #3
209
+ bl __ZN16objc2_foundation14__string_macro8is_ascii17h6ed9b17e599aba93E
210
+ tbz w0, #0, LBB0_2
211
+ Lloh2:
212
+ adrp x0, __RNvNvCs9IkGjU4WDwV_14test_ns_string9get_ascii8CFSTRING@PAGE
213
+ Lloh3:
214
+ add x0, x0, __RNvNvCs9IkGjU4WDwV_14test_ns_string9get_ascii8CFSTRING@PAGEOFF
215
+ ldp x29, x30, [sp], #16
216
+ b __ZN16objc2_foundation14__string_macro13CFStringAscii6as_ptr17hb04bc801907abfefE
217
+ LBB0_2:
218
+ Lloh4:
219
+ adrp x0, __RNvNvCs9IkGjU4WDwV_14test_ns_string9get_asciis_8CFSTRING@PAGE
220
+ Lloh5:
221
+ add x0, x0, __RNvNvCs9IkGjU4WDwV_14test_ns_string9get_asciis_8CFSTRING@PAGEOFF
222
+ ldp x29, x30, [sp], #16
223
+ b __ZN16objc2_foundation14__string_macro13CFStringUtf166as_ptr17h2d998f5fc92d4caaE
224
+ .loh AdrpAdd Lloh0, Lloh1
225
+ .loh AdrpAdd Lloh2, Lloh3
226
+ .loh AdrpAdd Lloh4, Lloh5
227
+ "# ;
228
+
229
+ let after = r#"
230
+ _get_ascii:
231
+ stp x29, x30, [sp, #-16]!
232
+ mov x29, sp
233
+ Lloh0:
234
+ adrp x0, l___unnamed_1@PAGE
235
+ Lloh1:
236
+ add x0, x0, l___unnamed_1@PAGEOFF
237
+ mov w1, #3
238
+ bl SYM(objc2_foundation::__string_macro::is_ascii::GENERATED_ID, 0)
239
+ tbz w0, #0, LBB0_2
240
+ Lloh2:
241
+ adrp x0, SYM(test_ns_string[CRATE_ID]::get_ascii::CFSTRING, 0)@PAGE
242
+ Lloh3:
243
+ add x0, x0, SYM(test_ns_string[CRATE_ID]::get_ascii::CFSTRING, 0)@PAGEOFF
244
+ ldp x29, x30, [sp], #16
245
+ b SYM(objc2_foundation::__string_macro::CFStringAscii::as_ptr::GENERATED_ID, 0)
246
+ LBB0_2:
247
+ Lloh4:
248
+ adrp x0, SYM(test_ns_string[CRATE_ID]::get_ascii::CFSTRING, 1)@PAGE
249
+ Lloh5:
250
+ add x0, x0, SYM(test_ns_string[CRATE_ID]::get_ascii::CFSTRING, 1)@PAGEOFF
251
+ ldp x29, x30, [sp], #16
252
+ b SYM(objc2_foundation::__string_macro::CFStringUtf16::as_ptr::GENERATED_ID, 0)
253
+ .loh AdrpAdd Lloh0, Lloh1
254
+ .loh AdrpAdd Lloh2, Lloh3
255
+ .loh AdrpAdd Lloh4, Lloh5
256
+ "# ;
257
+ let output = demangle_assembly ( before) ;
258
+ assert_eq ! ( output, after, "Got {}" , output) ;
259
+ }
260
+ }
0 commit comments