Linux Tutorial #13 커널 덤프 분석 (crash)

문연수·2021년 5월 26일
1

Linux Tutorial

목록 보기
14/25

crash 는 리눅스 커널 소스를 GNU gdb 와 연동하여 디버깅할 수 있는 도구다. gdb 는 다양한 기능을 제공하지만 커널 덤프 파일을 분석하기에는 불편하다. crash 는 이러한 덤프 파일을 분석하는데 도움이 되는 다양한 기능을 제공한다.

1. 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

2. 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"

3. 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_KEXECUSE_GRUB_CONFIGtrue 로 설정되어 있어야 한다. 이제 아래의 명령어를 입력해서 커널을 덤프한다. 덤프 명령어를 입력하면 시스템은 자동으로 재부팅된다.

su
echo 1 > /proc/sys/kernel/sysrq
echo c > /proc/sysrq-trigger

4. 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" 이고 프로세스 ID23540 이다.

vm 명령

vm 명령은 커널의 가상 메모리 정보를 출력한다. -m <pid> 형태로 옵션을 주면 해당 프로세스의 mm_struct 구조체의 내용을 출력한다. 아래의 삽화는 현재 실행 중인 crash 프로그램의 mm_struct 의 일부분이다:

kmem 명령

kmem 명령은 커널 메모리와 관련된 내용들을 보여준다. -i 옵션을 주고 명령을 실행하면 현재 메모리 사용 정보를 출력한다:

sym 명령

sym 명령은 커널의 심볼 정보를 출력한다. -l 옵션으로 전체 심볼의 정보를 출력한 결과는 아래와 같다:

p 명령

p 명령은 pinrt 의 약자이다. 심볼이나 표현식의 값을 출력한다.

list, tree 명령

list, tree 명령은 커널의 연결 리스트와 트리 자료구조의 정보를 출력한다.

foreach 명령

foreach 명령은 여러가지 명령이 반복 실행된 결과 데이터를 출력한다.

출처

[사이트] https://github.com/crash-utility/crash
[책] 리눅스 커널 소스 해설: 기초입문 (정재준 저)

profile
2000.11.30

0개의 댓글