brintos

brintos / linux-shallow public Read only

0
0
Text · 8.6 KiB · 030de95 Raw
324 lines · plain
1#2# This file contains a few gdb macros (user defined commands) to extract3# useful information from kernel crashdump (kdump) like stack traces of4# all the processes or a particular process and trapinfo.5#6# These macros can be used by copying this file in .gdbinit (put in home7# directory or current directory) or by invoking gdb command with8# --command=<command-file-name> option9#10# Credits:11# Alexander Nyberg <alexn@telia.com>12# V Srivatsa <vatsa@in.ibm.com>13# Maneesh Soni <maneesh@in.ibm.com>14#15 16define bttnobp17	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_task20	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_t24		printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm25		printf "===================\n"26		set var $stackp = $next_t.thread.sp27		set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize28 29		while ($stackp < $stack_top)30			if (*($stackp) > _stext && *($stackp) < _sinittext)31				info symbol *($stackp)32			end33			set $stackp += 434		end35		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_th38			printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm39			printf "===================\n"40			set var $stackp = $next_t.thread.sp41			set var $stack_top = ($stackp & ~($stacksize - 1)) + stacksize42 43			while ($stackp < $stack_top)44				if (*($stackp) > _stext && *($stackp) < _sinittext)45					info symbol *($stackp)46				end47				set $stackp += 448			end49			set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)50		end51		set $next_t=(char *)($next_t->tasks.next) - $tasks_off52	end53end54document bttnobp55	dump all thread stack traces on a kernel compiled with !CONFIG_FRAME_POINTER56end57 58define btthreadstack59	set var $pid_task = $arg060 61	printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm62	printf "task struct: "63	print $pid_task64	printf "===================\n"65	set var $stackp = $pid_task.thread.sp66	set var $stacksize = sizeof(union thread_union)67	set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize68	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 $addr74		set $stackp = *((unsigned long *) $stackp)75	end76end77document btthreadstack78	 dump a thread stack using the given task structure pointer79end80 81 82define btt83	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_task86	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)87	while ($next_t != $init_t)88		set $next_t=(struct task_struct *)$next_t89		btthreadstack $next_t90 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_th94			btthreadstack $next_th95			set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)96		end97		set $next_t=(char *)($next_t->tasks.next) - $tasks_off98	end99end100document btt101	dump all thread stack traces on a kernel compiled with CONFIG_FRAME_POINTER102end103 104define btpid105	set var $pid = $arg0106	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_task109	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)110	set var $pid_task = 0111 112	while ($next_t != $init_t)113		set $next_t=(struct task_struct *)$next_t114 115		if ($next_t.pid == $pid)116			set $pid_task = $next_t117		end118 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_th122			if ($next_th.pid == $pid)123				set $pid_task = $next_th124			end125			set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)126		end127		set $next_t=(char *)($next_t->tasks.next) - $tasks_off128	end129 130	btthreadstack $pid_task131end132document btpid133	backtrace of pid134end135 136 137define trapinfo138	set var $pid = $arg0139	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_task142	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)143	set var $pid_task = 0144 145	while ($next_t != $init_t)146		set $next_t=(struct task_struct *)$next_t147 148		if ($next_t.pid == $pid)149			set $pid_task = $next_t150		end151 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_th155			if ($next_th.pid == $pid)156				set $pid_task = $next_th157			end158			set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)159		end160		set $next_t=(char *)($next_t->tasks.next) - $tasks_off161	end162 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_code165 166end167document trapinfo168	Run info threads and lookup pid of thread #1169	'trapinfo <pid>' will tell you by which trap & possibly170	address the kernel panicked.171end172 173define dump_record174	set var $desc = $arg0175	set var $info = $arg1176	if ($argc > 2)177		set var $prev_flags = $arg2178	else179		set var $prev_flags = 0180	end181 182	set var $prefix = 1183	set var $newline = 1184 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 record189	if ($begin & 1)190		set var $text_len = 0191		set var $log = ""192	else193		# handle wrapping data block194		if ($begin > $next)195			set var $begin = 0196		end197 198		# skip over descriptor id199		set var $begin = $begin + sizeof(long)200 201		# handle truncated message202		if ($next - $begin < $info->text_len)203			set var $text_len = $next - $begin204		else205			set var $text_len = $info->text_len206		end207 208		set var $log = &prb->text_data_ring.data[$begin]209	end210 211	# prev & LOG_CONT && !(info->flags & LOG_PREIX)212	if (($prev_flags & 8) && !($info->flags & 4))213		set var $prefix = 0214	end215 216	# info->flags & LOG_CONT217	if ($info->flags & 8)218		# (prev & LOG_CONT && !(prev & LOG_NEWLINE))219		if (($prev_flags & 8) && !($prev_flags & 2))220			set var $prefix = 0221		end222		# (!(info->flags & LOG_NEWLINE))223		if (!($info->flags & 2))224			set var $newline = 0225		end226	end227 228	if ($prefix)229		printf "[%5lu.%06lu] ", $info->ts_nsec / 1000000000, $info->ts_nsec % 1000000000230	end231	if ($text_len)232		eval "printf \"%%%d.%ds\", $log", $text_len, $text_len233	end234	if ($newline)235		printf "\n"236	end237 238	# handle dictionary data239 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 = 0245		while ($idx < $dict_len)246			set var $c = $dict[$idx]247			if ($c == '\0')248				loop_break249			else250				if ($c < ' ' || $c >= 127 || $c == '\\')251					printf "\\x%02x", $c252				else253					printf "%c", $c254				end255			end256			set var $idx = $idx + 1257		end258		printf "\n"259	end260 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 = 0266		while ($idx < $dict_len)267			set var $c = $dict[$idx]268			if ($c == '\0')269				loop_break270			else271				if ($c < ' ' || $c >= 127 || $c == '\\')272					printf "\\x%02x", $c273				else274					printf "%c", $c275				end276			end277			set var $idx = $idx + 1278		end279		printf "\n"280	end281end282document dump_record283	Dump a single record. The first parameter is the descriptor,284	the second parameter is the info, the third parameter is285	optional and specifies the previous record's flags, used for286	properly formatting continued lines.287end288 289define dmesg290	# definitions from kernel/printk/printk_ringbuffer.h291	set var $desc_committed = 1292	set var $desc_finalized = 2293	set var $desc_sv_bits = sizeof(long) * 8294	set var $desc_flags_shift = $desc_sv_bits - 2295	set var $desc_flags_mask = 3 << $desc_flags_shift296	set var $id_mask = ~$desc_flags_mask297 298	set var $desc_count = 1U << prb->desc_ring.count_bits299	set var $prev_flags = 0300 301	set var $id = prb->desc_ring.tail_id.counter302	set var $end_id = prb->desc_ring.head_id.counter303 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 record309		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_flags312			set var $prev_flags = $info->flags313		end314 315		if ($id == $end_id)316			loop_break317		end318		set var $id = ($id + 1) & $id_mask319	end320end321document dmesg322	print the kernel ring buffer323end324