gdb do not work when kernel ctf

kernel 익스 문제를 처음으로 풀어봤는데 run.sh 로 qemu로 vmlinux를 실행하고 이제 vmlinux에 gdb로 들어가서 디버깅을 해야하는데 이상하게 gdb가 실행이 되지 않았다.

이유를 분석하다 보니깐..

기존 run.sh 을 보면

Shell
#!/bin/sh
# Copyright (C) 2020  Theori Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
set -e

listen_host=${1:-127.0.0.1}
listen_port_con=${2:-8023}
listen_port_ser=${3:-8088}

# [Local] $ nc <HOST> <PORT-8088> < local-file > /dev/null
#    [VM] $ cat /dev/vport0p1 > /tmp/remote-file

exec qemu-system-x86_64 \
	-M microvm,x-option-roms=off,isa-serial=off -no-acpi \
	-cpu qemu64 -m 128m -smp 1 -no-reboot \
	-kernel vmlinuz -initrd initramfs.img -dtb no-shutdown.dtb \
	-append "reboot=t panic=-1 console=hvc0 quiet" \
	-nodefaults -no-user-config -nographic \
	-device virtio-serial-device \
	-chardev socket,id=virtiocon0,server,telnet,host="$listen_host",port="$listen_port_con" \
	-device virtconsole,chardev=virtiocon0 \
	-chardev socket,id=virtioser0,server,nowait,host="$listen_host",port="$listen_port_ser" \
	-device virtserialport,chardev=virtioser0

다음과 같이 기본 8023 포트로 접속을 하게 해놓았는데

즉, 콘솔 chardev(8023)가 “nowait”가 아니라서, QEMU가 콘솔 연결이 올 때까지 초기화를 그 지점에서 멈춰서 기다리는 상태가 된다.

즉, 한번의 연결이 있기 전까지 gdbstub도 아직 리슨 소켓을 못 열게 될수도 있다는 말 (초기화 순서상).

따라서 다음과 같이

Shell
#!/bin/sh
# Copyright (C) 2020  Theori Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
set -e

listen_host=${1:-127.0.0.1}
listen_port_con=${2:-8023}
listen_port_ser=${3:-8088}

# [Local] $ nc <HOST> <PORT-8088> < local-file > /dev/null
#    [VM] $ cat /dev/vport0p1 > /tmp/remote-file

exec qemu-system-x86_64 \
	-M microvm,x-option-roms=off,isa-serial=off -no-acpi \
	-cpu qemu64 -m 128m -smp 1 -no-reboot \
	-kernel vmlinuz -initrd initramfs.img -dtb no-shutdown.dtb \
	-append "reboot=t panic=-1 nokaslr console=hvc0 quiet" \
	-nodefaults -no-user-config -nographic \
	-S -gdb tcp:127.0.0.1:31235 \
	-device virtio-serial-device \
	-chardev socket,id=virtiocon0,server,telnet,wait=off,host="$listen_host",port="$listen_port_con" \
	-device virtconsole,chardev=virtiocon0 \
	-chardev socket,id=virtioser0,server,nowait,host="$listen_host",port="$listen_port_ser" \
	-device virtserialport,chardev=virtioser0

nowait 나 wait=off 를 붙여주면 된다