Merge tag 'linux-kselftest-kunit-fixes-5.11-rc3' of git://git.kernel.org/pub/scm...
[linux/fpc-iii.git] / Documentation / admin-guide / kdump / gdbmacros.txt
blob82aecdcae8a6c182d0bebea90492b79a199510a8
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.
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
10 # Credits:
11 # Alexander Nyberg <alexn@telia.com>
12 # V Srivatsa <vatsa@in.ibm.com>
13 # Maneesh Soni <maneesh@in.ibm.com>
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
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
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
58 define btthreadstack
59         set var $pid_task = $arg0
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))
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
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
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
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
112         while ($next_t != $init_t)
113                 set $next_t=(struct task_struct *)$next_t
115                 if ($next_t.pid == $pid)
116                         set $pid_task = $next_t
117                 end
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
130         btthreadstack $pid_task
132 document btpid
133         backtrace of pid
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
145         while ($next_t != $init_t)
146                 set $next_t=(struct task_struct *)$next_t
148                 if ($next_t.pid == $pid)
149                         set $pid_task = $next_t
150                 end
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
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
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.
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
182         set var $prefix = 1
183         set var $newline = 1
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)
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
198                 # skip over descriptor id
199                 set var $begin = $begin + sizeof(long)
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
208                 set var $log = &prb->text_data_ring.data[$begin]
209         end
211         # prev & LOG_CONT && !(info->flags & LOG_PREIX)
212         if (($prev_flags & 8) && !($info->flags & 4))
213                 set var $prefix = 0
214         end
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
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
238         # handle dictionary data
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
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
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.
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
298         set var $desc_count = 1U << prb->desc_ring.count_bits
299         set var $prev_flags = 0
301         set var $id = prb->desc_ring.tail_id.counter
302         set var $end_id = prb->desc_ring.head_id.counter
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]
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
315                 set var $id = ($id + 1) & $id_mask
316                 if ($id == $end_id)
317                         loop_break
318                 end
319         end
321 document dmesg
322         print the kernel ring buffer