kgmacros   [plain text]


# Kernel gdb macros
#
#  These gdb macros should be useful during kernel development in
#  determining what's going on in the kernel.
#
#  All the convenience variables used by these macros begin with $kgm_

set print asm-demangle on
set cp-abi gnu-v2

echo Loading Kernel GDB Macros package.  Type "help kgm" for more info.\n

define kgm
printf ""
echo  These are the gdb macros for kernel debugging.  Type "help kgm" for more info.\n
end

document kgm
| These are the kernel gdb macros.  These gdb macros are intended to be
| used when debugging a remote kernel via the kdp protocol.  Typically, you
| would connect to your remote target like so:
| 		 (gdb) target remote-kdp
| 		 (gdb) attach <name-of-remote-host>
|
| The following macros are available in this package:
|     showversion    Displays a string describing the remote kernel version
|
|     showalltasks   Display a summary listing of all tasks
|     showallthreads Display info about all threads in the system
|     showallstacks  Display the stack for each thread in the system
|     showcurrentthreads   Display info about the thread running on each cpu
|     showcurrentstacks    Display the stack for the thread running on each cpu
|     showallvm      Display a summary listing of all the vm maps
|     showallvme     Display a summary listing of all the vm map entries
|     showallipc     Display a summary listing of all the ipc spaces
|     showallrights  Display a summary listing of all the ipc rights
|     showallkmods   Display a summary listing of all the kernel modules
|
|     showallclasses    Display info about all OSObject subclasses in the system
|     showobject        Show info about an OSObject - its vtable ptr and retain count, & more info for simple container classes.
|     showregistry      Show info about all registry entries in the current plane
|     showregistryprops Show info about all registry entries in the current plane, and their properties
|     showregistryentry Show info about a registry entry; its properties and descendants in the current plane
|     setregistryplane  Set the plane to be used for the iokit registry macros (pass zero for list)
|
|     showtask       Display info about the specified task
|     showtaskthreads      Display info about the threads in the task
|     showtaskstacks Display the stack for each thread in the task
|     showtaskvm     Display info about the specified task's vm_map
|     showtaskvme    Display info about the task's vm_map entries
|     showtaskipc    Display info about the specified task's ipc space
|     showtaskrights Display info about the task's ipc space entries
|
|     showact	     Display info about a thread specified by activation
|     showactstack   Display the stack for a thread specified by activation
|
|     showmap	     Display info about the specified vm_map
|     showmapvme     Display a summary list of the specified vm_map's entries
|
|     showipc        Display info about the specified ipc space
|     showrights     Display a summary list of all the rights in an ipc space
|
|     showpid        Display info about the process identified by pid
|     showproc       Display info about the process identified by proc struct
|     showprocinfo   Display detailed info about the process identified by proc struct
|     showprocfiles  Given a proc_t pointer, display the list of open file descriptors
|     showproclocks  Given a proc_t pointer, display the list of advisory file locks
|     zombproc       Print out all procs in the zombie list
|     allproc        Print out all process in the system not in the zombie list
|     zombstacks     Print out all stacks of tasks that are exiting
|
|     showinitchild  Print out all processes in the system which are children of init process
|
|     showkmod	     Display info about a kernel module
|     showkmodaddr   Given an address, display the kernel module and offset
|
|     dumpcallqueue  Dump out all the entries given a queue head
|
|     showallmtx     Display info about mutexes usage
|     showallrwlck   Display info about reader/writer locks usage
|
|     zprint         Display info about the memory zones
|     showioalloc    Display info about iokit allocations
|     paniclog       Display the panic log info
|
|     switchtoact    Switch to different context specified by activation
|     switchtoctx    Switch to different context
|     showuserstack  Display numeric backtrace of the user stack for an 
|     		     activation
|
|     switchtouserthread Switch to the user context of the specified thread
|     resetstacks    Return to the original kernel context
|
|     resetctx       Reset context
|     resume_on      Resume when detaching from gdb
|     resume_off     Don't resume when detaching from gdb 
|
|     sendcore	     Configure kernel to send a coredump to the specified IP
|     disablecore    Configure the kernel to disable coredump transmission
|     switchtocorethread Corefile version of "switchtoact"
|     resetcorectx   Corefile version of "resetctx"
|
|     readphys       Reads the specified untranslated address
|     readphys64     Reads the specified untranslated 64-bit address
|
|     rtentry_showdbg Print the debug information of a route entry
|     rtentry_trash  Walk the list of trash route entries
|
|     mbuf_walkpkt   Walk the mbuf packet chain (m_nextpkt)
|     mbuf_walk      Walk the mbuf chain (m_next)
|     mbuf_buf2slab  Find the slab structure of the corresponding buffer
|     mbuf_buf2mca   Find the mcache audit structure of the corresponding mbuf
|     mbuf_showmca   Print the contents of an mbuf mcache audit structure
|     mbuf_showactive   Print all active/in-use mbuf objects
|     mbuf_showinactive Print all freed/in-cache mbuf objects 
|     mbuf_showall   Print all mbuf objects
|     mbuf_slabs     Print all slabs in the group
|     mbuf_slabstbl  Print slabs table
|     mbuf_stat      Print extended mbuf allocator statistics
|
|     mcache_walkobj     Walk the mcache object chain (obj_next)
|     mcache_stat        Print all mcaches in the system
|     mcache_showcache   Display the number of objects in the cache
|
|     showbootermemorymap Dump phys memory map from EFI
|
|     systemlog      Display the kernel's printf ring buffer
|
|     showvnodepath      Print the path for a vnode
|     showvnodelocks     Display list of advisory locks held/blocked on a vnode
|     showallvols        Display a summary of mounted volumes
|     showvnode          Display info about one vnode
|     showvolvnodes      Display info about all vnodes of a given volume
|     showvolbusyvnodes  Display info about busy (iocount!=0) vnodes of a given volume
|     showallbusyvnodes  Display info about all busy (iocount!=0) vnodes
|     showallvnodes      Display info about all vnodes
|     print_vnode        Print out the fields of a vnode struct
|     showprocvnodes     Print out all the open fds which are vnodes in a process
|     showallprocvnodes  Print out all the open fds which are vnodes in any process
|     showmountvnodes    Print the vnode list
|     showmountallvnodes Print the vnode inactive list
|     showworkqvnodes    Print the vnode worker list
|     shownewvnodes      Print the new vnode list
|
|     ifconfig       display ifconfig-like output
|     showifaddrs    show the list of addresses for the given ifp
|     showifmultiaddrs show the list of multicast addresses for the given ifp
|
|     showallpmworkqueues   Display info about all IOPMWorkQueue objects
|     showregistrypmstate   Display power management state for all IOPower registry entries
|     showioservicepm       Display the IOServicePM object
|     showstacksaftertask   showallstacks starting after a given task
|     showstacksafterthread showallstacks starting after a given thread
|
|     showMCAstate	Print machine-check register state after MC exception.
|
|     showallgdbstacks	Cause GDB to trace all thread stacks
|     showallgdbcorestacks Corefile equivalent of "showallgdbstacks"
|     kdp-reenter	Schedule reentry into the debugger and continue.
|     kdp-reboot	Restart remote target
|
|     zstack		Print zalloc caller stack (zone leak debugging)
|     findoldest	Find oldest zone leak debugging record
|     countpcs		Print how often a pc occurs in the zone leak log
|
|
| Type "help <macro>" for more specific help on a particular macro.
| Type "show user <macro>" to see what the macro is really doing.
end

# This macro should appear before any symbol references, to facilitate
# a gdb "source" without a loaded symbol file.
define showversion
       printf "%s\n", *(char **)0x501C
end

document showversion
Syntax: showversion
| Read the kernel version string from a fixed address in low
| memory. Useful if you don't know which kernel is on the other end,
| and need to find the appropriate symbols. Beware that if you've
| loaded a symbol file, but aren't connected to a remote target,
| the version string from the symbol file will be displayed instead.
| This macro expects to be connected to the remote kernel to function
| correctly.
end

set $kgm_mtype = ((struct mach_header)_mh_execute_header).cputype

# This option tells gdb to relax its stack tracing heuristics
# Useful for debugging across stack switches
# (to the interrupt stack, for instance). Requires gdb-675 or greater.
# Don't do this for arm as a workaround to 5486905
if ($kgm_mtype != 12)
	set backtrace sanity-checks off
end

set $kgm_dummy = &proc0
set $kgm_dummy = &kmod

set $kgm_reg_depth = 0
set $kgm_reg_plane = (void **) gIOServicePlane
set $kgm_namekey = (OSSymbol *) 0
set $kgm_childkey = (OSSymbol *) 0

set $kgm_show_object_addrs = 0
set $kgm_show_object_retain = 0
set $kgm_show_props = 0

set $kgm_show_kmod_syms = 0

define showkmodheader
    printf "kmod        address     size        "
    printf "id    refs     version  name\n"
end

define showkmodint
    set $kgm_kmodp = (struct kmod_info *)$arg0
    printf "0x%08x  ", $arg0
    printf "0x%08x  ", $kgm_kmodp->address
    printf "0x%08x  ", $kgm_kmodp->size
    printf "%3d  ", $kgm_kmodp->id
    printf "%5d  ", $kgm_kmodp->reference_count
    printf "%10s  ", &$kgm_kmodp->version
    printf "%s\n", &$kgm_kmodp->name
end

set $kgm_kmodmin = 0xffffffff
set $kgm_fkmodmin = 0x00000000
set $kgm_kmodmax = 0x00000000
set $kgm_fkmodmax = 0xffffffff
set $kgm_pkmod = 0
set $kgm_pkmodst = 0
set $kgm_pkmoden = 0
define showkmodaddrint
    printf "0x%x" , $arg0
    if ((unsigned int)$arg0 >= (unsigned int)$kgm_pkmodst) && ((unsigned int)$arg0 <= (unsigned int)$kgm_pkmoden)
	set $kgm_off = ((unsigned int)$arg0 - (unsigned int)$kgm_pkmodst)
	printf " <%s + 0x%x>", $kgm_pkmod->name, $kgm_off
    else
        if  ((unsigned int)$arg0 <= (unsigned int)$kgm_fkmodmax) && ((unsigned int)$arg0 >= (unsigned int)$kgm_fkmodmin)
	    set $kgm_kmodp = (struct kmod_info *)kmod
	    while $kgm_kmodp
		set $kgm_kmod = *$kgm_kmodp
		if $kgm_kmod.address && ($kgm_kmod.address < $kgm_kmodmin)
		    set $kgm_kmodmin = $kgm_kmod.address
		end
		if ($kgm_kmod.address + $kgm_kmod.size) > $kgm_kmodmax
	    	    set $kgm_kmodmax = $kgm_kmod.address + $kgm_kmod.size
	    	end
	        set $kgm_off = ((unsigned int)$arg0 - (unsigned int)$kgm_kmod.address)
	        if ($kgm_kmod.address <= $arg0) && ($kgm_off <= $kgm_kmod.size)
		    printf " <%s + 0x%x>", $kgm_kmodp->name, $kgm_off
		    set $kgm_pkmod = $kgm_kmodp
		    set $kgm_pkmodst = $kgm_kmod.address
		    set $kgm_pkmoden = $kgm_pkmodst + $kgm_kmod.size
	    	    set $kgm_kmodp = 0
	        else
	    	    set $kgm_kmodp = $kgm_kmod.next
	        end
	    end
	    if !$kgm_pkmod
		set $kgm_fkmodmin = $kgm_kmodmin
		set $kgm_fkmodmax = $kgm_kmodmax
	    end
	end
    end
end

define showkmodaddr
    showkmodaddrint $arg0
end

document showkmodaddr
Syntax: (gdb) showkmodaddr <addr>
| Given an address, print the offset and name for the kmod containing it
end

define showkmod
    showkmodheader
    showkmodint $arg0
end
document showkmod
Syntax: (gdb) showkmod <kmod>
| Routine to print info about a kernel module
end

define showallkmods
    showkmodheader
    set $kgm_kmodp = (struct kmod_info *)kmod
    while $kgm_kmodp
	showkmodint $kgm_kmodp
    	set $kgm_kmodp = $kgm_kmodp->next
    end
end
document showallkmods
Syntax: (gdb) showallkmods
| Routine to print a summary listing of all the kernel modules
end

define showactheader
    printf "            thread      "
    printf "processor   pri  state  wait_queue  wait_event\n"
end


define showactint
	printf "            0x%08x  ", $arg0
	set $kgm_thread = *(struct thread *)$arg0
	printf "0x%08x  ", $kgm_thread.last_processor
	printf "%3d  ", $kgm_thread.sched_pri
	set $kgm_state = $kgm_thread.state
	if $kgm_state & 0x80
	    printf "I" 
	end
	if $kgm_state & 0x40
	    printf "P" 
	end
	if $kgm_state & 0x20
	    printf "A" 
	end
	if $kgm_state & 0x10
	    printf "H" 
	end
	if $kgm_state & 0x08
	    printf "U" 
	end
	if $kgm_state & 0x04
	    printf "R" 
	end
	if $kgm_state & 0x02
	    printf "S" 
	end
   	if $kgm_state & 0x01
	    printf "W\t" 
	    printf "0x%08x  ", $kgm_thread.wait_queue
	    	if (((unsigned)$kgm_thread.wait_event > (unsigned)sectPRELINKB) \
		    && ($arg1 != 2) && ($kgm_show_kmod_syms == 0))
			showkmodaddr $kgm_thread.wait_event
	        else
			output /a (unsigned) $kgm_thread.wait_event
		end
		if ($kgm_thread.uthread != 0)
		    set $kgm_uthread = (struct uthread *)$kgm_thread.uthread
		    if ($kgm_uthread->uu_wmesg != 0)
			printf " \"%s\"", $kgm_uthread->uu_wmesg
		    end
		end
	end
	if $arg1 != 0
	    if ($kgm_thread.kernel_stack != 0)
		if ($kgm_thread.reserved_stack != 0)
			printf "\n\t\treserved_stack=0x%08x", $kgm_thread.reserved_stack
		end
		printf "\n\t\tkernel_stack=0x%08x", $kgm_thread.kernel_stack
		if ($kgm_mtype == 18)
			set $mysp = $kgm_thread.machine.pcb->save_r1
		end
		if ($kgm_mtype == 7)
			set $kgm_statep = (struct x86_kernel_state32 *) \
				($kgm_thread->kernel_stack + 0x4000 \
				 - sizeof(struct x86_kernel_state32))
			set $mysp = $kgm_statep->k_ebp
		end
		if ($kgm_mtype == 12)
			if ($arg0 == $r9)
				set $mysp = $r7
			else
				set $kgm_statep = (struct arm_saved_state *)$kgm_thread.machine.kstackptr
				set $mysp = $kgm_statep->r[7]
			end
		end
		set $prevsp = $mysp - 16
		printf "\n\t\tstacktop=0x%08x", $mysp
		if ($kgm_mtype == 18)
			set $stkmask = 0xf
		else
			set $stkmask = 0x3
		end
		set $kgm_return = 0
	    	while ($mysp != 0) && (($mysp & $stkmask) == 0) \
		      && ($mysp != $prevsp) \
		      && ((((unsigned) $mysp ^ (unsigned) $prevsp) < 0x2000) \
		      || (((unsigned)$mysp < ((unsigned) ($kgm_thread->kernel_stack+0x4000))) \
		      && ((unsigned)$mysp > (unsigned) ($kgm_thread->kernel_stack))))
			printf "\n\t\t0x%08x  ", $mysp
			if ($kgm_mtype == 18)
				set $kgm_return = *($mysp + 8)
			end
			if ($kgm_mtype == 7)
				set $kgm_return = *($mysp + 4)
			end
			if ($kgm_mtype == 12)
				set $kgm_return = *($mysp + 4)
			end
			if (((unsigned) $kgm_return > (unsigned) sectPRELINKB) \
			    && ($kgm_show_kmod_syms == 0))
				showkmodaddr $kgm_return
			else
				output /a (unsigned) $kgm_return
			end
			set $prevsp = $mysp
			set $mysp = * $mysp
		end
		set $kgm_return = 0
		printf "\n\t\tstackbottom=0x%08x", $prevsp
	    else
		printf "\n\t\t\tcontinuation="
		output /a (unsigned) $kgm_thread.continuation
	    end
	    printf "\n"
	else
	    printf "\n"
	end
end	    

define showact
    showactheader
    showactint $arg0 0
end
document showact
Syntax: (gdb) showact <activation> 
| Routine to print out the state of a specific thread.
end


define showactstack
    showactheader
    showactint $arg0 1
end
document showactstack
Syntax: (gdb) showactstack <activation> 
| Routine to print out the stack of a specific thread.
end


define showallthreads
    set $kgm_head_taskp = &tasks
    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
    while $kgm_taskp != $kgm_head_taskp
        showtaskheader
	showtaskint $kgm_taskp
	showactheader
	set $kgm_head_actp = &($kgm_taskp->threads)
        set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
	while $kgm_actp != $kgm_head_actp
	    showactint $kgm_actp 0
  	    set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
        end
	printf "\n"
    	set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
    end
end
document showallthreads
Syntax: (gdb) showallthreads
| Routine to print out info about all threads in the system.
end

define showcurrentthreads
set $kgm_prp = (struct processor *)processor_list
    while $kgm_prp != 0
    	printf "Processor 0x%08x State %d (cpu_id %x)\n", $kgm_prp, ($kgm_prp)->state, ($kgm_prp)->cpu_num
	if ($kgm_prp)->active_thread != 0
	    set $kgm_actp = ($kgm_prp)->active_thread
	    showtaskheader
	    showtaskint ($kgm_actp)->task
	    showactheader
	    showactint $kgm_actp 0
	    printf "\n"
	end
	set $kgm_prp = ($kgm_prp)->processor_list
    end
end
document showcurrentthreads
Syntax: (gdb) showcurrentthreads
| Routine to print out info about the thread running on each cpu.
end

set $decode_wait_events = 0
define showallstacks
    set $kgm_head_taskp = &tasks
    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
    while $kgm_taskp != $kgm_head_taskp
        showtaskheader
	showtaskint $kgm_taskp
	set $kgm_head_actp = &($kgm_taskp->threads)
        set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
	while $kgm_actp != $kgm_head_actp
	    showactheader
	    if ($decode_wait_events > 0)
	       showactint $kgm_actp 1
	    else
	       showactint $kgm_actp 2
	    end
  	    set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
        end
	printf "\n"
    	set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
    end
end

document showallstacks
Syntax: (gdb) showallstacks
| Routine to print out the stack for each thread in the system.
| If the variable $decode_wait_events is non-zero, the routine attempts to
| interpret thread wait_events as kernel module offsets, which can add to
| processing time.
end

define showcurrentstacks
set $kgm_prp = processor_list
    while $kgm_prp != 0
    	printf "Processor 0x%08x State %d (cpu_id %x)\n", $kgm_prp, ($kgm_prp)->state, ($kgm_prp)->cpu_num
	if ($kgm_prp)->active_thread != 0
	    set $kgm_actp = ($kgm_prp)->active_thread
	    showtaskheader
	    showtaskint ($kgm_actp)->task
	    showactheader
	    showactint $kgm_actp 1
	    printf "\n"
	end
	set $kgm_prp = ($kgm_prp)->processor_list
    end
end

document showcurrentstacks
Syntax: (gdb) showcurrentstacks
| Routine to print out the thread running on each cpu (incl. its stack)
end

define showwaiterheader
    printf "waiters     activation  "
    printf "thread      pri  state  wait_queue  wait_event\n"
end

define showwaitqwaiters
    set $kgm_w_waitqp = (struct wait_queue *)$arg0
    set $kgm_w_linksp = &($kgm_w_waitqp->wq_queue)
    set $kgm_w_wqe = (struct wait_queue_element *)$kgm_w_linksp->next
    set $kgm_w_found = 0
    while ( (queue_entry_t)$kgm_w_wqe != (queue_entry_t)$kgm_w_linksp)
	if ($kgm_w_wqe->wqe_type != &_wait_queue_link)
		if !$kgm_w_found
			set $kgm_w_found = 1
			showwaiterheader
		end
		set $kgm_w_shuttle = (struct thread *)$kgm_w_wqe
		showactint $kgm_w_shuttle 0
	end	
	set $kgm_w_wqe = (struct wait_queue_element *)$kgm_w_wqe->wqe_links.next
    end
end

define showwaitqwaitercount
    set $kgm_wc_waitqp = (struct wait_queue *)$arg0
    set $kgm_wc_linksp = &($kgm_wc_waitqp->wq_queue)
    set $kgm_wc_wqe = (struct wait_queue_element *)$kgm_wc_linksp->next
    set $kgm_wc_count = 0
    while ( (queue_entry_t)$kgm_wc_wqe != (queue_entry_t)$kgm_wc_linksp)
	if ($kgm_wc_wqe->wqe_type != &_wait_queue_link)
        	set $kgm_wc_count = $kgm_wc_count + 1
	end
        set $kgm_wc_wqe = (struct wait_queue_element *)$kgm_wc_wqe->wqe_links.next
    end
    printf "0x%08x  ", $kgm_wc_count
end

define showwaitqmembercount
    set $kgm_mc_waitqsetp = (struct wait_queue_set *)$arg0
    set $kgm_mc_setlinksp = &($kgm_mc_waitqsetp->wqs_setlinks)
    set $kgm_mc_wql = (struct wait_queue_link *)$kgm_mc_setlinksp->next
    set $kgm_mc_count = 0
    while ( (queue_entry_t)$kgm_mc_wql != (queue_entry_t)$kgm_mc_setlinksp)
        set $kgm_mc_count = $kgm_mc_count + 1
        set $kgm_mc_wql = (struct wait_queue_link *)$kgm_mc_wql->wql_setlinks.next
    end
    printf "0x%08x  ", $kgm_mc_count
end

    
define showwaitqmemberheader
    printf "set-members wait_queue  interlock   "
    printf "pol  type   member_cnt  waiter_cnt\n"
end

define showwaitqmemberint
    set $kgm_m_waitqp = (struct wait_queue *)$arg0
    printf "            0x%08x  ", $kgm_m_waitqp
    printf "0x%08x  ", $kgm_m_waitqp->wq_interlock.lock_data
    if ($kgm_m_waitqp->wq_fifo)
        printf "Fifo "
    else
	printf "Prio "
    end
    if ($kgm_m_waitqp->wq_type == 0xf1d1)
	printf "Set    "
	showwaitqmembercount $kgm_m_waitqp
    else
	printf "Que    0x00000000  "
    end
    showwaitqwaitercount $kgm_m_waitqp
    printf "\n"
end


define showwaitqmemberofheader
    printf "member-of   wait_queue  interlock   "
    printf "pol  type   member_cnt  waiter_cnt\n"
end

define showwaitqmemberof
    set $kgm_mo_waitqp = (struct wait_queue *)$arg0
    set $kgm_mo_linksp = &($kgm_mo_waitqp->wq_queue)
    set $kgm_mo_wqe = (struct wait_queue_element *)$kgm_mo_linksp->next
    set $kgm_mo_found = 0
    while ( (queue_entry_t)$kgm_mo_wqe != (queue_entry_t)$kgm_mo_linksp)
	if ($kgm_mo_wqe->wqe_type == &_wait_queue_link)
		if !$kgm_mo_found
			set $kgm_mo_found = 1
			showwaitqmemberofheader
		end
		set $kgm_mo_wqlp = (struct wait_queue_link *)$kgm_mo_wqe
		set $kgm_mo_wqsetp = (struct wait_queue *)($kgm_mo_wqlp->wql_setqueue)
		showwaitqmemberint $kgm_mo_wqsetp
	end	
	set $kgm_mo_wqe = (struct wait_queue_element *)$kgm_mo_wqe->wqe_links.next
    end
end

define showwaitqmembers
    set $kgm_ms_waitqsetp = (struct wait_queue_set *)$arg0
    set $kgm_ms_setlinksp = &($kgm_ms_waitqsetp->wqs_setlinks)
    set $kgm_ms_wql = (struct wait_queue_link *)$kgm_ms_setlinksp->next
    set $kgm_ms_found = 0
    while ( (queue_entry_t)$kgm_ms_wql != (queue_entry_t)$kgm_ms_setlinksp)
        set $kgm_ms_waitqp = $kgm_ms_wql->wql_element.wqe_queue
        if !$kgm_ms_found  
	    showwaitqmemberheader
	    set $kgm_ms_found = 1
        end
        showwaitqmemberint $kgm_ms_waitqp
	set $kgm_ms_wql = (struct wait_queue_link *)$kgm_ms_wql->wql_setlinks.next
    end
end

define showwaitqheader
    printf "wait_queue  ref_count   interlock   "
    printf "pol  type   member_cnt  waiter_cnt\n"
end

define showwaitqint
    set $kgm_waitqp = (struct wait_queue *)$arg0
    printf "0x%08x  ", $kgm_waitqp
    if ($kgm_waitqp->wq_type == 0xf1d1)
	printf "0x%08x  ", ((struct wait_queue_set *)$kgm_waitqp)->wqs_refcount
    else
	printf "0x00000000  "
    end
    printf "0x%08x  ", $kgm_waitqp->wq_interlock.lock_data
    if ($kgm_waitqp->wq_fifo)
        printf "Fifo "
    else
	printf "Prio "
    end
    if ($kgm_waitqp->wq_type == 0xf1d1)
	printf "Set    "
	showwaitqmembercount $kgm_waitqp
    else
	printf "Que    0x00000000  "
    end
    showwaitqwaitercount $kgm_waitqp
    printf "\n"
end

define showwaitq
    set $kgm_waitq1p = (wait_queue_t)$arg0
    showwaitqheader
    showwaitqint $kgm_waitq1p	
    if ($kgm_waitq1p->wq_type == 0xf1d1)
	showwaitqmembers $kgm_waitq1p
    else
    	showwaitqmemberof $kgm_waitq1p
    end
    showwaitqwaiters $kgm_waitq1p
end

define showmapheader
    printf "vm_map      pmap        vm_size    "
    printf "#ents rpage  hint        first_free\n"
end

define showvmeheader
    printf "    entry       start       "
    printf "        prot #page  object      offset\n"
end

define showvmint
    set $kgm_mapp = (vm_map_t)$arg0
    set $kgm_map = *$kgm_mapp
    printf "0x%08x  ", $arg0
    printf "0x%08x  ", $kgm_map.pmap
    printf "0x%08x  ", $kgm_map.size
    printf "%3d  ", $kgm_map.hdr.nentries
    if $kgm_map.pmap
	printf "%5d  ", $kgm_map.pmap->stats.resident_count
    else
	printf "<n/a>  "
    end
    printf "0x%08x  ", $kgm_map.hint
    printf "0x%08x\n", $kgm_map.first_free
    if $arg1 != 0
	showvmeheader	
	set $kgm_head_vmep = &($kgm_mapp->hdr.links)
	set $kgm_vmep = $kgm_map.hdr.links.next
	while (($kgm_vmep != 0) && ($kgm_vmep != $kgm_head_vmep))
	    set $kgm_vme = *$kgm_vmep
	    printf "    0x%08x  ", $kgm_vmep
	    printf "0x%016llx  ", $kgm_vme.links.start
	    printf "%1x", $kgm_vme.protection
	    printf "%1x", $kgm_vme.max_protection
	    if $kgm_vme.inheritance == 0x0
		printf "S"
	    end
	    if $kgm_vme.inheritance == 0x1
		printf "C"
	    end
	    if $kgm_vme.inheritance == 0x2
		printf "-"
	    end
	    if $kgm_vme.inheritance == 0x3
		printf "D"
	    end
	    if $kgm_vme.is_sub_map
		printf "s "
	    else
		if $kgm_vme.needs_copy
		    printf "n "
		else
		    printf "  "
		end
	    end
	    printf "%5d  ",($kgm_vme.links.end - $kgm_vme.links.start) >> 12
	    printf "0x%08x  ", $kgm_vme.object.vm_object
	    printf "0x%016llx\n", $kgm_vme.offset
  	    set $kgm_vmep = $kgm_vme.links.next
        end
    end
    printf "\n"
end


define showmapvme
	showmapheader
	showvmint $arg0 1
end
document showmapvme
Syntax: (gdb) showmapvme <vm_map>
| Routine to print out a summary listing of all the entries in a vm_map
end


define showmap
	showmapheader
	showvmint $arg0 0
end
document showmap
Syntax: (gdb) showmap <vm_map>
| Routine to print out info about the specified vm_map
end

define showallvm
    set $kgm_head_taskp = &tasks
    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
    while $kgm_taskp != $kgm_head_taskp
        showtaskheader
	showmapheader
	showtaskint $kgm_taskp
	showvmint $kgm_taskp->map 0
    	set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
    end
end
document showallvm
Syntax: (gdb) showallvm
| Routine to print a summary listing of all the vm maps
end


define showallvme
    set $kgm_head_taskp = &tasks
    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
    while $kgm_taskp != $kgm_head_taskp
        showtaskheader
	showmapheader
	showtaskint $kgm_taskp
	showvmint $kgm_taskp->map 1
    	set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
    end
end
document showallvme
Syntax: (gdb) showallvme
| Routine to print a summary listing of all the vm map entries
end


define showipcheader
    printf "ipc_space   is_table    table_next "
    printf "flags tsize  splaytree   splaybase\n"
end

define showipceheader
    printf "            name        object      "
    printf "rite urefs  destname    destination\n"
end

define showipceint
    set $kgm_ie = *(ipc_entry_t)$arg0
    printf "            0x%08x  ", $arg1
    printf "0x%08x  ", $kgm_ie.ie_object
    if $kgm_ie.ie_bits & 0x00100000
	printf "Dead "
        printf "%5d\n", $kgm_ie.ie_bits & 0xffff
    else
        if $kgm_ie.ie_bits & 0x00080000
	    printf "SET  "
            printf "%5d\n", $kgm_ie.ie_bits & 0xffff
        else
            if $kgm_ie.ie_bits & 0x00010000
	        if $kgm_ie.ie_bits & 0x00020000
	            printf " SR"
	        else
	            printf "  S"
	        end
            else
	        if $kgm_ie.ie_bits & 0x00020000
	           printf "  R"
	        end
            end
            if $kgm_ie.ie_bits & 0x00040000
	        printf "  O"
            end
            if $kgm_ie.index.request
	        printf "n"
            else
                printf " "
            end
            if $kgm_ie.ie_bits & 0x00800000
		printf "c"
    	    else
		printf " "
    	    end
            printf "%5d  ", $kgm_ie.ie_bits & 0xffff
            showportdest $kgm_ie.ie_object
        end
    end
end

define showipcint
    set $kgm_isp = (ipc_space_t)$arg0
    set $kgm_is = *$kgm_isp
    printf "0x%08x  ", $arg0
    printf "0x%08x  ", $kgm_is.is_table
    printf "0x%08x  ", $kgm_is.is_table_next
    if $kgm_is.is_growing != 0
	printf "G"
    else
	printf " "
    end
    if $kgm_is.is_fast != 0
	printf "F"
    else
	printf " "
    end
    if $kgm_is.is_active != 0
	printf "A  "
    else
	printf "   "
    end
    printf "%5d  ", $kgm_is.is_table_size
    printf "0x%08x  ", $kgm_is.is_tree_total
    printf "0x%08x\n", &$kgm_isp->is_tree
    if $arg1 != 0
	showipceheader
	set $kgm_iindex = 0
	set $kgm_iep = $kgm_is.is_table
	set $kgm_destspacep = (ipc_space_t)0
        while ( $kgm_iindex < $kgm_is.is_table_size )
	    set $kgm_ie = *$kgm_iep
	    if $kgm_ie.ie_bits & 0x001f0000
		set $kgm_name = (($kgm_iindex << 8)|($kgm_ie.ie_bits >> 24))
		showipceint $kgm_iep $kgm_name
	    end
	    set $kgm_iindex = $kgm_iindex + 1
	    set $kgm_iep = &($kgm_is.is_table[$kgm_iindex])
	end
	if $kgm_is.is_tree_total
	    printf "Still need to write tree traversal\n"
	end
    end
    printf "\n"
end


define showipc
	set $kgm_isp = (ipc_space_t)$arg0
        showipcheader
	showipcint $kgm_isp 0
end
document showipc
Syntax: (gdb) showipc <ipc_space>
| Routine to print the status of the specified ipc space
end

define showrights
	set $kgm_isp = (ipc_space_t)$arg0
        showipcheader
	showipcint $kgm_isp 1
end
document showrights
Syntax: (gdb) showrights <ipc_space>
| Routine to print a summary list of all the rights in a specified ipc space
end


define showtaskipc
	set $kgm_taskp = (task_t)$arg0
	showtaskheader
    showipcheader
	showtaskint $kgm_taskp
	showipcint $kgm_taskp->itk_space 0
end
document showtaskipc
Syntax: (gdb) showtaskipc <task>
| Routine to print info about the ipc space for a task
end


define showtaskrights
	set $kgm_taskp = (task_t)$arg0
	showtaskheader
        showipcheader
	showtaskint $kgm_taskp
	showipcint $kgm_taskp->itk_space 1
end
document showtaskrights
Syntax: (gdb) showtaskrights <task>
| Routine to print info about the ipc rights for a task
end

define showallipc
    set $kgm_head_taskp = &tasks
    set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next)
    while $kgm_cur_taskp != $kgm_head_taskp
        showtaskheader
        showipcheader
	showtaskint $kgm_cur_taskp
	showipcint $kgm_cur_taskp->itk_space 0
    	set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->tasks.next)
    end
end
document showallipc
Syntax: (gdb) showallipc
| Routine to print a summary listing of all the ipc spaces
end


define showallrights
    set $kgm_head_taskp = &tasks
    set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next)
    while $kgm_cur_taskp != $kgm_head_taskp
        showtaskheader
        showipcheader
	showtaskint $kgm_cur_taskp
	showipcint $kgm_cur_taskp->itk_space 1
    	set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->tasks.next)
    end
end
document showallrights
Syntax: (gdb) showallrights
| Routine to print a summary listing of all the ipc rights
end


define showtaskvm
	set $kgm_taskp = (task_t)$arg0
	showtaskheader
	showmapheader
	showtaskint $kgm_taskp
	showvmint $kgm_taskp->map 0
end
document showtaskvm
Syntax: (gdb) showtaskvm <task>
| Routine to print out info about a task's vm_map
end

define showtaskvme
	set $kgm_taskp = (task_t)$arg0
	showtaskheader
	showmapheader
	showtaskint $kgm_taskp
	showvmint $kgm_taskp->map 1
end
document showtaskvme
Syntax: (gdb) showtaskvme <task>
| Routine to print out info about a task's vm_map_entries
end


define showtaskheader
    printf "task        vm_map      ipc_space  #acts  "
    showprocheader
end


define showtaskint
    set $kgm_task = *(struct task *)$arg0
    printf "0x%08x  ", $arg0
    printf "0x%08x  ", $kgm_task.map
    printf "0x%08x  ", $kgm_task.itk_space
    printf "%3d  ", $kgm_task.thread_count
    showprocint $kgm_task.bsd_info
end

define showtask
    showtaskheader
    showtaskint $arg0
end
document showtask
Syntax (gdb) showtask <task>
| Routine to print out info about a task.
end


define showtaskthreads
    showtaskheader
    set $kgm_taskp = (struct task *)$arg0
    showtaskint $kgm_taskp
    showactheader
    set $kgm_head_actp = &($kgm_taskp->threads)
    set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
    while $kgm_actp != $kgm_head_actp
	showactint $kgm_actp 0
    	set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
    end
end
document showtaskthreads
Syntax: (gdb) showtaskthreads <task>
| Routine to print info about the threads in a task.
end


define showtaskstacks
    showtaskheader
    set $kgm_taskp = (struct task *)$arg0
    showtaskint $kgm_taskp
    set $kgm_head_actp = &($kgm_taskp->threads)
    set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
    while $kgm_actp != $kgm_head_actp
        showactheader
	showactint $kgm_actp 1
    	set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
    end
end
document showtaskstacks
Syntax: (gdb) showtaskstacks <task>
| Routine to print out the stack for each thread in a task.
end


define showalltasks
    showtaskheader
    set $kgm_head_taskp = &tasks
    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
    while $kgm_taskp != $kgm_head_taskp
	showtaskint $kgm_taskp
    	set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
    end
end
document showalltasks
Syntax: (gdb) showalltasks
| Routine to print a summary listing of all the tasks
end


define showprocheader
    printf " pid  proc        command\n"
end

define showprocint
    set $kgm_procp = (struct proc *)$arg0
    if $kgm_procp != 0
        printf "%5d  ", $kgm_procp->p_pid
	printf "0x%08x  ", $kgm_procp
	printf "%s\n", $kgm_procp->p_comm
    else
	printf "  *0*  0x00000000  --\n"
    end
end

define showpid
    showtaskheader
    set $kgm_head_taskp = &tasks
    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
    while $kgm_taskp != $kgm_head_taskp
	set $kgm_procp = (struct proc *)$kgm_taskp->bsd_info
	if (($kgm_procp != 0) && ($kgm_procp->p_pid == $arg0))
	    showtaskint $kgm_taskp
	    set $kgm_taskp = $kgm_head_taskp
	else
    	    set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
	end
    end
end
document showpid
Syntax: (gdb) showpid <pid>
| Routine to print a single process by pid
end

define showproc
    showtaskheader
    set $kgm_procp = (struct proc *)$arg0
    showtaskint $kgm_procp->task $arg1 $arg2
end


define kdb
    set switch_debugger=1
    continue
end
document kdb
| kdb - Switch to the inline kernel debugger
|
| usage: kdb
|
| The kdb macro allows you to invoke the inline kernel debugger.
end

define showpsetheader
    printf "portset     waitqueue   recvname    "
    printf "flags refs  recvname    process\n"
end

define showportheader
    printf "port        mqueue      recvname    "
    printf "flags refs  recvname    process\n"
end

define showportmemberheader
    printf "members     port        recvname    "
    printf "flags refs  mqueue      msgcount\n"
end

define showkmsgheader
    printf "messages    kmsg        size        "
    printf "disp msgid  remote-port local-port\n"
end

define showkmsgint
    printf "            0x%08x  ", $arg0
    set $kgm_kmsgh = ((ipc_kmsg_t)$arg0)->ikm_header
    printf "0x%08x  ", $kgm_kmsgh.msgh_size
    if (($kgm_kmsgh.msgh_bits & 0xff) == 19)
	printf "rC"
    else
	printf "rM"
    end
    if (($kgm_kmsgh.msgh_bits & 0xff00) == (19 < 8))
	printf "lC"
    else
	printf "lM"
    end
    if ($kgm_kmsgh.msgh_bits & 0xf0000000)
	printf "c"
    else
	printf "s"
    end
    printf "%5d  ", $kgm_kmsgh.msgh_id
    printf "0x%08x  ", $kgm_kmsgh.msgh_remote_port
    printf "0x%08x\n", $kgm_kmsgh.msgh_local_port
end



define showkobject
    set $kgm_portp = (struct ipc_port *)$arg0
    printf "0x%08x  kobject(", $kgm_portp->ip_kobject
    set $kgm_kotype = ($kgm_portp->ip_object.io_bits & 0x00000fff)
    if ($kgm_kotype == 1)
	printf "THREAD"
    end
    if ($kgm_kotype == 2)
	printf "TASK"
    end
    if ($kgm_kotype == 3)
	printf "HOST"
    end
    if ($kgm_kotype == 4)
	printf "HOST_PRIV"
    end
    if ($kgm_kotype == 5)
	printf "PROCESSOR"
    end
    if ($kgm_kotype == 6)
	printf "PSET"
    end
    if ($kgm_kotype == 7)
	printf "PSET_NAME"
    end
    if ($kgm_kotype == 8)
	printf "TIMER"
    end
    if ($kgm_kotype == 9)
	printf "PAGER_REQ"
    end
    if ($kgm_kotype == 10)
	printf "DEVICE"
    end
    if ($kgm_kotype == 11)
	printf "XMM_OBJECT"
    end
    if ($kgm_kotype == 12)
	printf "XMM_PAGER"
    end
    if ($kgm_kotype == 13)
	printf "XMM_KERNEL"
    end
    if ($kgm_kotype == 14)
	printf "XMM_REPLY"
    end
    if ($kgm_kotype == 15)
	printf "NOTDEF 15"
    end
    if ($kgm_kotype == 16)
	printf "NOTDEF 16"
    end
    if ($kgm_kotype == 17)
	printf "HOST_SEC"
    end
    if ($kgm_kotype == 18)
	printf "LEDGER"
    end
    if ($kgm_kotype == 19)
	printf "MASTER_DEV"
    end
    if ($kgm_kotype == 20)
	printf "ACTIVATION"
    end
    if ($kgm_kotype == 21)
	printf "SUBSYSTEM"
    end
    if ($kgm_kotype == 22)
	printf "IO_DONE_QUE"
    end
    if ($kgm_kotype == 23)
	printf "SEMAPHORE"
    end
    if ($kgm_kotype == 24)
	printf "LOCK_SET"
    end
    if ($kgm_kotype == 25)
	printf "CLOCK"
    end
    if ($kgm_kotype == 26)
	printf "CLOCK_CTRL"
    end
    if ($kgm_kotype == 27)
	printf "IOKIT_SPARE"
    end
    if ($kgm_kotype == 28)
	printf "NAMED_MEM"
    end
    if ($kgm_kotype == 29)
	printf "IOKIT_CON"
    end
    if ($kgm_kotype == 30)
	printf "IOKIT_OBJ"
    end
    if ($kgm_kotype == 31)
	printf "UPL"
    end
    printf ")\n"
end

define showportdestproc
    set $kgm_portp = (struct ipc_port *)$arg0
    set $kgm_spacep = $kgm_portp->data.receiver
#   check against the previous cached value - this is slow
    if ($kgm_spacep != $kgm_destspacep)
	set $kgm_destprocp = (struct proc *)0
        set $kgm_head_taskp = &tasks
        set $kgm_desttaskp = (struct task *)($kgm_head_taskp->next)
        while (($kgm_destprocp == 0) && ($kgm_desttaskp != $kgm_head_taskp))
	    set $kgm_destspacep = $kgm_desttaskp->itk_space
	    if ($kgm_destspacep == $kgm_spacep)
	       set $kgm_destprocp = (struct proc *)$kgm_desttaskp->bsd_info
	    else
    	       set $kgm_desttaskp = (struct task *)($kgm_desttaskp->tasks.next)
            end
        end
    end
    if $kgm_destprocp != 0
       printf "%s(%d)\n", $kgm_destprocp->p_comm, $kgm_destprocp->p_pid
    else
       printf "task 0x%08x\n", $kgm_desttaskp
    end
end

define showportdest
    set $kgm_portp = (struct ipc_port *)$arg0
    set $kgm_spacep = $kgm_portp->data.receiver
    if ($kgm_spacep == ipc_space_kernel)
	showkobject $kgm_portp
    else
	if ($kgm_portp->ip_object.io_bits & 0x80000000)
	    printf "0x%08x  ", $kgm_portp->ip_object.io_receiver_name
	    showportdestproc $kgm_portp
	else
	    printf "0x%08x  inactive-port\n", $kgm_portp
	end
    end
end

define showportmember
    printf "            0x%08x  ", $arg0
    set $kgm_portp = (struct ipc_port *)$arg0
    printf "0x%08x  ", $kgm_portp->ip_object.io_receiver_name
    if ($kgm_portp->ip_object.io_bits & 0x80000000)
	printf "A"
    else
	printf " "
    end
    if ($kgm_portp->ip_object.io_bits & 0x7fff0000)
	printf "Set "
    else
	printf "Port"
    end
    printf "%5d  ", $kgm_portp->ip_object.io_references
    printf "0x%08x  ", &($kgm_portp->ip_messages)
    printf "0x%08x\n", $kgm_portp->ip_messages.data.port.msgcount
end

define showportint
    printf "0x%08x  ", $arg0
    set $kgm_portp = (struct ipc_port *)$arg0
    printf "0x%08x  ", &($kgm_portp->ip_messages)
    printf "0x%08x  ", $kgm_portp->ip_object.io_receiver_name
    if ($kgm_portp->ip_object.io_bits & 0x80000000)
	printf "A"
    else
	printf "D"
    end
    printf "Port"
    printf "%5d  ", $kgm_portp->ip_object.io_references
    set $kgm_destspacep = (struct ipc_space *)0
    showportdest $kgm_portp
    set $kgm_kmsgp = (ipc_kmsg_t)$kgm_portp->ip_messages.data.port.messages.ikmq_base
    if $arg1 && $kgm_kmsgp
	showkmsgheader
	showkmsgint $kgm_kmsgp
	set $kgm_kmsgheadp = $kgm_kmsgp
	set $kgm_kmsgp = $kgm_kmsgp->ikm_next
	while $kgm_kmsgp != $kgm_kmsgheadp
	    showkmsgint $kgm_kmsgp
	    set $kgm_kmsgp = $kgm_kmsgp->ikm_next
        end
    end
end

define showpsetint
    printf "0x%08x  ", $arg0
    set $kgm_psetp = (struct ipc_pset *)$arg0
    printf "0x%08x  ", &($kgm_psetp->ips_messages)
    printf "0x%08x  ", $kgm_psetp->ips_object.io_receiver_name
    if ($kgm_psetp->ips_object.io_bits & 0x80000000)
	printf "A"
    else
	printf "D"
    end
    printf "Set "
    printf "%5d  ", $kgm_psetp->ips_object.io_references
    printf "0x%08x  ", $kgm_psetp->ips_object.io_receiver_name
    set $kgm_setlinksp = &($kgm_psetp->ips_messages.data.set_queue.wqs_setlinks)
    set $kgm_wql = (struct wait_queue_link *)$kgm_setlinksp->next
    set $kgm_found = 0
    while ( (queue_entry_t)$kgm_wql != (queue_entry_t)$kgm_setlinksp)
        set $kgm_portp = (struct ipc_port *)((int)($kgm_wql->wql_element->wqe_queue) - ((int)$kgm_portoff))
	if !$kgm_found  
	    set $kgm_destspacep = (struct ipc_space *)0
	    showportdestproc $kgm_portp
	    showportmemberheader
	    set $kgm_found = 1
	end
	showportmember $kgm_portp 0
	set $kgm_wql = (struct wait_queue_link *)$kgm_wql->wql_setlinks.next
    end
    if !$kgm_found
	printf "--n/e--\n"
    end
end

define showpset
    showpsetheader
    showpsetint $arg0 1
end

define showport
    showportheader
    showportint $arg0 1
end

define showipcobject
    set $kgm_object = (ipc_object_t)$arg0
    if ($kgm_objectp->io_bits & 0x7fff0000)
	showpset $kgm_objectp
    else
	showport $kgm_objectp
    end
end

define showmqueue
    set $kgm_mqueue = *(struct ipc_mqueue *)$arg0
    set $kgm_psetoff = &(((struct ipc_pset *)0)->ips_messages)
    set $kgm_portoff = &(((struct ipc_port *)0)->ip_messages)
    if ($kgm_mqueue.data.set_queue.wqs_wait_queue.wq_type == 0xf1d1)
	set $kgm_pset = (((int)$arg0) - ((int)$kgm_psetoff))
        showpsetheader
	showpsetint $kgm_pset 1
    end
    if ($kgm_mqueue.data.set_queue.wqs_wait_queue.wq_type == 0xf1d0)
	showportheader
	set $kgm_port = (((int)$arg0) - ((int)$kgm_portoff))
	showportint $kgm_port 1
    end
end

define zprint_one
set $kgm_zone = (struct zone *)$arg0

printf "0x%08x ", $kgm_zone
printf "%8d ",$kgm_zone->count
printf "%8x ",$kgm_zone->cur_size
printf "%8x ",$kgm_zone->max_size
printf "%6d ",$kgm_zone->elem_size
printf "%8x ",$kgm_zone->alloc_size
printf "%s ",$kgm_zone->zone_name

if ($kgm_zone->exhaustible)
	printf "H"
end
if ($kgm_zone->collectable)
	printf "C"
end
if ($kgm_zone->expandable)
	printf "X"
end
printf "\n"
end


define zprint
printf "ZONE          COUNT   TOT_SZ   MAX_SZ ELT_SZ ALLOC_SZ NAME\n"
set $kgm_zone_ptr = (struct zone *)first_zone
while ($kgm_zone_ptr != 0)
	zprint_one $kgm_zone_ptr
	set $kgm_zone_ptr = $kgm_zone_ptr->next_zone
end
printf "\n"
end
document zprint
Syntax: (gdb) zprint
| Routine to print a summary listing of all the kernel zones
end

define showmtxgrp
set $kgm_mtxgrp = (struct _lck_grp_ *)$arg0

if ($kgm_mtxgrp->lck_grp_mtxcnt)
printf "0x%08x ", $kgm_mtxgrp
printf "%8d ",$kgm_mtxgrp->lck_grp_mtxcnt
printf "%12u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_util_cnt
printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_miss_cnt
printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_wait_cnt
printf "%s ",&$kgm_mtxgrp->lck_grp_name
printf "\n"
end
end


define showallmtx
printf "LCK GROUP       CNT         UTIL     MISS     WAIT NAME\n"
set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)&lck_grp_queue
set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)$kgm_mtxgrp_ptr->lck_grp_link.next
while ($kgm_mtxgrp_ptr != (struct _lck_grp_ *)&lck_grp_queue)
	showmtxgrp $kgm_mtxgrp_ptr
	set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)$kgm_mtxgrp_ptr->lck_grp_link.next
end
printf "\n"
end
document showallmtx
Syntax: (gdb) showallmtx
| Routine to print a summary listing of all mutexes
end

define showrwlckgrp
set $kgm_rwlckgrp = (struct _lck_grp_ *)$arg0

if ($kgm_rwlckgrp->lck_grp_rwcnt)
printf "0x%08x ", $kgm_rwlckgrp
printf "%8d ",$kgm_rwlckgrp->lck_grp_rwcnt
printf "%12u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_util_cnt
printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_miss_cnt
printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_wait_cnt
printf "%s ",&$kgm_rwlckgrp->lck_grp_name
printf "\n"
end
end


define showallrwlck
printf "LCK GROUP       CNT         UTIL     MISS     WAIT NAME\n"
set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)&lck_grp_queue
set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)$kgm_rwlckgrp_ptr->lck_grp_link.next
while ($kgm_rwlckgrp_ptr != (struct _lck_grp_ *)&lck_grp_queue)
	showrwlckgrp $kgm_rwlckgrp_ptr
	set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)$kgm_rwlckgrp_ptr->lck_grp_link.next
end
printf "\n"
end
document showallrwlck
Syntax: (gdb) showallrwlck
| Routine to print a summary listing of all read/writer locks
end

set $kdp_act_counter = 0

set $r0_save	= 0
set $r1_save	= 0
set $r2_save	= 0
set $r3_save	= 0
set $r4_save	= 0
set $r5_save	= 0
set $r6_save	= 0
set $r7_save	= 0
set $r8_save	= 0
set $r9_save	= 0
set $r10_save	= 0
set $r11_save	= 0
set $r12_save	= 0
set $sp_save	= 0
set $lr_save	= 0
set $pc_save	= 0

define showcontext_int
	echo Context switched, current instruction pointer: 
	output/a $pc
	echo \n
end

define switchtoact
	set $newact = (struct thread *) $arg0
	select 0
	if ($newact->kernel_stack == 0)
		echo This activation does not have a stack.\n
		echo continuation:
		output/a (unsigned) $newact.continuation
		echo \n
	else
	if ($kgm_mtype == 18)
		if ($kdp_act_counter == 0)
			set $kdpstate = (struct savearea *) kdp.saved_state
		end
		set $kdp_act_counter = $kdp_act_counter + 1
		set (struct savearea *) kdp.saved_state=$newact->machine->pcb
		flushregs
		flushstack
		set $pc=$newact->machine->pcb.save_srr0
		update
	end
	if ($kgm_mtype == 7)
		set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state
		if ($kdp_act_counter == 0)
			set $kdpstate = *($kdpstatep)
		end	
		set $kdp_act_counter = $kdp_act_counter + 1

		set $kgm_statep = (struct x86_kernel_state32 *) \
					($newact->kernel_stack + 0x4000 \
					 - sizeof(struct x86_kernel_state32))
		set $kdpstatep->ebx = $kgm_statep->k_ebx 
		set $kdpstatep->ebp = $kgm_statep->k_ebp 
		set $kdpstatep->edi = $kgm_statep->k_edi 
		set $kdpstatep->esi = $kgm_statep->k_esi 
		set $kdpstatep->eip = $kgm_statep->k_eip 
		flushregs
		flushstack
		set $pc = $kgm_statep->k_eip
		update
	end
	if ($kgm_mtype == 12)
		set $r0_save   = $r0
		set $r1_save   = $r1
		set $r2_save   = $r2
		set $r3_save   = $r3
		set $r4_save   = $r4
		set $r5_save   = $r5
		set $r6_save   = $r6
		set $r7_save   = $r7
		set $r8_save   = $r8
		set $r9_save   = $r9
		set $r10_save  = $r10
		set $r11_save  = $r11
		set $r12_save  = $r12
		set $sp_save   = $sp
		set $lr_save   = $lr
		set $pc_save   = $pc
		set $pc_ctx = load_reg+8
		set $kgm_statep = (struct arm_saved_state *)((struct thread*)$arg0)->machine.kstackptr
		set $r0 =  $kgm_statep->r[0]
		set $r1 =  $kgm_statep->r[1]
		set $r2 =  $kgm_statep->r[2]
		set $r3 =  $kgm_statep->r[3]
		set $r4 =  $kgm_statep->r[4]
		set $r5 =  $kgm_statep->r[5]
		set $r6 =  $kgm_statep->r[6]
		set $r8 =  $kgm_statep->r[8]
		set $r9 =  $kgm_statep->r[9]
		set $r10 = $kgm_statep->r[10]
		set $r11 = $kgm_statep->r[11]
		set $r12 = $kgm_statep->r[12]
		set $sp = $kgm_statep->sp
		set $lr = $kgm_statep->lr
		set $pc = $pc_ctx
		set $r7 =  $kgm_statep->r[7]
		flushregs
		flushstack
		end
	end
	showcontext_int
end

document switchtoact  
Syntax: switchtoact <address of activation>
| This command allows gdb to examine the execution context and call
| stack for the specified activation. For example, to view the backtrace
| for an activation issue "switchtoact <address>", followed by "bt".
| Before resuming execution, issue a "resetctx" command, to
| return to the original execution context.
end     

define switchtoctx
	select 0
	if ($kgm_mtype == 18)
		if ($kdp_act_counter == 0)
		set $kdpstate = (struct savearea *) kdp.saved_state
		end
		set $kdp_act_counter = $kdp_act_counter + 1
		set (struct savearea *) kdp.saved_state=(struct savearea *) $arg0
		flushregs
		flushstack
		set $pc=((struct savearea *) $arg0)->save_srr0
		update
	else
	if ($kgm_mtype == 12)
		set $r0_save   = $r0
		set $r1_save   = $r1
		set $r2_save   = $r2
		set $r3_save   = $r3
		set $r4_save   = $r4
		set $r5_save   = $r5
		set $r6_save   = $r6
		set $r7_save   = $r7
		set $r8_save   = $r8
		set $r9_save   = $r9
		set $r10_save  = $r10
		set $r11_save  = $r11
		set $r12_save  = $r12
		set $sp_save   = $sp
		set $lr_save   = $lr
		set $pc_save   = $pc
		set $kgm_statep = (struct arm_saved_state *)$arg0
		set $r0 =  $kgm_statep->r[0]
		set $r1 =  $kgm_statep->r[1]
		set $r2 =  $kgm_statep->r[2]
		set $r3 =  $kgm_statep->r[3]
		set $r4 =  $kgm_statep->r[4]
		set $r5 =  $kgm_statep->r[5]
		set $r6 =  $kgm_statep->r[6]
		set $r8 =  $kgm_statep->r[8]
		set $r9 =  $kgm_statep->r[9]
		set $r10 = $kgm_statep->r[10]
		set $r11 = $kgm_statep->r[11]
		set $r12 = $kgm_statep->r[12]
		set $sp = $kgm_statep->sp
		set $lr = $kgm_statep->lr
		set $r7 =  $kgm_statep->r[7]
		set $pc = $kgm_statep->pc
		flushregs
		flushstack
		update
	else
		echo switchtoctx not implemented for this architecture.\n
	end
end

document switchtoctx  
Syntax: switchtoctx <address of pcb>
| This command allows gdb to examine an execution context and dump the
| backtrace for this execution context.
| Before resuming execution, issue a "resetctx" command, to
| return to the original execution context.
end     

define resetctx
	select 0
	if ($kdp_act_counter != 0)
	if ($kgm_mtype == 18)
		set (struct savearea *)kdp.saved_state=$kdpstate
		flushregs
		flushstack
		set $pc=((struct savearea *) kdp.saved_state)->save_srr0
		update
		set $kdp_act_counter = 0
	end
	if ($kgm_mtype == 7)
		set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state
		set *($kdpstatep)=$kdpstate
		flushregs
		flushstack
		set $pc=$kdpstatep->eip
		update
		set $kdp_act_counter = 0
	end
	if ($kgm_mtype == 12)
		set $r0  = $r0_save
		flushregs
		set $r1  = $r1_save
		flushregs
		set $r2  = $r2_save
		flushregs
		set $r3  = $r3_save
		flushregs
		set $r4  = $r4_save
		flushregs
		set $r5  = $r5_save
		flushregs
		set $r6  = $r6_save
		flushregs
		set $r8  = $r8_save
		flushregs
		set $r9  = $r9_save
		flushregs
		set $r10 = $r10_save
		flushregs
		set $r11 = $r11_save
		flushregs
		set $r12 = $r12_save
		flushregs
		set $sp  = $sp_save
		flushregs
		set $lr  = $lr_save
		flushregs
		set $pc  = $pc_save
		flushregs
		set $r7  = $r7_save
		flushregs
	end
	showcontext_int
	end
end     
        
document resetctx
| Syntax: resetctx
| Returns to the original execution context. This command should be
| issued if you wish to resume execution after using the "switchtoact"
| or "switchtoctx" commands.
end     

# This is a pre-hook for the continue command, to prevent inadvertent attempts 
# to resume from the context switched to for examination.
define hook-continue
       resetctx
end

# This is a pre-hook for the detach command, to prevent inadvertent attempts 
# to resume from the context switched to for examination.
define hook-detach
       resetctx
end

define resume_on
	set noresume_on_disconnect = 0
end

document resume_on
| Syntax: resume_on
| The target system will resume when detaching  or exiting from gdb. 
| This is the default behavior.
end

define resume_off
	set noresume_on_disconnect = 1
end

document resume_off
| Syntax: resume_off
| The target system  won't resume after detaching from gdb and
| can be attached with a new gdb session
end

define paniclog
	set $kgm_panic_bufptr = debug_buf
	set $kgm_panic_bufptr_max = debug_buf_ptr
	while $kgm_panic_bufptr < $kgm_panic_bufptr_max
		if *(char *)$kgm_panic_bufptr == 10
			printf "\n"
		else
			printf "%c", *$kgm_panic_bufptr
		end
		set $kgm_panic_bufptr= (char *)$kgm_panic_bufptr + 1
	end
end

document paniclog
| Syntax: paniclog
| Display the panic log information
|
end

define dumpcallqueue
	set $kgm_callhead = (queue_t)&$arg0
	set $kgm_call = (struct call_entry *)$kgm_callhead.next
	set $kgm_i = 0
	while $kgm_call != $kgm_callhead
		printf "0x%08x ", $kgm_call
		printf "0x%08x 0x%08x ", $kgm_call->param0, $kgm_call->param1
		output $kgm_call->state
		printf "\t"
		output $kgm_call->deadline
		printf "\t"
		output $kgm_call->func
		printf "\n"
		set $kgm_i = $kgm_i + 1
		set $kgm_call = (struct call_entry *)$kgm_call->q_link.next
	end
	printf "%d entries\n", $kgm_i
end

document dumpcallqueue
| Syntax: dumpcallqueue <queue head>
| Displays the contents of the specified call_entry queue.
end

define showtaskacts
showtaskthreads $arg0
end
document showtaskacts
| See help showtaskthreads.
end

define showallacts
showallthreads
end
document showallacts
| See help showallthreads.
end


define resetstacks
       _kgm_flush_loop
       set kdp_pmap = 0
       _kgm_flush_loop
       resetctx
       _kgm_flush_loop
       _kgm_update_loop
       resetctx
       _kgm_update_loop
end

document resetstacks
| Syntax: resetstacks
| Internal kgmacro routine used by the "showuserstack" macro 
| to reset the target pmap to the kernel pmap.
end

#Barely effective hacks to work around bugs in the "flush" and "update" 
#gdb commands in Tiger (up to 219); these aren't necessary with Panther
#gdb, but do no harm.
define _kgm_flush_loop
       set $kgm_flush_loop_ctr = 0
       while ($kgm_flush_loop_ctr < 30)
       	     flushregs
	     flushstack
	     set $kgm_flush_loop_ctr = $kgm_flush_loop_ctr + 1
       end
end

define _kgm_update_loop
       set $kgm_update_loop_ctr = 0
       while ($kgm_update_loop_ctr < 30)
       	     update
       	     set $kgm_update_loop_ctr = $kgm_update_loop_ctr + 1
       end
end

#This is necessary since gdb often doesn't do backtraces on x86 correctly
#in the absence of symbols.The code below in showuserstack and 
#showx86backtrace also contains several workarouds for the gdb bug where 
#gdb stops macro evaluation because of spurious "Cannot read memory"
#errors on x86. These errors appear on ppc as well, but they don't
#always stop macro evaluation.

set $kgm_cur_ebp = 0
set $kgm_cur_eip = 0

define showx86backtrace
	if ($kgm_cur_ebp == 0)
		set $kgm_cur_ebp = $ebp
	end
	if ($kgm_cur_eip == 0)
		set $kgm_cur_eip = $eip
	end
	printf "0: EBP: 0x%08x EIP: 0x%08x\n", $kgm_cur_ebp, $kgm_cur_eip
	x/i $kgm_cur_eip
	set $kgm_prev_ebp = *((uint32_t *) $kgm_cur_ebp)
	set $kgm_prev_eip = *((uint32_t *) ($kgm_cur_ebp + 4))
	set $kgm_cur_ebp = 0
	set $kgm_cur_eip = 0
	set $kgm_frameno = 1
	while $kgm_prev_ebp != 0
		printf "%d: saved EBP: 0x%08x saved EIP: 0x%08x\n", $kgm_frameno, $kgm_prev_ebp, $kgm_prev_eip
		x/i $kgm_prev_eip
		set $kgm_prev_eip = *((uint32_t *) ($kgm_prev_ebp + 4))
		set $kgm_prev_ebp = *((uint32_t *) $kgm_prev_ebp)
		set $kgm_frameno = $kgm_frameno + 1
	end
	set kdp_pmap = 0
end

define showuserstack
		select 0
  		if ($kgm_mtype == 18)	
		   if ($kdp_act_counter == 0)
		      set $kdpstate = (struct savearea *) kdp.saved_state
		   end
		   set $kdp_act_counter = $kdp_act_counter + 1
		   set $newact = (struct thread *) $arg0
		   _kgm_flush_loop
		   set $checkpc = $newact->machine->upcb.save_srr0
		   if ($checkpc == 0)
		      echo This activation does not appear to have
		      echo \20 a valid user context.\n
		   else	      
		     set (struct savearea *) kdp.saved_state=$newact->machine->upcb
		     set $pc = $checkpc
#flush and update seem to be executed lazily by gdb on Tiger, hence the
#repeated invocations - see 3743135
	   	    _kgm_flush_loop
# This works because the new pmap is used only for reads
		     set kdp_pmap = $newact->task->map->pmap
		     _kgm_flush_loop
		     _kgm_update_loop
		     bt
		     resetstacks
		     _kgm_flush_loop
		     _kgm_update_loop
		     resetstacks
		     _kgm_flush_loop
		     _kgm_update_loop
		   end
		else
		if ($kgm_mtype == 7)
			set $newact = (struct thread *) $arg0
#This needs to identify 64-bit processes as well
			set $newiss = (x86_saved_state32_t) ($newact->machine.pcb->iss.uss.ss_32)
			set $checkpc = $newiss.eip
			if ($checkpc == 0)
			    echo This activation does not appear to have
			    echo \20 a valid user context.\n
			else
			set $kgm_cur_ebp = $newiss.ebp
			set $kgm_cur_eip = $checkpc
			printf "You may now issue the showx86backtrace command to see the user space backtrace for this thread (0x%08x); you can also examine memory locations in this address space (pmap 0x%08x) before issuing the backtrace. This two-step process is necessary to work around various bugs in x86 gdb, which cause it to stop memory evaluation on spurious memory read errors. Additionally, you may need to issue a set kdp_pmap = 0 command after the showx86backtrace completes, to resume reading from the kernel address space.\n", $arg0, $newact->task->map->pmap
			set kdp_pmap = $newact->task->map->pmap
			_kgm_flush_loop
			_kgm_update_loop
			end			
		else
			echo showuserstack not supported on this architecture\n
		end
		end
end
document showuserstack
Syntax: showuserstack <address of thread activation>
|This command displays a numeric backtrace for the user space stack of
|the given thread activation. It may, of course, fail to display a
|complete backtrace if portions of the user stack are not mapped in.
|Symbolic backtraces can be obtained either by running gdb on the
|user space binary, or a tool such as "symbolicate".
|Note that while this command works on Panther's gdb, an issue
|with Tiger gdb (3743135) appears to hamper the evaluation of this
|macro in some cases.
end

#Stopgap until gdb can generate the HOSTREBOOT packet
define kdp-reboot
#Alternatively, set *(*(unsigned **) 0x2498) = 1 (or 0x5498 on PPC)
       set flag_kdp_trigger_reboot = 1
       continue
end

document kdp-reboot
Syntax: kdp-reboot
|Reboot the remote target machine; not guaranteed to succeed. Requires symbols
|until gdb support for the HOSTREBOOT packet is implemented.
end

define sendcore
       set kdp_trigger_core_dump = 1
       set kdp_flag |= 0x40
       set panicd_ip_str = "$arg0"
       set panicd_specified = 1
       set disable_debug_output = 0
       set disableConsoleOutput = 0
       set logPanicDataToScreen = 1
       set reattach_wait = 1
       resume_off
end

document sendcore
Syntax: sendcore <IP address>
|Configure the kernel to transmit a kernel coredump to a server (kdumpd) 
|at the specified IP address. This is useful when the remote target has
|not been previously configured to transmit coredumps, and you wish to
|preserve kernel state for later examination. NOTE: You must issue a "continue"
|command after using this macro to trigger the kernel coredump. The kernel
|will resume waiting in the debugger after completion of the coredump. You
|may disable coredumps by executing the "disablecore" macro.
end

define disablecore
       set kdp_trigger_core_dump = 0
       set kdp_flag |= 0x40
       set kdp_flag &= ~0x10
       set panicd_specified = 0
end

document disablecore
Syntax: disablecore
|Reconfigures the kernel so that it no longer transmits kernel coredumps. This
|complements the "sendcore" macro, but it may be used if the kernel has been
|configured to transmit coredumps through boot-args as well.
end

define switchtocorethread
	set $newact = (struct thread *) $arg0
	select 0
	if ($newact->kernel_stack == 0)
	   echo This thread does not have a stack.\n
	   echo continuation:
	   output/a (unsigned) $newact.continuation
	   echo \n
	else
	if ($kgm_mtype == 18)
	   loadcontext $newact->machine->pcb
	   flushstack
	   set $pc = $newact->machine->pcb.save_srr0
	else
	if ($kgm_mtype == 7)
		set $kgm_cstatep = (struct x86_kernel_state32 *) \
					($newact->kernel_stack + 0x4000 \
					 - sizeof(struct x86_kernel_state32))
		loadcontext $kgm_cstatep
		flushstack
	else
		echo switchtocorethread not supported on this architecture\n
	end
 	end
	showcontext_int
	end
end

document switchtocorethread
Syntax: switchtocorethread <address of activation>
| The corefile equivalent of "switchtoact". When debugging a kernel coredump
| file, this command can be used to examine the execution context and stack
| trace for a given thread activation. For example, to view the backtrace
| for a thread issue "switchtocorethread <address>", followed by "bt".
| Before resuming execution, issue a "resetcorectx" command, to
| return to the original execution context. Note that this command
| requires gdb support, as documented in Radar 3401283.
end

define loadcontext
	select 0
	if ($kgm_mtype == 18)
	set $kgm_contextp = (struct savearea *) $arg0
	set $pc = $kgm_contextp.save_srr0
	set $r1 = $kgm_contextp.save_r1
	set $lr = $kgm_contextp.save_lr

	set $r2 = $kgm_contextp.save_r2
	set $r3 = $kgm_contextp.save_r3
	set $r4 = $kgm_contextp.save_r4
	set $r5 = $kgm_contextp.save_r5
	set $r6 = $kgm_contextp.save_r6
	set $r7 = $kgm_contextp.save_r7
	set $r8 = $kgm_contextp.save_r8
	set $r9 = $kgm_contextp.save_r9
	set $r10 = $kgm_contextp.save_r10
	set $r11 = $kgm_contextp.save_r11
	set $r12 = $kgm_contextp.save_r12
	set $r13 = $kgm_contextp.save_r13
	set $r14 = $kgm_contextp.save_r14
	set $r15 = $kgm_contextp.save_r15
	set $r16 = $kgm_contextp.save_r16
	set $r17 = $kgm_contextp.save_r17
	set $r18 = $kgm_contextp.save_r18
	set $r19 = $kgm_contextp.save_r19
	set $r20 = $kgm_contextp.save_r20
	set $r21 = $kgm_contextp.save_r21
	set $r22 = $kgm_contextp.save_r22
	set $r23 = $kgm_contextp.save_r23
	set $r24 = $kgm_contextp.save_r24
	set $r25 = $kgm_contextp.save_r25
	set $r26 = $kgm_contextp.save_r26
	set $r27 = $kgm_contextp.save_r27
	set $r28 = $kgm_contextp.save_r28
	set $r29 = $kgm_contextp.save_r29
	set $r30 = $kgm_contextp.save_r30
	set $r31 = $kgm_contextp.save_r31

	set $cr = $kgm_contextp.save_cr
	set $ctr = $kgm_contextp.save_ctr
       else
	if ($kgm_mtype == 7)
		set $kgm_contextp = (struct x86_kernel_state32 *) $arg0
		set $ebx = $kgm_contextp->k_ebx 
		set $ebp = $kgm_contextp->k_ebp 
		set $edi = $kgm_contextp->k_edi 
		set $esi = $kgm_contextp->k_esi 
		set $eip = $kgm_contextp->k_eip 
		set $pc =  $kgm_contextp->k_eip
	else
		echo loadcontext not supported on this architecture\n
	end
	end
end

define resetcorectx
	select 0
	if ($kgm_mtype == 18)
		set $kgm_corecontext = (struct savearea *) kdp.saved_state
		loadcontext $kgm_corecontext
	else
	if ($kgm_mtype == 7)
		set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state
		set $ebx = $kdpstatep->ebx
		set $ebp = $kdpstatep->ebp
		set $edi = $kdpstatep->edi
		set $esi = $kdpstatep->esi
		set $eip = $kdpstatep->eip
		set $eax = $kdpstatep->eax
		set $ecx = $kdpstatep->ecx
		set $edx = $kdpstatep->edx
		flushregs
		flushstack
		set $pc = $kdpstatep->eip
		update
	else
		echo resetcorectx not supported on this architecture\n
	end
	end
	showcontext_int
end

document resetcorectx
Syntax: resetcorectx
| The corefile equivalent of "resetctx". Returns to the original
| execution context (that of the active thread at the time of the NMI or
| panic). This command should be issued if you wish to resume
| execution after using the "switchtocorethread" command.
end

#Helper function for "showallgdbstacks"

define showgdbthread
	printf "            0x%08x  ", $arg0
	set $kgm_thread = *(struct thread *)$arg0
	printf "0x%08x  ", $arg0
	printf "%3d  ", $kgm_thread.sched_pri
	set $kgm_state = $kgm_thread.state
	if $kgm_state & 0x80
	    printf "I" 
	end
	if $kgm_state & 0x40
	    printf "P" 
	end
	if $kgm_state & 0x20
	    printf "A" 
	end
	if $kgm_state & 0x10
	    printf "H" 
	end
	if $kgm_state & 0x08
	    printf "U" 
	end
	if $kgm_state & 0x04
	    printf "R" 
	end
	if $kgm_state & 0x02
	    printf "S" 
	end
   	if $kgm_state & 0x01
	    printf "W\t" 
	    printf "0x%08x  ", $kgm_thread.wait_queue
            output /a (unsigned) $kgm_thread.wait_event
		if ($kgm_thread.uthread != 0)
			set $kgm_uthread = (struct uthread *)$kgm_thread.uthread
			if ($kgm_uthread->uu_wmesg != 0)
				printf " \"%s\"", $kgm_uthread->uu_wmesg
			end
	    end
	end
	if $arg1 != 0
	    if ($kgm_thread.kernel_stack != 0)
		if ($kgm_thread.reserved_stack != 0)
			printf "\n\t\treserved_stack=0x%08x", $kgm_thread.reserved_stack
		end
		printf "\n\t\tkernel_stack=0x%08x", $kgm_thread.kernel_stack
		if ($kgm_mtype == 18)
			set $mysp = $kgm_thread.machine.pcb->save_r1
		end
		if ($kgm_mtype == 7)
			set $kgm_statep = (struct x86_kernel_state32 *) \
				($kgm_thread->kernel_stack + 0x4000 \
				 - sizeof(struct x86_kernel_state32))
			set $mysp = $kgm_statep->k_ebp
		end
		if ($kgm_mtype == 12)
			if ($arg0 == $r9)
				set $mysp = $r7
			else
                        	set $kgm_statep = (struct arm_saved_state *)$kgm_thread.machine.kstackptr
                        	set $mysp = $kgm_statep->r[7]
			end
		end
		set $prevsp = 0
		printf "\n\t\tstacktop=0x%08x", $mysp
		if ($arg2 == 0)
			switchtoact $arg0
		else
			switchtocorethread $arg0
		end
	    	bt
	    else
		printf "\n\t\t\tcontinuation="
		output /a (unsigned) $kgm_thread.continuation
	    end
	    printf "\n"
	else
	    printf "\n"
	end
end	    

#Use of this macro is currently (8/04) blocked by the fact that gdb
#stops evaluating macros when encountering an error, such as a failure
#to read memory from a certain location. Until this issue (described in
#3758949) is addressed, evaluation of this macro may stop upon
#encountering such an error.

define showallgdbstacks
    set $kgm_head_taskp = &tasks
    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
    while $kgm_taskp != $kgm_head_taskp
        showtaskheader
	showtaskint $kgm_taskp
	set $kgm_head_actp = &($kgm_taskp->threads)
        set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
	while $kgm_actp != $kgm_head_actp
	    showactheader
	    showgdbthread $kgm_actp 1 0
  	    set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
        end
	printf "\n"
    	set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
    end
    resetctx
end

document showallgdbstacks
Syntax: showallgdbstacks
| An alternative to "showallstacks". Iterates through the task list and
| displays a gdb generated backtrace for each kernel thread. It is
| advantageous in that it is much faster than "showallstacks", and
| decodes function call arguments and displays source level traces, but
| it has the drawback that it doesn't determine if frames belong to
| functions from kernel extensions, as with "showallstacks".
| This command may terminate prematurely because of a gdb bug
| (Radar 3758949), which stops macro evaluation on memory read
| errors.
end

define showallgdbcorestacks
	select 0
	set $kgm_head_taskp = &tasks
	set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
        while $kgm_taskp != $kgm_head_taskp
		showtaskheader
		showtaskint $kgm_taskp
		set $kgm_head_actp = &($kgm_taskp->threads)
		set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
		while $kgm_actp != $kgm_head_actp
		showactheader
		showgdbthread $kgm_actp 1 1
		set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
		end
		printf "\n"
		set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
	end
	resetcorectx
end


document showallgdbcorestacks
Syntax: showallgdbcorestacks
|Corefile version of "showallgdbstacks"
end


define switchtouserthread
		select 0
  		if ($kgm_mtype == 18)	
		   if ($kdp_act_counter == 0)
		      set $kdpstate = (struct savearea *) kdp.saved_state
		   end
		   set $kdp_act_counter = $kdp_act_counter + 1
		   set $newact = (struct thread *) $arg0
		   _kgm_flush_loop
		   set $checkpc = $newact->machine->upcb.save_srr0
		   if ($checkpc == 0)
		      echo This activation does not appear to have
		      echo \20 a valid user context.\n
		   else	      
		     set (struct savearea *) kdp.saved_state=$newact->machine->upcb
		     set $pc = $checkpc
#flush and update seem to be executed lazily by gdb on Tiger, hence the
#repeated invocations - see 3743135
	   	    _kgm_flush_loop
# This works because the new pmap is used only for reads
		     set kdp_pmap = $newact->task->map->pmap
		     _kgm_flush_loop
		     _kgm_update_loop
		   end
		else
		   echo switchtouserthread not implemented for this architecture.\n
	end
end

document switchtouserthread
Syntax: switchtouserthread <address of thread>
| Analogous to switchtoact, but switches to the user context of a
| specified thread address. Similar to the "showuserstack"
| command, but this command does not return gdb to the kernel context
| immediately. This is to assist with the following (rather risky)
| manoeuvre - upon switching to the user context and virtual address
| space, the user may choose to call remove-symbol-file on the
| mach_kernel symbol file, and then add-symbol-file on the user space
| binary's symfile. gdb can then generate symbolic backtraces 
| for the user space thread. To return to the
| kernel context and virtual address space, the process must be
| reversed, i.e. call remove-symbol-file on the user space symbols, and
| then add-symbol-file on the appropriate mach_kernel, and issue the
| "resetstacks" command. Note that gdb may not react kindly to all these
| symbol file switches. The same restrictions that apply to "showuserstack"
| apply here - pages that have been paged out cannot be read while in the
| debugger context, so backtraces may terminate early.
| If the virtual addresses in the stack trace do not conflict with those
| of symbols in the kernel's address space, it may be sufficient to
| just do an add-symbol-file on the user space binary's symbol file.
| Note that while this command works on Panther's gdb, an issue
| with Tiger gdb (3743135) appears to hamper the evaluation of this
| macro in some cases.
end

define showmetaclass
    set $kgm_metaclassp = (OSMetaClass *)$arg0
    printf "%-5d", $kgm_metaclassp->instanceCount
    printf "x %5d bytes", $kgm_metaclassp->classSize
    printf " %s\n", $kgm_metaclassp->className->string
end

define showstring
    printf "\"%s\"", ((OSString *)$arg0)->string
end

define shownumber
    printf "%lld", ((OSNumber *)$arg0)->value
end

define showboolean
    if ($arg0 == gOSBooleanFalse)
	printf "No"
    else
	printf "Yes"
    end
end

define showdata
    set $kgm_data = (OSData *)$arg0

    printf "<"
    set $kgm_datap = (const unsigned char *) $kgm_data->data

    set $kgm_printstr = 0
    if (0 == (3 & (unsigned int)$kgm_datap) && ($kgm_data->length >= 3))
	set $kgm_bytes = *(unsigned int *) $kgm_datap
	if (0xffff0000 & $kgm_bytes)
	    set $kgm_idx = 0
	    set $kgm_printstr = 1
	    while ($kgm_idx++ < 4)
		set $kgm_bytes = $kgm_bytes >> 8
		set $kgm_char = 0xff & $kgm_bytes
		if ($kgm_char && (($kgm_char < 0x20) || ($kgm_char > 0x7e)))
		    set $kgm_printstr = 0
		end
	    end
	end
    end
    
    set $kgm_idx = 0
    if ($kgm_printstr)
	set $kgm_quoted = 0
	while ($kgm_idx < $kgm_data->length)
	    set $kgm_char = $kgm_datap[$kgm_idx++]
	    if ($kgm_char)
		if (0 == $kgm_quoted)
		    set $kgm_quoted = 1
		    if ($kgm_idx > 1)
			printf ",\""
		    else
			printf "\""
		    end
		end
		printf "%c", $kgm_char
	    else
		if ($kgm_quoted)
		    set $kgm_quoted = 0
		    printf "\""
		end
	    end
	end
	if ($kgm_quoted)
	    printf "\""
	end
    else
	if (0 == (3 & (unsigned int)$kgm_datap))
	    while (($kgm_idx + 3) <= $kgm_data->length)
		printf "%08x", *(unsigned int *) &$kgm_datap[$kgm_idx]
		set $kgm_idx = $kgm_idx + 4
	    end
	end
	while ($kgm_idx < $kgm_data->length)
	    printf "%02x", $kgm_datap[$kgm_idx++]
	end
    end
    printf ">"
end

define showdictionaryint
    set $kgm$arg0_dict = (OSDictionary *)$arg1

    printf "{"
    set $kgm$arg0_idx = 0
    while ($kgm$arg0_idx < $kgm$arg0_dict->count)
	set $kgm_obj = $kgm$arg0_dict->dictionary[$kgm$arg0_idx].key
	showobjectint _$arg0 $kgm_obj
	printf "="
	set $kgm_obj = $kgm$arg0_dict->dictionary[$kgm$arg0_idx++].value
	showobjectint _$arg0 $kgm_obj
	if ($kgm$arg0_idx < $kgm$arg0_dict->count)
	    printf ","
	end
    end
    printf "}"
end

define indent
    set $kgm_idx = 0
    while ($kgm_idx < $arg0)
	if ($arg1 & (1 << $kgm_idx++))
	    printf "| "
	else
	    printf "  "
	end
    end
end

define showregdictionary
    indent $kgm_reg_depth+2 $arg1
    printf "{\n"

    set $kgm_reg_idx = 0
    while ($kgm_reg_idx < $arg0->count)
	indent $kgm_reg_depth+2 $arg1
	printf "  "
	set $kgm_obj = $arg0->dictionary[$kgm_reg_idx].key
	showobjectint _ $kgm_obj
	printf " = "

	set $kgm_obj = $arg0->dictionary[$kgm_reg_idx++].value
	showobjectint _ $kgm_obj
	printf "\n"
    end
    indent $kgm_reg_depth+2 $arg1
    printf "}\n"
end


define showarraysetint
    set $kgm$arg0_array = (OSArray *)$arg1

    set $kgm$arg0_idx = 0
    while ($kgm$arg0_idx < $kgm$arg0_array->count)
	set $kgm_obj = $kgm$arg0_array->array[$kgm$arg0_idx++]
	showobjectint _$arg0 $kgm_obj
	if ($kgm$arg0_idx < $kgm$arg0_array->count)
	    printf ","
	end
    end
end

define showarrayint
    printf "("
    showarraysetint $arg0 $arg1
    printf ")"
end

define showsetint
    set $kgm_array = ((OSSet *)$arg1)->members
    printf "["
    showarraysetint $arg0 $kgm_array
    printf "]"
end


define showobjectint
    set $kgm_obj = (OSObject *) $arg1
    set $kgm_vt = *((void **) $arg1)

    if ($kgm_mtype == 12)
        set $kgm_vt = $kgm_vt - 2 * sizeof(void *)
    end

    if ($kgm_show_object_addrs)
	printf "`object %p, vt ", $arg1
	output /a (unsigned) $kgm_vt
	if ($kgm_show_object_retain)
	    printf ", retain count %d, container retain %d", (0xffff & $kgm_obj->retainCount), $kgm_obj->retainCount >> 16
	end
	printf "` "
    end

    if ($kgm_vt == _ZTV8OSString)
	showstring $arg1
    else
	if ($kgm_vt == _ZTV8OSSymbol)
	    showstring $arg1
	else
	    if ($kgm_vt == _ZTV8OSNumber)
		shownumber $arg1
	    else
		if ($kgm_vt == _ZTV6OSData)
		    showdata $arg1
		else
		    if ($kgm_vt == _ZTV9OSBoolean)
			showboolean $arg1
		    else
			if ($kgm_vt == _ZTV12OSDictionary)
			    showdictionaryint _$arg0 $arg1
			else
			    if ($kgm_vt == _ZTV7OSArray)
				showarrayint _$arg0 $arg1
			    else
				if ($kgm_vt == _ZTV5OSSet)
				    showsetint _$arg0 $arg1
				else
				    if ($kgm_show_object_addrs == 0)
					printf "`object %p, vt ", $arg1
					output /a (unsigned) $kgm_vt
					printf "`"
				    end
				end
			    end
			end
		    end
		end
	    end
	end
    end
end

define showobject
    set $kgm_save = $kgm_show_object_addrs
    set $kgm_show_object_addrs = 1
    set $kgm_show_object_retain = 1
    showobjectint _ $arg0
    set $kgm_show_object_addrs = $kgm_save
    set $kgm_show_object_retain = 0
    printf "\n"
end
document showobject
Syntax: (gdb) showobject <object address>
| Show info about an OSObject - its vtable ptr and retain count.
| If the object is a simple container class, more info will be shown.
end

define dictget 
    set $kgm_dictp = (OSDictionary *)$arg0
    set $kgm_keyp = (const OSSymbol *)$arg1
    set $kgm_idx = 0
    set $kgm_result = 0
    while (($kgm_idx < $kgm_dictp->count) && ($kgm_result == 0))
	if ($kgm_keyp == $kgm_dictp->dictionary[$kgm_idx].key)
	    set $kgm_result = $kgm_dictp->dictionary[$kgm_idx].value
	end
	set $kgm_idx = $kgm_idx + 1
    end
end


define showregistryentryrecurse
    set $kgm_re         = (IOService *)$arg1
    set $kgm$arg0_stack = (unsigned long long) $arg2

    if ($arg3)
	set $kgm$arg0_stack = $kgm$arg0_stack | (1ULL << $kgm_reg_depth)
    else
	set $kgm$arg0_stack = $kgm$arg0_stack & ~(1ULL << $kgm_reg_depth)
    end

    dictget $kgm_re->fRegistryTable $kgm_childkey
    set $kgm$arg0_child_array = (OSArray *) $kgm_result

    if ($kgm$arg0_child_array)
	set $kgm$arg0_child_count = $kgm$arg0_child_array->count
    else
	set $kgm$arg0_child_count = 0
    end

    if ($kgm$arg0_child_count)
	set $kgm$arg0_stack = $kgm$arg0_stack | (2ULL << $kgm_reg_depth)
    else
	set $kgm$arg0_stack = $kgm$arg0_stack & ~(2ULL << $kgm_reg_depth)
    end

    indent $kgm_reg_depth $kgm$arg0_stack
    printf "+-o "

    dictget $kgm_re->fRegistryTable $kgm_namekey
    if ($kgm_result == 0)
	dictget $kgm_re->fRegistryTable gIONameKey
    end
    if ($kgm_result == 0)
	dictget $kgm_re->fPropertyTable gIOClassKey
    end

    if ($kgm_result != 0)
	printf "%s", ((OSString *)$kgm_result)->string
    else
 	if (((IOService*)$kgm_re)->pwrMgt &&  ((IOService*)$kgm_re)->pwrMgt->Name)
 	    printf "%s", ((IOService*)$kgm_re)->pwrMgt->Name
	else
#	    printf ", guessclass "
#	    guessclass $kgm_re
	    printf "??"
	end
    end


    printf "  <object %p, ", $kgm_re
    printf "vtable "
    set $kgm_vt = (unsigned) *(void**) $kgm_re
    if ($kgm_mtype == 12)
        set $kgm_vt = $kgm_vt - 2 * sizeof(void *)
    end
    output /a $kgm_vt

    if ($kgm_vt != _ZTV15IORegistryEntry)
	printf ", "
	set $kgm_state =  $kgm_re->__state[0]
	# kIOServiceRegisteredState
	if (0 == ($kgm_state & 2))
	    printf "!"
	end
	printf "registered, "
	# kIOServiceMatchedState
	if (0 == ($kgm_state & 4))
	    printf "!"
	end
	printf "matched, "
	# kIOServiceInactiveState
	if ($kgm_state & 1)
	    printf "in"
	end
	printf "active, busy %d, retain count %d", (0xff & $kgm_re->__state[1]), (0xffff & $kgm_re->retainCount)
    end
    printf ">\n"

    if ($kgm_show_props)
	set $kgm_props = $kgm_re->fPropertyTable
	showregdictionary $kgm_props $kgm$arg0_stack
    end

    # recurse
    if ($kgm$arg0_child_count != 0)

	set $kgm_reg_depth = $kgm_reg_depth + 1
	set $kgm$arg0_child_idx = 0

	while ($kgm$arg0_child_idx < $kgm$arg0_child_count)
	    set $kgm_re = $kgm$arg0_child_array->array[$kgm$arg0_child_idx++]
	    set $kgm_more_sib = ($kgm$arg0_child_idx < $kgm$arg0_child_count)
	    showregistryentryrecurse _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib
	end

	set $kgm_reg_depth = $kgm_reg_depth - 1
    end
end

define showregistryentryint
    set $kgm_namekey   = (OSSymbol *) $kgm_reg_plane[2]
    set $kgm_childkey  = (OSSymbol *) $kgm_reg_plane[4]

    showregistryentryrecurse _ $arg0 0 0
end

define showregistry
    set $kgm_reg_depth  = 0
    set $kgm_show_props = 0
    showregistryentryint gRegistryRoot
end
document showregistry
Syntax: (gdb) showregistry 
| Show info about all registry entries in the current plane.
end

define showregistryprops
    set $kgm_reg_depth  = 0
    set $kgm_show_props = 1
    showregistryentryint gRegistryRoot
end
document showregistryprops
Syntax: (gdb) showregistryprops 
| Show info about all registry entries in the current plane, and their properties.
| set $kgm_show_object_addrs = 1 and/or set $kgm_show_object_retain = 1 will display
| more verbose information
end

define showregistryentry
    set $kgm_reg_depth  = 0
    set $kgm_show_props = 1
    showregistryentryint $arg0
end
document showregistryentry
Syntax: (gdb) showregistryentry <object address>
| Show info about a registry entry; its properties and descendants in the current plane.
end

define setregistryplane
    if ($arg0)
	set $kgm_reg_plane = (void **) $arg0
    else
	showobjectint _ gIORegistryPlanes
	printf "\n"
    end
end
document setregistryplane
Syntax: (gdb) setregistryplane <plane object address>
| Set the plane to be used for the iokit registry macros. An argument of zero will 
| display known planes.
end

define guessclass
    set $kgm_classidx = 0
    set $kgm_lookvt = *((void **) $arg0)
    set $kgm_bestvt = (void *) 0
    set $kgm_bestidx = 0
    
    while $kgm_classidx < sAllClassesDict->count
	set $kgm_meta = (OSMetaClass *) sAllClassesDict->dictionary[$kgm_classidx].value

	set $kgm_vt = *((void **) $kgm_meta)

	if (($kgm_vt > $kgm_bestvt) && ($kgm_vt < $kgm_lookvt))
	    set $kgm_bestvt  = $kgm_vt
	    set $kgm_bestidx = $kgm_classidx
	end
	set $kgm_classidx = $kgm_classidx + 1
    end
    printf "%s", sAllClassesDict->dictionary[$kgm_bestidx].key->string
end

define showallclasses
    set $kgm_classidx = 0
    while $kgm_classidx < sAllClassesDict->count
	set $kgm_meta = (OSMetaClass *) sAllClassesDict->dictionary[$kgm_classidx++].value
	showmetaclass $kgm_meta
    end
end

document showallclasses
Syntax: (gdb) showallclasses
| Show the instance counts and ivar size of all OSObject subclasses. See ioclasscount man page for details.
end

define showioalloc
    printf " Instance allocation = 0x%08lx = %4ld K\n", (int) debug_ivars_size, ((int) debug_ivars_size) / 1024
    printf "Container allocation = 0x%08lx = %4ld K\n", (int) debug_container_malloc_size, ((int) debug_container_malloc_size) / 1024
    printf " IOMalloc allocation = 0x%08lx = %4ld K\n", (int) debug_iomalloc_size, ((int) debug_iomalloc_size) / 1024
    printf " Pageable allocation = 0x%08lx = %4ld K\n", (vm_size_t) debug_iomallocpageable_size, ((vm_size_t) debug_iomallocpageable_size) / 1024
end

document showioalloc
Syntax: (gdb) showioalloc
| Show some accounting of memory allocated by IOKit allocators. See ioalloccount man page for details.
end

define showosobjecttracking
    set $kgm_next = (OSObjectTracking *) gOSObjectTrackList.next
    while $kgm_next != &gOSObjectTrackList
	set $obj = (OSObject *) ($kgm_next+1)
	showobject $obj
	set $kgm_idx = 0
	while $kgm_idx < (sizeof($kgm_next->bt) / sizeof($kgm_next->bt[0]))
	    if ((unsigned) $kgm_next->bt[$kgm_idx] > (unsigned) sectPRELINKB)
		showkmodaddr $kgm_next->bt[$kgm_idx]
		printf "\n"
	    else
		if ((unsigned) $kgm_next->bt[$kgm_idx] > 0)
		    output /a (unsigned) $kgm_next->bt[$kgm_idx]
		    printf "\n"
		end
	    end
	    set $kgm_idx = $kgm_idx + 1
	end
	printf "\n"
	set $kgm_next = (OSObjectTracking *) $kgm_next->link.next
    end
end

document showosobjecttracking
Syntax: (gdb) showosobjecttracking
| Show the list of tracked OSObject allocations with backtraces.
| Boot with the kOSTraceObjectAlloc (0x00400000) io debug flag set. 
| Set gOSObjectTrackThread to 1 or a thread_t to capture new OSObjects allocated by a thread or all threads.
end

define readphys
       set kdp_trans_off = 1
       x/x $arg0
       set kdp_trans_off = 0
end

define readphys64
	if ($kgm_mtype == 18)
	   set kdp_src_high32 = ((uint32_t) ($arg0)) >> 32
	   x/x (uint32_t) (($arg0) & 0x00000000ffffffffUL)
	   set kdp_src_high32 = 0
	else
		echo readphys64 not available on this architecture.\n
	end
end

document readphys
| The argument is interpreted as a physical address, and the word addressed is
| displayed. While this fails if no physical page exists at the given address,
| it must be used with caution.
end

document readphys64
| The argument is interpreted as a 64-bit physical address, and the word
| addressed is displayed. While this fails if no physical page exists at the
| given address, it must be used with caution.
end

define addkextsyms
        shell ls $arg0/* | xargs -n 1 echo add-symbol-file > /tmp/gdb-syms
        source /tmp/gdb-syms
	set $kgm_show_kmod_syms = 1
end

document addkextsyms
| Takes a directory of symbols for kexts generated with kextcache -y and loads them
| into gdb.
| (gdb) addkextsyms /path/to/symboldir
end

define showprocfiles
    if ($argc == 1)
	_showprocheader
	_showprocfiles $arg0
    else
    	printf "| Usage:\n|\n"
	help showprocfiles
    end
end
document showprocfiles
Syntax: (gdb) showprocfiles <proc_t>
| Given a proc_t pointer, display the list of open file descriptors for the
| referenced process.
end

define _showprocheader
    printf "fd     fileglob    fg flags    fg type   fg data     info\n"
    printf "-----  ----------  ----------  --------  ----------  -------------------\n"
end

define _showprocfiles
    set $kgm_spf_filedesc = ((proc_t)$arg0)->p_fd
    set $kgm_spf_last = $kgm_spf_filedesc->fd_lastfile
    set $kgm_spf_ofiles = $kgm_spf_filedesc->fd_ofiles
    set $kgm_spf_count = 0
    while ($kgm_spf_count <= $kgm_spf_last)
	if ($kgm_spf_ofiles[$kgm_spf_count] == 0)
	    # DEBUG: For files that were open, but are now closed
	    # printf "%-5d  FILEPROC_NULL\n", $kgm_spf_count
	else
	    # display fd #, fileglob address, fileglob flags
	    set $kgm_spf_flags = $kgm_spf_ofiles[$kgm_spf_count].f_flags
	    set $kgm_spf_fg = $kgm_spf_ofiles[$kgm_spf_count].f_fglob
	    printf "%-5d  0x%08x  0x%08x  ", $kgm_spf_count, $kgm_spf_fg, $kgm_spf_flags
	    # decode fileglob type
	    set $kgm_spf_fgt = $kgm_spf_fg->fg_type
	    if ($kgm_spf_fgt == 1)
	    	printf "VNODE   "
	    end
	    if ($kgm_spf_fgt == 2)
	    	printf "SOCKET  "
	    end
	    if ($kgm_spf_fgt == 3)
	    	printf "PSXSHM  "
	    end
	    if ($kgm_spf_fgt == 4)
	    	printf "PSXSEM  "
	    end
	    if ($kgm_spf_fgt == 5)
	    	printf "KQUEUE  "
	    end
	    if ($kgm_spf_fgt == 6)
	    	printf "PIPE    "
	    end
	    if ($kgm_spf_fgt == 7)
	    	printf "FSEVENTS"
	    end
	    if ($kgm_spf_fgt < 1 || $kgm_spf_fgt > 7)
	        printf "?: %-5d", $kgm_spf_fgt
	    end

	    # display fileglob data address and decode interesting fact(s)
	    # about data, if we know any
	    set $kgm_spf_fgd = $kgm_spf_fg->fg_data
	    printf "  0x%08x  ", $kgm_spf_fgd
	    if ($kgm_spf_fgt == 1)
	    	set $kgm_spf_name = ((struct vnode *)$kgm_spf_fgd)->v_name
		if ($kgm_spf_name == 0)
		    printf "(null)"
		else
		    printf "%s", $kgm_spf_name
		end
	    end
	    printf "\n"
	end
    	set $kgm_spf_count = $kgm_spf_count + 1
    end
end

#
# Show all the advisory file locks held by a process for each of the vnode
# type files that it has open; do this by walking the per process open file
# table and looking at any vnode type fileglob that has a non-NULL lock list
# associated with it.
#
define showproclocks
    if ($argc == 1)
	_showproclocks $arg0
    else
    	printf "| Usage:\n|\n"
	help showproclocks
    end
end
document showproclocks
Syntax: (gdb) showproclocks <proc_t>
| Given a proc_t pointer, display the list of advisory file locks held by the
| referenced process.
end

define _showproclocks
    set $kgm_spl_filedesc = ((proc_t)$arg0)->p_fd
    set $kgm_spl_last = $kgm_spl_filedesc->fd_lastfile
    set $kgm_spl_ofiles = $kgm_spl_filedesc->fd_ofiles
    set $kgm_spl_count = 0
    set $kgm_spl_seen = 0
    while ($kgm_spl_count <= $kgm_spl_last)
	if ($kgm_spl_ofiles[$kgm_spl_count] == 0)
	    # DEBUG: For files that were open, but are now closed
	    # printf "%-5d  FILEPROC_NULL\n", $kgm_spl_count
	else
	    set $kgm_spl_fg = $kgm_spl_ofiles[$kgm_spl_count].f_fglob
	    # decode fileglob type
	    set $kgm_spl_fgt = $kgm_spl_fg->fg_type
	    if ($kgm_spl_fgt == 1)
		set $kgm_spl_fgd = $kgm_spl_fg->fg_data
	    	set $kgm_spl_name = ((struct vnode *)$kgm_spl_fgd)->v_name
		set $kgm_spl_vnode = ((vnode_t)$kgm_spl_fgd)
		set $kgm_spl_lockiter = $kgm_spl_vnode->v_lockf
		if ($kgm_spl_lockiter != 0)
		    if ($kgm_spl_seen == 0)
			_showvnodelockheader
		    end
		    set $kgm_spl_seen = $kgm_spl_seen + 1
		    printf "( fd %d, name ", $kgm_spl_count
		    if ($kgm_spl_name == 0)
			printf "(null) )"
		    else
			printf "%s )\n", $kgm_spl_name
		    end
		    _showvnodelocks $kgm_spl_fgd
		end
	    end
	end
    	set $kgm_spl_count = $kgm_spf_count + 1
    end
    printf "%d total locks for 0x%08x\n", $kgm_spl_seen, $arg0
end

define showprocinfo
    set $kgm_spi_proc = (proc_t)$arg0
    printf "Process 0x%08x\n", $kgm_spi_proc
    printf "   name %s\n", $kgm_spi_proc->p_comm
	printf "   pid:%.8d", $kgm_spi_proc->p_pid
	printf "   task:0x%.8x", $kgm_spi_proc->task
	printf "   p_stat:%.1d", $kgm_spi_proc->p_stat
	printf "   parent pid:%.8d", $kgm_spi_proc->p_ppid
    # decode part of credential
    set $kgm_spi_cred = $kgm_spi_proc->p_ucred
    if ($kgm_spi_cred != 0)
	printf "Cred: euid %d ruid %d svuid %d\n", $kgm_spi_cred->cr_uid, $kgm_spi_cred->cr_ruid, $kgm_spi_cred->cr_svuid
    else
    	printf "Cred: (null)\n"
    end
    # decode flags
    set $kgm_spi_flag = $kgm_spi_proc->p_flag
    printf "Flags: 0x%08x\n", $kgm_spi_flag
    if ($kgm_spi_flag & 0x00000001)
	printf "    0x00000001 - may hold advisory locks\n"
    end
    if ($kgm_spi_flag & 0x00000002)
	printf "    0x00000002 - has a controlling tty\n"
    end
    if ($kgm_spi_flag & 0x00000004)
	printf "    0x00000004 - process is 64 bit\n"
    else
	printf "   !0x00000004 - process is 32 bit\n"
    end
    if ($kgm_spi_flag & 0x00000008)
	printf "    0x00000008 - no SIGCHLD on child stop\n"
    end
    if ($kgm_spi_flag & 0x00000010)
	printf "    0x00000010 - waiting for child exec/exit\n"
    end
    if ($kgm_spi_flag & 0x00000020)
	printf "    0x00000020 - has started profiling\n"
    end
    if ($kgm_spi_flag & 0x00000040)
	printf "    0x00000040 - in select; wakeup/waiting danger\n"
    end
    if ($kgm_spi_flag & 0x00000080)
	printf "    0x00000080 - was stopped and continued\n"
    end
    if ($kgm_spi_flag & 0x00000100)
	printf "    0x00000100 - has set privileges since exec\n"
    end
    if ($kgm_spi_flag & 0x00000200)
	printf "    0x00000200 - system process: no signals, stats, or swap\n"
    end
    if ($kgm_spi_flag & 0x00000400)
	printf "    0x00000400 - timing out during a sleep\n"
    end
    if ($kgm_spi_flag & 0x00000800)
	printf "    0x00000800 - debugged process being traced\n"
    end
    if ($kgm_spi_flag & 0x00001000)
	printf "    0x00001000 - debugging process has waited for child\n"
    end
    if ($kgm_spi_flag & 0x00002000)
	printf "    0x00002000 - exit in progress\n"
    end
    if ($kgm_spi_flag & 0x00004000)
	printf "    0x00004000 - process has called exec\n"
    end
    if ($kgm_spi_flag & 0x00008000)
	printf "    0x00008000 - owe process an addupc() XXX\n"
    end
    if ($kgm_spi_flag & 0x00010000)
	printf "    0x00010000 - affinity for Rosetta children\n"
    end
    if ($kgm_spi_flag & 0x00020000)
	printf "    0x00020000 - wants to run Rosetta\n"
    end
    if ($kgm_spi_flag & 0x00040000)
	printf "    0x00040000 - has wait() in progress\n"
    end
    if ($kgm_spi_flag & 0x00080000)
	printf "    0x00080000 - kdebug tracing on for this process\n"
    end
    if ($kgm_spi_flag & 0x00100000)
	printf "    0x00100000 - blocked due to SIGTTOU or SIGTTIN\n"
    end
    if ($kgm_spi_flag & 0x00200000)
	printf "    0x00200000 - has called reboot()\n"
    end
    if ($kgm_spi_flag & 0x00400000)
	printf "    0x00400000 - is TBE state\n"
    end
    if ($kgm_spi_flag & 0x00800000)
	printf "    0x00800000 - signal exceptions\n"
    end
    if ($kgm_spi_flag & 0x01000000)
	printf "    0x01000000 - being branch traced\n"
    end
    if ($kgm_spi_flag & 0x02000000)
	printf "    0x02000000 - has vfork() children\n"
    end
    if ($kgm_spi_flag & 0x04000000)
	printf "    0x04000000 - not allowed to attach\n"
    end
    if ($kgm_spi_flag & 0x08000000)
	printf "    0x08000000 - vfork() in progress\n"
    end
    if ($kgm_spi_flag & 0x10000000)
	printf "    0x10000000 - no shared libraries\n"
    end
    if ($kgm_spi_flag & 0x20000000)
	printf "    0x20000000 - force quota for root\n"
    end
    if ($kgm_spi_flag & 0x40000000)
	printf "    0x40000000 - no zombies when children exit\n"
    end
    if ($kgm_spi_flag & 0x80000000)
	printf "    0x80000000 - don't hang on remote FS ops\n"
    end
    # decode state
    set $kgm_spi_state = $kgm_spi_proc->p_stat
    printf "State: "
    if ($kgm_spi_state == 1)
    	printf "Idle\n"
    end
    if ($kgm_spi_state == 2)
    	printf "Run\n"
    end
    if ($kgm_spi_state == 3)
    	printf "Sleep\n"
    end
    if ($kgm_spi_state == 4)
    	printf "Stop\n"
    end
    if ($kgm_spi_state == 5)
    	printf "Zombie\n"
    end
    if ($kgm_spi_state == 6)
    	printf "Reaping\n"
    end
    if ($kgm_spi_state < 1 || $kgm_spi_state > 6)
    	printf "(Unknown)\n"
    end
end

document showprocinfo
Syntax: (gdb) showprocinfo <proc_t>
| Displays name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields.
end

#
# dump the zombprocs 
#
define zombproc
  set $basep = (struct proc  *)zombproc->lh_first
  set $pp = $basep
  while $pp
	showprocinfo $pp
      set $pp = $pp->p_list.le_next
  end
end

document zombproc
Syntax: (gdb) zombproc 
| Routine to print out all procs in the zombie list
end

#
# dump the zombstacks 
#
define zombstacks
  set $basep = (struct proc  *)zombproc->lh_first
  set $pp = $basep
  while $pp
	if $pp->p_stat != 5
		showtaskstacks $pp->task
	end
     set $pp = $pp->p_list.le_next
  end
end

document zombstacks
Syntax: (gdb) zombstacks 
| Routine to print out all stacks of tasks that are exiting
end


#
# dump the allprocs
#
define allproc
  set $basep = (struct proc  *)allproc->lh_first
  set $pp = $basep
  while $pp
	showprocinfo $pp
      set $pp = $pp->p_list.le_next
  end
end

document allproc
Syntax: (gdb) allproc 
| Routine to print out all process in the system 
| which are not in the zombie list
end



define print_vnode
   set $vp = (struct vnode *)$arg0
   printf "   "
   printf " vp 0x%.8x", $vp
   printf " use %d", $vp->v_usecount
   printf " io %d", $vp->v_iocount
   printf " kuse %d", $vp->v_kusecount
   printf " type %d", $vp->v_type
   printf " flg 0x%.8x", $vp->v_flag
   printf " lflg 0x%.8x", $vp->v_lflag
   printf " par 0x%.8x", $vp->v_parent
   set $_name = (char *)$vp->v_name
   if ($_name != 0)
      printf " %s", $_name
   end
  if ($vp->v_type == VREG) && ($vp->v_un.vu_ubcinfo != 0)
       printf " mapped %d", ($vp->v_un.vu_ubcinfo.ui_flags & 0x08) ? 1 : 0
   end
   printf "\n"
end

document print_vnode
Syntax: (gdb) print_vnode <vnode>
| Prints out the fields of a vnode struct
end

define showprocvnodes
	set $pp = (struct proc *)$arg0
	set $fdp = (struct filedesc *)$pp->p_fd
	set $cvp = $fdp->fd_cdir
	set $rvp = $fdp->fd_rdir
	if $cvp
		printf "Current Working Directory \n"
		print_vnode $cvp
		printf "\n"
	end
	if $rvp
		printf "Current Root Directory \n"
		print_vnode $rvp
		printf "\n"
	end
	set $count = 0
	set $fpp =  (struct fileproc **)($fdp->fd_ofiles)
	set $fpo =  (char)($fdp->fd_ofileflags[0])
	while $count < $fdp->fd_nfiles
		#printf"fpp %x ", *$fpp
		if *$fpp
			set $fg =(struct fileglob *)((**$fpp)->f_fglob)
			if  $fg && (($fg)->fg_type == 1) 
				if $fdp->fd_ofileflags[$count] & 4
					printf "U: "
				else
					printf " "
				end
				printf "fd = %d ", $count
				print_vnode $fg->fg_data
			end
		end
		set $fpp = $fpp + 1
	 	set $count = $count + 1		
	end
end

document showprocvnodes
Syntax: (gdb) showprocvnodes <proc_address>
| Routine to print out all the open fds
| which are vnodes in a process
end

define showallprocvnodes
  set $basep = (struct proc  *)allproc->lh_first
  set $pp = $basep
  while $pp
	printf "============================================ \n"
	showprocinfo $pp
	showprocvnodes $pp
  	set $pp = $pp->p_list.le_next
  end
end

document showallprocvnodes
Syntax: (gdb) showallprocvnodes
| Routine to print out all the open fds
| which are vnodes 
end


#   
# dump the childrent of a proc 
#
define showinitchild
  set $basep = (struct proc  *)initproc->p_children.lh_first
  set $pp = $basep
  while $pp
	showprocinfo $pp
      set $pp = $pp->p_sibling.le_next
  end
end

document showinitchild
Syntax: (gdb) showinitchild 
| Routine to print out all processes in the system 
| which are children of init process
end


define showmountallvnodes
  set $mp = (struct mount *)$arg0
  set $basevp = (struct vnode *)$mp->mnt_vnodelist.tqh_first
  set $vp = $basevp
  printf "____________________ Vnode list Queue ---------------\n"
  while $vp
      print_vnode $vp
      set $vp = $vp->v_mntvnodes->tqe_next
  end
  set $basevp = (struct vnode *)$mp->mnt_workerqueue.tqh_first
  set $vp = $basevp
  printf "____________________ Worker Queue ---------------\n"
  while $vp
      print_vnode $vp
      set $vp = $vp->v_mntvnodes->tqe_next
  end
  set $basevp = (struct vnode *)$mp->mnt_newvnodes.tqh_first
  set $vp = $basevp
  printf "____________________ New vnodes  Queue ---------------\n"
  while $vp
      print_vnode $vp
      set $vp = $vp->v_mntvnodes->tqe_next
  end
end
document showmountallvnodes
Syntax: showmountallvnodes <struct mount *>
| Print the vnode inactive list
end


define showmountvnodes
  set $mp = (struct mount *)$arg0
  set $basevp = (struct vnode *)$mp->mnt_vnodelist.tqh_first
  set $vp = $basevp
  printf "____________________ Vnode list Queue ---------------\n"
  while $vp
      print_vnode $vp
      set $vp = $vp->v_mntvnodes->tqe_next
  end
end
document showmountvnodes
Syntax: showmountvnodes <struct mount *>
| Print the vnode list
end



define showworkqvnodes
  set $mp = (struct mount *)$arg0
  set $basevp = (struct vnode *)$mp->mnt_workerqueue.tqh_first
  set $vp = $basevp
  printf "____________________ Worker Queue ---------------\n"
  while $vp
      print_vnode $vp
      set $vp = $vp->v_mntvnodes->tqe_next
  end
end
document showworkqvnodes
Syntax: showworkqvnodes <struct mount *>
| Print the vnode worker list
end


define shownewvnodes
  set $mp = (struct mount *)$arg0
  set $basevp = (struct vnode *)$mp->mnt_newvnodes.tqh_first
  set $vp = $basevp
  printf "____________________ New vnodes  Queue ---------------\n"
  while $vp
      print_vnode $vp
      set $vp = $vp->v_mntvnodes->tqe_next
  end
end

document shownewvnodes
Syntax: shownewvnodes <struct mount *>
| Print the new vnode list
end


#
# print mount point info
define print_mount 
   set $mp = (struct mount *)$arg0
   printf "   "
   printf " mp 0x%.8x", $mp
   printf " flag %x", $mp->mnt_flag
   printf " kern_flag %x", $mp->mnt_kern_flag
   printf " lflag %x", $mp->mnt_lflag
   printf " type:  %s", $mp->mnt_vfsstat.f_fstypename
   printf " mnton:  %s", $mp->mnt_vfsstat.f_mntonname
   printf " mntfrom:  %s", $mp->mnt_vfsstat.f_mntfromname
   printf "\n"
end

define showallmounts
	set $mp=(struct mount *)mountlist.tqh_first
	while $mp
	 	print_mount $mp
		set $mp = $mp->mnt_list.tqe_next
	end
end
	
document showallmounts
Syntax: showallmounts
| Print all mount points
end

define pcprint
	set $pc = $arg0
	if ((unsigned int)$pc <= (unsigned int) $kgm_fkmodmax) && \
	    ((unsigned int)$pc >= (unsigned int)$kgm_fkmodmin)
		showkmodaddr $pc
	else
		output/a $pc
	end
end

define mbuf_walkpkt
	set $mp = (struct mbuf *)$arg0
	set $cnt = 1
	set $tot = 0
	while $mp
		printf "%4d: 0x%08x [len %4d, type %2d, ", $cnt, $mp, \
		    $mp->m_hdr.mh_len, $mp->m_hdr.mh_type
		if mclaudit != 0
			mbuf_buf2mca $mp
			printf ", "
		end
		set $tot = $tot + $mp->m_hdr.mh_len
		printf "total %d]\n", $tot
		set $mp = $mp->m_hdr.mh_nextpkt
		set $cnt = $cnt + 1
	end
end

document mbuf_walkpkt
Syntax: (gdb) mbuf_walkpkt <addr>
| Given an mbuf address, walk its m_nextpkt pointer
end

define mbuf_walk
	set $mp = (struct mbuf *)$arg0
	set $cnt = 1
	set $tot = 0
	while $mp
		printf "%4d: 0x%08x [len %4d, type %2d, ", $cnt, $mp, \
		    $mp->m_hdr.mh_len, $mp->m_hdr.mh_type
		if mclaudit != 0
			mbuf_buf2mca $mp
			printf ", "
		end
		set $tot = $tot + $mp->m_hdr.mh_len
		printf "total %d]\n", $tot
		set $mp = $mp->m_hdr.mh_next
		set $cnt = $cnt + 1
	end
end

document mbuf_walk
Syntax: (gdb) mbuf_walk <addr>
| Given an mbuf address, walk its m_next pointer
end

define mbuf_buf2slab
	set $addr = $arg0
	set $gix = ((char *)$addr - (char *)mbutl) >> 20
	set $ix = ((char *)$addr - (char *)mbutl) >> 11
	set $slab = &slabstbl[$gix].slg_slab[$ix]
	printf "0x%08x", $slab
end

document mbuf_buf2slab
| Given an mbuf object, find its corresponding slab address.
end

define mbuf_buf2mca
	set $addr = $arg0
	set $ix = ((char *)$addr - (char *)mbutl) >> 11
	set $clbase = ((union mcluster *)(mbutl + $ix))
	set $mclidx = (((char *)$addr - (char *)$clbase) >> 8)
	set $mca = mclaudit[$ix].cl_audit[$mclidx]
	printf "mca: 0x%08x", $mca
end

document mbuf_buf2mca
Syntax: (gdb) mbuf_buf2mca <addr>
| Given an mbuf object, find its buffer audit structure address.
| This requires mbuf buffer auditing to be turned on, by setting
| the appropriate flags to the "mbuf_debug" boot-args parameter.
end

define mbuf_showmca
	set language c
	set $mca = (mcache_audit_t *)$arg0
	set $cp = (mcache_t *)$mca->mca_cache
	printf "object type:\t\t"
	mbuf_mca_ctype $mca 1
	printf "\ncontrolling mcache:\t%p (%s)\n", $mca->mca_cache, $cp->mc_name
	if $mca->mca_uflags & $MB_SCVALID
		set $ix = ((char *)$mca->mca_addr - (char *)mbutl) >> 11
		set $clbase = ((union mcluster *)(mbutl + $ix))
		set $mclidx = (((char *)$mca->mca_addr - (char *)$clbase) >> 8)
		printf "mbuf obj:\t\t%p\n", $mca->mca_addr
		printf "mbuf index:\t\t%d (out of 8) in cluster base %p\n", \
		    $mclidx + 1, $clbase
		if $mca->mca_uptr != 0
			set $peer_mca = (mcache_audit_t *)$mca->mca_uptr
			printf "paired cluster obj:\t%p (mca %p)\n", \
			    $peer_mca->mca_addr, $peer_mca
		end
		printf "saved contents:\t\t%p (%d bytes)\n", \
		    $mca->mca_contents, $mca->mca_contents_size
	else
		printf "cluster obj:\t\t%p\n", $mca->mca_addr
		if $mca->mca_uptr != 0
			set $peer_mca = (mcache_audit_t *)$mca->mca_uptr
			printf "paired mbuf obj:\t%p (mca %p)\n", \
			    $peer_mca->mca_addr, $peer_mca
		end
	end
	printf "recent transaction for this buffer (thread %p):\n", \
	    $mca->mca_thread
	set $cnt = 0
	while $cnt < $mca->mca_depth
		set $pc = $mca->mca_stack[$cnt]
		printf "%4d: ", $cnt + 1
		pcprint $pc
		printf "\n"
		set $cnt = $cnt + 1
	end
	if $mca->mca_pdepth > 0
		printf "previous transaction for this buffer (thread %p):\n", \
		    $mca->mca_pthread
	end
	set $cnt = 0
	while $cnt < $mca->mca_pdepth
		set $pc = $mca->mca_pstack[$cnt]
		printf "%4d: ", $cnt + 1
		pcprint $pc
		printf "\n"
		set $cnt = $cnt + 1
	end
	set language auto
end

document mbuf_showmca
Syntax: (gdb) mbuf_showmca <addr>
| Given an mbuf/cluster buffer audit structure address, print the audit
| records including the stack trace of the last buffer transaction.
end

set $MCF_NOCPUCACHE = 0x10

define mcache_stat
	set $head = (mcache_t *)mcache_head
	set $mc = $head
	printf "cache                        cache      cache    buf   buf    backing             (# of retries)     bufs\n"
	printf "name                         state       addr   size align       zone     wait   nowait   failed  incache\n"
	printf "------------------------- -------- ---------- ------ ----- ---------- -------------------------- --------\n"
	while $mc != 0
		set $bktsize = $mc->mc_cpu.cc_bktsize
		printf "%-25s ", $mc->mc_name
		if ($mc->mc_flags & $MCF_NOCPUCACHE)
			printf "disabled"
		else
			if $mc->mc_purge_cnt > 0
				printf " purging"
			else
				if $bktsize == 0
					printf " offline"
				else
					printf "  online"
				end
			end
		end
		printf " 0x%08x %6d %5d ",$mc, \
		    $mc->mc_bufsize, $mc->mc_align
		if $mc->mc_slab_zone != 0
			printf "0x%08x", $mc->mc_slab_zone
		else
			printf "    custom"
		end
		set $tot = 0
		set $tot += $mc->mc_full.bl_total * $bktsize
		set $ccp = (mcache_cpu_t *)$mc->mc_cpu
		set $n = 0
		while $n < ncpu
			if $ccp->cc_objs > 0
				set $tot += $ccp->cc_objs
			end
			if $ccp->cc_pobjs > 0
				set $tot += $ccp->cc_pobjs
			end
			set $n += 1
			set $ccp += 1
		end
		printf " %8d %8d %8d %8d", $mc->mc_wretry_cnt, \
		    $mc->mc_nwretry_cnt, $mc->mc_nwfail_cnt, $tot
		printf "\n"
		set $mc = (mcache_t *)$mc->mc_list.le_next
	end
end

document mcache_stat
Syntax: (gdb) mcache_stat
| Print all mcaches in the system.
end

define mcache_showzone
	set $mc = (mcache_t *)$arg0
	if $mc->mc_slab_zone != 0
		printf "%p", $mc->mc_slab_zone
	else
		printf "   custom"
end

document mcache_showzone
Syntax: (gdb) mcache_showzone <mcache_addr>
| Print the type of backend (custom or zone) of a mcache.
end

define mcache_walkobj
	set $p = (mcache_obj_t *)$arg0
	set $cnt = 1
	set $tot = 0
	while $p
		printf "%4d: 0x%08x\n", $cnt, $p,
		set $p = $p->obj_next
		set $cnt = $cnt + 1
	end
end

document mcache_walkobj
Syntax: (gdb) mcache_walkobj <addr>
| Given a mcache object address, walk its obj_next pointer
end

define mcache_showcache
	set $cp = (mcache_t *)$arg0
	set $ccp = (mcache_cpu_t *)$cp->mc_cpu
	set $bktsize = $cp->mc_cpu.cc_bktsize
	set $cnt = 0
	set $tot = 0
	printf "Showing cache '%s':\n\n", $cp->mc_name
	printf " CPU  cc_objs cc_pobjs    total\n"
	printf "---- -------- -------- --------\n"
	while $cnt < ncpu
		set $objs = $ccp->cc_objs
		if $objs <= 0
			set $objs = 0
		end
		set $pobjs = $ccp->cc_pobjs
		if $pobjs <= 0
			set $pobjs = 0
		end
		set $tot_cpu = $objs + $pobjs
		set $tot += $tot_cpu
		printf "%4d %8d %8d %8d\n", $cnt, $objs, $pobjs, $tot_cpu
		set $ccp += 1
		set $cnt += 1
	end
	printf "                       ========\n"
	printf "                       %8d\n", $tot
	printf "\n"
	set $tot += $cp->mc_full.bl_total * $bktsize
	printf "Total # of full buckets (%d objs/bkt):\t%-8d\n", \
	    $bktsize, $cp->mc_full.bl_total
	printf "Total # of objects cached:\t\t%-8d\n", $tot
end

document mcache_showcache
| Display the number of objects in the cache
end

set $NSLABSPMB = sizeof(mcl_slabg_t)/sizeof(mcl_slab_t)

define mbuf_slabstbl
	set $x = 0

	printf "slot addr       slabs range\n"
	printf "---- ---------- -----------------------\n"
	while $x < maxslabgrp
		set $slg = slabstbl[$x]
		printf "%3d: ", $x
		if $slg == 0
			printf "-\n"
		else
			printf "%p [%p-%p]\n", $slg, &$slg->slg_slab[0], \
			    &$slg->slg_slab[$NSLABSPMB-1]
		end
		set $x += 1
	end
end

document mbuf_slabstbl
| Display the mbuf slabs table
end

set $SLF_MAPPED=0x0001
set $SLF_PARTIAL=0x0002
set $SLF_DETACHED=0x0004

define mbuf_slabs
	set $slg = (mcl_slabg_t *)$arg0
	set $x = 0

	printf "slot addr       next       base        C  R  N   size flags\n"
	printf "---- ---------- ---------- ---------- -- -- -- ------ -----\n"
	while $x < $NSLABSPMB
		set $sl = &$slg->slg_slab[$x]
		printf "%3d: 0x%08x 0x%08x 0x%08x %2d %2d %2d %6d 0x%04x ", \
		    $x + 1, $sl, $sl->sl_next, $sl->sl_base, $sl->sl_class, \
		    $sl->sl_refcnt, $sl->sl_chunks, $sl->sl_len, \
		    $sl->sl_flags
		if $sl->sl_flags != 0
			printf "<"
			if $sl->sl_flags & $SLF_MAPPED
				printf "mapped"
			end
			if $sl->sl_flags & $SLF_PARTIAL
				printf ",partial"
			end
			if $sl->sl_flags & $SLF_DETACHED
				printf ",detached"
			end
			printf ">"
		end
		printf "\n"
		set $x += 1
	end
end

document mbuf_slabs
| Display all mbuf slabs in the group
end

define mbuf_stat
	set $x = 0

	printf "class               total   cached     uncached           inuse           failed   waiter notified    purge\n"
	printf "name                 objs     objs     objs / slabs        objs      alloc count    count    count    count\n"
	printf "---------------- -------- -------- ------------------- -------- ---------------- -------- -------- --------\n"
	while $x < (sizeof(mbuf_table) / sizeof(mbuf_table[0]))
		set $mbt = mbuf_table[$x]
		set $mcs = (mb_class_stat_t *)mbuf_table[$x].mtbl_stats
		set $tot = 0
		set $mc = $mbt->mtbl_cache
		set $bktsize = $mc->mc_cpu.cc_bktsize
		set $tot += $mc->mc_full.bl_total * $bktsize
		set $ccp = (mcache_cpu_t *)$mc->mc_cpu
		set $n = 0
		while $n < ncpu
			if $ccp->cc_objs > 0
				set $tot += $ccp->cc_objs
			end
			if $ccp->cc_pobjs > 0
				set $tot += $ccp->cc_pobjs
			end
			set $n += 1
			set $ccp += 1
		end

		printf "%-16s %8d %8d %8d / %-8d %8d %16llu %8d %8llu %8llu", \
		    $mcs->mbcl_cname, $mcs->mbcl_total, $tot, \
		    $mcs->mbcl_infree, $mcs->mbcl_slab_cnt, \
		    ($mcs->mbcl_total - $tot - $mcs->mbcl_infree), \
		    $mcs->mbcl_fail_cnt, $mc->mc_waiter_cnt, \
		    $mcs->mbcl_notified, $mcs->mbcl_purge_cnt
		printf "\n"
		set $x += 1
	end
end

document mbuf_stat
| Print extended mbuf allocator statistics.
end

set $MB_INUSE = 0x1
set $MB_COMP_INUSE = 0x2
set $MB_SCVALID = 0x4

set $MCLBYTES = 2048
set $MSIZE = 256
set $NBPG = 4096
set $M16KCLBYTES = 16384

define mbuf_mca_ctype
	set $mca = (mcache_audit_t *)$arg0
	set $vopt = $arg1
	set $cp = $mca->mca_cache
	set $class = (unsigned int)$cp->mc_private
	set $csize = mbuf_table[$class].mtbl_stats->mbcl_size
	set $done = 0
	if $csize == $MSIZE
		if $vopt
			printf "M (mbuf) "
		else
			printf "M     "
		end
		set $done = 1
	end
	if !$done && $csize == $MCLBYTES
		if $vopt
			printf "CL (2K cluster) "
		else
			printf "CL    "
		end
		set $done = 1
	end
	if !$done && $csize == $NBPG
		if $vopt
			printf "BCL (4K cluster) "
		else
			printf "BCL   "
		end
		set $done = 1
	end
	if !$done && $csize == $M16KCLBYTES
		if $vopt
			printf "JCL (16K cluster) "
		else
			printf "JCL   "
		end
		set $done = 1
	end
	if !$done && $csize == ($MSIZE+$MCLBYTES)
		if $mca->mca_uflags & $MB_SCVALID
			if $mca->mca_uptr
				printf "M+CL  "
				if $vopt
					printf "(paired mbuf, 2K cluster)"
				end
			else
				printf "M-CL  "
				if $vopt
					printf "(unpaired mbuf, 2K cluster) "
				end
			end
		else
			if $mca->mca_uptr
				printf "CL+M  "
				if $vopt
					printf "(paired 2K cluster, mbuf) "
				end
			else
				printf "CL-M  "
				if $vopt
					printf "(paired 2K cluster, mbuf) "
				end
			end
		end
		set $done = 1
	end
	if !$done && $csize == ($MSIZE+$NBPG)
		if $mca->mca_uflags & $MB_SCVALID
			if $mca->mca_uptr
				printf "M+BCL "
				if $vopt
					printf "(paired mbuf, 4K cluster) "
				end
			else
				printf "M-BCL "
				if $vopt
					printf "(unpaired mbuf, 4K cluster) "
				end
			end
		else
			if $mca->mca_uptr
				printf "BCL+M "
				if $vopt
					printf "(paired 4K cluster, mbuf) "
				end
			else
				printf "BCL-M "
				if $vopt
					printf "(unpaired 4K cluster, mbuf) "
				end
			end
		end
		set $done = 1
	end
	if !$done && $csize == ($MSIZE+$M16KCLBYTES)
		if $mca->mca_uflags & $MB_SCVALID
			if $mca->mca_uptr
				printf "M+JCL "
				if $vopt
					printf "(paired mbuf, 16K cluster) "
				end
			else
				printf "M-JCL "
				if $vopt
					printf "(unpaired mbuf, 16K cluster) "
				end
			end
		else
			if $mca->mca_uptr
				printf "JCL+M "
				if $vopt
					printf "(paired 16K cluster, mbuf) "
				end
			else
				printf "JCL-M "
				if $vopt
					printf "(unpaired 16K cluster, mbuf) "
				end
			end
		end
		set $done = 1
	end
	if !$done
		printf "unknown: %s ", $cp->mc_name
	end
end

document mbuf_mca_ctype
| This is a helper macro for mbuf_show{active,inactive,all} that prints
| out the mbuf object type represented by a given mcache audit structure.
end

define mbuf_showactive
	mbuf_walkallslabs 1 0
end

document mbuf_showactive
Syntax: (gdb) mbuf_showactive
| Walk the mbuf objects pool and print only the active ones; this
| requires mbuf debugging to be turned on, by setting the appropriate flags
| to the "mbuf_debug" boot-args parameter.  Active objects are those that
| are outstanding (have not returned to the mbuf slab layer) and in use
| by the client (have not been freed).
end

define mbuf_showinactive
	mbuf_walkallslabs 0 1
end

document mbuf_showinactive
Syntax: (gdb) mbuf_showinactive
| Walk the mbuf objects pool and print only the inactive ones; this
| requires mbuf debugging to be turned on, by setting the appropriate flags
| to the "mbuf_debug" boot-args parameter.  Inactive objects are those that
| are outstanding (have not returned to the mbuf slab layer) but have been
| freed by the client, i.e. they still reside in the mcache layer ready to
| be used for subsequent allocation requests.
end

define mbuf_showall
	mbuf_walkallslabs 1 1
end

document mbuf_showall
Syntax: (gdb) mbuf_showall
| Walk the mbuf objects pool and print them all; this requires
| mbuf debugging to be turned on, by setting the appropriate flags to the
| "mbuf_debug" boot-args parameter.
end

define mbuf_mcaobjs
end

define mbuf_walkallslabs
	set $show_a = $arg0
	set $show_f = $arg1
	set $x = 0
	set $total = 0
	set $total_a = 0
	set $total_f = 0

	printf "("
	if $show_a && !$show_f
		printf "Searching only for active "
	end
	if !$show_a && $show_f
		printf "Searching only for inactive "
	end
	if $show_a && $show_f
		printf "Displaying all "
	end
	printf "objects; this may take a while ...)\n\n"

	printf "                slab        mca        obj        allocation\n"
	printf "slot idx     address    address    address type        state\n"
	printf "---- ---- ---------- ---------- ---------- ----- -----------\n"

	while $x < slabgrp
		set $slg = slabstbl[$x]
		set $y = 0
		set $stop = 0
		while $y < $NSLABSPMB && $stop == 0
			set $sl = &$slg->slg_slab[$y]
			set $base = (char *)$sl->sl_base
			set $ix = ($base - (char *)mbutl) >> 11
			set $clbase = ((union mcluster *)(mbutl + $ix))
			set $mclidx = ($base - (char *)$clbase) >> 8
			set $mca = mclaudit[$ix].cl_audit[$mclidx]
			set $first = 1

			while $mca != 0 && $mca->mca_addr != 0
				set $printmca = 0
				if $mca->mca_uflags & ($MB_INUSE|$MB_COMP_INUSE)
					set $total_a = $total_a + 1
					set $printmca = $show_a
				else
					set $total_f = $total_f + 1
					set $printmca = $show_f
				end

				if $printmca != 0
					if $first == 1
						printf "%4d %4d 0x%08x ", $x, $y, $sl
					else
						printf "                     "
					end

					printf "0x%08x 0x%08x ", $mca, $mca->mca_addr
					mbuf_mca_ctype $mca 0
					if $mca->mca_uflags & ($MB_INUSE|$MB_COMP_INUSE)
						printf "active      "
					else
						printf "      freed "
					end
					if $first == 1
						set $first = 0
					end
					printf "\n"
					set $total = $total + 1
				end
				set $mca = $mca->mca_next
			end
			set $y += 1
			if $slg->slg_slab[$y].sl_base == 0
				set $stop = 1
			end
		end
		set $x += 1
	end
	if $total && $show_a && $show_f
		printf "\ntotal objects:\t%d\n", $total
		printf "active/unfreed:\t%d\n", $total_a
		printf "freed/in_cache:\t%d\n", $total_f
	end
end

document mbuf_walkallslabs
| Walk the mbuf objects pool; this requires mbuf debugging to be
| turned on, by setting the appropriate flags to the "mbuf_debug" boot-args
| parameter.  This is a backend routine for mbuf_show{active,inactive,all}.
end

define rtentry_trash
	set $rtd = (struct rtentry_dbg *)rttrash_head.tqh_first
	set $cnt = 0
	while $rtd != 0
		if $cnt == 0
			printf "      rtentry_dbg  ref flags\n"
			printf "      ------------ --- ----------\n"
		end
		printf "%4d: %p    %3d 0x%08x\n", $cnt + 1, $rtd, \
		    $rtd->rtd_refhold_cnt - $rtd->rtd_refrele_cnt, \
		    $rtd->rtd_entry.rt_flags
		set $rtd = $rtd->rtd_trash_link.tqe_next
		set $cnt = $cnt + 1
	end
end

document rtentry_trash
Syntax: (gdb) rtentry_trash
| Walk the list of trash route entries; this requires route entry
| debugging to be turned on, by setting the appropriate flags to the
| "rte_debug" boot-args parameter.
end

set $RTD_TRSTACK_SIZE = 8
set $RTD_REFHIST_SIZE = 4

define rtentry_showdbg
	set $rtd = (struct rtentry_dbg *)$arg0
	set $cnt = 0

	printf "Total holds: %d\n", $rtd->rtd_refhold_cnt
	printf "Next hold slot: %d\n", $rtd->rtd_refhold_next
	printf "Total releases: %d\n", $rtd->rtd_refrele_cnt
	printf "Next release slot: %d\n", $rtd->rtd_refrele_next

	set $ix = 0
	while $ix < $RTD_TRSTACK_SIZE
		set $pc = $rtd->rtd_alloc_stk_pc[$ix]
		if $pc != 0
			if $ix == 0
				printf "\nAlloc (thread %p):\n", \
				    $rtd->rtd_alloc_thread
			end
			printf "%4d: ", $ix + 1
			pcprint $pc
			printf "\n"
		end
		set $ix = $ix + 1
	end
	set $ix = 0
	while $ix < $RTD_TRSTACK_SIZE
		set $pc = $rtd->rtd_free_stk_pc[$ix]
		if $pc != 0
			if $ix == 0
				printf "\nFree: (thread %p)\n", \
				    $rtd->rtd_free_thread
			end
			printf "%4d: ", $ix + 1
			pcprint $pc
			printf "\n"
		end
		set $ix = $ix + 1
	end
	while $cnt < $RTD_REFHIST_SIZE
		set $ix = 0
		while $ix < $RTD_TRSTACK_SIZE
			set $pc = $rtd->rtd_refhold[$cnt].pc[$ix]
			if $pc != 0
				if $ix == 0
					printf "\nHold [%d] (thread %p):\n", \
					    $cnt, $rtd->rtd_refhold[$cnt].th
				end
				printf "%4d: ", $ix + 1
				pcprint $pc
				printf "\n"
			end
			set $ix = $ix + 1
		end
		set $cnt = $cnt + 1
	end
	set $cnt = 0
	while $cnt < $RTD_REFHIST_SIZE
		set $ix = 0
		while $ix < $RTD_TRSTACK_SIZE
			set $pc = $rtd->rtd_refrele[$cnt].pc[$ix]
			if $pc != 0
				if $ix == 0
					printf "\nRelease [%d] (thread %p):\n",\
					    $cnt, $rtd->rtd_refrele[$cnt].th
				end
				printf "%4d: ", $ix + 1
				pcprint $pc
				printf "\n"
			end
			set $ix = $ix + 1
		end
		set $cnt = $cnt + 1
	end
end

document rtentry_showdbg
Syntax: (gdb) rtentry_showdbg <addr>
| Given a route entry structure address, print the debug information
| related to it.  This requires route entry debugging to be turned
| on, by setting the appropriate flags to the "rte_debug" boot-args
| parameter.
end

#
# print all OSMalloc stats 

define ostag_print
set $kgm_tagp = (OSMallocTag)$arg0
printf "0x%08x: ", $kgm_tagp
printf "%8d ",$kgm_tagp->OSMT_refcnt
printf "%8x ",$kgm_tagp->OSMT_state
printf "%8x ",$kgm_tagp->OSMT_attr
printf "%s ",$kgm_tagp->OSMT_name
printf "\n"
end


define showosmalloc 
printf "TAG          COUNT     STATE     ATTR     NAME\n"
set $kgm_tagheadp = (OSMallocTag)&OSMalloc_tag_list
    set $kgm_tagptr = (OSMallocTag )($kgm_tagheadp->OSMT_link.next)
    while $kgm_tagptr != $kgm_tagheadp
	ostag_print $kgm_tagptr
	set $kgm_tagptr = (OSMallocTag)$kgm_tagptr->OSMT_link.next
    end
	printf "\n"
end
document showosmalloc
Syntax: (gdb) showosmalloc
| Print the outstanding allocation count by OSMallocTags.
end


define systemlog
    if msgbufp->msg_bufc[msgbufp->msg_bufx] == 0
        # The buffer hasn't wrapped, so take the easy (and fast!) path
        printf "%s", msgbufp->msg_bufc
    else
        set $kgm_msgbuf = *msgbufp
        set $kgm_syslog_bufsize = $kgm_msgbuf.msg_size
        set $kgm_syslog_bufend = $kgm_msgbuf.msg_bufx
        if $kgm_syslog_bufend >= $kgm_syslog_bufsize
            set $kgm_syslog_bufend = 0
        end
    
        # print older messages from msg_bufx to end of buffer
        set $kgm_i = $kgm_syslog_bufend
        while $kgm_i < $kgm_syslog_bufsize
            set $kgm_syslog_char = $kgm_msgbuf.msg_bufc[$kgm_i]
            if $kgm_syslog_char == 0
                # break out of loop
                set $kgm_i = $kgm_syslog_bufsize
            else
                printf "%c", $kgm_syslog_char
            end
            set $kgm_i = $kgm_i + 1
        end
        
        # print newer messages from start of buffer to msg_bufx
        set $kgm_i = 0
        while $kgm_i < $kgm_syslog_bufend
            set $kgm_syslog_char = $kgm_msgbuf.msg_bufc[$kgm_i]
            printf "%c", $kgm_syslog_char
            set $kgm_i = $kgm_i + 1
        end
    end
    printf "\n"
end
document systemlog
| Syntax: systemlog
| Display the kernel's printf ring buffer
end

define printvnodepathint_recur
	if $arg0 != 0
		if ($arg0->v_flag & 0x000001) && ($arg0->v_mount != 0)
			if $arg0->v_mount->mnt_vnodecovered != 0
				printvnodepathint_recur  $arg0->v_mount->mnt_vnodecovered $arg0->v_mount->mnt_vnodecovered->v_name
			end
		else
			printvnodepathint_recur $arg0->v_parent $arg0->v_parent->v_name
			printf "/%s", $arg1
		end
	end
end

#
# Show the locks held on a vnode by range, type, and holder.
#
define showvnodelocks
    if ($argc == 1)
    	_showvnodelockheader
	_showvnodelocks $arg0
    else
    	printf "| Usage:\n|\n"
	help showvnodelocks
    end
end
document showvnodelocks
| Given a vnodet pointer, display the list of advisory record locks for the
| referenced pvnode.
| The following is the syntax:
|     (gdb) showvnodelocks <vnode_t>
end

define _showvnodelockheader
    printf "*  type   W  held by        lock type  start               end\n"
    printf "-  -----  -  -------------  ---------  ------------------  ------------------\n"
end

#
# Macro to display a single lock; used to display both held locks and
# blocked locks
#
define _showvnodelock
    set $kgm_svl_lock = ((struct lockf *)$arg0)

    # decode flags
    set $kgm_svl_flags = $kgm_svl_lock->lf_flags
    set $kgm_svl_type = $kgm_svl_lock->lf_type
    if ($kgm_svl_flags & 0x20)
	printf "flock"
    end
    if ($kgm_svl_flags & 0x40)
	printf "posix"
    end
    if ($kgm_svl_flags & 0x80)
	printf "prov "
    end
    if ($kgm_svl_flags & 0x10)
	printf "  W  "
    else
	printf "  .  "
    end

    # POSIX file vs. advisory range locks
    if ($kgm_svl_flags & 0x40)
	set $kgm_svl_proc = (proc_t)$kgm_svl_lock->lf_id
	printf "PID %8d   ", $kgm_svl_proc->p_pid
    else
	printf "ID 0x%08x  ", $kgm_svl_lock->lf_id
    end

    # lock type
    if ($kgm_svl_type == 1)
		printf "shared     "
    else
	if ($kgm_svl_type == 3)
		printf "exclusive  "
	else
	    if ($kgm_svl_type == 2)
		printf "unlock     "
	    else
		printf "unknown    "
	    end
	end
    end

    # start and stop
    printf "0x%016x..", $kgm_svl_lock->lf_start
    printf "0x%016x  ", $kgm_svl_lock->lf_end
    printf "\n"
end

# Body of showvnodelocks, not including header
define _showvnodelocks
    set $kgm_svl_vnode = ((vnode_t)$arg0)
    set $kgm_svl_lockiter = $kgm_svl_vnode->v_lockf
    while ($kgm_svl_lockiter != 0)
	# locks that are held
    	printf "H  "
    	_showvnodelock $kgm_svl_lockiter

	# and any locks blocked by them
	set $kgm_svl_blocker = $kgm_svl_lockiter->lf_blkhd.tqh_first
	while ($kgm_svl_blocker != 0)
	    printf ">  "
	    _showvnodelock $kgm_svl_blocker
	    set $kgm_svl_blocker = $kgm_svl_blocker->lf_block.tqe_next
	end

	# and on to the next one...
    	set $kgm_svl_lockiter = $kgm_svl_lockiter->lf_next
    end
end

define showvnodepath
	set $vp = (struct vnode *)$arg0
	if $vp != 0
		if ($vp->v_flag & 0x000001) && ($vp->v_mount != 0) && ($vp->v_mount->mnt_flag & 0x00004000)
			printf "/"
		else
			printvnodepathint_recur $vp $vp->v_name
		end
	end
	printf "\n"
end

document showvnodepath
Syntax: (gdb) showvnodepath <vnode>
| Prints the path for a vnode
end

define printcolonhex
    if ($argc == 2) 
	set $addr = $arg0
	set $count = $arg1
	set $li = 0
	while ($li < $count)
	    if ($li == 0)
		printf "%02x", (u_char)$addr[$li]
	    end
	    if ($li != 0)
		printf ":%02x", (u_char)$addr[$li]
	    end
	    set $li = $li + 1
	end
    end
end

define showsockaddr_dl
    set $sdl = (struct sockaddr_dl *)$arg0
    printf "LINK "
    if ($sdl == 0)
	printf "(null)"
    else
	set $addr = $sdl->sdl_data + $sdl->sdl_nlen
	set $count = $sdl->sdl_alen
	printcolonhex $addr $count
    end
end

define showsockaddr_unspec
    set $sockaddr = (struct sockaddr *)$arg0
    set $addr = $sockaddr->sa_data
    set $count = $sockaddr->sa_len - 2
    printf "UNSP "
    printcolonhex $addr $count
end

define showsockaddr_at
    set $sockaddr = (struct sockaddr *)$arg0
    set $addr = $sockaddr->sa_data
    set $count = $sockaddr->sa_len - 2
    printf "ATLK "
    printcolonhex $addr $count
end

define showsockaddr_in
    set $sin = (struct sockaddr_in *)$arg0
    set $sa_bytes = (unsigned char *)&($sin->sin_addr)
    printf "IPV4 %d.%d.%d.%d", $sa_bytes[0], $sa_bytes[1], $sa_bytes[2], $sa_bytes[3]
end

define showsockaddr_in6
    set $sin6 = (struct sockaddr_in6 *)$arg0
    set $sa_bytes = $sin6->sin6_addr.__u6_addr.__u6_addr8
    printf "IPV6 %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", $sa_bytes[0], $sa_bytes[1], $sa_bytes[2], $sa_bytes[3], $sa_bytes[4], $sa_bytes[5], $sa_bytes[6], $sa_bytes[7], $sa_bytes[8], $sa_bytes[9], $sa_bytes[10], $sa_bytes[11], $sa_bytes[12], $sa_bytes[13], $sa_bytes[14], $sa_bytes[15]
end

define showifmultiaddrs
   set $ifp = (struct ifnet *)$arg0
   set $if_multi = (struct ifmultiaddr *)$ifp->if_multiaddrs->lh_first
   set $mymulti = $if_multi
   set $myi = 0
   while ($mymulti != 0)
	printf "%2d. ", $myi
	set $sa_family = $mymulti->ifma_addr.sa_family
	if ($sa_family == 2)
	    if ($mymulti->ifma_ll != 0)
	    	showsockaddr_dl $mymulti->ifma_ll->ifma_addr
	        printf " "
	    end
	    showsockaddr_in $mymulti->ifma_addr
	end
	if ($sa_family == 30)
	    if ($mymulti->ifma_ll != 0)
	    	showsockaddr_dl $mymulti->ifma_ll->ifma_addr
	        printf " "
	    end
	    showsockaddr_in6 $mymulti->ifma_addr
	end
 	if ($sa_family == 18)
	    showsockaddr_dl $mymulti->ifma_addr
	end
	if ($sa_family == 0)
	    showsockaddr_unspec $mymulti->ifma_addr 6
	end
	printf " [%d]", $mymulti->ifma_refcount
	printf "\n"
	set $mymulti = $mymulti->ifma_link.le_next
	set $myi = $myi + 1
   end
end

document showifmultiaddrs
Syntax showifmultiaddrs <ifp>
| show the (struct ifnet).if_multiaddrs list of multicast addresses for the given ifp
end

define showsockaddr
    set $mysock = (struct sockaddr *)$arg0
    set $showsockaddr_handled = 0
    if ($mysock == 0)
	printf "(null)"
    else
	if ($mysock->sa_family == 0)
	    showsockaddr_unspec $mysock
	    set $showsockaddr_handled = 1
	end
	if ($mysock->sa_family == 2)
	    showsockaddr_in $mysock
	    set $showsockaddr_handled = 1
	end
	if ($mysock->sa_family == 30)
	    showsockaddr_in6 $mysock
	    set $showsockaddr_handled = 1
	end
	if ($mysock->sa_family == 18)
	    showsockaddr_dl $mysock
	    set $showsockaddr_handled = 1
	end
	if ($mysock->sa_family == 16)
	    showsockaddr_at $mysock
	    set $showsockaddr_handled = 1
	end
	if ($showsockaddr_handled == 0)
	    printf "%d ", $mysock->sa_family
	    set $addr = $mysock->sa_data
	    set $count = $mysock->sa_len
	    printcolonhex $addr $count
	end
    end
end

define showifflags
	set $flags = (u_short)$arg0
	set $first = 1
	printf "<"
	if ($flags & 0x1)
	    printf "UP"
	    set $first = 0
	end
	if ($flags & 0x2)
	    if ($first == 1)
		set $first = 0
	    else
	    	printf ","
	    end
	    printf "BROADCAST"
	end
	if ($flags & 0x4)
	    printf "DEBUG"
	end
	if ($flags & 0x8)
	    if ($first == 1)
		set $first = 0
	    else
	    	printf ","
	    end
	    printf "LOOPBACK"
	end
	if ($flags & 0x10)
	    if ($first == 1)
		set $first = 0
	    else
	    	printf ","
	    end
	    printf "POINTTOPOINT"
	end
#	if ($flags & 0x20)
#	    if ($first == 1)
#		set $first = 0
#	    else
#	    	printf ","
#	    end
#	    printf "NOTRAILERS"
#	end
	if ($flags & 0x40)
	    if ($first == 1)
		set $first = 0
	    else
	    	printf ","
	    end
	    printf "RUNNING"
	end
	if ($flags & 0x80)
	    if ($first == 1)
		set $first = 0
	    else
	    	printf ","
	    end
	    printf "NOARP"
	end
	if ($flags & 0x100)
	    if ($first == 1)
		set $first = 0
	    else
	    	printf ","
	    end
	    printf "PROMISC"
	end
	if ($flags & 0x200)
	    if ($first == 1)
		set $first = 0
	    else
	    	printf ","
	    end
	    printf "ALLMULTI"
	end
	if ($flags & 0x400)
	    if ($first == 1)
		set $first = 0
	    else
	    	printf ","
	    end
	    printf "OACTIVE"
	end
	if ($flags & 0x800)
	    if ($first == 1)
		set $first = 0
	    else
	    	printf ","
	    end
	    printf "SIMPLEX"
	end
	if ($flags & 0x1000)
	    if ($first == 1)
		set $first = 0
	    else
	    	printf ","
	    end
	    printf "LINK0"
	end
	if ($flags & 0x2000)
	    if ($first == 1)
		set $first = 0
	    else
	    	printf ","
	    end
	    printf "LINK1"
	end
	if ($flags & 0x4000)
	    if ($first == 1)
		set $first = 0
	    else
	    	printf ","
	    end
	    printf "LINK2-ALTPHYS"
	end
	if ($flags & 0x8000)
	    if ($first == 1)
		set $first = 0
	    else
	    	printf ","
	    end
	    printf "MULTICAST"
	end
	printf ">"
end

define showifaddrs
   set $ifp = (struct ifnet *)$arg0
   set $myifaddr = (struct ifaddr *)$ifp->if_addrhead->tqh_first
   set $myi = 0
   while ($myifaddr != 0)
	printf "\t%d. ", $myi
	showsockaddr $myifaddr->ifa_addr
	printf " [%d]\n", $myifaddr->ifa_refcnt
	set $myifaddr = $myifaddr->ifa_link->tqe_next
	set $myi = $myi + 1
   end
end

document showifaddrs
Syntax: showifaddrs <ifp>
| show the (struct ifnet).if_addrhead list of addresses for the given ifp
end

define ifconfig
   set $ifconfig_all = 0
   if ($argc == 1)
	set $ifconfig_all = 1
   end
   set $ifp = (struct ifnet *)(ifnet->tqh_first)
   while ($ifp != 0)
	printf "%s%d: flags=%x", $ifp->if_name, $ifp->if_unit, (u_short)$ifp->if_flags
	showifflags $ifp->if_flags
	printf " mtu %d\n", $ifp->if_data.ifi_mtu
	printf "\t(struct ifnet *)0x%x\n", $ifp
	if ($ifconfig_all == 1) 
	   showifaddrs $ifp
        end
	set $ifp = $ifp->if_link->tqe_next
   end
end
document ifconfig
Syntax: (gdb) ifconfig
| display ifconfig-like output, and print the (struct ifnet *) pointers for further inspection
end

define showbpfdtab
    set $myi = 0
    while ($myi < bpf_dtab_size)
	if (bpf_dtab[$myi] != 0)
		printf "Address 0x%x, bd_next 0x%x\n", bpf_dtab[$myi], bpf_dtab[$myi]->bd_next
		print *bpf_dtab[$myi]
	end
	set $myi = $myi + 1
    end
end

define showallvols
	printf "volume      mnt_data    mnt_devvp   typename    mountpoint\n"
	set $kgm_vol = (mount_t) mountlist.tqh_first
	while $kgm_vol
		printf "0x%08x  ", $kgm_vol
		printf "0x%08x  ", $kgm_vol->mnt_data
		printf "0x%08x  ", $kgm_vol->mnt_devvp
		if  ($kgm_vol->mnt_vtable->vfc_name[0] == 'h') && \
		    ($kgm_vol->mnt_vtable->vfc_name[1] == 'f') && \
		    ($kgm_vol->mnt_vtable->vfc_name[2] == 's') && \
		    ($kgm_vol->mnt_vtable->vfc_name[3] == '\0')
			set $kgm_hfsmount = \
			    (struct hfsmount *) $kgm_vol->mnt_data
			if $kgm_hfsmount->hfs_freezing_proc != 0
				printf "FROZEN hfs  "
			else
				printf "hfs         "
			end
		else
			printf "%-10s  ", $kgm_vol->mnt_vtable->vfc_name
		end
		printf "%s\n", $kgm_vol->mnt_vfsstat.f_mntonname
		
		set $kgm_vol = (mount_t) $kgm_vol->mnt_list.tqe_next
	end
end

document showallvols
Syntax: (gdb) showallvols
| Display a summary of mounted volumes
end

define showvnodeheader
	printf "vnode       usecount  iocount  v_data      vtype  parent      name\n"
end

define showvnodeint
	set $kgm_vnode = (vnode_t) $arg0
	printf "0x%08x  ", $kgm_vnode
	printf "%8d  ", $kgm_vnode->v_usecount
	printf "%7d  ", $kgm_vnode->v_iocount
# print information about clean/dirty blocks?
	printf "0x%08x  ", $kgm_vnode->v_data

	# print the vtype, using the enum tag
	set $kgm_vtype = $kgm_vnode->v_type
	if $kgm_vtype == VNON
		printf "VNON   "
	end
	if $kgm_vtype == VREG
		printf "VREG   "
	end
	if $kgm_vtype == VDIR
		printf "VDIR   "
	end
	if $kgm_vtype == VBLK
		printf "VBLK   "
	end
	if $kgm_vtype == VCHR
		printf "VCHR   "
	end
	if $kgm_vtype == VLNK
		printf "VLNK   "
	end
	if $kgm_vtype == VSOCK
		printf "VSOCK  "
	end
	if $kgm_vtype == VFIFO
		printf "VFIFO  "
	end
	if $kgm_vtype == VBAD
		printf "VBAD   "
	end
	if ($kgm_vtype < VNON) || ($kgm_vtype > VBAD)
		printf "%5d  ", $kgm_vtype
	end

	printf "0x%08x  ", $kgm_vnode->v_parent
	if $kgm_vnode->v_name != 0
		printf "%s\n", $kgm_vnode->v_name
	else
		printf "\n"
	end
end

define showvnode
	showvnodeheader
	showvnodeint $arg0
end

document showvnode
Syntax: (gdb) showvnode <vnode>
| Display info about one vnode
end

define showvolvnodes
	showvnodeheader
	set $kgm_vol = (mount_t) $arg0
	set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first
	while $kgm_vnode
		showvnodeint $kgm_vnode
		set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next
	end
end

document showvolvnodes
Syntax: (gdb) showvolvnodes <mouont_t>
| Display info about all vnodes of a given mount_t
end

define showvolbusyvnodes
	showvnodeheader
	set $kgm_vol = (mount_t) $arg0
	set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first
	while $kgm_vnode
		if $kgm_vnode->v_iocount != 0
			showvnodeint $kgm_vnode
		end
		set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next
	end
end

document showvolbusyvnodes
Syntax: (gdb) showvolbusyvnodes <mount_t>
| Display info about busy (iocount!=0) vnodes of a given mount_t
end

define showallbusyvnodes
	showvnodeheader
	set $kgm_vol = (mount_t) mountlist.tqh_first
	while $kgm_vol
		set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first
		while $kgm_vnode
			if $kgm_vnode->v_iocount != 0
				showvnodeint $kgm_vnode
			end
			set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next
		end
		set $kgm_vol = (mount_t) $kgm_vol->mnt_list.tqe_next
	end
end

document showallbusyvnodes
Syntax: (gdb) showallbusyvnodes <vnode>
| Display info about all busy (iocount!=0) vnodes
end

define showallvnodes
	showvnodeheader
	set $kgm_vol = (mount_t) mountlist.tqh_first
	while $kgm_vol
		set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first
		while $kgm_vnode
			showvnodeint $kgm_vnode
			set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next
		end
		set $kgm_vol = (mount_t) $kgm_vol->mnt_list.tqe_next
	end
end

document showallvnodes
Syntax: (gdb) showallvnodes
| Display info about all vnodes
end

define _showvnodelockheader
    printf "*  type   W  held by        lock type  start               end\n"
    printf "-  -----  -  -------------  ---------  ------------------  ------------------\n"
end

define _showvnodelock
    set $kgm_svl_lock = ((struct lockf *)$arg0)

    # decode flags
    set $kgm_svl_flags = $kgm_svl_lock->lf_flags
    set $kgm_svl_type = $kgm_svl_lock->lf_type
    if ($kgm_svl_flags & 0x20)
	printf "flock"
    end
    if ($kgm_svl_flags & 0x40)
	printf "posix"
    end
    if ($kgm_svl_flags & 0x80)
	printf "prov "
    end
    if ($kgm_svl_flags & 0x10)
	printf "  W  "
    else
	printf "  .  "
    end

    # POSIX file vs. advisory range locks
    if ($kgm_svl_flags & 0x40)
	set $kgm_svl_proc = (proc_t)$kgm_svl_lock->lf_id
	printf "PID %8d   ", $kgm_svl_proc->p_pid
    else
	printf "ID 0x%08x  ", $kgm_svl_lock->lf_id
    end

    # lock type
    if ($kgm_svl_type == 1)
		printf "shared     "
    else
	if ($kgm_svl_type == 3)
		printf "exclusive  "
	else
	    if ($kgm_svl_type == 2)
		printf "unlock     "
	    else
		printf "unknown    "
	    end
	end
    end

    # start and stop
    printf "0x%016x..", $kgm_svl_lock->lf_start
    printf "0x%016x  ", $kgm_svl_lock->lf_end
    printf "\n"
end
# Body of showvnodelocks, not including header
define _showvnodelocks
    set $kgm_svl_vnode = ((vnode_t)$arg0)
    set $kgm_svl_lockiter = $kgm_svl_vnode->v_lockf
    while ($kgm_svl_lockiter != 0)
	# locks that are held
    	printf "H  "
    	_showvnodelock $kgm_svl_lockiter

	# and any locks blocked by them
	set $kgm_svl_blocker = $kgm_svl_lockiter->lf_blkhd.tqh_first
	while ($kgm_svl_blocker != 0)
	    printf ">  "
	    _showvnodelock $kgm_svl_blocker
	    set $kgm_svl_blocker = $kgm_svl_blocker->lf_block.tqe_next
	end

	# and on to the next one...
    	set $kgm_svl_lockiter = $kgm_svl_lockiter->lf_next
    end
end


define showvnodelocks
    if ($argc == 1)
    	_showvnodelockheader
	_showvnodelocks $arg0
    else
    	printf "| Usage:\n|\n"
	help showvnodelocks
    end
end

document showvnodelocks
Syntax: (gdb) showvnodelocks <vnode_t>
| Given a vnodet pointer, display the list of advisory record locks for the
| referenced pvnodes
end

define showbootargs
	printf "%s\n", (char*)((boot_args*)PE_state.bootArgs).CommandLine
end

document showbootargs
Syntax: showbootargs
| Display boot arguments passed to the target kernel
end

define showbootermemorymap
       set $kgm_boot_args = kernelBootArgs
       set $kgm_msize = kernelBootArgs->MemoryMapDescriptorSize
       set $kgm_mcount = kernelBootArgs->MemoryMapSize / $kgm_msize
       set $kgm_i = 0
       
       printf "Type       Physical Start   Number of Pages\n"
       while $kgm_i < $kgm_mcount
	     set $kgm_mptr = (EfiMemoryRange *)((unsigned long)kernelBootArgs->MemoryMap + $kgm_i * $kgm_msize)
#	     p/x *$kgm_mptr
	     if $kgm_mptr->Type == 0
	       printf "reserved  "
	     end
	     if $kgm_mptr->Type == 1
	       printf "LoaderCode"
	     end
	     if $kgm_mptr->Type == 2
	       printf "LoaderData"
	     end
	     if $kgm_mptr->Type == 3
	       printf "BS_code   "
	     end
	     if $kgm_mptr->Type == 4
	       printf "BS_data   "
	     end
	     if $kgm_mptr->Type == 5
	       printf "RT_code   "
	     end
	     if $kgm_mptr->Type == 6
	       printf "RT_data   "
	     end
	     if $kgm_mptr->Type == 7
	       printf "available "
	     end
	     if $kgm_mptr->Type == 8
    	       printf "Unusable  "
	     end
	     if $kgm_mptr->Type == 9
               printf "ACPI_recl "
	     end
	     if $kgm_mptr->Type == 10
               printf "ACPI_NVS  "
	     end
	     if $kgm_mptr->Type == 11
               printf "MemMapIO  "
	     end
	     if $kgm_mptr->Type == 12
               printf "MemPortIO "
	     end
	     if $kgm_mptr->Type == 13
               printf "PAL_code  "
	     end
	     if $kgm_mptr->Type > 13
               printf "UNKNOWN   "
	     end

       	     printf " %016llx %016llx\n", $kgm_mptr->PhysicalStart, $kgm_mptr->NumberOfPages
	     set $kgm_i = $kgm_i + 1
       end
end

document showbootermemorymap
Syntax: (gdb) showbootermemorymap
| Prints out the phys memory map from kernelBootArgs
end


define showstacksaftertask
    set $kgm_head_taskp = &default_pset.tasks
    set $kgm_taskp = (struct task *)$arg0
    while $kgm_taskp != $kgm_head_taskp
        showtaskheader
        showtaskint $kgm_taskp
        set $kgm_head_actp = &($kgm_taskp->threads)
        set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) 
        while $kgm_actp != $kgm_head_actp
            showactheader
            if ($decode_wait_events > 0)
               showactint $kgm_actp 1
            else
               showactint $kgm_actp 2
            end
            set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
        end
        printf "\n"
        set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next)
    end
end
document showstacksaftertask
Syntax: (gdb) showstacksaftertask <task>
| Routine to print out all stacks (as in showallstacks) starting after a given task
| Useful if that gdb refuses to print a certain task's stack.
end

define showpmworkqueueint
    set $kgm_pm_wq = (IOPMWorkQueue *)$arg0
    set $kgm_pm_node = (IOService *)$kgm_pm_wq->owner
    printf "0x%08x  0x%08x  ", $kgm_pm_wq, $kgm_pm_node
    printf "%02d ", $kgm_pm_node->pwrMgt->CurrentPowerState
    printf "%02d ", $kgm_pm_node->pwrMgt->MachineState
    printf "%02d  ", $kgm_pm_node->pwrMgt->WaitReason
    printf "%s\n", $kgm_pm_node->pwrMgt->Name
    set $kgm_pm_queue = &($kgm_pm_wq->fWorkQueue)
    set $kgm_pm_req = (IOPMRequest *) $kgm_pm_queue->next
    while ( (queue_entry_t) $kgm_pm_req != (queue_entry_t) $kgm_pm_queue)
        printf "   Request  0x%08x [%02x]  Args ", $kgm_pm_req, $kgm_pm_req->fType
        printf "0x%08x ", $kgm_pm_req->fArg0
        printf "0x%08x ", $kgm_pm_req->fArg1
        printf "0x%08x\n", $kgm_pm_req->fArg2
        set $kgm_pm_req = (IOPMRequest *)$kgm_pm_req->fCommandChain.next
    end
end

define showallpmworkqueues
    set $kgm_pm_next = gIOPMWorkLoop->eventChain
    printf "WorkQueue   Owner       PS MS WT  Name\n"
    printf "--------------------------------------\n"
    while ( $kgm_pm_next )
        set $kgm_vt = *((void **) $kgm_pm_next)
        if ($kgm_vt == _ZTV13IOPMWorkQueue)
            showpmworkqueueint $kgm_pm_next
        end
        set $kgm_pm_next = $kgm_pm_next->eventChainNext
    end
end

document showallpmworkqueues
Syntax: (gdb) showallpmworkqueues
| Display info about all IOPMWorkQueue objects
end

define showioservicepm
	set $kgm_iopmpriv = (IOServicePM *)$arg0
	printf "{ this object = %08x", $kgm_iopmpriv->Owner
	if ( $kgm_iopmpriv->WeAreRoot )
		printf " (root)"
	end
	printf ", "
	
	printf "MachineState = %d (", $kgm_iopmpriv->MachineState
	if ( $kgm_iopmpriv->MachineState == 1 )
		printf "kIOPM_OurChangeTellClientsPowerDown"
	else
		if ( $kgm_iopmpriv->MachineState == 2 )
			printf "kIOPM_OurChangeTellPriorityClientsPowerDown"
		else
			if ( $kgm_iopmpriv->MachineState == 3 )
				printf "kIOPM_OurChangeNotifyInterestedDriversWillChange"
			else
				if ( $kgm_iopmpriv->MachineState == 4 )
					printf "kIOPM_OurChangeSetPowerState"
				else
					if ( $kgm_iopmpriv->MachineState == 5 )
						printf "kIOPM_OurChangeWaitForPowerSettle"
					else
						if ( $kgm_iopmpriv->MachineState == 6 )
							printf "kIOPM_OurChangeNotifyInterestedDriversDidChange"
						else
							if ( $kgm_iopmpriv->MachineState == 7 )
								printf "kIOPM_OurChangeFinish"
							else
								if ( $kgm_iopmpriv->MachineState == 8 )
									printf "kIOPM_ParentDownTellPriorityClientsPowerDown"
								else
									if ( $kgm_iopmpriv->MachineState == 9 )
										printf "kIOPM_ParentDownNotifyInterestedDriversWillChange"
									else
										if ( $kgm_iopmpriv->MachineState == 10 )
											printf "Unused_MachineState_10"
										else
											if ( $kgm_iopmpriv->MachineState == 11 )
												printf "kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange"
											else
												if ( $kgm_iopmpriv->MachineState == 12 )
													printf "kIOPM_ParentDownSetPowerState"
												else
													if ( $kgm_iopmpriv->MachineState == 13 )
														printf "kIOPM_ParentDownWaitForPowerSettle"
													else
														if ( $kgm_iopmpriv->MachineState == 14 )
															printf "kIOPM_ParentDownAcknowledgeChange"
														else
															if ( $kgm_iopmpriv->MachineState == 15)
																printf "kIOPM_ParentUpSetPowerState"
															else
																if ( $kgm_iopmpriv->MachineState == 16)
																	printf "Unused_MachineState_16"
																else
																	if ( $kgm_iopmpriv->MachineState == 17)
																		printf "kIOPM_ParentUpWaitForSettleTime"
																	else
																		if ( $kgm_iopmpriv->MachineState == 18)
																			printf "kIOPM_ParentUpNotifyInterestedDriversDidChange"
																		else
																			if ( $kgm_iopmpriv->MachineState == 19)
																				printf "kIOPM_ParentUpAcknowledgePowerChange"
																			else
																				if ( $kgm_iopmpriv->MachineState == 20)
																					printf "kIOPM_Finished"
                                                                                else
                                                                                    if ( $kgm_iopmpriv->MachineState == 21)
                                                                                        printf "kIOPM_DriverThreadCallDone"
                                                                                    else
                                                                                        if ( $kgm_iopmpriv->MachineState == 22)
                                                                                            printf "kIOPM_NotifyChildrenDone"
                                                                                        end
                                                                                    end
																				end
																			end
																		end
																	end
																end
															end
														end
													end
												end
											end
										end
									end
								end
							end
						end
					end
				end
			end
		end
	end
	printf "), "
	
	if ( $kgm_iopmpriv->MachineState != 20 )
        printf "DriverTimer = %d, ",(unsigned int)$kgm_iopmpriv->DriverTimer
        printf "SettleTime  = %d, ",(unsigned int)$kgm_iopmpriv->SettleTimeUS
        printf "HeadNoteFlags = %08x, ",(unsigned int)$kgm_iopmpriv->HeadNoteFlags
        printf "HeadNoteState = %d, ",(unsigned int)$kgm_iopmpriv->HeadNoteState
        printf "HeadNoteOutputFlags = %08x, ",(unsigned int)$kgm_iopmpriv->HeadNoteOutputFlags
        printf "HeadNoteDomainState = %08x, ",(unsigned int)$kgm_iopmpriv->HeadNoteDomainState
        printf "HeadNoteCapabilityFlags = %08x, ",(unsigned int)$kgm_iopmpriv->HeadNoteCapabilityFlags
        printf "HeadNotePendingAcks = %x, ",(unsigned int)$kgm_iopmpriv->HeadNotePendingAcks
	end

    if ( $kgm_iopmpriv->DeviceOverrides != 0 )
        printf"DeviceOverrides, "
    end
	
    printf "DriverDesire = %d, ",(unsigned int)$kgm_iopmpriv->DriverDesire
    printf "DeviceDesire = %d, ",(unsigned int)$kgm_iopmpriv->DeviceDesire
    printf "DesiredPowerState = %d, ",(unsigned int)$kgm_iopmpriv->DesiredPowerState
    printf "PreviousRequest = %d }",(unsigned int)$kgm_iopmpriv->PreviousRequest
end

document showioservicepm
Syntax: (gdb) showioservicepm <IOServicePM pointer>
| Routine to dump the IOServicePM object
end

define showregistryentryrecursepmstate
    set $kgm_re         = (IOService *)$arg1
    set $kgm$arg0_stack = (unsigned long long) $arg2

    if ($arg3)
	set $kgm$arg0_stack = $kgm$arg0_stack | (1ULL << $kgm_reg_depth)
    else
	set $kgm$arg0_stack = $kgm$arg0_stack & ~(1ULL << $kgm_reg_depth)
    end

    dictget $kgm_re->fRegistryTable $kgm_childkey
    set $kgm$arg0_child_array = (OSArray *) $kgm_result

    if ($kgm$arg0_child_array)
	set $kgm$arg0_child_count = $kgm$arg0_child_array->count
    else
	set $kgm$arg0_child_count = 0
    end

    if ($kgm$arg0_child_count)
	set $kgm$arg0_stack = $kgm$arg0_stack | (2ULL << $kgm_reg_depth)
    else
	set $kgm$arg0_stack = $kgm$arg0_stack & ~(2ULL << $kgm_reg_depth)
    end

    indent $kgm_reg_depth $kgm$arg0_stack
    printf "+-o "

    dictget $kgm_re->fRegistryTable $kgm_namekey
    if ($kgm_result == 0)
	dictget $kgm_re->fRegistryTable gIONameKey
    end
    if ($kgm_result == 0)
	dictget $kgm_re->fPropertyTable gIOClassKey
    end

    if ($kgm_result != 0)
	printf "%s <%p>", ((OSString *)$kgm_result)->string, $kgm_re
    else
 	if (((IOService*)$kgm_re)->pwrMgt &&  ((IOService*)$kgm_re)->pwrMgt->Name)
 	    printf "%s <%p>", ((IOService*)$kgm_re)->pwrMgt->Name, $kgm_re
	else
	    printf "?? <%p>", $kgm_re
	end
    end

    if (((IOService*)$kgm_re)->pwrMgt )
    	printf " Current Power State: %ld ", ((IOService*)$kgm_re)->pwrMgt->CurrentPowerState
    	#printf " Mach State %ld", ((IOService*)$kgm_re)->pwrMgt->MachineState
        showioservicepm ((IOService*)$kgm_re)->pwrMgt
    end
    printf "\n"
   

    # recurse
    if ($kgm$arg0_child_count != 0)

	set $kgm_reg_depth = $kgm_reg_depth + 1
	set $kgm$arg0_child_idx = 0

	while ($kgm$arg0_child_idx < $kgm$arg0_child_count)
	    set $kgm_re = $kgm$arg0_child_array->array[$kgm$arg0_child_idx++]
	    set $kgm_more_sib = ($kgm$arg0_child_idx < $kgm$arg0_child_count)
	    showregistryentryrecursepmstate _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib
	end

	set $kgm_reg_depth = $kgm_reg_depth - 1
    end
end

define showregistryentryintpmstate
    set $kgm_namekey   = (OSSymbol *) $kgm_reg_plane[2]
    set $kgm_childkey  = (OSSymbol *) $kgm_reg_plane[4]
    showregistryentryrecursepmstate _ $arg0 0 0
end

define showregistrypmstate
#    setregistryplane gIOPowerPlane
    set $kgm_reg_depth  = 0
    set $kgm_show_props = 1
    showregistryentryintpmstate gRegistryRoot
end

document showregistrypmstate
Syntax: (gdb) showregistrypmstate
| Routine to dump the PM state of each IOPower registry entry
end

define showstacksafterthread
    set $kgm_head_taskp = &default_pset.tasks
    set $kgm_actp = (struct thread *)$arg0
    set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
    set $kgm_taskp = (struct task *)$kgm_actp->task
    while $kgm_taskp != $kgm_head_taskp
        showtaskheader
        showtaskint $kgm_taskp
        set $kgm_head_actp = &($kgm_taskp->threads)
        while $kgm_actp != $kgm_head_actp
            showactheader
            if ($decode_wait_events > 0)
               showactint $kgm_actp 1
            else
               showactint $kgm_actp 2
            end
            set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
        end
        printf "\n"
        set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next) 
    end
end

document showstacksafterthread
Syntax: (gdb) showstacksafterthread <thread>
| Routine to print out all stacks (as in showallstacks) starting after a given thread
| Useful if that gdb refuses to print a certain task's stack.
end

define kdp-reenter
       set kdp_reentry_deadline = ((unsigned) $arg0)*1000
       continue
end

document kdp-reenter
Syntax: (gdb) kdp-reenter <seconds>
| Schedules reentry into the debugger after <seconds> seconds, and resumes
| the target system.
end

define _if_present
    if (!$arg0)
        printf " not"
    end
    printf " present"
end

define showMCAstate
    if ($kgm_mtype != 7)
        printf "Not available for current architecture.\n"
    else
        printf "MCA"
        _if_present mca_MCA_present
        printf ", control MSR"
        _if_present mca_control_MSR_present
        printf ", threshold status"
        _if_present mca_threshold_status_present
        printf "\n%d error banks, ", mca_error_bank_count
        printf "family code 0x%x, ", mca_family
        printf "machine-check dump state: %d\n", mca_dump_state
        set $kgm_cpu = 0
        while cpu_data_ptr[$kgm_cpu] != 0
            set $kgm_mcp = cpu_data_ptr[$kgm_cpu]->cpu_mca_state
            if $kgm_mcp
                printf "CPU %d:", $kgm_cpu
                printf " mca_mcg_ctl: 0x%016llx", $kgm_mcp->mca_mcg_ctl
                printf " mca_mcg_status: 0x%016llx\n", $kgm_mcp->mca_mcg_status.u64
                printf "bank   "
                printf "mca_mci_ctl        "
                printf "mca_mci_status     "
                printf "mca_mci_addr       "
                printf "mca_mci_misc\n"
                set $kgm_bank = 0
                while $kgm_bank < mca_error_bank_count
                    set $kgm_bp = &$kgm_mcp->mca_error_bank[$kgm_bank]
                    printf " %2d:", $kgm_bank
                    printf " 0x%016llx", $kgm_bp->mca_mci_ctl
                    printf " 0x%016llx", $kgm_bp->mca_mci_status.u64
                    printf " 0x%016llx", $kgm_bp->mca_mci_addr
                    printf " 0x%016llx\n", $kgm_bp->mca_mci_misc
                    set $kgm_bank = $kgm_bank + 1
                end
            end
            set $kgm_cpu = $kgm_cpu + 1
        end
    end
end

document showMCAstate
Syntax: showMCAstate
| Print machine-check register state after MC exception.
end

define _pt_step
    #
    # Step to lower-level page table and print attributes
    #   $kgm_pt_paddr: current page table entry physical address
    #   $kgm_pt_index: current page table entry index (0..511)
    # returns
    #   $kgm_pt_paddr: next level page table entry physical address
    #                  or null if invalid
    # For $kgm_pt_verbose = 0: print nothing
    #                       1: print basic information
    #                       2: print basic information and hex table dump
    # The trickery with kdp_src_high32 is required for accesses above 4GB.
    #
    set $kgm_entryp = $kgm_pt_paddr + 8*$kgm_pt_index
    set kdp_src_high32 = $kgm_pt_paddr >> 32
    set kdp_trans_off = 1
    set $entry =  *(pt_entry_t *)($kgm_entryp & 0x0ffffffffULL)
    if $kgm_pt_verbose == 2
        x/512g ($kgm_pt_paddr & 0x0ffffffffULL)
    end
    set kdp_trans_off = 0
    set kdp_src_high32 = 0
    set $kgm_paddr_mask = ~((0xffffULL<<48) | 0xfffULL)
    if $kgm_pt_verbose == 0
        if $entry & (0x1 << 0)
            set $kgm_pt_paddr = $entry & $kgm_paddr_mask
        else
            set $kgm_pt_paddr = 0
        end
    else
        printf "0x%016llx:\n\t0x%016llx\n\t", $kgm_entryp, $entry
        if $entry & (0x1 << 0)
            printf "valid"	
            set $kgm_pt_paddr = $entry & $kgm_paddr_mask
        else
            printf "invalid"
            set $kgm_pt_paddr = 0
        end
        if $entry & (0x1 << 1)
            printf " writeable" 
        else
            printf " read-only" 
        end
        if $entry & (0x1 << 2)
            printf " user" 
        else
            printf " supervisor" 
        end
        if $entry & (0x1 << 3)
            printf " PWT" 
        end
        if $entry & (0x1 << 4)
            printf " PCD" 
        end
        if $entry & (0x1 << 5)
            printf " accessed" 
        end
        if $entry & (0x1 << 6)
            printf " dirty" 
        end
        if $entry & (0x1 << 7)
            printf " PAT" 
        end
        if $entry & (0x1 << 8)
            printf " global" 
        end
        if $entry & (0x3 << 9)
            printf " avail:0x%x", ($entry >> 9) & 0x3
        end
        if $entry & (0x1 << 63)
            printf " noexec" 
        end
        printf "\n"
    end
end

define _pmap_walk
    set $kgm_pmap = (pmap_t) $arg0
    set $kgm_vaddr = $arg1
    set $kgm_pt_paddr = $kgm_pmap->pm_cr3
    if $kgm_pt_paddr && cpu_64bit
        set $kgm_pt_index = ($kgm_vaddr >> 39) & 0x1ffULL
        if $kgm_pt_verbose
            printf "pml4 (index %d):\n", $kgm_pt_index
        end
        _pt_step
    end
    if $kgm_pt_paddr
        set $kgm_pt_index = ($kgm_vaddr >> 30) & 0x1ffULL
        if $kgm_pt_verbose
            printf "pdpt (index %d):\n", $kgm_pt_index
        end
        _pt_step
    end
    if $kgm_pt_paddr
        set $kgm_pt_index = ($kgm_vaddr >> 21) & 0x1ffULL
        if $kgm_pt_verbose
            printf "pdt (index %d):\n", $kgm_pt_index
        end
        _pt_step
    end
    if $kgm_pt_paddr
        set $kgm_pt_index = ($kgm_vaddr >> 12) & 0x1ffULL
        if $kgm_pt_verbose
            printf "pt (index %d):\n", $kgm_pt_index
        end
        _pt_step
    end
    if $kgm_pt_paddr
        set $kgm_paddr = $kgm_pt_paddr + ($kgm_vaddr & 0xfffULL)
        set kdp_trans_off = 1
        set kdp_src_high32 = $kgm_paddr >> 32
        set $kgm_value = *($kgm_paddr & 0x0ffffffffULL)
        set kdp_trans_off = 0
        set kdp_src_high32 = 0
        printf "phys 0x%016llx: 0x%08x\n", $kgm_paddr, $kgm_value
    else
        set $kgm_paddr = 0
        printf "(no translation)\n"
    end
end

define pmap_walk
    if $kgm_mtype != 7
        printf "Not available for current architecture.\n"
    else
        if $argc != 2
            printf "pmap_walk <pmap> <vaddr>\n"
        else
            if !$kgm_pt_verbose
                set $kgm_pt_verbose = 1
            else
                if $kgm_pt_verbose != 2
                    set $kgm_pt_verbose = 1
                end
            end
            _pmap_walk $arg0 $arg1
        end
    end
end

document pmap_walk
Syntax: (gdb) pmap_walk <pmap> <virtual_address>
| Perform a page-table walk in <pmap> for <virtual_address>.
| Set $kgm_pt_verbose=2 for full hex dump of page tables.
end

define pmap_vtop
    if $kgm_mtype != 7
        printf "Not available for current architecture.\n"
    else
        if $argc != 2
            printf "pmap_vtop <pamp> <vaddr>\n"
        else
            set $kgm_pt_verbose = 0
            _pmap_walk $arg0 $arg1
        end
    end
end

document pmap_vtop
Syntax: (gdb) pmap_vtop <pmap> <virtual_address>
| For page-tables in <pmap> translate <virtual_address> to physical address.
end

define zstack
	set $index = $arg0

	if (log_records == 0)
		set $count = 0
		printf "Zone logging not enabled.  Add 'zlog=<zone name>' to boot-args.\n"
	else 
		if ($argc == 2)
			set $count = $arg1
		else
			set $count = 1
		end
	end

	while ($count)
		printf "\n--------------- "

		if (zrecords[$index].z_opcode == 1)
			printf "ALLOC "
		else
			printf "FREE "
		end

		printf " 0x%x : index %d  :  ztime %d -------------\n", zrecords[$index].z_element, $index, zrecords[$index].z_time

		set $frame = 0

		while ($frame < 15)
			set $frame_pc = zrecords[$index].z_pc[$frame]

			if ($frame_pc == 0)
				loop_break
			end

			x/i $frame_pc
			set $frame = $frame + 1
		end

		set $index = $index + 1
		set $count = $count - 1
	end
end

document zstack
Syntax: (gdb) zstack <index> [<count>]
| Zone leak debugging: print the stack trace of log element at <index>.
| If a <count> is supplied, it prints <count> log elements starting at <index>.
|
| The suggested usage is to look at indexes below zcurrent and look for common stack traces.
| The stack trace that occurs the most is probably the cause of the leak.  Find the pc of the
| function calling into zalloc and use the countpcs kgmacro to find out how often that pc occurs in the log.
| The pc occuring in a high percentage of records is most likely the source of the leak.
|
| The findoldest kgmacro is also useful for leak debugging since it identifies the oldest record
| in the log, which may indicate the leaker.
end

define findoldest
	set $index = 0
	set $count = log_records
	set $cur_min = 2000000000
	set $cur_index = 0

	if (log_records == 0)
		printf "Zone logging not enabled.  Add 'zlog=<zone name>' to boot-args.\n"
	else

		while ($count)
			if (zrecords[$index].z_element && zrecords[$index].z_time < $cur_min)
				set $cur_index = $index
				set $cur_min = zrecords[$index].z_time
			end
	
			set $count = $count - 1
			set $index = $index + 1
		end
	
		printf "oldest record is at log index %d:\n", $cur_index
		zstack $cur_index
	end
end

document findoldest
Syntax: (gdb) findoldest
| Zone leak debugging: find and print the oldest record in the log.  Note that this command
| can take several minutes to run since it uses linear search.
|
| Once it prints a stack trace, find the pc of the caller above all the zalloc, kalloc and
| IOKit layers.  Then use the countpcs kgmacro to see how often this caller has allocated
| memory.  A caller with a high percentage of records in the log is probably the leaker.
end

define countpcs
	set $target_pc = $arg0
	set $index = 0
	set $count = log_records
	set $found = 0

	if (log_records == 0)
		printf "Zone logging not enabled.  Add 'zlog=<zone name>' to boot-args.\n"
	else

		while ($count)
			set $frame = 0
	
			if (zrecords[$index].z_element != 0)
				while ($frame < 15)
					if (zrecords[$index].z_pc[$frame] == $target_pc)
						set $found = $found + 1
						set $frame = 15
					end
		
					set $frame = $frame + 1
				end
			end
	
			set $index = $index + 1
			set $count = $count - 1
		end
	
		printf "occurred %d times in log (%d%c of records)\n", $found, ($found * 100) / zrecorded, '%'
	end
end

document countpcs
Syntax: (gdb) countpcs <pc>
| Zone leak debugging: search the log and print a count of all log entries that contain the given <pc>
| in the stack trace.  This is useful for verifying a suspected <pc> as being the source of
| the leak.  If a high percentage of the log entries contain the given <pc>, then it's most
| likely the source of the leak.  Note that this command can take several minutes to run.
end

define findelem
	set $fe_index = zcurrent
	set $fe_count = log_records
	set $fe_elem = $arg0
	set $fe_prev_op = -1

	if (log_records == 0)
		printf "Zone logging not enabled.  Add 'zlog=<zone name>' to boot-args.\n"
	end

	while ($fe_count)
		if (zrecords[$fe_index].z_element == $fe_elem)
			zstack $fe_index

			if (zrecords[$fe_index].z_opcode == $fe_prev_op)
				printf "***************   DOUBLE OP!   *********************\n
			end

			set $fe_prev_op = zrecords[$fe_index].z_opcode
		end

		set $fe_count = $fe_count - 1
		set $fe_index = $fe_index + 1

		if ($fe_index >= log_records)
			set $fe_index = 0
		end
	end
end

document findelem
Syntax: (gdb) findelem <elem addr>
| Zone corruption debugging: search the log and print out the stack traces for all log entries that
| refer to the given zone element.  When the kernel panics due to a corrupted zone element, get the
| element address and use this macro.  This will show you the stack traces of all logged zalloc and
| zfree operations which tells you who touched the element in the recent past.  This also makes
| double-frees readily apparent.
end