QEMU - VRIG-Ritsec/Resources GitHub Wiki
QEMU, otherwise known as "Quick Emulator" is a key piece of software that is able to emulate software as well as run VMs.
QEMU has two modes: system-mode and user-mode. System-mode can be used for running bare-metal applications (i.e., firmware or OSes) and user-mode can be used to run user programs.
QEMU also has two emulations modes: TCG and KVM. TCG aka Tiny-Code Generator allows one to run applications compiled for a different architecture. For example, if you have a program compiled for arm64 and you want to run it on x86, you can do that via TCG. TCG works on both user-mode and system-mode. KVM is intended for running VMs natively (i.e., without TCG). TCG is very slow as it is software based emulation meaning it attempts to emulate every operation of the CPU (i.e., memory, interrupts, exceptions, etc.) purely in software. This results in relatively slow operation.
KVM mode works with your CPU directly to create a virtual environment. This leverages virtualization extensions built into your CPU (i.e., Intel VT-X, AMD-V) to run VMs natively. With KVM and underlying virtualization extensions, CPU operations are performed by the CPU resulting in almost native speeds.
Launching a program in QEMU
To launch a program in QEMU, use the qemu command. All system-mode qemu programs start with qemu-system-
and all user-mode qemu programs start with qemu-
. We will be focusing on system-mode.
Suppose you have developed a kernel program which is represented as [kernel file-path here]. To launch your kernel in QEMU run:
qemu-system-x86_64 -kernel [kernel file-path here]
If you are running this in a terminal-only environment (i.e., an SSH session), run:
qemu-system-x86_64 -kernel [kernel file-path here] -nographic
The -nographic
prevents qemu from opening a display. Otherwise, by default, QEMU will attempt to open up a display that serves as a virtual monitor for your VM.
QEMU Debugging
QEMU has many features that we will use throughout this project. One of the main features is debugging via GDB. Through QEMU, we are able to walk through the program step-by-step and potentially debug any errors as well as get introspection into how the CPU is operating.
To debug your kernel via QEMU, run:
qemu-system-x86_64 -kernel [kernel file-path here] -nographic -s -S
The -s
opens a gdbserver on localhost:1234
(TCP port 1234) while -S
does not start your kernel until you tell it to via GDB. Essentially, what is happening is that QEMU has begun running your kernel. However, it is waiting for you to connect to QEMU via GDB before it does anything.
To connect GDB to your QEMU instance, run:
gdb [kernel file-path here]
This should open up a GDB session that is debugging your kernel.
Once in the gdb session, run:
set architecture i386:x86-64
target remote :1234
The first command sets the architecture to support both x86-64 and i386. The second command connects to the GDB server on port 1234.
From here, GDB acts exactly the same as if you were debugging any other program.