diff --git a/README.adoc b/README.adoc index 99acaf1..38053b9 100644 --- a/README.adoc +++ b/README.adoc @@ -8998,13 +8998,13 @@ time \ and this line is also saved to a file for convenience: .... -cat "$(./getvar -a arm run_dir)/cmd.sh" +cat "$(./getvar -a arm run_cmd_file)" .... or for gem5: .... -cat "$(./getvar -a arm -g run_dir)/cmd.sh" +cat "$(./getvar -a arm -g run_cmd_file)" .... Next, you will also want to give the relevant images to save them time. Zip the images with: @@ -9422,10 +9422,10 @@ The action seems to be happening at: `hw/arm/virt.c`. **** `out//buildroot/build/linux-custom`: symlink to a variant, custom madness that we do on top of Buildroot: <> **** `out//buildroot/build/linux-custom.`: what `linux-custom` points to *** `out//qemu`: QEMU runtime outputs -*** `out//qemu//cmd.sh`: full CLI used to run QEMU. See: <> +*** `out//qemu//run.sh`: full CLI used to run QEMU. See: <> *** `out//gem5//`: gem5 runtime outputs **** `out//gem5//m5out` -**** `out//gem5//cmd.sh`: full CLI used to run gem5. See: <> +**** `out//gem5//run.sh`: full CLI used to run gem5. See: <> ** `out/common`: cross arch outputs, for when we can gain a lot of time and space by sharing things that are common across different archs. *** `out/common/dl/`: Buildroot caches downloaded source there due to `BR2_DL_DIR` *** `out/common/gem5/`: `arm` and `aarch64` have the same build. diff --git a/common.py b/common.py index 206629b..f9d23cf 100644 --- a/common.py +++ b/common.py @@ -285,7 +285,7 @@ def setup(parser, **extra_args): this.executable = this.qemu_executable this.run_dir = this.qemu_run_dir this.termout_file = this.qemu_termout_file - this.run_cmd_file = os.path.join(this.run_dir, 'cmd.sh') + this.run_cmd_file = os.path.join(this.run_dir, 'run.sh') if args.arch == 'arm': this.linux_image = os.path.join('arch', 'arm', 'boot', 'zImage') elif args.arch == 'aarch64': diff --git a/rungdb b/rungdb index 3343834..e5da5c3 100755 --- a/rungdb +++ b/rungdb @@ -8,75 +8,79 @@ import subprocess import common -parser = common.get_argparse(argparse_args={'description':'Connect with GDB to an emulator to debug Linux itself'}) -parser.add_argument( - '-A', '--after', default='', - help='Pass extra arguments to GDB, to be appended after all other arguments' -) -parser.add_argument( - '-b', '--before', default='', - help='Pass extra arguments to GDB to be prepended before any of the arguments passed by this script' -) -parser.add_argument( - '-C', '--no-continue', default=False, action='store_true', - help="Don't run continue after connecting" -) -parser.add_argument( - '-k', '--kgdb', default=False, action='store_true' -) -parser.add_argument( - '-X', '--no-lxsymbols', default=False, action='store_true' -) -parser.add_argument( - 'break_at', nargs='?', - help='Extra options to append at the end of the emulator command line' -) -args = common.setup(parser) -after = shlex.split(args.after) -before = shlex.split(args.before) -if args.no_lxsymbols: - lx_symbols = [] -else: - lx_symbols = ['-ex', 'lx-symbols ../kernel_module-1.0/'] -if args.break_at is not None: - break_at = ['-ex', 'break {}'.format(args.break_at)] -else: - break_at = [] -cmd = ( - [ - os.path.join(common.host_bin_dir, - '{}-linux-gdb'.format(args.arch)) - ] + - before + - [ - '-q', - '-ex', 'add-auto-load-safe-path {}'.format(common.linux_variant_dir), - '-ex', 'file {}'.format(common.vmlinux), - '-ex', 'target remote localhost:{}'.format(common.gdb_port), - ] -) -if not args.kgdb: - cmd.extend(break_at) -if not args.no_continue: - # ## 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.extend(['-ex', 'continue'] + lx_symbols) -cmd.extend(after) -sys.exit(common.run_cmd(cmd, cmd_file=os.path.join(common.run_dir, 'rungdb.sh'), cwd=common.linux_variant_dir)) +def main(args): + after = shlex.split(args.after) + before = shlex.split(args.before) + if args.no_lxsymbols: + lx_symbols = [] + else: + lx_symbols = ['-ex', 'lx-symbols ../kernel_module-1.0/'] + if args.break_at is not None: + break_at = ['-ex', 'break {}'.format(args.break_at)] + else: + break_at = [] + cmd = ( + [ + os.path.join(common.host_bin_dir, + '{}-linux-gdb'.format(args.arch)) + ] + + before + + [ + '-q', + '-ex', 'add-auto-load-safe-path {}'.format(common.linux_variant_dir), + '-ex', 'file {}'.format(common.vmlinux), + '-ex', 'target remote localhost:{}'.format(common.gdb_port), + ] + ) + if not args.kgdb: + cmd.extend(break_at) + if not args.no_continue: + # ## 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.extend(['-ex', 'continue'] + lx_symbols) + cmd.extend(after) + return common.run_cmd(cmd, cmd_file=os.path.join(common.run_dir, 'rungdb.sh'), cwd=common.linux_variant_dir) + +if __name__ == '__main__': + parser = common.get_argparse(argparse_args={'description':'Connect with GDB to an emulator to debug Linux itself'}) + parser.add_argument( + '-A', '--after', default='', + help='Pass extra arguments to GDB, to be appended after all other arguments' + ) + parser.add_argument( + '-b', '--before', default='', + help='Pass extra arguments to GDB to be prepended before any of the arguments passed by this script' + ) + parser.add_argument( + '-C', '--no-continue', default=False, action='store_true', + help="Don't run continue after connecting" + ) + parser.add_argument( + '-k', '--kgdb', default=False, action='store_true' + ) + parser.add_argument( + '-X', '--no-lxsymbols', default=False, action='store_true' + ) + parser.add_argument( + 'break_at', nargs='?', + help='Extra options to append at the end of the emulator command line' + ) + args = common.setup(parser) + sys.exit(main(args)) diff --git a/rungdb-user b/rungdb-user index a4b2371..3a93df4 100755 --- a/rungdb-user +++ b/rungdb-user @@ -1,38 +1,45 @@ -#!/usr/bin/env bash -. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common" -gem5_opt= -while getopts "h${common_getopts_flags}" OPT; do - case "$OPT" in - h) - echo "$0 []" - exit - ;; - ?) - common_getopts_case "$OPT" - ;; - esac -done -shift "$(($OPTIND - 1))" -executable_rel="$1" -shift -if [ "$#" -gt 0 ]; then - brk="'$1'" - shift -else - brk= -fi -common_setup -if "$common_gem5"; then - gem5_opt=-g -fi -executable="${common_build_dir}/${executable_rel}" -addr="$("${common_root_dir}/runtc" readelf -h "$executable" | awk '/Entry/{ print $NF }' )" -ex="-ex \"add-symbol-file $executable $addr\"" -# -X or else lx-symbols throws for arm: +#!/usr/bin/env python3 + +import imp +import os +import subprocess +import re + +import common +rungdb = imp.load_source('config', 'rungdb') + +parser = common.get_argparse(argparse_args={ + 'description':'''GDB step debug guest userland processes without gdbserver. + +More information at: https://github.com/cirosantilli/linux-kernel-module-cheat#gdb-step-debug-userland-processes +''' +}) +parser.add_argument( + 'executable', + help='Path to the executable to be debugged relative to the Buildroot build directory.' +) +parser.add_argument( + 'break', + default=None, + help='Break at this point, e.g. main.', + nargs='?' +) +args = common.setup(parser) +readelf_header = subprocess.check_output([ + common.get_toolchain_tool('readelf'), + '-h', + os.path.join(common.build_dir, args.executable), +]) +for line in readelf_header.decode().split('\n'): + split = line.split() + if line.startswith(' Entry point address:'): + addr = line.split()[-1] + break +print(addr) +args.before = '-ex \"add-symbol-file {} {}\"'.format(args.executable, addr) +# 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 '${common_arch}' -b '${ex}' ${gem5_opt} -X ${brk}" -echo "$cmd" -eval "$cmd" +args.no_lxsymbols = True +rungdb.main(args) diff --git a/rungdbserver b/rungdbserver index 963a119..9236192 100755 --- a/rungdbserver +++ b/rungdbserver @@ -12,7 +12,7 @@ parser = common.get_argparse(argparse_args={ }) parser.add_argument( 'executable', - help='''Path to the executable to be debugged relative to the Buildroot build directory.''' + help='Path to the executable to be debugged relative to the Buildroot build directory.' ) args = common.setup(parser) sys.exit(subprocess.Popen([