Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/tests/all/debug/lldb.rs
1691 views
1
use anyhow::{Result, bail, format_err};
2
use filecheck::{CheckerBuilder, NO_VARIABLES};
3
use std::env;
4
use std::io::Write;
5
use std::process::Command;
6
use tempfile::NamedTempFile;
7
use test_programs_artifacts::*;
8
9
macro_rules! assert_test_exists {
10
($name:ident) => {
11
#[expect(unused_imports, reason = "here to assert tests exist")]
12
use self::$name as _;
13
};
14
}
15
foreach_dwarf!(assert_test_exists);
16
17
fn lldb_with_script(args: &[&str], script: &str) -> Result<String> {
18
let _ = env_logger::try_init();
19
20
let lldb_path = env::var("LLDB").unwrap_or("lldb".to_string());
21
let mut cmd = Command::new(&lldb_path);
22
23
cmd.arg("--batch");
24
if cfg!(target_os = "macos") {
25
cmd.args(&["-o", "settings set plugin.jit-loader.gdb.enable on"]);
26
}
27
let mut script_file = NamedTempFile::new()?;
28
script_file.write(script.as_bytes())?;
29
let script_path = script_file.path().to_str().unwrap();
30
cmd.args(&["-s", &script_path]);
31
32
let mut me = std::env::current_exe().expect("current_exe specified");
33
me.pop(); // chop off the file name
34
me.pop(); // chop off `deps`
35
if cfg!(target_os = "windows") {
36
me.push("wasmtime.exe");
37
} else {
38
me.push("wasmtime");
39
}
40
cmd.arg(me);
41
42
cmd.arg("--");
43
cmd.args(args);
44
45
log::trace!("Running command: {cmd:?}");
46
let output = cmd.output().expect("success");
47
48
let stdout = String::from_utf8(output.stdout)?;
49
log::trace!("--- sdout ---\n{stdout}");
50
51
let stderr = String::from_utf8(output.stderr)?;
52
log::trace!("--- sderr ---\n{stderr}");
53
54
if !output.status.success() {
55
bail!(
56
"failed to execute {cmd:?}:\n\
57
--- stderr ---\n\
58
{stderr}\n\
59
--- stdout ---\n\
60
{stdout}",
61
);
62
}
63
Ok(stdout)
64
}
65
66
fn check_lldb_output(output: &str, directives: &str) -> Result<()> {
67
let mut builder = CheckerBuilder::new();
68
builder
69
.text(directives)
70
.map_err(|e| format_err!("unable to build checker: {:?}", e))?;
71
let checker = builder.finish();
72
let check = checker
73
.explain(output, NO_VARIABLES)
74
.map_err(|e| format_err!("{:?}", e))?;
75
assert!(check.0, "didn't pass check {}", check.1);
76
Ok(())
77
}
78
79
#[allow(dead_code, reason = "tested elsewhere")]
80
fn dwarf_dead_code() {} // this is tested over in `translate.rs`
81
82
#[test]
83
#[ignore]
84
pub fn dwarf_fib_wasm() -> Result<()> {
85
let output = lldb_with_script(
86
&[
87
"-Ccache=n",
88
"-Ddebug-info",
89
"-Oopt-level=0",
90
"--invoke",
91
"fib",
92
DWARF_FIB_WASM,
93
"3",
94
],
95
r#"b fib
96
r
97
fr v
98
c"#,
99
)?;
100
101
check_lldb_output(
102
&output,
103
r#"
104
check: Breakpoint 1: no locations (pending)
105
check: Unable to resolve breakpoint to any actual locations.
106
check: 1 location added to breakpoint 1
107
check: stop reason = breakpoint 1.1
108
check: frame #0
109
sameln: JIT
110
sameln: fib(n=3)
111
check: n = 3
112
check: a = 0
113
check: resuming
114
check: exited with status
115
"#,
116
)?;
117
Ok(())
118
}
119
120
#[test]
121
#[ignore]
122
pub fn dwarf_fib_wasm_dwarf5() -> Result<()> {
123
let output = lldb_with_script(
124
&[
125
"-Ccache=n",
126
"-Ddebug-info",
127
"-Oopt-level=0",
128
"--invoke",
129
"fib",
130
DWARF_FIB_WASM_DWARF5,
131
"3",
132
],
133
r#"b fib
134
r
135
fr v
136
c"#,
137
)?;
138
139
check_lldb_output(
140
&output,
141
r#"
142
check: Breakpoint 1: no locations (pending)
143
check: Unable to resolve breakpoint to any actual locations.
144
check: 1 location added to breakpoint 1
145
check: stop reason = breakpoint 1.1
146
check: frame #0
147
sameln: JIT
148
sameln: fib(n=3)
149
check: n = 3
150
check: a = 0
151
check: resuming
152
check: exited with status
153
"#,
154
)?;
155
Ok(())
156
}
157
158
#[test]
159
#[ignore]
160
pub fn dwarf_fib_wasm_split4() -> Result<()> {
161
let output = lldb_with_script(
162
&[
163
"-Ccache=n",
164
"-Ddebug-info",
165
"-Oopt-level=0",
166
"--invoke",
167
"fib",
168
DWARF_FIB_WASM_SPLIT4,
169
"3",
170
],
171
r#"b fib
172
r
173
fr v
174
c"#,
175
)?;
176
177
check_lldb_output(
178
&output,
179
r#"
180
check: Breakpoint 1: no locations (pending)
181
check: Unable to resolve breakpoint to any actual locations.
182
check: 1 location added to breakpoint 1
183
check: stop reason = breakpoint 1.1
184
check: frame #0
185
sameln: JIT
186
sameln: fib(n=3)
187
check: n = 3
188
check: a = 0
189
check: resuming
190
check: exited with status
191
"#,
192
)?;
193
Ok(())
194
}
195
196
#[test]
197
#[ignore]
198
pub fn dwarf_generic() -> Result<()> {
199
let output = lldb_with_script(
200
&["-Ccache=n", "-Ddebug-info", "-Oopt-level=0", DWARF_GENERIC],
201
r#"br set -n debug_break -C up
202
r
203
p __vmctx->set()
204
p (x + x)
205
c
206
p (x + x)
207
c
208
p inst.BaseValue + inst.DerivedValue
209
c
210
type lookup DerivedType
211
c
212
p __this->BaseValue + __this->DerivedValue
213
c
214
p __this->BaseValue + __this->DerivedValue
215
c
216
p __this->BaseValue + __this->DerivedValue
217
c
218
f
219
n
220
s
221
v var0
222
v var1
223
c"#,
224
)?;
225
226
check_lldb_output(
227
&output,
228
r#"
229
check: stop reason = breakpoint 1.1
230
check: 2
231
check: stop reason = breakpoint 1.1
232
check: 4
233
check: stop reason = breakpoint 1.1
234
check: 3
235
check: stop reason = breakpoint 1.1
236
check: static int InstanceMethod
237
check: static int ConstInstanceMethod
238
check: stop reason = breakpoint 1.1
239
check: 6
240
check: stop reason = breakpoint 1.1
241
check: 7
242
check: stop reason = breakpoint 1.1
243
check: 8
244
check: stop reason = breakpoint 1.1
245
check: 9
246
check: 10
247
check: exited with status = 0
248
"#,
249
)?;
250
Ok(())
251
}
252
253
#[test]
254
#[ignore]
255
pub fn dwarf_codegen_optimized() -> Result<()> {
256
let output = lldb_with_script(
257
&[
258
"-Ccache=n",
259
"-Ddebug-info",
260
"-Oopt-level=2",
261
DWARF_CODEGEN_OPTIMIZED,
262
],
263
r#"b InitializeTest
264
r
265
b dwarf_codegen_optimized.cpp:25
266
b dwarf_codegen_optimized.cpp:26
267
c
268
v x
269
c
270
v x
271
c"#,
272
)?;
273
274
check_lldb_output(
275
&output,
276
r#"
277
check: stop reason = breakpoint 1.1
278
check: stop reason = breakpoint 2.1
279
check: x = 42
280
check: stop reason = breakpoint 3.1
281
check: x = <variable not available>
282
check: exited with status = 0
283
"#,
284
)?;
285
Ok(())
286
}
287
288
#[test]
289
#[ignore]
290
pub fn dwarf_codegen_optimized_wasm_optimized() -> Result<()> {
291
let output = lldb_with_script(
292
&[
293
"-Ccache=n",
294
"-Ddebug-info",
295
"-Oopt-level=2",
296
DWARF_CODEGEN_OPTIMIZED_WASM_OPTIMIZED,
297
],
298
r#"b InitializeTest
299
r
300
b dwarf_codegen_optimized_wasm_optimized.cpp:23
301
b dwarf_codegen_optimized_wasm_optimized.cpp:29
302
c
303
v b
304
c
305
v b
306
c"#,
307
)?;
308
309
check_lldb_output(
310
&output,
311
r#"
312
check: stop reason = breakpoint 1.1
313
check: stop reason = breakpoint 2.1
314
check: b = 42
315
check: stop reason = breakpoint 3.1
316
check: b = 43
317
check: exited with status = 0
318
"#,
319
)?;
320
Ok(())
321
}
322
323
#[test]
324
#[ignore]
325
pub fn dwarf_fraction_norm() -> Result<()> {
326
let output = lldb_with_script(
327
&[
328
"-Ccache=n",
329
"-Oopt-level=0",
330
"-Ddebug-info",
331
DWARF_FRACTION_NORM,
332
],
333
r#"b dwarf_fraction_norm.cc:26
334
r
335
p __vmctx->set(),n->denominator
336
c"#,
337
)?;
338
339
check_lldb_output(
340
&output,
341
r#"
342
check: Breakpoint 1: no locations (pending)
343
check: stop reason = breakpoint 1.1
344
check: frame #0
345
sameln: norm(n=(__ptr =
346
check: 27
347
check: resuming
348
"#,
349
)?;
350
Ok(())
351
}
352
353
#[test]
354
#[ignore]
355
pub fn dwarf_two_removed_branches() -> Result<()> {
356
let output = lldb_with_script(
357
&[
358
"-Ccache=n",
359
"-Oopt-level=0",
360
"-Ddebug-info",
361
DWARF_TWO_REMOVED_BRANCHES,
362
],
363
r#"r"#,
364
)?;
365
366
// We are simply checking that the output compiles.
367
check_lldb_output(
368
&output,
369
r#"
370
check: exited with status
371
"#,
372
)?;
373
Ok(())
374
}
375
376
#[test]
377
#[ignore]
378
pub fn dwarf_spilled_frame_base() -> Result<()> {
379
let output = lldb_with_script(
380
&[
381
"-Ccache=n",
382
"-Oopt-level=0",
383
"-Ddebug-info",
384
DWARF_SPILLED_FRAME_BASE,
385
],
386
r#"b dwarf_spilled_frame_base.c:13
387
r
388
fr v i
389
n
390
fr v i
391
n
392
fr v i
393
n
394
fr v i
395
n
396
fr v i
397
n
398
fr v i
399
c
400
"#,
401
)?;
402
403
// Check that if the frame base (shadow frame pointer) local
404
// is spilled, we can still read locals that reference it.
405
check_lldb_output(
406
&output,
407
r#"
408
check: i = 0
409
check: i = 1
410
check: i = 1
411
check: i = 1
412
check: i = 1
413
check: i = 1
414
check: exited with status
415
"#,
416
)?;
417
Ok(())
418
}
419
420
#[test]
421
#[ignore]
422
pub fn dwarf_fission() -> Result<()> {
423
let output = lldb_with_script(
424
&["-Ccache=n", "-Ddebug-info", "-Oopt-level=0", DWARF_FISSION],
425
r#"breakpoint set --file dwarf_fission.c --line 8
426
r
427
fr v
428
s
429
fr v
430
c"#,
431
)?;
432
433
check_lldb_output(
434
&output,
435
r#"
436
check: Breakpoint 1: no locations (pending)
437
check: Unable to resolve breakpoint to any actual locations.
438
check: 1 location added to breakpoint 1
439
check: stop reason = breakpoint 1.1
440
check: i = 1
441
check: stop reason = step in
442
check: i = 2
443
check: resuming
444
check: exited with status = 0
445
"#,
446
)?;
447
Ok(())
448
}
449
450
fn test_dwarf_simple(wasm: &str, extra_args: &[&str]) -> Result<()> {
451
println!("testing {wasm:?}");
452
let mut args = vec!["-Ccache=n", "-Oopt-level=0", "-Ddebug-info"];
453
args.extend(extra_args);
454
args.push(wasm);
455
let output = lldb_with_script(
456
&args,
457
r#"
458
breakpoint set --file dwarf_simple.rs --line 3
459
breakpoint set --file dwarf_simple.rs --line 5
460
r
461
fr v
462
c
463
fr v
464
breakpoint disable 2
465
c"#,
466
)?;
467
468
check_lldb_output(
469
&output,
470
r#"
471
check: Breakpoint 1: no locations (pending)
472
check: Unable to resolve breakpoint to any actual locations.
473
check: 1 location added to breakpoint 1
474
check: stop reason = breakpoint 1.1
475
check: dwarf_simple.rs:3
476
check: a = 100
477
check: dwarf_simple.rs:5
478
check: a = 110
479
check: b = 117
480
check: resuming
481
check: exited with status = 0
482
"#,
483
)?;
484
Ok(())
485
}
486
487
#[test]
488
#[ignore]
489
fn dwarf_simple() -> Result<()> {
490
for wasm in [DWARF_SIMPLE, DWARF_SIMPLE_COMPONENT] {
491
test_dwarf_simple(wasm, &[])?;
492
}
493
Ok(())
494
}
495
496
#[test]
497
#[ignore]
498
fn dwarf_imported_memory() -> Result<()> {
499
test_dwarf_simple(
500
DWARF_IMPORTED_MEMORY,
501
&["--preload=env=./tests/all/debug/satisfy_memory_import.wat"],
502
)
503
}
504
505
#[test]
506
#[ignore]
507
fn dwarf_shared_memory() -> Result<()> {
508
test_dwarf_simple(DWARF_SHARED_MEMORY, &[])
509
}
510
511
#[test]
512
#[ignore]
513
fn dwarf_multiple_codegen_units() -> Result<()> {
514
for wasm in [
515
DWARF_MULTIPLE_CODEGEN_UNITS,
516
DWARF_MULTIPLE_CODEGEN_UNITS_COMPONENT,
517
] {
518
println!("testing {wasm:?}");
519
let output = lldb_with_script(
520
&["-Ccache=n", "-Oopt-level=0", "-Ddebug-info", wasm],
521
r#"
522
breakpoint set --file dwarf_multiple_codegen_units.rs --line 3
523
breakpoint set --file dwarf_multiple_codegen_units.rs --line 10
524
r
525
fr v
526
c
527
fr v
528
breakpoint delete 2
529
finish
530
c"#,
531
)?;
532
533
check_lldb_output(
534
&output,
535
r#"
536
check: Breakpoint 1: no locations (pending)
537
check: Breakpoint 2: no locations (pending)
538
check: stop reason = breakpoint 1.1
539
check: foo::bar(a)
540
check: a = 3
541
check: sum += i
542
check: x = 3
543
check: sum = 0
544
check: 1 breakpoints deleted
545
check: Return value: $(=.*) 3
546
check: exited with status = 0
547
"#,
548
)?;
549
}
550
Ok(())
551
}
552
553