aboutsummaryrefslogtreecommitdiff
path: root/Documentation/core-api/debug-objects.rst
blob: ac926fd55a64a9023680081c0e6ae20b2f33f460 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
============================================
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).