요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
============================================
The object-lifetime debugging infrastructure
============================================
:Author: Thomas Gleixner
Introduction
============
debugobjects is a generic infrastructure to track the life time of
kernel objects and validate the operations on those.
debugobjects is useful to check for the following error patterns:
- Activation of uninitialized objects
- Initialization of active objects
- Usage of freed/destroyed objects
debugobjects is not changing the data structure of the real object so it
can be compiled in with a minimal runtime impact and enabled on demand
with a kernel command line option.
Howto use debugobjects
======================
A kernel subsystem needs to provide a data structure which describes the
object type and add calls into the debug code at appropriate places. The
data structure to describe the object type needs at minimum the name of
the object type. Optional functions can and should be provided to fixup
detected problems so the kernel can continue to work and the debug
information can be retrieved from a live system instead of hard core
debugging with serial consoles and stack trace transcripts from the
monitor.
The debug calls provided by debugobjects are:
- debug_object_init
- debug_object_init_on_stack
- debug_object_activate
- debug_object_deactivate
- debug_object_destroy
- debug_object_free
- debug_object_assert_init
Each of these functions takes the address of the real object and a
pointer to the object type specific debug description structure.
Each detected error is reported in the statistics and a limited number
of errors are printk'ed including a full stack trace.
The statistics are available via /sys/kernel/debug/debug_objects/stats.
They provide information about the number of warnings and the number of
successful fixups along with information about the usage of the internal
tracking objects and the state of the internal tracking objects pool.
Debug functions
===============
.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_init
This function is called whenever the initialization function of a real
object is called.
When the real object is already tracked by debugobjects it is checked,
whether the object can be initialized. Initializing is not allowed for
active and destroyed objects. When debugobjects detects an error, then
it calls the fixup_init function of the object type description
structure if provided by the caller. The fixup function can correct the
problem before the real initialization of the object happens. E.g. it
can deactivate an active object in order to prevent damage to the
subsystem.
When the real object is not yet tracked by debugobjects, debugobjects
allocates a tracker object for the real object and sets the tracker
object state to ODEBUG_STATE_INIT. It verifies that the object is not
on the callers stack. If it is on the callers stack then a limited
number of warnings including a full stack trace is printk'ed. The
calling code must use debug_object_init_on_stack() and remove the
object before leaving the function which allocated it. See next section.
.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_init_on_stack
This function is called whenever the initialization function of a real
object which resides on the stack is called.
When the real object is already tracked by debugobjects it is checked,
whether the object can be initialized. Initializing is not allowed for
active and destroyed objects. When debugobjects detects an error, then
it calls the fixup_init function of the object type description
structure if provided by the caller. The fixup function can correct the
problem before the real initialization of the object happens. E.g. it
can deactivate an active object in order to prevent damage to the
subsystem.
When the real object is not yet tracked by debugobjects debugobjects
allocates a tracker object for the real object and sets the tracker
object state to ODEBUG_STATE_INIT. It verifies that the object is on
the callers stack.
An object which is on the stack must be removed from the tracker by
calling debug_object_free() before the function which allocates the
object returns. Otherwise we keep track of stale objects.
.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_activate
This function is called whenever the activation function of a real
object is called.
When the real object is already tracked by debugobjects it is checked,
whether the object can be activated. Activating is not allowed for
active and destroyed objects. When debugobjects detects an error, then
it calls the fixup_activate function of the object type description
structure if provided by the caller. The fixup function can correct the
problem before the real activation of the object happens. E.g. it can
deactivate an active object in order to prevent damage to the subsystem.
When the real object is not yet tracked by debugobjects then the
fixup_activate function is called if available. This is necessary to
allow the legitimate activation of statically allocated and initialized
objects. The fixup function checks whether the object is valid and calls
the debug_objects_init() function to initialize the tracking of this
object.
When the activation is legitimate, then the state of the associated
tracker object is set to ODEBUG_STATE_ACTIVE.
.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_deactivate
This function is called whenever the deactivation function of a real
object is called.
When the real object is tracked by debugobjects it is checked, whether
the object can be deactivated. Deactivating is not allowed for untracked
or destroyed objects.
When the deactivation is legitimate, then the state of the associated
tracker object is set to ODEBUG_STATE_INACTIVE.
.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_destroy
This function is called to mark an object destroyed. This is useful to
prevent the usage of invalid objects, which are still available in
memory: either statically allocated objects or objects which are freed
later.
When the real object is tracked by debugobjects it is checked, whether
the object can be destroyed. Destruction is not allowed for active and
destroyed objects. When debugobjects detects an error, then it calls the
fixup_destroy function of the object type description structure if
provided by the caller. The fixup function can correct the problem
before the real destruction of the object happens. E.g. it can
deactivate an active object in order to prevent damage to the subsystem.
When the destruction is legitimate, then the state of the associated
tracker object is set to ODEBUG_STATE_DESTROYED.
.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_free
This function is called before an object is freed.
When the real object is tracked by debugobjects it is checked, whether
the object can be freed. Free is not allowed for active objects. When
debugobjects detects an error, then it calls the fixup_free function of
the object type description structure if provided by the caller. The
fixup function can correct the problem before the real free of the
object happens. E.g. it can deactivate an active object in order to
prevent damage to the subsystem.
Note that debug_object_free removes the object from the tracker. Later
usage of the object is detected by the other debug checks.
.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_assert_init
This function is called to assert that an object has been initialized.
When the real object is not tracked by debugobjects, it calls
fixup_assert_init of the object type description structure provided by
the caller, with the hardcoded object state ODEBUG_NOT_AVAILABLE. The
fixup function can correct the problem by calling debug_object_init
and other specific initializing functions.
When the real object is already tracked by debugobjects it is ignored.
Fixup functions
===============
Debug object type description structure
---------------------------------------
.. kernel-doc:: include/linux/debugobjects.h
:internal:
fixup_init
-----------
This function is called from the debug code whenever a problem in
debug_object_init is detected. The function takes the address of the
object and the state which is currently recorded in the tracker.
Called from debug_object_init when the object state is:
- ODEBUG_STATE_ACTIVE
The function returns true when the fixup was successful, otherwise
false. The return value is used to update the statistics.
Note, that the function needs to call the debug_object_init() function
again, after the damage has been repaired in order to keep the state
consistent.
fixup_activate
---------------
This function is called from the debug code whenever a problem in
debug_object_activate is detected.
Called from debug_object_activate when the object state is:
- ODEBUG_STATE_NOTAVAILABLE
- ODEBUG_STATE_ACTIVE
The function returns true when the fixup was successful, otherwise
false. The return value is used to update the statistics.
Note that the function needs to call the debug_object_activate()
function again after the damage has been repaired in order to keep the
state consistent.
The activation of statically initialized objects is a special case. When
debug_object_activate() has no tracked object for this object address
then fixup_activate() is called with object state
ODEBUG_STATE_NOTAVAILABLE. The fixup function needs to check whether
this is a legitimate case of a statically initialized object or not. In
case it is it calls debug_object_init() and debug_object_activate()
to make the object known to the tracker and marked active. In this case
the function should return false because this is not a real fixup.
fixup_destroy
--------------
This function is called from the debug code whenever a problem in
debug_object_destroy is detected.
Called from debug_object_destroy when the object state is:
- ODEBUG_STATE_ACTIVE
The function returns true when the fixup was successful, otherwise
false. The return value is used to update the statistics.
fixup_free
-----------
This function is called from the debug code whenever a problem in
debug_object_free is detected. Further it can be called from the debug
checks in kfree/vfree, when an active object is detected from the
debug_check_no_obj_freed() sanity checks.
Called from debug_object_free() or debug_check_no_obj_freed() when
the object state is:
- ODEBUG_STATE_ACTIVE
The function returns true when the fixup was successful, otherwise
false. The return value is used to update the statistics.
fixup_assert_init
-------------------
This function is called from the debug code whenever a problem in
debug_object_assert_init is detected.
Called from debug_object_assert_init() with a hardcoded state
ODEBUG_STATE_NOTAVAILABLE when the object is not found in the debug
bucket.
The function returns true when the fixup was successful, otherwise
false. The return value is used to update the statistics.
Note, this function should make sure debug_object_init() is called
before returning.
The handling of statically initialized objects is a special case. The
fixup function should check if this is a legitimate case of a statically
initialized object or not. In this case only debug_object_init()
should be called to make the object known to the tracker. Then the
function should return false because this is not a real fixup.
Known Bugs And Assumptions
==========================
None (knock on wood).
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Object-lifetime debugging infrastructure
1-24저자는 Thomas Gleixner입니다.
`debugobjects`는 kernel object의 lifetime을 추적하고 그 object에 대한 operation이 유효한지 검사하는 generic infrastructure입니다.
다음 error pattern을 검사하는 데 유용합니다.
- 초기화되지 않은 object의 activation
- Active object의 initialization
- Free 또는 destroy된 object의 사용
`debugobjects`는 실제 object의 data structure를 변경하지 않습니다. 따라서 runtime impact를 최소화한 채 compile할 수 있고 kernel command-line option으로 필요할 때 enable할 수 있습니다.
debugobjects 사용 방법
25-63Kernel subsystem은 object type을 설명하는 data structure를 제공하고 적절한 위치에서 debug code를 호출해야 합니다. Type description에는 최소한 object type name이 필요합니다.
발견한 문제를 fixup하는 optional function도 제공하는 것이 좋습니다. 그러면 kernel이 계속 동작하며, serial console과 monitor의 stack trace transcript에 의존하는 hard-core debugging 대신 live system에서 debug 정보를 가져올 수 있습니다.
제공되는 debug call은 다음과 같습니다.
- debug_object_init
- debug_object_init_on_stack
- debug_object_activate
- debug_object_deactivate
- debug_object_destroy
- debug_object_free
- debug_object_assert_init
각 function은 실제 object의 address와 object type별 debug description structure pointer를 받습니다.
발견된 모든 error는 statistics에 기록되며, 제한된 수의 error는 full stack trace와 함께 `printk`로 출력됩니다.
Statistics는 `/sys/kernel/debug/debug_objects/stats`에서 확인할 수 있습니다. Warning 수와 성공한 fixup 수뿐 아니라 internal tracking object 사용량과 tracking object pool 상태도 제공합니다.
debug_object_init
64-89.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_init
실제 object의 initialization function이 호출될 때마다 `debug_object_init()`을 호출합니다.
Object를 이미 추적 중이면 초기화 가능한지 검사합니다. Active 또는 destroyed object는 초기화할 수 없습니다. Error를 발견하면 caller가 제공한 type description의 `fixup_init`을 호출합니다. Fixup은 실제 initialization 전에 active object를 deactivate하는 식으로 subsystem 손상을 막을 수 있습니다.
아직 추적하지 않는 object라면 tracker object를 할당하고 state를 `ODEBUG_STATE_INIT`으로 설정합니다. 또한 caller stack에 있지 않은지 검사합니다.
Object가 caller stack에 있으면 제한된 수의 warning을 full stack trace와 함께 출력합니다. 이런 object는 `debug_object_init_on_stack()`을 사용하고, object를 할당한 function을 떠나기 전에 tracker에서 제거해야 합니다.
debug_object_init_on_stack
90-113.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_init_on_stack
Stack에 존재하는 실제 object의 initialization function이 호출될 때 `debug_object_init_on_stack()`을 호출합니다.
이미 추적 중이면 초기화 가능 여부를 검사하며 active 및 destroyed object는 허용하지 않습니다. Error가 있으면 제공된 `fixup_init`이 실제 initialization 전에 문제를 고칠 수 있습니다.
아직 추적하지 않으면 tracker를 할당하고 `ODEBUG_STATE_INIT`으로 설정한 뒤 object가 caller stack에 있는지 확인합니다.
Stack object는 이를 할당한 function이 return하기 전에 `debug_object_free()`를 호출하여 tracker에서 제거해야 합니다. 그렇지 않으면 stale object를 계속 추적하게 됩니다.
debug_object_activate
114-138.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_activate
실제 object의 activation function이 호출될 때마다 `debug_object_activate()`를 호출합니다.
이미 추적 중이면 activate 가능한지 검사합니다. Active 또는 destroyed object는 activate할 수 없습니다. Error가 있으면 제공된 `fixup_activate`가 실제 activation 전에 active object를 deactivate하는 등의 방식으로 문제를 고칠 수 있습니다.
아직 추적하지 않는 object에도 `fixup_activate`가 있으면 호출합니다. 이는 statically allocated 및 initialized object의 합법적인 activation을 허용하기 위해 필요합니다. Fixup은 object의 유효성을 검사하고 `debug_objects_init()`을 호출해 tracking을 초기화합니다.
Activation이 유효하면 연결된 tracker object state를 `ODEBUG_STATE_ACTIVE`로 설정합니다.
debug_object_deactivate
139-151.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_deactivate
실제 object의 deactivation function이 호출될 때마다 `debug_object_deactivate()`를 호출합니다.
추적 중인 object가 deactivate 가능한지 검사하며, untracked 또는 destroyed object의 deactivation은 허용하지 않습니다. 유효하면 tracker state를 `ODEBUG_STATE_INACTIVE`로 설정합니다.
debug_object_destroy
152-170.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_destroy
`debug_object_destroy()`는 object를 destroyed 상태로 표시합니다. 이는 statically allocated object나 나중에 free할 object처럼 memory에 아직 남아 있지만 유효하지 않은 object의 사용을 막는 데 유용합니다.
추적 중이면 destroy 가능한지 검사합니다. Active 또는 이미 destroyed인 object는 허용하지 않습니다. Error가 있으면 제공된 `fixup_destroy`가 실제 destruction 전에 active object를 deactivate하는 등의 방식으로 문제를 고칠 수 있습니다.
Destruction이 유효하면 tracker state를 `ODEBUG_STATE_DESTROYED`로 설정합니다.
debug_object_free
171-187.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_free
Object를 free하기 전에 `debug_object_free()`를 호출합니다.
추적 중인 object가 free 가능한지 검사하며 active object의 free는 허용하지 않습니다. Error가 있으면 제공된 `fixup_free`가 실제 free 전에 active object를 deactivate하는 등의 방식으로 문제를 고칠 수 있습니다.
`debug_object_free()`는 tracker에서 object를 제거합니다. 나중에 이 object를 다시 사용하면 다른 debug check가 이를 감지합니다.
debug_object_assert_init
188-200.. kernel-doc:: lib/debugobjects.c
:functions: debug_object_assert_init
Object가 initialized 상태임을 assert하기 위해 `debug_object_assert_init()`을 호출합니다.
실제 object를 추적하지 않으면 caller가 제공한 type description의 `fixup_assert_init`을 hardcoded state `ODEBUG_NOT_AVAILABLE`과 함께 호출합니다. Fixup은 `debug_object_init()`과 type-specific initialization function을 호출하여 문제를 고칠 수 있습니다.
이미 추적 중인 object는 무시합니다.
Fixup function과 type description
201-209Fixup callback이 들어 있는 debug object type description structure의 internal kernel-doc는 `include/linux/debugobjects.h`에서 가져옵니다.
.. kernel-doc:: include/linux/debugobjects.h
:internal:
fixup_init
210-227`debug_object_init`에서 문제를 발견하면 debug code가 `fixup_init`을 호출합니다. Function은 object address와 tracker에 현재 기록된 state를 받습니다.
다음 state에서 호출됩니다.
- ODEBUG_STATE_ACTIVE
Fixup에 성공하면 true, 아니면 false를 반환하며 이 값으로 statistics를 갱신합니다.
손상을 고친 뒤 state consistency를 유지하려면 `debug_object_init()`을 다시 호출해야 합니다.
fixup_activate
228-255`debug_object_activate`에서 문제를 발견하면 debug code가 `fixup_activate`를 호출합니다.
다음 state에서 호출됩니다.
- ODEBUG_STATE_NOTAVAILABLE
- ODEBUG_STATE_ACTIVE
Fixup에 성공하면 true, 아니면 false를 반환하여 statistics를 갱신합니다. 손상을 고친 뒤 consistency를 위해 `debug_object_activate()`를 다시 호출해야 합니다.
Statically initialized object의 activation은 특별한 경우입니다. 해당 address의 tracked object가 없으면 `ODEBUG_STATE_NOTAVAILABLE`로 `fixup_activate()`를 호출합니다.
Fixup은 합법적인 static initialization인지 확인하고, 맞다면 `debug_object_init()`과 `debug_object_activate()`를 호출해 tracker에 등록하고 active로 표시합니다. 이는 실제 fixup이 아니므로 false를 반환해야 합니다.
fixup_destroy
256-268`debug_object_destroy`에서 문제를 발견하면 debug code가 `fixup_destroy`를 호출합니다.
다음 state에서 호출됩니다.
- ODEBUG_STATE_ACTIVE
Fixup에 성공하면 true, 아니면 false를 반환하며 이 값으로 statistics를 갱신합니다.
fixup_free
269-284`debug_object_free`에서 문제를 발견하면 `fixup_free`를 호출합니다. `kfree`/`vfree`의 `debug_check_no_obj_freed()` sanity check가 active object를 발견했을 때도 호출할 수 있습니다.
다음 state에서 호출됩니다.
- ODEBUG_STATE_ACTIVE
Fixup에 성공하면 true, 아니면 false를 반환하며 이 값으로 statistics를 갱신합니다.
fixup_assert_init
285-306`debug_object_assert_init`에서 문제를 발견하면 debug code가 `fixup_assert_init`을 호출합니다.
Object를 debug bucket에서 찾지 못한 경우 hardcoded state `ODEBUG_STATE_NOTAVAILABLE`과 함께 호출합니다. 성공하면 true, 아니면 false를 반환하여 statistics를 갱신합니다.
Return 전에 `debug_object_init()`이 호출되도록 보장해야 합니다.
Statically initialized object는 특별한 경우입니다. 합법적인 static initialization인지 검사하고, 맞다면 `debug_object_init()`만 호출해 tracker에 알립니다. 실제 fixup이 아니므로 false를 반환해야 합니다.
Known Bugs And Assumptions
307-310알려진 bug나 별도의 assumption은 없습니다. 원문 표현으로는 "knock on wood"입니다.
요약과 해설
debug-objects.rst:1-310Debugobjects는 실제 object layout을 바꾸지 않고 별도 tracker에 INIT, ACTIVE, INACTIVE, DESTROYED state를 기록하여 잘못된 lifetime operation을 감지합니다.
Subsystem은 각 lifecycle operation 지점에서 대응하는 debug_object_* API를 호출하고, type description에 fixup callback을 제공하여 error를 보고하면서도 system이 계속 동작하도록 복구할 수 있습니다.
Stack object는 전용 initialization API를 사용하고 function return 전에 tracker에서 제거해야 하며, statically initialized object는 NOTAVAILABLE state를 정상 사례로 판별하는 특별한 fixup 경로가 필요합니다.