define btt
	dont-repeat
	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
	set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
	set $init_t=&init_task
	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
	set $machine1=*system_utsname.machine
	while ($next_t != $init_t)
		set $next_t=(struct task_struct *)$next_t
		printf "\n%d - %s\n", $next_t.pid, $next_t.comm
		printf "-------------------\n"
		if $machine1 = 0x78
			set var $stackp = $next_t.thread.rsp
		else
			set var $stackp = $next_t.thread.esp
		end
		set var $stack_top = ($stackp & ~4095) + 4096

		while ($stackp < $stack_top)
			set $func = *($stackp)
			if ($func > _stext && $func < _sinittext)
				printf "%x ", $func
				info symbol $func
			end
			set $stackp += 4
		end
		set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
		while ($next_th != $next_t)
			set $next_th=(struct task_struct *)$next_th
			printf "\n%d - %s\n", $next_t.pid, $next_t.comm
			printf "-------------------\n"
			if $machine1 = 0x78
				set var $stackp = $next_t.thread.rsp
			else
				set var $stackp = $next_t.thread.esp
			end
			set var $stack_top = ($stackp & ~4095) + 4096

			while ($stackp < $stack_top)
				set $func = *($stackp)
				if ($func > _stext && $func < _sinittext)
					printf "%x ", $func
					info symbol $func
				end
				set $stackp += 4
			end
			set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
		end
		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
	end
end
document btt
	print symbolic stack backtraces of *all* tasks, very slow
	works only with x86_64 or ia32 kernel compiled with CONFIG_FRAME_POINTER off.
end

define btpid
	dont-repeat
	set var $pid = $arg0
	printf "looking for task_struct of pid %d...\n", $pid
	printf "This may take a few seconds or up to a few minutes (with many tasks)\n"
	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
	set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
	set $init_t=&init_task
	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
	set var $pid_task = 0

	while ($next_t != $init_t)
		set $next_t=(struct task_struct *)$next_t

		if ($next_t.pid == $pid)
			set $pid_task = $next_t
			loop_break
		end

		set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
		while ($next_th != $next_t)
			set $next_th=(struct task_struct *)$next_th
			if ($next_th.pid == $pid)
				set $pid_task = $next_th
				loop_break
			end
			set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
		end
		if $pid_task != 0
			loop_break
		end
		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
	end

	printf "\npid %d - %s:\n", $pid_task.pid, $pid_task.comm
	printf "-------------------\n"
	set $machine1=*system_utsname.machine
	if $machine1 == 0x78
		set var $stackp = $pid_task.thread.rsp
	else
		set var $stackp = $pid_task.thread.esp
	end
	set var $stack_top = ($stackp & ~4095) + 4096

	while ($stackp < $stack_top)
		set $func = *($stackp)
		if ($func > _stext && $func < _sinittext)
			printf "%x ", $func
			info symbol $func
		end
		set $stackp += 4
	end
end
document btpid
	Print a symbolic backtrace of the task with the passed pid
end

define trapinfo
	dont-repeat
	set var $pid = $arg0
	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
	set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
	set $init_t=&init_task
	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
	set var $pid_task = 0

	while ($next_t != $init_t)
		set $next_t=(struct task_struct *)$next_t

		if ($next_t.pid == $pid)
			set $pid_task = $next_t
		end

		set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
		while ($next_th != $next_t)
			set $next_th=(struct task_struct *)$next_th
			if ($next_th.pid == $pid)
				set $pid_task = $next_th
			end
			set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
		end
		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
	end

	printf "Trapno %ld, cr2 0x%lx, error_code %ld\n", $pid_task.thread.trap_no, \
				$pid_task.thread.cr2, $pid_task.thread.error_code

end
document trapinfo
	Run info threads and lookup pid of thread #1
	'trapinfo <pid>' will tell you by which trap & possibly
	addresthe kernel paniced.
end

# fireproxy leaks memory when this is executed:
define dmesg
	echo "This command will cause fireproxy to eat all your memory, abort fireproxy now!"
	dont-repeat
	set $i = 0
	set $log_end = log_end
	set $log_buf_len = log_buf_len
	set $end_idx = (log_end - 1) & (log_buf_len - 1)
	set $logged_chars = logged_chars
	set $rest = $log_end - 1 - $logged_chars

	while ($i < $logged_chars)
		set $idx = ($rest + $i) & ($log_buf_len - 1)

		if ($idx + 100 <= $end_idx) || \
		   ($end_idx <= $idx && $idx + 100 < $log_buf_len)
			printf "%.100s", &log_buf[$idx]
			set $i = $i + 100
			#printf "."
		else
			printf "%c", log_buf[$idx]
			set $i = $i + 1
		end
	end 
end
document dmesg
	print the kernel ring buffer, does not work yet, fireproxy leask also too much memory
end
# Works fine but may not work correcyly if buffer has wrapped:
define dump_dmesg
	dont-repeat
	# dump binary memory to demesg.out start-addr, end-addr:
	dump binary memory dmesg.out log_buf (log_buf+log_end)
	# see gdb reference for details:
	# http://sources.redhat.com/gdb/onlinedocs/gdb_9.html#SEC75
end
document dump_dmesg
	dump the kernel ring buffer into dmesg.out, buffer should not be wrapped
end
define dump_kernel_3m
	dont-repeat
	# may take a half a minute:
	dump binary memory kernel.dump 0xc0000000 0xc046f788
	# run strings kernel.dump and look for e.g. <5>Linux in the output
	# to find the boot messages 
end
document dump_kernel_3m
	dump the i386 kernel memory from 0xc0000000 0xc046f788 to kernel.dump
end

# for gdb-side debug output on the remote protocol:
#set debug serial 1
#set debug target 1

set prompt Create a symlink ../vmlinux, which points to the vmlinux file\n\
of the remote kernel, compiled with -g, type 'q' to exit:\ 
file ../vmlinux

# this command, instead of "file" does not work on x86_64 yet, it causes
# different symbol addresses being loaded, to compare with i386:
#symbol-file ../vmlinux

set prompt Check if you can connect to this machine and port and\n\
check if fireproxy is (re)started already, type 'q' to exit:\ 
target remote localhost:4
set prompt (kgdb)\ 
echo Messages like: warning: shared library handler failed to enable breakpoint
echo and '0x00000000 in ?? ()' are currently normal.

	echo ========================================================================
	echo = Welcome to fireproxy. If vmlinux matches, this is the remote system: =
	echo ========================================================================
	set $sysname  = system_utsname.sysname
	set $nodename = system_utsname.nodename
	set $release  = system_utsname.release
	set $version  = system_utsname.version
	set $machine  = system_utsname.machine
	printf "%s %s %s %s %s\n", $sysname, $nodename, $release, $version, $machine

#set verbose on
set confirm off
set output-radix 16
show output-radix
set logging file .gdblog
set history filename .gdbhistory
set history save on
set history expansion on
#show commands
set print null-stop
set print repeats 20
set print pretty on
set print sevenbit-strings on

# Show the currently defined used-defined commands:
help user-defined


# `detach'
#      When you have finished debugging the remote program, you can use
#      the `detach' command to release it from GDB control.  Detaching
#      from the target normally resumes its execution, but the results
#      will depend on your particular remote stub.  After the `detach'
#      command, GDB is free to connect to another target.
# 
# `disconnect'
#      The `disconnect' command behaves like `detach', except that the
#      target is generally not resumed.  It will wait for GDB (this
#      instance or another one) to connect and continue debugging.  After
#      the `disconnect' command, GDB is again free to connect to another
#      target.
# 
# `monitor CMD'
#      This command allows you to send commands directly to the remote
#      monitor.
# 
