Skip to content

Commit 200d358

Browse files
committed
feat(gdb): Support config over api
Allow a GDB debugging session to be started over API Signed-off-by: Jack Thomson <[email protected]>
1 parent ae30a82 commit 200d358

File tree

6 files changed

+44
-21
lines changed

6 files changed

+44
-21
lines changed

docs/gdb-debugging.md

+18-7
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ Firecracker supports debugging the guest kernel via GDB remote serial protocol.
66
This allows us to connect GDB to the firecracker process and step through debug
77
the guest kernel.
88

9-
The GDB feature requires Firecracker to be booted with a config file.
10-
119
## Prerequisites
1210

1311
Firstly, to enable GDB debugging we need to compile Firecracker with the `gdb`
@@ -25,22 +23,35 @@ debugging to work. The key config options to enable are:
2523

2624
```
2725
CONFIG_FRAME_POINTER=y
28-
CONFIG_KGDB=y
29-
CONFIG_KGDB_SERIAL_CONSOLE=y
3026
CONFIG_DEBUG_INFO=y
3127
```
3228

33-
For GDB debugging the `gdb-socket` option should be set in your config file. In
34-
this example we set it to `/tmp/gdb.socket`
29+
For GDB debugging the `gdb_socket_path` option under `machine-config` should be
30+
set. When using the API the socket address must be set before instance start.
31+
32+
In this example we set the address to `/tmp/gdb.socket` in the config file:
3533

3634
```
3735
{
3836
...
39-
"gdb-socket": "/tmp/gdb.socket"
37+
"machine-config": {
38+
...
39+
"gdb_socket_path": "/tmp/gdb.socket"
40+
...
41+
}
4042
...
4143
}
4244
```
4345

46+
Using the API the socket address can be configured before boot like so:
47+
48+
```
49+
sudo curl -X PATCH --unix-socket "${API_SOCKET}" \
50+
--data "{
51+
\"gdb_socket_path\": \"/tmp/gdb.socket\"
52+
}" "http://localhost/machine-config"
53+
```
54+
4455
## Starting Firecracker with GDB
4556

4657
With all the prerequisites in place you can now start firecracker ready to

src/firecracker/swagger/firecracker.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,9 @@ definitions:
10281028
properties:
10291029
cpu_template:
10301030
$ref: "#/definitions/CpuTemplate"
1031+
# gdb_socket_path:
1032+
# type: string
1033+
# description: Path to the GDB socket. Requires the gdb feature to be enabled.
10311034
smt:
10321035
type: boolean
10331036
description: Flag for enabling/disabling simultaneous multithreading. Can be enabled only on x86.

src/vmm/src/builder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,8 @@ pub fn build_microvm_for_boot(
346346
let vmm = Arc::new(Mutex::new(vmm));
347347

348348
#[cfg(feature = "gdb")]
349-
if let Some(gdb_socket_addr) = &vm_resources.gdb_socket_addr {
350-
gdb::gdb_thread(vmm.clone(), vcpu_fds, gdb_rx, entry_addr, gdb_socket_addr)
349+
if let Some(gdb_socket_path) = &vm_resources.vm_config.gdb_socket_path {
350+
gdb::gdb_thread(vmm.clone(), vcpu_fds, gdb_rx, entry_addr, gdb_socket_path)
351351
.map_err(GdbServer)?;
352352
} else {
353353
debug!("No GDB socket provided not starting gdb server.");

src/vmm/src/persist.rs

+2
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,8 @@ pub fn restore_from_snapshot(
433433
cpu_template: Some(microvm_state.vm_info.cpu_template),
434434
track_dirty_pages: Some(track_dirty_pages),
435435
huge_pages: Some(microvm_state.vm_info.huge_pages),
436+
#[cfg(feature = "gdb")]
437+
gdb_socket_path: None,
436438
})
437439
.map_err(BuildMicrovmFromSnapshotError::VmUpdateConfig)?;
438440

src/vmm/src/resources.rs

-12
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,6 @@ pub struct VmmConfig {
8686
vsock_device: Option<VsockDeviceConfig>,
8787
#[serde(rename = "entropy")]
8888
entropy_device: Option<EntropyDeviceConfig>,
89-
#[cfg(feature = "gdb")]
90-
#[serde(rename = "gdb-socket")]
91-
gdb_socket_addr: Option<String>,
9289
}
9390

9491
/// A data structure that encapsulates the device configurations
@@ -117,9 +114,6 @@ pub struct VmResources {
117114
pub mmds_size_limit: usize,
118115
/// Whether or not to load boot timer device.
119116
pub boot_timer: bool,
120-
#[cfg(feature = "gdb")]
121-
/// Configures the location of the GDB socket
122-
pub gdb_socket_addr: Option<String>,
123117
}
124118

125119
impl VmResources {
@@ -142,8 +136,6 @@ impl VmResources {
142136

143137
let mut resources: Self = Self {
144138
mmds_size_limit,
145-
#[cfg(feature = "gdb")]
146-
gdb_socket_addr: vmm_config.gdb_socket_addr,
147139
..Default::default()
148140
};
149141
if let Some(machine_config) = vmm_config.machine_config {
@@ -529,8 +521,6 @@ impl From<&VmResources> for VmmConfig {
529521
net_devices: resources.net_builder.configs(),
530522
vsock_device: resources.vsock.config(),
531523
entropy_device: resources.entropy.config(),
532-
#[cfg(feature = "gdb")]
533-
gdb_socket_addr: resources.gdb_socket_addr.clone(),
534524
}
535525
}
536526
}
@@ -640,8 +630,6 @@ mod tests {
640630
boot_timer: false,
641631
mmds_size_limit: HTTP_MAX_PAYLOAD_SIZE,
642632
entropy: Default::default(),
643-
#[cfg(feature = "gdb")]
644-
gdb_socket_addr: None,
645633
}
646634
}
647635

src/vmm/src/vmm_config/machine_config.rs

+19
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ pub struct MachineConfig {
111111
/// Configures what page size Firecracker should use to back guest memory.
112112
#[serde(default)]
113113
pub huge_pages: HugePageConfig,
114+
/// GDB socket address.
115+
#[cfg(feature = "gdb")]
116+
#[serde(default, skip_serializing_if = "Option::is_none")]
117+
pub gdb_socket_path: Option<String>,
114118
}
115119

116120
impl Default for MachineConfig {
@@ -146,6 +150,10 @@ pub struct MachineConfigUpdate {
146150
/// Configures what page size Firecracker should use to back guest memory.
147151
#[serde(default, skip_serializing_if = "Option::is_none")]
148152
pub huge_pages: Option<HugePageConfig>,
153+
/// GDB socket address.
154+
#[cfg(feature = "gdb")]
155+
#[serde(default, skip_serializing_if = "Option::is_none")]
156+
pub gdb_socket_path: Option<String>,
149157
}
150158

151159
impl MachineConfigUpdate {
@@ -166,6 +174,8 @@ impl From<MachineConfig> for MachineConfigUpdate {
166174
cpu_template: cfg.cpu_template,
167175
track_dirty_pages: Some(cfg.track_dirty_pages),
168176
huge_pages: Some(cfg.huge_pages),
177+
#[cfg(feature = "gdb")]
178+
gdb_socket_path: cfg.gdb_socket_path,
169179
}
170180
}
171181
}
@@ -185,6 +195,9 @@ pub struct VmConfig {
185195
pub track_dirty_pages: bool,
186196
/// Configures what page size Firecracker should use to back guest memory.
187197
pub huge_pages: HugePageConfig,
198+
/// GDB socket address.
199+
#[cfg(feature = "gdb")]
200+
pub gdb_socket_path: Option<String>,
188201
}
189202

190203
impl VmConfig {
@@ -238,6 +251,8 @@ impl VmConfig {
238251
cpu_template,
239252
track_dirty_pages: update.track_dirty_pages.unwrap_or(self.track_dirty_pages),
240253
huge_pages: page_config,
254+
#[cfg(feature = "gdb")]
255+
gdb_socket_path: update.gdb_socket_path.clone(),
241256
})
242257
}
243258
}
@@ -251,6 +266,8 @@ impl Default for VmConfig {
251266
cpu_template: None,
252267
track_dirty_pages: false,
253268
huge_pages: HugePageConfig::None,
269+
#[cfg(feature = "gdb")]
270+
gdb_socket_path: None,
254271
}
255272
}
256273
}
@@ -264,6 +281,8 @@ impl From<&VmConfig> for MachineConfig {
264281
cpu_template: value.cpu_template.as_ref().map(|template| template.into()),
265282
track_dirty_pages: value.track_dirty_pages,
266283
huge_pages: value.huge_pages,
284+
#[cfg(feature = "gdb")]
285+
gdb_socket_path: value.gdb_socket_path.clone(),
267286
}
268287
}
269288
}

0 commit comments

Comments
 (0)