Update tests to gracefully handle multiple qemu processess running

Previously test scripts would just indiscriminately kill all qemu
processes on the system. This would kill other debug sessions I had
running. These changes make the test scripts record the qemu pids they
run and only kill those.

The old scripts would also not allow you to specify a gdb port, so
if you were already running a debug session with port 1234, the tests
would fail. This update allows you to pass --gdb-port=NNNN to use a
non-default port. You can pass -Q to preserve failing qemu instances.
The scripts now also will show qemu errors to console, and will warn
the user if there is a qemu port conflict.

Also update gdb-pt-dump submodule as it has been updated recently to not
throw an exception when multiple qemu processes are running. The
exception thrown in the event of a failure also changed, so
this has also been updated on the pwndbg side.
pull/1905/head
Aaron Adams 2 years ago committed by Disconnect3d
parent 9110cb14f6
commit ee0377d3bf

@ -1 +1 @@
Subproject commit 25bae64f45e5e957cab5083a1067acc88ce70ec5
Subproject commit aa7d3f86ed1554224c11fe9578562dfaea37d96e

@ -434,7 +434,7 @@ def kernel_vmmap_via_page_tables():
p = pt.PageTableDump()
try:
p.lazy_init()
except PermissionError:
except Exception:
print(
M.error(
"Permission error when attempting to parse page tables with gdb-pt-dump.\n"

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
ARCH=""
KERNEL_TYPE=""
@ -8,12 +8,13 @@ CWD=$(dirname -- "$0")
IMAGE_DIR="${CWD}/images"
KERNEL_LIST=($(basename -a "${IMAGE_DIR}"/vmlinux* | sed "s/vmlinux-//"))
GDB_PORT=1234
help_and_exit() {
echo "Usage: $0 [options] [-- other qemu options]"
echo ""
echo " --kernel=<KERNEL> select kernel to run"
echo " --append=<CMDLINE> append something to the kernel's cmdline."
echo " --gdb-port=<PORT> specify gdb kernel port"
echo ""
echo "Options after '--' will be passed to QEMU."
echo ""
@ -26,6 +27,7 @@ while [[ $# -gt 0 ]]; do
case "$1" in
--kernel=*) KERNEL_NAME="${1#--kernel=}" ;;
--append=*) CMDLINE="${CMDLINE} ${1#--append=}" ;;
--gdb-port=*) GDB_PORT="${1#--gdb-port=}" ;;
-h | --help) help_and_exit ;;
--)
shift
@ -73,10 +75,9 @@ QEMU_ARGS+=(
-kernel $KERNEL
-nographic
-drive "file=$ROOTFS,if=virtio,format=qcow2"
-S -s
-S -gdb tcp::${GDB_PORT}
"${QEMU_ARGS_EXT[@]}"
)
echo "Waiting for GDB to attach (use 'ctrl-a x' to quit)"
$QEMU_BIN ${QEMU_ARGS[@]} -append "${CMDLINE}"
$QEMU_BIN ${QEMU_ARGS[@]} -append "${CMDLINE}"

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
#set -o errexit
set -o pipefail
@ -24,18 +24,21 @@ EOF
fi
help_and_exit() {
echo "Usage: ./tests.sh [-p|--pdb] [-c|--cov] [<test-name-filter>]"
echo " -p, --pdb enable pdb (Python debugger) post mortem debugger on failed tests"
echo " -c, --cov enable codecov"
echo " -v, --verbose display all test output instead of just failing test output"
echo " --collect-only only show the output of test collection, don't run any tests"
echo " <test-name-filter> run only tests that match the regex"
echo "Usage: ./tests.sh [-p|--pdb] [-c|--cov] [--gdb-port=<port>] [-Q|--preserve-qemu-image] [<test-name-filter>]"
echo " -p, --pdb enable pdb (Python debugger) post mortem debugger on failed tests"
echo " -c, --cov enable codecov"
echo " -v, --verbose display all test output instead of just failing test output"
echo " --gdb-port=<port> specify debug port for gdb/QEMU (Default: 1234)"
echo " --collect-only only show the output of test collection, don't run any tests"
echo " -Q, --preserve-qemu-image don't kill QEMU image after failed tests"
echo " <test-name-filter> run only tests that match the regex"
exit 1
}
handle_sigint() {
echo "Exiting..." >&2
pkill qemu-system
echo "Killing QEMU process $QEMU_PID"... >&2
pkill -P $QEMU_PID
exit 1
}
trap handle_sigint SIGINT
@ -49,26 +52,30 @@ TEST_NAME_FILTER=""
RUN_CODECOV=0
VERBOSE=0
COLLECT_ONLY=0
PRESERVE_QEMU_IMAGE=0
GDB_PORT=1234
while [[ $# -gt 0 ]]; do
case $1 in
-p | --pdb)
USE_PDB=1
echo "Will run tests with Python debugger"
shift
;;
-c | --cov)
echo "Will run codecov"
RUN_CODECOV=1
shift
;;
-v | --verbose)
VERBOSE=1
shift
;;
--collect-only)
COLLECT_ONLY=1
shift
;;
-Q | --preserve-qemu-image)
PRESERVE_QEMU_IMAGE=1
;;
--gdb-port=*)
GDB_PORT="${1#--gdb-port=}"
;;
-h | --help)
help_and_exit
@ -78,11 +85,27 @@ while [[ $# -gt 0 ]]; do
help_and_exit
fi
TEST_NAME_FILTER="$1"
shift
;;
esac
shift
done
# Test if the port is already listening, possibly by other qemu instance. This
# can cause unexpected test failures.
NETSTAT=$(which netstat)
if [[ -z "${NETSTAT}" ]]; then
NETSTAT=$(which ss)
fi
if [[ -z "${NETSTAT}" ]]; then
echo "WARNING: netstat/ss not found. Cannot check if port ${GDB_PORT} is already bound." >&2
exit 1
else
if [[ $(${NETSTAT} -tuln 2> /dev/null | grep ":${GDB_PORT}" | grep -c LISTEN) -ne 0 ]]; then
echo "WARNING: Port ${GDB_PORT} appears already bound. Please specify a different port with --gdb-port=<port>" >&2
exit 1
fi
fi
gdb_load_pwndbg=(--command "$GDB_INIT_PATH" -ex "set exception-verbose on")
run_gdb() {
local arch="$1"
@ -118,7 +141,7 @@ init_gdb() {
local kernel_version="$2"
local arch="$3"
gdb_connect_qemu=(-ex "file ${IMAGE_DIR}/vmlinux-${kernel_type}-${kernel_version}-${arch}" -ex "target remote :1234")
gdb_connect_qemu=(-ex "file ${IMAGE_DIR}/vmlinux-${kernel_type}-${kernel_version}-${arch}" -ex "target remote :${GDB_PORT}")
# using 'rest_init' instead of 'start_kernel' to make sure that kernel
# initialization has progressed sufficiently for testing purposes
gdb_args=("${gdb_connect_qemu[@]}" -ex 'break *rest_init' -ex 'continue')
@ -131,11 +154,12 @@ run_test() {
local kernel_version="$3"
local arch="$4"
gdb_connect_qemu=(-ex "file ${IMAGE_DIR}/vmlinux-${kernel_type}-${kernel_version}-${arch}" -ex "target remote :1234")
gdb_connect_qemu=(-ex "file ${IMAGE_DIR}/vmlinux-${kernel_type}-${kernel_version}-${arch}" -ex "target remote :${GDB_PORT}")
gdb_args=("${gdb_connect_qemu[@]}" --command pytests_launcher.py)
if [ ${RUN_CODECOV} -ne 0 ]; then
gdb_args=(-ex 'py import coverage;coverage.process_startup()' "${gdb_args[@]}")
fi
SRC_DIR=$ROOT_DIR \
COVERAGE_FILE=$ROOT_DIR/.cov/coverage \
COVERAGE_PROCESS_START=$COVERAGERC_PATH \
@ -151,6 +175,9 @@ run_test() {
process_output() {
output="$1"
if [[ -z "$output" ]]; then
return
fi
read -r testname result < <(
echo "$output" | grep -Po '(^tests/[^ ]+)|(\x1b\[3.m(PASSED|FAILED|SKIPPED|XPASS|XFAIL)\x1b\[0m)' \
@ -189,8 +216,10 @@ test_system() {
fi
echo ""
"${CWD}/run_qemu_system.sh" --kernel="${kernel_type}-${kernel_version}-${arch}" -- "${qemu_args[@]}" > /dev/null 2>&1 &
# NOTE: If you run simultaneous tests or left an image lying around via -Q, this
# will hang due to failure to obtain lock. But will see the error message...
"${CWD}/run_qemu_system.sh" --kernel="${kernel_type}-${kernel_version}-${arch}" --gdb-port="${GDB_PORT}" -- "${qemu_args[@]}" > /dev/null &
QEMU_PID=$!
init_gdb "${kernel_type}" "${kernel_version}" "${arch}"
start=$(date +%s)
@ -217,10 +246,16 @@ test_system() {
echo ""
echo "Failing tests: ${FAILED_TESTS[@]}"
echo ""
if [ ${PRESERVE_QEMU_IMAGE} -eq 0 ]; then
pkill -P $QEMU_PID
else
echo "Preserving qemu image for debugging purposes. Kill with 'pkill -P $QEMU_PID'"
fi
exit 1
fi
pkill qemu-system
pkill -P $QEMU_PID
}
for vmlinux in "${VMLINUX_LIST[@]}"; do

Loading…
Cancel
Save