@@ -58,7 +58,9 @@ pub fn read_assembly<P: AsRef<Path>>(path: P) -> io::Result<String> {
5858 // they're uninteresting for out use-case.
5959 //
6060 // 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)
6264}
6365
6466#[ cfg( feature = "run" ) ]
@@ -89,3 +91,170 @@ pub fn get_artifact(result_stream: &[u8], package: &str) -> PathBuf {
8991pub fn get_artifact ( _result_stream : & [ u8 ] , _package : & str ) -> PathBuf {
9092 panic ! ( "`run` feature must be enabled" )
9193}
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