Skip to content

Commit 68ac57e

Browse files
committed
test(gdb): add integ test to verify gdb works on x86
The integ test opens gdb on a subprocess which connects to Firecracker, sets a breakpoint and continues until boot is complete. If the VM boots correctly and the breakpoint gets hit, then the test will succeed. This test currently only works on x86 as GDB requires a vmlinux image (we use a uImage on ARM). Signed-off-by: Riccardo Mancini <[email protected]>
1 parent fa2627a commit 68ac57e

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

tests/framework/microvm.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ def __init__(
287287

288288
self.help = MicrovmHelpers(self)
289289

290+
self.gdb_socket = None
291+
290292
def __repr__(self):
291293
return f"<Microvm id={self.id}>"
292294

@@ -1198,6 +1200,11 @@ def wait_for_ssh_up(self):
11981200
# run commands. The actual connection retry loop happens in SSHConnection._init_connection
11991201
_ = self.ssh_iface(0)
12001202

1203+
def enable_gdb(self):
1204+
"""Enables GDB debugging"""
1205+
self.gdb_socket = "gdb.socket"
1206+
self.api.machine_config.patch(gdb_socket_path=self.gdb_socket)
1207+
12011208

12021209
class MicroVMFactory:
12031210
"""MicroVM factory"""

tests/integration_tests/build/test_gdb.py

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,91 @@
22
# SPDX-License-Identifier: Apache-2.0
33
"""A test that ensures that firecracker builds with GDB feature enabled at integration time."""
44

5+
import os
56
import platform
7+
import signal
8+
import subprocess
9+
import tempfile
10+
from pathlib import Path
611

712
import host_tools.cargo_build as host
13+
import pytest
14+
from framework.defs import LOCAL_BUILD_PATH
15+
from framework.microvm import MicroVMFactory
816

917
MACHINE = platform.machine()
1018
TARGET = "{}-unknown-linux-musl".format(MACHINE)
19+
BUILD_PATH = LOCAL_BUILD_PATH / "gdb"
20+
21+
22+
def build_gdb():
23+
"""Builds Firecracker with GDB feature enabled"""
24+
25+
host.cargo(
26+
"build",
27+
f"--features gdb --target {TARGET} --all",
28+
env={"CARGO_TARGET_DIR": BUILD_PATH},
29+
)
1130

1231

1332
def test_gdb_compiles():
1433
"""Checks that Firecracker compiles with GDB enabled"""
1534

16-
host.cargo("build", f"--features gdb --target {TARGET}")
35+
build_gdb()
36+
37+
38+
@pytest.mark.skipif(
39+
platform.machine() != "x86_64",
40+
reason="GDB requires a vmlinux but we ship a uImage for ARM in our CI",
41+
)
42+
def test_gdb_connects(guest_kernel_linux_6_1, rootfs):
43+
"""Checks that GDB works in a FC VM"""
44+
45+
build_gdb()
46+
47+
vmfcty = MicroVMFactory(BUILD_PATH / TARGET / "debug")
48+
kernel_dbg = guest_kernel_linux_6_1.parent / "debug" / guest_kernel_linux_6_1.name
49+
uvm = vmfcty.build(kernel_dbg, rootfs)
50+
uvm.spawn(validate_api=False)
51+
uvm.add_net_iface()
52+
uvm.basic_config()
53+
uvm.enable_gdb()
54+
55+
chroot_gdb_socket = Path(uvm.jailer.chroot_path(), uvm.gdb_socket)
56+
57+
gdb_commands = f"""
58+
target remote {chroot_gdb_socket}
59+
hbreak start_kernel
60+
# continue to start_kernel
61+
continue
62+
# continue boot until interrupted
63+
continue
64+
"""
65+
66+
with tempfile.NamedTemporaryFile(
67+
mode="w", suffix=".gdb", delete=False, prefix="fc_gdb_"
68+
) as f:
69+
f.write(gdb_commands)
70+
gdb_script = f.name
71+
72+
gdb_proc = subprocess.Popen(
73+
f"""
74+
until [ -S {chroot_gdb_socket} ]; do
75+
echo 'waiting for {chroot_gdb_socket}';
76+
sleep 1;
77+
done;
78+
gdb {kernel_dbg} -batch -x {gdb_script}
79+
""",
80+
shell=True,
81+
stdout=subprocess.PIPE,
82+
stderr=subprocess.PIPE,
83+
text=True,
84+
)
85+
uvm.start()
86+
os.kill(uvm.firecracker_pid, signal.SIGKILL)
87+
gdb_proc.terminate()
88+
uvm.mark_killed()
89+
stdout, stderr = gdb_proc.communicate(timeout=10)
90+
assert (
91+
"hit Breakpoint 1, start_kernel" in stdout
92+
), f"Breakpoint wasn't hit:\nstdout:\n{stdout}\n\nstderr:\n{stderr}"

0 commit comments

Comments
 (0)