# gdbserver Step debug userland processes to understand how they are talking to the kernel. In guest: /gdbserver.sh /myinsmod.out /hello.ko In host: ./rungdbserver kernel_module-1.0/user/myinsmod.out You can find the executable with: find buildroot/output.x86_64~/build -name myinsmod.out TODO: automate the path finding: - using the executable from under `buildroot/output.x86_64~/target` would be easier as the path is the same as in guest, but unfortunately those executables are stripped to make the guest smaller. `BR2_STRIP_none=y` should disable stripping, but make the image way larger. - `outputx86_64~/staging/` would be even better than `target/` as the docs say that this directory contains binaries before they were stripped. However, only a few binaries are pre-installed there by default, and it seems to be a manual per package thing. E.g. `pciutils` has for `lspci`: define PCIUTILS_INSTALL_STAGING_CMDS $(TARGET_MAKE_ENV) $(MAKE1) -C $(@D) $(PCIUTILS_MAKE_OPTS) \ PREFIX=$(STAGING_DIR)/usr SBINDIR=$(STAGING_DIR)/usr/bin \ install install-lib install-pcilib endef and the docs describe the `*_INSTALL_STAGING` per package config, which is normally set for shared library packages. Feature request: An implementation overview can be found at: ## gdbserver different archs As usual, different archs work with: ./rungdbserver -a arm kernel_module-1.0/user/myinsmod.out ## gdbserver BusyBox BusyBox executables are all symlinks, so if you do on guest: /gdbserver.sh ls on host you need: ./rungdbserver busybox-1.26.2/busybox ## gdbserver shared libraries Our setup gives you the rare opportunity to step debug libc and other system libraries e.g. with: b open c Or simply by stepping into calls: s This is made possible by the GDB command: set sysroot ${buildroot_out_dir}/staging which automatically finds unstripped shared libraries on the host for us. See also: ## Debug userland process without gdbserver QEMU `-gdb` GDB breakpoints are set on virtual addresses, so you can in theory debug userland processes as well. - - The only use case I can see for this is to debug the init process (and have fun), otherwise, why wouldn't you just use `gdbserver`? Known limitations of direct userland debugging: - the kernel might switch context to another process, and you would enter "garbage" - TODO step into shared libraries. If I attempt to load them explicitly: (gdb) sharedlibrary ../../staging/lib/libc.so.0 No loaded shared libraries match the pattern `../../staging/lib/libc.so.0'. since GDB does not know that libc is loaded. Custom init process: - Shell 1: ./run -d -e 'init=/sleep_forever.out' -n - Shell 2: ./rungdb-user kernel_module-1.0/user/sleep_forever.out main BusyBox custom init process: - Shell 1: ./run -d -e 'init=/bin/ls' -n - Shell 2: ./rungdb-user -h busybox-1.26.2/busybox ls_main This follows BusyBox' convention of calling the main for each executable as `_main` since the `busybox` executable has many "mains". BusyBox default init process: - Shell 1: ./run -d -n - Shell 2: ./rungdb-user -h busybox-1.26.2/busybox init_main This cannot be debugged in another way without modifying the source, or `/sbin/init` exits early with: "must be run as PID 1" Non-init process: - Shell 1 ./run -d -n - Shell 2 ./rungdb-user kernel_module-1.0/user/sleep_forever.out Ctrl + C b main continue - Shell 1 /sleep_forever.out This is of least reliable setup as there might be other processes that use the given virtual address.