At this stage, you should be familiar with the steps of configuring, building and running any application within Unikraft and know the main parts of the architecture. Below you can see a list of useful commands.
| Command | Description |
|---|---|
make clean | Clean the application |
make properclean | Clean the application, fully remove the build/ folder |
make distclean | Clean the application, also remove .config |
make menuconfig | Configure application through the main menu |
make | Build configured application (in .config) |
Today we'll make use of gdb.
We recommend the following cheat sheet for the most common commands.
A quick crash course on GDB may be found here.
Contrary to popular belief, debugging an unikernel is simpler than debugging a standard operating system. Since the application and OS are linked into a single binary, debuggers can be used on the running unikernel to debug both application and OS code at the same time. A couple of things you should know before you get started:
make menuconfig), under Build Options make sure that Drop unused functions and data is unselected.
This prevents Unikraft from removing unused symbols from the final image and, if enabled, might hide missing dependencies during development.make V=1 to see verbose output for all the commands being executed during the build.
If the compilation for a particular file is breaking and you would like to understand why (e.g., perhaps the included paths are wrong), you can debug things by adding the -E flag to the command, removing the -o [objname], and redirecting the output to a file which you can then inspect.Miscellaneous when typing make help, these may come in handy.
For instance, make print-vars enables inspecting at the value of a particular variable in Makefile.uk.The build system always creates two image files for each selected platform:
.dbg file extension)Before using GDB, make sure compiler optimization is turned off: in the configuration menu, go to Build Options --> Optimization level and select No optimizations.
Then, under Build Options, select a Debug information level that is bigger than 0.
We recommend 3, the highest level.
Once set, save the configuration and build your images.
You must run the image that does not contain debugging information (as in no .dbg extension).
We will use the .dbg image with gdb.
We recommend creating the guest in a paused state (the -S option):
qemu-system-x86_64 -s -S -nographic -kernel workdir/build/hello-c_qemu-x86_64
Note that the -s parameter is shorthand for -gdb tcp::1234.
Now connect GDB by using the debug image with:
gdb --eval-command="target remote :1234" workdir/build/app-helloworld_kvm-x86_64.dbg
Note: you will want to run gdb using the .dbg command, otherwise you will not have any debugging symbols.
Unless you're debugging early boot code, you’ll need to set a hardware break point. Hardware breakpoints have the same effect as the common software breakpoints you are used to, but they are different in the implementation. As the name suggests, hardware breakpoints are based on direct hardware support. This may limit the number of breakpoints you can set, but makes them especially useful when debugging kernel code.
hbreak [location]continue
You can now run continue and debug as you would do normally.
Build the c-hello application, like you did in the last session.
Enable build messages, attach gdb to the application and toy around.
Break at the main function, see if you can make the application print a different message without changing the source code.
Before starting the task, let's get familiar with some GDB commands.
ni - go to the next instruction, but skip function calls
si - go to the next instruction, but enters function calls
c - continue execution to the next breakpoint
p expr - display the value of an expression
x addr - get the value at the indicated address (similar to p *addr)
whatis arg - print the data type of arg
GDB provides convenience variables that you can use within GDB to hold on to a value and refer to it later. For example:
(gdb) set $foo = *object_ptr
Note that you can also cast variables in GDB similar to C:
(gdb) set $var = (int *) ptr
If you want to dereference a pointer and actually see the value, you can use the following command:
(gdb) p *addr
You can find more GDB commands here Also, if you are unfamiliar with X86_64 calling convention you can read more about it here.
Now, let's get back to the task. Download the target kernel image from here.
Use qemu and gdb to navigate through the mystery_kvm-x86_64.dbg file.
Run the application using the following command:
qemu-system-x86_64 -nographic -kernel mystery_kvm-x86_64.dbg -s -S
You can attach to it from another terminal using
gdb --eval-command="target remote :1234" mystery_kvm-x86_64.dbg
Do you think you can find out the secret?
Look through the assembly code and see what it does.
Follow the test eax, eax instructions and see what needs to happen to pass those tests and get to the last point where the secret is printed (i.e. be able to advance to address 0x000000000018a4ae).
Investigate memory addresses (using the x instruction - such as x/s $rbp-0x120), do instruction stepping (stepi or nexti), use breakpoints (break *<address>) and find out the secret.
Let's try a new application based on networking, Nginx.
Use the same setup from the last session, follow the instructions in the README.md file from the catalog repository and build Nginx for Qemu/KVM.
Do you observe something strange?
Where is the main.c file?
Edit the Config.uk file and remove the select LIBNGINX_MAIN_FUNCTION line.
Deselect this make menuconfig option Library Configuration -> libnginx -> Provide a main function and try to build and run the Nginx application again.
Try to create your own main.c file so that the application works again.
In order to add your main file to the build system, you must add it to the Makefile.uk file.
Check the c-hello Makefile.uk to see an example.
Basically, this exercise has two tasks:
provide main functionHints:
nm on the kernel image to see what functions are available.workdir/libs/nginx.Feel free to ask questions, report issues, and meet new people.