crash
는 리눅스 커널 소스를 GNU gdb
와 연동하여 디버깅할 수 있는 도구다. gdb
는 다양한 기능을 제공하지만 커널 덤프 파일을 분석하기에는 불편하다. crash
는 이러한 덤프 파일을 분석하는데 도움이 되는 다양한 기능을 제공한다.
crash
설치하기 crash
는 아래의 명령어를 통해 설치가 가능하다:
sudo apt install linux-crashdump
이제 crash -v
를 입력해서 버전을 확인한다. 만일 버전이 7.3
이하라면 5.12.2
커널에서는 제대로 동작하지 않을 수 있다. 만일 버전이 낮다면 공식 레포지토리에 들어가서 설치하는 방법으로 진행해야 한다.
git clone "https"//github.com/crash-utility/crash" cd crash make sudo cp -v crash /bin/crash
위 명령어를 순서대로 입력한 후 다시 crash -v
를 입력해서 버전을 확인한다. 아래와 같이 나오면 성공이다.
또한 crash
를 사용하기 위해서는 커널 소스를 -g
옵션으로 컴파일해야 하는데 일반적으로 다 설정이 되어 있으므로 특별히 무언가 건드릴 필요는 없다. 혹시 궁금하다면 커널을 빌드할 때 사용했던 .config
파일에서 다음의 정보를 확인하길 바란다.
CONFIG_DEBUG_INFO=y
CONFIG_KGDB=y
CONFIG_KGDB_SERIAL_CONSOLE=y
CONFIG_FRAME_POINTER=y
crash
실행 with Live System
아무 옵션도 주지 말고 crash
입력해서 실행해봐라.
다음과 같은 메세지가 나올텐데, 보는 것처럼 crash
프로그램은 /dev/mem
디바이스 노드에 접근한다. 따라서 root
권한으로 실행하지 않으면 프로그램이 제대로 실행되지 않을 수 있다. root
권한으로 다시 crash
를 실행하면 아래와 같이 터미널의 입력부가 crash>
로 바뀌게 된다:
위와 같이 나오면 성공이다. 만일 이렇게 실행이 안된다면 .config
파일의 CONFIG_STRICT_DEVMEM
값을 제거하고 다시 빌드, /etc/default/grub
파일의 GRUB_CMDLINE_LINUX
의 값을 아래와 같이 바꾸길 바란다:
GRUB_CMDLINE_LINUX="crashkernel=auto console=ttyS0 console=tty0 panic=5 net.ifnames=0 biosdevname=0"
crash
실행 with dump file
crash
는 /dev/mem
에 실시간으로 접근하여 커널을 디버깅할 수도 있지만, 커널 실행 데이터를 미리 덤프하여 디버깅하는 것도 가능하다. 커널 데이터 덤프를 위해서는 아래의 도구를 설치해야 한다:
sudo apt install kexec-tools sudo apt install linux-crashdump sudo apt install kdump-tools
필자는 이미 모두 설치되어 있었는데 만일 설치가 안되어 있다면 설치하도록 하자. 이제 커널 덤프를 가능하도록 만들기 위해 다음과 같이 실행하여 "Yes" 를 선택한다.
sudo dpkg-reconfigure kdump-tools
위에서 YES
를 선택하면 /etc/default/kdump-tools
환경설정 파일의 값이 USE_KDUMP=1
로 바뀔 것이다.
sudo kdump-config show
를 입력해서 결과를 확인할 수도 있다. 필자는 아래와 같은 결과가 나왔다.
마지막으로 /etc/default/kexec
파일의 내용이 아래와 같이 설정되어 있는지 확인한다:
# Defaults for kexec initscript
# sourced by /etc/init.d/kexec and /etc/init.d/kexec-load
# Load a kexec kernel (true/false)
LOAD_KEXEC=true
# Kernel and initrd image
KERNEL_IMAGE="/vmlinuz"
INITRD="/initrd.img"
# If empty, use current /proc/cmdline
APPEND=""
# Load the default kernel from grub config (true/false)
USE_GRUB_CONFIG=true
반드시 LOAD_KEXEC
과 USE_GRUB_CONFIG
가 true
로 설정되어 있어야 한다. 이제 아래의 명령어를 입력해서 커널을 덤프한다. 덤프 명령어를 입력하면 시스템은 자동으로 재부팅된다.
su
echo 1 > /proc/sys/kernel/sysrq
echo c > /proc/sysrq-trigger
crash
명령어 사용하기사용 가능한 crash
명령어는 crash
프로그램이 실행된 상태로 help
를 입력해서 확인할 수 있다.
backtrace
명령 (bt
) backtrace
명령은 커널 안에서 명령들이 실행된 흐름을 추적할 수 있다. 여러가지 인자를 전달할 수 있지만 필자는 간단히 bt
명령만 입력해서 실행시켜 보았다. 자세한 내용은 help bt
를 입력해서 확인하길 바란다.
bt
명령어만 실행하면 다음과 같이 현재 실행된 프로세스의 정보를 출력한다.
ps
명령어ps
명령어는 프로세스의 상태 정보를 표시한다. ps -k
옵션으로 실행하면 커널 프로세스(태스크, 쓰레드) 리스트가, ps -u
옵션으로 실행하면 유저 프로세스 리스트가 출력된다.
위 정보는 커널 프로세스 리스트 정보이고 아래는 유저 프로세스 리스트이다:
struct
명령 struct
명령은 커널 구조체들의 구조와 그 안의 값들을 출력한다. 커널 스케쥴러에서 중요한 역할을 하는 task_struct
구조체는 아래와 같이 출력된다.
crash > strut task_struct
내용이 너무 길어서 아주 일부만 잘라서 가져왔는데 직접 출력해서 그 내용을 확인해보길 바란다. -o
옵션을 추가하면 구조체의 멤버 변수들의 오프셋도 같이 출력되니 옵션을 주고 출력하는 것도 좋을 것이다.
task
명령 task
명령은 task_struct
구조체와 thread_info
구조체 안의 내용을 출력한다.
위 삽화는 아무런 옵션없이 그냥 명령을 입력했을 때의 출력결과이다. task
명령만 입력하게 되면 실행되고 있는 프로세스의 정보를 출력하게 된다. 프로세스 명은 "crash"
이고 프로세스 ID
는 23540
이다.
vm
명령 vm
명령은 커널의 가상 메모리 정보를 출력한다. -m <pid>
형태로 옵션을 주면 해당 프로세스의 mm_struct
구조체의 내용을 출력한다. 아래의 삽화는 현재 실행 중인 crash
프로그램의 mm_struct
의 일부분이다:
kmem
명령 kmem
명령은 커널 메모리와 관련된 내용들을 보여준다. -i
옵션을 주고 명령을 실행하면 현재 메모리 사용 정보를 출력한다:
sym
명령sym
명령은 커널의 심볼 정보를 출력한다. -l
옵션으로 전체 심볼의 정보를 출력한 결과는 아래와 같다:
p
명령p
명령은 pinrt
의 약자이다. 심볼이나 표현식의 값을 출력한다.
list
, tree
명령list
, tree
명령은 커널의 연결 리스트와 트리 자료구조의 정보를 출력한다.
foreach
명령은 여러가지 명령이 반복 실행된 결과 데이터를 출력한다.
[사이트] https://github.com/crash-utility/crash
[책] 리눅스 커널 소스 해설: 기초입문 (정재준 저)