-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gdb server #2168
Gdb server #2168
Conversation
Hey there, I'm the author of Oh, and if you're wondering how some random guy stumbled across this PR: I'll occasionally search GitHub to see if anyone's using P.S: I was a former intern on the |
Hey, thanks for the heads up; I'll be sure to use the new release. Also, great work on |
Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
This provides support for breakpoints Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
The KVM_SET_GUEST_DEBUG ioctl enables the handling of a trap signal, generated when execution reaches a breakpoint or single-stepping is enabled. An alternative to this seccomp rule would be requiring the execution of the guest under GDB to be performed with seccomp disabled Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
Improve readability, define proper error types and add support for early-boot virtual address access Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
Cases in which PDPTE's PS flag would be 1 or PDE's PS flag would be 0 were not properly treated. This problem only manifested itself later in the boot process (e.g., register_virtio_device for a stack address) Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
Removed the option of setting breakpoints at linear addresses in early boot. The support for it contained a work-around and not all inconsistencies at the client could have been solved on the server side (e.g.: "info breakpoints" would not display such a breakpoint as "hit" when it was the case). Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
Specifying the --debugger argument will enable GDB guest debugging for the current session; not specifying it leads to normal execution Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
Adding a "debugger_enabled" argument to some public functions impacted some unit and integration tests Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
Change virt_to_phys() function signature so that it only receives the data it actually needs Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
This unittest verifies the virtual-to-physical address translation is properly performed in the early boot process of a kernel Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
I've started looking over the PR, but I'm occasionally having a hard time understanding some of the magic numbers and why some operations are done. I suggest going over the PR and trying to either move the magic numbers to constants and adding more comments so that it's easier to follow the logic. |
src/gdb_server/src/util.rs
Outdated
impl Debugger { | ||
pub fn enable_kvm_debug(vcpu: &VcpuFd, step: bool) -> Result<(), DebuggerError> { | ||
let mut control: __u32 = 0; | ||
control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could control
be declared as KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP
directly instead of 0?
mask = 0x0000ff8000000000u64; | ||
|
||
paddr = context.cr3 & 0x000ffffffffff000u64; | ||
movem = 36; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is 36
?
src/gdb_server/src/util.rs
Outdated
/// obtaining the physical address corresponding to the one received from a GDB client | ||
pub fn virt_to_phys( | ||
addr: u64, | ||
gm: &GuestMemoryMmap, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gm
could be named guest_memory
so that it's easier to follow. It would also be consistent with the guest_state
parameter declared below.
} | ||
|
||
if Debugger::check_entry(table_entry, TABLE_ENTRY_RSVD_BITS[0]).is_err() { | ||
return Debugger::fixup_pointer(addr, e_phdrs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a comment on why we are exiting through here.
Before, a target remote command would start the guest VM and would let it wait at the entry point. This commit offers the user the responsibility of issuing a continue command in the beginning so that the VM starts and executes until reaching the entry point. This is also aligned with the practice used in IDEs of starting the debugging process with a default continue. Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
Add comments, remove magic numbers, etc. Also, add support for setting multiple registers Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
This update allows for connection on any host interface and on a port that is easily accessible for a EC2 host Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
entry_addr, | ||
)?; | ||
|
||
if target.insert_bp(entry_addr.0, false).is_err() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment on why we are setting this breakpoint.
src/gdb_server/src/lib.rs
Outdated
return Err("GDB server error".into()); | ||
} | ||
|
||
let connection: Box<dyn Connection<Error = std::io::Error>> = { Box::new(wait_for_tcp(8443)?) }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
8443
should be a constant defined at the beginning of the file.
src/kernel/src/loader/mod.rs
Outdated
@@ -421,3 +423,30 @@ mod tests { | |||
assert_eq!(val, b'\0'); | |||
} | |||
} | |||
|
|||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] | |||
pub fn extract_phdrs<F>(kernel_image: &mut F) -> Result<Vec<elf::Elf64_Phdr>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment on the purpose of the function.
Can it be unit tested?
@@ -453,7 +472,9 @@ fn load_kernel( | |||
kernel::loader::load_kernel(guest_memory, &mut kernel_file, arch::get_kernel_start()) | |||
.map_err(StartMicrovmError::KernelLoader)?; | |||
|
|||
Ok(entry_addr) | |||
let phdrs = kernel::loader::extract_phdrs(&mut kernel_file).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment on why we are doing the header extraction.
Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
Add a few code comments and fix some minor code style issues Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
Signed-off-by: Marius-Cristian Baciu <baciumar@amazon.com>
The build here is failing with following errors.
This is because changes in pull request firecracker-microvm/kvm-ioctls#11 is not yet merged. It would be great if someone can review those changes and then we have a working build. |
The changes are already merged in upstream: rust-vmm/kvm-ioctls@f87ee79, just need a sync from upstream to https://github.com/firecracker-microvm/kvm-ioctls |
Do you think it would be feasible to start the debugger stub on demand via REST api? This would open up some interesting use cases for me. |
Ok(entry_addr) | ||
// The program headers of the kernel image are necessary in the address translation | ||
// mechanism in the GDB Server thread | ||
let phdrs = kernel::loader::extract_phdrs(&mut kernel_file).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me it seems this information could be also extracted later at runtime, i.e. in the RPC interface no? I am just brainstorming here how to make the debug interface attachable on demand
@Mic92 the GDB server could be started up at runtime, yes. We will probably add this as an enhancement as we move towards integrating it in Firecracker. |
closing in favour of: #2333 |
Reason for This PR
Initial implementation of a GDB server for guest debugging.
Description of Changes
Created a new package implementing the gdbstub interface for client-server communication
Implemented the following functionalities: breakpoint, single-step, reading of registers and memory
Implemented virtual-to-physical address translation, used by any guest memory access performed as part of the above-mentioned functionalities
Created a new thread for handling client requests and two channels for vCPU - GDB server thread communication
Added a "--debugger" command-line option for the firecracker executable
This functionality can be added in
rust-vmm
.License Acceptance
By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license.
PR Checklist
[Author TODO: Meet these criteria.]
[Reviewer TODO: Verify that these criteria are met. Request changes if not]
git commit -s
).unsafe
code is properly documented.firecracker/swagger.yaml
.CHANGELOG.md
.