new file mode 100644
@@ -0,0 +1,68 @@
+python
+import os, subprocess
+kdir = os.environ['KERNELDIR']
+mdir = os.environ['MODULEDIR'] or '/lib/modules'
+gdb.execute(f'add-auto-load-safe-path {kdir}/scripts/gdb/')
+cwd=os.getcwd()
+gdb.execute(f'cd {kdir}')
+gdb.execute(f'source {kdir}/vmlinux-gdb.py')
+p = subprocess.run([f'./linux', '--version'], capture_output=True)
+ver = p.stdout.strip().decode('ascii')
+gdb.execute(f'cd {cwd}')
+end
+break os_early_checks
+commands
+silent
+python
+gdb.execute(f'cd {kdir}')
+gdb.execute(f'lx-symbols {mdir}/{ver}/')
+gdb.execute(f'cd {cwd}')
+end
+# only once
+del 1
+continue
+end
+handle 11 nostop noprint pass
+#
+# So ... this is complicated. When gdb installs a regular breakpoint
+# on some place, it writes there a breakpoint instruction (which is
+# a single 0xCC byte on x86). This breaks out into the debugger and
+# it can then restart/simulate the correct instruction when continuing
+# across the breakpoint.
+#
+# Additionally, gdb (correctly) removes these breakpoint instructions
+# from forked children when detaching from them. This also seems fine.
+#
+# However, due to how user-mode-linux works, this causes issues with
+# kernel modules. These are loaded into the vmalloc area, and even if
+# that isn't quite part of physmem, it's still mapped as MAP_SHARED.
+#
+# Unfortunately, this means that gdb deletes breakpoints in modules
+# when a new userspace process is started, since that causes a new
+# process to be created by clone() and gdb has to detach from it.
+#
+# The other thing to know is that when gdb hits a breakpoint it will
+# restore all the code to normal, and reinstall breakpoints when we
+# continue.
+#
+# Thus we can use that behaviour to work around the module issue:
+# simply put a breakpoint on init_new_ldt which happens just after
+# the clone() for a new userspace process, and do nothing there but
+# continue, which reinstalls all breakpoints, including the ones in
+# modules.
+#
+break init_new_ldt
+commands
+silent
+continue
+end
+
+echo \n
+echo Welcome to hwsim kernel debugging\n
+echo ---------------------------------\n\n
+echo You can install breakpoints in modules, they're treated\n
+echo as shared libraries, so just say 'y' if asked to make the\n
+echo breakpoint pending on future load.\n\n
+echo Do NOT, however, delete the breakpoint on 'init_new_ldt'!\n\n
+echo Now enter 'run' to start the run.\n\n
+echo Have fun!\n\n
@@ -62,6 +62,7 @@ TIMESTAMP=$(date +%s)
DATE=$TIMESTAMP
CODECOV=no
TIMEWARP=0
+GDB=0
TELNET_QEMU=
TELNET_ARG=0
CODECOV_DIR=
@@ -85,6 +86,9 @@ while [ "$1" != "" ]; do
--timewrap ) shift
TIMEWARP=1
;;
+ --gdb ) shift
+ GDB=1
+ ;;
--telnet ) shift
TELNET_ARG=1
TELNET_QEMU="-net nic,model=virtio -net user,id=telnet,restrict=on,net=172.16.0.0/24,hostfwd=tcp:127.0.0.1:$1-:23"
@@ -162,17 +166,22 @@ fi
A+="ro"
if [ -z $KVM ]; then
- $KERNEL \
- mem=${MEMORY}M \
+ UML_ARGS="mem=${MEMORY}M \
LOGDIR=$LOGDIR \
time-travel=inf-cpu \
$A \
root=none hostfs=/ rootfstype=hostfs rootflags=/ \
ssl0=fd:0,fd:1 \
ssl1=fd:100 \
- ssl-non-raw \
- 100<>$LOGDIR/console 2>&1 | \
- sed -u '0,/VM has started up/d'
+ ssl-non-raw"
+
+ if [ "$GDB" = "1" ] ; then
+ export KERNELDIR=$KERNELDIR
+ export MODULEDIR=$MODULEDIR
+ gdb -ex "source linux.gdb" --args $KERNEL $UML_ARGS 100<>$LOGDIR/console
+ else
+ $KERNEL $UML_ARGS 100<>$LOGDIR/console #2>&1 | sed -u '0,/VM has started up/d'
+ fi
else
$KVM \
-kernel $KERNEL \