diff --git a/README.adoc b/README.adoc index 7b9ad81..f1facf8 100644 --- a/README.adoc +++ b/README.adoc @@ -379,15 +379,17 @@ If you are feeling raw, you can insert and remove modules with our own minimal m which teaches you how it is done from C code. [[gdb]] -== GDB step debugging +== GDB step debug -To GDB step debug the Linux kernel, first run: +=== GDB step debug kernel boot + +`-d` makes QEMU wait for a GDB connection, otherwise we could accidentally go past the point we want to break at: .... ./run -d .... -If you want to break immediately at a symbol, e.g. `start_kernel` of the boot sequence, run on another shell: +Say you want to break at `start_kernel`. So on another shell: .... ./rungdb start_kernel @@ -407,21 +409,36 @@ n c .... -To skip the boot, run just: +See also: + +* http://stackoverflow.com/questions/11408041/how-to-debug-the-linux-kernel-with-gdb-and-qemu/33203642#33203642 +* http://stackoverflow.com/questions/4943857/linux-kernel-live-debugging-how-its-done-and-what-tools-are-used/42316607#42316607 + +`O=0` is an impossible dream, `O=2` being the default: https://stackoverflow.com/questions/29151235/how-to-de-optimize-the-linux-kernel-to-and-compile-it-with-o0 So get ready for some weird jumps, and `` fun. Why, Linux, why. + +=== GDB step debug kernel post-boot + +Let's observe the kernel as it reacts to some userland actions. + +Start QEMU with just: .... -./rungdb +./run .... -and when you want to break, do `Ctrl + C` from GDB. - -To have some fun, you can first run inside QEMU: +and after boot inside a shell run: .... /count.sh .... -which counts to infinity to stdout, and then in GDB: +which counts to infinity to stdout. Then in another shell, run: + +.... +./rungdb +.... + +and then hit: .... Ctrl + C @@ -431,34 +448,46 @@ continue continue .... -And you now control the counting from GDB. +And you now control the counting on the first shell from GDB! -See also: +When you hit `Ctrl + C`, if we happen to be inside kernel code at that point, which is very likely if there are no heavy background tasks waiting, and we are just waiting on a `sleep` type system call of the command prompt, we can already see the source for the random place inside the kernel where we stopped. -* http://stackoverflow.com/questions/11408041/how-to-debug-the-linux-kernel-with-gdb-and-qemu/33203642#33203642 -* http://stackoverflow.com/questions/4943857/linux-kernel-live-debugging-how-its-done-and-what-tools-are-used/42316607#42316607 +=== tmux multi terminal -`O=0` is an impossible dream, `O=2` being the default: https://stackoverflow.com/questions/29151235/how-to-de-optimize-the-linux-kernel-to-and-compile-it-with-o0 So get ready for some weird jumps, and `` fun. Why, Linux, why. +tmux just makes things even more fun by allowing us to see both terminals at once without dragging windows around! https://unix.stackexchange.com/questions/152738/how-to-split-a-new-window-and-run-a-command-in-this-new-window-using-tmux/432111#432111 -=== Kernel module debugging +.... +./tmu ./rungdb && ./run -dn +.... + +=== GDB step debug kernel module Loadable kernel modules are a bit trickier since the kernel can place them at different memory locations depending on load order. So we cannot set the breakpoints before `insmod`. -However, the Linux kernel GDB scripts offer the `lx-symbols` command, which takes care of that beautifully for us: +However, the Linux kernel GDB scripts offer the `lx-symbols` command, which takes care of that beautifully for us. + +Shell 1: .... -./run -d -./rungdb +./run .... -In QEMU: +Wait for the boot to end and run: .... insmod /timer.ko .... +This prints a message to dmesg every second. + +Shell 2: + +.... +./rungdb +.... + In GDB, hit `Ctrl + C`, and note how it says: .... @@ -485,7 +514,13 @@ See also: http://stackoverflow.com/questions/28607538/how-to-debug-linux-kernel- ==== Bypass lx-symbols -Useless, but a good way to show how hardcore you are. From inside QEMU: +Useless, but a good way to show how hardcore you are. Disable `lx-symbols` with: + +.... +./rungdb -L +.... + +From inside guest: .... insmod /fops.ko @@ -505,7 +540,7 @@ Ctrl + C add-symbol-file ../kernel_module-1.0/fops.ko 0xfffffffa00000000 .... -=== Debug kernel early boot +=== GDB step debug early boot TODO: why can't we break at early startup stuff such as: @@ -514,8 +549,140 @@ TODO: why can't we break at early startup stuff such as: ./rungdb main .... +Maybe it is because they are being copied around at specific locations instead of being run directly from inside the main image, which is where the debug information points to? + See also: https://stackoverflow.com/questions/2589845/what-are-the-first-operations-that-the-linux-kernel-executes-on-boot +=== GDB step debug userland processes + +QEMU's `-gdb` 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/16273614/debug-init-on-qemu-using-gdb + +You will generally want to use <> for this as it is more reliable, but this method can overcome the following limitations of `gdbserver`: + +* the emulator does not support host to guest networking. This seems to be the case for gem5: <> +* cannot see the start of the `init` process easily +* `gdbserver` alters the working of the kernel, and makes your run less representative + +Known limitations of direct userland debugging: + +* the kernel might switch context to another process or to the kernel itself e.g. on a system call, and then TODO confirm the PIC would go to weird places and source code would be missing. +* 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. + +==== GDB step debug userland custom init + +* Shell 1: ++ +.... +./run -d -e 'init=/sleep_forever.out' +.... +* Shell 2: ++ +.... +./rungdb-user kernel_module-1.0/user/sleep_forever.out main +.... + +==== GDB step debug userland BusyBox init + +BusyBox custom init process: + +* Shell 1: ++ +.... +./run -d -e 'init=/bin/ls' +.... +* Shell 2: ++ +.... +./rungdb-user 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 +.... +* Shell 2: ++ +.... +./rungdb-user 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" +.... + +==== GDB step debug userland non-init + +Non-init process: + +* Shell 1: ++ +.... +./run -d +.... +* Shell 2: ++ +.... +./rungdb-user kernel_module-1.0/user/myinsmod.out main +.... +* Shell 1 after the boot finishes: ++ +.... +/myinsmod.out /hello.ko +.... + +This is the least reliable setup as there might be other processes that use the given virtual address. + +===== GDB step debug userland non-init without -d + +TODO: it works on x86 and aarch64 but fails on arm as follows: + +* Shell 1: ++ +.... +./run -a arm +.... +* Shell 2: wait for boot to finish, and run: ++ +.... +./rungdb-user -a arm kernel_module-1.0/user/myinsmod.out main +.... +* Shell 1: ++ +.... +/myinsmod.out /hello.ko +.... + +The problem is that the `b main` that we do inside `./rungdb-user` says: + +.... +Cannot access memory at address 0x107b8 +.... + +However, if we do a Ctrl + C, and then a direct: + +.... +b *0x107b8 +.... + +it works. Why?! + === GDB call GDB can call functions as explained at: https://stackoverflow.com/questions/1354731/how-to-evaluate-functions-in-gdb @@ -745,95 +912,6 @@ 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 -=== Debug userland process without gdbserver - -QEMU `-gdb` 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/16273614/debug-init-on-qemu-using-gdb - -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. - == Architectures The portability of the kernel and toolchains is amazing: change an option and most things magically work on completely different hardware. @@ -874,25 +952,6 @@ On gem5, it is possible to use the `m5` instrumentation from guest as a good wor .... m5 exit .... -* GDB step debugging of kernel modules broke at some point. This happens at 6420c31986e064c81561da8f2be0bd33483af598 on kernel v4.15, 6b0f89a8b43e8d33d3a3a436ed827f962da3008a v4.14 and 5ad68edd000685c016c45e344470f2c1867b8e39 v4.12 and also if kernel 4.9.6 is checked out. So maybe it was never working in the first place, but we never noticed? -+ -Just after GDB connects, we get the following message from the kernel GDB Python scripts: -.... -loading vmlinux -Traceback (most recent call last): - File "/home/ciro/bak/git/linux-kernel-module-cheat/buildroot/output.arm~/build/linux-custom/scripts/gdb/linux/symbols.py", line 163, in invoke - self.load_all_symbols() - File "/home/ciro/bak/git/linux-kernel-module-cheat/buildroot/output.arm~/build/linux-custom/scripts/gdb/linux/symbols.py", line 150, in load_all_symbols - [self.load_module_symbols(module) for module in module_list] - File "/home/ciro/bak/git/linux-kernel-module-cheat/buildroot/output.arm~/build/linux-custom/scripts/gdb/linux/symbols.py", line 110, in load_module_symbols - module_name = module['name'].string() - File "/home/ciro/bak/git/linux-kernel-module-cheat/buildroot/output.arm~/host/lib/python2.7/encodings/utf_8.py", line 16, in decode - return codecs.utf_8_decode(input, errors, True) -UnicodeDecodeError: 'utf8' codec can't decode byte 0x9f in position 2: invalid start byte -Error occurred in Python command: 'utf8' codec can't decode byte 0x9f in position 2: invalid start byte -.... -+ -and then after inserting the module, symbols are not found, presumably because `lx-symbols` never ran. === aarch64 @@ -911,16 +970,6 @@ ____ + `-M virt` has some limitations, e.g. I could not pass `-drive if=scsi` as for `arm`, and so <> fails. -So, as long as you keep those points in mind, our `-a aarch64` offers an interesting different setup to play with. - -TODOs: - -* <> appears to be stuck on an infinite loop: -+ -.... -no module object found for '' -.... - === mips64 Keep in mind that MIPS has the worst support compared to our other architectures due to the smaller community. Patches welcome as usual. @@ -1819,7 +1868,7 @@ Even mor awesome than `chroot` be to `pivot_root`, but I couldn't get that worki === Guest host networking -==== Host to guest +==== Host to guest networking Guest, BusyBox `nc` enabled with `CONFIG_NC=y`: @@ -1851,7 +1900,11 @@ BR2_PACKAGE_OPENSSH=y Not enabled by default due to the build / runtime overhead, but it was tested and worked at the time of this commit. -==== Guest to host +===== gem5 host to guest networking + +Could not do port forwarding from host to guest, and therefore could not use `gdbserver`: https://stackoverflow.com/questions/48941494/how-to-do-port-forwarding-from-guest-to-host-in-gem5 + +==== Guest to host networking TODO. There is `guestfwd`, which sounds analogous to `hostwfd` used in the other sense, but I was not able to get it working, e.g.: @@ -2373,7 +2426,7 @@ Yes, we do run the benchmarks on host just to unpack / generate inputs... and th PARSEC simply wasn't designed with non native machines in mind. -Running a benchmark of a different size requires a rebuild wit: +Running a benchmark of a different size requires a rebuild with: .... ./build \ @@ -2583,21 +2636,79 @@ On the second shell: ./rungdb -a arm -g .... -This makes the VM stop, so from inside GDB: - -.... -continue -.... - On a third shell: .... ./gem5-shell .... +When you want to break, just do a Ctrl + C on GDB shell, and then `continue`. + And we now see the boot messages, and then get a shell. Now try the `/continue.sh` procedure described for QEMU. -TODO: how to stop at `start_kernel`? gem5 listens for GDB by default, and therefore does not wait for a GDB connection to start like QEMU does. So when GDB connects we might have already passed `start_kernel`. Maybe `--debug-break=0` can be used? +TODO: how to stop at `start_kernel`? gem5 listens for GDB by default, and therefore does not wait for a GDB connection to start like QEMU does. So when GDB connects we might have already passed `start_kernel`. Maybe `--debug-break=0` can be used? https://stackoverflow.com/questions/49296092/how-to-make-gem5-wait-for-gdb-to-connect-to-reliably-break-at-start-kernel-of-th + +==== gem5 GDB step debugging aarch64 + +TODO: GDB fails with: + +.... +Reading symbols from vmlinux...done. +Remote debugging using localhost:7000 +Remote 'g' packet reply is too long: 000000000000000090a4f90fc0ffffff4875450ec0ffffff01000000000000000100000000000000000000000000000001000000000000000000000000000000ffffffffffffffff646d60616b64fffe7f7f7f7f7f7f7f7f0101010101010101300000000000000000000000ffffffff48454422207d2c2017162f21262820160100000000000000070000000000000001000000000000004075450ec0ffffffc073450ec0ffffff82080000000000004075450ec0ffffff8060f90fc0ffffffc073450ec0fffffff040900880ffffff40ab400ec0ffffff586d900880ffffff0068a20ec0ffffff903b010880ffffffc8ff210880ffffff903b010880ffffffccff210880ffffff050000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +.... + +and gem5 says: + +.... +4107766500: system.remote_gdb: remote gdb attached +warn: Couldn't read data from debugger. +4107767500: system.remote_gdb: remote gdb detached +.... + +I've also tried the fix at: https://stackoverflow.com/questions/27411621/remote-g-packet-reply-is-too-long-aarch64-arm64 by adding to the link:rungdb[] script: + +.... +-ex 'set tdesc filename buildroot/output.aarch64~/build/gdb-7.11.1/./gdb/features/aarch64.xml' +.... + +but it did not help. + +=== gem5 debug userland programs + +TODO + +We are unable to use `gdbserver` because of networking: <> + +The alternative is to do as in <>. + +First make sure that for your arch: + +* the kernel debugging on the given target works for the architecture: <>. +* as explained at <>, some archs require explicit `b *0x1234` addresses, `b main` didn't work + +On shell 1: + +.... +./run -a arm -d -g +.... + +Shell 2: + +.... +./rungdb-user -a arm -g kernel_module-1.0/user/myinsmod.out main +.... + +Gives: + +.... +Cannot access memory at address 0x107b8 +.... + +This does however work for QEMU, so it must be either: + +* a timing sensitive thing. The address is only visible sometimes, and because QEMU runs faster, we usually saw it when it was available. +* a protocol thing of type QEMU GDB allows addresses that are not currently present on the pagetables, but gem5 does not. === gem5 checkpoint @@ -2945,11 +3056,9 @@ which is very close to the end of the boot. Increasing the memory from 256M to 5 === gem5 limitations * networking not working. We currently just disable it from `inittab` by default to prevent waiting at startup -* could not do port forwarding from host to guest, and therefore use `gdbserver`: https://stackoverflow.com/questions/48941494/how-to-do-port-forwarding-from-guest-to-host-in-gem5 ==== gem5 x86_64 limitations -* `gdb` debugging not working. First we need to remove the initial `set arch i386:x86-64:intel` required for QEMU. Then it cannot find the symbols. * gets stuck for a long time at: + .... diff --git a/br2 b/br2 index 8eda4ea..6af2e65 100644 --- a/br2 +++ b/br2 @@ -5,6 +5,7 @@ BR2_PACKAGE_KERNEL_MODULE=y BR2_TARGET_ROOTFS_CPIO=n BR2_TARGET_ROOTFS_EXT2=y BR2_TARGET_ROOTFS_INITRAMFS=n +BR2_TARGET_ROOTFS_EXT2_SIZE="512M" BR2_CCACHE=y # Otherwise our precious debug would break! diff --git a/kernel_config_x86_64-gem5 b/kernel_config_x86_64-gem5 index f29b4a1..704d52d 100644 --- a/kernel_config_x86_64-gem5 +++ b/kernel_config_x86_64-gem5 @@ -1,6 +1,14 @@ # Copied from: http://web.archive.org/web/20171229121642/http://www.lowepower.com/jason/files/config # which is referenced at: http://web.archive.org/web/20171229121525/http://www.lowepower.com/jason/setting-up-gem5-full-system.html +## Start changes for LKMC + +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_INFO=y +CONFIG_GDB_SCRIPTS=y + +## End changes for LKMC + # # Automatically generated file; DO NOT EDIT. # Linux/x86 4.8.13 Kernel Configuration @@ -2380,7 +2388,6 @@ CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # # Compile-time checks and compiler options # -# CONFIG_DEBUG_INFO is not set # CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set CONFIG_FRAME_WARN=2048 @@ -2388,7 +2395,6 @@ CONFIG_FRAME_WARN=2048 # CONFIG_READABLE_ASM is not set # CONFIG_UNUSED_SYMBOLS is not set # CONFIG_PAGE_OWNER is not set -# CONFIG_DEBUG_FS is not set # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_SECTION_MISMATCH is not set CONFIG_SECTION_MISMATCH_WARN_ONLY=y diff --git a/run b/run index ca75f21..20e8ea1 100755 --- a/run +++ b/run @@ -6,6 +6,7 @@ set -e arch=x86_64 cpus=1 debug_vm='' +debug=false kgdb=false kvm=false # norandmaps: Don't use address space randomization. Equivalent to echo 0 > /proc/sys/kernel/randomize_va_space. @@ -36,7 +37,8 @@ while getopts a:c:DdE:e:f:G:gIiKkm:nt:x OPT; do debug_vm='gdb -q -ex start --args' ;; d) - extra_flags_qemu="$extra_flags_qemu -S -s" + debug=true + extra_flags_qemu="$extra_flags_qemu -S" ;; E) lkmc_eval="$OPTARG" @@ -84,6 +86,10 @@ done shift "$(($OPTIND - 1))" extra_flags="$extra_flags $@" set_common_vars "$arch" "$gem5" +if "$debug" && "$kvm"; then + echo 'error: -d and -K are incompatible' 1>&2 + exit 1 +fi if "$initrd" || "$initramfs"; then ramfs=true else @@ -159,10 +165,11 @@ else qemu_common="\ ${debug_vm} \ '${out_dir}/host/usr/bin/qemu-system-${arch}' \ +-gdb tcp::1234 \ -m ${memory} \ -monitor telnet::45454,server,nowait \ -netdev user,hostfwd=tcp::45455-:45455,id=net0 \ --smp $cpus \ +-smp ${cpus} \ -virtfs local,path=9p,mount_tag=host_scratch,security_model=mapped,id=host_scratch \ -virtfs local,path=${out_dir}/build,mount_tag=host_out,security_model=mapped,id=host_out \ " diff --git a/rungdb b/rungdb index f1a369e..08c10f6 100755 --- a/rungdb +++ b/rungdb @@ -1,11 +1,13 @@ #!/usr/bin/env bash set -eu . common +after='' arch='x86_64' -bdfore='' +before='' gem5=false +lx_symbols="-ex 'lx-symbols ../kernel_module-1.0/'" kgdb=false -while getopts A:a:b:gk OPT; do +while getopts A:a:b:gkL OPT; do case "$OPT" in a) arch="$OPTARG" @@ -22,61 +24,65 @@ while getopts A:a:b:gk OPT; do k) kgdb=true ;; + L) + lx_symbols='' + ;; esac done shift "$(($OPTIND - 1))" if [ "$#" -gt 0 ]; then - brk="-ex 'break $1'" + brk="-ex 'break ${1}'" shift else brk='' fi if "$gem5"; then - arch_dir="${arch}-gem5" port=7000 else - arch_dir="$arch" port=1234 fi set_common_vars "$arch" "$gem5" -gdb="${out_dir}/host/usr/bin/${arch}-linux-gdb $before" +gdb="${out_dir}/host/usr/bin/${arch}-linux-gdb ${before}" cd "${out_dir}/build/linux-custom/" if "$kgdb"; then - cmd="$gdb \ + cmd="\ +${gdb} \ -q \ -ex 'add-auto-load-safe-path $(pwd)' \ -ex 'file vmlinux' \ --ex 'target remote localhost:$port' +-ex 'target remote localhost:${port}' " else - case "$arch" in - 'x86_64') - cmd="$gdb \ + # ## lx-symbols + # + # ### lx-symbols after continue + # + # lx symbols must be run after continue. + # + # running it immediately after the connect on the bootloader leads to failure, + # likely because kernel structure on which it depends are not yet available. + # + # With this setup, continue runs, and lx-symbols only runs when a break happens, + # either by hitting the breakpoint, or by entering Ctrl + C. + # + # Sure, if the user sets a break on a raw address of the bootloader, + # problems will still arise, but let's think about that some other time. + # + # ### lx-symbols autoload + # + # The lx-symbols commands gets loaded through the file vmlinux-gdb.py + # which gets put on the kernel build root when python debugging scripts are enabled. + cmd="\ +${gdb} \ -q \ -ex 'add-auto-load-safe-path $(pwd)' \ -ex 'file vmlinux' \ --ex 'set arch i386:x86-64:intel' \ --ex 'target remote localhost:$port' \ -$brk \ +-ex 'target remote localhost:${port}' \ +${brk} \ -ex 'continue' \ --ex 'disconnect' \ --ex 'set arch i386:x86-64' \ --ex 'target remote localhost:$port' \ --ex 'lx-symbols ../kernel_module-1.0/' \ +${lx_symbols} \ " - ;; - 'arm'|'aarch64'|'mips64') - cmd="$gdb \ --q \ --ex 'add-auto-load-safe-path $(pwd)' \ --ex 'file vmlinux' \ --ex 'target remote localhost:$port' \ --ex 'lx-symbols ../kernel_module-1.0/' \ -$brk \ -" - ;; - esac fi cmd="$cmd $after" -echo "$cmd" | tee rungdb.log +echo "$cmd" | tee "${root_dir}/rungdb.log" eval "$cmd" diff --git a/rungdb-user b/rungdb-user index e075f86..05c51a2 100755 --- a/rungdb-user +++ b/rungdb-user @@ -4,6 +4,7 @@ set -eu usage="$0 []" arch='x86_64' gem5=false +gem5_opt='' while getopts a:gh OPT; do case "$OPT" in a) @@ -11,6 +12,7 @@ while getopts a:gh OPT; do ;; g) gem5=true + gem5_opt=-g ;; h) echo "$usage" @@ -32,7 +34,11 @@ executable="${out_dir}/build/${executable_rel}" readelf="${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" +# -L or else lx-symbols throws for arm: +# gdb.MemoryError: Cannot access memory at address 0xbf0040cc +# TODO understand better. +# +# Also, lx-symbols overrides the add-symbol-file commands. +cmd="./rungdb -a '${arch}' -b '${ex}' ${gem5_opt} -L ${brk}" echo "$cmd" eval "$cmd"