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