The object-lifetime debugging infrastructure¶
- Author:
Thomas Gleixner
Introduction¶
debugobjects is a generic infrastructure to track the life time ofkernel 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 itcan be compiled in with a minimal runtime impact and enabled on demandwith a kernel command line option.
Howto use debugobjects¶
A kernel subsystem needs to provide a data structure which describes theobject type and add calls into the debug code at appropriate places. Thedata structure to describe the object type needs at minimum the name ofthe object type. Optional functions can and should be provided to fixupdetected problems so the kernel can continue to work and the debuginformation can be retrieved from a live system instead of hard coredebugging with serial consoles and stack trace transcripts from themonitor.
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 apointer to the object type specific debug description structure.
Each detected error is reported in the statistics and a limited numberof 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 ofsuccessful fixups along with information about the usage of the internaltracking objects and the state of the internal tracking objects pool.
Debug functions¶
- voiddebug_object_init(void*addr,conststructdebug_obj_descr*descr)¶
debug checks when an object is initialized
Parameters
void*addraddress of the object
conststructdebug_obj_descr*descrpointer to an object specific debug description structure
This function is called whenever the initialization function of a realobject is called.
When the real object is already tracked by debugobjects it is checked,whether the object can be initialized. Initializing is not allowed foractive and destroyed objects. When debugobjects detects an error, thenit calls the fixup_init function of the object type descriptionstructure if provided by the caller. The fixup function can correct theproblem before the real initialization of the object happens. E.g. itcan deactivate an active object in order to prevent damage to thesubsystem.
When the real object is not yet tracked by debugobjects, debugobjectsallocates a tracker object for the real object and sets the trackerobject state to ODEBUG_STATE_INIT. It verifies that the object is noton the callers stack. If it is on the callers stack then a limitednumber of warnings including a full stack trace is printk’ed. Thecalling code must usedebug_object_init_on_stack() and remove theobject before leaving the function which allocated it. See next section.
- voiddebug_object_init_on_stack(void*addr,conststructdebug_obj_descr*descr)¶
debug checks when an object on stack is initialized
Parameters
void*addraddress of the object
conststructdebug_obj_descr*descrpointer to an object specific debug description structure
This function is called whenever the initialization function of a realobject 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 foractive and destroyed objects. When debugobjects detects an error, thenit calls the fixup_init function of the object type descriptionstructure if provided by the caller. The fixup function can correct theproblem before the real initialization of the object happens. E.g. itcan deactivate an active object in order to prevent damage to thesubsystem.
When the real object is not yet tracked by debugobjects debugobjectsallocates a tracker object for the real object and sets the trackerobject state to ODEBUG_STATE_INIT. It verifies that the object is onthe callers stack.
An object which is on the stack must be removed from the tracker bycallingdebug_object_free() before the function which allocates theobject returns. Otherwise we keep track of stale objects.
- intdebug_object_activate(void*addr,conststructdebug_obj_descr*descr)¶
debug checks when an object is activated
Parameters
void*addraddress of the object
conststructdebug_obj_descr*descrpointer to an object specific debug description structureReturns 0 for success, -EINVAL for check failed.
This function is called whenever the activation function of a realobject is called.
When the real object is already tracked by debugobjects it is checked,whether the object can be activated. Activating is not allowed foractive and destroyed objects. When debugobjects detects an error, thenit calls the fixup_activate function of the object type descriptionstructure if provided by the caller. The fixup function can correct theproblem before the real activation of the object happens. E.g. it candeactivate an active object in order to prevent damage to the subsystem.
When the real object is not yet tracked by debugobjects then thefixup_activate function is called if available. This is necessary toallow the legitimate activation of statically allocated and initializedobjects. The fixup function checks whether the object is valid and callsthedebug_objects_init() function to initialize the tracking of thisobject.
When the activation is legitimate, then the state of the associatedtracker object is set to ODEBUG_STATE_ACTIVE.
- voiddebug_object_deactivate(void*addr,conststructdebug_obj_descr*descr)¶
debug checks when an object is deactivated
Parameters
void*addraddress of the object
conststructdebug_obj_descr*descrpointer to an object specific debug description structure
This function is called whenever the deactivation function of a realobject is called.
When the real object is tracked by debugobjects it is checked, whetherthe object can be deactivated. Deactivating is not allowed for untrackedor destroyed objects.
When the deactivation is legitimate, then the state of the associatedtracker object is set to ODEBUG_STATE_INACTIVE.
- voiddebug_object_destroy(void*addr,conststructdebug_obj_descr*descr)¶
debug checks when an object is destroyed
Parameters
void*addraddress of the object
conststructdebug_obj_descr*descrpointer to an object specific debug description structure
This function is called to mark an object destroyed. This is useful toprevent the usage of invalid objects, which are still available inmemory: either statically allocated objects or objects which are freedlater.
When the real object is tracked by debugobjects it is checked, whetherthe object can be destroyed. Destruction is not allowed for active anddestroyed objects. When debugobjects detects an error, then it calls thefixup_destroy function of the object type description structure ifprovided by the caller. The fixup function can correct the problembefore the real destruction of the object happens. E.g. it candeactivate an active object in order to prevent damage to the subsystem.
When the destruction is legitimate, then the state of the associatedtracker object is set to ODEBUG_STATE_DESTROYED.
- voiddebug_object_free(void*addr,conststructdebug_obj_descr*descr)¶
debug checks when an object is freed
Parameters
void*addraddress of the object
conststructdebug_obj_descr*descrpointer to an object specific debug description structure
This function is called before an object is freed.
When the real object is tracked by debugobjects it is checked, whetherthe object can be freed. Free is not allowed for active objects. Whendebugobjects detects an error, then it calls the fixup_free function ofthe object type description structure if provided by the caller. Thefixup function can correct the problem before the real free of theobject happens. E.g. it can deactivate an active object in order toprevent damage to the subsystem.
Note that debug_object_free removes the object from the tracker. Laterusage of the object is detected by the other debug checks.
- voiddebug_object_assert_init(void*addr,conststructdebug_obj_descr*descr)¶
debug checks when object should be init-ed
Parameters
void*addraddress of the object
conststructdebug_obj_descr*descrpointer to an object specific debug description structure
This function is called to assert that an object has been initialized.
When the real object is not tracked by debugobjects, it callsfixup_assert_init of the object type description structure provided bythe caller, with the hardcoded object state ODEBUG_NOT_AVAILABLE. Thefixup function can correct the problem by calling debug_object_initand other specific initializing functions.
When the real object is already tracked by debugobjects it is ignored.
Fixup functions¶
Debug object type description structure¶
- structdebug_obj¶
representation of an tracked object
Definition:
struct debug_obj { struct hlist_node node; enum debug_obj_state state; unsigned int astate; union { void *object; struct hlist_node *batch_last; }; const struct debug_obj_descr *descr;};Members
nodehlist node to link the object into the tracker list
statetracked object state
astatecurrent active state
{unnamed_union}anonymous
objectpointer to the real object
batch_lastpointer to the last hlist node in a batch
descrpointer to an object type specific debug description structure
- structdebug_obj_descr¶
object type specific debug description structure
Definition:
struct debug_obj_descr { const char *name; void *(*debug_hint)(void *addr); bool (*is_static_object)(void *addr); bool (*fixup_init)(void *addr, enum debug_obj_state state); bool (*fixup_activate)(void *addr, enum debug_obj_state state); bool (*fixup_destroy)(void *addr, enum debug_obj_state state); bool (*fixup_free)(void *addr, enum debug_obj_state state); bool (*fixup_assert_init)(void *addr, enum debug_obj_state state);};Members
namename of the object typee
debug_hintfunction returning address, which have associatedkernel symbol, to allow identify the object
is_static_objectreturn true if the obj is static, otherwise return false
fixup_initfixup function, which is called when the init checkfails. All fixup functions must return true if fixupwas successful, otherwise return false
fixup_activatefixup function, which is called when the activate checkfails
fixup_destroyfixup function, which is called when the destroy checkfails
fixup_freefixup function, which is called when the free checkfails
fixup_assert_initfixup function, which is called when the assert_initcheck fails
fixup_init¶
This function is called from the debug code whenever a problem indebug_object_init is detected. The function takes the address of theobject 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, otherwisefalse. The return value is used to update the statistics.
Note, that the function needs to call thedebug_object_init() functionagain, after the damage has been repaired in order to keep the stateconsistent.
fixup_activate¶
This function is called from the debug code whenever a problem indebug_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, otherwisefalse. The return value is used to update the statistics.
Note that the function needs to call thedebug_object_activate()function again after the damage has been repaired in order to keep thestate consistent.
The activation of statically initialized objects is a special case. Whendebug_object_activate() has no tracked object for this object addressthenfixup_activate() is called with object stateODEBUG_STATE_NOTAVAILABLE. The fixup function needs to check whetherthis is a legitimate case of a statically initialized object or not. Incase it is it callsdebug_object_init() anddebug_object_activate()to make the object known to the tracker and marked active. In this casethe function should return false because this is not a real fixup.
fixup_destroy¶
This function is called from the debug code whenever a problem indebug_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, otherwisefalse. The return value is used to update the statistics.
fixup_free¶
This function is called from the debug code whenever a problem indebug_object_free is detected. Further it can be called from the debugchecks in kfree/vfree, when an active object is detected from thedebug_check_no_obj_freed() sanity checks.
Called fromdebug_object_free() ordebug_check_no_obj_freed() whenthe object state is:
ODEBUG_STATE_ACTIVE
The function returns true when the fixup was successful, otherwisefalse. The return value is used to update the statistics.
fixup_assert_init¶
This function is called from the debug code whenever a problem indebug_object_assert_init is detected.
Called fromdebug_object_assert_init() with a hardcoded stateODEBUG_STATE_NOTAVAILABLE when the object is not found in the debugbucket.
The function returns true when the fixup was successful, otherwisefalse. The return value is used to update the statistics.
Note, this function should make suredebug_object_init() is calledbefore returning.
The handling of statically initialized objects is a special case. Thefixup function should check if this is a legitimate case of a staticallyinitialized object or not. In this case onlydebug_object_init()should be called to make the object known to the tracker. Then thefunction should return false because this is not a real fixup.
Known Bugs And Assumptions¶
None (knock on wood).