xref: /openbmc/linux/Documentation/admin-guide/kdump/gdbmacros.txt (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1330d4810SMauro Carvalho Chehab#
2330d4810SMauro Carvalho Chehab# This file contains a few gdb macros (user defined commands) to extract
3330d4810SMauro Carvalho Chehab# useful information from kernel crashdump (kdump) like stack traces of
4330d4810SMauro Carvalho Chehab# all the processes or a particular process and trapinfo.
5330d4810SMauro Carvalho Chehab#
6330d4810SMauro Carvalho Chehab# These macros can be used by copying this file in .gdbinit (put in home
7330d4810SMauro Carvalho Chehab# directory or current directory) or by invoking gdb command with
8330d4810SMauro Carvalho Chehab# --command=<command-file-name> option
9330d4810SMauro Carvalho Chehab#
10330d4810SMauro Carvalho Chehab# Credits:
11330d4810SMauro Carvalho Chehab# Alexander Nyberg <alexn@telia.com>
12330d4810SMauro Carvalho Chehab# V Srivatsa <vatsa@in.ibm.com>
13330d4810SMauro Carvalho Chehab# Maneesh Soni <maneesh@in.ibm.com>
14330d4810SMauro Carvalho Chehab#
15330d4810SMauro Carvalho Chehab
16330d4810SMauro Carvalho Chehabdefine bttnobp
17330d4810SMauro Carvalho Chehab	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
18330d4810SMauro Carvalho Chehab	set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
19330d4810SMauro Carvalho Chehab	set $init_t=&init_task
20330d4810SMauro Carvalho Chehab	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
21330d4810SMauro Carvalho Chehab	set var $stacksize = sizeof(union thread_union)
22330d4810SMauro Carvalho Chehab	while ($next_t != $init_t)
23330d4810SMauro Carvalho Chehab		set $next_t=(struct task_struct *)$next_t
24330d4810SMauro Carvalho Chehab		printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
25330d4810SMauro Carvalho Chehab		printf "===================\n"
26330d4810SMauro Carvalho Chehab		set var $stackp = $next_t.thread.sp
27330d4810SMauro Carvalho Chehab		set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize
28330d4810SMauro Carvalho Chehab
29330d4810SMauro Carvalho Chehab		while ($stackp < $stack_top)
30330d4810SMauro Carvalho Chehab			if (*($stackp) > _stext && *($stackp) < _sinittext)
31330d4810SMauro Carvalho Chehab				info symbol *($stackp)
32330d4810SMauro Carvalho Chehab			end
33330d4810SMauro Carvalho Chehab			set $stackp += 4
34330d4810SMauro Carvalho Chehab		end
35330d4810SMauro Carvalho Chehab		set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
36330d4810SMauro Carvalho Chehab		while ($next_th != $next_t)
37330d4810SMauro Carvalho Chehab			set $next_th=(struct task_struct *)$next_th
38330d4810SMauro Carvalho Chehab			printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
39330d4810SMauro Carvalho Chehab			printf "===================\n"
40330d4810SMauro Carvalho Chehab			set var $stackp = $next_t.thread.sp
41330d4810SMauro Carvalho Chehab			set var $stack_top = ($stackp & ~($stacksize - 1)) + stacksize
42330d4810SMauro Carvalho Chehab
43330d4810SMauro Carvalho Chehab			while ($stackp < $stack_top)
44330d4810SMauro Carvalho Chehab				if (*($stackp) > _stext && *($stackp) < _sinittext)
45330d4810SMauro Carvalho Chehab					info symbol *($stackp)
46330d4810SMauro Carvalho Chehab				end
47330d4810SMauro Carvalho Chehab				set $stackp += 4
48330d4810SMauro Carvalho Chehab			end
49330d4810SMauro Carvalho Chehab			set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
50330d4810SMauro Carvalho Chehab		end
51330d4810SMauro Carvalho Chehab		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
52330d4810SMauro Carvalho Chehab	end
53330d4810SMauro Carvalho Chehabend
54330d4810SMauro Carvalho Chehabdocument bttnobp
55330d4810SMauro Carvalho Chehab	dump all thread stack traces on a kernel compiled with !CONFIG_FRAME_POINTER
56330d4810SMauro Carvalho Chehabend
57330d4810SMauro Carvalho Chehab
58330d4810SMauro Carvalho Chehabdefine btthreadstack
59330d4810SMauro Carvalho Chehab	set var $pid_task = $arg0
60330d4810SMauro Carvalho Chehab
61330d4810SMauro Carvalho Chehab	printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm
62330d4810SMauro Carvalho Chehab	printf "task struct: "
63330d4810SMauro Carvalho Chehab	print $pid_task
64330d4810SMauro Carvalho Chehab	printf "===================\n"
65330d4810SMauro Carvalho Chehab	set var $stackp = $pid_task.thread.sp
66330d4810SMauro Carvalho Chehab	set var $stacksize = sizeof(union thread_union)
67330d4810SMauro Carvalho Chehab	set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize
68330d4810SMauro Carvalho Chehab	set var $stack_bot = ($stackp & ~($stacksize - 1))
69330d4810SMauro Carvalho Chehab
70330d4810SMauro Carvalho Chehab	set $stackp = *((unsigned long *) $stackp)
71330d4810SMauro Carvalho Chehab	while (($stackp < $stack_top) && ($stackp > $stack_bot))
72330d4810SMauro Carvalho Chehab		set var $addr = *(((unsigned long *) $stackp) + 1)
73330d4810SMauro Carvalho Chehab		info symbol $addr
74330d4810SMauro Carvalho Chehab		set $stackp = *((unsigned long *) $stackp)
75330d4810SMauro Carvalho Chehab	end
76330d4810SMauro Carvalho Chehabend
77330d4810SMauro Carvalho Chehabdocument btthreadstack
78330d4810SMauro Carvalho Chehab	 dump a thread stack using the given task structure pointer
79330d4810SMauro Carvalho Chehabend
80330d4810SMauro Carvalho Chehab
81330d4810SMauro Carvalho Chehab
82330d4810SMauro Carvalho Chehabdefine btt
83330d4810SMauro Carvalho Chehab	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
84330d4810SMauro Carvalho Chehab	set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
85330d4810SMauro Carvalho Chehab	set $init_t=&init_task
86330d4810SMauro Carvalho Chehab	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
87330d4810SMauro Carvalho Chehab	while ($next_t != $init_t)
88330d4810SMauro Carvalho Chehab		set $next_t=(struct task_struct *)$next_t
89330d4810SMauro Carvalho Chehab		btthreadstack $next_t
90330d4810SMauro Carvalho Chehab
91330d4810SMauro Carvalho Chehab		set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
92330d4810SMauro Carvalho Chehab		while ($next_th != $next_t)
93330d4810SMauro Carvalho Chehab			set $next_th=(struct task_struct *)$next_th
94330d4810SMauro Carvalho Chehab			btthreadstack $next_th
95330d4810SMauro Carvalho Chehab			set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
96330d4810SMauro Carvalho Chehab		end
97330d4810SMauro Carvalho Chehab		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
98330d4810SMauro Carvalho Chehab	end
99330d4810SMauro Carvalho Chehabend
100330d4810SMauro Carvalho Chehabdocument btt
101330d4810SMauro Carvalho Chehab	dump all thread stack traces on a kernel compiled with CONFIG_FRAME_POINTER
102330d4810SMauro Carvalho Chehabend
103330d4810SMauro Carvalho Chehab
104330d4810SMauro Carvalho Chehabdefine btpid
105330d4810SMauro Carvalho Chehab	set var $pid = $arg0
106330d4810SMauro Carvalho Chehab	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
107330d4810SMauro Carvalho Chehab	set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
108330d4810SMauro Carvalho Chehab	set $init_t=&init_task
109330d4810SMauro Carvalho Chehab	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
110330d4810SMauro Carvalho Chehab	set var $pid_task = 0
111330d4810SMauro Carvalho Chehab
112330d4810SMauro Carvalho Chehab	while ($next_t != $init_t)
113330d4810SMauro Carvalho Chehab		set $next_t=(struct task_struct *)$next_t
114330d4810SMauro Carvalho Chehab
115330d4810SMauro Carvalho Chehab		if ($next_t.pid == $pid)
116330d4810SMauro Carvalho Chehab			set $pid_task = $next_t
117330d4810SMauro Carvalho Chehab		end
118330d4810SMauro Carvalho Chehab
119330d4810SMauro Carvalho Chehab		set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
120330d4810SMauro Carvalho Chehab		while ($next_th != $next_t)
121330d4810SMauro Carvalho Chehab			set $next_th=(struct task_struct *)$next_th
122330d4810SMauro Carvalho Chehab			if ($next_th.pid == $pid)
123330d4810SMauro Carvalho Chehab				set $pid_task = $next_th
124330d4810SMauro Carvalho Chehab			end
125330d4810SMauro Carvalho Chehab			set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
126330d4810SMauro Carvalho Chehab		end
127330d4810SMauro Carvalho Chehab		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
128330d4810SMauro Carvalho Chehab	end
129330d4810SMauro Carvalho Chehab
130330d4810SMauro Carvalho Chehab	btthreadstack $pid_task
131330d4810SMauro Carvalho Chehabend
132330d4810SMauro Carvalho Chehabdocument btpid
133330d4810SMauro Carvalho Chehab	backtrace of pid
134330d4810SMauro Carvalho Chehabend
135330d4810SMauro Carvalho Chehab
136330d4810SMauro Carvalho Chehab
137330d4810SMauro Carvalho Chehabdefine trapinfo
138330d4810SMauro Carvalho Chehab	set var $pid = $arg0
139330d4810SMauro Carvalho Chehab	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
140330d4810SMauro Carvalho Chehab	set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
141330d4810SMauro Carvalho Chehab	set $init_t=&init_task
142330d4810SMauro Carvalho Chehab	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
143330d4810SMauro Carvalho Chehab	set var $pid_task = 0
144330d4810SMauro Carvalho Chehab
145330d4810SMauro Carvalho Chehab	while ($next_t != $init_t)
146330d4810SMauro Carvalho Chehab		set $next_t=(struct task_struct *)$next_t
147330d4810SMauro Carvalho Chehab
148330d4810SMauro Carvalho Chehab		if ($next_t.pid == $pid)
149330d4810SMauro Carvalho Chehab			set $pid_task = $next_t
150330d4810SMauro Carvalho Chehab		end
151330d4810SMauro Carvalho Chehab
152330d4810SMauro Carvalho Chehab		set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
153330d4810SMauro Carvalho Chehab		while ($next_th != $next_t)
154330d4810SMauro Carvalho Chehab			set $next_th=(struct task_struct *)$next_th
155330d4810SMauro Carvalho Chehab			if ($next_th.pid == $pid)
156330d4810SMauro Carvalho Chehab				set $pid_task = $next_th
157330d4810SMauro Carvalho Chehab			end
158330d4810SMauro Carvalho Chehab			set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
159330d4810SMauro Carvalho Chehab		end
160330d4810SMauro Carvalho Chehab		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
161330d4810SMauro Carvalho Chehab	end
162330d4810SMauro Carvalho Chehab
163330d4810SMauro Carvalho Chehab	printf "Trapno %ld, cr2 0x%lx, error_code %ld\n", $pid_task.thread.trap_no, \
164330d4810SMauro Carvalho Chehab				$pid_task.thread.cr2, $pid_task.thread.error_code
165330d4810SMauro Carvalho Chehab
166330d4810SMauro Carvalho Chehabend
167330d4810SMauro Carvalho Chehabdocument trapinfo
168330d4810SMauro Carvalho Chehab	Run info threads and lookup pid of thread #1
169330d4810SMauro Carvalho Chehab	'trapinfo <pid>' will tell you by which trap & possibly
170330d4810SMauro Carvalho Chehab	address the kernel panicked.
171330d4810SMauro Carvalho Chehabend
172330d4810SMauro Carvalho Chehab
173e6076831SJohn Ognessdefine dump_record
174e6076831SJohn Ogness	set var $desc = $arg0
17574caba7fSJohn Ogness	set var $info = $arg1
17674caba7fSJohn Ogness	if ($argc > 2)
17774caba7fSJohn Ogness		set var $prev_flags = $arg2
178330d4810SMauro Carvalho Chehab	else
179e6076831SJohn Ogness		set var $prev_flags = 0
180330d4810SMauro Carvalho Chehab	end
181330d4810SMauro Carvalho Chehab
182e6076831SJohn Ogness	set var $prefix = 1
183e6076831SJohn Ogness	set var $newline = 1
184e6076831SJohn Ogness
185e6076831SJohn Ogness	set var $begin = $desc->text_blk_lpos.begin % (1U << prb->text_data_ring.size_bits)
186e6076831SJohn Ogness	set var $next = $desc->text_blk_lpos.next % (1U << prb->text_data_ring.size_bits)
187e6076831SJohn Ogness
188e6076831SJohn Ogness	# handle data-less record
189e6076831SJohn Ogness	if ($begin & 1)
190e6076831SJohn Ogness		set var $text_len = 0
191e6076831SJohn Ogness		set var $log = ""
192e6076831SJohn Ogness	else
193e6076831SJohn Ogness		# handle wrapping data block
194e6076831SJohn Ogness		if ($begin > $next)
195e6076831SJohn Ogness			set var $begin = 0
196e6076831SJohn Ogness		end
197e6076831SJohn Ogness
198e6076831SJohn Ogness		# skip over descriptor id
199e6076831SJohn Ogness		set var $begin = $begin + sizeof(long)
200e6076831SJohn Ogness
201e6076831SJohn Ogness		# handle truncated message
202e6076831SJohn Ogness		if ($next - $begin < $info->text_len)
203e6076831SJohn Ogness			set var $text_len = $next - $begin
204e6076831SJohn Ogness		else
205e6076831SJohn Ogness			set var $text_len = $info->text_len
206e6076831SJohn Ogness		end
207e6076831SJohn Ogness
208e6076831SJohn Ogness		set var $log = &prb->text_data_ring.data[$begin]
209e6076831SJohn Ogness	end
210e6076831SJohn Ogness
211e6076831SJohn Ogness	# prev & LOG_CONT && !(info->flags & LOG_PREIX)
212e6076831SJohn Ogness	if (($prev_flags & 8) && !($info->flags & 4))
213e6076831SJohn Ogness		set var $prefix = 0
214e6076831SJohn Ogness	end
215e6076831SJohn Ogness
216e6076831SJohn Ogness	# info->flags & LOG_CONT
217e6076831SJohn Ogness	if ($info->flags & 8)
218330d4810SMauro Carvalho Chehab		# (prev & LOG_CONT && !(prev & LOG_NEWLINE))
219330d4810SMauro Carvalho Chehab		if (($prev_flags & 8) && !($prev_flags & 2))
220e6076831SJohn Ogness			set var $prefix = 0
221330d4810SMauro Carvalho Chehab		end
222e6076831SJohn Ogness		# (!(info->flags & LOG_NEWLINE))
223e6076831SJohn Ogness		if (!($info->flags & 2))
224e6076831SJohn Ogness			set var $newline = 0
225330d4810SMauro Carvalho Chehab		end
226330d4810SMauro Carvalho Chehab	end
227330d4810SMauro Carvalho Chehab
228330d4810SMauro Carvalho Chehab	if ($prefix)
229e6076831SJohn Ogness		printf "[%5lu.%06lu] ", $info->ts_nsec / 1000000000, $info->ts_nsec % 1000000000
230330d4810SMauro Carvalho Chehab	end
231e6076831SJohn Ogness	if ($text_len)
232e6076831SJohn Ogness		eval "printf \"%%%d.%ds\", $log", $text_len, $text_len
233330d4810SMauro Carvalho Chehab	end
234330d4810SMauro Carvalho Chehab	if ($newline)
235330d4810SMauro Carvalho Chehab		printf "\n"
236330d4810SMauro Carvalho Chehab	end
237e6076831SJohn Ogness
238e6076831SJohn Ogness	# handle dictionary data
239e6076831SJohn Ogness
24074caba7fSJohn Ogness	set var $dict = &$info->dev_info.subsystem[0]
24174caba7fSJohn Ogness	set var $dict_len = sizeof($info->dev_info.subsystem)
24274caba7fSJohn Ogness	if ($dict[0] != '\0')
24374caba7fSJohn Ogness		printf " SUBSYSTEM="
244e6076831SJohn Ogness		set var $idx = 0
245e6076831SJohn Ogness		while ($idx < $dict_len)
246e6076831SJohn Ogness			set var $c = $dict[$idx]
247330d4810SMauro Carvalho Chehab			if ($c == '\0')
24874caba7fSJohn Ogness				loop_break
24974caba7fSJohn Ogness			else
25074caba7fSJohn Ogness				if ($c < ' ' || $c >= 127 || $c == '\\')
25174caba7fSJohn Ogness					printf "\\x%02x", $c
25274caba7fSJohn Ogness				else
25374caba7fSJohn Ogness					printf "%c", $c
25474caba7fSJohn Ogness				end
25574caba7fSJohn Ogness			end
25674caba7fSJohn Ogness			set var $idx = $idx + 1
25774caba7fSJohn Ogness		end
258330d4810SMauro Carvalho Chehab		printf "\n"
25974caba7fSJohn Ogness	end
26074caba7fSJohn Ogness
26174caba7fSJohn Ogness	set var $dict = &$info->dev_info.device[0]
26274caba7fSJohn Ogness	set var $dict_len = sizeof($info->dev_info.device)
26374caba7fSJohn Ogness	if ($dict[0] != '\0')
26474caba7fSJohn Ogness		printf " DEVICE="
26574caba7fSJohn Ogness		set var $idx = 0
26674caba7fSJohn Ogness		while ($idx < $dict_len)
26774caba7fSJohn Ogness			set var $c = $dict[$idx]
26874caba7fSJohn Ogness			if ($c == '\0')
26974caba7fSJohn Ogness				loop_break
270330d4810SMauro Carvalho Chehab			else
271330d4810SMauro Carvalho Chehab				if ($c < ' ' || $c >= 127 || $c == '\\')
272330d4810SMauro Carvalho Chehab					printf "\\x%02x", $c
273330d4810SMauro Carvalho Chehab				else
274330d4810SMauro Carvalho Chehab					printf "%c", $c
275330d4810SMauro Carvalho Chehab				end
276330d4810SMauro Carvalho Chehab			end
277e6076831SJohn Ogness			set var $idx = $idx + 1
278330d4810SMauro Carvalho Chehab		end
279330d4810SMauro Carvalho Chehab		printf "\n"
280330d4810SMauro Carvalho Chehab	end
281330d4810SMauro Carvalho Chehabend
282e6076831SJohn Ognessdocument dump_record
28374caba7fSJohn Ogness	Dump a single record. The first parameter is the descriptor,
28474caba7fSJohn Ogness	the second parameter is the info, the third parameter is
28574caba7fSJohn Ogness	optional and specifies the previous record's flags, used for
28674caba7fSJohn Ogness	properly formatting continued lines.
287330d4810SMauro Carvalho Chehabend
288330d4810SMauro Carvalho Chehab
289330d4810SMauro Carvalho Chehabdefine dmesg
29010dcb06dSJohn Ogness	# definitions from kernel/printk/printk_ringbuffer.h
29110dcb06dSJohn Ogness	set var $desc_committed = 1
2924cfc7258SJohn Ogness	set var $desc_finalized = 2
29310dcb06dSJohn Ogness	set var $desc_sv_bits = sizeof(long) * 8
29410dcb06dSJohn Ogness	set var $desc_flags_shift = $desc_sv_bits - 2
29510dcb06dSJohn Ogness	set var $desc_flags_mask = 3 << $desc_flags_shift
29610dcb06dSJohn Ogness	set var $id_mask = ~$desc_flags_mask
297e6076831SJohn Ogness
298e6076831SJohn Ogness	set var $desc_count = 1U << prb->desc_ring.count_bits
299e6076831SJohn Ogness	set var $prev_flags = 0
300e6076831SJohn Ogness
301e6076831SJohn Ogness	set var $id = prb->desc_ring.tail_id.counter
302e6076831SJohn Ogness	set var $end_id = prb->desc_ring.head_id.counter
303330d4810SMauro Carvalho Chehab
304330d4810SMauro Carvalho Chehab	while (1)
305e6076831SJohn Ogness		set var $desc = &prb->desc_ring.descs[$id % $desc_count]
30674caba7fSJohn Ogness		set var $info = &prb->desc_ring.infos[$id % $desc_count]
307e6076831SJohn Ogness
308e6076831SJohn Ogness		# skip non-committed record
30910dcb06dSJohn Ogness		set var $state = 3 & ($desc->state_var.counter >> $desc_flags_shift)
3104cfc7258SJohn Ogness		if ($state == $desc_committed || $state == $desc_finalized)
31174caba7fSJohn Ogness			dump_record $desc $info $prev_flags
31274caba7fSJohn Ogness			set var $prev_flags = $info->flags
313330d4810SMauro Carvalho Chehab		end
314e6076831SJohn Ogness
315e6076831SJohn Ogness		if ($id == $end_id)
316330d4810SMauro Carvalho Chehab			loop_break
317330d4810SMauro Carvalho Chehab		end
318*f2e4cca2SJohn Ogness		set var $id = ($id + 1) & $id_mask
319330d4810SMauro Carvalho Chehab	end
320330d4810SMauro Carvalho Chehabend
321330d4810SMauro Carvalho Chehabdocument dmesg
322330d4810SMauro Carvalho Chehab	print the kernel ring buffer
323330d4810SMauro Carvalho Chehabend
324