From 52c3ee15dc4a9cfe822252e46f68a6d3e975f5d7 Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Sun, 8 Oct 2017 21:16:45 +0100 Subject: [PATCH] Userland without gdbserver --- README.md | 78 ++++++++++++++++++++++++++++++++++++++++++++--------- rungdb-user | 33 +++++++++++++++++++++++ 2 files changed, 98 insertions(+), 13 deletions(-) create mode 100755 rungdb-user diff --git a/README.md b/README.md index 2f6c860..9517a4a 100644 --- a/README.md +++ b/README.md @@ -574,6 +574,8 @@ TODO: automate the path finding: 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 @@ -611,28 +613,78 @@ which automatically finds unstripped shared libraries on the host for us. See also: -### Debug userland process directly from QEMU +### Userland process without gdbserver GDB breakpoints are set on virtual addresses, so you can in theory debug userland processes as well. - +- +- - ./runqemu -d -e 'init=/rand_check.out' -n +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 of direct userland debugging: -On another shell: +- the kernel might switch context to another process, and you would enter "garbage" - buildroot/output.x86_64~/host/usr/bin/x86_64-linux-readelf -h buildroot/output.x86_64~/build/kernel_module-1.0/user/rand_check.out | grep Entry - # Entry point address: 0x400560 - buildroot/output.x86_64~/host/usr/bin/x86_64-linux-readelf -s buildroot/output.x86_64~/build/kernel_module-1.0/user/rand_check.out | grep -E '\bmain\b' - # 68: 0000000000400748 309 FUNC GLOBAL DEFAULT 8 main - ./rungdb '*0x400748' +- TODO step into shared libraries. If I attempt to load them explicitly: -Alternatively, from inside GDB you can do the more succinct: + (gdb) sharedlibrary ../../staging/lib/libc.so.0 + No loaded shared libraries match the pattern `../../staging/lib/libc.so.0'. - shell ../../host/usr/bin/x86_64-linux-readelf -h ../kernel_module-1.0/user/rand_check.out | grep Ent - shell ../../host/usr/bin/x86_64-linux-readelf -s ../kernel_module-1.0/user/rand_check.out | grep -E '\bmain\b' + since GDB does not know that libc is loaded. -Those steps should be fully automatable `.gdbinit` script. +Custom init process: + +- Shell 1: + + ./runqemu -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: + + ./runqemu -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: + + ./runqemu -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 + + ./runqemu -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. ## X11 diff --git a/rungdb-user b/rungdb-user new file mode 100755 index 0000000..9ae2d88 --- /dev/null +++ b/rungdb-user @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -e +usage="$0 []" +arch='x86_64' +while getopts a:h OPT; do + case "$OPT" in + a) + arch="$OPTARG" + ;; + h) + echo "$usage" + exit 0 + ;; + esac +done +shift "$(($OPTIND - 1))" +executable_rel="$1" +shift +if [ "$#" -gt 0 ]; then + brk="'$1'" + shift +else + brk='' +fi +buildroot_out_dir="$(pwd)/buildroot/output.${arch}~" +executable="${buildroot_out_dir}/build/${executable_rel}" +readelf="${buildroot_out_dir}/host/usr/bin/${arch}-linux-readelf" +addr="$("$readelf" -h "$executable" | awk '/Entry/{ print $NF }' )" +ex="-ex \"add-symbol-file $executable $addr\"" +# Twice because lx-symbols overrides our add-symbol-file commands. +cmd="./rungdb -b '$ex' -A '$ex' $brk" +echo "$cmd" +eval "$cmd"