리눅스 커널 디버깅 개론 — User/Kernel 경계와 도구 선택
지금까지 다룬 GDB·Sanitizer·Valgrind는 모두 user-space 프로세스가 대상이었습니다. 커널은 다릅니다 — 멈춰서 들여다볼 프로세스 컨텍스트가 없고, 전체 시스템이 한 컨텍스트로 도는 데다, 디버거 자체가 그 위에서 돌고 있어 평소 도구가 안 통합니다.
이 시리즈는 Linux 커널 디버깅의 전체 흐름을 다룹니다. 첫 장은 왜 어렵나부터 — user/kernel 경계, /proc 인터페이스, 커널 심볼·debug info의 구조까지.
#User-space vs Kernel-space
| user-space | kernel-space | |
|---|---|---|
| 주소 공간 | 프로세스별 분리 | 단일 (모든 프로세스 공유) |
| 보호 | 페이지 권한 | 전 access |
| 정지 | ptrace로 가능 | 정지 = 시스템 정지 |
| crash 영향 | 그 프로세스만 | 시스템 전체 (panic) |
| 디버거 attach | gdb -p PID | kgdb (별 머신 필요) |
| 표준 도구 | printf | printk |
| Backtrace | DWARF + libunwind | objtool + ORC unwinder |
| Memory | malloc | kmalloc / vmalloc / get_free_pages |
자기 자신을 디버깅하는 bootstrap 문제가 핵심. CPU 한 개에서 도는 single-machine 환경에서는 디버거를 띄울 컨텍스트가 없기 때문.
#Kernel 디버깅 다섯 가지 방법
| 방법 | 사용 | 위험도 |
|---|---|---|
| printk + dmesg | 가장 흔함, 단순 | 낮음 |
| dynamic_debug | 런타임 토글 가능한 디버그 메시지 | 낮음 |
| ftrace | 함수·이벤트 trace, in-kernel | 낮음 |
| eBPF / bpftrace | 동적 instrumentation | 낮음 |
| kdb / kgdb | 실시간 인터랙티브 (별 머신 필요) | 중 |
| kdump + crash | 사후 분석 (vmcore 덤프) | 낮음 (사고 후) |
| drgn | Python으로 라이브/vmcore 분석 | 낮음 |
대부분의 일상은 printk + ftrace + bpftrace로 해결. 인터랙티브 step 디버깅은 드물지만 kgdb.
#/proc — 커널 상태의 표준 인터페이스
$ ls /proc/1/ 2/ ... buddyinfo cgroups cpuinfo filesystemsinterrupts iomem ioports kallsyms kmsg loadavgmeminfo modules mounts net/ schedstat slabinfosoftirqs stat swaps sys/ uptime version vmallocinfo vmstat핵심 진단 파일들.
| 파일 | 내용 |
|---|---|
/proc/cpuinfo | CPU 정보 |
/proc/meminfo | 메모리 전체 통계 |
/proc/slabinfo | kmalloc slab 통계 |
/proc/interrupts | IRQ별 카운터 |
/proc/softirqs | softirq 카운터 |
/proc/loadavg | 1/5/15분 load average |
/proc/stat | 커널 통계 (CPU time, IRQ 카운트 등) |
/proc/vmstat | 가상 메모리 통계 |
/proc/modules | 로드된 모듈 |
/proc/kallsyms | 커널 심볼 테이블 |
/proc/kmsg | 커널 메시지 큐 (dmesg raw source) |
/proc/sys/ | sysctl 인터페이스 |
/proc/[pid]/ | 프로세스별 정보 (Ch에서 다룸) |
/proc/kallsyms이 특히 중요. 커널의 모든 함수·변수 주소가 있어 추적·디버깅의 기반.
$ sudo cat /proc/kallsyms | grep -E "T do_fork$"ffffffff8108c130 T do_fork
$ sudo cat /proc/kallsyms | head -10ffffffff81000000 T startup_64ffffffff81000040 T secondary_startup_64ffffffff8100007e T verify_cpu...각 줄: <주소> <type> <name>. type:
T— Text (function)D— Data (initialized)B— BSSR— read-only datat— local function
sudo로 봐야 실제 주소가 나옴 (보안상 일반 사용자에겐 0으로 마스킹). KASLR 활성이면 부팅마다 주소 다름.
#Kernel 심볼과 debug info
커널 자체도 ELF + DWARF.
$ file /usr/lib/debug/lib/modules/$(uname -r)/vmlinuxvmlinux: ELF 64-bit LSB executable, x86-64, ...
$ readelf -S /usr/lib/debug/lib/modules/$(uname -r)/vmlinux | grep debug[36] .debug_aranges PROGBITS ...[37] .debug_info PROGBITS ...[38] .debug_abbrev PROGBITS ...[39] .debug_line PROGBITS ...배포판 debuginfo 패키지에 vmlinux + debug sections.
# Fedora$ sudo dnf install kernel-debuginfo-$(uname -r)# Ubuntu/Debian$ sudo apt install linux-image-$(uname -r)-dbgvmlinux + kallsyms 조합이 모든 커널 디버깅 도구의 기반. crash, drgn, perf 등이 사용.
#Modules
$ lsmod | head -5Module Size Used bynf_conntrack 172032 4 nf_nat,xt_conntrack,...btrfs 1748992 1xfs 1810432 1...
$ modinfo nf_conntrackfilename: /lib/modules/.../nf_conntrack.ko.xzlicense: GPLdescription: ...depends: nf_defrag_ipv6,nf_defrag_ipv4,...각 모듈도 ELF (.ko) 파일. debug info는 모듈별로.
$ ls /usr/lib/debug/lib/modules/$(uname -r)/kernel/net/netfilter/nf_conntrack.ko.debug ...#Tainted Kernel
$ cat /proc/sys/kernel/tainted00이 아니면 비-vanilla 상태. 비트별 의미.
| 비트 | 문자 | 의미 |
|---|---|---|
| 0 | G/P | proprietary 모듈 로드 |
| 1 | F | force module load |
| 2 | S | SMP 검증 안 됨 |
| 3 | R | force unload |
| 4 | M | MCE 발생 |
| 5 | B | bad page 발견 |
| 6 | U | user-space에서 tainted 설정 |
| 7 | D | die (oops/panic 후) |
| 9 | A | ACPI table 덮어씀 |
| 10 | W | warning 발생 |
| 12 | I | tainted via ad-hoc |
| 13 | C | staging driver 로드 |
| 14 | O | out-of-tree 모듈 |
| 17 | K | kexec |
| 18 | X | proprietary firmware |
$ dmesg | grep -i taint[0.000000] Disabled fast string operations[...] BUG: ... Tainted: G W OE 5.15.0-...Tainted: G W OE = proprietary + warning + out-of-tree. 버그 리포트 시 vanilla 커널에서 재현해야 하는 이유.
#sysrq — Magic SysRq
$ echo 1 | sudo tee /proc/sys/kernel/sysrq # 활성화$ echo b | sudo tee /proc/sysrq-trigger # immediate reboot$ echo s | sudo tee /proc/sysrq-trigger # sync all filesystems$ echo t | sudo tee /proc/sysrq-trigger # dump all task stacks → dmesg$ echo m | sudo tee /proc/sysrq-trigger # dump memory info$ echo w | sudo tee /proc/sysrq-trigger # dump tasks in D state$ echo c | sudo tee /proc/sysrq-trigger # trigger kernel crash → kdump물리적 키보드는 Alt+SysRq+<key>. 시스템 hang 상태에서 유일하게 응답하는 경로. t로 모든 스레드 stack 덤프 → dmesg에서 hang 원인 추적.
#addr2line on vmlinux
크래시 로그의 PC를 함수+줄로.
$ addr2line -e /usr/lib/debug/.../vmlinux 0xffffffff8108c1a0mm/memory.c:1234
$ addr2line -e /usr/lib/debug/.../vmlinux -fi 0xffffffff8108c1a0handle_pte_faultmm/memory.c:1234 (inlined by) handle_mm_faultmm/memory.c:5678user-space addr2line과 같음 — vmlinux를 인자로 줌만 차이.
#kpatch / livepatch
커널 재부팅 없이 패치 적용. 핫픽스 표준 도구.
$ sudo kpatch load /lib/modules/.../my-patch.ko$ kpatch listLoaded patch modules:my-patch디버깅에 직접 쓰는 도구는 아니지만 프로덕션에서 디버그 빌드를 라이브로 swap하는 데 유용.
#자주 만나는 함정
| 증상 | 원인 |
|---|---|
/proc/kallsyms 주소가 모두 0 | /proc/sys/kernel/kptr_restrict=2 (보안 기본). sudo 또는 root로. |
printk 출력 안 보임 | log level이 낮음. dmesg -n 7 또는 /proc/sys/kernel/printk |
| kdump 파일 안 만들어짐 | kdump 서비스 비활성 또는 crashkernel 부팅 옵션 누락 |
| eBPF “Permission denied” | CAP_BPF 또는 root 권한 |
| 모듈 debug info 없음 | 해당 모듈의 -debuginfo 패키지 별도 설치 |
#debuginfo + debuginfod for kernel
debuginfod 시리즈에서 본것처럼 커널 vmlinux도 build-id로 자동 다운로드.
$ export DEBUGINFOD_URLS="https://debuginfod.fedoraproject.org/"$ gdb /usr/lib/debug/.../vmlinux /var/crash/.../vmcore[자동 vmlinux + 모듈 debuginfo 다운로드]대형 SaaS 사업자 (CoreOS, AWS) 환경에서 vmlinux를 어디서나 자동 매칭하는 표준 경로.
#정리
- 커널 디버깅 = user-space와 근본적으로 다름. 단일 컨텍스트, 시스템 영향, attach 불가.
- 5가지 무기: printk, ftrace, eBPF, kgdb, crash/drgn.
- /proc이 표준 상태 인터페이스. /proc/kallsyms이 심볼 진입점.
- vmlinux + DWARF가 debug info의 기반.
- Tainted 커널은 vanilla 재현 필요.
- Magic SysRq는 hang 상태의 유일한 응답 경로.
- addr2line은 같지만 vmlinux를 인자로.
#다음 장 예고
Ch 2 — printk + dmesg + dynamic_debug. 커널 로깅의 모든 것: log level, ratelimit, 동적 활성화.
#관련 항목
- Ch 2: printk / dmesg / dynamic_debug
- DWARF and ELF Internals
- strace / tracing 시리즈 — ftrace/eBPF 사전 학습
- Linux Kernel Documentation — Debugging
man 5 proc— /proc 전체Documentation/admin-guide/sysrq.rst— Magic SysRq
Kernel Debugging · 1 of 9
- 1리눅스 커널 디버깅 개론 — User/Kernel 경계와 도구 선택
- 2printk·dmesg·dynamic_debug 분석 — 커널 로그 추적
- 3ftrace와 tracepoints 활용 — 커널 함수 호출 트레이싱
- 4eBPF·bpftrace로 커널 디버깅 — 동적 관측의 신세대
- 5kdb·kgdb 인터랙티브 커널 디버깅 — Source-level Step·Breakpoint
- 6crash와 drgn 분석 — vmcore에서 커널 상태 복원하기
- 7Kernel Panic·Oops 메시지 해석 — Decoder Ring 만들기
- 8CXL 커널 드라이버 디버깅 — ftrace·bpftrace·drgn 활용
- 9drivers/cxl 코드 분석 — 진입점부터 sysfs까지
관련 글
Kernel Panic·Oops 메시지 해석 — Decoder Ring 만들기
dmesg 한 줄로 정확한 위치 찾기. RIP, Call Trace, BUG, Tainted 디코딩.
crash와 drgn 분석 — vmcore에서 커널 상태 복원하기
kdump로 만든 vmcore를 사후 분석. crash 명령, drgn Python API, 실전 흐름.
kdb·kgdb 인터랙티브 커널 디버깅 — Source-level Step·Breakpoint
별 머신 또는 시리얼로 커널을 step-debug. kgdb 셋업, gdb 연결, 실전 흐름.