Skip to content
This repository has been archived by the owner on Mar 18, 2021. It is now read-only.

Debug bhyve

Marcelo Araujo edited this page Nov 29, 2018 · 9 revisions

There are different strategy that can be used to debug bhyve while you are developing it. This document is a working in progress where we will try to cover as much as possible different ways to debug bhyve.

Build kernel and world with debug symbols

Kernel

The FreeBSD HEAD with GENERIC kernel by default is compiled with DEBUG symbols.

[araujo@pipoca] /usr/src/sys/amd64/conf# pwd
/usr/src/sys/amd64/conf
[araujo@pipoca] /usr/src/sys/amd64/conf# vi GENERIC

On GENERIC file, we will see an option:

makeoptions DEBUG=-g

Also there is an option where we can debug the guest vm, to be able to do that we need to add a new device on kernel GENERIC.

device bvmdebug

World

We need build the user-land with debug symbols. The bhyve(8) itself is compiled with debug symbols by default:

[araujo@pipoca] /usr/src/usr.sbin/bhyve# pwd
/usr/src/usr.sbin/bhyve
[araujo@pipoca] /usr/src/usr.sbin/bhyve# cat Makefile|grep DEBUG
DEBUG_FLAGS= -g -O0

Also you can set DEBUG_FLAGS as a global value to build all world with debug symbols. You need to add inside file /etc/src.conf the following flag:

DEBUG_FLAGS=-g

Rebuild everything

World

[araujo@pipoca] /# cd /usr/src/
[araujo@pipoca] /usr/src# make buildworld -j<N_CPU>
[araujo@pipoca] /usr/src# make installworld

NOTE: After we rebuild everything, sometimes we want rebuild parts of the code without clean everything and start from scratch, we can build only the difference.

[araujo@pipoca] /usr/src# make buildworld -j<N_CPU> -DNO_CLEAN

NOTE: Also for bhyve(8) you can build it without rebuild all world.

[araujo@pipoca] /usr/src# cd /usr/src/usr.sbin/bhyve
[araujo@pipoca] /usr/src/usr.sbin/bhyve# make clean; make; make install

Kernel

[araujo@pipoca] /usr/src# make buildkernel KERNCONF=GENERIC -j<N_CPU>
[araujo@pipoca] /usr/src# make installkernel KERNCONF=GENERIC

NOTE: Also for Kernel you can use the flag -DNO_CLEAN if you don't want to do a clean kernel build.

mergemaster(8)

The last step is merge the changes of some configuration files and scripts.

[araujo@pipoca] /usr/src# mergemaster
[araujo@pipoca] /usr/src# reboot

Debug bhyve

Debugging using gdb(4)

First launch bhyve using gdb(4)

[araujo@pipoca] /usr/src# gdb /usr/sbin/bhyve
GNU gdb (GDB) 8.1 [GDB v8.1 for FreeBSD]
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-portbld-freebsd11.0".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/sbin/bhyve...Reading symbols from /usr/lib/debug/usr/sbin/bhyve.debug...done.
done.

You will notice the following line: Reading symbols from /usr/sbin/bhyve...Reading symbols from /usr/lib/debug/usr/sbin/bhyve.debug...done. Now we can launch a vm.

(gdb) run -A -H -w -c 1 -m 2048 -s 0:0,hostbridge -s 31,lpc -l com1,/dev/nmdm135A -l bootrom,/usr/local/share/uefi-firmware/BHYVE_UEFI.fd -s 3,e1000,tap0,mac=00:a0:98:65:89:b6 -s 29,fbuf,vncserver,tcp=192.168.100.111:6035,w=800,h=600,, -s 30,xhci,tablet -s 4,ahci-hd,/dev/zvol/tank/freebsdUFS 135_FreeBSD12UFS

As soon as bhyve(8) crashes you will receive the following messages:

Thread 1 "mevent" received signal SIGBUS, Bus error.
__je_bitmap_unset (bitmap=<optimized out>, binfo=<optimized out>, bit=<optimized out>)
    at /freenas-11-nightlies/freenas/_BE/os/contrib/jemalloc/include/jemalloc/internal/bitmap.h:248
248	/freenas-11-nightlies/freenas/_BE/os/contrib/jemalloc/include/jemalloc/internal/bitmap.h: No such file or directory.
(gdb) bt
#0  __je_bitmap_unset (bitmap=<optimized out>, binfo=<optimized out>, bit=<optimized out>)
    at /freenas-11-nightlies/freenas/_BE/os/contrib/jemalloc/include/jemalloc/internal/bitmap.h:248
#1  arena_run_reg_dalloc (run=<optimized out>, ptr=<optimized out>) at jemalloc_arena.c:345
#2  arena_dalloc_bin_locked_impl (tsdn=<optimized out>, arena=<optimized out>, chunk=<optimized out>, ptr=<optimized out>, 
    bitselm=<optimized out>, junked=<optimized out>) at jemalloc_arena.c:2903
#3  0x0000000801733d47 in __je_tcache_bin_flush_small (tsd=<optimized out>, tcache=<optimized out>, tbin=0x80200d148, 
    binind=<optimized out>, rem=0) at jemalloc_tcache.c:134
#4  0x0000000801733b6f in __je_tcache_event_hard (tsd=0x3e7, tcache=0x80200d000) at jemalloc_tcache.c:45
#5  0x0000000801759621 in __free (ptr=0x88620eb40) at jemalloc_jemalloc.c:1935
#6  0x0000000000413eb9 in mevent_build (mfd=10, kev=0x7fffffffdff0)
    at /freenas-11-nightlies/freenas/_BE/os/usr.sbin/bhyve/mevent.c:221
#7  0x0000000000413b7d in mevent_dispatch () at /freenas-11-nightlies/freenas/_BE/os/usr.sbin/bhyve/mevent.c:459
#8  0x000000000040b069 in main (argc=1, argv=0x7fffffffe9a8)
    at /freenas-11-nightlies/freenas/_BE/os/usr.sbin/bhyve/bhyverun.c:1052

The first line gives us an idea where it breaks: Thread 1 "mevent" received signal SIGBUS, Bus error. The rest of lines show us where the problem happens, in this particular case the problem is exactly at line #6.

DPRINTF and WPRINTF macros

Some of bhyve(8) source files includes two macros DPRINTF(debug) and WPRINTF(warning), It is a good approach to add them on source files that you are working on as well as in points that it would help for debugging. Usually those source files has an int flag to enable or disable DPRINTF.

src: pci_nvme.c

79 static int nvme_debug = 0;                                                      
80 #define!DPRINTF(params) if (nvme_debug) printf params

Some examples of DPRINTF usage:

src: pci_nvme.c

363 !·······DPRINTF(("%s\r\n", __func__));

OR

485 !·······!·······DPRINTF(("%s sq %u size %u gaddr %p cqid %u\r\n", __func__,     
486 !·······!·······        qid, nsq->size, nsq->qbase, nsq->cqid));

Debugging a Kernel panic

First install devel/gdb

root# pkg install gdb

NOTE: Kernel must be compiled with debug symbols: makeoptions DEBUG=-g

Now you can launch kgdb as follow:

root# kgdb /boot/kernel/kernel /var/crash/vmcore.0

If you have kernel.debug and all symbols necessary, you will be able to start the backtrace as follow:

(kgdb) bt

You will see several lines followed by a # and a number, to go to that line you can do as follow:

(kgdb) up 14
#14 0xffffffff83b41760 in emulate_inout_port (vm=<optimized out>, vcpuid=<optimized out>, 
    vmexit=<optimized out>, retu=<optimized out>) at /z/freebsd-upb/sys/amd64/vmm/vmm_ioport.c:125
125		error = (*handler)(vm, vcpuid, vmexit->u.inout.in,
(kgdb)

Also you can list the frame as follow (ex.: we are listing the frame of line #16):

(kgdb) bt
...
#14 0xffffffff83b41760 in emulate_inout_port (vm=<optimized out>, vcpuid=<optimized out>, 
    vmexit=<optimized out>, retu=<optimized out>) at /z/freebsd-upb/sys/amd64/vmm/vmm_ioport.c:125
#15 vm_handle_inout (vm=0xfffffe00b5c00000, vcpuid=0, vmexit=0xfffffe00b5c002c0, 
    retu=0xfffffe00b5e225a7) at /z/freebsd-upb/sys/amd64/vmm/vmm_ioport.c:169
#16 0xffffffff83b38272 in vm_run (vm=0xfffffe00b5c00000, vmrun=0xfffff802836b7a00)
    at /z/freebsd-upb/sys/amd64/vmm/vmm.c:1830
...
(kgdb) list *0xffffffff83b38272
0xffffffff83b38272 is in vm_run (/z/freebsd-upb/sys/amd64/vmm/vmm.c:1830).
1825			case VM_EXITCODE_INST_EMUL:
1826				error = vm_handle_inst_emul(vm, vcpuid, &retu);
1827				break;
1828			case VM_EXITCODE_INOUT:
1829			case VM_EXITCODE_INOUT_STR:
1830				error = vm_handle_inout(vm, vcpuid, vme, &retu);
1831				break;
1832			case VM_EXITCODE_MONITOR:
1833			case VM_EXITCODE_MWAIT:
1834			case VM_EXITCODE_VMINSN:
(kgdb) 

For more information, here there are some additional resources:

FreeBSD Handbook - Kernel Debugging

Debugging the FreeBSD kernel for dummies - by syrinx@