| ============================================ | |
| 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). |