@@ -15,7 +15,7 @@ use std::path::{Path, PathBuf};
15
15
use std:: str:: FromStr ;
16
16
use termcolor:: { Color , ColorChoice , ColorSpec , StandardStream , WriteColor } ;
17
17
use wasmtime:: Engine ;
18
- use wasmtime_environ:: { obj, FilePos , Trap } ;
18
+ use wasmtime_environ:: { obj, FilePos , StackMap , Trap } ;
19
19
20
20
/// A helper utility in wasmtime to explore the compiled object file format of
21
21
/// a `*.cwasm` file.
@@ -36,11 +36,11 @@ pub struct ObjdumpCommand {
36
36
address_jumps : bool ,
37
37
38
38
/// What functions should be printed (all|wasm|trampoline|builtin|libcall, default: wasm)
39
- #[ arg( long, value_parser = Func :: from_str) ]
39
+ #[ arg( long, value_parser = Func :: from_str, value_name = "KIND" ) ]
40
40
funcs : Vec < Func > ,
41
41
42
42
/// String filter to apply to function names to only print some functions.
43
- #[ arg( long) ]
43
+ #[ arg( long, value_name = "STR" ) ]
44
44
filter : Option < String > ,
45
45
46
46
/// Whether or not instruction bytes are disassembled.
@@ -52,19 +52,43 @@ pub struct ObjdumpCommand {
52
52
color : ColorChoice ,
53
53
54
54
/// Whether or not to interleave instructions with address maps.
55
- #[ arg( long) ]
56
- addrmap : bool ,
55
+ #[ arg( long, require_equals = true , value_name = "true|false" ) ]
56
+ addrmap : Option < Option < bool > > ,
57
57
58
58
/// Column width of how large an address is rendered as.
59
- #[ arg( long, default_value = "10" ) ]
59
+ #[ arg( long, default_value = "10" , value_name = "N" ) ]
60
60
address_width : usize ,
61
61
62
62
/// Whether or not to show information about what instructions can trap.
63
- #[ arg( long) ]
64
- traps : bool ,
63
+ #[ arg( long, require_equals = true , value_name = "true|false" ) ]
64
+ traps : Option < Option < bool > > ,
65
+
66
+ /// Whether or not to show information about stack maps.
67
+ #[ arg( long, require_equals = true , value_name = "true|false" ) ]
68
+ stack_maps : Option < Option < bool > > ,
69
+ }
70
+
71
+ fn optional_flag_with_default ( flag : Option < Option < bool > > , default : bool ) -> bool {
72
+ match flag {
73
+ None => default,
74
+ Some ( None ) => true ,
75
+ Some ( Some ( val) ) => val,
76
+ }
65
77
}
66
78
67
79
impl ObjdumpCommand {
80
+ fn addrmap ( & self ) -> bool {
81
+ optional_flag_with_default ( self . addrmap , false )
82
+ }
83
+
84
+ fn traps ( & self ) -> bool {
85
+ optional_flag_with_default ( self . traps , true )
86
+ }
87
+
88
+ fn stack_maps ( & self ) -> bool {
89
+ optional_flag_with_default ( self . stack_maps , true )
90
+ }
91
+
68
92
/// Executes the command.
69
93
pub fn execute ( self ) -> Result < ( ) > {
70
94
// Setup stdout handling color options. Also build some variables used
@@ -107,6 +131,11 @@ impl ObjdumpCommand {
107
131
. and_then ( |section| section. data ( ) . ok ( ) )
108
132
. and_then ( |bytes| wasmtime_environ:: iterate_traps ( bytes) )
109
133
. map ( |i| ( Box :: new ( i) as Box < dyn Iterator < Item = _ > > ) . peekable ( ) ) ,
134
+ stack_maps : elf
135
+ . section_by_name ( obj:: ELF_WASMTIME_STACK_MAP )
136
+ . and_then ( |section| section. data ( ) . ok ( ) )
137
+ . and_then ( |bytes| StackMap :: iter ( bytes) )
138
+ . map ( |i| ( Box :: new ( i) as Box < dyn Iterator < Item = _ > > ) . peekable ( ) ) ,
110
139
objdump : & self ,
111
140
} ;
112
141
@@ -485,16 +514,18 @@ struct Decorator<'a> {
485
514
objdump : & ' a ObjdumpCommand ,
486
515
addrmap : Option < Peekable < Box < dyn Iterator < Item = ( u32 , FilePos ) > + ' a > > > ,
487
516
traps : Option < Peekable < Box < dyn Iterator < Item = ( u32 , Trap ) > + ' a > > > ,
517
+ stack_maps : Option < Peekable < Box < dyn Iterator < Item = ( u32 , StackMap < ' a > ) > + ' a > > > ,
488
518
}
489
519
490
520
impl Decorator < ' _ > {
491
521
fn decorate ( & mut self , address : u64 , list : & mut Vec < String > ) {
492
522
self . addrmap ( address, list) ;
493
523
self . traps ( address, list) ;
524
+ self . stack_maps ( address, list) ;
494
525
}
495
526
496
527
fn addrmap ( & mut self , address : u64 , list : & mut Vec < String > ) {
497
- if !self . objdump . addrmap {
528
+ if !self . objdump . addrmap ( ) {
498
529
return ;
499
530
}
500
531
let Some ( addrmap) = & mut self . addrmap else {
@@ -511,7 +542,7 @@ impl Decorator<'_> {
511
542
}
512
543
513
544
fn traps ( & mut self , address : u64 , list : & mut Vec < String > ) {
514
- if !self . objdump . traps {
545
+ if !self . objdump . traps ( ) {
515
546
return ;
516
547
}
517
548
let Some ( traps) = & mut self . traps else {
@@ -524,4 +555,25 @@ impl Decorator<'_> {
524
555
list. push ( format ! ( "trap: {trap:?}" ) ) ;
525
556
}
526
557
}
558
+
559
+ fn stack_maps ( & mut self , address : u64 , list : & mut Vec < String > ) {
560
+ if !self . objdump . stack_maps ( ) {
561
+ return ;
562
+ }
563
+ let Some ( stack_maps) = & mut self . stack_maps else {
564
+ return ;
565
+ } ;
566
+ while let Some ( ( addr, stack_map) ) =
567
+ stack_maps. next_if ( |( addr, _pos) | u64:: from ( * addr) <= address)
568
+ {
569
+ if u64:: from ( addr) != address {
570
+ continue ;
571
+ }
572
+ list. push ( format ! (
573
+ "stack_map: frame_size={}, frame_offsets={:?}" ,
574
+ stack_map. frame_size( ) ,
575
+ stack_map. offsets( ) . collect:: <Vec <_>>( )
576
+ ) ) ;
577
+ }
578
+ }
527
579
}
0 commit comments