← Documents Documentation/process/debugging/driver_development_debugging_guide.rst GitHub 원문 ↗

Linux 6.18.37 · Debugging

Driver 개발 중 kernel debugging

printk와 dev_dbg, trace_printk·ftrace tracepoint, debugfs, KASAN·UBSAN·lockdep, PSI와 devcoredump 사용 범위를 설명합니다.

Source pathDocumentation/process/debugging/driver_development_debugging_guide.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

printk, dev_dbg와 임시 log

driver_development_debugging_guide.rst:4-100

가장 빠른 확인은 pr_* 또는 device context가 붙는 dev_* message다. 정상 path의 반복 message는 timing과 log volume을 바꾸므로 level과 rate limit을 선택한다. dev_dbg는 dynamic debug와 결합해 build를 바꾸지 않고 file·function별로 enable할 수 있다.

trace_printk는 ftrace ring buffer에 기록해 printk console보다 교란이 작지만 production code에 남길 interface가 아니다. Custom debug macro를 만들기 전에 dev_dbg, pr_debug와 dynamic_debug가 요구를 충족하는지 확인한다.

재사용 가능한 custom tracepoint

driver_development_debugging_guide.rst:101-118

빈도가 높거나 state correlation이 필요한 path는 TRACE_EVENT 기반 tracepoint로 field를 구조화한다. Tracepoint는 enable되지 않았을 때 overhead를 최소화하고 perf, trace-cmd와 BPF consumer가 같은 event를 사용할 수 있다.

DebugFS state 노출

driver_development_debugging_guide.rst:119-161

Debugfs는 driver 내부 state와 실험 control을 개발자에게 노출할 수 있지만 stable userspace ABI가 아니다. Production application dependency를 만들지 않고 lifetime과 removal을 device unbind 경로에 맞춘다. Sensitive register와 kernel address를 무분별하게 노출하지 않는다.

KASAN, UBSAN과 lockdep

driver_development_debugging_guide.rst:162-206
도구찾는 문제
KASANOut-of-bounds, use-after-free와 잘못된 memory access
UBSANC undefined behavior, overflow와 잘못된 shift·type operation
lockdepLock ordering cycle, recursive acquire와 잘못된 context 사용
PSICPU, memory와 I/O pressure 때문에 task가 실제로 stall된 시간

Sanitizer와 lockdep는 report 첫 fault에서 stack과 allocation·lock history를 읽고 후속 cascade message보다 최초 원인을 우선한다. Instrumentation이 memory와 timing을 바꾸므로 reproduction 차이도 기록한다.

Device firmware coredump

driver_development_debugging_guide.rst:207-236

Device가 firmware crash state나 on-device memory를 제공할 수 있으면 devcoredump interface로 userspace가 binary dump를 회수하게 한다. Buffer ownership은 devcoredump API로 넘긴 뒤 driver가 다시 free하지 않으며 timeout·read 완료 때 release callback이 처리한다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 ========================================
4 Debugging advice for driver development
5 ========================================
6
7 This document serves as a general starting point and lookup for debugging
8 device drivers.
9 While this guide focuses on debugging that requires re-compiling the
10 module/kernel, the :doc:`userspace debugging guide
11 </process/debugging/userspace_debugging_guide>` will guide
12 you through tools like dynamic debug, ftrace and other tools useful for
13 debugging issues and behavior.
14 For general debugging advice, see the :doc:`general advice document
15 </process/debugging/index>`.
16
17 .. contents::
18 :depth: 3
19
20 The following sections show you the available tools.
21
22 printk() & friends
23 ------------------
24
25 These are derivatives of printf() with varying destinations and support for
26 being dynamically turned on or off, or lack thereof.
27
28 Simple printk()
29 ~~~~~~~~~~~~~~~
30
31 The classic, can be used to great effect for quick and dirty development
32 of new modules or to extract arbitrary necessary data for troubleshooting.
33
34 Prerequisite: ``CONFIG_PRINTK`` (usually enabled by default)
35
36 **Pros**:
37
38 - No need to learn anything, simple to use
39 - Easy to modify exactly to your needs (formatting of the data (See:
40 :doc:`/core-api/printk-formats`), visibility in the log)
41 - Can cause delays in the execution of the code (beneficial to confirm whether
42 timing is a factor)
43
44 **Cons**:
45
46 - Requires rebuilding the kernel/module
47 - Can cause delays in the execution of the code (which can cause issues to be
48 not reproducible)
49
50 For the full documentation see :doc:`/core-api/printk-basics`
51
52 Trace_printk
53 ~~~~~~~~~~~~
54
55 Prerequisite: ``CONFIG_DYNAMIC_FTRACE`` & ``#include <linux/ftrace.h>``
56
57 It is a tiny bit less comfortable to use than printk(), because you will have
58 to read the messages from the trace file (See: :ref:`read_ftrace_log`
59 instead of from the kernel log, but very useful when printk() adds unwanted
60 delays into the code execution, causing issues to be flaky or hidden.)
61
62 If the processing of this still causes timing issues then you can try
63 trace_puts().
64
65 For the full Documentation see trace_printk()
66
67 dev_dbg
68 ~~~~~~~
69
70 Print statement, which can be targeted by
71 :ref:`process/debugging/userspace_debugging_guide:dynamic debug` that contains
72 additional information about the device used within the context.
73
74 **When is it appropriate to leave a debug print in the code?**
75
76 Permanent debug statements have to be useful for a developer to troubleshoot
77 driver misbehavior. Judging that is a bit more of an art than a science, but
78 some guidelines are in the :ref:`Coding style guidelines
79 <process/coding-style:13) printing kernel messages>`. In almost all cases the
80 debug statements shouldn't be upstreamed, as a working driver is supposed to be
81 silent.
82
83 Custom printk
84 ~~~~~~~~~~~~~
85
86 Example::
87
88 #define core_dbg(fmt, arg...) do { \
89 if (core_debug) \
90 printk(KERN_DEBUG pr_fmt("core: " fmt), ## arg); \
91 } while (0)
92
93 **When should you do this?**
94
95 It is better to just use a pr_debug(), which can later be turned on/off with
96 dynamic debug. Additionally, a lot of drivers activate these prints via a
97 variable like ``core_debug`` set by a module parameter. However, Module
98 parameters `are not recommended anymore
99 <https://lore.kernel.org/all/2024032757-surcharge-grime-d3dd@gregkh>`_.
100
101 Ftrace
102 ------
103
104 Creating a custom Ftrace tracepoint
105 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106
107 A tracepoint adds a hook into your code that will be called and logged when the
108 tracepoint is enabled. This can be used, for example, to trace hitting a
109 conditional branch or to dump the internal state at specific points of the code
110 flow during a debugging session.
111
112 Here is a basic description of :ref:`how to implement new tracepoints
113 <trace/tracepoints:usage>`.
114
115 For the full event tracing documentation see :doc:`/trace/events`
116
117 For the full Ftrace documentation see :doc:`/trace/ftrace`
118
119 DebugFS
120 -------
121
122 Prerequisite: ``CONFIG_DEBUG_FS` & `#include <linux/debugfs.h>``
123
124 DebugFS differs from the other approaches of debugging, as it doesn't write
125 messages to the kernel log nor add traces to the code. Instead it allows the
126 developer to handle a set of files.
127 With these files you can either store values of variables or make
128 register/memory dumps or you can make these files writable and modify
129 values/settings in the driver.
130
131 Possible use-cases among others:
132
133 - Store register values
134 - Keep track of variables
135 - Store errors
136 - Store settings
137 - Toggle a setting like debug on/off
138 - Error injection
139
140 This is especially useful, when the size of a data dump would be hard to digest
141 as part of the general kernel log (for example when dumping raw bitstream data)
142 or when you are not interested in all the values all the time, but with the
143 possibility to inspect them.
144
145 The general idea is:
146
147 - Create a directory during probe (``struct dentry *parent =
148 debugfs_create_dir("my_driver", NULL);``)
149 - Create a file (``debugfs_create_u32("my_value", 444, parent, &my_variable);``)
150
151 - In this example the file is found in
152 ``/sys/kernel/debug/my_driver/my_value`` (with read permissions for
153 user/group/all)
154 - any read of the file will return the current contents of the variable
155 ``my_variable``
156
157 - Clean up the directory when removing the device
158 (``debugfs_remove(parent);``)
159
160 For the full documentation see :doc:`/filesystems/debugfs`.
161
162 KASAN, UBSAN, lockdep and other error checkers
163 ----------------------------------------------
164
165 KASAN (Kernel Address Sanitizer)
166 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
167
168 Prerequisite: ``CONFIG_KASAN``
169
170 KASAN is a dynamic memory error detector that helps to find use-after-free and
171 out-of-bounds bugs. It uses compile-time instrumentation to check every memory
172 access.
173
174 For the full documentation see :doc:`/dev-tools/kasan`.
175
176 UBSAN (Undefined Behavior Sanitizer)
177 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
178
179 Prerequisite: ``CONFIG_UBSAN``
180
181 UBSAN relies on compiler instrumentation and runtime checks to detect undefined
182 behavior. It is designed to find a variety of issues, including signed integer
183 overflow, array index out of bounds, and more.
184
185 For the full documentation see :doc:`/dev-tools/ubsan`
186
187 lockdep (Lock Dependency Validator)
188 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
189
190 Prerequisite: ``CONFIG_DEBUG_LOCKDEP``
191
192 lockdep is a runtime lock dependency validator that detects potential deadlocks
193 and other locking-related issues in the kernel.
194 It tracks lock acquisitions and releases, building a dependency graph that is
195 analyzed for potential deadlocks.
196 lockdep is especially useful for validating the correctness of lock ordering in
197 the kernel.
198
199 PSI (Pressure stall information tracking)
200 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
201
202 Prerequisite: ``CONFIG_PSI``
203
204 PSI is a measurement tool to identify excessive overcommits on hardware
205 resources, that can cause performance disruptions or even OOM kills.
206
207 device coredump
208 ---------------
209
210 Prerequisite: ``CONFIG_DEV_COREDUMP`` & ``#include <linux/devcoredump.h>``
211
212 Provides the infrastructure for a driver to provide arbitrary data to userland.
213 It is most often used in conjunction with udev or similar userland application
214 to listen for kernel uevents, which indicate that the dump is ready. Udev has
215 rules to copy that file somewhere for long-term storage and analysis, as by
216 default, the data for the dump is automatically cleaned up after a default
217 5 minutes. That data is analyzed with driver-specific tools or GDB.
218
219 A device coredump can be created with a vmalloc area, with read/free
220 methods, or as a scatter/gather list.
221
222 You can find an example implementation at:
223 `drivers/media/platform/qcom/venus/core.c
224 <https://elixir.bootlin.com/linux/v6.11.6/source/drivers/media/platform/qcom/venus/core.c#L30>`__,
225 in the Bluetooth HCI layer, in several wireless drivers, and in several
226 DRM drivers.
227
228 devcoredump interfaces
229 ~~~~~~~~~~~~~~~~~~~~~~
230
231 .. kernel-doc:: include/linux/devcoredump.h
232
233 .. kernel-doc:: drivers/base/devcoredump.c
234
235 **Copyright** ©2024 : Collabora
236

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Driver debugging 도구의 범위

1-20

이 문서는 device driver debugging의 일반 출발점이다. Module 또는 kernel rebuild가 필요한 기법을 중심으로 하고 dynamic debug, ftrace 같은 runtime 도구는 userspace debugging guide를 참고한다. 일반 원칙은 Documentation/process/debugging/index.rst에 있다.

printk()의 장점과 timing 부작용

22-50

CONFIG_PRINTK가 필요하며 보통 기본 enable이다. 새 module을 빠르게 개발하거나 troubleshooting에 필요한 임의 data를 뽑을 때 가장 단순한 방법이다.

장점단점
배울 내용이 거의 없고 사용이 단순하다.Kernel 또는 module을 다시 build해야 한다.
Format과 log visibility를 필요에 맞게 쉽게 바꿀 수 있다.실행을 지연시켜 timing-dependent bug가 재현되지 않을 수 있다.
의도적으로 실행을 지연시켜 timing이 원인인지 확인할 수 있다.관찰 자체가 system 동작을 바꾸는 probe effect가 생긴다.

Format은 core-api/printk-formats, 전체 사용법은 core-api/printk-basics를 참고한다.

trace_printk()와 trace_puts()

52-65

CONFIG_DYNAMIC_FTRACE와 linux/ftrace.h가 필요하다. Kernel log가 아니라 trace file에서 읽어야 해 printk()보다 조금 불편하지만 printk()의 지연이 문제를 숨기거나 불안정하게 만들 때 유용하다. 처리 비용도 timing을 바꾼다면 trace_puts()를 시도한다.

dev_dbg()와 permanent debug print

67-81

dev_dbg()는 관련 device 정보를 포함하고 dynamic debug로 call site를 선택할 수 있다. Upstream에 남길 permanent debug statement는 앞으로 driver 오동작을 조사하는 데 실제로 유용해야 한다.

판단은 완전한 규칙보다 경험이 필요하지만 coding style의 kernel message 지침을 따른다. 정상 동작하는 driver는 조용해야 하므로 거의 모든 임시 debug statement는 upstream에 포함하지 않는다.

Custom printk macro보다 pr_debug()

83-99
#define core_dbg(fmt, arg...) do { \
    if (core_debug) \
        printk(KERN_DEBUG pr_fmt("core: " fmt), ## arg); \
} while (0)

이런 custom macro보다 dynamic debug로 runtime on/off할 수 있는 pr_debug()가 낫다. core_debug 같은 module parameter로 print를 제어하는 driver도 많지만 새 module parameter는 더 이상 권장되지 않는다.

Custom ftrace tracepoint

101-117

Tracepoint는 enable되었을 때 호출되고 기록되는 hook을 code에 추가한다. Conditional branch 도달이나 debug session 중 특정 code-flow 지점의 internal state를 추적할 수 있다. 구현법은 trace/tracepoints, event tracing은 trace/events, 전체 ftrace는 trace/ftrace 문서를 참고한다.

DebugFS로 값과 dump 노출

119-160

CONFIG_DEBUG_FS와 linux/debugfs.h가 필요하다. DebugFS는 kernel log나 trace 대신 file을 통해 driver state를 다룬다. Register와 memory dump, variable, error, setting을 저장하고 writable file로 설정을 바꾸거나 error를 injection할 수 있다.

Raw bitstream처럼 kernel log에 넣기 큰 dump나 항상 보지 않아도 되지만 필요할 때 확인할 값에 특히 유용하다.

struct dentry *parent = debugfs_create_dir("my_driver", NULL);
debugfs_create_u32("my_value", 0444, parent, &my_variable);
/* /sys/kernel/debug/my_driver/my_value */
...
debugfs_remove(parent);

Probe에서 directory와 file을 만들고 file read가 current my_variable 값을 반환하게 한다. Device 제거 때 directory를 정리한다. 전체 API는 filesystems/debugfs 문서를 참고한다.

KASAN, UBSAN, lockdep, PSI

162-205
도구Configuration검출 대상
KASANCONFIG_KASANCompile-time instrumentation으로 모든 memory access를 검사해 use-after-free와 out-of-bounds를 찾는다.
UBSANCONFIG_UBSANCompiler instrumentation과 runtime check로 signed overflow, array index out-of-bounds 등 undefined behavior를 찾는다.
lockdepCONFIG_DEBUG_LOCKDEPLock acquire/release dependency graph를 만들고 potential deadlock과 lock ordering 문제를 찾는다.
PSICONFIG_PSIHardware resource overcommit으로 생기는 performance stall과 OOM kill 위험을 측정한다.

Device coredump

207-235

CONFIG_DEV_COREDUMP와 linux/devcoredump.h가 필요하다. Driver가 arbitrary data를 userspace에 전달하는 infrastructure다. Udev 같은 application이 dump 준비를 알리는 kernel uevent를 듣고 file을 장기 저장 위치로 복사한다.

기본 설정에서는 dump data가 5분 뒤 자동 삭제되므로 userspace 수집이 필요하다. 저장한 data는 driver 전용 tool이나 GDB로 분석한다. Vmalloc area, read/free method, scatter/gather list 형태로 coredump를 만들 수 있다.

구현 예는 drivers/media/platform/qcom/venus/core.c, Bluetooth HCI layer, 여러 wireless와 DRM driver에 있다. Interface kernel-doc은 include/linux/devcoredump.h와 drivers/base/devcoredump.c에서 가져온다. 원문 copyright는 ©2024 Collabora다.