Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/Documentation/admin-guide/kdump/gdbmacros.txt
26299 views
1
#
2
# This file contains a few gdb macros (user defined commands) to extract
3
# useful information from kernel crashdump (kdump) like stack traces of
4
# all the processes or a particular process and trapinfo.
5
#
6
# These macros can be used by copying this file in .gdbinit (put in home
7
# directory or current directory) or by invoking gdb command with
8
# --command=<command-file-name> option
9
#
10
# Credits:
11
# Alexander Nyberg <[email protected]>
12
# V Srivatsa <[email protected]>
13
# Maneesh Soni <[email protected]>
14
#
15
16
define bttnobp
17
set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
18
set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
19
set $init_t=&init_task
20
set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
21
set var $stacksize = sizeof(union thread_union)
22
while ($next_t != $init_t)
23
set $next_t=(struct task_struct *)$next_t
24
printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
25
printf "===================\n"
26
set var $stackp = $next_t.thread.sp
27
set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize
28
29
while ($stackp < $stack_top)
30
if (*($stackp) > _stext && *($stackp) < _sinittext)
31
info symbol *($stackp)
32
end
33
set $stackp += 4
34
end
35
set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
36
while ($next_th != $next_t)
37
set $next_th=(struct task_struct *)$next_th
38
printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
39
printf "===================\n"
40
set var $stackp = $next_t.thread.sp
41
set var $stack_top = ($stackp & ~($stacksize - 1)) + stacksize
42
43
while ($stackp < $stack_top)
44
if (*($stackp) > _stext && *($stackp) < _sinittext)
45
info symbol *($stackp)
46
end
47
set $stackp += 4
48
end
49
set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
50
end
51
set $next_t=(char *)($next_t->tasks.next) - $tasks_off
52
end
53
end
54
document bttnobp
55
dump all thread stack traces on a kernel compiled with !CONFIG_FRAME_POINTER
56
end
57
58
define btthreadstack
59
set var $pid_task = $arg0
60
61
printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm
62
printf "task struct: "
63
print $pid_task
64
printf "===================\n"
65
set var $stackp = $pid_task.thread.sp
66
set var $stacksize = sizeof(union thread_union)
67
set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize
68
set var $stack_bot = ($stackp & ~($stacksize - 1))
69
70
set $stackp = *((unsigned long *) $stackp)
71
while (($stackp < $stack_top) && ($stackp > $stack_bot))
72
set var $addr = *(((unsigned long *) $stackp) + 1)
73
info symbol $addr
74
set $stackp = *((unsigned long *) $stackp)
75
end
76
end
77
document btthreadstack
78
dump a thread stack using the given task structure pointer
79
end
80
81
82
define btt
83
set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
84
set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
85
set $init_t=&init_task
86
set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
87
while ($next_t != $init_t)
88
set $next_t=(struct task_struct *)$next_t
89
btthreadstack $next_t
90
91
set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
92
while ($next_th != $next_t)
93
set $next_th=(struct task_struct *)$next_th
94
btthreadstack $next_th
95
set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
96
end
97
set $next_t=(char *)($next_t->tasks.next) - $tasks_off
98
end
99
end
100
document btt
101
dump all thread stack traces on a kernel compiled with CONFIG_FRAME_POINTER
102
end
103
104
define btpid
105
set var $pid = $arg0
106
set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
107
set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
108
set $init_t=&init_task
109
set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
110
set var $pid_task = 0
111
112
while ($next_t != $init_t)
113
set $next_t=(struct task_struct *)$next_t
114
115
if ($next_t.pid == $pid)
116
set $pid_task = $next_t
117
end
118
119
set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
120
while ($next_th != $next_t)
121
set $next_th=(struct task_struct *)$next_th
122
if ($next_th.pid == $pid)
123
set $pid_task = $next_th
124
end
125
set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
126
end
127
set $next_t=(char *)($next_t->tasks.next) - $tasks_off
128
end
129
130
btthreadstack $pid_task
131
end
132
document btpid
133
backtrace of pid
134
end
135
136
137
define trapinfo
138
set var $pid = $arg0
139
set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
140
set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
141
set $init_t=&init_task
142
set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
143
set var $pid_task = 0
144
145
while ($next_t != $init_t)
146
set $next_t=(struct task_struct *)$next_t
147
148
if ($next_t.pid == $pid)
149
set $pid_task = $next_t
150
end
151
152
set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
153
while ($next_th != $next_t)
154
set $next_th=(struct task_struct *)$next_th
155
if ($next_th.pid == $pid)
156
set $pid_task = $next_th
157
end
158
set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
159
end
160
set $next_t=(char *)($next_t->tasks.next) - $tasks_off
161
end
162
163
printf "Trapno %ld, cr2 0x%lx, error_code %ld\n", $pid_task.thread.trap_no, \
164
$pid_task.thread.cr2, $pid_task.thread.error_code
165
166
end
167
document trapinfo
168
Run info threads and lookup pid of thread #1
169
'trapinfo <pid>' will tell you by which trap & possibly
170
address the kernel panicked.
171
end
172
173
define dump_record
174
set var $desc = $arg0
175
set var $info = $arg1
176
if ($argc > 2)
177
set var $prev_flags = $arg2
178
else
179
set var $prev_flags = 0
180
end
181
182
set var $prefix = 1
183
set var $newline = 1
184
185
set var $begin = $desc->text_blk_lpos.begin % (1U << prb->text_data_ring.size_bits)
186
set var $next = $desc->text_blk_lpos.next % (1U << prb->text_data_ring.size_bits)
187
188
# handle data-less record
189
if ($begin & 1)
190
set var $text_len = 0
191
set var $log = ""
192
else
193
# handle wrapping data block
194
if ($begin > $next)
195
set var $begin = 0
196
end
197
198
# skip over descriptor id
199
set var $begin = $begin + sizeof(long)
200
201
# handle truncated message
202
if ($next - $begin < $info->text_len)
203
set var $text_len = $next - $begin
204
else
205
set var $text_len = $info->text_len
206
end
207
208
set var $log = &prb->text_data_ring.data[$begin]
209
end
210
211
# prev & LOG_CONT && !(info->flags & LOG_PREIX)
212
if (($prev_flags & 8) && !($info->flags & 4))
213
set var $prefix = 0
214
end
215
216
# info->flags & LOG_CONT
217
if ($info->flags & 8)
218
# (prev & LOG_CONT && !(prev & LOG_NEWLINE))
219
if (($prev_flags & 8) && !($prev_flags & 2))
220
set var $prefix = 0
221
end
222
# (!(info->flags & LOG_NEWLINE))
223
if (!($info->flags & 2))
224
set var $newline = 0
225
end
226
end
227
228
if ($prefix)
229
printf "[%5lu.%06lu] ", $info->ts_nsec / 1000000000, $info->ts_nsec % 1000000000
230
end
231
if ($text_len)
232
eval "printf \"%%%d.%ds\", $log", $text_len, $text_len
233
end
234
if ($newline)
235
printf "\n"
236
end
237
238
# handle dictionary data
239
240
set var $dict = &$info->dev_info.subsystem[0]
241
set var $dict_len = sizeof($info->dev_info.subsystem)
242
if ($dict[0] != '\0')
243
printf " SUBSYSTEM="
244
set var $idx = 0
245
while ($idx < $dict_len)
246
set var $c = $dict[$idx]
247
if ($c == '\0')
248
loop_break
249
else
250
if ($c < ' ' || $c >= 127 || $c == '\\')
251
printf "\\x%02x", $c
252
else
253
printf "%c", $c
254
end
255
end
256
set var $idx = $idx + 1
257
end
258
printf "\n"
259
end
260
261
set var $dict = &$info->dev_info.device[0]
262
set var $dict_len = sizeof($info->dev_info.device)
263
if ($dict[0] != '\0')
264
printf " DEVICE="
265
set var $idx = 0
266
while ($idx < $dict_len)
267
set var $c = $dict[$idx]
268
if ($c == '\0')
269
loop_break
270
else
271
if ($c < ' ' || $c >= 127 || $c == '\\')
272
printf "\\x%02x", $c
273
else
274
printf "%c", $c
275
end
276
end
277
set var $idx = $idx + 1
278
end
279
printf "\n"
280
end
281
end
282
document dump_record
283
Dump a single record. The first parameter is the descriptor,
284
the second parameter is the info, the third parameter is
285
optional and specifies the previous record's flags, used for
286
properly formatting continued lines.
287
end
288
289
define dmesg
290
# definitions from kernel/printk/printk_ringbuffer.h
291
set var $desc_committed = 1
292
set var $desc_finalized = 2
293
set var $desc_sv_bits = sizeof(long) * 8
294
set var $desc_flags_shift = $desc_sv_bits - 2
295
set var $desc_flags_mask = 3 << $desc_flags_shift
296
set var $id_mask = ~$desc_flags_mask
297
298
set var $desc_count = 1U << prb->desc_ring.count_bits
299
set var $prev_flags = 0
300
301
set var $id = prb->desc_ring.tail_id.counter
302
set var $end_id = prb->desc_ring.head_id.counter
303
304
while (1)
305
set var $desc = &prb->desc_ring.descs[$id % $desc_count]
306
set var $info = &prb->desc_ring.infos[$id % $desc_count]
307
308
# skip non-committed record
309
set var $state = 3 & ($desc->state_var.counter >> $desc_flags_shift)
310
if ($state == $desc_committed || $state == $desc_finalized)
311
dump_record $desc $info $prev_flags
312
set var $prev_flags = $info->flags
313
end
314
315
if ($id == $end_id)
316
loop_break
317
end
318
set var $id = ($id + 1) & $id_mask
319
end
320
end
321
document dmesg
322
print the kernel ring buffer
323
end
324
325