Userland without gdbserver

This commit is contained in:
Ciro Santilli
2017-10-08 21:16:45 +01:00
parent b3b1df5560
commit 52c3ee15dc
2 changed files with 98 additions and 13 deletions

View File

@@ -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. and the docs describe the `*_INSTALL_STAGING` per package config, which is normally set for shared library packages.
Feature request: <https://bugs.busybox.net/show_bug.cgi?id=10386>
An implementation overview can be found at: <https://reverseengineering.stackexchange.com/questions/8829/cross-debugging-for-mips-elf-with-qemu-toolchain/16214#16214> An implementation overview can be found at: <https://reverseengineering.stackexchange.com/questions/8829/cross-debugging-for-mips-elf-with-qemu-toolchain/16214#16214>
### gdbserver different archs ### gdbserver different archs
@@ -611,28 +613,78 @@ which automatically finds unstripped shared libraries on the host for us.
See also: <https://stackoverflow.com/questions/8611194/debugging-shared-libraries-with-gdbserver/45252113#45252113> See also: <https://stackoverflow.com/questions/8611194/debugging-shared-libraries-with-gdbserver/45252113#45252113>
### 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. GDB breakpoints are set on virtual addresses, so you can in theory debug userland processes as well.
<https://stackoverflow.com/questions/26271901/is-it-possible-to-use-gdb-and-qemu-to-debug-linux-user-space-programs-and-kernel> - <https://stackoverflow.com/questions/26271901/is-it-possible-to-use-gdb-and-qemu-to-debug-linux-user-space-programs-and-kernel>
- <https://stackoverflow.com/questions/16273614/debug-init-on-qemu-using-gdb>
./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 - TODO step into shared libraries. If I attempt to load them explicitly:
# 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'
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 since GDB does not know that libc is loaded.
shell ../../host/usr/bin/x86_64-linux-readelf -s ../kernel_module-1.0/user/rand_check.out | grep -E '\bmain\b'
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 `<exec>_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 ## X11

33
rungdb-user Executable file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env bash
set -e
usage="$0 <exec-relative-path> [<brk-symbol>]"
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"