@@ -185,6 +185,47 @@ impl Axecutor {
185
185
}
186
186
}
187
187
188
+ // This is only the call stack, which uses different data than the full tracing functionality
189
+ #[ wasm_bindgen]
190
+ impl Axecutor {
191
+ /// Give an overview of the current call stack.
192
+ /// This works best when a symbol table has been provided, which is currently only the case for ELF binaries.
193
+ pub fn call_stack ( & self ) -> Result < String , AxError > {
194
+ let mut trace = String :: new ( ) ;
195
+
196
+ for ( i, addr) in self . state . call_stack . iter ( ) . enumerate ( ) {
197
+ let formatted = match self . symbol_table . get ( addr) {
198
+ Some ( sym) => format ! ( "{sym}@{addr:#x}" ) ,
199
+ None => format ! ( "{addr:#x}" ) ,
200
+ } ;
201
+
202
+ if i == self . state . call_stack . len ( ) - 1 {
203
+ trace. push_str ( & format ! (
204
+ "{}=> {} <------------ in this function\n " ,
205
+ " " . repeat( i) ,
206
+ formatted
207
+ ) ) ;
208
+ } else {
209
+ trace. push_str ( & format ! ( "{}-> {}\n " , " " . repeat( i) , formatted) ) ;
210
+ }
211
+ }
212
+
213
+ let rip = self . reg_read_64 ( SupportedRegister :: RIP ) ?;
214
+ if let Ok ( instr) = self . decode_at ( rip) {
215
+ trace. push_str ( & format ! (
216
+ "{} rip@{:#x} <------------ at or before this instruction pointer\n {} {} ({:#?}) <------------ at this or the previous instruction" ,
217
+ " " . repeat( self . state. call_stack. len( ) ) ,
218
+ rip,
219
+ " " . repeat( self . state. call_stack. len( ) ) ,
220
+ instr,
221
+ instr. code( )
222
+ ) ) ;
223
+ }
224
+
225
+ Ok ( trace)
226
+ }
227
+ }
228
+
188
229
#[ cfg( test) ]
189
230
mod tests {
190
231
use crate :: auto:: generated:: SupportedMnemonic ;
@@ -273,44 +314,3 @@ mod tests {
273
314
"# , unsafe { jle_count } , ax. reg_read_64( RSI ) . unwrap( ) , ax. reg_read_64( RDX ) . unwrap( ) , ax. reg_read_64( R10 ) . unwrap( ) , ax. reg_read_64( R8 ) . unwrap( ) , ax. reg_read_64( R9 ) . unwrap( ) ) ) ;
274
315
} ] ;
275
316
}
276
-
277
- // This is only the call stack, which uses different data than the full tracing functionality
278
- #[ wasm_bindgen]
279
- impl Axecutor {
280
- /// Give an overview of the current call stack.
281
- /// This works best when a symbol table has been provided, which is currently only the case for ELF binaries.
282
- pub fn call_stack ( & self ) -> Result < String , AxError > {
283
- let mut trace = String :: new ( ) ;
284
-
285
- for ( i, addr) in self . state . call_stack . iter ( ) . enumerate ( ) {
286
- let formatted = match self . symbol_table . get ( addr) {
287
- Some ( sym) => format ! ( "{sym}@{addr:#x}" ) ,
288
- None => format ! ( "{addr:#x}" ) ,
289
- } ;
290
-
291
- if i == self . state . call_stack . len ( ) - 1 {
292
- trace. push_str ( & format ! (
293
- "{}=> {} <------------ in this function\n " ,
294
- " " . repeat( i) ,
295
- formatted
296
- ) ) ;
297
- } else {
298
- trace. push_str ( & format ! ( "{}-> {}\n " , " " . repeat( i) , formatted) ) ;
299
- }
300
- }
301
-
302
- let rip = self . reg_read_64 ( SupportedRegister :: RIP ) ?;
303
- if let Ok ( instr) = self . decode_at ( rip) {
304
- trace. push_str ( & format ! (
305
- "{} rip@{:#x} <------------ at or before this instruction pointer\n {} {} ({:#?}) <------------ at this or the previous instruction" ,
306
- " " . repeat( self . state. call_stack. len( ) ) ,
307
- rip,
308
- " " . repeat( self . state. call_stack. len( ) ) ,
309
- instr,
310
- instr. code( )
311
- ) ) ;
312
- }
313
-
314
- Ok ( trace)
315
- }
316
- }
0 commit comments