@@ -204,6 +204,18 @@ impl Scroll {
204
204
}
205
205
}
206
206
207
+ #[ derive( Clone , Debug ) ]
208
+ struct Config {
209
+ // Deref and show string values
210
+ deref_show_string : bool ,
211
+ }
212
+
213
+ impl Default for Config {
214
+ fn default ( ) -> Self {
215
+ Self { deref_show_string : true }
216
+ }
217
+ }
218
+
207
219
#[ derive( Clone , Debug ) ]
208
220
struct State {
209
221
/// Messages to write to gdb mi
@@ -253,10 +265,11 @@ struct State {
253
265
status : String ,
254
266
bt : Vec < Bt > ,
255
267
completions : Vec < String > ,
268
+ config : Config ,
256
269
}
257
270
258
271
impl State {
259
- pub fn new ( args : Args ) -> State {
272
+ pub fn new ( args : Args , config : Config ) -> State {
260
273
State {
261
274
next_write : vec ! [ ] ,
262
275
written : VecDeque :: new ( ) ,
@@ -286,6 +299,7 @@ impl State {
286
299
status : String :: new ( ) ,
287
300
bt : vec ! [ ] ,
288
301
completions : vec ! [ ] ,
302
+ config,
289
303
}
290
304
}
291
305
}
@@ -425,7 +439,8 @@ fn main() -> anyhow::Result<()> {
425
439
}
426
440
// Start rx thread
427
441
let ( gdb_stdout, mut app) = App :: new_stream ( args. clone ( ) ) ;
428
- let state = State :: new ( args. clone ( ) ) ;
442
+ let config = Config :: default ( ) ;
443
+ let state = State :: new ( args. clone ( ) , config) ;
429
444
let mut state_share = StateShare { state : Arc :: new ( Mutex :: new ( state) ) } ;
430
445
431
446
// Setup terminal
@@ -1067,9 +1082,15 @@ mod tests {
1067
1082
use ratatui:: { Terminal , backend:: TestBackend } ;
1068
1083
use test_assets_ureq:: { TestAssetDef , dl_test_files_backoff} ;
1069
1084
1070
- fn run_a_bit ( args : Args ) -> ( App , StateShare , Terminal < TestBackend > ) {
1085
+ fn run_a_bit (
1086
+ args : Args ,
1087
+ mode : Mode ,
1088
+ size : Option < ( u16 , u16 ) > ,
1089
+ ) -> ( App , StateShare , Terminal < TestBackend > ) {
1071
1090
let ( gdb_stdout, mut app) = App :: new_stream ( args. clone ( ) ) ;
1072
- let state = State :: new ( args. clone ( ) ) ;
1091
+ let config = Config { deref_show_string : false , ..Config :: default ( ) } ;
1092
+ let mut state = State :: new ( args. clone ( ) , config) ;
1093
+ state. mode = mode;
1073
1094
let state_share = StateShare { state : Arc :: new ( Mutex :: new ( state) ) } ;
1074
1095
spawn_gdb_interact ( & state_share, gdb_stdout) ;
1075
1096
@@ -1083,7 +1104,11 @@ mod tests {
1083
1104
}
1084
1105
}
1085
1106
}
1086
- let mut terminal = Terminal :: new ( TestBackend :: new ( 160 , 50 ) ) . unwrap ( ) ;
1107
+ let mut terminal = if let Some ( ( x, y) ) = size {
1108
+ Terminal :: new ( TestBackend :: new ( x, y) ) . unwrap ( )
1109
+ } else {
1110
+ Terminal :: new ( TestBackend :: new ( 160 , 50 ) ) . unwrap ( )
1111
+ } ;
1087
1112
let start_time = Instant :: now ( ) ;
1088
1113
let duration = Duration :: from_secs ( 10 ) ;
1089
1114
@@ -1147,7 +1172,7 @@ mod tests {
1147
1172
let mut args = Args :: default ( ) ;
1148
1173
args. cmds = Some ( PathBuf :: from ( "test-sources/repeated_ptr.source" ) ) ;
1149
1174
1150
- let ( _, state, terminal) = run_a_bit ( args) ;
1175
+ let ( _, state, terminal) = run_a_bit ( args, Mode :: All , None ) ;
1151
1176
let _output = terminal. backend ( ) ;
1152
1177
let registers = state. state . lock ( ) . unwrap ( ) . registers . clone ( ) ;
1153
1178
let stack = state. state . lock ( ) . unwrap ( ) . stack . clone ( ) ;
@@ -1164,6 +1189,37 @@ mod tests {
1164
1189
assert ! ( stack[ 5 ] . 1 . repeated_pattern) ;
1165
1190
}
1166
1191
1192
+ #[ test]
1193
+ fn test_segfault ( ) {
1194
+ // ```
1195
+ // int main() {
1196
+ // int *p = (int*)0xdeadbeef;
1197
+ // *p = 42;
1198
+ // return 0;
1199
+ // }
1200
+ // ```
1201
+ const FILE_NAME : & str = "segfault" ;
1202
+ const TEST_PATH : & str = "test-assets/segfault/" ;
1203
+ let file_path = format ! ( "{TEST_PATH}/{FILE_NAME}" ) ;
1204
+ let asset_defs = [ TestAssetDef {
1205
+ filename : FILE_NAME . to_string ( ) ,
1206
+ hash : "8d486249e73785737cc1dd8c973f43c4dbb79e723d6a262846a625c184b95d7b" . to_string ( ) ,
1207
+ url : "https://wcampbell.dev/heretek/segfault/segfault" . to_string ( ) ,
1208
+ } ] ;
1209
+
1210
+ dl_test_files_backoff ( & asset_defs, TEST_PATH , true , Duration :: from_secs ( 1 ) ) . unwrap ( ) ;
1211
+ let c_path = CString :: new ( file_path. to_string ( ) ) . expect ( "CString::new failed" ) ;
1212
+ let mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH ;
1213
+ unsafe { chmod ( c_path. as_ptr ( ) , mode) } ;
1214
+
1215
+ let mut args = Args :: default ( ) ;
1216
+ args. cmds = Some ( PathBuf :: from ( "test-sources/segfault.source" ) ) ;
1217
+
1218
+ let ( _, state, terminal) = run_a_bit ( args, Mode :: All , Some ( ( 160 , 40 ) ) ) ;
1219
+ let output = terminal. backend ( ) ;
1220
+ assert_snapshot ! ( output) ;
1221
+ }
1222
+
1167
1223
#[ test]
1168
1224
fn test_render_app ( ) {
1169
1225
// gcc test.c -g -fno-stack-protector -static
@@ -1209,7 +1265,7 @@ mod tests {
1209
1265
let mut args = Args :: default ( ) ;
1210
1266
args. cmds = Some ( PathBuf :: from ( "test-sources/test.source" ) ) ;
1211
1267
1212
- let ( _, state, terminal) = run_a_bit ( args) ;
1268
+ let ( _, state, terminal) = run_a_bit ( args, Mode :: All , None ) ;
1213
1269
let output = terminal. backend ( ) ;
1214
1270
1215
1271
// Now, we need to rewrite all the addresses that change for the registers and stack
0 commit comments