Skip to content
This repository was archived by the owner on Jan 28, 2023. It is now read-only.
This repository was archived by the owner on Jan 28, 2023. It is now read-only.

Guest debugging support #66

@AlexAltea

Description

@AlexAltea

Opening this issue as follow-up to the discussion in qemu-devel:
https://lists.gnu.org/archive/html/qemu-devel/2018-04/msg00030.html

Summarizing: Guest debugging is extremely relevant to debugging bootloaders/microkernels, or in my case, kernels that do not include debugging backends. Aside from the intrinsic value of this feature, it's also really beneficial to developers/researchers as neither WHPX (Windows) nor HVF (macOS) support guest debugging and while they remain closed-source this probably won't change.


This week I've started experimenting with guest debugging support on HAXM, but it's still too early to submit any patches (plus, this should probably coordinated with QEMU somehow). These are the key ideas (inspired by KVM):

  • Adding a HAX_VCPU_IOCTL_DEBUG ioctl (i.e. QEMU-to-HAXM) with a structure containing:
    • Flags to enable/disable debugging and specific features:
      This is meant to manage the guest state accordingly: e.g. if guest debugging via hardware breakpoints is enabled we should protect the guest drN values in the exit_dr_access handler. Additionally, to know where to redirect #BP, e.g. if software breakpoints are enabled forward to QEMU, otherwise forward to VM.
    • Values for debugging registers: dr0, dr1, dr2, dr3, dr6, dr7:
      They already are a self-contained way of describing hardware breakpoints, so no need to wrap that information in another layer of abstraction.
  • Adding a HAX_EXIT_DEBUG exit (i.e. HAXM-to-QEMU) with a structure containing:
    • Cause: Software breakpoint, hardware breakpoint, singlestep.
    • Value of: rip: For software breakpoint events.
    • Value of: dr6, dr7: For hardware breakpoint events.
  • Software breakpoints are managed by QEMU as an array of objects containing an address and the original byte at that instruction before patching int 3h (0xCC). Its lifecycle is:
    1. GDB: Sends break * command.
    2. QEMU: Creates/initializes hax_sw_brakpoint object and patches instruction with int 3h.
    3. HAXM: Runs the virtual machine, and returns to QEMU after hitting #BP.
    4. QEMU: Returns control to GDB.
    5. GDB: Sends continue command.
    6. QEMU: Reverts the instruction patch and single-steps.
    7. HAXM: Executes one instruction and returns.
    8. QEMU: Reapplies the instruction patch and resumes execution.
  • Hardware breakpoints are specified by directly writing into the guest drN register through the previously described ioctl.

Current experiments can be found in AlexAltea/orbital-qemu@77d61c7 (QEMU) and https://github.com/AlexAltea/haxm/tree/debug (HAXM). I'm facing some issues still:

  • Hardware breakpoints have no effect.
  • Software breakpoints trigger a triple fault, not a #BP.

Disclaimer: I haven't much experience with debuggers, so any feedback will be helpful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions