blob: f39a874f01941dd44cc6402f248184a21deb4a45 [file] [edit]
class CWasmTestCase:
test_file = "resources/c-wasm/add/main.js"
def execute(self):
self.breakpointTest()
self.inspectionTest()
self.stepTest()
self.memoryTest()
self.memoryReadWriteTest()
self.detachTest()
self.quitTest()
def breakpointTest(self):
self.session.cmd("b add")
for _ in range(10):
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "add.c:2"])
self.session.cmd("b main")
self.session.cmd(
"br list",
patterns=[
"Current breakpoints:",
"name = 'add'",
"name = 'main'",
],
)
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "add.c:7"])
self.session.cmd("br del -f", patterns=["All breakpoints removed. (2 breakpoints)"])
def inspectionTest(self):
self.session.cmd("target modules list", patterns=["(0x4000000000000000)"])
self.session.cmd(
"list 1",
patterns=[
"add(int a, int b)",
"main()",
],
)
self.session.cmd("b add")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "add.c:2"])
self.session.cmd(
"bt",
patterns=[
"frame #0: 0x400000000000018b",
"frame #1: 0x40000000000001e0",
"frame #2: 0x4000000000000201",
],
)
self.session.cmd(
"var",
patterns=[
"a =",
"b =",
"result =",
],
)
self.session.cmd(
"thread list",
patterns=[
"0x400000000000018b",
"add.c:2:18",
],
)
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
def stepTest(self):
self.session.cmd("b main")
# Step over
self.session.cmd(
"c", patterns=["Process 1 stopped", "stop reason = breakpoint"]
)
self.session.cmd(
"dis", patterns=["-> 0x40000000000001c0 <+29>: local.get 0"]
)
patterns = [
["-> 0x40000000000001c7 <+36>: local.get 0"],
["-> 0x40000000000001ce <+43>: local.get 0"],
["-> 0x40000000000001e3 <+64>: local.get 0"],
["-> 0x4000000000000201"],
["-> 0x40000000000001c0 <+29>: local.get 0"],
]
for _ in range(10):
for pattern in patterns:
self.session.cmd("n")
self.session.cmd("dis", patterns=pattern)
# Step Into
self.session.cmd(
"c", patterns=["Process 1 stopped", "stop reason = breakpoint"]
)
self.session.cmd(
"dis", patterns=["-> 0x40000000000001c0 <+29>: local.get 0"]
)
patterns = [
["-> 0x40000000000001c7 <+36>: local.get 0"],
["-> 0x40000000000001ce <+43>: local.get 0"],
["-> 0x4000000000000172 <+3>: global.get 0"],
["-> 0x400000000000018b <+28>: local.get 2"],
["-> 0x400000000000019b <+44>: local.get 2"],
["-> 0x40000000000001e0 <+61>: i32.store 0"],
["-> 0x40000000000001e3 <+64>: local.get 0"],
["-> 0x4000000000000201"],
["-> 0x40000000000001c0 <+29>: local.get 0"],
]
for _ in range(10):
for pattern in patterns:
self.session.cmd("s")
self.session.cmd("dis", patterns=pattern)
# Step Out
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
self.session.cmd("b add")
for _ in range(10):
self.session.cmd(
"c", patterns=["Process 1 stopped", "stop reason = breakpoint"]
)
self.session.cmd(
"dis", patterns=["-> 0x400000000000018b <+28>: local.get 2"]
)
self.session.cmd("fin")
self.session.cmd(
"dis", patterns=["-> 0x40000000000001e0 <+61>: i32.store 0"]
)
# Step Instruction
self.session.cmd(
"c", patterns=["Process 1 stopped", "stop reason = breakpoint"]
)
self.session.cmd(
"dis", patterns=["-> 0x400000000000018b <+28>: local.get 2"]
)
for _ in range(10):
patterns = [
["-> 0x400000000000018d <+30>: local.get 2"],
["-> 0x400000000000018f <+32>: i32.load 12"],
["-> 0x4000000000000192 <+35>: local.get 2"],
["-> 0x4000000000000194 <+37>: i32.load 8"],
["-> 0x4000000000000197 <+40>: i32.add"],
["-> 0x4000000000000198 <+41>: i32.store 4"],
["-> 0x400000000000019b <+44>: local.get 2"],
["-> 0x400000000000019d <+46>: i32.load 4"],
["-> 0x40000000000001a0 <+49>: return"],
["-> 0x40000000000001e0 <+61>: i32.store 0"],
["-> 0x40000000000001e3 <+64>: local.get 0"],
["-> 0x40000000000001e5 <+66>: i32.load 0"],
["-> 0x40000000000001e8 <+69>: local.set 1"],
["-> 0x40000000000001ea <+71>: local.get 0"],
["-> 0x40000000000001ec <+73>: i32.const 16"],
["-> 0x40000000000001ee <+75>: i32.add"],
["-> 0x40000000000001ef <+76>: global.set 0"],
["-> 0x40000000000001f5 <+82>: local.get 1"],
["-> 0x40000000000001f7 <+84>: return"],
["-> 0x4000000000000201"],
["-> 0x400000000000018b <+28>: local.get 2"],
]
for pattern in patterns:
self.session.cmd("si")
self.session.cmd("dis", patterns=pattern)
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
def memoryTest(self):
self.session.cmd(
"mem reg --all",
patterns=[
"[0x0000000000000000-0x0000000001010000) rw- wasm_memory_0_0",
"[0x0000000001010000-0x4000000000000000) ---",
"[0x4000000000000000-0x40000000000014e0) r-x wasm_module_0",
"[0x40000000000014e0-0xffffffffffffffff) ---",
],
)
self.session.cmd(
"mem reg 0x4000000000000000",
patterns=["[0x4000000000000000-0x40000000000014e0) r-x wasm_module_0"],
)
self.session.cmd(
"mem reg 0x0000000000000000",
patterns=["[0x0000000000000000-0x0000000001010000) rw- wasm_memory_0_0"],
)
def memoryReadWriteTest(self):
self.session.cmd("memory write 0x1000 0x42 0x43 0x44 0x45", [])
self.session.cmd("memory read -c 4 0x1000", patterns=["0x00001000: 42 43 44 45"])
self.session.cmd("memory write 0x0000000001000000 0x46", [])
self.session.cmd("memory read -c 1 0x0000000001000000", patterns=["0x01000000: 46"])
self.session.cmd("memory write 0x0000000001010000 0x00", patterns=["error:"])
self.session.cmd("memory write 0x4000000000000000 0x00", patterns=["error:"])
self.session.cmd("memory write 0x40000000000014e0 0x00", patterns=["error:"])
def detachTest(self):
self.session.cmd(
"detach",
patterns=[
"Process 1 detached",
],
)
def quitTest(self):
self.session.cmd("quit", [])
class SwiftWasmTestCase:
test_file = "resources/swift-wasm/test/main.js"
def execute(self):
self.breakpointTest()
self.inspectionTest()
self.stepTest()
self.memoryTest()
self.memoryReadWriteTest()
self.variableTest()
def breakpointTest(self):
self.session.cmd("b processNumber")
for _ in range(10):
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint"])
self.session.cmd("b test.swift:17")
self.session.cmd(
"br list",
patterns=[
"Current breakpoints:",
"name = 'processNumber'",
"file = 'test.swift', line = 17",
],
)
self.session.cmd("br del -f", patterns=["All breakpoints removed. (2 breakpoints)"])
def inspectionTest(self):
self.session.cmd(
"target modules list", patterns=["(0x4000000000000000)"]
)
self.session.cmd(
"list 1",
patterns=[
"func doubleValue(_ x: Int32) -> Int32",
"func addNumbers(_ a: Int32, _ b: Int32) -> Int32",
"func isEven(_ n: Int32) -> Bool",
],
)
self.session.cmd("b isEven")
self.session.cmd(
"c", patterns=["Process 1 stopped", "stop reason = breakpoint"]
)
self.session.cmd(
"dis", patterns=["-> 0x4000000000010960 <+28>: block"]
)
self.session.cmd(
"bt",
patterns=[
"frame #0: 0x4000000000010960",
"frame #1: 0x4000000000010a05",
"frame #2: 0x400000000001098f",
"frame #3: 0xc000000000000000",
],
)
self.session.cmd("var", patterns=["n ="])
self.session.cmd(
"thread list",
patterns=[
"0x4000000000010960",
"test.swift:10:7",
],
)
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
def stepTest(self):
self.session.cmd("b processNumber")
# FIXME: Step over - Current Swift LLDB is problematic with step over
# Step Into
self.session.cmd(
"c", patterns=["Process 1 stopped", "stop reason = breakpoint"]
)
self.session.cmd(
"dis", patterns=["-> 0x40000000000109cb <+56>: call 18"]
)
patterns = [
["-> 0x40000000000108b9 <+3>: global.get 0"],
["-> 0x40000000000108d6 <+32>: i32.lt_s"],
["-> 0x40000000000108ef <+57>: local.get 5"],
["-> 0x40000000000109d1 <+62>: local.set 4"],
["-> 0x40000000000109e2 <+79>: call 19"],
["-> 0x40000000000108f9 <+3>: global.get 0"],
["-> 0x4000000000010924 <+46>: i32.lt_s"],
["-> 0x400000000001093d <+71>: local.get 6"],
["-> 0x40000000000109e8 <+85>: local.set 5"],
["-> 0x40000000000109ff <+108>: call 20"],
["-> 0x4000000000010947 <+3>: global.get 0"],
["-> 0x4000000000010960 <+28>: block"],
["-> 0x400000000001097f <+59>: return"],
["-> 0x4000000000010a05 <+114>: i32.const 1"],
]
for pattern in patterns:
self.session.cmd("s")
self.session.cmd("dis", patterns=pattern)
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
# Step Out
self.session.cmd("b addNumbers")
for _ in range(10):
self.session.cmd(
"c", patterns=["Process 1 stopped", "stop reason = breakpoint"]
)
self.session.cmd(
"dis", patterns=["-> 0x4000000000010924 <+46>: i32.lt_s"]
)
self.session.cmd("fin")
self.session.cmd(
"dis", patterns=["-> 0x40000000000109e8 <+85>: local.set 5"]
)
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
# Step Instruction
self.session.cmd("b processNumber")
self.session.cmd(
"c", patterns=["Process 1 stopped", "stop reason = breakpoint"]
)
self.session.cmd(
"dis", patterns=["-> 0x40000000000109cb <+56>: call 18"]
)
patterns = [
["-> 0x40000000000108b9 <+3>: global.get 0"],
["-> 0x40000000000108bf <+9>: i32.const 16"],
["-> 0x40000000000108c1 <+11>: i32.sub"],
["-> 0x40000000000108c2 <+12>: local.set 3"],
["-> 0x40000000000108c4 <+14>: local.get 3"],
["-> 0x40000000000108c6 <+16>: i32.const 0"],
["-> 0x40000000000108c8 <+18>: i32.store 12"],
["-> 0x40000000000108cb <+21>: local.get 3"],
["-> 0x40000000000108cd <+23>: local.get 0"],
["-> 0x40000000000108cf <+25>: i32.store 12"],
["-> 0x40000000000108d2 <+28>: local.get 0"],
["-> 0x40000000000108d4 <+30>: i32.const 0"],
["-> 0x40000000000108d6 <+32>: i32.lt_s"],
["-> 0x40000000000108d7 <+33>: local.set 4"],
["-> 0x40000000000108d9 <+35>: local.get 0"],
["-> 0x40000000000108db <+37>: local.get 0"],
["-> 0x40000000000108dd <+39>: i32.add"],
["-> 0x40000000000108de <+40>: local.set 5"],
["-> 0x40000000000108e0 <+42>: block"],
["-> 0x40000000000108e2 <+44>: local.get 4"],
["-> 0x40000000000108e4 <+46>: local.get 5"],
["-> 0x40000000000108e6 <+48>: local.get 0"],
["-> 0x40000000000108e8 <+50>: i32.lt_s"],
["-> 0x40000000000108e9 <+51>: i32.xor"],
["-> 0x40000000000108ea <+52>: i32.const 1"],
["-> 0x40000000000108ec <+54>: i32.and"],
["-> 0x40000000000108ed <+55>: br_if 0"],
["-> 0x40000000000108ef <+57>: local.get 5"],
["-> 0x40000000000108f1 <+59>: return"],
["-> 0x40000000000109d1 <+62>: local.set 4"],
]
for pattern in patterns:
self.session.cmd("si")
self.session.cmd("dis", patterns=pattern)
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
def memoryTest(self):
self.session.cmd(
"mem reg --all",
patterns=[
"[0x0000000000000000-0x0000000000130000) rw- wasm_memory_0_0",
"[0x0000000000130000-0x4000000000000000) ---",
"[0x4000000000000000-0x40000000006b1239) r-x wasm_module_0",
"[0x40000000006b1239-0xffffffffffffffff) ---",
],
)
self.session.cmd(
"mem reg 0x4000000000000000",
patterns=["[0x4000000000000000-0x40000000006b1239) r-x wasm_module_0"],
)
self.session.cmd(
"mem reg 0x0000000000000000",
patterns=["[0x0000000000000000-0x0000000000130000) rw- wasm_memory_0_0"],
)
def memoryReadWriteTest(self):
self.session.cmd("memory write 0x1000 0xde 0xad 0xbe 0xef", [])
self.session.cmd("memory read -c 4 0x1000", patterns=["0x00001000: de ad be ef"])
self.session.cmd("memory write 0x0000000000120000 0xab", [])
self.session.cmd("memory read -c 1 0x0000000000120000", patterns=["0x00120000: ab"])
self.session.cmd("memory write 0x0000000000130000 0x00", patterns=["error:"])
self.session.cmd("memory write 0x4000000000000000 0x00", patterns=["error:"])
self.session.cmd("memory write 0x40000000006b1239 0x00", patterns=["error:"])
def variableTest(self):
self.session.cmd("b isEven")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint"])
self.session.cmd("v", patterns=["(Int32) n ="])
self.session.cmd("up", patterns=["-> 17 \t guard isEven(sum) else {"])
self.session.cmd("v", patterns=[
"(Int32) input =",
"(Int32) doubled =",
"(Int32) sum =",
])
class SwiftWasmGlobalTestCase:
test_file = "resources/swift-wasm/globals-test/main.js"
def execute(self):
self.session.cmd("b helper")
self.session.cmd(
"c",
patterns=[
"Process 1 stopped",
"stop reason = breakpoint",
"-> 7 \t globalCounter2 = 2",
],
)
self.session.cmd("n", patterns=["-> 8 \t globalCounter3 = 3"])
self.session.cmd("n", patterns=["-> 9 \t}"])
self.session.cmd("p globalCounter2", patterns=["(Int32) 2"])
self.session.cmd("p globalCounter3", patterns=["(Int32) 3"])
self.session.cmd("up", patterns=["-> 14 \t helper()"])
self.session.cmd("p globalCounter1", patterns=["(Int32) 1"])
self.session.cmd("br del -f", patterns=["All breakpoints removed."])
class NopDropSelectEndTestCase:
test_file = "resources/wasm/nop-drop-select-end.js"
def execute(self):
self.session.cmd("b 0x4000000000000021")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x4000000000000021: nop"])
patterns = [
["-> 0x4000000000000021: nop"],
["-> 0x4000000000000022: i32.const 42"],
["-> 0x4000000000000024: drop"],
["-> 0x4000000000000025: i32.const 1"],
["-> 0x4000000000000027: i32.const 2"],
["-> 0x4000000000000029: i32.const 1"],
["-> 0x400000000000002b: f32.select"],
["-> 0x400000000000002c: drop"],
["-> 0x400000000000002d: block"],
["-> 0x400000000000002f: i32.const 5"],
["-> 0x4000000000000031: drop"],
["-> 0x4000000000000032: end"],
["-> 0x4000000000000033: end"],
]
for _ in range(10):
for pattern in patterns:
self.session.cmd("dis", patterns=pattern)
self.session.cmd("si")
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class CallTestCase:
test_file = "resources/wasm/call.js"
def execute(self):
self.session.cmd("b 0x4000000000000036")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x4000000000000036: call 2"])
patterns = [
["-> 0x4000000000000036: call 2"],
["-> 0x400000000000003f: i32.const 42"],
["-> 0x4000000000000041: end"],
["-> 0x4000000000000038: drop"],
["-> 0x4000000000000039: call 0"],
["-> 0x400000000000003b: drop"],
["-> 0x400000000000003c: end"],
]
for _ in range(10):
for pattern in patterns:
self.session.cmd("dis", patterns=pattern)
self.session.cmd("si")
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class CallIndirectTestCase:
test_file = "resources/wasm/call-indirect.js"
def execute(self):
self.session.cmd("b 0x4000000000000046")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x4000000000000046: i32.const 0"])
patterns = [
["-> 0x4000000000000046: i32.const 0"],
["-> 0x4000000000000048: call_indirect 1"],
["-> 0x4000000000000055: i32.const 42"],
["-> 0x4000000000000057: end"],
["-> 0x400000000000004b: drop"],
["-> 0x400000000000004c: i32.const 1"],
["-> 0x400000000000004e: call_indirect 1"],
["-> 0x4000000000000051: drop"],
["-> 0x4000000000000052: end"],
]
for _ in range(10):
for pattern in patterns:
self.session.cmd("dis", patterns=pattern)
self.session.cmd("si")
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class CallRefTestCase:
test_file = "resources/wasm/call-ref.js"
def execute(self):
self.session.cmd("b 0x4000000000000043")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x4000000000000043"])
patterns = [
["-> 0x4000000000000043"],
["-> 0x4000000000000045"],
["-> 0x400000000000003e: i32.const 42"],
["-> 0x4000000000000040: end"],
["-> 0x4000000000000047: drop"],
["-> 0x4000000000000048"],
["-> 0x400000000000004a"],
["-> 0x400000000000004c: drop"],
["-> 0x400000000000004d: end"],
]
for _ in range(10):
for pattern in patterns:
self.session.cmd("dis", patterns=pattern)
self.session.cmd("si")
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class ReturnCallTestCase:
test_file = "resources/wasm/return-call.js"
def execute(self):
self.session.cmd("b 0x4000000000000035")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x4000000000000035: call 2"])
patterns = [
["-> 0x4000000000000035: call 2"],
["-> 0x4000000000000040: return_call 4"],
["-> 0x400000000000004e: i32.const 42"],
["-> 0x4000000000000050: end"],
["-> 0x4000000000000037: call 3"],
["-> 0x4000000000000047: return_call 0"],
["-> 0x4000000000000039: i32.add"],
["-> 0x400000000000003a: i32.const 1"],
["-> 0x400000000000003c: i32.add"],
["-> 0x400000000000003d: end"],
]
for _ in range(10):
for pattern in patterns:
self.session.cmd("dis", patterns=pattern)
self.session.cmd("si")
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class ReturnCallIndirectTestCase:
test_file = "resources/wasm/return-call-indirect.js"
def execute(self):
self.session.cmd("b 0x4000000000000045")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x4000000000000045: call 2"])
patterns = [
["-> 0x4000000000000045: call 2"],
["-> 0x4000000000000050: i32.const 0"],
["-> 0x4000000000000052: return_call_indirect 0"],
["-> 0x4000000000000060: i32.const 42"],
["-> 0x4000000000000062: end"],
["-> 0x4000000000000047: call 3"],
["-> 0x4000000000000058: i32.const 1"],
["-> 0x400000000000005a: return_call_indirect 0"],
["-> 0x4000000000000049: i32.add"],
["-> 0x400000000000004a: i32.const 1"],
["-> 0x400000000000004c: i32.add"],
["-> 0x400000000000004d: end"],
]
for _ in range(10):
for pattern in patterns:
self.session.cmd("dis", patterns=pattern)
self.session.cmd("si")
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class ReturnCallRefTestCase:
test_file = "resources/wasm/return-call-ref.js"
def execute(self):
for _ in range(10):
self.session.cmd("b 0x400000000000003e")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x400000000000003e: call 2"])
patterns = [
["-> 0x400000000000003e: call 2"],
["-> 0x4000000000000049"],
["-> 0x400000000000004b"],
["-> 0x4000000000000057: i32.const 42"],
["-> 0x4000000000000059: end"],
["-> 0x4000000000000040: call 3"],
["-> 0x4000000000000050"],
["-> 0x4000000000000052"],
["-> 0x4000000000000042: i32.add"],
["-> 0x4000000000000043: i32.const 1"],
["-> 0x4000000000000045: i32.add"],
["-> 0x4000000000000046: end"],
]
for pattern in patterns:
self.session.cmd("dis", patterns=pattern)
self.session.cmd("si")
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class ThrowCatchTestCase:
test_file = "resources/wasm/throw-catch.js"
def execute(self):
self.session.cmd("b 0x4000000000000071")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x4000000000000071: call 1"])
patterns = [
["-> 0x4000000000000071: call 1"],
["-> 0x400000000000003c: try i32"],
["-> 0x400000000000003e: throw 0"],
["-> 0x4000000000000044: i32.const 1"],
["-> 0x4000000000000046: end"],
["-> 0x4000000000000047: end"],
["-> 0x4000000000000073: call 3"],
["-> 0x400000000000004f: try i32"],
["-> 0x4000000000000051: call 0"],
["-> 0x4000000000000035: throw 0"],
["-> 0x4000000000000055: i32.const 2"],
["-> 0x4000000000000057: end"],
["-> 0x4000000000000058: end"],
["-> 0x4000000000000075: i32.add"],
["-> 0x4000000000000076: try i32"],
["-> 0x4000000000000078: call 6"],
["-> 0x400000000000006c: call 4"],
["-> 0x400000000000005b: call 2"],
["-> 0x400000000000004a: call 0"],
["-> 0x4000000000000035: throw 0"],
["-> 0x400000000000007c: i32.const 4"],
["-> 0x400000000000007e: end"],
["-> 0x400000000000007f: i32.add"],
["-> 0x4000000000000080: call 5"],
["-> 0x4000000000000060: try i32"],
["-> 0x4000000000000062: call 4"],
["-> 0x400000000000005b: call 2"],
["-> 0x400000000000004a: call 0"],
["-> 0x4000000000000035: throw 0"],
["-> 0x4000000000000066: i32.const 3"],
["-> 0x4000000000000068: end"],
["-> 0x4000000000000069: end"],
["-> 0x4000000000000082: i32.add"],
["-> 0x4000000000000083: end"],
]
for _ in range(10):
for pattern in patterns:
self.session.cmd("dis", patterns=pattern)
self.session.cmd("si")
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class ThrowCatchAllTestCase:
test_file = "resources/wasm/throw-catch-all.js"
def execute(self):
self.session.cmd("b 0x400000000000006e")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x400000000000006e: call 1"])
patterns = [
["-> 0x400000000000006e: call 1"],
["-> 0x400000000000003c: try i32"],
["-> 0x400000000000003e: throw 0"],
["-> 0x4000000000000043: i32.const 1"],
["-> 0x4000000000000045: end"],
["-> 0x4000000000000046: end"],
["-> 0x4000000000000070: call 3"],
["-> 0x400000000000004e: try i32"],
["-> 0x4000000000000050: call 0"],
["-> 0x4000000000000035: throw 0"],
["-> 0x4000000000000053: i32.const 2"],
["-> 0x4000000000000055: end"],
["-> 0x4000000000000056: end"],
["-> 0x4000000000000072: i32.add"],
["-> 0x4000000000000073: try i32"],
["-> 0x4000000000000075: call 6"],
["-> 0x4000000000000069: call 4"],
["-> 0x4000000000000059: call 2"],
["-> 0x4000000000000049: call 0"],
["-> 0x4000000000000035: throw 0"],
["-> 0x4000000000000078: i32.const 4"],
["-> 0x400000000000007a: end"],
["-> 0x400000000000007b: i32.add"],
["-> 0x400000000000007c: call 5"],
["-> 0x400000000000005e: try i32"],
["-> 0x4000000000000060: call 4"],
["-> 0x4000000000000059: call 2"],
["-> 0x4000000000000049: call 0"],
["-> 0x4000000000000035: throw 0"],
["-> 0x4000000000000063: i32.const 3"],
["-> 0x4000000000000065: end"],
["-> 0x4000000000000066: end"],
["-> 0x400000000000007e: i32.add"],
["-> 0x400000000000007f: end"],
]
for _ in range(10):
for pattern in patterns:
self.session.cmd("dis", patterns=pattern)
self.session.cmd("si")
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class DelegateTestCase:
test_file = "resources/wasm/delegate.js"
def execute(self):
self.session.cmd("b 0x40000000000000c6")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x40000000000000c6: call 1"])
patterns = [
# Test function entry
["-> 0x40000000000000c6: call 1"],
# Function 1: delegate_to_parent - delegate depth 0
["-> 0x400000000000003e: try i32"],
["-> 0x4000000000000040: try i32"],
["-> 0x4000000000000042: throw 0"],
["-> 0x4000000000000048: i32.const 1"], # caught by parent
["-> 0x400000000000004a: end"],
["-> 0x400000000000004b: end"],
# Back to test_all
["-> 0x40000000000000c8: call 2"],
# Function 2: delegate_to_grandparent - delegate depth 1
["-> 0x400000000000004e: try i32"],
["-> 0x4000000000000050: try i32"],
["-> 0x4000000000000052: try i32"],
["-> 0x4000000000000054: throw 0"],
[
"-> 0x4000000000000060: i32.const 2"
], # caught by grandparent (skipped parent)
["-> 0x4000000000000062: end"],
["-> 0x4000000000000063: end"],
# Back to test_all
["-> 0x40000000000000ca: i32.add"],
["-> 0x40000000000000cb: call 3"],
# Function 3: delegate_to_great_grandparent - delegate depth 2
["-> 0x4000000000000066: try i32"],
["-> 0x4000000000000068: try i32"],
["-> 0x400000000000006a: try i32"],
["-> 0x400000000000006c: try i32"],
["-> 0x400000000000006e: throw 0"],
[
"-> 0x4000000000000080: i32.const 3"
], # caught by great-grandparent (skipped 2 levels)
["-> 0x4000000000000082: end"],
["-> 0x4000000000000083: end"],
# Back to test_all
["-> 0x40000000000000cd: i32.add"],
["-> 0x40000000000000ce: call 5"],
# Function 5: catches_delegated_from_callee
["-> 0x400000000000008f: try i32"],
["-> 0x4000000000000091: call 4"],
# Function 4: no_handler_delegates_to_caller - delegates to caller
["-> 0x4000000000000086: try i32"],
["-> 0x4000000000000088: throw 0"],
# Back to function 5's catch handler
[
"-> 0x4000000000000095: i32.const 4"
], # caller catches delegated exception
["-> 0x4000000000000097: end"],
["-> 0x4000000000000098: end"],
# Back to test_all
["-> 0x40000000000000d0: i32.add"],
["-> 0x40000000000000d1: call 6"],
# Function 6: delegate_chain - multiple delegates in chain
["-> 0x400000000000009b: try i32"],
["-> 0x400000000000009d: try i32"],
["-> 0x400000000000009f: try i32"],
["-> 0x40000000000000a1: throw 0"],
# Inner delegates to middle, middle delegates to outer
[
"-> 0x40000000000000a9: i32.const 5"
], # outer catches after delegate chain
["-> 0x40000000000000ab: end"],
["-> 0x40000000000000ac: end"],
# Back to test_all
["-> 0x40000000000000d3: i32.add"],
["-> 0x40000000000000d4: call 7"],
# Function 7: delegate_past_catch_all - delegate skips catch_all
["-> 0x40000000000000af: try i32"],
["-> 0x40000000000000b1: try i32"],
["-> 0x40000000000000b3: try i32"],
["-> 0x40000000000000b5: throw 0"],
[
"-> 0x40000000000000c0: i32.const 6"
], # grandparent catches (skipped parent's catch_all)
["-> 0x40000000000000c2: end"],
["-> 0x40000000000000c3: end"],
# Back to test_all final add
["-> 0x40000000000000d6: i32.add"],
["-> 0x40000000000000d7: end"],
]
for _ in range(10):
for pattern in patterns:
self.session.cmd("dis", patterns=pattern)
self.session.cmd("si")
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class RethrowTestCase:
test_file = "resources/wasm/rethrow.js"
def execute(self):
self.session.cmd("b 0x40000000000000b8")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x40000000000000b8: call 0"])
patterns = [
# Test function entry
["-> 0x40000000000000b8: call 0"],
# Function 0: basic_rethrow_in_catch
["-> 0x4000000000000036: try i32"],
["-> 0x4000000000000038: try i32"],
["-> 0x400000000000003a: throw 0"],
["-> 0x400000000000003e: rethrow 0"],
["-> 0x4000000000000043: i32.const 1"], # outer catches rethrown exception
["-> 0x4000000000000045: end"],
["-> 0x4000000000000046: end"],
# Back to test_all
["-> 0x40000000000000ba: call 1"],
# Function 1: rethrow_in_catch_all
["-> 0x4000000000000049: try i32"],
["-> 0x400000000000004b: try i32"],
["-> 0x400000000000004d: throw 0"],
["-> 0x4000000000000050: rethrow 0"],
[
"-> 0x4000000000000055: i32.const 2"
], # outer catches rethrown from catch_all
["-> 0x4000000000000057: end"],
["-> 0x4000000000000058: end"],
# Back to test_all
["-> 0x40000000000000bc: i32.add"],
["-> 0x40000000000000bd: call 2"],
# Function 2: rethrow_after_partial_handling
["-> 0x400000000000005b: try i32"],
["-> 0x400000000000005d: try i32"],
["-> 0x400000000000005f: throw 0"],
["-> 0x4000000000000063: rethrow 0"],
[
"-> 0x4000000000000068: i32.const 3"
], # outer catches rethrown after partial handling
["-> 0x400000000000006a: end"],
["-> 0x400000000000006b: end"],
# Back to test_all
["-> 0x40000000000000bf: i32.add"],
["-> 0x40000000000000c0: call 4"],
# Function 4: catches_rethrown_from_callee
["-> 0x400000000000007a: try i32"],
["-> 0x400000000000007c: call 3"],
# Function 3: rethrows_to_caller
["-> 0x400000000000006e: try i32"],
["-> 0x4000000000000070: throw 0"],
["-> 0x4000000000000074: rethrow 0"],
# Back to function 4's catch handler
[
"-> 0x4000000000000080: i32.const 4"
], # caller catches rethrown exception
["-> 0x4000000000000082: end"],
["-> 0x4000000000000083: end"],
# Back to test_all
["-> 0x40000000000000c2: i32.add"],
["-> 0x40000000000000c3: call 5"],
# Function 5: rethrow_chain - multiple rethrows through nested handlers
["-> 0x4000000000000086: try i32"],
["-> 0x4000000000000088: try i32"],
["-> 0x400000000000008a: try i32"],
["-> 0x400000000000008c: throw 0"],
["-> 0x4000000000000090: rethrow 0"], # inner rethrows to middle
["-> 0x4000000000000095: rethrow 0"], # middle rethrows to outer
[
"-> 0x400000000000009a: i32.const 5"
], # outer catches after rethrow chain
["-> 0x400000000000009c: end"],
["-> 0x400000000000009d: end"],
# Back to test_all
["-> 0x40000000000000c5: i32.add"],
["-> 0x40000000000000c6: call 6"],
# Function 6: mixed_rethrow_with_catch_all
["-> 0x40000000000000a0: try i32"],
["-> 0x40000000000000a2: try i32"],
["-> 0x40000000000000a4: try i32"],
["-> 0x40000000000000a6: throw 0"],
[
"-> 0x40000000000000a9: rethrow 0"
], # rethrow from catch_all to middle catch
[
"-> 0x40000000000000ae: rethrow 0"
], # rethrow from catch to outer catch_all
[
"-> 0x40000000000000b2: i32.const 6"
], # outer catch_all catches rethrown exception
["-> 0x40000000000000b4: end"],
["-> 0x40000000000000b5: end"],
# Back to test_all final add
["-> 0x40000000000000c8: i32.add"],
["-> 0x40000000000000c9: end"],
]
for _ in range(10):
for pattern in patterns:
self.session.cmd("dis", patterns=pattern)
self.session.cmd("si")
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class ThrowRefTestCase:
test_file = "resources/wasm/throw-ref.js"
def execute(self):
# Define all test patterns at the top for clarity
# Function 0: catch-throw_ref-0 - basic throw_ref
func0_iter1 = [
"-> 0x40000000000000e6: try_table",
"-> 0x40000000000000ec: throw 0",
"-> 0x40000000000000f1: throw_ref",
]
# Function 1: catch-throw_ref-1 - conditional throw_ref (param=0 throws, param=1 returns 23)
func1_iter1 = [
"-> 0x40000000000000fb: try_table i32",
"-> 0x4000000000000101: throw 0",
"-> 0x4000000000000106: local.get 0",
"-> 0x4000000000000108: i32.eqz",
"-> 0x4000000000000109: if",
"-> 0x400000000000010b: throw_ref",
]
func1_iter2 = [
"-> 0x40000000000000fb: try_table i32",
"-> 0x4000000000000101: throw 0",
"-> 0x4000000000000106: local.get 0",
"-> 0x4000000000000108: i32.eqz",
"-> 0x4000000000000109: if",
"-> 0x400000000000010d: drop",
"-> 0x400000000000010e: end",
"-> 0x400000000000010f: i32.const 23",
"-> 0x4000000000000111: end",
]
# Function 2: catchall-throw_ref-0 - catch_all_ref with throw_ref
func2_iter1 = [
"-> 0x400000000000011a: try_table exnref",
"-> 0x400000000000011f: throw 0",
"-> 0x4000000000000123: throw_ref",
]
# Function 3: catchall-throw_ref-1 - conditional catch_all_ref
func3_iter1 = [
"-> 0x400000000000012d: try_table i32",
"-> 0x4000000000000132: throw 0",
"-> 0x4000000000000137: local.get 0",
"-> 0x4000000000000139: i32.eqz",
"-> 0x400000000000013a: if",
"-> 0x400000000000013c: throw_ref",
]
func3_iter2 = [
"-> 0x400000000000012d: try_table i32",
"-> 0x4000000000000132: throw 0",
"-> 0x4000000000000137: local.get 0",
"-> 0x4000000000000139: i32.eqz",
"-> 0x400000000000013a: if",
"-> 0x400000000000013e: drop",
"-> 0x400000000000013f: end",
"-> 0x4000000000000140: i32.const 23",
"-> 0x4000000000000142: end",
]
# Function 4: throw_ref-nested - stores two different exceptions (3 iterations)
# Entry at 0x14b is verified by helper, patterns start from 0x14d
# Structure: Two sequential blocks (not nested), each catches a different exception
func4_nested_common = [
"-> 0x400000000000014d: try_table i32",
"-> 0x4000000000000153: throw 1",
"-> 0x4000000000000158: local.set 1",
"-> 0x400000000000015a: block exnref",
"-> 0x400000000000015c: try_table i32",
"-> 0x4000000000000162: throw 0",
"-> 0x4000000000000167: local.set 2",
"-> 0x4000000000000169: local.get 0",
"-> 0x400000000000016b: i32.const 0",
"-> 0x400000000000016d: i32.eq",
"-> 0x400000000000016e: if",
]
func4_iter1 = func4_nested_common + [
"-> 0x4000000000000170: local.get 1",
"-> 0x4000000000000172: throw_ref",
]
func4_iter2 = func4_nested_common + [
"-> 0x4000000000000174: local.get 0",
"-> 0x4000000000000176: i32.const 1",
"-> 0x4000000000000178: i32.eq",
"-> 0x4000000000000179: if",
"-> 0x400000000000017b: local.get 2",
"-> 0x400000000000017d: throw_ref",
]
func4_iter3 = func4_nested_common + [
"-> 0x4000000000000174: local.get 0",
"-> 0x4000000000000176: i32.const 1",
"-> 0x4000000000000178: i32.eq",
"-> 0x4000000000000179: if",
"-> 0x400000000000017f: i32.const 23",
"-> 0x4000000000000181: end",
]
# Function 5: throw_ref-recatch - catch, store, re-throw_ref, re-catch
# Two sequential try_table blocks
func5_iter1 = [
"-> 0x400000000000018c: try_table i32",
"-> 0x4000000000000192: throw 0",
"-> 0x4000000000000197: local.set 1",
"-> 0x4000000000000199: block exnref",
"-> 0x400000000000019b: try_table i32",
"-> 0x40000000000001a1: local.get 0",
"-> 0x40000000000001a3: i32.eqz",
"-> 0x40000000000001a4: if",
"-> 0x40000000000001a6: local.get 1",
"-> 0x40000000000001a8: throw_ref",
"-> 0x40000000000001af: drop",
"-> 0x40000000000001b0: i32.const 23",
"-> 0x40000000000001b2: end",
]
func5_iter2 = [
"-> 0x400000000000018c: try_table i32",
"-> 0x4000000000000192: throw 0",
"-> 0x4000000000000197: local.set 1",
"-> 0x4000000000000199: block exnref",
"-> 0x400000000000019b: try_table i32",
"-> 0x40000000000001a1: local.get 0",
"-> 0x40000000000001a3: i32.eqz",
"-> 0x40000000000001a4: if",
"-> 0x40000000000001aa: i32.const 42",
"-> 0x40000000000001ac: end",
"-> 0x40000000000001ad: return",
]
# Function 6: throw_ref-stack-polymorphism - tests polymorphic throw_ref
func6_iter1 = [
"-> 0x40000000000001bd: try_table f64",
"-> 0x40000000000001c3: throw 0",
"-> 0x40000000000001c8: local.set 0",
"-> 0x40000000000001ca: i32.const 1",
"-> 0x40000000000001cc: local.get 0",
"-> 0x40000000000001ce: throw_ref",
]
# Execute all test functions
self.test_function_with_breakpoint("0x40000000000000e4", [func0_iter1])
self.test_function_with_breakpoint(
"0x40000000000000f9", [func1_iter1, func1_iter2]
)
self.test_function_with_breakpoint("0x4000000000000118", [func2_iter1])
self.test_function_with_breakpoint(
"0x400000000000012b", [func3_iter1, func3_iter2]
)
self.test_function_with_breakpoint(
"0x400000000000014b", [func4_iter1, func4_iter2, func4_iter3]
)
self.test_function_with_breakpoint(
"0x400000000000018a", [func5_iter1, func5_iter2]
)
self.test_function_with_breakpoint("0x40000000000001bb", [func6_iter1])
def test_function_iteration(self, patterns):
for pattern in patterns:
self.session.cmd("si")
self.session.cmd("dis", patterns=[pattern])
def test_function_with_breakpoint(self, entry_address, iterations):
# Set breakpoint at function entry
self.session.cmd(f"b {entry_address}")
entry_pattern = f"-> {entry_address}: block exnref"
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", entry_pattern])
# Verify we're at function entry
self.session.cmd("dis", patterns=[entry_pattern])
# Run each iteration
for i, patterns in enumerate(iterations):
if i > 0:
# Continue to next iteration and verify we're at entry
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", entry_pattern])
self.session.cmd("dis", patterns=[entry_pattern])
# Step through all patterns for this iteration
self.test_function_iteration(patterns)
# Remove breakpoint
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class TryTableTestCase:
test_file = "resources/wasm/try-table.js"
def execute(self):
self.session.cmd("b 0x40000000000000aa")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x40000000000000aa: call 1"])
patterns = [
["-> 0x40000000000000aa: call 1"],
["-> 0x400000000000003f: block"],
["-> 0x4000000000000041: try_table i32"],
["-> 0x4000000000000047: throw 0"],
["-> 0x400000000000004e: i32.const 1"],
["-> 0x4000000000000050: end"],
["-> 0x40000000000000ac: call 3"],
["-> 0x4000000000000058: block"],
["-> 0x400000000000005a: try_table i32"],
["-> 0x4000000000000060: call 0"],
["-> 0x4000000000000038: throw 0"],
["-> 0x4000000000000065: i32.const 2"],
["-> 0x4000000000000067: end"],
["-> 0x40000000000000ae: i32.add"],
["-> 0x40000000000000af: block"],
["-> 0x40000000000000b1: try_table i32"],
["-> 0x40000000000000b7: call 6"],
["-> 0x4000000000000081: call 4"],
["-> 0x400000000000006a: call 2"],
["-> 0x4000000000000053: call 0"],
["-> 0x4000000000000038: throw 0"],
["-> 0x40000000000000c8: drop"],
["-> 0x40000000000000c9: i32.const 4"],
["-> 0x40000000000000cb: i32.const 3"],
["-> 0x40000000000000cd: i32.add"],
["-> 0x40000000000000ce: call 5"],
["-> 0x400000000000006f: block"],
["-> 0x4000000000000071: try_table i32"],
["-> 0x4000000000000077: call 4"],
["-> 0x400000000000006a: call 2"],
["-> 0x4000000000000053: call 0"],
["-> 0x4000000000000038: throw 0"],
["-> 0x400000000000007c: i32.const 3"],
["-> 0x400000000000007e: end"],
["-> 0x40000000000000d0: i32.add"],
["-> 0x40000000000000d1: call 7"],
["-> 0x4000000000000086: block"],
["-> 0x4000000000000088: try_table"],
["-> 0x400000000000008d: throw 0"],
["-> 0x4000000000000094: i32.const 5"],
["-> 0x4000000000000096: end"],
["-> 0x40000000000000d3: i32.add"],
["-> 0x40000000000000d4: call 8"],
["-> 0x4000000000000099: block"],
["-> 0x400000000000009b: try_table"],
["-> 0x40000000000000a0: call 0"],
["-> 0x4000000000000038: throw 0"],
["-> 0x40000000000000a5: i32.const 6"],
["-> 0x40000000000000a7: end"],
["-> 0x40000000000000d6: i32.add"],
["-> 0x40000000000000d7: end"],
]
for _ in range(10):
for pattern in patterns:
self.session.cmd("dis", patterns=pattern)
self.session.cmd("si")
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class SystemCallTestCase:
test_file = "resources/wasm/system-call.js"
def execute(self):
self.session.cmd("dis", patterns=["error: read memory from 0x8000000000000000 failed"])
class MultiVMSameModuleSameFunctionTestCase:
test_file = "resources/wasm/multi-vm-same-module-same-func.js"
def execute(self):
self.session.cmd("th list", patterns=["thread #1", "thread #2", "thread #3"])
self.session.cmd("b 0x4000000100000024")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x4000000100000024: nop"])
patterns = [
["-> 0x4000000100000025: i32.const 42"],
["-> 0x4000000100000027: drop"],
["-> 0x4000000100000028: nop"],
["-> 0x4000000100000029: end"],
]
for pattern in patterns:
self.session.cmd("si", patterns=pattern)
class MultiVMSameModuleDifferentFunctionsTestCase:
test_file = "resources/wasm/multi-vm-same-module-different-funcs.js"
def execute(self):
self.session.cmd("th list", patterns=["thread #1", "thread #2"])
self.session.cmd("b 0x4000000000000034")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x4000000000000034"])
patterns = [
["-> 0x4000000000000035: i32.const 10"],
["-> 0x4000000000000037: drop"],
["-> 0x4000000000000038: nop"],
["-> 0x4000000000000039: i32.const 20"],
["-> 0x400000000000003b: drop"],
["-> 0x400000000000003c: end"],
]
for pattern in patterns:
self.session.cmd("si", patterns=pattern)
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
self.session.cmd("b 0x400000010000003f")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 0x400000010000003f"])
patterns = [
["-> 0x4000000100000040: i32.const 30"],
["-> 0x4000000100000042: drop"],
["-> 0x4000000100000043: nop"],
["-> 0x4000000100000044: i32.const 40"],
["-> 0x4000000100000046: drop"],
["-> 0x4000000100000047: end"],
]
for pattern in patterns:
self.session.cmd("si", patterns=pattern)
self.session.cmd(
"br del -f", patterns=["All breakpoints removed. (1 breakpoint)"]
)
class MemoryAtomicWaitTestCase:
test_file = "resources/wasm/memory-atomic-wait.js"
extra_jsc_options = ["--useDollarVM=1"]
def execute(self):
self.session.cmd("th list", patterns=["thread #1", "thread #2"])
self.session.cmd("b 0x4000000000000030")
self.session.cmd(
"c",
patterns=[
"Process 1 stopped",
"stop reason = breakpoint",
"-> 0x4000000000000030",
],
)
self.session.cmd("si", patterns=["-> 0x4000000000000034: end"])
self.session.cmd(
"c",
patterns=[
"Process 1 stopped",
"stop reason = breakpoint",
"-> 0x4000000000000030: memory.atomic.wait32",
],
)
self.session.cmd("br del -f", patterns=["All breakpoints removed. (1 breakpoint)"])
class MemoryAtomicWaitNoTimeoutTestCase:
test_file = "resources/wasm/memory-atomic-wait-no-timeout.js"
extra_jsc_options = ["--useDollarVM=1"]
def execute(self):
self.session.cmd("th list", patterns=["thread #1", "thread #2"])
self.session.cmd("dis", patterns=["-> 0x4000000000000030: memory.atomic.wait32 0"])
class DoCatchThrowTestCase:
test_file = "resources/swift-wasm/do-catch-throw/main.js"
def execute(self):
self.session.cmd("b testDoThrowCatch")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 14"])
self.session.cmd("n", patterns=["-> 15"])
self.session.cmd("n", patterns=["-> 18"])
self.session.cmd("n", patterns=["-> 19"])
self.session.cmd("br del -f", patterns=["All breakpoints removed. (1 breakpoint)"])
self.session.cmd("b testDoThrowCatchNested")
self.session.cmd("c", patterns=["Process 1 stopped", "stop reason = breakpoint", "-> 26"])
self.session.cmd("n", patterns=["-> 31"])
self.session.cmd("n", patterns=["-> 32"])
self.session.cmd("n", patterns=["-> 37"])
self.session.cmd("n", patterns=["-> 42"])
self.session.cmd("br del -f", patterns=["All breakpoints removed. (1 breakpoint)"])
# FIXME: Swift WASM Compiler Bug Incorrect DWARF Line Numbers rdar://169306069
# self.session.cmd("b testDoThrowCatch")
# self.session.cmd("b testDoThrowFuncCatchNested")
class WasmWasmWasmCallStackTestCase:
test_file = "resources/wasm/wasm-wasm-wasm.js"
def execute(self):
self.session.cmd("b 0x400000000000003a")
self.session.cmd("c", patterns=["stop reason = breakpoint", "0x400000000000003a"])
self.session.cmd(
"bt",
patterns=[
"frame #0: 0x400000000000003a", # wasm_inner (nop)
"frame #1: 0x4000000000000037", # wasm_middle return PC (after call wasm_inner)
"frame #2: 0x4000000000000032", # test return PC (after call wasm_middle)
"frame #3: 0xc000000000000000", # JS main loop
],
)
class JsWasmJsWasmCallStackTestCase:
test_file = "resources/wasm/js-wasm-js-wasm.js"
def execute(self):
self.session.cmd("b 0x4000000000000045")
self.session.cmd("c", patterns=["stop reason = breakpoint", "0x4000000000000045"])
self.session.cmd(
"bt",
patterns=[
"frame #0: 0x4000000000000045", # wasm_inner (nop)
"frame #1: 0xc000000000000000", # JS callback
"frame #2: 0x4000000000000042", # test call-site return PC (after 'call 0' at 0x40)
"frame #3: 0xc000000000000000", # JS main loop
],
)
class JsJsWasmJsJsWasmCallStackTestCase:
test_file = "resources/wasm/js-js-wasm-js-js-wasm.js"
def execute(self):
self.session.cmd("b 0x4000000000000045")
self.session.cmd("c", patterns=["stop reason = breakpoint", "0x4000000000000045"])
self.session.cmd(
"bt",
patterns=[
"frame #0: 0x4000000000000045", # wasm_inner (nop)
"frame #1: 0xc000000000000000", # js_c
"frame #2: 0xc000000000000000", # callback
"frame #3: 0x4000000000000042", # test call-site return PC (after 'call 0' at 0x40)
"frame #4: 0xc000000000000000", # js_b
"frame #5: 0xc000000000000000", # js_a
"frame #6: 0xc000000000000000", # JS main loop
],
)
class WasmWasmJsWasmWasmCallStackTestCase:
test_file = "resources/wasm/wasm-wasm-js-wasm-wasm.js"
def execute(self):
self.session.cmd("b 0x400000000000005f")
self.session.cmd("c", patterns=["stop reason = breakpoint", "0x400000000000005f"])
self.session.cmd(
"bt",
patterns=[
"frame #0: 0x400000000000005f", # wasm_leaf nop
"frame #1: 0x400000000000005c", # test_c return PC (after call wasm_leaf at 0x5a)
"frame #2: 0xc000000000000000", # mid_callback JS frame
"frame #3: 0x4000000000000057", # test_b return PC (after call mid_callback at 0x55, from WasmToJSIPIntReturnPCSlot)
"frame #4: 0x4000000000000052", # test_a return PC (after call test_b at 0x50, from test_b cfr−8)
"frame #5: 0xc000000000000000", # JS main loop
],
)
class WasmJsWasmJsWasmCallStackTestCase:
test_file = "resources/wasm/wasm-js-wasm-js-wasm.js"
def execute(self):
self.session.cmd("b 0x400000000000006c")
self.session.cmd("c", patterns=["stop reason = breakpoint", "0x400000000000006c"])
self.session.cmd(
"bt",
patterns=[
"frame #0: 0x400000000000006c", # wasm_inner nop
"frame #1: 0xc000000000000000", # js_mid_inner JS frame
"frame #2: 0x4000000000000069", # test_mid return PC (after call mid_inner at 0x67, from WasmToJSIPIntReturnPCSlot)
"frame #3: 0xc000000000000000", # js_mid_outer JS frame
"frame #4: 0x4000000000000064", # test_outer return PC (after call mid_outer at 0x62, from WasmToJSIPIntReturnPCSlot)
"frame #5: 0xc000000000000000", # JS main loop
],
)
class SwiftWasmCrashTestCase:
test_file = "resources/swift-wasm/crash-test/main.js"
def execute(self):
for _ in range(10):
self.session.cmd("c", patterns=["Process 1 stopped"])
self.session.cmd("dis", patterns=["-> 0x4000000000010a43 <+1>: unreachable"])
self.session.cmd(
"bt",
patterns=[
"frame #0: 0x4000000000010a43",
"frame #1: 0x4000000000010a43",
"frame #2: 0x4000000000010a6a",
"frame #3: 0x4000000000010a46",
"frame #4: 0xc000000000000000",
]
)
class WasmUnreachableFaultTestCase:
test_file = "resources/wasm/unreachable.js"
def execute(self):
for _ in range(10):
self.session.cmd("c", patterns=["Process 1 stopped"])
self.session.cmd("dis", patterns=["-> 0x4000000000000024: unreachable"])
self.session.cmd(
"bt",
patterns=[
"frame #0: 0x4000000000000024",
"frame #1: 0xc000000000000000",
]
)
class WasmDivByZeroTrapTestCase:
test_file = "resources/wasm/trap-div-by-zero.js"
def execute(self):
for _ in range(10):
self.session.cmd("c", patterns=["Process 1 stopped", "Division by zero"])
self.session.cmd("dis", patterns=["-> 0x400000000000002d: i32.div_s"])
self.session.cmd(
"bt",
patterns=[
"frame #0: 0x400000000000002d",
"frame #1: 0xc000000000000000",
]
)
class WasmOutOfBoundsCallIndirectTrapTestCase:
test_file = "resources/wasm/trap-out-of-bounds-call-indirect.js"
def execute(self):
for _ in range(10):
self.session.cmd("c", patterns=["Process 1 stopped", "Out of bounds call_indirect"])
self.session.cmd("dis", patterns=["-> 0x4000000000000031: call_indirect 0"])
self.session.cmd(
"bt",
patterns=[
"frame #0: 0x4000000000000031",
"frame #1: 0xc000000000000000",
]
)
class WasmStackOverflowTrapTestCase:
test_file = "resources/wasm/trap-stack-overflow.js"
extra_jsc_options = ["--maxPerThreadStackUsage=524288"]
def execute(self):
for _ in range(10):
self.session.cmd("c", patterns=["Process 1 stopped", "Stack overflow", "-> 0x4000000000000028: call"])
self.session.cmd(
"bt",
patterns=[
"frame #0: 0x4000000000000028",
"frame #1: 0x400000000000002a",
"frame #99: 0x400000000000002a",
]
)
class WasmOobMemoryTrapTestCase:
test_file = "resources/wasm/trap-oob-memory.js"
def execute(self):
for _ in range(10):
self.session.cmd("c", patterns=["Process 1 stopped", "Out of bounds memory access"])
self.session.cmd("dis", patterns=["-> 0x4000000000000032: i32.load"])
self.session.cmd(
"bt",
patterns=[
"frame #0: 0x4000000000000032",
"frame #1: 0xc000000000000000",
]
)
class DynamicModuleLoadTestCase:
test_file = "resources/wasm/dynamic-module-load.js"
extra_jsc_options = ["--useDollarVM=1"]
def execute(self):
# Set a breakpoint at the 'end' instruction of func_a in module 1 (virtual address
# 0x4000000000000023). Module 1 is already loaded, so the breakpoint resolves immediately.
self.session.cmd("b 0x4000000000000023", patterns=["Breakpoint 1"])
# Resume: stops at the func_a breakpoint in module 1.
# Disassembly confirms the stopped instruction is 'end' at the expected address.
self.session.cmd("c", patterns=["Process 1 stopped", "-> 0x4000000000000023: end"])
# Resume: stops for the module-load notification (library:; T-packet) when module 2 is
# instantiated. LLDB re-queries qXfer:libraries:read and loads module 2.
self.session.cmd("c", patterns=["Process 1 stopped", "loaded new wasm module with ids: 1"])
# Set a breakpoint at the 'end' instruction of func_b in module 2 (virtual address
# 0x4000000100000023). Module 2 is now loaded, so the breakpoint resolves immediately.
self.session.cmd("b 0x4000000100000023", patterns=["Breakpoint 2"])
# Resume: stops at the func_b breakpoint in module 2.
# Disassembly confirms the stopped instruction is 'end' at the expected address.
self.session.cmd("c", patterns=["Process 1 stopped", "-> 0x4000000100000023: end"])
class SwiftWasmDynamicModuleLoadTestCase:
test_file = "resources/swift-wasm/dynamic-module-load/main.js"
extra_jsc_options = ["--useDollarVM=1"]
def execute(self):
# Module A is loaded at the start, so this breakpoint is resolved immediately.
self.session.cmd("b func_a", patterns=["Breakpoint 1", "func_a"])
# Module B is loaded dynamically later, so this breakpoint is pending at the start.
self.session.cmd("b func_b", patterns=["pending"])
# Resume: stops at the func_a breakpoint (module A), confirming that the breakpoint is set and hit correctly.
self.session.cmd("c", patterns=["Process 1 stopped", "func_a"])
# Resume: stops at when Module B is loaded and the associated instance is created. This stop trigger
# LLDB re-querying debug info and resolving the pending breakpoint for func_b, confirming that dynamic
# module load triggers pending breakpoint resolution.
self.session.cmd("c", patterns=["Process 1 stopped", "loaded new wasm module with ids: 1"])
self.session.cmd("br list", patterns=["func_a", "func_b"])
# Resume: stops at the func_b breakpoint (module B) on the first call, confirming that the pending breakpoint was resolved via debug info.
self.session.cmd("c", patterns=["Process 1 stopped", "func_b"])
class ModuleNamingFromNameSectionTestCase:
test_file = "resources/wasm/named-streaming-module.js"
extra_jsc_options = ["--useDollarVM=1"]
def execute(self):
self.session.cmd("image list", patterns=["mymodule"])
# Set a breakpoint at func_a's 'end' instruction by virtual address.
self.session.cmd("b 0x4000000000000023", patterns=["Breakpoint 1"])
# Resume: stops at the breakpoint; disassembly confirms the module name in the frame.
self.session.cmd("c", patterns=["Process 1 stopped", "-> 0x4000000000000023: end"])
self.session.cmd("br del -f", patterns=["All breakpoints removed. (1 breakpoint)"])
class StreamingModuleSourceURLTestCase:
test_file = "resources/wasm/url-named-streaming-module.js"
extra_jsc_options = ["--useDollarVM=1"]
def execute(self):
self.session.cmd("image list", patterns=["cdn.example.com/path/canvaskit.wasm"])
# Set a breakpoint at func_b's 'end' instruction by virtual address.
self.session.cmd("b 0x4000000000000023", patterns=["Breakpoint 1"])
# Resume: stops at the breakpoint in the URL-named streaming-compiled module.
self.session.cmd("c", patterns=["Process 1 stopped", "-> 0x4000000000000023: end"])
self.session.cmd("br del -f", patterns=["All breakpoints removed. (1 breakpoint)"])
class StreamingModuleLoadTestCase:
test_file = "resources/wasm/streaming-module-load.js"
extra_jsc_options = ["--useDollarVM=1"]
def execute(self):
# The streaming module is already loaded, so the breakpoint resolves immediately.
self.session.cmd("b 0x4000000000000023", patterns=["Breakpoint 1"])
# Resume: stops at the func_a breakpoint in the streaming-compiled module.
# Disassembly confirms the stopped instruction is 'end' at the expected address.
self.session.cmd("c", patterns=["Process 1 stopped", "-> 0x4000000000000023: end"])
self.session.cmd("br del -f", patterns=["All breakpoints removed. (1 breakpoint)"])
class SwiftWasmFatalErrorTestCase:
test_file = "resources/swift-wasm/fatal-error-test/main.js"
def execute(self):
for _ in range(10):
self.session.cmd("c", patterns=["Process 1 stopped"])
self.session.cmd("bt", patterns=["main.swift:4"])
ALL_TESTS = [
CWasmTestCase,
SwiftWasmTestCase,
SwiftWasmGlobalTestCase,
NopDropSelectEndTestCase,
CallTestCase,
CallIndirectTestCase,
CallRefTestCase,
ReturnCallTestCase,
ReturnCallIndirectTestCase,
ReturnCallRefTestCase,
ThrowCatchTestCase,
ThrowCatchAllTestCase,
DelegateTestCase,
RethrowTestCase,
ThrowRefTestCase,
TryTableTestCase,
SystemCallTestCase,
MultiVMSameModuleSameFunctionTestCase,
MultiVMSameModuleDifferentFunctionsTestCase,
MemoryAtomicWaitTestCase,
MemoryAtomicWaitNoTimeoutTestCase,
DoCatchThrowTestCase,
WasmWasmWasmCallStackTestCase,
JsWasmJsWasmCallStackTestCase,
JsJsWasmJsJsWasmCallStackTestCase,
WasmWasmJsWasmWasmCallStackTestCase,
WasmJsWasmJsWasmCallStackTestCase,
SwiftWasmCrashTestCase,
WasmUnreachableFaultTestCase,
WasmDivByZeroTrapTestCase,
WasmOutOfBoundsCallIndirectTrapTestCase,
WasmStackOverflowTrapTestCase,
WasmOobMemoryTrapTestCase,
DynamicModuleLoadTestCase,
SwiftWasmDynamicModuleLoadTestCase,
ModuleNamingFromNameSectionTestCase,
StreamingModuleSourceURLTestCase,
StreamingModuleLoadTestCase,
SwiftWasmFatalErrorTestCase,
]