1# Kernel gdb macros
2#
3#  These gdb macros should be useful during kernel development in
4#  determining what's going on in the kernel.
5#
6#  All the convenience variables used by these macros begin with $kgm_
7
8set print asm-demangle on
9set cp-abi gnu-v2
10
11echo Loading Kernel GDB Macros package.  Type "help kgm" for more info.\n
12
13define kgm
14printf ""
15echo  These are the gdb macros for kernel debugging.  Type "help kgm" for more info.\n
16end
17
18document kgm
19| These are the kernel gdb macros.  These gdb macros are intended to be
20| used when debugging a remote kernel via the kdp protocol.  Typically, you
21| would connect to your remote target like so:
22| 		 (gdb) target remote-kdp
23| 		 (gdb) attach <name-of-remote-host>
24|
25| The following macros are available in this package:
26|     showversion    Displays a string describing the remote kernel version
27|
28|     showalltasks   Display a summary listing of all tasks
29|     showallthreads Display info about all threads in the system
30|     showallstacks  Display the stack for each thread in the system
31|     showcurrentthreads   Display info about the thread running on each cpu
32|     showcurrentstacks    Display the stack for the thread running on each cpu
33|     showallvm      Display a summary listing of all the vm maps
34|     showallvme     Display a summary listing of all the vm map entries
35|     showallipc     Display a summary listing of all the ipc spaces
36|     showallrights  Display a summary listing of all the ipc rights
37|     showallkmods   Display a summary listing of all the kernel modules
38|
39|     showallclasses    Display info about all OSObject subclasses in the system
40|     showobject        Show info about an OSObject - its vtable ptr and retain count, & more info for simple container classes.
41|     showregistry      Show info about all registry entries in the current plane
42|     showregistryprops Show info about all registry entries in the current plane, and their properties
43|     showregistryentry Show info about a registry entry; its properties and descendants in the current plane
44|     setregistryplane  Set the plane to be used for the iokit registry macros (pass zero for list)
45|
46|     showtask       Display info about the specified task
47|     showtaskthreads      Display info about the threads in the task
48|     showtaskstacks Display the stack for each thread in the task
49|     showtaskvm     Display info about the specified task's vm_map
50|     showtaskvme    Display info about the task's vm_map entries
51|     showtaskipc    Display info about the specified task's ipc space
52|     showtaskrights Display info about the task's ipc space entries
53|
54|     showact	     Display info about a thread specified by activation
55|     showactstack   Display the stack for a thread specified by activation
56|
57|     showmap	     Display info about the specified vm_map
58|     showmapvme     Display a summary list of the specified vm_map's entries
59|
60|     showipc        Display info about the specified ipc space
61|     showrights     Display a summary list of all the rights in an ipc space
62|
63|     showpid        Display info about the process identified by pid
64|     showproc       Display info about the process identified by proc struct
65|     showprocinfo   Display detailed info about the process identified by proc struct
66|     showprocfiles  Given a proc_t pointer, display the list of open file descriptors
67|     showproclocks  Given a proc_t pointer, display the list of advisory file locks
68|     zombproc       Print out all procs in the zombie list
69|     allproc        Print out all process in the system not in the zombie list
70|     zombstacks     Print out all stacks of tasks that are exiting
71|
72|     showinitchild  Print out all processes in the system which are children of init process
73|
74|     showkmod	     Display info about a kernel module
75|     showkmodaddr   Given an address, display the kernel module and offset
76|
77|     dumpcallqueue  Dump out all the entries given a queue head
78|
79|     showallmtx     Display info about mutexes usage
80|     showallrwlck   Display info about reader/writer locks usage
81|
82|     zprint         Display info about the memory zones
83|     showioalloc    Display info about iokit allocations
84|     paniclog       Display the panic log info
85|
86|     switchtoact    Switch to different context specified by activation
87|     switchtoctx    Switch to different context
88|     showuserstack  Display numeric backtrace of the user stack for an 
89|     		     activation
90|
91|     switchtouserthread Switch to the user context of the specified thread
92|     resetstacks    Return to the original kernel context
93|
94|     resetctx       Reset context
95|     resume_on      Resume when detaching from gdb
96|     resume_off     Don't resume when detaching from gdb 
97|
98|     sendcore	     Configure kernel to send a coredump to the specified IP
99|     disablecore    Configure the kernel to disable coredump transmission
100|     switchtocorethread Corefile version of "switchtoact"
101|     resetcorectx   Corefile version of "resetctx"
102|
103|     readphys       Reads the specified untranslated address
104|     readphys64     Reads the specified untranslated 64-bit address
105|
106|     rtentry_showdbg Print the debug information of a route entry
107|     rtentry_trash  Walk the list of trash route entries
108|
109|     mbuf_walkpkt   Walk the mbuf packet chain (m_nextpkt)
110|     mbuf_walk      Walk the mbuf chain (m_next)
111|     mbuf_buf2slab  Find the slab structure of the corresponding buffer
112|     mbuf_buf2mca   Find the mcache audit structure of the corresponding mbuf
113|     mbuf_showmca   Print the contents of an mbuf mcache audit structure
114|     mbuf_showactive   Print all active/in-use mbuf objects
115|     mbuf_showinactive Print all freed/in-cache mbuf objects 
116|     mbuf_showall   Print all mbuf objects
117|     mbuf_slabs     Print all slabs in the group
118|     mbuf_slabstbl  Print slabs table
119|     mbuf_stat      Print extended mbuf allocator statistics
120|
121|     mcache_walkobj     Walk the mcache object chain (obj_next)
122|     mcache_stat        Print all mcaches in the system
123|     mcache_showcache   Display the number of objects in the cache
124|
125|     showbootermemorymap Dump phys memory map from EFI
126|
127|     systemlog      Display the kernel's printf ring buffer
128|
129|     showvnodepath      Print the path for a vnode
130|     showvnodelocks     Display list of advisory locks held/blocked on a vnode
131|     showallvols        Display a summary of mounted volumes
132|     showvnode          Display info about one vnode
133|     showvolvnodes      Display info about all vnodes of a given volume
134|     showvolbusyvnodes  Display info about busy (iocount!=0) vnodes of a given volume
135|     showallbusyvnodes  Display info about all busy (iocount!=0) vnodes
136|     showallvnodes      Display info about all vnodes
137|     print_vnode        Print out the fields of a vnode struct
138|     showprocvnodes     Print out all the open fds which are vnodes in a process
139|     showallprocvnodes  Print out all the open fds which are vnodes in any process
140|     showmountvnodes    Print the vnode list
141|     showmountallvnodes Print the vnode inactive list
142|     showworkqvnodes    Print the vnode worker list
143|     shownewvnodes      Print the new vnode list
144|
145|     ifconfig       display ifconfig-like output
146|     showifaddrs    show the list of addresses for the given ifp
147|     showifmultiaddrs show the list of multicast addresses for the given ifp
148|
149|     showallpmworkqueues   Display info about all IOPMWorkQueue objects
150|     showregistrypmstate   Display power management state for all IOPower registry entries
151|     showioservicepm       Display the IOServicePM object
152|     showstacksaftertask   showallstacks starting after a given task
153|     showstacksafterthread showallstacks starting after a given thread
154|
155|     showMCAstate	Print machine-check register state after MC exception.
156|
157|     showallgdbstacks	Cause GDB to trace all thread stacks
158|     showallgdbcorestacks Corefile equivalent of "showallgdbstacks"
159|     kdp-reenter	Schedule reentry into the debugger and continue.
160|     kdp-reboot	Restart remote target
161|
162|     zstack		Print zalloc caller stack (zone leak debugging)
163|     findoldest	Find oldest zone leak debugging record
164|     countpcs		Print how often a pc occurs in the zone leak log
165|
166|
167| Type "help <macro>" for more specific help on a particular macro.
168| Type "show user <macro>" to see what the macro is really doing.
169end
170
171# This macro should appear before any symbol references, to facilitate
172# a gdb "source" without a loaded symbol file.
173define showversion
174       printf "%s\n", *(char **)0x501C
175end
176
177document showversion
178Syntax: showversion
179| Read the kernel version string from a fixed address in low
180| memory. Useful if you don't know which kernel is on the other end,
181| and need to find the appropriate symbols. Beware that if you've
182| loaded a symbol file, but aren't connected to a remote target,
183| the version string from the symbol file will be displayed instead.
184| This macro expects to be connected to the remote kernel to function
185| correctly.
186end
187
188set $kgm_mtype = ((struct mach_header)_mh_execute_header).cputype
189
190# This option tells gdb to relax its stack tracing heuristics
191# Useful for debugging across stack switches
192# (to the interrupt stack, for instance). Requires gdb-675 or greater.
193# Don't do this for arm as a workaround to 5486905
194if ($kgm_mtype != 12)
195	set backtrace sanity-checks off
196end
197
198set $kgm_dummy = &proc0
199set $kgm_dummy = &kmod
200
201set $kgm_reg_depth = 0
202set $kgm_reg_plane = (void **) gIOServicePlane
203set $kgm_namekey = (OSSymbol *) 0
204set $kgm_childkey = (OSSymbol *) 0
205
206set $kgm_show_object_addrs = 0
207set $kgm_show_object_retain = 0
208set $kgm_show_props = 0
209
210set $kgm_show_kmod_syms = 0
211
212define showkmodheader
213    printf "kmod        address     size        "
214    printf "id    refs     version  name\n"
215end
216
217define showkmodint
218    set $kgm_kmodp = (struct kmod_info *)$arg0
219    printf "0x%08x  ", $arg0
220    printf "0x%08x  ", $kgm_kmodp->address
221    printf "0x%08x  ", $kgm_kmodp->size
222    printf "%3d  ", $kgm_kmodp->id
223    printf "%5d  ", $kgm_kmodp->reference_count
224    printf "%10s  ", &$kgm_kmodp->version
225    printf "%s\n", &$kgm_kmodp->name
226end
227
228set $kgm_kmodmin = 0xffffffff
229set $kgm_fkmodmin = 0x00000000
230set $kgm_kmodmax = 0x00000000
231set $kgm_fkmodmax = 0xffffffff
232set $kgm_pkmod = 0
233set $kgm_pkmodst = 0
234set $kgm_pkmoden = 0
235define showkmodaddrint
236    printf "0x%x" , $arg0
237    if ((unsigned int)$arg0 >= (unsigned int)$kgm_pkmodst) && ((unsigned int)$arg0 <= (unsigned int)$kgm_pkmoden)
238	set $kgm_off = ((unsigned int)$arg0 - (unsigned int)$kgm_pkmodst)
239	printf " <%s + 0x%x>", $kgm_pkmod->name, $kgm_off
240    else
241        if  ((unsigned int)$arg0 <= (unsigned int)$kgm_fkmodmax) && ((unsigned int)$arg0 >= (unsigned int)$kgm_fkmodmin)
242	    set $kgm_kmodp = (struct kmod_info *)kmod
243	    while $kgm_kmodp
244		set $kgm_kmod = *$kgm_kmodp
245		if $kgm_kmod.address && ($kgm_kmod.address < $kgm_kmodmin)
246		    set $kgm_kmodmin = $kgm_kmod.address
247		end
248		if ($kgm_kmod.address + $kgm_kmod.size) > $kgm_kmodmax
249	    	    set $kgm_kmodmax = $kgm_kmod.address + $kgm_kmod.size
250	    	end
251	        set $kgm_off = ((unsigned int)$arg0 - (unsigned int)$kgm_kmod.address)
252	        if ($kgm_kmod.address <= $arg0) && ($kgm_off <= $kgm_kmod.size)
253		    printf " <%s + 0x%x>", $kgm_kmodp->name, $kgm_off
254		    set $kgm_pkmod = $kgm_kmodp
255		    set $kgm_pkmodst = $kgm_kmod.address
256		    set $kgm_pkmoden = $kgm_pkmodst + $kgm_kmod.size
257	    	    set $kgm_kmodp = 0
258	        else
259	    	    set $kgm_kmodp = $kgm_kmod.next
260	        end
261	    end
262	    if !$kgm_pkmod
263		set $kgm_fkmodmin = $kgm_kmodmin
264		set $kgm_fkmodmax = $kgm_kmodmax
265	    end
266	end
267    end
268end
269
270define showkmodaddr
271    showkmodaddrint $arg0
272end
273
274document showkmodaddr
275Syntax: (gdb) showkmodaddr <addr>
276| Given an address, print the offset and name for the kmod containing it
277end
278
279define showkmod
280    showkmodheader
281    showkmodint $arg0
282end
283document showkmod
284Syntax: (gdb) showkmod <kmod>
285| Routine to print info about a kernel module
286end
287
288define showallkmods
289    showkmodheader
290    set $kgm_kmodp = (struct kmod_info *)kmod
291    while $kgm_kmodp
292	showkmodint $kgm_kmodp
293    	set $kgm_kmodp = $kgm_kmodp->next
294    end
295end
296document showallkmods
297Syntax: (gdb) showallkmods
298| Routine to print a summary listing of all the kernel modules
299end
300
301define showactheader
302    printf "            thread      "
303    printf "processor   pri  state  wait_queue  wait_event\n"
304end
305
306
307define showactint
308	printf "            0x%08x  ", $arg0
309	set $kgm_thread = *(struct thread *)$arg0
310	printf "0x%08x  ", $kgm_thread.last_processor
311	printf "%3d  ", $kgm_thread.sched_pri
312	set $kgm_state = $kgm_thread.state
313	if $kgm_state & 0x80
314	    printf "I" 
315	end
316	if $kgm_state & 0x40
317	    printf "P" 
318	end
319	if $kgm_state & 0x20
320	    printf "A" 
321	end
322	if $kgm_state & 0x10
323	    printf "H" 
324	end
325	if $kgm_state & 0x08
326	    printf "U" 
327	end
328	if $kgm_state & 0x04
329	    printf "R" 
330	end
331	if $kgm_state & 0x02
332	    printf "S" 
333	end
334   	if $kgm_state & 0x01
335	    printf "W\t" 
336	    printf "0x%08x  ", $kgm_thread.wait_queue
337	    	if (((unsigned)$kgm_thread.wait_event > (unsigned)sectPRELINKB) \
338		    && ($arg1 != 2) && ($kgm_show_kmod_syms == 0))
339			showkmodaddr $kgm_thread.wait_event
340	        else
341			output /a (unsigned) $kgm_thread.wait_event
342		end
343		if ($kgm_thread.uthread != 0)
344		    set $kgm_uthread = (struct uthread *)$kgm_thread.uthread
345		    if ($kgm_uthread->uu_wmesg != 0)
346			printf " \"%s\"", $kgm_uthread->uu_wmesg
347		    end
348		end
349	end
350	if $arg1 != 0
351	    if ($kgm_thread.kernel_stack != 0)
352		if ($kgm_thread.reserved_stack != 0)
353			printf "\n\t\treserved_stack=0x%08x", $kgm_thread.reserved_stack
354		end
355		printf "\n\t\tkernel_stack=0x%08x", $kgm_thread.kernel_stack
356		if ($kgm_mtype == 18)
357			set $mysp = $kgm_thread.machine.pcb->save_r1
358		end
359		if ($kgm_mtype == 7)
360			set $kgm_statep = (struct x86_kernel_state32 *) \
361				($kgm_thread->kernel_stack + 0x4000 \
362				 - sizeof(struct x86_kernel_state32))
363			set $mysp = $kgm_statep->k_ebp
364		end
365		if ($kgm_mtype == 12)
366			if ($arg0 == $r9)
367				set $mysp = $r7
368			else
369				set $kgm_statep = (struct arm_saved_state *)$kgm_thread.machine.kstackptr
370				set $mysp = $kgm_statep->r[7]
371			end
372		end
373		set $prevsp = $mysp - 16
374		printf "\n\t\tstacktop=0x%08x", $mysp
375		if ($kgm_mtype == 18)
376			set $stkmask = 0xf
377		else
378			set $stkmask = 0x3
379		end
380		set $kgm_return = 0
381	    	while ($mysp != 0) && (($mysp & $stkmask) == 0) \
382		      && ($mysp != $prevsp) \
383		      && ((((unsigned) $mysp ^ (unsigned) $prevsp) < 0x2000) \
384		      || (((unsigned)$mysp < ((unsigned) ($kgm_thread->kernel_stack+0x4000))) \
385		      && ((unsigned)$mysp > (unsigned) ($kgm_thread->kernel_stack))))
386			printf "\n\t\t0x%08x  ", $mysp
387			if ($kgm_mtype == 18)
388				set $kgm_return = *($mysp + 8)
389			end
390			if ($kgm_mtype == 7)
391				set $kgm_return = *($mysp + 4)
392			end
393			if ($kgm_mtype == 12)
394				set $kgm_return = *($mysp + 4)
395			end
396			if (((unsigned) $kgm_return > (unsigned) sectPRELINKB) \
397			    && ($kgm_show_kmod_syms == 0))
398				showkmodaddr $kgm_return
399			else
400				output /a (unsigned) $kgm_return
401			end
402			set $prevsp = $mysp
403			set $mysp = * $mysp
404		end
405		set $kgm_return = 0
406		printf "\n\t\tstackbottom=0x%08x", $prevsp
407	    else
408		printf "\n\t\t\tcontinuation="
409		output /a (unsigned) $kgm_thread.continuation
410	    end
411	    printf "\n"
412	else
413	    printf "\n"
414	end
415end	    
416
417define showact
418    showactheader
419    showactint $arg0 0
420end
421document showact
422Syntax: (gdb) showact <activation> 
423| Routine to print out the state of a specific thread.
424end
425
426
427define showactstack
428    showactheader
429    showactint $arg0 1
430end
431document showactstack
432Syntax: (gdb) showactstack <activation> 
433| Routine to print out the stack of a specific thread.
434end
435
436
437define showallthreads
438    set $kgm_head_taskp = &tasks
439    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
440    while $kgm_taskp != $kgm_head_taskp
441        showtaskheader
442	showtaskint $kgm_taskp
443	showactheader
444	set $kgm_head_actp = &($kgm_taskp->threads)
445        set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
446	while $kgm_actp != $kgm_head_actp
447	    showactint $kgm_actp 0
448  	    set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
449        end
450	printf "\n"
451    	set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
452    end
453end
454document showallthreads
455Syntax: (gdb) showallthreads
456| Routine to print out info about all threads in the system.
457end
458
459define showcurrentthreads
460set $kgm_prp = (struct processor *)processor_list
461    while $kgm_prp != 0
462    	printf "Processor 0x%08x State %d (cpu_id %x)\n", $kgm_prp, ($kgm_prp)->state, ($kgm_prp)->cpu_num
463	if ($kgm_prp)->active_thread != 0
464	    set $kgm_actp = ($kgm_prp)->active_thread
465	    showtaskheader
466	    showtaskint ($kgm_actp)->task
467	    showactheader
468	    showactint $kgm_actp 0
469	    printf "\n"
470	end
471	set $kgm_prp = ($kgm_prp)->processor_list
472    end
473end
474document showcurrentthreads
475Syntax: (gdb) showcurrentthreads
476| Routine to print out info about the thread running on each cpu.
477end
478
479set $decode_wait_events = 0
480define showallstacks
481    set $kgm_head_taskp = &tasks
482    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
483    while $kgm_taskp != $kgm_head_taskp
484        showtaskheader
485	showtaskint $kgm_taskp
486	set $kgm_head_actp = &($kgm_taskp->threads)
487        set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
488	while $kgm_actp != $kgm_head_actp
489	    showactheader
490	    if ($decode_wait_events > 0)
491	       showactint $kgm_actp 1
492	    else
493	       showactint $kgm_actp 2
494	    end
495  	    set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
496        end
497	printf "\n"
498    	set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
499    end
500end
501
502document showallstacks
503Syntax: (gdb) showallstacks
504| Routine to print out the stack for each thread in the system.
505| If the variable $decode_wait_events is non-zero, the routine attempts to
506| interpret thread wait_events as kernel module offsets, which can add to
507| processing time.
508end
509
510define showcurrentstacks
511set $kgm_prp = processor_list
512    while $kgm_prp != 0
513    	printf "Processor 0x%08x State %d (cpu_id %x)\n", $kgm_prp, ($kgm_prp)->state, ($kgm_prp)->cpu_num
514	if ($kgm_prp)->active_thread != 0
515	    set $kgm_actp = ($kgm_prp)->active_thread
516	    showtaskheader
517	    showtaskint ($kgm_actp)->task
518	    showactheader
519	    showactint $kgm_actp 1
520	    printf "\n"
521	end
522	set $kgm_prp = ($kgm_prp)->processor_list
523    end
524end
525
526document showcurrentstacks
527Syntax: (gdb) showcurrentstacks
528| Routine to print out the thread running on each cpu (incl. its stack)
529end
530
531define showwaiterheader
532    printf "waiters     activation  "
533    printf "thread      pri  state  wait_queue  wait_event\n"
534end
535
536define showwaitqwaiters
537    set $kgm_w_waitqp = (struct wait_queue *)$arg0
538    set $kgm_w_linksp = &($kgm_w_waitqp->wq_queue)
539    set $kgm_w_wqe = (struct wait_queue_element *)$kgm_w_linksp->next
540    set $kgm_w_found = 0
541    while ( (queue_entry_t)$kgm_w_wqe != (queue_entry_t)$kgm_w_linksp)
542	if ($kgm_w_wqe->wqe_type != &_wait_queue_link)
543		if !$kgm_w_found
544			set $kgm_w_found = 1
545			showwaiterheader
546		end
547		set $kgm_w_shuttle = (struct thread *)$kgm_w_wqe
548		showactint $kgm_w_shuttle 0
549	end	
550	set $kgm_w_wqe = (struct wait_queue_element *)$kgm_w_wqe->wqe_links.next
551    end
552end
553
554define showwaitqwaitercount
555    set $kgm_wc_waitqp = (struct wait_queue *)$arg0
556    set $kgm_wc_linksp = &($kgm_wc_waitqp->wq_queue)
557    set $kgm_wc_wqe = (struct wait_queue_element *)$kgm_wc_linksp->next
558    set $kgm_wc_count = 0
559    while ( (queue_entry_t)$kgm_wc_wqe != (queue_entry_t)$kgm_wc_linksp)
560	if ($kgm_wc_wqe->wqe_type != &_wait_queue_link)
561        	set $kgm_wc_count = $kgm_wc_count + 1
562	end
563        set $kgm_wc_wqe = (struct wait_queue_element *)$kgm_wc_wqe->wqe_links.next
564    end
565    printf "0x%08x  ", $kgm_wc_count
566end
567
568define showwaitqmembercount
569    set $kgm_mc_waitqsetp = (struct wait_queue_set *)$arg0
570    set $kgm_mc_setlinksp = &($kgm_mc_waitqsetp->wqs_setlinks)
571    set $kgm_mc_wql = (struct wait_queue_link *)$kgm_mc_setlinksp->next
572    set $kgm_mc_count = 0
573    while ( (queue_entry_t)$kgm_mc_wql != (queue_entry_t)$kgm_mc_setlinksp)
574        set $kgm_mc_count = $kgm_mc_count + 1
575        set $kgm_mc_wql = (struct wait_queue_link *)$kgm_mc_wql->wql_setlinks.next
576    end
577    printf "0x%08x  ", $kgm_mc_count
578end
579
580    
581define showwaitqmemberheader
582    printf "set-members wait_queue  interlock   "
583    printf "pol  type   member_cnt  waiter_cnt\n"
584end
585
586define showwaitqmemberint
587    set $kgm_m_waitqp = (struct wait_queue *)$arg0
588    printf "            0x%08x  ", $kgm_m_waitqp
589    printf "0x%08x  ", $kgm_m_waitqp->wq_interlock.lock_data
590    if ($kgm_m_waitqp->wq_fifo)
591        printf "Fifo "
592    else
593	printf "Prio "
594    end
595    if ($kgm_m_waitqp->wq_type == 0xf1d1)
596	printf "Set    "
597	showwaitqmembercount $kgm_m_waitqp
598    else
599	printf "Que    0x00000000  "
600    end
601    showwaitqwaitercount $kgm_m_waitqp
602    printf "\n"
603end
604
605
606define showwaitqmemberofheader
607    printf "member-of   wait_queue  interlock   "
608    printf "pol  type   member_cnt  waiter_cnt\n"
609end
610
611define showwaitqmemberof
612    set $kgm_mo_waitqp = (struct wait_queue *)$arg0
613    set $kgm_mo_linksp = &($kgm_mo_waitqp->wq_queue)
614    set $kgm_mo_wqe = (struct wait_queue_element *)$kgm_mo_linksp->next
615    set $kgm_mo_found = 0
616    while ( (queue_entry_t)$kgm_mo_wqe != (queue_entry_t)$kgm_mo_linksp)
617	if ($kgm_mo_wqe->wqe_type == &_wait_queue_link)
618		if !$kgm_mo_found
619			set $kgm_mo_found = 1
620			showwaitqmemberofheader
621		end
622		set $kgm_mo_wqlp = (struct wait_queue_link *)$kgm_mo_wqe
623		set $kgm_mo_wqsetp = (struct wait_queue *)($kgm_mo_wqlp->wql_setqueue)
624		showwaitqmemberint $kgm_mo_wqsetp
625	end	
626	set $kgm_mo_wqe = (struct wait_queue_element *)$kgm_mo_wqe->wqe_links.next
627    end
628end
629
630define showwaitqmembers
631    set $kgm_ms_waitqsetp = (struct wait_queue_set *)$arg0
632    set $kgm_ms_setlinksp = &($kgm_ms_waitqsetp->wqs_setlinks)
633    set $kgm_ms_wql = (struct wait_queue_link *)$kgm_ms_setlinksp->next
634    set $kgm_ms_found = 0
635    while ( (queue_entry_t)$kgm_ms_wql != (queue_entry_t)$kgm_ms_setlinksp)
636        set $kgm_ms_waitqp = $kgm_ms_wql->wql_element.wqe_queue
637        if !$kgm_ms_found  
638	    showwaitqmemberheader
639	    set $kgm_ms_found = 1
640        end
641        showwaitqmemberint $kgm_ms_waitqp
642	set $kgm_ms_wql = (struct wait_queue_link *)$kgm_ms_wql->wql_setlinks.next
643    end
644end
645
646define showwaitqheader
647    printf "wait_queue  ref_count   interlock   "
648    printf "pol  type   member_cnt  waiter_cnt\n"
649end
650
651define showwaitqint
652    set $kgm_waitqp = (struct wait_queue *)$arg0
653    printf "0x%08x  ", $kgm_waitqp
654    if ($kgm_waitqp->wq_type == 0xf1d1)
655	printf "0x%08x  ", ((struct wait_queue_set *)$kgm_waitqp)->wqs_refcount
656    else
657	printf "0x00000000  "
658    end
659    printf "0x%08x  ", $kgm_waitqp->wq_interlock.lock_data
660    if ($kgm_waitqp->wq_fifo)
661        printf "Fifo "
662    else
663	printf "Prio "
664    end
665    if ($kgm_waitqp->wq_type == 0xf1d1)
666	printf "Set    "
667	showwaitqmembercount $kgm_waitqp
668    else
669	printf "Que    0x00000000  "
670    end
671    showwaitqwaitercount $kgm_waitqp
672    printf "\n"
673end
674
675define showwaitq
676    set $kgm_waitq1p = (wait_queue_t)$arg0
677    showwaitqheader
678    showwaitqint $kgm_waitq1p	
679    if ($kgm_waitq1p->wq_type == 0xf1d1)
680	showwaitqmembers $kgm_waitq1p
681    else
682    	showwaitqmemberof $kgm_waitq1p
683    end
684    showwaitqwaiters $kgm_waitq1p
685end
686
687define showmapheader
688    printf "vm_map      pmap        vm_size    "
689    printf "#ents rpage  hint        first_free\n"
690end
691
692define showvmeheader
693    printf "    entry       start       "
694    printf "        prot #page  object      offset\n"
695end
696
697define showvmint
698    set $kgm_mapp = (vm_map_t)$arg0
699    set $kgm_map = *$kgm_mapp
700    printf "0x%08x  ", $arg0
701    printf "0x%08x  ", $kgm_map.pmap
702    printf "0x%08x  ", $kgm_map.size
703    printf "%3d  ", $kgm_map.hdr.nentries
704    if $kgm_map.pmap
705	printf "%5d  ", $kgm_map.pmap->stats.resident_count
706    else
707	printf "<n/a>  "
708    end
709    printf "0x%08x  ", $kgm_map.hint
710    printf "0x%08x\n", $kgm_map.first_free
711    if $arg1 != 0
712	showvmeheader	
713	set $kgm_head_vmep = &($kgm_mapp->hdr.links)
714	set $kgm_vmep = $kgm_map.hdr.links.next
715	while (($kgm_vmep != 0) && ($kgm_vmep != $kgm_head_vmep))
716	    set $kgm_vme = *$kgm_vmep
717	    printf "    0x%08x  ", $kgm_vmep
718	    printf "0x%016llx  ", $kgm_vme.links.start
719	    printf "%1x", $kgm_vme.protection
720	    printf "%1x", $kgm_vme.max_protection
721	    if $kgm_vme.inheritance == 0x0
722		printf "S"
723	    end
724	    if $kgm_vme.inheritance == 0x1
725		printf "C"
726	    end
727	    if $kgm_vme.inheritance == 0x2
728		printf "-"
729	    end
730	    if $kgm_vme.inheritance == 0x3
731		printf "D"
732	    end
733	    if $kgm_vme.is_sub_map
734		printf "s "
735	    else
736		if $kgm_vme.needs_copy
737		    printf "n "
738		else
739		    printf "  "
740		end
741	    end
742	    printf "%5d  ",($kgm_vme.links.end - $kgm_vme.links.start) >> 12
743	    printf "0x%08x  ", $kgm_vme.object.vm_object
744	    printf "0x%016llx\n", $kgm_vme.offset
745  	    set $kgm_vmep = $kgm_vme.links.next
746        end
747    end
748    printf "\n"
749end
750
751
752define showmapvme
753	showmapheader
754	showvmint $arg0 1
755end
756document showmapvme
757Syntax: (gdb) showmapvme <vm_map>
758| Routine to print out a summary listing of all the entries in a vm_map
759end
760
761
762define showmap
763	showmapheader
764	showvmint $arg0 0
765end
766document showmap
767Syntax: (gdb) showmap <vm_map>
768| Routine to print out info about the specified vm_map
769end
770
771define showallvm
772    set $kgm_head_taskp = &tasks
773    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
774    while $kgm_taskp != $kgm_head_taskp
775        showtaskheader
776	showmapheader
777	showtaskint $kgm_taskp
778	showvmint $kgm_taskp->map 0
779    	set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
780    end
781end
782document showallvm
783Syntax: (gdb) showallvm
784| Routine to print a summary listing of all the vm maps
785end
786
787
788define showallvme
789    set $kgm_head_taskp = &tasks
790    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
791    while $kgm_taskp != $kgm_head_taskp
792        showtaskheader
793	showmapheader
794	showtaskint $kgm_taskp
795	showvmint $kgm_taskp->map 1
796    	set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
797    end
798end
799document showallvme
800Syntax: (gdb) showallvme
801| Routine to print a summary listing of all the vm map entries
802end
803
804
805define showipcheader
806    printf "ipc_space   is_table    table_next "
807    printf "flags tsize  splaytree   splaybase\n"
808end
809
810define showipceheader
811    printf "            name        object      "
812    printf "rite urefs  destname    destination\n"
813end
814
815define showipceint
816    set $kgm_ie = *(ipc_entry_t)$arg0
817    printf "            0x%08x  ", $arg1
818    printf "0x%08x  ", $kgm_ie.ie_object
819    if $kgm_ie.ie_bits & 0x00100000
820	printf "Dead "
821        printf "%5d\n", $kgm_ie.ie_bits & 0xffff
822    else
823        if $kgm_ie.ie_bits & 0x00080000
824	    printf "SET  "
825            printf "%5d\n", $kgm_ie.ie_bits & 0xffff
826        else
827            if $kgm_ie.ie_bits & 0x00010000
828	        if $kgm_ie.ie_bits & 0x00020000
829	            printf " SR"
830	        else
831	            printf "  S"
832	        end
833            else
834	        if $kgm_ie.ie_bits & 0x00020000
835	           printf "  R"
836	        end
837            end
838            if $kgm_ie.ie_bits & 0x00040000
839	        printf "  O"
840            end
841            if $kgm_ie.index.request
842	        printf "n"
843            else
844                printf " "
845            end
846            if $kgm_ie.ie_bits & 0x00800000
847		printf "c"
848    	    else
849		printf " "
850    	    end
851            printf "%5d  ", $kgm_ie.ie_bits & 0xffff
852            showportdest $kgm_ie.ie_object
853        end
854    end
855end
856
857define showipcint
858    set $kgm_isp = (ipc_space_t)$arg0
859    set $kgm_is = *$kgm_isp
860    printf "0x%08x  ", $arg0
861    printf "0x%08x  ", $kgm_is.is_table
862    printf "0x%08x  ", $kgm_is.is_table_next
863    if $kgm_is.is_growing != 0
864	printf "G"
865    else
866	printf " "
867    end
868    if $kgm_is.is_fast != 0
869	printf "F"
870    else
871	printf " "
872    end
873    if $kgm_is.is_active != 0
874	printf "A  "
875    else
876	printf "   "
877    end
878    printf "%5d  ", $kgm_is.is_table_size
879    printf "0x%08x  ", $kgm_is.is_tree_total
880    printf "0x%08x\n", &$kgm_isp->is_tree
881    if $arg1 != 0
882	showipceheader
883	set $kgm_iindex = 0
884	set $kgm_iep = $kgm_is.is_table
885	set $kgm_destspacep = (ipc_space_t)0
886        while ( $kgm_iindex < $kgm_is.is_table_size )
887	    set $kgm_ie = *$kgm_iep
888	    if $kgm_ie.ie_bits & 0x001f0000
889		set $kgm_name = (($kgm_iindex << 8)|($kgm_ie.ie_bits >> 24))
890		showipceint $kgm_iep $kgm_name
891	    end
892	    set $kgm_iindex = $kgm_iindex + 1
893	    set $kgm_iep = &($kgm_is.is_table[$kgm_iindex])
894	end
895	if $kgm_is.is_tree_total
896	    printf "Still need to write tree traversal\n"
897	end
898    end
899    printf "\n"
900end
901
902
903define showipc
904	set $kgm_isp = (ipc_space_t)$arg0
905        showipcheader
906	showipcint $kgm_isp 0
907end
908document showipc
909Syntax: (gdb) showipc <ipc_space>
910| Routine to print the status of the specified ipc space
911end
912
913define showrights
914	set $kgm_isp = (ipc_space_t)$arg0
915        showipcheader
916	showipcint $kgm_isp 1
917end
918document showrights
919Syntax: (gdb) showrights <ipc_space>
920| Routine to print a summary list of all the rights in a specified ipc space
921end
922
923
924define showtaskipc
925	set $kgm_taskp = (task_t)$arg0
926	showtaskheader
927    showipcheader
928	showtaskint $kgm_taskp
929	showipcint $kgm_taskp->itk_space 0
930end
931document showtaskipc
932Syntax: (gdb) showtaskipc <task>
933| Routine to print info about the ipc space for a task
934end
935
936
937define showtaskrights
938	set $kgm_taskp = (task_t)$arg0
939	showtaskheader
940        showipcheader
941	showtaskint $kgm_taskp
942	showipcint $kgm_taskp->itk_space 1
943end
944document showtaskrights
945Syntax: (gdb) showtaskrights <task>
946| Routine to print info about the ipc rights for a task
947end
948
949define showallipc
950    set $kgm_head_taskp = &tasks
951    set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next)
952    while $kgm_cur_taskp != $kgm_head_taskp
953        showtaskheader
954        showipcheader
955	showtaskint $kgm_cur_taskp
956	showipcint $kgm_cur_taskp->itk_space 0
957    	set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->tasks.next)
958    end
959end
960document showallipc
961Syntax: (gdb) showallipc
962| Routine to print a summary listing of all the ipc spaces
963end
964
965
966define showallrights
967    set $kgm_head_taskp = &tasks
968    set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next)
969    while $kgm_cur_taskp != $kgm_head_taskp
970        showtaskheader
971        showipcheader
972	showtaskint $kgm_cur_taskp
973	showipcint $kgm_cur_taskp->itk_space 1
974    	set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->tasks.next)
975    end
976end
977document showallrights
978Syntax: (gdb) showallrights
979| Routine to print a summary listing of all the ipc rights
980end
981
982
983define showtaskvm
984	set $kgm_taskp = (task_t)$arg0
985	showtaskheader
986	showmapheader
987	showtaskint $kgm_taskp
988	showvmint $kgm_taskp->map 0
989end
990document showtaskvm
991Syntax: (gdb) showtaskvm <task>
992| Routine to print out info about a task's vm_map
993end
994
995define showtaskvme
996	set $kgm_taskp = (task_t)$arg0
997	showtaskheader
998	showmapheader
999	showtaskint $kgm_taskp
1000	showvmint $kgm_taskp->map 1
1001end
1002document showtaskvme
1003Syntax: (gdb) showtaskvme <task>
1004| Routine to print out info about a task's vm_map_entries
1005end
1006
1007
1008define showtaskheader
1009    printf "task        vm_map      ipc_space  #acts  "
1010    showprocheader
1011end
1012
1013
1014define showtaskint
1015    set $kgm_task = *(struct task *)$arg0
1016    printf "0x%08x  ", $arg0
1017    printf "0x%08x  ", $kgm_task.map
1018    printf "0x%08x  ", $kgm_task.itk_space
1019    printf "%3d  ", $kgm_task.thread_count
1020    showprocint $kgm_task.bsd_info
1021end
1022
1023define showtask
1024    showtaskheader
1025    showtaskint $arg0
1026end
1027document showtask
1028Syntax (gdb) showtask <task>
1029| Routine to print out info about a task.
1030end
1031
1032
1033define showtaskthreads
1034    showtaskheader
1035    set $kgm_taskp = (struct task *)$arg0
1036    showtaskint $kgm_taskp
1037    showactheader
1038    set $kgm_head_actp = &($kgm_taskp->threads)
1039    set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
1040    while $kgm_actp != $kgm_head_actp
1041	showactint $kgm_actp 0
1042    	set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
1043    end
1044end
1045document showtaskthreads
1046Syntax: (gdb) showtaskthreads <task>
1047| Routine to print info about the threads in a task.
1048end
1049
1050
1051define showtaskstacks
1052    showtaskheader
1053    set $kgm_taskp = (struct task *)$arg0
1054    showtaskint $kgm_taskp
1055    set $kgm_head_actp = &($kgm_taskp->threads)
1056    set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
1057    while $kgm_actp != $kgm_head_actp
1058        showactheader
1059	showactint $kgm_actp 1
1060    	set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
1061    end
1062end
1063document showtaskstacks
1064Syntax: (gdb) showtaskstacks <task>
1065| Routine to print out the stack for each thread in a task.
1066end
1067
1068
1069define showalltasks
1070    showtaskheader
1071    set $kgm_head_taskp = &tasks
1072    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
1073    while $kgm_taskp != $kgm_head_taskp
1074	showtaskint $kgm_taskp
1075    	set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
1076    end
1077end
1078document showalltasks
1079Syntax: (gdb) showalltasks
1080| Routine to print a summary listing of all the tasks
1081end
1082
1083
1084define showprocheader
1085    printf " pid  proc        command\n"
1086end
1087
1088define showprocint
1089    set $kgm_procp = (struct proc *)$arg0
1090    if $kgm_procp != 0
1091        printf "%5d  ", $kgm_procp->p_pid
1092	printf "0x%08x  ", $kgm_procp
1093	printf "%s\n", $kgm_procp->p_comm
1094    else
1095	printf "  *0*  0x00000000  --\n"
1096    end
1097end
1098
1099define showpid
1100    showtaskheader
1101    set $kgm_head_taskp = &tasks
1102    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
1103    while $kgm_taskp != $kgm_head_taskp
1104	set $kgm_procp = (struct proc *)$kgm_taskp->bsd_info
1105	if (($kgm_procp != 0) && ($kgm_procp->p_pid == $arg0))
1106	    showtaskint $kgm_taskp
1107	    set $kgm_taskp = $kgm_head_taskp
1108	else
1109    	    set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
1110	end
1111    end
1112end
1113document showpid
1114Syntax: (gdb) showpid <pid>
1115| Routine to print a single process by pid
1116end
1117
1118define showproc
1119    showtaskheader
1120    set $kgm_procp = (struct proc *)$arg0
1121    showtaskint $kgm_procp->task $arg1 $arg2
1122end
1123
1124
1125define kdb
1126    set switch_debugger=1
1127    continue
1128end
1129document kdb
1130| kdb - Switch to the inline kernel debugger
1131|
1132| usage: kdb
1133|
1134| The kdb macro allows you to invoke the inline kernel debugger.
1135end
1136
1137define showpsetheader
1138    printf "portset     waitqueue   recvname    "
1139    printf "flags refs  recvname    process\n"
1140end
1141
1142define showportheader
1143    printf "port        mqueue      recvname    "
1144    printf "flags refs  recvname    process\n"
1145end
1146
1147define showportmemberheader
1148    printf "members     port        recvname    "
1149    printf "flags refs  mqueue      msgcount\n"
1150end
1151
1152define showkmsgheader
1153    printf "messages    kmsg        size        "
1154    printf "disp msgid  remote-port local-port\n"
1155end
1156
1157define showkmsgint
1158    printf "            0x%08x  ", $arg0
1159    set $kgm_kmsgh = ((ipc_kmsg_t)$arg0)->ikm_header
1160    printf "0x%08x  ", $kgm_kmsgh.msgh_size
1161    if (($kgm_kmsgh.msgh_bits & 0xff) == 19)
1162	printf "rC"
1163    else
1164	printf "rM"
1165    end
1166    if (($kgm_kmsgh.msgh_bits & 0xff00) == (19 < 8))
1167	printf "lC"
1168    else
1169	printf "lM"
1170    end
1171    if ($kgm_kmsgh.msgh_bits & 0xf0000000)
1172	printf "c"
1173    else
1174	printf "s"
1175    end
1176    printf "%5d  ", $kgm_kmsgh.msgh_id
1177    printf "0x%08x  ", $kgm_kmsgh.msgh_remote_port
1178    printf "0x%08x\n", $kgm_kmsgh.msgh_local_port
1179end
1180
1181
1182
1183define showkobject
1184    set $kgm_portp = (struct ipc_port *)$arg0
1185    printf "0x%08x  kobject(", $kgm_portp->ip_kobject
1186    set $kgm_kotype = ($kgm_portp->ip_object.io_bits & 0x00000fff)
1187    if ($kgm_kotype == 1)
1188	printf "THREAD"
1189    end
1190    if ($kgm_kotype == 2)
1191	printf "TASK"
1192    end
1193    if ($kgm_kotype == 3)
1194	printf "HOST"
1195    end
1196    if ($kgm_kotype == 4)
1197	printf "HOST_PRIV"
1198    end
1199    if ($kgm_kotype == 5)
1200	printf "PROCESSOR"
1201    end
1202    if ($kgm_kotype == 6)
1203	printf "PSET"
1204    end
1205    if ($kgm_kotype == 7)
1206	printf "PSET_NAME"
1207    end
1208    if ($kgm_kotype == 8)
1209	printf "TIMER"
1210    end
1211    if ($kgm_kotype == 9)
1212	printf "PAGER_REQ"
1213    end
1214    if ($kgm_kotype == 10)
1215	printf "DEVICE"
1216    end
1217    if ($kgm_kotype == 11)
1218	printf "XMM_OBJECT"
1219    end
1220    if ($kgm_kotype == 12)
1221	printf "XMM_PAGER"
1222    end
1223    if ($kgm_kotype == 13)
1224	printf "XMM_KERNEL"
1225    end
1226    if ($kgm_kotype == 14)
1227	printf "XMM_REPLY"
1228    end
1229    if ($kgm_kotype == 15)
1230	printf "NOTDEF 15"
1231    end
1232    if ($kgm_kotype == 16)
1233	printf "NOTDEF 16"
1234    end
1235    if ($kgm_kotype == 17)
1236	printf "HOST_SEC"
1237    end
1238    if ($kgm_kotype == 18)
1239	printf "LEDGER"
1240    end
1241    if ($kgm_kotype == 19)
1242	printf "MASTER_DEV"
1243    end
1244    if ($kgm_kotype == 20)
1245	printf "ACTIVATION"
1246    end
1247    if ($kgm_kotype == 21)
1248	printf "SUBSYSTEM"
1249    end
1250    if ($kgm_kotype == 22)
1251	printf "IO_DONE_QUE"
1252    end
1253    if ($kgm_kotype == 23)
1254	printf "SEMAPHORE"
1255    end
1256    if ($kgm_kotype == 24)
1257	printf "LOCK_SET"
1258    end
1259    if ($kgm_kotype == 25)
1260	printf "CLOCK"
1261    end
1262    if ($kgm_kotype == 26)
1263	printf "CLOCK_CTRL"
1264    end
1265    if ($kgm_kotype == 27)
1266	printf "IOKIT_SPARE"
1267    end
1268    if ($kgm_kotype == 28)
1269	printf "NAMED_MEM"
1270    end
1271    if ($kgm_kotype == 29)
1272	printf "IOKIT_CON"
1273    end
1274    if ($kgm_kotype == 30)
1275	printf "IOKIT_OBJ"
1276    end
1277    if ($kgm_kotype == 31)
1278	printf "UPL"
1279    end
1280    printf ")\n"
1281end
1282
1283define showportdestproc
1284    set $kgm_portp = (struct ipc_port *)$arg0
1285    set $kgm_spacep = $kgm_portp->data.receiver
1286#   check against the previous cached value - this is slow
1287    if ($kgm_spacep != $kgm_destspacep)
1288	set $kgm_destprocp = (struct proc *)0
1289        set $kgm_head_taskp = &tasks
1290        set $kgm_desttaskp = (struct task *)($kgm_head_taskp->next)
1291        while (($kgm_destprocp == 0) && ($kgm_desttaskp != $kgm_head_taskp))
1292	    set $kgm_destspacep = $kgm_desttaskp->itk_space
1293	    if ($kgm_destspacep == $kgm_spacep)
1294	       set $kgm_destprocp = (struct proc *)$kgm_desttaskp->bsd_info
1295	    else
1296    	       set $kgm_desttaskp = (struct task *)($kgm_desttaskp->tasks.next)
1297            end
1298        end
1299    end
1300    if $kgm_destprocp != 0
1301       printf "%s(%d)\n", $kgm_destprocp->p_comm, $kgm_destprocp->p_pid
1302    else
1303       printf "task 0x%08x\n", $kgm_desttaskp
1304    end
1305end
1306
1307define showportdest
1308    set $kgm_portp = (struct ipc_port *)$arg0
1309    set $kgm_spacep = $kgm_portp->data.receiver
1310    if ($kgm_spacep == ipc_space_kernel)
1311	showkobject $kgm_portp
1312    else
1313	if ($kgm_portp->ip_object.io_bits & 0x80000000)
1314	    printf "0x%08x  ", $kgm_portp->ip_object.io_receiver_name
1315	    showportdestproc $kgm_portp
1316	else
1317	    printf "0x%08x  inactive-port\n", $kgm_portp
1318	end
1319    end
1320end
1321
1322define showportmember
1323    printf "            0x%08x  ", $arg0
1324    set $kgm_portp = (struct ipc_port *)$arg0
1325    printf "0x%08x  ", $kgm_portp->ip_object.io_receiver_name
1326    if ($kgm_portp->ip_object.io_bits & 0x80000000)
1327	printf "A"
1328    else
1329	printf " "
1330    end
1331    if ($kgm_portp->ip_object.io_bits & 0x7fff0000)
1332	printf "Set "
1333    else
1334	printf "Port"
1335    end
1336    printf "%5d  ", $kgm_portp->ip_object.io_references
1337    printf "0x%08x  ", &($kgm_portp->ip_messages)
1338    printf "0x%08x\n", $kgm_portp->ip_messages.data.port.msgcount
1339end
1340
1341define showportint
1342    printf "0x%08x  ", $arg0
1343    set $kgm_portp = (struct ipc_port *)$arg0
1344    printf "0x%08x  ", &($kgm_portp->ip_messages)
1345    printf "0x%08x  ", $kgm_portp->ip_object.io_receiver_name
1346    if ($kgm_portp->ip_object.io_bits & 0x80000000)
1347	printf "A"
1348    else
1349	printf "D"
1350    end
1351    printf "Port"
1352    printf "%5d  ", $kgm_portp->ip_object.io_references
1353    set $kgm_destspacep = (struct ipc_space *)0
1354    showportdest $kgm_portp
1355    set $kgm_kmsgp = (ipc_kmsg_t)$kgm_portp->ip_messages.data.port.messages.ikmq_base
1356    if $arg1 && $kgm_kmsgp
1357	showkmsgheader
1358	showkmsgint $kgm_kmsgp
1359	set $kgm_kmsgheadp = $kgm_kmsgp
1360	set $kgm_kmsgp = $kgm_kmsgp->ikm_next
1361	while $kgm_kmsgp != $kgm_kmsgheadp
1362	    showkmsgint $kgm_kmsgp
1363	    set $kgm_kmsgp = $kgm_kmsgp->ikm_next
1364        end
1365    end
1366end
1367
1368define showpsetint
1369    printf "0x%08x  ", $arg0
1370    set $kgm_psetp = (struct ipc_pset *)$arg0
1371    printf "0x%08x  ", &($kgm_psetp->ips_messages)
1372    printf "0x%08x  ", $kgm_psetp->ips_object.io_receiver_name
1373    if ($kgm_psetp->ips_object.io_bits & 0x80000000)
1374	printf "A"
1375    else
1376	printf "D"
1377    end
1378    printf "Set "
1379    printf "%5d  ", $kgm_psetp->ips_object.io_references
1380    printf "0x%08x  ", $kgm_psetp->ips_object.io_receiver_name
1381    set $kgm_setlinksp = &($kgm_psetp->ips_messages.data.set_queue.wqs_setlinks)
1382    set $kgm_wql = (struct wait_queue_link *)$kgm_setlinksp->next
1383    set $kgm_found = 0
1384    while ( (queue_entry_t)$kgm_wql != (queue_entry_t)$kgm_setlinksp)
1385        set $kgm_portp = (struct ipc_port *)((int)($kgm_wql->wql_element->wqe_queue) - ((int)$kgm_portoff))
1386	if !$kgm_found  
1387	    set $kgm_destspacep = (struct ipc_space *)0
1388	    showportdestproc $kgm_portp
1389	    showportmemberheader
1390	    set $kgm_found = 1
1391	end
1392	showportmember $kgm_portp 0
1393	set $kgm_wql = (struct wait_queue_link *)$kgm_wql->wql_setlinks.next
1394    end
1395    if !$kgm_found
1396	printf "--n/e--\n"
1397    end
1398end
1399
1400define showpset
1401    showpsetheader
1402    showpsetint $arg0 1
1403end
1404
1405define showport
1406    showportheader
1407    showportint $arg0 1
1408end
1409
1410define showipcobject
1411    set $kgm_object = (ipc_object_t)$arg0
1412    if ($kgm_objectp->io_bits & 0x7fff0000)
1413	showpset $kgm_objectp
1414    else
1415	showport $kgm_objectp
1416    end
1417end
1418
1419define showmqueue
1420    set $kgm_mqueue = *(struct ipc_mqueue *)$arg0
1421    set $kgm_psetoff = &(((struct ipc_pset *)0)->ips_messages)
1422    set $kgm_portoff = &(((struct ipc_port *)0)->ip_messages)
1423    if ($kgm_mqueue.data.set_queue.wqs_wait_queue.wq_type == 0xf1d1)
1424	set $kgm_pset = (((int)$arg0) - ((int)$kgm_psetoff))
1425        showpsetheader
1426	showpsetint $kgm_pset 1
1427    end
1428    if ($kgm_mqueue.data.set_queue.wqs_wait_queue.wq_type == 0xf1d0)
1429	showportheader
1430	set $kgm_port = (((int)$arg0) - ((int)$kgm_portoff))
1431	showportint $kgm_port 1
1432    end
1433end
1434
1435define zprint_one
1436set $kgm_zone = (struct zone *)$arg0
1437
1438printf "0x%08x ", $kgm_zone
1439printf "%8d ",$kgm_zone->count
1440printf "%8x ",$kgm_zone->cur_size
1441printf "%8x ",$kgm_zone->max_size
1442printf "%6d ",$kgm_zone->elem_size
1443printf "%8x ",$kgm_zone->alloc_size
1444printf "%s ",$kgm_zone->zone_name
1445
1446if ($kgm_zone->exhaustible)
1447	printf "H"
1448end
1449if ($kgm_zone->collectable)
1450	printf "C"
1451end
1452if ($kgm_zone->expandable)
1453	printf "X"
1454end
1455printf "\n"
1456end
1457
1458
1459define zprint
1460printf "ZONE          COUNT   TOT_SZ   MAX_SZ ELT_SZ ALLOC_SZ NAME\n"
1461set $kgm_zone_ptr = (struct zone *)first_zone
1462while ($kgm_zone_ptr != 0)
1463	zprint_one $kgm_zone_ptr
1464	set $kgm_zone_ptr = $kgm_zone_ptr->next_zone
1465end
1466printf "\n"
1467end
1468document zprint
1469Syntax: (gdb) zprint
1470| Routine to print a summary listing of all the kernel zones
1471end
1472
1473define showmtxgrp
1474set $kgm_mtxgrp = (struct _lck_grp_ *)$arg0
1475
1476if ($kgm_mtxgrp->lck_grp_mtxcnt)
1477printf "0x%08x ", $kgm_mtxgrp
1478printf "%8d ",$kgm_mtxgrp->lck_grp_mtxcnt
1479printf "%12u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_util_cnt
1480printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_miss_cnt
1481printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_wait_cnt
1482printf "%s ",&$kgm_mtxgrp->lck_grp_name
1483printf "\n"
1484end
1485end
1486
1487
1488define showallmtx
1489printf "LCK GROUP       CNT         UTIL     MISS     WAIT NAME\n"
1490set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)&lck_grp_queue
1491set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)$kgm_mtxgrp_ptr->lck_grp_link.next
1492while ($kgm_mtxgrp_ptr != (struct _lck_grp_ *)&lck_grp_queue)
1493	showmtxgrp $kgm_mtxgrp_ptr
1494	set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)$kgm_mtxgrp_ptr->lck_grp_link.next
1495end
1496printf "\n"
1497end
1498document showallmtx
1499Syntax: (gdb) showallmtx
1500| Routine to print a summary listing of all mutexes
1501end
1502
1503define showrwlckgrp
1504set $kgm_rwlckgrp = (struct _lck_grp_ *)$arg0
1505
1506if ($kgm_rwlckgrp->lck_grp_rwcnt)
1507printf "0x%08x ", $kgm_rwlckgrp
1508printf "%8d ",$kgm_rwlckgrp->lck_grp_rwcnt
1509printf "%12u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_util_cnt
1510printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_miss_cnt
1511printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_wait_cnt
1512printf "%s ",&$kgm_rwlckgrp->lck_grp_name
1513printf "\n"
1514end
1515end
1516
1517
1518define showallrwlck
1519printf "LCK GROUP       CNT         UTIL     MISS     WAIT NAME\n"
1520set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)&lck_grp_queue
1521set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)$kgm_rwlckgrp_ptr->lck_grp_link.next
1522while ($kgm_rwlckgrp_ptr != (struct _lck_grp_ *)&lck_grp_queue)
1523	showrwlckgrp $kgm_rwlckgrp_ptr
1524	set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)$kgm_rwlckgrp_ptr->lck_grp_link.next
1525end
1526printf "\n"
1527end
1528document showallrwlck
1529Syntax: (gdb) showallrwlck
1530| Routine to print a summary listing of all read/writer locks
1531end
1532
1533set $kdp_act_counter = 0
1534
1535set $r0_save	= 0
1536set $r1_save	= 0
1537set $r2_save	= 0
1538set $r3_save	= 0
1539set $r4_save	= 0
1540set $r5_save	= 0
1541set $r6_save	= 0
1542set $r7_save	= 0
1543set $r8_save	= 0
1544set $r9_save	= 0
1545set $r10_save	= 0
1546set $r11_save	= 0
1547set $r12_save	= 0
1548set $sp_save	= 0
1549set $lr_save	= 0
1550set $pc_save	= 0
1551
1552define showcontext_int
1553	echo Context switched, current instruction pointer: 
1554	output/a $pc
1555	echo \n
1556end
1557
1558define switchtoact
1559	set $newact = (struct thread *) $arg0
1560	select 0
1561	if ($newact->kernel_stack == 0)
1562		echo This activation does not have a stack.\n
1563		echo continuation:
1564		output/a (unsigned) $newact.continuation
1565		echo \n
1566	else
1567	if ($kgm_mtype == 18)
1568		if ($kdp_act_counter == 0)
1569			set $kdpstate = (struct savearea *) kdp.saved_state
1570		end
1571		set $kdp_act_counter = $kdp_act_counter + 1
1572		set (struct savearea *) kdp.saved_state=$newact->machine->pcb
1573		flushregs
1574		flushstack
1575		set $pc=$newact->machine->pcb.save_srr0
1576		update
1577	end
1578	if ($kgm_mtype == 7)
1579		set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state
1580		if ($kdp_act_counter == 0)
1581			set $kdpstate = *($kdpstatep)
1582		end	
1583		set $kdp_act_counter = $kdp_act_counter + 1
1584
1585		set $kgm_statep = (struct x86_kernel_state32 *) \
1586					($newact->kernel_stack + 0x4000 \
1587					 - sizeof(struct x86_kernel_state32))
1588		set $kdpstatep->ebx = $kgm_statep->k_ebx 
1589		set $kdpstatep->ebp = $kgm_statep->k_ebp 
1590		set $kdpstatep->edi = $kgm_statep->k_edi 
1591		set $kdpstatep->esi = $kgm_statep->k_esi 
1592		set $kdpstatep->eip = $kgm_statep->k_eip 
1593		flushregs
1594		flushstack
1595		set $pc = $kgm_statep->k_eip
1596		update
1597	end
1598	if ($kgm_mtype == 12)
1599		set $r0_save   = $r0
1600		set $r1_save   = $r1
1601		set $r2_save   = $r2
1602		set $r3_save   = $r3
1603		set $r4_save   = $r4
1604		set $r5_save   = $r5
1605		set $r6_save   = $r6
1606		set $r7_save   = $r7
1607		set $r8_save   = $r8
1608		set $r9_save   = $r9
1609		set $r10_save  = $r10
1610		set $r11_save  = $r11
1611		set $r12_save  = $r12
1612		set $sp_save   = $sp
1613		set $lr_save   = $lr
1614		set $pc_save   = $pc
1615		set $pc_ctx = load_reg+8
1616		set $kgm_statep = (struct arm_saved_state *)((struct thread*)$arg0)->machine.kstackptr
1617		set $r0 =  $kgm_statep->r[0]
1618		set $r1 =  $kgm_statep->r[1]
1619		set $r2 =  $kgm_statep->r[2]
1620		set $r3 =  $kgm_statep->r[3]
1621		set $r4 =  $kgm_statep->r[4]
1622		set $r5 =  $kgm_statep->r[5]
1623		set $r6 =  $kgm_statep->r[6]
1624		set $r8 =  $kgm_statep->r[8]
1625		set $r9 =  $kgm_statep->r[9]
1626		set $r10 = $kgm_statep->r[10]
1627		set $r11 = $kgm_statep->r[11]
1628		set $r12 = $kgm_statep->r[12]
1629		set $sp = $kgm_statep->sp
1630		set $lr = $kgm_statep->lr
1631		set $pc = $pc_ctx
1632		set $r7 =  $kgm_statep->r[7]
1633		flushregs
1634		flushstack
1635		end
1636	end
1637	showcontext_int
1638end
1639
1640document switchtoact  
1641Syntax: switchtoact <address of activation>
1642| This command allows gdb to examine the execution context and call
1643| stack for the specified activation. For example, to view the backtrace
1644| for an activation issue "switchtoact <address>", followed by "bt".
1645| Before resuming execution, issue a "resetctx" command, to
1646| return to the original execution context.
1647end     
1648
1649define switchtoctx
1650	select 0
1651	if ($kgm_mtype == 18)
1652		if ($kdp_act_counter == 0)
1653		set $kdpstate = (struct savearea *) kdp.saved_state
1654		end
1655		set $kdp_act_counter = $kdp_act_counter + 1
1656		set (struct savearea *) kdp.saved_state=(struct savearea *) $arg0
1657		flushregs
1658		flushstack
1659		set $pc=((struct savearea *) $arg0)->save_srr0
1660		update
1661	else
1662	if ($kgm_mtype == 12)
1663		set $r0_save   = $r0
1664		set $r1_save   = $r1
1665		set $r2_save   = $r2
1666		set $r3_save   = $r3
1667		set $r4_save   = $r4
1668		set $r5_save   = $r5
1669		set $r6_save   = $r6
1670		set $r7_save   = $r7
1671		set $r8_save   = $r8
1672		set $r9_save   = $r9
1673		set $r10_save  = $r10
1674		set $r11_save  = $r11
1675		set $r12_save  = $r12
1676		set $sp_save   = $sp
1677		set $lr_save   = $lr
1678		set $pc_save   = $pc
1679		set $kgm_statep = (struct arm_saved_state *)$arg0
1680		set $r0 =  $kgm_statep->r[0]
1681		set $r1 =  $kgm_statep->r[1]
1682		set $r2 =  $kgm_statep->r[2]
1683		set $r3 =  $kgm_statep->r[3]
1684		set $r4 =  $kgm_statep->r[4]
1685		set $r5 =  $kgm_statep->r[5]
1686		set $r6 =  $kgm_statep->r[6]
1687		set $r8 =  $kgm_statep->r[8]
1688		set $r9 =  $kgm_statep->r[9]
1689		set $r10 = $kgm_statep->r[10]
1690		set $r11 = $kgm_statep->r[11]
1691		set $r12 = $kgm_statep->r[12]
1692		set $sp = $kgm_statep->sp
1693		set $lr = $kgm_statep->lr
1694		set $r7 =  $kgm_statep->r[7]
1695		set $pc = $kgm_statep->pc
1696		flushregs
1697		flushstack
1698		update
1699	else
1700		echo switchtoctx not implemented for this architecture.\n
1701	end
1702end
1703
1704document switchtoctx  
1705Syntax: switchtoctx <address of pcb>
1706| This command allows gdb to examine an execution context and dump the
1707| backtrace for this execution context.
1708| Before resuming execution, issue a "resetctx" command, to
1709| return to the original execution context.
1710end     
1711
1712define resetctx
1713	select 0
1714	if ($kdp_act_counter != 0)
1715	if ($kgm_mtype == 18)
1716		set (struct savearea *)kdp.saved_state=$kdpstate
1717		flushregs
1718		flushstack
1719		set $pc=((struct savearea *) kdp.saved_state)->save_srr0
1720		update
1721		set $kdp_act_counter = 0
1722	end
1723	if ($kgm_mtype == 7)
1724		set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state
1725		set *($kdpstatep)=$kdpstate
1726		flushregs
1727		flushstack
1728		set $pc=$kdpstatep->eip
1729		update
1730		set $kdp_act_counter = 0
1731	end
1732	if ($kgm_mtype == 12)
1733		set $r0  = $r0_save
1734		flushregs
1735		set $r1  = $r1_save
1736		flushregs
1737		set $r2  = $r2_save
1738		flushregs
1739		set $r3  = $r3_save
1740		flushregs
1741		set $r4  = $r4_save
1742		flushregs
1743		set $r5  = $r5_save
1744		flushregs
1745		set $r6  = $r6_save
1746		flushregs
1747		set $r8  = $r8_save
1748		flushregs
1749		set $r9  = $r9_save
1750		flushregs
1751		set $r10 = $r10_save
1752		flushregs
1753		set $r11 = $r11_save
1754		flushregs
1755		set $r12 = $r12_save
1756		flushregs
1757		set $sp  = $sp_save
1758		flushregs
1759		set $lr  = $lr_save
1760		flushregs
1761		set $pc  = $pc_save
1762		flushregs
1763		set $r7  = $r7_save
1764		flushregs
1765	end
1766	showcontext_int
1767	end
1768end     
1769        
1770document resetctx
1771| Syntax: resetctx
1772| Returns to the original execution context. This command should be
1773| issued if you wish to resume execution after using the "switchtoact"
1774| or "switchtoctx" commands.
1775end     
1776
1777# This is a pre-hook for the continue command, to prevent inadvertent attempts 
1778# to resume from the context switched to for examination.
1779define hook-continue
1780       resetctx
1781end
1782
1783# This is a pre-hook for the detach command, to prevent inadvertent attempts 
1784# to resume from the context switched to for examination.
1785define hook-detach
1786       resetctx
1787end
1788
1789define resume_on
1790	set noresume_on_disconnect = 0
1791end
1792
1793document resume_on
1794| Syntax: resume_on
1795| The target system will resume when detaching  or exiting from gdb. 
1796| This is the default behavior.
1797end
1798
1799define resume_off
1800	set noresume_on_disconnect = 1
1801end
1802
1803document resume_off
1804| Syntax: resume_off
1805| The target system  won't resume after detaching from gdb and
1806| can be attached with a new gdb session
1807end
1808
1809define paniclog
1810	set $kgm_panic_bufptr = debug_buf
1811	set $kgm_panic_bufptr_max = debug_buf_ptr
1812	while $kgm_panic_bufptr < $kgm_panic_bufptr_max
1813		if *(char *)$kgm_panic_bufptr == 10
1814			printf "\n"
1815		else
1816			printf "%c", *$kgm_panic_bufptr
1817		end
1818		set $kgm_panic_bufptr= (char *)$kgm_panic_bufptr + 1
1819	end
1820end
1821
1822document paniclog
1823| Syntax: paniclog
1824| Display the panic log information
1825|
1826end
1827
1828define dumpcallqueue
1829	set $kgm_callhead = (queue_t)&$arg0
1830	set $kgm_call = (struct call_entry *)$kgm_callhead.next
1831	set $kgm_i = 0
1832	while $kgm_call != $kgm_callhead
1833		printf "0x%08x ", $kgm_call
1834		printf "0x%08x 0x%08x ", $kgm_call->param0, $kgm_call->param1
1835		output $kgm_call->state
1836		printf "\t"
1837		output $kgm_call->deadline
1838		printf "\t"
1839		output $kgm_call->func
1840		printf "\n"
1841		set $kgm_i = $kgm_i + 1
1842		set $kgm_call = (struct call_entry *)$kgm_call->q_link.next
1843	end
1844	printf "%d entries\n", $kgm_i
1845end
1846
1847document dumpcallqueue
1848| Syntax: dumpcallqueue <queue head>
1849| Displays the contents of the specified call_entry queue.
1850end
1851
1852define showtaskacts
1853showtaskthreads $arg0
1854end
1855document showtaskacts
1856| See help showtaskthreads.
1857end
1858
1859define showallacts
1860showallthreads
1861end
1862document showallacts
1863| See help showallthreads.
1864end
1865
1866
1867define resetstacks
1868       _kgm_flush_loop
1869       set kdp_pmap = 0
1870       _kgm_flush_loop
1871       resetctx
1872       _kgm_flush_loop
1873       _kgm_update_loop
1874       resetctx
1875       _kgm_update_loop
1876end
1877
1878document resetstacks
1879| Syntax: resetstacks
1880| Internal kgmacro routine used by the "showuserstack" macro 
1881| to reset the target pmap to the kernel pmap.
1882end
1883
1884#Barely effective hacks to work around bugs in the "flush" and "update" 
1885#gdb commands in Tiger (up to 219); these aren't necessary with Panther
1886#gdb, but do no harm.
1887define _kgm_flush_loop
1888       set $kgm_flush_loop_ctr = 0
1889       while ($kgm_flush_loop_ctr < 30)
1890       	     flushregs
1891	     flushstack
1892	     set $kgm_flush_loop_ctr = $kgm_flush_loop_ctr + 1
1893       end
1894end
1895
1896define _kgm_update_loop
1897       set $kgm_update_loop_ctr = 0
1898       while ($kgm_update_loop_ctr < 30)
1899       	     update
1900       	     set $kgm_update_loop_ctr = $kgm_update_loop_ctr + 1
1901       end
1902end
1903
1904#This is necessary since gdb often doesn't do backtraces on x86 correctly
1905#in the absence of symbols.The code below in showuserstack and 
1906#showx86backtrace also contains several workarouds for the gdb bug where 
1907#gdb stops macro evaluation because of spurious "Cannot read memory"
1908#errors on x86. These errors appear on ppc as well, but they don't
1909#always stop macro evaluation.
1910
1911set $kgm_cur_ebp = 0
1912set $kgm_cur_eip = 0
1913
1914define showx86backtrace
1915	if ($kgm_cur_ebp == 0)
1916		set $kgm_cur_ebp = $ebp
1917	end
1918	if ($kgm_cur_eip == 0)
1919		set $kgm_cur_eip = $eip
1920	end
1921	printf "0: EBP: 0x%08x EIP: 0x%08x\n", $kgm_cur_ebp, $kgm_cur_eip
1922	x/i $kgm_cur_eip
1923	set $kgm_prev_ebp = *((uint32_t *) $kgm_cur_ebp)
1924	set $kgm_prev_eip = *((uint32_t *) ($kgm_cur_ebp + 4))
1925	set $kgm_cur_ebp = 0
1926	set $kgm_cur_eip = 0
1927	set $kgm_frameno = 1
1928	while $kgm_prev_ebp != 0
1929		printf "%d: saved EBP: 0x%08x saved EIP: 0x%08x\n", $kgm_frameno, $kgm_prev_ebp, $kgm_prev_eip
1930		x/i $kgm_prev_eip
1931		set $kgm_prev_eip = *((uint32_t *) ($kgm_prev_ebp + 4))
1932		set $kgm_prev_ebp = *((uint32_t *) $kgm_prev_ebp)
1933		set $kgm_frameno = $kgm_frameno + 1
1934	end
1935	set kdp_pmap = 0
1936end
1937
1938define showuserstack
1939		select 0
1940  		if ($kgm_mtype == 18)	
1941		   if ($kdp_act_counter == 0)
1942		      set $kdpstate = (struct savearea *) kdp.saved_state
1943		   end
1944		   set $kdp_act_counter = $kdp_act_counter + 1
1945		   set $newact = (struct thread *) $arg0
1946		   _kgm_flush_loop
1947		   set $checkpc = $newact->machine->upcb.save_srr0
1948		   if ($checkpc == 0)
1949		      echo This activation does not appear to have
1950		      echo \20 a valid user context.\n
1951		   else	      
1952		     set (struct savearea *) kdp.saved_state=$newact->machine->upcb
1953		     set $pc = $checkpc
1954#flush and update seem to be executed lazily by gdb on Tiger, hence the
1955#repeated invocations - see 3743135
1956	   	    _kgm_flush_loop
1957# This works because the new pmap is used only for reads
1958		     set kdp_pmap = $newact->task->map->pmap
1959		     _kgm_flush_loop
1960		     _kgm_update_loop
1961		     bt
1962		     resetstacks
1963		     _kgm_flush_loop
1964		     _kgm_update_loop
1965		     resetstacks
1966		     _kgm_flush_loop
1967		     _kgm_update_loop
1968		   end
1969		else
1970		if ($kgm_mtype == 7)
1971			set $newact = (struct thread *) $arg0
1972#This needs to identify 64-bit processes as well
1973			set $newiss = (x86_saved_state32_t) ($newact->machine.pcb->iss.uss.ss_32)
1974			set $checkpc = $newiss.eip
1975			if ($checkpc == 0)
1976			    echo This activation does not appear to have
1977			    echo \20 a valid user context.\n
1978			else
1979			set $kgm_cur_ebp = $newiss.ebp
1980			set $kgm_cur_eip = $checkpc
1981			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
1982			set kdp_pmap = $newact->task->map->pmap
1983			_kgm_flush_loop
1984			_kgm_update_loop
1985			end			
1986		else
1987			echo showuserstack not supported on this architecture\n
1988		end
1989		end
1990end
1991document showuserstack
1992Syntax: showuserstack <address of thread activation>
1993|This command displays a numeric backtrace for the user space stack of
1994|the given thread activation. It may, of course, fail to display a
1995|complete backtrace if portions of the user stack are not mapped in.
1996|Symbolic backtraces can be obtained either by running gdb on the
1997|user space binary, or a tool such as "symbolicate".
1998|Note that while this command works on Panther's gdb, an issue
1999|with Tiger gdb (3743135) appears to hamper the evaluation of this
2000|macro in some cases.
2001end
2002
2003#Stopgap until gdb can generate the HOSTREBOOT packet
2004define kdp-reboot
2005#Alternatively, set *(*(unsigned **) 0x2498) = 1 (or 0x5498 on PPC)
2006       set flag_kdp_trigger_reboot = 1
2007       continue
2008end
2009
2010document kdp-reboot
2011Syntax: kdp-reboot
2012|Reboot the remote target machine; not guaranteed to succeed. Requires symbols
2013|until gdb support for the HOSTREBOOT packet is implemented.
2014end
2015
2016define sendcore
2017       set kdp_trigger_core_dump = 1
2018       set kdp_flag |= 0x40
2019       set panicd_ip_str = "$arg0"
2020       set panicd_specified = 1
2021       set disable_debug_output = 0
2022       set disableConsoleOutput = 0
2023       set logPanicDataToScreen = 1
2024       set reattach_wait = 1
2025       resume_off
2026end
2027
2028document sendcore
2029Syntax: sendcore <IP address>
2030|Configure the kernel to transmit a kernel coredump to a server (kdumpd) 
2031|at the specified IP address. This is useful when the remote target has
2032|not been previously configured to transmit coredumps, and you wish to
2033|preserve kernel state for later examination. NOTE: You must issue a "continue"
2034|command after using this macro to trigger the kernel coredump. The kernel
2035|will resume waiting in the debugger after completion of the coredump. You
2036|may disable coredumps by executing the "disablecore" macro.
2037end
2038
2039define disablecore
2040       set kdp_trigger_core_dump = 0
2041       set kdp_flag |= 0x40
2042       set kdp_flag &= ~0x10
2043       set panicd_specified = 0
2044end
2045
2046document disablecore
2047Syntax: disablecore
2048|Reconfigures the kernel so that it no longer transmits kernel coredumps. This
2049|complements the "sendcore" macro, but it may be used if the kernel has been
2050|configured to transmit coredumps through boot-args as well.
2051end
2052
2053define switchtocorethread
2054	set $newact = (struct thread *) $arg0
2055	select 0
2056	if ($newact->kernel_stack == 0)
2057	   echo This thread does not have a stack.\n
2058	   echo continuation:
2059	   output/a (unsigned) $newact.continuation
2060	   echo \n
2061	else
2062	if ($kgm_mtype == 18)
2063	   loadcontext $newact->machine->pcb
2064	   flushstack
2065	   set $pc = $newact->machine->pcb.save_srr0
2066	else
2067	if ($kgm_mtype == 7)
2068		set $kgm_cstatep = (struct x86_kernel_state32 *) \
2069					($newact->kernel_stack + 0x4000 \
2070					 - sizeof(struct x86_kernel_state32))
2071		loadcontext $kgm_cstatep
2072		flushstack
2073	else
2074		echo switchtocorethread not supported on this architecture\n
2075	end
2076 	end
2077	showcontext_int
2078	end
2079end
2080
2081document switchtocorethread
2082Syntax: switchtocorethread <address of activation>
2083| The corefile equivalent of "switchtoact". When debugging a kernel coredump
2084| file, this command can be used to examine the execution context and stack
2085| trace for a given thread activation. For example, to view the backtrace
2086| for a thread issue "switchtocorethread <address>", followed by "bt".
2087| Before resuming execution, issue a "resetcorectx" command, to
2088| return to the original execution context. Note that this command
2089| requires gdb support, as documented in Radar 3401283.
2090end
2091
2092define loadcontext
2093	select 0
2094	if ($kgm_mtype == 18)
2095	set $kgm_contextp = (struct savearea *) $arg0
2096	set $pc = $kgm_contextp.save_srr0
2097	set $r1 = $kgm_contextp.save_r1
2098	set $lr = $kgm_contextp.save_lr
2099
2100	set $r2 = $kgm_contextp.save_r2
2101	set $r3 = $kgm_contextp.save_r3
2102	set $r4 = $kgm_contextp.save_r4
2103	set $r5 = $kgm_contextp.save_r5
2104	set $r6 = $kgm_contextp.save_r6
2105	set $r7 = $kgm_contextp.save_r7
2106	set $r8 = $kgm_contextp.save_r8
2107	set $r9 = $kgm_contextp.save_r9
2108	set $r10 = $kgm_contextp.save_r10
2109	set $r11 = $kgm_contextp.save_r11
2110	set $r12 = $kgm_contextp.save_r12
2111	set $r13 = $kgm_contextp.save_r13
2112	set $r14 = $kgm_contextp.save_r14
2113	set $r15 = $kgm_contextp.save_r15
2114	set $r16 = $kgm_contextp.save_r16
2115	set $r17 = $kgm_contextp.save_r17
2116	set $r18 = $kgm_contextp.save_r18
2117	set $r19 = $kgm_contextp.save_r19
2118	set $r20 = $kgm_contextp.save_r20
2119	set $r21 = $kgm_contextp.save_r21
2120	set $r22 = $kgm_contextp.save_r22
2121	set $r23 = $kgm_contextp.save_r23
2122	set $r24 = $kgm_contextp.save_r24
2123	set $r25 = $kgm_contextp.save_r25
2124	set $r26 = $kgm_contextp.save_r26
2125	set $r27 = $kgm_contextp.save_r27
2126	set $r28 = $kgm_contextp.save_r28
2127	set $r29 = $kgm_contextp.save_r29
2128	set $r30 = $kgm_contextp.save_r30
2129	set $r31 = $kgm_contextp.save_r31
2130
2131	set $cr = $kgm_contextp.save_cr
2132	set $ctr = $kgm_contextp.save_ctr
2133       else
2134	if ($kgm_mtype == 7)
2135		set $kgm_contextp = (struct x86_kernel_state32 *) $arg0
2136		set $ebx = $kgm_contextp->k_ebx 
2137		set $ebp = $kgm_contextp->k_ebp 
2138		set $edi = $kgm_contextp->k_edi 
2139		set $esi = $kgm_contextp->k_esi 
2140		set $eip = $kgm_contextp->k_eip 
2141		set $pc =  $kgm_contextp->k_eip
2142	else
2143		echo loadcontext not supported on this architecture\n
2144	end
2145	end
2146end
2147
2148define resetcorectx
2149	select 0
2150	if ($kgm_mtype == 18)
2151		set $kgm_corecontext = (struct savearea *) kdp.saved_state
2152		loadcontext $kgm_corecontext
2153	else
2154	if ($kgm_mtype == 7)
2155		set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state
2156		set $ebx = $kdpstatep->ebx
2157		set $ebp = $kdpstatep->ebp
2158		set $edi = $kdpstatep->edi
2159		set $esi = $kdpstatep->esi
2160		set $eip = $kdpstatep->eip
2161		set $eax = $kdpstatep->eax
2162		set $ecx = $kdpstatep->ecx
2163		set $edx = $kdpstatep->edx
2164		flushregs
2165		flushstack
2166		set $pc = $kdpstatep->eip
2167		update
2168	else
2169		echo resetcorectx not supported on this architecture\n
2170	end
2171	end
2172	showcontext_int
2173end
2174
2175document resetcorectx
2176Syntax: resetcorectx
2177| The corefile equivalent of "resetctx". Returns to the original
2178| execution context (that of the active thread at the time of the NMI or
2179| panic). This command should be issued if you wish to resume
2180| execution after using the "switchtocorethread" command.
2181end
2182
2183#Helper function for "showallgdbstacks"
2184
2185define showgdbthread
2186	printf "            0x%08x  ", $arg0
2187	set $kgm_thread = *(struct thread *)$arg0
2188	printf "0x%08x  ", $arg0
2189	printf "%3d  ", $kgm_thread.sched_pri
2190	set $kgm_state = $kgm_thread.state
2191	if $kgm_state & 0x80
2192	    printf "I" 
2193	end
2194	if $kgm_state & 0x40
2195	    printf "P" 
2196	end
2197	if $kgm_state & 0x20
2198	    printf "A" 
2199	end
2200	if $kgm_state & 0x10
2201	    printf "H" 
2202	end
2203	if $kgm_state & 0x08
2204	    printf "U" 
2205	end
2206	if $kgm_state & 0x04
2207	    printf "R" 
2208	end
2209	if $kgm_state & 0x02
2210	    printf "S" 
2211	end
2212   	if $kgm_state & 0x01
2213	    printf "W\t" 
2214	    printf "0x%08x  ", $kgm_thread.wait_queue
2215            output /a (unsigned) $kgm_thread.wait_event
2216		if ($kgm_thread.uthread != 0)
2217			set $kgm_uthread = (struct uthread *)$kgm_thread.uthread
2218			if ($kgm_uthread->uu_wmesg != 0)
2219				printf " \"%s\"", $kgm_uthread->uu_wmesg
2220			end
2221	    end
2222	end
2223	if $arg1 != 0
2224	    if ($kgm_thread.kernel_stack != 0)
2225		if ($kgm_thread.reserved_stack != 0)
2226			printf "\n\t\treserved_stack=0x%08x", $kgm_thread.reserved_stack
2227		end
2228		printf "\n\t\tkernel_stack=0x%08x", $kgm_thread.kernel_stack
2229		if ($kgm_mtype == 18)
2230			set $mysp = $kgm_thread.machine.pcb->save_r1
2231		end
2232		if ($kgm_mtype == 7)
2233			set $kgm_statep = (struct x86_kernel_state32 *) \
2234				($kgm_thread->kernel_stack + 0x4000 \
2235				 - sizeof(struct x86_kernel_state32))
2236			set $mysp = $kgm_statep->k_ebp
2237		end
2238		if ($kgm_mtype == 12)
2239			if ($arg0 == $r9)
2240				set $mysp = $r7
2241			else
2242                        	set $kgm_statep = (struct arm_saved_state *)$kgm_thread.machine.kstackptr
2243                        	set $mysp = $kgm_statep->r[7]
2244			end
2245		end
2246		set $prevsp = 0
2247		printf "\n\t\tstacktop=0x%08x", $mysp
2248		if ($arg2 == 0)
2249			switchtoact $arg0
2250		else
2251			switchtocorethread $arg0
2252		end
2253	    	bt
2254	    else
2255		printf "\n\t\t\tcontinuation="
2256		output /a (unsigned) $kgm_thread.continuation
2257	    end
2258	    printf "\n"
2259	else
2260	    printf "\n"
2261	end
2262end	    
2263
2264#Use of this macro is currently (8/04) blocked by the fact that gdb
2265#stops evaluating macros when encountering an error, such as a failure
2266#to read memory from a certain location. Until this issue (described in
2267#3758949) is addressed, evaluation of this macro may stop upon
2268#encountering such an error.
2269
2270define showallgdbstacks
2271    set $kgm_head_taskp = &tasks
2272    set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
2273    while $kgm_taskp != $kgm_head_taskp
2274        showtaskheader
2275	showtaskint $kgm_taskp
2276	set $kgm_head_actp = &($kgm_taskp->threads)
2277        set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
2278	while $kgm_actp != $kgm_head_actp
2279	    showactheader
2280	    showgdbthread $kgm_actp 1 0
2281  	    set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
2282        end
2283	printf "\n"
2284    	set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
2285    end
2286    resetctx
2287end
2288
2289document showallgdbstacks
2290Syntax: showallgdbstacks
2291| An alternative to "showallstacks". Iterates through the task list and
2292| displays a gdb generated backtrace for each kernel thread. It is
2293| advantageous in that it is much faster than "showallstacks", and
2294| decodes function call arguments and displays source level traces, but
2295| it has the drawback that it doesn't determine if frames belong to
2296| functions from kernel extensions, as with "showallstacks".
2297| This command may terminate prematurely because of a gdb bug
2298| (Radar 3758949), which stops macro evaluation on memory read
2299| errors.
2300end
2301
2302define showallgdbcorestacks
2303	select 0
2304	set $kgm_head_taskp = &tasks
2305	set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
2306        while $kgm_taskp != $kgm_head_taskp
2307		showtaskheader
2308		showtaskint $kgm_taskp
2309		set $kgm_head_actp = &($kgm_taskp->threads)
2310		set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
2311		while $kgm_actp != $kgm_head_actp
2312		showactheader
2313		showgdbthread $kgm_actp 1 1
2314		set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
2315		end
2316		printf "\n"
2317		set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
2318	end
2319	resetcorectx
2320end
2321
2322
2323document showallgdbcorestacks
2324Syntax: showallgdbcorestacks
2325|Corefile version of "showallgdbstacks"
2326end
2327
2328
2329define switchtouserthread
2330		select 0
2331  		if ($kgm_mtype == 18)	
2332		   if ($kdp_act_counter == 0)
2333		      set $kdpstate = (struct savearea *) kdp.saved_state
2334		   end
2335		   set $kdp_act_counter = $kdp_act_counter + 1
2336		   set $newact = (struct thread *) $arg0
2337		   _kgm_flush_loop
2338		   set $checkpc = $newact->machine->upcb.save_srr0
2339		   if ($checkpc == 0)
2340		      echo This activation does not appear to have
2341		      echo \20 a valid user context.\n
2342		   else	      
2343		     set (struct savearea *) kdp.saved_state=$newact->machine->upcb
2344		     set $pc = $checkpc
2345#flush and update seem to be executed lazily by gdb on Tiger, hence the
2346#repeated invocations - see 3743135
2347	   	    _kgm_flush_loop
2348# This works because the new pmap is used only for reads
2349		     set kdp_pmap = $newact->task->map->pmap
2350		     _kgm_flush_loop
2351		     _kgm_update_loop
2352		   end
2353		else
2354		   echo switchtouserthread not implemented for this architecture.\n
2355	end
2356end
2357
2358document switchtouserthread
2359Syntax: switchtouserthread <address of thread>
2360| Analogous to switchtoact, but switches to the user context of a
2361| specified thread address. Similar to the "showuserstack"
2362| command, but this command does not return gdb to the kernel context
2363| immediately. This is to assist with the following (rather risky)
2364| manoeuvre - upon switching to the user context and virtual address
2365| space, the user may choose to call remove-symbol-file on the
2366| mach_kernel symbol file, and then add-symbol-file on the user space
2367| binary's symfile. gdb can then generate symbolic backtraces 
2368| for the user space thread. To return to the
2369| kernel context and virtual address space, the process must be
2370| reversed, i.e. call remove-symbol-file on the user space symbols, and
2371| then add-symbol-file on the appropriate mach_kernel, and issue the
2372| "resetstacks" command. Note that gdb may not react kindly to all these
2373| symbol file switches. The same restrictions that apply to "showuserstack"
2374| apply here - pages that have been paged out cannot be read while in the
2375| debugger context, so backtraces may terminate early.
2376| If the virtual addresses in the stack trace do not conflict with those
2377| of symbols in the kernel's address space, it may be sufficient to
2378| just do an add-symbol-file on the user space binary's symbol file.
2379| Note that while this command works on Panther's gdb, an issue
2380| with Tiger gdb (3743135) appears to hamper the evaluation of this
2381| macro in some cases.
2382end
2383
2384define showmetaclass
2385    set $kgm_metaclassp = (OSMetaClass *)$arg0
2386    printf "%-5d", $kgm_metaclassp->instanceCount
2387    printf "x %5d bytes", $kgm_metaclassp->classSize
2388    printf " %s\n", $kgm_metaclassp->className->string
2389end
2390
2391define showstring
2392    printf "\"%s\"", ((OSString *)$arg0)->string
2393end
2394
2395define shownumber
2396    printf "%lld", ((OSNumber *)$arg0)->value
2397end
2398
2399define showboolean
2400    if ($arg0 == gOSBooleanFalse)
2401	printf "No"
2402    else
2403	printf "Yes"
2404    end
2405end
2406
2407define showdata
2408    set $kgm_data = (OSData *)$arg0
2409
2410    printf "<"
2411    set $kgm_datap = (const unsigned char *) $kgm_data->data
2412
2413    set $kgm_printstr = 0
2414    if (0 == (3 & (unsigned int)$kgm_datap) && ($kgm_data->length >= 3))
2415	set $kgm_bytes = *(unsigned int *) $kgm_datap
2416	if (0xffff0000 & $kgm_bytes)
2417	    set $kgm_idx = 0
2418	    set $kgm_printstr = 1
2419	    while ($kgm_idx++ < 4)
2420		set $kgm_bytes = $kgm_bytes >> 8
2421		set $kgm_char = 0xff & $kgm_bytes
2422		if ($kgm_char && (($kgm_char < 0x20) || ($kgm_char > 0x7e)))
2423		    set $kgm_printstr = 0
2424		end
2425	    end
2426	end
2427    end
2428    
2429    set $kgm_idx = 0
2430    if ($kgm_printstr)
2431	set $kgm_quoted = 0
2432	while ($kgm_idx < $kgm_data->length)
2433	    set $kgm_char = $kgm_datap[$kgm_idx++]
2434	    if ($kgm_char)
2435		if (0 == $kgm_quoted)
2436		    set $kgm_quoted = 1
2437		    if ($kgm_idx > 1)
2438			printf ",\""
2439		    else
2440			printf "\""
2441		    end
2442		end
2443		printf "%c", $kgm_char
2444	    else
2445		if ($kgm_quoted)
2446		    set $kgm_quoted = 0
2447		    printf "\""
2448		end
2449	    end
2450	end
2451	if ($kgm_quoted)
2452	    printf "\""
2453	end
2454    else
2455	if (0 == (3 & (unsigned int)$kgm_datap))
2456	    while (($kgm_idx + 3) <= $kgm_data->length)
2457		printf "%08x", *(unsigned int *) &$kgm_datap[$kgm_idx]
2458		set $kgm_idx = $kgm_idx + 4
2459	    end
2460	end
2461	while ($kgm_idx < $kgm_data->length)
2462	    printf "%02x", $kgm_datap[$kgm_idx++]
2463	end
2464    end
2465    printf ">"
2466end
2467
2468define showdictionaryint
2469    set $kgm$arg0_dict = (OSDictionary *)$arg1
2470
2471    printf "{"
2472    set $kgm$arg0_idx = 0
2473    while ($kgm$arg0_idx < $kgm$arg0_dict->count)
2474	set $kgm_obj = $kgm$arg0_dict->dictionary[$kgm$arg0_idx].key
2475	showobjectint _$arg0 $kgm_obj
2476	printf "="
2477	set $kgm_obj = $kgm$arg0_dict->dictionary[$kgm$arg0_idx++].value
2478	showobjectint _$arg0 $kgm_obj
2479	if ($kgm$arg0_idx < $kgm$arg0_dict->count)
2480	    printf ","
2481	end
2482    end
2483    printf "}"
2484end
2485
2486define indent
2487    set $kgm_idx = 0
2488    while ($kgm_idx < $arg0)
2489	if ($arg1 & (1 << $kgm_idx++))
2490	    printf "| "
2491	else
2492	    printf "  "
2493	end
2494    end
2495end
2496
2497define showregdictionary
2498    indent $kgm_reg_depth+2 $arg1
2499    printf "{\n"
2500
2501    set $kgm_reg_idx = 0
2502    while ($kgm_reg_idx < $arg0->count)
2503	indent $kgm_reg_depth+2 $arg1
2504	printf "  "
2505	set $kgm_obj = $arg0->dictionary[$kgm_reg_idx].key
2506	showobjectint _ $kgm_obj
2507	printf " = "
2508
2509	set $kgm_obj = $arg0->dictionary[$kgm_reg_idx++].value
2510	showobjectint _ $kgm_obj
2511	printf "\n"
2512    end
2513    indent $kgm_reg_depth+2 $arg1
2514    printf "}\n"
2515end
2516
2517
2518define showarraysetint
2519    set $kgm$arg0_array = (OSArray *)$arg1
2520
2521    set $kgm$arg0_idx = 0
2522    while ($kgm$arg0_idx < $kgm$arg0_array->count)
2523	set $kgm_obj = $kgm$arg0_array->array[$kgm$arg0_idx++]
2524	showobjectint _$arg0 $kgm_obj
2525	if ($kgm$arg0_idx < $kgm$arg0_array->count)
2526	    printf ","
2527	end
2528    end
2529end
2530
2531define showarrayint
2532    printf "("
2533    showarraysetint $arg0 $arg1
2534    printf ")"
2535end
2536
2537define showsetint
2538    set $kgm_array = ((OSSet *)$arg1)->members
2539    printf "["
2540    showarraysetint $arg0 $kgm_array
2541    printf "]"
2542end
2543
2544
2545define showobjectint
2546    set $kgm_obj = (OSObject *) $arg1
2547    set $kgm_vt = *((void **) $arg1)
2548
2549    if ($kgm_mtype == 12)
2550        set $kgm_vt = $kgm_vt - 2 * sizeof(void *)
2551    end
2552
2553    if ($kgm_show_object_addrs)
2554	printf "`object %p, vt ", $arg1
2555	output /a (unsigned) $kgm_vt
2556	if ($kgm_show_object_retain)
2557	    printf ", retain count %d, container retain %d", (0xffff & $kgm_obj->retainCount), $kgm_obj->retainCount >> 16
2558	end
2559	printf "` "
2560    end
2561
2562    if ($kgm_vt == _ZTV8OSString)
2563	showstring $arg1
2564    else
2565	if ($kgm_vt == _ZTV8OSSymbol)
2566	    showstring $arg1
2567	else
2568	    if ($kgm_vt == _ZTV8OSNumber)
2569		shownumber $arg1
2570	    else
2571		if ($kgm_vt == _ZTV6OSData)
2572		    showdata $arg1
2573		else
2574		    if ($kgm_vt == _ZTV9OSBoolean)
2575			showboolean $arg1
2576		    else
2577			if ($kgm_vt == _ZTV12OSDictionary)
2578			    showdictionaryint _$arg0 $arg1
2579			else
2580			    if ($kgm_vt == _ZTV7OSArray)
2581				showarrayint _$arg0 $arg1
2582			    else
2583				if ($kgm_vt == _ZTV5OSSet)
2584				    showsetint _$arg0 $arg1
2585				else
2586				    if ($kgm_show_object_addrs == 0)
2587					printf "`object %p, vt ", $arg1
2588					output /a (unsigned) $kgm_vt
2589					printf "`"
2590				    end
2591				end
2592			    end
2593			end
2594		    end
2595		end
2596	    end
2597	end
2598    end
2599end
2600
2601define showobject
2602    set $kgm_save = $kgm_show_object_addrs
2603    set $kgm_show_object_addrs = 1
2604    set $kgm_show_object_retain = 1
2605    showobjectint _ $arg0
2606    set $kgm_show_object_addrs = $kgm_save
2607    set $kgm_show_object_retain = 0
2608    printf "\n"
2609end
2610document showobject
2611Syntax: (gdb) showobject <object address>
2612| Show info about an OSObject - its vtable ptr and retain count.
2613| If the object is a simple container class, more info will be shown.
2614end
2615
2616define dictget 
2617    set $kgm_dictp = (OSDictionary *)$arg0
2618    set $kgm_keyp = (const OSSymbol *)$arg1
2619    set $kgm_idx = 0
2620    set $kgm_result = 0
2621    while (($kgm_idx < $kgm_dictp->count) && ($kgm_result == 0))
2622	if ($kgm_keyp == $kgm_dictp->dictionary[$kgm_idx].key)
2623	    set $kgm_result = $kgm_dictp->dictionary[$kgm_idx].value
2624	end
2625	set $kgm_idx = $kgm_idx + 1
2626    end
2627end
2628
2629
2630define showregistryentryrecurse
2631    set $kgm_re         = (IOService *)$arg1
2632    set $kgm$arg0_stack = (unsigned long long) $arg2
2633
2634    if ($arg3)
2635	set $kgm$arg0_stack = $kgm$arg0_stack | (1ULL << $kgm_reg_depth)
2636    else
2637	set $kgm$arg0_stack = $kgm$arg0_stack & ~(1ULL << $kgm_reg_depth)
2638    end
2639
2640    dictget $kgm_re->fRegistryTable $kgm_childkey
2641    set $kgm$arg0_child_array = (OSArray *) $kgm_result
2642
2643    if ($kgm$arg0_child_array)
2644	set $kgm$arg0_child_count = $kgm$arg0_child_array->count
2645    else
2646	set $kgm$arg0_child_count = 0
2647    end
2648
2649    if ($kgm$arg0_child_count)
2650	set $kgm$arg0_stack = $kgm$arg0_stack | (2ULL << $kgm_reg_depth)
2651    else
2652	set $kgm$arg0_stack = $kgm$arg0_stack & ~(2ULL << $kgm_reg_depth)
2653    end
2654
2655    indent $kgm_reg_depth $kgm$arg0_stack
2656    printf "+-o "
2657
2658    dictget $kgm_re->fRegistryTable $kgm_namekey
2659    if ($kgm_result == 0)
2660	dictget $kgm_re->fRegistryTable gIONameKey
2661    end
2662    if ($kgm_result == 0)
2663	dictget $kgm_re->fPropertyTable gIOClassKey
2664    end
2665
2666    if ($kgm_result != 0)
2667	printf "%s", ((OSString *)$kgm_result)->string
2668    else
2669 	if (((IOService*)$kgm_re)->pwrMgt &&  ((IOService*)$kgm_re)->pwrMgt->Name)
2670 	    printf "%s", ((IOService*)$kgm_re)->pwrMgt->Name
2671	else
2672#	    printf ", guessclass "
2673#	    guessclass $kgm_re
2674	    printf "??"
2675	end
2676    end
2677
2678
2679    printf "  <object %p, ", $kgm_re
2680    printf "vtable "
2681    set $kgm_vt = (unsigned) *(void**) $kgm_re
2682    if ($kgm_mtype == 12)
2683        set $kgm_vt = $kgm_vt - 2 * sizeof(void *)
2684    end
2685    output /a $kgm_vt
2686
2687    if ($kgm_vt != _ZTV15IORegistryEntry)
2688	printf ", "
2689	set $kgm_state =  $kgm_re->__state[0]
2690	# kIOServiceRegisteredState
2691	if (0 == ($kgm_state & 2))
2692	    printf "!"
2693	end
2694	printf "registered, "
2695	# kIOServiceMatchedState
2696	if (0 == ($kgm_state & 4))
2697	    printf "!"
2698	end
2699	printf "matched, "
2700	# kIOServiceInactiveState
2701	if ($kgm_state & 1)
2702	    printf "in"
2703	end
2704	printf "active, busy %d, retain count %d", (0xff & $kgm_re->__state[1]), (0xffff & $kgm_re->retainCount)
2705    end
2706    printf ">\n"
2707
2708    if ($kgm_show_props)
2709	set $kgm_props = $kgm_re->fPropertyTable
2710	showregdictionary $kgm_props $kgm$arg0_stack
2711    end
2712
2713    # recurse
2714    if ($kgm$arg0_child_count != 0)
2715
2716	set $kgm_reg_depth = $kgm_reg_depth + 1
2717	set $kgm$arg0_child_idx = 0
2718
2719	while ($kgm$arg0_child_idx < $kgm$arg0_child_count)
2720	    set $kgm_re = $kgm$arg0_child_array->array[$kgm$arg0_child_idx++]
2721	    set $kgm_more_sib = ($kgm$arg0_child_idx < $kgm$arg0_child_count)
2722	    showregistryentryrecurse _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib
2723	end
2724
2725	set $kgm_reg_depth = $kgm_reg_depth - 1
2726    end
2727end
2728
2729define showregistryentryint
2730    set $kgm_namekey   = (OSSymbol *) $kgm_reg_plane[2]
2731    set $kgm_childkey  = (OSSymbol *) $kgm_reg_plane[4]
2732
2733    showregistryentryrecurse _ $arg0 0 0
2734end
2735
2736define showregistry
2737    set $kgm_reg_depth  = 0
2738    set $kgm_show_props = 0
2739    showregistryentryint gRegistryRoot
2740end
2741document showregistry
2742Syntax: (gdb) showregistry 
2743| Show info about all registry entries in the current plane.
2744end
2745
2746define showregistryprops
2747    set $kgm_reg_depth  = 0
2748    set $kgm_show_props = 1
2749    showregistryentryint gRegistryRoot
2750end
2751document showregistryprops
2752Syntax: (gdb) showregistryprops 
2753| Show info about all registry entries in the current plane, and their properties.
2754| set $kgm_show_object_addrs = 1 and/or set $kgm_show_object_retain = 1 will display
2755| more verbose information
2756end
2757
2758define showregistryentry
2759    set $kgm_reg_depth  = 0
2760    set $kgm_show_props = 1
2761    showregistryentryint $arg0
2762end
2763document showregistryentry
2764Syntax: (gdb) showregistryentry <object address>
2765| Show info about a registry entry; its properties and descendants in the current plane.
2766end
2767
2768define setregistryplane
2769    if ($arg0)
2770	set $kgm_reg_plane = (void **) $arg0
2771    else
2772	showobjectint _ gIORegistryPlanes
2773	printf "\n"
2774    end
2775end
2776document setregistryplane
2777Syntax: (gdb) setregistryplane <plane object address>
2778| Set the plane to be used for the iokit registry macros. An argument of zero will 
2779| display known planes.
2780end
2781
2782define guessclass
2783    set $kgm_classidx = 0
2784    set $kgm_lookvt = *((void **) $arg0)
2785    set $kgm_bestvt = (void *) 0
2786    set $kgm_bestidx = 0
2787    
2788    while $kgm_classidx < sAllClassesDict->count
2789	set $kgm_meta = (OSMetaClass *) sAllClassesDict->dictionary[$kgm_classidx].value
2790
2791	set $kgm_vt = *((void **) $kgm_meta)
2792
2793	if (($kgm_vt > $kgm_bestvt) && ($kgm_vt < $kgm_lookvt))
2794	    set $kgm_bestvt  = $kgm_vt
2795	    set $kgm_bestidx = $kgm_classidx
2796	end
2797	set $kgm_classidx = $kgm_classidx + 1
2798    end
2799    printf "%s", sAllClassesDict->dictionary[$kgm_bestidx].key->string
2800end
2801
2802define showallclasses
2803    set $kgm_classidx = 0
2804    while $kgm_classidx < sAllClassesDict->count
2805	set $kgm_meta = (OSMetaClass *) sAllClassesDict->dictionary[$kgm_classidx++].value
2806	showmetaclass $kgm_meta
2807    end
2808end
2809
2810document showallclasses
2811Syntax: (gdb) showallclasses
2812| Show the instance counts and ivar size of all OSObject subclasses. See ioclasscount man page for details.
2813end
2814
2815define showioalloc
2816    printf " Instance allocation = 0x%08lx = %4ld K\n", (int) debug_ivars_size, ((int) debug_ivars_size) / 1024
2817    printf "Container allocation = 0x%08lx = %4ld K\n", (int) debug_container_malloc_size, ((int) debug_container_malloc_size) / 1024
2818    printf " IOMalloc allocation = 0x%08lx = %4ld K\n", (int) debug_iomalloc_size, ((int) debug_iomalloc_size) / 1024
2819    printf " Pageable allocation = 0x%08lx = %4ld K\n", (vm_size_t) debug_iomallocpageable_size, ((vm_size_t) debug_iomallocpageable_size) / 1024
2820end
2821
2822document showioalloc
2823Syntax: (gdb) showioalloc
2824| Show some accounting of memory allocated by IOKit allocators. See ioalloccount man page for details.
2825end
2826
2827define showosobjecttracking
2828    set $kgm_next = (OSObjectTracking *) gOSObjectTrackList.next
2829    while $kgm_next != &gOSObjectTrackList
2830	set $obj = (OSObject *) ($kgm_next+1)
2831	showobject $obj
2832	set $kgm_idx = 0
2833	while $kgm_idx < (sizeof($kgm_next->bt) / sizeof($kgm_next->bt[0]))
2834	    if ((unsigned) $kgm_next->bt[$kgm_idx] > (unsigned) sectPRELINKB)
2835		showkmodaddr $kgm_next->bt[$kgm_idx]
2836		printf "\n"
2837	    else
2838		if ((unsigned) $kgm_next->bt[$kgm_idx] > 0)
2839		    output /a (unsigned) $kgm_next->bt[$kgm_idx]
2840		    printf "\n"
2841		end
2842	    end
2843	    set $kgm_idx = $kgm_idx + 1
2844	end
2845	printf "\n"
2846	set $kgm_next = (OSObjectTracking *) $kgm_next->link.next
2847    end
2848end
2849
2850document showosobjecttracking
2851Syntax: (gdb) showosobjecttracking
2852| Show the list of tracked OSObject allocations with backtraces.
2853| Boot with the kOSTraceObjectAlloc (0x00400000) io debug flag set. 
2854| Set gOSObjectTrackThread to 1 or a thread_t to capture new OSObjects allocated by a thread or all threads.
2855end
2856
2857define readphys
2858       set kdp_trans_off = 1
2859       x/x $arg0
2860       set kdp_trans_off = 0
2861end
2862
2863define readphys64
2864	if ($kgm_mtype == 18)
2865	   set kdp_src_high32 = ((uint32_t) ($arg0)) >> 32
2866	   x/x (uint32_t) (($arg0) & 0x00000000ffffffffUL)
2867	   set kdp_src_high32 = 0
2868	else
2869		echo readphys64 not available on this architecture.\n
2870	end
2871end
2872
2873document readphys
2874| The argument is interpreted as a physical address, and the word addressed is
2875| displayed. While this fails if no physical page exists at the given address,
2876| it must be used with caution.
2877end
2878
2879document readphys64
2880| The argument is interpreted as a 64-bit physical address, and the word
2881| addressed is displayed. While this fails if no physical page exists at the
2882| given address, it must be used with caution.
2883end
2884
2885define addkextsyms
2886        shell ls $arg0/* | xargs -n 1 echo add-symbol-file > /tmp/gdb-syms
2887        source /tmp/gdb-syms
2888	set $kgm_show_kmod_syms = 1
2889end
2890
2891document addkextsyms
2892| Takes a directory of symbols for kexts generated with kextcache -y and loads them
2893| into gdb.
2894| (gdb) addkextsyms /path/to/symboldir
2895end
2896
2897define showprocfiles
2898    if ($argc == 1)
2899	_showprocheader
2900	_showprocfiles $arg0
2901    else
2902    	printf "| Usage:\n|\n"
2903	help showprocfiles
2904    end
2905end
2906document showprocfiles
2907Syntax: (gdb) showprocfiles <proc_t>
2908| Given a proc_t pointer, display the list of open file descriptors for the
2909| referenced process.
2910end
2911
2912define _showprocheader
2913    printf "fd     fileglob    fg flags    fg type   fg data     info\n"
2914    printf "-----  ----------  ----------  --------  ----------  -------------------\n"
2915end
2916
2917define _showprocfiles
2918    set $kgm_spf_filedesc = ((proc_t)$arg0)->p_fd
2919    set $kgm_spf_last = $kgm_spf_filedesc->fd_lastfile
2920    set $kgm_spf_ofiles = $kgm_spf_filedesc->fd_ofiles
2921    set $kgm_spf_count = 0
2922    while ($kgm_spf_count <= $kgm_spf_last)
2923	if ($kgm_spf_ofiles[$kgm_spf_count] == 0)
2924	    # DEBUG: For files that were open, but are now closed
2925	    # printf "%-5d  FILEPROC_NULL\n", $kgm_spf_count
2926	else
2927	    # display fd #, fileglob address, fileglob flags
2928	    set $kgm_spf_flags = $kgm_spf_ofiles[$kgm_spf_count].f_flags
2929	    set $kgm_spf_fg = $kgm_spf_ofiles[$kgm_spf_count].f_fglob
2930	    printf "%-5d  0x%08x  0x%08x  ", $kgm_spf_count, $kgm_spf_fg, $kgm_spf_flags
2931	    # decode fileglob type
2932	    set $kgm_spf_fgt = $kgm_spf_fg->fg_type
2933	    if ($kgm_spf_fgt == 1)
2934	    	printf "VNODE   "
2935	    end
2936	    if ($kgm_spf_fgt == 2)
2937	    	printf "SOCKET  "
2938	    end
2939	    if ($kgm_spf_fgt == 3)
2940	    	printf "PSXSHM  "
2941	    end
2942	    if ($kgm_spf_fgt == 4)
2943	    	printf "PSXSEM  "
2944	    end
2945	    if ($kgm_spf_fgt == 5)
2946	    	printf "KQUEUE  "
2947	    end
2948	    if ($kgm_spf_fgt == 6)
2949	    	printf "PIPE    "
2950	    end
2951	    if ($kgm_spf_fgt == 7)
2952	    	printf "FSEVENTS"
2953	    end
2954	    if ($kgm_spf_fgt < 1 || $kgm_spf_fgt > 7)
2955	        printf "?: %-5d", $kgm_spf_fgt
2956	    end
2957
2958	    # display fileglob data address and decode interesting fact(s)
2959	    # about data, if we know any
2960	    set $kgm_spf_fgd = $kgm_spf_fg->fg_data
2961	    printf "  0x%08x  ", $kgm_spf_fgd
2962	    if ($kgm_spf_fgt == 1)
2963	    	set $kgm_spf_name = ((struct vnode *)$kgm_spf_fgd)->v_name
2964		if ($kgm_spf_name == 0)
2965		    printf "(null)"
2966		else
2967		    printf "%s", $kgm_spf_name
2968		end
2969	    end
2970	    printf "\n"
2971	end
2972    	set $kgm_spf_count = $kgm_spf_count + 1
2973    end
2974end
2975
2976#
2977# Show all the advisory file locks held by a process for each of the vnode
2978# type files that it has open; do this by walking the per process open file
2979# table and looking at any vnode type fileglob that has a non-NULL lock list
2980# associated with it.
2981#
2982define showproclocks
2983    if ($argc == 1)
2984	_showproclocks $arg0
2985    else
2986    	printf "| Usage:\n|\n"
2987	help showproclocks
2988    end
2989end
2990document showproclocks
2991Syntax: (gdb) showproclocks <proc_t>
2992| Given a proc_t pointer, display the list of advisory file locks held by the
2993| referenced process.
2994end
2995
2996define _showproclocks
2997    set $kgm_spl_filedesc = ((proc_t)$arg0)->p_fd
2998    set $kgm_spl_last = $kgm_spl_filedesc->fd_lastfile
2999    set $kgm_spl_ofiles = $kgm_spl_filedesc->fd_ofiles
3000    set $kgm_spl_count = 0
3001    set $kgm_spl_seen = 0
3002    while ($kgm_spl_count <= $kgm_spl_last)
3003	if ($kgm_spl_ofiles[$kgm_spl_count] == 0)
3004	    # DEBUG: For files that were open, but are now closed
3005	    # printf "%-5d  FILEPROC_NULL\n", $kgm_spl_count
3006	else
3007	    set $kgm_spl_fg = $kgm_spl_ofiles[$kgm_spl_count].f_fglob
3008	    # decode fileglob type
3009	    set $kgm_spl_fgt = $kgm_spl_fg->fg_type
3010	    if ($kgm_spl_fgt == 1)
3011		set $kgm_spl_fgd = $kgm_spl_fg->fg_data
3012	    	set $kgm_spl_name = ((struct vnode *)$kgm_spl_fgd)->v_name
3013		set $kgm_spl_vnode = ((vnode_t)$kgm_spl_fgd)
3014		set $kgm_spl_lockiter = $kgm_spl_vnode->v_lockf
3015		if ($kgm_spl_lockiter != 0)
3016		    if ($kgm_spl_seen == 0)
3017			_showvnodelockheader
3018		    end
3019		    set $kgm_spl_seen = $kgm_spl_seen + 1
3020		    printf "( fd %d, name ", $kgm_spl_count
3021		    if ($kgm_spl_name == 0)
3022			printf "(null) )"
3023		    else
3024			printf "%s )\n", $kgm_spl_name
3025		    end
3026		    _showvnodelocks $kgm_spl_fgd
3027		end
3028	    end
3029	end
3030    	set $kgm_spl_count = $kgm_spf_count + 1
3031    end
3032    printf "%d total locks for 0x%08x\n", $kgm_spl_seen, $arg0
3033end
3034
3035define showprocinfo
3036    set $kgm_spi_proc = (proc_t)$arg0
3037    printf "Process 0x%08x\n", $kgm_spi_proc
3038    printf "   name %s\n", $kgm_spi_proc->p_comm
3039	printf "   pid:%.8d", $kgm_spi_proc->p_pid
3040	printf "   task:0x%.8x", $kgm_spi_proc->task
3041	printf "   p_stat:%.1d", $kgm_spi_proc->p_stat
3042	printf "   parent pid:%.8d", $kgm_spi_proc->p_ppid
3043    # decode part of credential
3044    set $kgm_spi_cred = $kgm_spi_proc->p_ucred
3045    if ($kgm_spi_cred != 0)
3046	printf "Cred: euid %d ruid %d svuid %d\n", $kgm_spi_cred->cr_uid, $kgm_spi_cred->cr_ruid, $kgm_spi_cred->cr_svuid
3047    else
3048    	printf "Cred: (null)\n"
3049    end
3050    # decode flags
3051    set $kgm_spi_flag = $kgm_spi_proc->p_flag
3052    printf "Flags: 0x%08x\n", $kgm_spi_flag
3053    if ($kgm_spi_flag & 0x00000001)
3054	printf "    0x00000001 - may hold advisory locks\n"
3055    end
3056    if ($kgm_spi_flag & 0x00000002)
3057	printf "    0x00000002 - has a controlling tty\n"
3058    end
3059    if ($kgm_spi_flag & 0x00000004)
3060	printf "    0x00000004 - process is 64 bit\n"
3061    else
3062	printf "   !0x00000004 - process is 32 bit\n"
3063    end
3064    if ($kgm_spi_flag & 0x00000008)
3065	printf "    0x00000008 - no SIGCHLD on child stop\n"
3066    end
3067    if ($kgm_spi_flag & 0x00000010)
3068	printf "    0x00000010 - waiting for child exec/exit\n"
3069    end
3070    if ($kgm_spi_flag & 0x00000020)
3071	printf "    0x00000020 - has started profiling\n"
3072    end
3073    if ($kgm_spi_flag & 0x00000040)
3074	printf "    0x00000040 - in select; wakeup/waiting danger\n"
3075    end
3076    if ($kgm_spi_flag & 0x00000080)
3077	printf "    0x00000080 - was stopped and continued\n"
3078    end
3079    if ($kgm_spi_flag & 0x00000100)
3080	printf "    0x00000100 - has set privileges since exec\n"
3081    end
3082    if ($kgm_spi_flag & 0x00000200)
3083	printf "    0x00000200 - system process: no signals, stats, or swap\n"
3084    end
3085    if ($kgm_spi_flag & 0x00000400)
3086	printf "    0x00000400 - timing out during a sleep\n"
3087    end
3088    if ($kgm_spi_flag & 0x00000800)
3089	printf "    0x00000800 - debugged process being traced\n"
3090    end
3091    if ($kgm_spi_flag & 0x00001000)
3092	printf "    0x00001000 - debugging process has waited for child\n"
3093    end
3094    if ($kgm_spi_flag & 0x00002000)
3095	printf "    0x00002000 - exit in progress\n"
3096    end
3097    if ($kgm_spi_flag & 0x00004000)
3098	printf "    0x00004000 - process has called exec\n"
3099    end
3100    if ($kgm_spi_flag & 0x00008000)
3101	printf "    0x00008000 - owe process an addupc() XXX\n"
3102    end
3103    if ($kgm_spi_flag & 0x00010000)
3104	printf "    0x00010000 - affinity for Rosetta children\n"
3105    end
3106    if ($kgm_spi_flag & 0x00020000)
3107	printf "    0x00020000 - wants to run Rosetta\n"
3108    end
3109    if ($kgm_spi_flag & 0x00040000)
3110	printf "    0x00040000 - has wait() in progress\n"
3111    end
3112    if ($kgm_spi_flag & 0x00080000)
3113	printf "    0x00080000 - kdebug tracing on for this process\n"
3114    end
3115    if ($kgm_spi_flag & 0x00100000)
3116	printf "    0x00100000 - blocked due to SIGTTOU or SIGTTIN\n"
3117    end
3118    if ($kgm_spi_flag & 0x00200000)
3119	printf "    0x00200000 - has called reboot()\n"
3120    end
3121    if ($kgm_spi_flag & 0x00400000)
3122	printf "    0x00400000 - is TBE state\n"
3123    end
3124    if ($kgm_spi_flag & 0x00800000)
3125	printf "    0x00800000 - signal exceptions\n"
3126    end
3127    if ($kgm_spi_flag & 0x01000000)
3128	printf "    0x01000000 - being branch traced\n"
3129    end
3130    if ($kgm_spi_flag & 0x02000000)
3131	printf "    0x02000000 - has vfork() children\n"
3132    end
3133    if ($kgm_spi_flag & 0x04000000)
3134	printf "    0x04000000 - not allowed to attach\n"
3135    end
3136    if ($kgm_spi_flag & 0x08000000)
3137	printf "    0x08000000 - vfork() in progress\n"
3138    end
3139    if ($kgm_spi_flag & 0x10000000)
3140	printf "    0x10000000 - no shared libraries\n"
3141    end
3142    if ($kgm_spi_flag & 0x20000000)
3143	printf "    0x20000000 - force quota for root\n"
3144    end
3145    if ($kgm_spi_flag & 0x40000000)
3146	printf "    0x40000000 - no zombies when children exit\n"
3147    end
3148    if ($kgm_spi_flag & 0x80000000)
3149	printf "    0x80000000 - don't hang on remote FS ops\n"
3150    end
3151    # decode state
3152    set $kgm_spi_state = $kgm_spi_proc->p_stat
3153    printf "State: "
3154    if ($kgm_spi_state == 1)
3155    	printf "Idle\n"
3156    end
3157    if ($kgm_spi_state == 2)
3158    	printf "Run\n"
3159    end
3160    if ($kgm_spi_state == 3)
3161    	printf "Sleep\n"
3162    end
3163    if ($kgm_spi_state == 4)
3164    	printf "Stop\n"
3165    end
3166    if ($kgm_spi_state == 5)
3167    	printf "Zombie\n"
3168    end
3169    if ($kgm_spi_state == 6)
3170    	printf "Reaping\n"
3171    end
3172    if ($kgm_spi_state < 1 || $kgm_spi_state > 6)
3173    	printf "(Unknown)\n"
3174    end
3175end
3176
3177document showprocinfo
3178Syntax: (gdb) showprocinfo <proc_t>
3179| Displays name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields.
3180end
3181
3182#
3183# dump the zombprocs 
3184#
3185define zombproc
3186  set $basep = (struct proc  *)zombproc->lh_first
3187  set $pp = $basep
3188  while $pp
3189	showprocinfo $pp
3190      set $pp = $pp->p_list.le_next
3191  end
3192end
3193
3194document zombproc
3195Syntax: (gdb) zombproc 
3196| Routine to print out all procs in the zombie list
3197end
3198
3199#
3200# dump the zombstacks 
3201#
3202define zombstacks
3203  set $basep = (struct proc  *)zombproc->lh_first
3204  set $pp = $basep
3205  while $pp
3206	if $pp->p_stat != 5
3207		showtaskstacks $pp->task
3208	end
3209     set $pp = $pp->p_list.le_next
3210  end
3211end
3212
3213document zombstacks
3214Syntax: (gdb) zombstacks 
3215| Routine to print out all stacks of tasks that are exiting
3216end
3217
3218
3219#
3220# dump the allprocs
3221#
3222define allproc
3223  set $basep = (struct proc  *)allproc->lh_first
3224  set $pp = $basep
3225  while $pp
3226	showprocinfo $pp
3227      set $pp = $pp->p_list.le_next
3228  end
3229end
3230
3231document allproc
3232Syntax: (gdb) allproc 
3233| Routine to print out all process in the system 
3234| which are not in the zombie list
3235end
3236
3237
3238
3239define print_vnode
3240   set $vp = (struct vnode *)$arg0
3241   printf "   "
3242   printf " vp 0x%.8x", $vp
3243   printf " use %d", $vp->v_usecount
3244   printf " io %d", $vp->v_iocount
3245   printf " kuse %d", $vp->v_kusecount
3246   printf " type %d", $vp->v_type
3247   printf " flg 0x%.8x", $vp->v_flag
3248   printf " lflg 0x%.8x", $vp->v_lflag
3249   printf " par 0x%.8x", $vp->v_parent
3250   set $_name = (char *)$vp->v_name
3251   if ($_name != 0)
3252      printf " %s", $_name
3253   end
3254  if ($vp->v_type == VREG) && ($vp->v_un.vu_ubcinfo != 0)
3255       printf " mapped %d", ($vp->v_un.vu_ubcinfo.ui_flags & 0x08) ? 1 : 0
3256   end
3257   printf "\n"
3258end
3259
3260document print_vnode
3261Syntax: (gdb) print_vnode <vnode>
3262| Prints out the fields of a vnode struct
3263end
3264
3265define showprocvnodes
3266	set $pp = (struct proc *)$arg0
3267	set $fdp = (struct filedesc *)$pp->p_fd
3268	set $cvp = $fdp->fd_cdir
3269	set $rvp = $fdp->fd_rdir
3270	if $cvp
3271		printf "Current Working Directory \n"
3272		print_vnode $cvp
3273		printf "\n"
3274	end
3275	if $rvp
3276		printf "Current Root Directory \n"
3277		print_vnode $rvp
3278		printf "\n"
3279	end
3280	set $count = 0
3281	set $fpp =  (struct fileproc **)($fdp->fd_ofiles)
3282	set $fpo =  (char)($fdp->fd_ofileflags[0])
3283	while $count < $fdp->fd_nfiles
3284		#printf"fpp %x ", *$fpp
3285		if *$fpp
3286			set $fg =(struct fileglob *)((**$fpp)->f_fglob)
3287			if  $fg && (($fg)->fg_type == 1) 
3288				if $fdp->fd_ofileflags[$count] & 4
3289					printf "U: "
3290				else
3291					printf " "
3292				end
3293				printf "fd = %d ", $count
3294				print_vnode $fg->fg_data
3295			end
3296		end
3297		set $fpp = $fpp + 1
3298	 	set $count = $count + 1		
3299	end
3300end
3301
3302document showprocvnodes
3303Syntax: (gdb) showprocvnodes <proc_address>
3304| Routine to print out all the open fds
3305| which are vnodes in a process
3306end
3307
3308define showallprocvnodes
3309  set $basep = (struct proc  *)allproc->lh_first
3310  set $pp = $basep
3311  while $pp
3312	printf "============================================ \n"
3313	showprocinfo $pp
3314	showprocvnodes $pp
3315  	set $pp = $pp->p_list.le_next
3316  end
3317end
3318
3319document showallprocvnodes
3320Syntax: (gdb) showallprocvnodes
3321| Routine to print out all the open fds
3322| which are vnodes 
3323end
3324
3325
3326#   
3327# dump the childrent of a proc 
3328#
3329define showinitchild
3330  set $basep = (struct proc  *)initproc->p_children.lh_first
3331  set $pp = $basep
3332  while $pp
3333	showprocinfo $pp
3334      set $pp = $pp->p_sibling.le_next
3335  end
3336end
3337
3338document showinitchild
3339Syntax: (gdb) showinitchild 
3340| Routine to print out all processes in the system 
3341| which are children of init process
3342end
3343
3344
3345define showmountallvnodes
3346  set $mp = (struct mount *)$arg0
3347  set $basevp = (struct vnode *)$mp->mnt_vnodelist.tqh_first
3348  set $vp = $basevp
3349  printf "____________________ Vnode list Queue ---------------\n"
3350  while $vp
3351      print_vnode $vp
3352      set $vp = $vp->v_mntvnodes->tqe_next
3353  end
3354  set $basevp = (struct vnode *)$mp->mnt_workerqueue.tqh_first
3355  set $vp = $basevp
3356  printf "____________________ Worker Queue ---------------\n"
3357  while $vp
3358      print_vnode $vp
3359      set $vp = $vp->v_mntvnodes->tqe_next
3360  end
3361  set $basevp = (struct vnode *)$mp->mnt_newvnodes.tqh_first
3362  set $vp = $basevp
3363  printf "____________________ New vnodes  Queue ---------------\n"
3364  while $vp
3365      print_vnode $vp
3366      set $vp = $vp->v_mntvnodes->tqe_next
3367  end
3368end
3369document showmountallvnodes
3370Syntax: showmountallvnodes <struct mount *>
3371| Print the vnode inactive list
3372end
3373
3374
3375define showmountvnodes
3376  set $mp = (struct mount *)$arg0
3377  set $basevp = (struct vnode *)$mp->mnt_vnodelist.tqh_first
3378  set $vp = $basevp
3379  printf "____________________ Vnode list Queue ---------------\n"
3380  while $vp
3381      print_vnode $vp
3382      set $vp = $vp->v_mntvnodes->tqe_next
3383  end
3384end
3385document showmountvnodes
3386Syntax: showmountvnodes <struct mount *>
3387| Print the vnode list
3388end
3389
3390
3391
3392define showworkqvnodes
3393  set $mp = (struct mount *)$arg0
3394  set $basevp = (struct vnode *)$mp->mnt_workerqueue.tqh_first
3395  set $vp = $basevp
3396  printf "____________________ Worker Queue ---------------\n"
3397  while $vp
3398      print_vnode $vp
3399      set $vp = $vp->v_mntvnodes->tqe_next
3400  end
3401end
3402document showworkqvnodes
3403Syntax: showworkqvnodes <struct mount *>
3404| Print the vnode worker list
3405end
3406
3407
3408define shownewvnodes
3409  set $mp = (struct mount *)$arg0
3410  set $basevp = (struct vnode *)$mp->mnt_newvnodes.tqh_first
3411  set $vp = $basevp
3412  printf "____________________ New vnodes  Queue ---------------\n"
3413  while $vp
3414      print_vnode $vp
3415      set $vp = $vp->v_mntvnodes->tqe_next
3416  end
3417end
3418
3419document shownewvnodes
3420Syntax: shownewvnodes <struct mount *>
3421| Print the new vnode list
3422end
3423
3424
3425#
3426# print mount point info
3427define print_mount 
3428   set $mp = (struct mount *)$arg0
3429   printf "   "
3430   printf " mp 0x%.8x", $mp
3431   printf " flag %x", $mp->mnt_flag
3432   printf " kern_flag %x", $mp->mnt_kern_flag
3433   printf " lflag %x", $mp->mnt_lflag
3434   printf " type:  %s", $mp->mnt_vfsstat.f_fstypename
3435   printf " mnton:  %s", $mp->mnt_vfsstat.f_mntonname
3436   printf " mntfrom:  %s", $mp->mnt_vfsstat.f_mntfromname
3437   printf "\n"
3438end
3439
3440define showallmounts
3441	set $mp=(struct mount *)mountlist.tqh_first
3442	while $mp
3443	 	print_mount $mp
3444		set $mp = $mp->mnt_list.tqe_next
3445	end
3446end
3447	
3448document showallmounts
3449Syntax: showallmounts
3450| Print all mount points
3451end
3452
3453define pcprint
3454	set $pc = $arg0
3455	if ((unsigned int)$pc <= (unsigned int) $kgm_fkmodmax) && \
3456	    ((unsigned int)$pc >= (unsigned int)$kgm_fkmodmin)
3457		showkmodaddr $pc
3458	else
3459		output/a $pc
3460	end
3461end
3462
3463define mbuf_walkpkt
3464	set $mp = (struct mbuf *)$arg0
3465	set $cnt = 1
3466	set $tot = 0
3467	while $mp
3468		printf "%4d: 0x%08x [len %4d, type %2d, ", $cnt, $mp, \
3469		    $mp->m_hdr.mh_len, $mp->m_hdr.mh_type
3470		if mclaudit != 0
3471			mbuf_buf2mca $mp
3472			printf ", "
3473		end
3474		set $tot = $tot + $mp->m_hdr.mh_len
3475		printf "total %d]\n", $tot
3476		set $mp = $mp->m_hdr.mh_nextpkt
3477		set $cnt = $cnt + 1
3478	end
3479end
3480
3481document mbuf_walkpkt
3482Syntax: (gdb) mbuf_walkpkt <addr>
3483| Given an mbuf address, walk its m_nextpkt pointer
3484end
3485
3486define mbuf_walk
3487	set $mp = (struct mbuf *)$arg0
3488	set $cnt = 1
3489	set $tot = 0
3490	while $mp
3491		printf "%4d: 0x%08x [len %4d, type %2d, ", $cnt, $mp, \
3492		    $mp->m_hdr.mh_len, $mp->m_hdr.mh_type
3493		if mclaudit != 0
3494			mbuf_buf2mca $mp
3495			printf ", "
3496		end
3497		set $tot = $tot + $mp->m_hdr.mh_len
3498		printf "total %d]\n", $tot
3499		set $mp = $mp->m_hdr.mh_next
3500		set $cnt = $cnt + 1
3501	end
3502end
3503
3504document mbuf_walk
3505Syntax: (gdb) mbuf_walk <addr>
3506| Given an mbuf address, walk its m_next pointer
3507end
3508
3509define mbuf_buf2slab
3510	set $addr = $arg0
3511	set $gix = ((char *)$addr - (char *)mbutl) >> 20
3512	set $ix = ((char *)$addr - (char *)mbutl) >> 11
3513	set $slab = &slabstbl[$gix].slg_slab[$ix]
3514	printf "0x%08x", $slab
3515end
3516
3517document mbuf_buf2slab
3518| Given an mbuf object, find its corresponding slab address.
3519end
3520
3521define mbuf_buf2mca
3522	set $addr = $arg0
3523	set $ix = ((char *)$addr - (char *)mbutl) >> 11
3524	set $clbase = ((union mcluster *)(mbutl + $ix))
3525	set $mclidx = (((char *)$addr - (char *)$clbase) >> 8)
3526	set $mca = mclaudit[$ix].cl_audit[$mclidx]
3527	printf "mca: 0x%08x", $mca
3528end
3529
3530document mbuf_buf2mca
3531Syntax: (gdb) mbuf_buf2mca <addr>
3532| Given an mbuf object, find its buffer audit structure address.
3533| This requires mbuf buffer auditing to be turned on, by setting
3534| the appropriate flags to the "mbuf_debug" boot-args parameter.
3535end
3536
3537define mbuf_showmca
3538	set language c
3539	set $mca = (mcache_audit_t *)$arg0
3540	set $cp = (mcache_t *)$mca->mca_cache
3541	printf "object type:\t\t"
3542	mbuf_mca_ctype $mca 1
3543	printf "\ncontrolling mcache:\t%p (%s)\n", $mca->mca_cache, $cp->mc_name
3544	if $mca->mca_uflags & $MB_SCVALID
3545		set $ix = ((char *)$mca->mca_addr - (char *)mbutl) >> 11
3546		set $clbase = ((union mcluster *)(mbutl + $ix))
3547		set $mclidx = (((char *)$mca->mca_addr - (char *)$clbase) >> 8)
3548		printf "mbuf obj:\t\t%p\n", $mca->mca_addr
3549		printf "mbuf index:\t\t%d (out of 8) in cluster base %p\n", \
3550		    $mclidx + 1, $clbase
3551		if $mca->mca_uptr != 0
3552			set $peer_mca = (mcache_audit_t *)$mca->mca_uptr
3553			printf "paired cluster obj:\t%p (mca %p)\n", \
3554			    $peer_mca->mca_addr, $peer_mca
3555		end
3556		printf "saved contents:\t\t%p (%d bytes)\n", \
3557		    $mca->mca_contents, $mca->mca_contents_size
3558	else
3559		printf "cluster obj:\t\t%p\n", $mca->mca_addr
3560		if $mca->mca_uptr != 0
3561			set $peer_mca = (mcache_audit_t *)$mca->mca_uptr
3562			printf "paired mbuf obj:\t%p (mca %p)\n", \
3563			    $peer_mca->mca_addr, $peer_mca
3564		end
3565	end
3566	printf "recent transaction for this buffer (thread %p):\n", \
3567	    $mca->mca_thread
3568	set $cnt = 0
3569	while $cnt < $mca->mca_depth
3570		set $pc = $mca->mca_stack[$cnt]
3571		printf "%4d: ", $cnt + 1
3572		pcprint $pc
3573		printf "\n"
3574		set $cnt = $cnt + 1
3575	end
3576	if $mca->mca_pdepth > 0
3577		printf "previous transaction for this buffer (thread %p):\n", \
3578		    $mca->mca_pthread
3579	end
3580	set $cnt = 0
3581	while $cnt < $mca->mca_pdepth
3582		set $pc = $mca->mca_pstack[$cnt]
3583		printf "%4d: ", $cnt + 1
3584		pcprint $pc
3585		printf "\n"
3586		set $cnt = $cnt + 1
3587	end
3588	set language auto
3589end
3590
3591document mbuf_showmca
3592Syntax: (gdb) mbuf_showmca <addr>
3593| Given an mbuf/cluster buffer audit structure address, print the audit
3594| records including the stack trace of the last buffer transaction.
3595end
3596
3597set $MCF_NOCPUCACHE = 0x10
3598
3599define mcache_stat
3600	set $head = (mcache_t *)mcache_head
3601	set $mc = $head
3602	printf "cache                        cache      cache    buf   buf    backing             (# of retries)     bufs\n"
3603	printf "name                         state       addr   size align       zone     wait   nowait   failed  incache\n"
3604	printf "------------------------- -------- ---------- ------ ----- ---------- -------------------------- --------\n"
3605	while $mc != 0
3606		set $bktsize = $mc->mc_cpu.cc_bktsize
3607		printf "%-25s ", $mc->mc_name
3608		if ($mc->mc_flags & $MCF_NOCPUCACHE)
3609			printf "disabled"
3610		else
3611			if $mc->mc_purge_cnt > 0
3612				printf " purging"
3613			else
3614				if $bktsize == 0
3615					printf " offline"
3616				else
3617					printf "  online"
3618				end
3619			end
3620		end
3621		printf " 0x%08x %6d %5d ",$mc, \
3622		    $mc->mc_bufsize, $mc->mc_align
3623		if $mc->mc_slab_zone != 0
3624			printf "0x%08x", $mc->mc_slab_zone
3625		else
3626			printf "    custom"
3627		end
3628		set $tot = 0
3629		set $tot += $mc->mc_full.bl_total * $bktsize
3630		set $ccp = (mcache_cpu_t *)$mc->mc_cpu
3631		set $n = 0
3632		while $n < ncpu
3633			if $ccp->cc_objs > 0
3634				set $tot += $ccp->cc_objs
3635			end
3636			if $ccp->cc_pobjs > 0
3637				set $tot += $ccp->cc_pobjs
3638			end
3639			set $n += 1
3640			set $ccp += 1
3641		end
3642		printf " %8d %8d %8d %8d", $mc->mc_wretry_cnt, \
3643		    $mc->mc_nwretry_cnt, $mc->mc_nwfail_cnt, $tot
3644		printf "\n"
3645		set $mc = (mcache_t *)$mc->mc_list.le_next
3646	end
3647end
3648
3649document mcache_stat
3650Syntax: (gdb) mcache_stat
3651| Print all mcaches in the system.
3652end
3653
3654define mcache_showzone
3655	set $mc = (mcache_t *)$arg0
3656	if $mc->mc_slab_zone != 0
3657		printf "%p", $mc->mc_slab_zone
3658	else
3659		printf "   custom"
3660end
3661
3662document mcache_showzone
3663Syntax: (gdb) mcache_showzone <mcache_addr>
3664| Print the type of backend (custom or zone) of a mcache.
3665end
3666
3667define mcache_walkobj
3668	set $p = (mcache_obj_t *)$arg0
3669	set $cnt = 1
3670	set $tot = 0
3671	while $p
3672		printf "%4d: 0x%08x\n", $cnt, $p,
3673		set $p = $p->obj_next
3674		set $cnt = $cnt + 1
3675	end
3676end
3677
3678document mcache_walkobj
3679Syntax: (gdb) mcache_walkobj <addr>
3680| Given a mcache object address, walk its obj_next pointer
3681end
3682
3683define mcache_showcache
3684	set $cp = (mcache_t *)$arg0
3685	set $ccp = (mcache_cpu_t *)$cp->mc_cpu
3686	set $bktsize = $cp->mc_cpu.cc_bktsize
3687	set $cnt = 0
3688	set $tot = 0
3689	printf "Showing cache '%s':\n\n", $cp->mc_name
3690	printf " CPU  cc_objs cc_pobjs    total\n"
3691	printf "---- -------- -------- --------\n"
3692	while $cnt < ncpu
3693		set $objs = $ccp->cc_objs
3694		if $objs <= 0
3695			set $objs = 0
3696		end
3697		set $pobjs = $ccp->cc_pobjs
3698		if $pobjs <= 0
3699			set $pobjs = 0
3700		end
3701		set $tot_cpu = $objs + $pobjs
3702		set $tot += $tot_cpu
3703		printf "%4d %8d %8d %8d\n", $cnt, $objs, $pobjs, $tot_cpu
3704		set $ccp += 1
3705		set $cnt += 1
3706	end
3707	printf "                       ========\n"
3708	printf "                       %8d\n", $tot
3709	printf "\n"
3710	set $tot += $cp->mc_full.bl_total * $bktsize
3711	printf "Total # of full buckets (%d objs/bkt):\t%-8d\n", \
3712	    $bktsize, $cp->mc_full.bl_total
3713	printf "Total # of objects cached:\t\t%-8d\n", $tot
3714end
3715
3716document mcache_showcache
3717| Display the number of objects in the cache
3718end
3719
3720set $NSLABSPMB = sizeof(mcl_slabg_t)/sizeof(mcl_slab_t)
3721
3722define mbuf_slabstbl
3723	set $x = 0
3724
3725	printf "slot addr       slabs range\n"
3726	printf "---- ---------- -----------------------\n"
3727	while $x < maxslabgrp
3728		set $slg = slabstbl[$x]
3729		printf "%3d: ", $x
3730		if $slg == 0
3731			printf "-\n"
3732		else
3733			printf "%p [%p-%p]\n", $slg, &$slg->slg_slab[0], \
3734			    &$slg->slg_slab[$NSLABSPMB-1]
3735		end
3736		set $x += 1
3737	end
3738end
3739
3740document mbuf_slabstbl
3741| Display the mbuf slabs table
3742end
3743
3744set $SLF_MAPPED=0x0001
3745set $SLF_PARTIAL=0x0002
3746set $SLF_DETACHED=0x0004
3747
3748define mbuf_slabs
3749	set $slg = (mcl_slabg_t *)$arg0
3750	set $x = 0
3751
3752	printf "slot addr       next       base        C  R  N   size flags\n"
3753	printf "---- ---------- ---------- ---------- -- -- -- ------ -----\n"
3754	while $x < $NSLABSPMB
3755		set $sl = &$slg->slg_slab[$x]
3756		printf "%3d: 0x%08x 0x%08x 0x%08x %2d %2d %2d %6d 0x%04x ", \
3757		    $x + 1, $sl, $sl->sl_next, $sl->sl_base, $sl->sl_class, \
3758		    $sl->sl_refcnt, $sl->sl_chunks, $sl->sl_len, \
3759		    $sl->sl_flags
3760		if $sl->sl_flags != 0
3761			printf "<"
3762			if $sl->sl_flags & $SLF_MAPPED
3763				printf "mapped"
3764			end
3765			if $sl->sl_flags & $SLF_PARTIAL
3766				printf ",partial"
3767			end
3768			if $sl->sl_flags & $SLF_DETACHED
3769				printf ",detached"
3770			end
3771			printf ">"
3772		end
3773		printf "\n"
3774		set $x += 1
3775	end
3776end
3777
3778document mbuf_slabs
3779| Display all mbuf slabs in the group
3780end
3781
3782define mbuf_stat
3783	set $x = 0
3784
3785	printf "class               total   cached     uncached           inuse           failed   waiter notified    purge\n"
3786	printf "name                 objs     objs     objs / slabs        objs      alloc count    count    count    count\n"
3787	printf "---------------- -------- -------- ------------------- -------- ---------------- -------- -------- --------\n"
3788	while $x < (sizeof(mbuf_table) / sizeof(mbuf_table[0]))
3789		set $mbt = mbuf_table[$x]
3790		set $mcs = (mb_class_stat_t *)mbuf_table[$x].mtbl_stats
3791		set $tot = 0
3792		set $mc = $mbt->mtbl_cache
3793		set $bktsize = $mc->mc_cpu.cc_bktsize
3794		set $tot += $mc->mc_full.bl_total * $bktsize
3795		set $ccp = (mcache_cpu_t *)$mc->mc_cpu
3796		set $n = 0
3797		while $n < ncpu
3798			if $ccp->cc_objs > 0
3799				set $tot += $ccp->cc_objs
3800			end
3801			if $ccp->cc_pobjs > 0
3802				set $tot += $ccp->cc_pobjs
3803			end
3804			set $n += 1
3805			set $ccp += 1
3806		end
3807
3808		printf "%-16s %8d %8d %8d / %-8d %8d %16llu %8d %8llu %8llu", \
3809		    $mcs->mbcl_cname, $mcs->mbcl_total, $tot, \
3810		    $mcs->mbcl_infree, $mcs->mbcl_slab_cnt, \
3811		    ($mcs->mbcl_total - $tot - $mcs->mbcl_infree), \
3812		    $mcs->mbcl_fail_cnt, $mc->mc_waiter_cnt, \
3813		    $mcs->mbcl_notified, $mcs->mbcl_purge_cnt
3814		printf "\n"
3815		set $x += 1
3816	end
3817end
3818
3819document mbuf_stat
3820| Print extended mbuf allocator statistics.
3821end
3822
3823set $MB_INUSE = 0x1
3824set $MB_COMP_INUSE = 0x2
3825set $MB_SCVALID = 0x4
3826
3827set $MCLBYTES = 2048
3828set $MSIZE = 256
3829set $NBPG = 4096
3830set $M16KCLBYTES = 16384
3831
3832define mbuf_mca_ctype
3833	set $mca = (mcache_audit_t *)$arg0
3834	set $vopt = $arg1
3835	set $cp = $mca->mca_cache
3836	set $class = (unsigned int)$cp->mc_private
3837	set $csize = mbuf_table[$class].mtbl_stats->mbcl_size
3838	set $done = 0
3839	if $csize == $MSIZE
3840		if $vopt
3841			printf "M (mbuf) "
3842		else
3843			printf "M     "
3844		end
3845		set $done = 1
3846	end
3847	if !$done && $csize == $MCLBYTES
3848		if $vopt
3849			printf "CL (2K cluster) "
3850		else
3851			printf "CL    "
3852		end
3853		set $done = 1
3854	end
3855	if !$done && $csize == $NBPG
3856		if $vopt
3857			printf "BCL (4K cluster) "
3858		else
3859			printf "BCL   "
3860		end
3861		set $done = 1
3862	end
3863	if !$done && $csize == $M16KCLBYTES
3864		if $vopt
3865			printf "JCL (16K cluster) "
3866		else
3867			printf "JCL   "
3868		end
3869		set $done = 1
3870	end
3871	if !$done && $csize == ($MSIZE+$MCLBYTES)
3872		if $mca->mca_uflags & $MB_SCVALID
3873			if $mca->mca_uptr
3874				printf "M+CL  "
3875				if $vopt
3876					printf "(paired mbuf, 2K cluster)"
3877				end
3878			else
3879				printf "M-CL  "
3880				if $vopt
3881					printf "(unpaired mbuf, 2K cluster) "
3882				end
3883			end
3884		else
3885			if $mca->mca_uptr
3886				printf "CL+M  "
3887				if $vopt
3888					printf "(paired 2K cluster, mbuf) "
3889				end
3890			else
3891				printf "CL-M  "
3892				if $vopt
3893					printf "(paired 2K cluster, mbuf) "
3894				end
3895			end
3896		end
3897		set $done = 1
3898	end
3899	if !$done && $csize == ($MSIZE+$NBPG)
3900		if $mca->mca_uflags & $MB_SCVALID
3901			if $mca->mca_uptr
3902				printf "M+BCL "
3903				if $vopt
3904					printf "(paired mbuf, 4K cluster) "
3905				end
3906			else
3907				printf "M-BCL "
3908				if $vopt
3909					printf "(unpaired mbuf, 4K cluster) "
3910				end
3911			end
3912		else
3913			if $mca->mca_uptr
3914				printf "BCL+M "
3915				if $vopt
3916					printf "(paired 4K cluster, mbuf) "
3917				end
3918			else
3919				printf "BCL-M "
3920				if $vopt
3921					printf "(unpaired 4K cluster, mbuf) "
3922				end
3923			end
3924		end
3925		set $done = 1
3926	end
3927	if !$done && $csize == ($MSIZE+$M16KCLBYTES)
3928		if $mca->mca_uflags & $MB_SCVALID
3929			if $mca->mca_uptr
3930				printf "M+JCL "
3931				if $vopt
3932					printf "(paired mbuf, 16K cluster) "
3933				end
3934			else
3935				printf "M-JCL "
3936				if $vopt
3937					printf "(unpaired mbuf, 16K cluster) "
3938				end
3939			end
3940		else
3941			if $mca->mca_uptr
3942				printf "JCL+M "
3943				if $vopt
3944					printf "(paired 16K cluster, mbuf) "
3945				end
3946			else
3947				printf "JCL-M "
3948				if $vopt
3949					printf "(unpaired 16K cluster, mbuf) "
3950				end
3951			end
3952		end
3953		set $done = 1
3954	end
3955	if !$done
3956		printf "unknown: %s ", $cp->mc_name
3957	end
3958end
3959
3960document mbuf_mca_ctype
3961| This is a helper macro for mbuf_show{active,inactive,all} that prints
3962| out the mbuf object type represented by a given mcache audit structure.
3963end
3964
3965define mbuf_showactive
3966	mbuf_walkallslabs 1 0
3967end
3968
3969document mbuf_showactive
3970Syntax: (gdb) mbuf_showactive
3971| Walk the mbuf objects pool and print only the active ones; this
3972| requires mbuf debugging to be turned on, by setting the appropriate flags
3973| to the "mbuf_debug" boot-args parameter.  Active objects are those that
3974| are outstanding (have not returned to the mbuf slab layer) and in use
3975| by the client (have not been freed).
3976end
3977
3978define mbuf_showinactive
3979	mbuf_walkallslabs 0 1
3980end
3981
3982document mbuf_showinactive
3983Syntax: (gdb) mbuf_showinactive
3984| Walk the mbuf objects pool and print only the inactive ones; this
3985| requires mbuf debugging to be turned on, by setting the appropriate flags
3986| to the "mbuf_debug" boot-args parameter.  Inactive objects are those that
3987| are outstanding (have not returned to the mbuf slab layer) but have been
3988| freed by the client, i.e. they still reside in the mcache layer ready to
3989| be used for subsequent allocation requests.
3990end
3991
3992define mbuf_showall
3993	mbuf_walkallslabs 1 1
3994end
3995
3996document mbuf_showall
3997Syntax: (gdb) mbuf_showall
3998| Walk the mbuf objects pool and print them all; this requires
3999| mbuf debugging to be turned on, by setting the appropriate flags to the
4000| "mbuf_debug" boot-args parameter.
4001end
4002
4003define mbuf_mcaobjs
4004end
4005
4006define mbuf_walkallslabs
4007	set $show_a = $arg0
4008	set $show_f = $arg1
4009	set $x = 0
4010	set $total = 0
4011	set $total_a = 0
4012	set $total_f = 0
4013
4014	printf "("
4015	if $show_a && !$show_f
4016		printf "Searching only for active "
4017	end
4018	if !$show_a && $show_f
4019		printf "Searching only for inactive "
4020	end
4021	if $show_a && $show_f
4022		printf "Displaying all "
4023	end
4024	printf "objects; this may take a while ...)\n\n"
4025
4026	printf "                slab        mca        obj        allocation\n"
4027	printf "slot idx     address    address    address type        state\n"
4028	printf "---- ---- ---------- ---------- ---------- ----- -----------\n"
4029
4030	while $x < slabgrp
4031		set $slg = slabstbl[$x]
4032		set $y = 0
4033		set $stop = 0
4034		while $y < $NSLABSPMB && $stop == 0
4035			set $sl = &$slg->slg_slab[$y]
4036			set $base = (char *)$sl->sl_base
4037			set $ix = ($base - (char *)mbutl) >> 11
4038			set $clbase = ((union mcluster *)(mbutl + $ix))
4039			set $mclidx = ($base - (char *)$clbase) >> 8
4040			set $mca = mclaudit[$ix].cl_audit[$mclidx]
4041			set $first = 1
4042
4043			while $mca != 0 && $mca->mca_addr != 0
4044				set $printmca = 0
4045				if $mca->mca_uflags & ($MB_INUSE|$MB_COMP_INUSE)
4046					set $total_a = $total_a + 1
4047					set $printmca = $show_a
4048				else
4049					set $total_f = $total_f + 1
4050					set $printmca = $show_f
4051				end
4052
4053				if $printmca != 0
4054					if $first == 1
4055						printf "%4d %4d 0x%08x ", $x, $y, $sl
4056					else
4057						printf "                     "
4058					end
4059
4060					printf "0x%08x 0x%08x ", $mca, $mca->mca_addr
4061					mbuf_mca_ctype $mca 0
4062					if $mca->mca_uflags & ($MB_INUSE|$MB_COMP_INUSE)
4063						printf "active      "
4064					else
4065						printf "      freed "
4066					end
4067					if $first == 1
4068						set $first = 0
4069					end
4070					printf "\n"
4071					set $total = $total + 1
4072				end
4073				set $mca = $mca->mca_next
4074			end
4075			set $y += 1
4076			if $slg->slg_slab[$y].sl_base == 0
4077				set $stop = 1
4078			end
4079		end
4080		set $x += 1
4081	end
4082	if $total && $show_a && $show_f
4083		printf "\ntotal objects:\t%d\n", $total
4084		printf "active/unfreed:\t%d\n", $total_a
4085		printf "freed/in_cache:\t%d\n", $total_f
4086	end
4087end
4088
4089document mbuf_walkallslabs
4090| Walk the mbuf objects pool; this requires mbuf debugging to be
4091| turned on, by setting the appropriate flags to the "mbuf_debug" boot-args
4092| parameter.  This is a backend routine for mbuf_show{active,inactive,all}.
4093end
4094
4095define rtentry_trash
4096	set $rtd = (struct rtentry_dbg *)rttrash_head.tqh_first
4097	set $cnt = 0
4098	while $rtd != 0
4099		if $cnt == 0
4100			printf "      rtentry_dbg  ref flags\n"
4101			printf "      ------------ --- ----------\n"
4102		end
4103		printf "%4d: %p    %3d 0x%08x\n", $cnt + 1, $rtd, \
4104		    $rtd->rtd_refhold_cnt - $rtd->rtd_refrele_cnt, \
4105		    $rtd->rtd_entry.rt_flags
4106		set $rtd = $rtd->rtd_trash_link.tqe_next
4107		set $cnt = $cnt + 1
4108	end
4109end
4110
4111document rtentry_trash
4112Syntax: (gdb) rtentry_trash
4113| Walk the list of trash route entries; this requires route entry
4114| debugging to be turned on, by setting the appropriate flags to the
4115| "rte_debug" boot-args parameter.
4116end
4117
4118set $RTD_TRSTACK_SIZE = 8
4119set $RTD_REFHIST_SIZE = 4
4120
4121define rtentry_showdbg
4122	set $rtd = (struct rtentry_dbg *)$arg0
4123	set $cnt = 0
4124
4125	printf "Total holds: %d\n", $rtd->rtd_refhold_cnt
4126	printf "Next hold slot: %d\n", $rtd->rtd_refhold_next
4127	printf "Total releases: %d\n", $rtd->rtd_refrele_cnt
4128	printf "Next release slot: %d\n", $rtd->rtd_refrele_next
4129
4130	set $ix = 0
4131	while $ix < $RTD_TRSTACK_SIZE
4132		set $pc = $rtd->rtd_alloc_stk_pc[$ix]
4133		if $pc != 0
4134			if $ix == 0
4135				printf "\nAlloc (thread %p):\n", \
4136				    $rtd->rtd_alloc_thread
4137			end
4138			printf "%4d: ", $ix + 1
4139			pcprint $pc
4140			printf "\n"
4141		end
4142		set $ix = $ix + 1
4143	end
4144	set $ix = 0
4145	while $ix < $RTD_TRSTACK_SIZE
4146		set $pc = $rtd->rtd_free_stk_pc[$ix]
4147		if $pc != 0
4148			if $ix == 0
4149				printf "\nFree: (thread %p)\n", \
4150				    $rtd->rtd_free_thread
4151			end
4152			printf "%4d: ", $ix + 1
4153			pcprint $pc
4154			printf "\n"
4155		end
4156		set $ix = $ix + 1
4157	end
4158	while $cnt < $RTD_REFHIST_SIZE
4159		set $ix = 0
4160		while $ix < $RTD_TRSTACK_SIZE
4161			set $pc = $rtd->rtd_refhold[$cnt].pc[$ix]
4162			if $pc != 0
4163				if $ix == 0
4164					printf "\nHold [%d] (thread %p):\n", \
4165					    $cnt, $rtd->rtd_refhold[$cnt].th
4166				end
4167				printf "%4d: ", $ix + 1
4168				pcprint $pc
4169				printf "\n"
4170			end
4171			set $ix = $ix + 1
4172		end
4173		set $cnt = $cnt + 1
4174	end
4175	set $cnt = 0
4176	while $cnt < $RTD_REFHIST_SIZE
4177		set $ix = 0
4178		while $ix < $RTD_TRSTACK_SIZE
4179			set $pc = $rtd->rtd_refrele[$cnt].pc[$ix]
4180			if $pc != 0
4181				if $ix == 0
4182					printf "\nRelease [%d] (thread %p):\n",\
4183					    $cnt, $rtd->rtd_refrele[$cnt].th
4184				end
4185				printf "%4d: ", $ix + 1
4186				pcprint $pc
4187				printf "\n"
4188			end
4189			set $ix = $ix + 1
4190		end
4191		set $cnt = $cnt + 1
4192	end
4193end
4194
4195document rtentry_showdbg
4196Syntax: (gdb) rtentry_showdbg <addr>
4197| Given a route entry structure address, print the debug information
4198| related to it.  This requires route entry debugging to be turned
4199| on, by setting the appropriate flags to the "rte_debug" boot-args
4200| parameter.
4201end
4202
4203#
4204# print all OSMalloc stats 
4205
4206define ostag_print
4207set $kgm_tagp = (OSMallocTag)$arg0
4208printf "0x%08x: ", $kgm_tagp
4209printf "%8d ",$kgm_tagp->OSMT_refcnt
4210printf "%8x ",$kgm_tagp->OSMT_state
4211printf "%8x ",$kgm_tagp->OSMT_attr
4212printf "%s ",$kgm_tagp->OSMT_name
4213printf "\n"
4214end
4215
4216
4217define showosmalloc 
4218printf "TAG          COUNT     STATE     ATTR     NAME\n"
4219set $kgm_tagheadp = (OSMallocTag)&OSMalloc_tag_list
4220    set $kgm_tagptr = (OSMallocTag )($kgm_tagheadp->OSMT_link.next)
4221    while $kgm_tagptr != $kgm_tagheadp
4222	ostag_print $kgm_tagptr
4223	set $kgm_tagptr = (OSMallocTag)$kgm_tagptr->OSMT_link.next
4224    end
4225	printf "\n"
4226end
4227document showosmalloc
4228Syntax: (gdb) showosmalloc
4229| Print the outstanding allocation count by OSMallocTags.
4230end
4231
4232
4233define systemlog
4234    if msgbufp->msg_bufc[msgbufp->msg_bufx] == 0
4235        # The buffer hasn't wrapped, so take the easy (and fast!) path
4236        printf "%s", msgbufp->msg_bufc
4237    else
4238        set $kgm_msgbuf = *msgbufp
4239        set $kgm_syslog_bufsize = $kgm_msgbuf.msg_size
4240        set $kgm_syslog_bufend = $kgm_msgbuf.msg_bufx
4241        if $kgm_syslog_bufend >= $kgm_syslog_bufsize
4242            set $kgm_syslog_bufend = 0
4243        end
4244    
4245        # print older messages from msg_bufx to end of buffer
4246        set $kgm_i = $kgm_syslog_bufend
4247        while $kgm_i < $kgm_syslog_bufsize
4248            set $kgm_syslog_char = $kgm_msgbuf.msg_bufc[$kgm_i]
4249            if $kgm_syslog_char == 0
4250                # break out of loop
4251                set $kgm_i = $kgm_syslog_bufsize
4252            else
4253                printf "%c", $kgm_syslog_char
4254            end
4255            set $kgm_i = $kgm_i + 1
4256        end
4257        
4258        # print newer messages from start of buffer to msg_bufx
4259        set $kgm_i = 0
4260        while $kgm_i < $kgm_syslog_bufend
4261            set $kgm_syslog_char = $kgm_msgbuf.msg_bufc[$kgm_i]
4262            printf "%c", $kgm_syslog_char
4263            set $kgm_i = $kgm_i + 1
4264        end
4265    end
4266    printf "\n"
4267end
4268document systemlog
4269| Syntax: systemlog
4270| Display the kernel's printf ring buffer
4271end
4272
4273define printvnodepathint_recur
4274	if $arg0 != 0
4275		if ($arg0->v_flag & 0x000001) && ($arg0->v_mount != 0)
4276			if $arg0->v_mount->mnt_vnodecovered != 0
4277				printvnodepathint_recur  $arg0->v_mount->mnt_vnodecovered $arg0->v_mount->mnt_vnodecovered->v_name
4278			end
4279		else
4280			printvnodepathint_recur $arg0->v_parent $arg0->v_parent->v_name
4281			printf "/%s", $arg1
4282		end
4283	end
4284end
4285
4286#
4287# Show the locks held on a vnode by range, type, and holder.
4288#
4289define showvnodelocks
4290    if ($argc == 1)
4291    	_showvnodelockheader
4292	_showvnodelocks $arg0
4293    else
4294    	printf "| Usage:\n|\n"
4295	help showvnodelocks
4296    end
4297end
4298document showvnodelocks
4299| Given a vnodet pointer, display the list of advisory record locks for the
4300| referenced pvnode.
4301| The following is the syntax:
4302|     (gdb) showvnodelocks <vnode_t>
4303end
4304
4305define _showvnodelockheader
4306    printf "*  type   W  held by        lock type  start               end\n"
4307    printf "-  -----  -  -------------  ---------  ------------------  ------------------\n"
4308end
4309
4310#
4311# Macro to display a single lock; used to display both held locks and
4312# blocked locks
4313#
4314define _showvnodelock
4315    set $kgm_svl_lock = ((struct lockf *)$arg0)
4316
4317    # decode flags
4318    set $kgm_svl_flags = $kgm_svl_lock->lf_flags
4319    set $kgm_svl_type = $kgm_svl_lock->lf_type
4320    if ($kgm_svl_flags & 0x20)
4321	printf "flock"
4322    end
4323    if ($kgm_svl_flags & 0x40)
4324	printf "posix"
4325    end
4326    if ($kgm_svl_flags & 0x80)
4327	printf "prov "
4328    end
4329    if ($kgm_svl_flags & 0x10)
4330	printf "  W  "
4331    else
4332	printf "  .  "
4333    end
4334
4335    # POSIX file vs. advisory range locks
4336    if ($kgm_svl_flags & 0x40)
4337	set $kgm_svl_proc = (proc_t)$kgm_svl_lock->lf_id
4338	printf "PID %8d   ", $kgm_svl_proc->p_pid
4339    else
4340	printf "ID 0x%08x  ", $kgm_svl_lock->lf_id
4341    end
4342
4343    # lock type
4344    if ($kgm_svl_type == 1)
4345		printf "shared     "
4346    else
4347	if ($kgm_svl_type == 3)
4348		printf "exclusive  "
4349	else
4350	    if ($kgm_svl_type == 2)
4351		printf "unlock     "
4352	    else
4353		printf "unknown    "
4354	    end
4355	end
4356    end
4357
4358    # start and stop
4359    printf "0x%016x..", $kgm_svl_lock->lf_start
4360    printf "0x%016x  ", $kgm_svl_lock->lf_end
4361    printf "\n"
4362end
4363
4364# Body of showvnodelocks, not including header
4365define _showvnodelocks
4366    set $kgm_svl_vnode = ((vnode_t)$arg0)
4367    set $kgm_svl_lockiter = $kgm_svl_vnode->v_lockf
4368    while ($kgm_svl_lockiter != 0)
4369	# locks that are held
4370    	printf "H  "
4371    	_showvnodelock $kgm_svl_lockiter
4372
4373	# and any locks blocked by them
4374	set $kgm_svl_blocker = $kgm_svl_lockiter->lf_blkhd.tqh_first
4375	while ($kgm_svl_blocker != 0)
4376	    printf ">  "
4377	    _showvnodelock $kgm_svl_blocker
4378	    set $kgm_svl_blocker = $kgm_svl_blocker->lf_block.tqe_next
4379	end
4380
4381	# and on to the next one...
4382    	set $kgm_svl_lockiter = $kgm_svl_lockiter->lf_next
4383    end
4384end
4385
4386define showvnodepath
4387	set $vp = (struct vnode *)$arg0
4388	if $vp != 0
4389		if ($vp->v_flag & 0x000001) && ($vp->v_mount != 0) && ($vp->v_mount->mnt_flag & 0x00004000)
4390			printf "/"
4391		else
4392			printvnodepathint_recur $vp $vp->v_name
4393		end
4394	end
4395	printf "\n"
4396end
4397
4398document showvnodepath
4399Syntax: (gdb) showvnodepath <vnode>
4400| Prints the path for a vnode
4401end
4402
4403define printcolonhex
4404    if ($argc == 2) 
4405	set $addr = $arg0
4406	set $count = $arg1
4407	set $li = 0
4408	while ($li < $count)
4409	    if ($li == 0)
4410		printf "%02x", (u_char)$addr[$li]
4411	    end
4412	    if ($li != 0)
4413		printf ":%02x", (u_char)$addr[$li]
4414	    end
4415	    set $li = $li + 1
4416	end
4417    end
4418end
4419
4420define showsockaddr_dl
4421    set $sdl = (struct sockaddr_dl *)$arg0
4422    printf "LINK "
4423    if ($sdl == 0)
4424	printf "(null)"
4425    else
4426	set $addr = $sdl->sdl_data + $sdl->sdl_nlen
4427	set $count = $sdl->sdl_alen
4428	printcolonhex $addr $count
4429    end
4430end
4431
4432define showsockaddr_unspec
4433    set $sockaddr = (struct sockaddr *)$arg0
4434    set $addr = $sockaddr->sa_data
4435    set $count = $sockaddr->sa_len - 2
4436    printf "UNSP "
4437    printcolonhex $addr $count
4438end
4439
4440define showsockaddr_at
4441    set $sockaddr = (struct sockaddr *)$arg0
4442    set $addr = $sockaddr->sa_data
4443    set $count = $sockaddr->sa_len - 2
4444    printf "ATLK "
4445    printcolonhex $addr $count
4446end
4447
4448define showsockaddr_in
4449    set $sin = (struct sockaddr_in *)$arg0
4450    set $sa_bytes = (unsigned char *)&($sin->sin_addr)
4451    printf "IPV4 %d.%d.%d.%d", $sa_bytes[0], $sa_bytes[1], $sa_bytes[2], $sa_bytes[3]
4452end
4453
4454define showsockaddr_in6
4455    set $sin6 = (struct sockaddr_in6 *)$arg0
4456    set $sa_bytes = $sin6->sin6_addr.__u6_addr.__u6_addr8
4457    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]
4458end
4459
4460define showifmultiaddrs
4461   set $ifp = (struct ifnet *)$arg0
4462   set $if_multi = (struct ifmultiaddr *)$ifp->if_multiaddrs->lh_first
4463   set $mymulti = $if_multi
4464   set $myi = 0
4465   while ($mymulti != 0)
4466	printf "%2d. ", $myi
4467	set $sa_family = $mymulti->ifma_addr.sa_family
4468	if ($sa_family == 2)
4469	    if ($mymulti->ifma_ll != 0)
4470	    	showsockaddr_dl $mymulti->ifma_ll->ifma_addr
4471	        printf " "
4472	    end
4473	    showsockaddr_in $mymulti->ifma_addr
4474	end
4475	if ($sa_family == 30)
4476	    if ($mymulti->ifma_ll != 0)
4477	    	showsockaddr_dl $mymulti->ifma_ll->ifma_addr
4478	        printf " "
4479	    end
4480	    showsockaddr_in6 $mymulti->ifma_addr
4481	end
4482 	if ($sa_family == 18)
4483	    showsockaddr_dl $mymulti->ifma_addr
4484	end
4485	if ($sa_family == 0)
4486	    showsockaddr_unspec $mymulti->ifma_addr 6
4487	end
4488	printf " [%d]", $mymulti->ifma_refcount
4489	printf "\n"
4490	set $mymulti = $mymulti->ifma_link.le_next
4491	set $myi = $myi + 1
4492   end
4493end
4494
4495document showifmultiaddrs
4496Syntax showifmultiaddrs <ifp>
4497| show the (struct ifnet).if_multiaddrs list of multicast addresses for the given ifp
4498end
4499
4500define showsockaddr
4501    set $mysock = (struct sockaddr *)$arg0
4502    set $showsockaddr_handled = 0
4503    if ($mysock == 0)
4504	printf "(null)"
4505    else
4506	if ($mysock->sa_family == 0)
4507	    showsockaddr_unspec $mysock
4508	    set $showsockaddr_handled = 1
4509	end
4510	if ($mysock->sa_family == 2)
4511	    showsockaddr_in $mysock
4512	    set $showsockaddr_handled = 1
4513	end
4514	if ($mysock->sa_family == 30)
4515	    showsockaddr_in6 $mysock
4516	    set $showsockaddr_handled = 1
4517	end
4518	if ($mysock->sa_family == 18)
4519	    showsockaddr_dl $mysock
4520	    set $showsockaddr_handled = 1
4521	end
4522	if ($mysock->sa_family == 16)
4523	    showsockaddr_at $mysock
4524	    set $showsockaddr_handled = 1
4525	end
4526	if ($showsockaddr_handled == 0)
4527	    printf "%d ", $mysock->sa_family
4528	    set $addr = $mysock->sa_data
4529	    set $count = $mysock->sa_len
4530	    printcolonhex $addr $count
4531	end
4532    end
4533end
4534
4535define showifflags
4536	set $flags = (u_short)$arg0
4537	set $first = 1
4538	printf "<"
4539	if ($flags & 0x1)
4540	    printf "UP"
4541	    set $first = 0
4542	end
4543	if ($flags & 0x2)
4544	    if ($first == 1)
4545		set $first = 0
4546	    else
4547	    	printf ","
4548	    end
4549	    printf "BROADCAST"
4550	end
4551	if ($flags & 0x4)
4552	    printf "DEBUG"
4553	end
4554	if ($flags & 0x8)
4555	    if ($first == 1)
4556		set $first = 0
4557	    else
4558	    	printf ","
4559	    end
4560	    printf "LOOPBACK"
4561	end
4562	if ($flags & 0x10)
4563	    if ($first == 1)
4564		set $first = 0
4565	    else
4566	    	printf ","
4567	    end
4568	    printf "POINTTOPOINT"
4569	end
4570#	if ($flags & 0x20)
4571#	    if ($first == 1)
4572#		set $first = 0
4573#	    else
4574#	    	printf ","
4575#	    end
4576#	    printf "NOTRAILERS"
4577#	end
4578	if ($flags & 0x40)
4579	    if ($first == 1)
4580		set $first = 0
4581	    else
4582	    	printf ","
4583	    end
4584	    printf "RUNNING"
4585	end
4586	if ($flags & 0x80)
4587	    if ($first == 1)
4588		set $first = 0
4589	    else
4590	    	printf ","
4591	    end
4592	    printf "NOARP"
4593	end
4594	if ($flags & 0x100)
4595	    if ($first == 1)
4596		set $first = 0
4597	    else
4598	    	printf ","
4599	    end
4600	    printf "PROMISC"
4601	end
4602	if ($flags & 0x200)
4603	    if ($first == 1)
4604		set $first = 0
4605	    else
4606	    	printf ","
4607	    end
4608	    printf "ALLMULTI"
4609	end
4610	if ($flags & 0x400)
4611	    if ($first == 1)
4612		set $first = 0
4613	    else
4614	    	printf ","
4615	    end
4616	    printf "OACTIVE"
4617	end
4618	if ($flags & 0x800)
4619	    if ($first == 1)
4620		set $first = 0
4621	    else
4622	    	printf ","
4623	    end
4624	    printf "SIMPLEX"
4625	end
4626	if ($flags & 0x1000)
4627	    if ($first == 1)
4628		set $first = 0
4629	    else
4630	    	printf ","
4631	    end
4632	    printf "LINK0"
4633	end
4634	if ($flags & 0x2000)
4635	    if ($first == 1)
4636		set $first = 0
4637	    else
4638	    	printf ","
4639	    end
4640	    printf "LINK1"
4641	end
4642	if ($flags & 0x4000)
4643	    if ($first == 1)
4644		set $first = 0
4645	    else
4646	    	printf ","
4647	    end
4648	    printf "LINK2-ALTPHYS"
4649	end
4650	if ($flags & 0x8000)
4651	    if ($first == 1)
4652		set $first = 0
4653	    else
4654	    	printf ","
4655	    end
4656	    printf "MULTICAST"
4657	end
4658	printf ">"
4659end
4660
4661define showifaddrs
4662   set $ifp = (struct ifnet *)$arg0
4663   set $myifaddr = (struct ifaddr *)$ifp->if_addrhead->tqh_first
4664   set $myi = 0
4665   while ($myifaddr != 0)
4666	printf "\t%d. ", $myi
4667	showsockaddr $myifaddr->ifa_addr
4668	printf " [%d]\n", $myifaddr->ifa_refcnt
4669	set $myifaddr = $myifaddr->ifa_link->tqe_next
4670	set $myi = $myi + 1
4671   end
4672end
4673
4674document showifaddrs
4675Syntax: showifaddrs <ifp>
4676| show the (struct ifnet).if_addrhead list of addresses for the given ifp
4677end
4678
4679define ifconfig
4680   set $ifconfig_all = 0
4681   if ($argc == 1)
4682	set $ifconfig_all = 1
4683   end
4684   set $ifp = (struct ifnet *)(ifnet->tqh_first)
4685   while ($ifp != 0)
4686	printf "%s%d: flags=%x", $ifp->if_name, $ifp->if_unit, (u_short)$ifp->if_flags
4687	showifflags $ifp->if_flags
4688	printf " mtu %d\n", $ifp->if_data.ifi_mtu
4689	printf "\t(struct ifnet *)0x%x\n", $ifp
4690	if ($ifconfig_all == 1) 
4691	   showifaddrs $ifp
4692        end
4693	set $ifp = $ifp->if_link->tqe_next
4694   end
4695end
4696document ifconfig
4697Syntax: (gdb) ifconfig
4698| display ifconfig-like output, and print the (struct ifnet *) pointers for further inspection
4699end
4700
4701define showbpfdtab
4702    set $myi = 0
4703    while ($myi < bpf_dtab_size)
4704	if (bpf_dtab[$myi] != 0)
4705		printf "Address 0x%x, bd_next 0x%x\n", bpf_dtab[$myi], bpf_dtab[$myi]->bd_next
4706		print *bpf_dtab[$myi]
4707	end
4708	set $myi = $myi + 1
4709    end
4710end
4711
4712define showallvols
4713	printf "volume      mnt_data    mnt_devvp   typename    mountpoint\n"
4714	set $kgm_vol = (mount_t) mountlist.tqh_first
4715	while $kgm_vol
4716		printf "0x%08x  ", $kgm_vol
4717		printf "0x%08x  ", $kgm_vol->mnt_data
4718		printf "0x%08x  ", $kgm_vol->mnt_devvp
4719		if  ($kgm_vol->mnt_vtable->vfc_name[0] == 'h') && \
4720		    ($kgm_vol->mnt_vtable->vfc_name[1] == 'f') && \
4721		    ($kgm_vol->mnt_vtable->vfc_name[2] == 's') && \
4722		    ($kgm_vol->mnt_vtable->vfc_name[3] == '\0')
4723			set $kgm_hfsmount = \
4724			    (struct hfsmount *) $kgm_vol->mnt_data
4725			if $kgm_hfsmount->hfs_freezing_proc != 0
4726				printf "FROZEN hfs  "
4727			else
4728				printf "hfs         "
4729			end
4730		else
4731			printf "%-10s  ", $kgm_vol->mnt_vtable->vfc_name
4732		end
4733		printf "%s\n", $kgm_vol->mnt_vfsstat.f_mntonname
4734		
4735		set $kgm_vol = (mount_t) $kgm_vol->mnt_list.tqe_next
4736	end
4737end
4738
4739document showallvols
4740Syntax: (gdb) showallvols
4741| Display a summary of mounted volumes
4742end
4743
4744define showvnodeheader
4745	printf "vnode       usecount  iocount  v_data      vtype  parent      name\n"
4746end
4747
4748define showvnodeint
4749	set $kgm_vnode = (vnode_t) $arg0
4750	printf "0x%08x  ", $kgm_vnode
4751	printf "%8d  ", $kgm_vnode->v_usecount
4752	printf "%7d  ", $kgm_vnode->v_iocount
4753# print information about clean/dirty blocks?
4754	printf "0x%08x  ", $kgm_vnode->v_data
4755
4756	# print the vtype, using the enum tag
4757	set $kgm_vtype = $kgm_vnode->v_type
4758	if $kgm_vtype == VNON
4759		printf "VNON   "
4760	end
4761	if $kgm_vtype == VREG
4762		printf "VREG   "
4763	end
4764	if $kgm_vtype == VDIR
4765		printf "VDIR   "
4766	end
4767	if $kgm_vtype == VBLK
4768		printf "VBLK   "
4769	end
4770	if $kgm_vtype == VCHR
4771		printf "VCHR   "
4772	end
4773	if $kgm_vtype == VLNK
4774		printf "VLNK   "
4775	end
4776	if $kgm_vtype == VSOCK
4777		printf "VSOCK  "
4778	end
4779	if $kgm_vtype == VFIFO
4780		printf "VFIFO  "
4781	end
4782	if $kgm_vtype == VBAD
4783		printf "VBAD   "
4784	end
4785	if ($kgm_vtype < VNON) || ($kgm_vtype > VBAD)
4786		printf "%5d  ", $kgm_vtype
4787	end
4788
4789	printf "0x%08x  ", $kgm_vnode->v_parent
4790	if $kgm_vnode->v_name != 0
4791		printf "%s\n", $kgm_vnode->v_name
4792	else
4793		printf "\n"
4794	end
4795end
4796
4797define showvnode
4798	showvnodeheader
4799	showvnodeint $arg0
4800end
4801
4802document showvnode
4803Syntax: (gdb) showvnode <vnode>
4804| Display info about one vnode
4805end
4806
4807define showvolvnodes
4808	showvnodeheader
4809	set $kgm_vol = (mount_t) $arg0
4810	set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first
4811	while $kgm_vnode
4812		showvnodeint $kgm_vnode
4813		set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next
4814	end
4815end
4816
4817document showvolvnodes
4818Syntax: (gdb) showvolvnodes <mouont_t>
4819| Display info about all vnodes of a given mount_t
4820end
4821
4822define showvolbusyvnodes
4823	showvnodeheader
4824	set $kgm_vol = (mount_t) $arg0
4825	set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first
4826	while $kgm_vnode
4827		if $kgm_vnode->v_iocount != 0
4828			showvnodeint $kgm_vnode
4829		end
4830		set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next
4831	end
4832end
4833
4834document showvolbusyvnodes
4835Syntax: (gdb) showvolbusyvnodes <mount_t>
4836| Display info about busy (iocount!=0) vnodes of a given mount_t
4837end
4838
4839define showallbusyvnodes
4840	showvnodeheader
4841	set $kgm_vol = (mount_t) mountlist.tqh_first
4842	while $kgm_vol
4843		set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first
4844		while $kgm_vnode
4845			if $kgm_vnode->v_iocount != 0
4846				showvnodeint $kgm_vnode
4847			end
4848			set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next
4849		end
4850		set $kgm_vol = (mount_t) $kgm_vol->mnt_list.tqe_next
4851	end
4852end
4853
4854document showallbusyvnodes
4855Syntax: (gdb) showallbusyvnodes <vnode>
4856| Display info about all busy (iocount!=0) vnodes
4857end
4858
4859define showallvnodes
4860	showvnodeheader
4861	set $kgm_vol = (mount_t) mountlist.tqh_first
4862	while $kgm_vol
4863		set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first
4864		while $kgm_vnode
4865			showvnodeint $kgm_vnode
4866			set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next
4867		end
4868		set $kgm_vol = (mount_t) $kgm_vol->mnt_list.tqe_next
4869	end
4870end
4871
4872document showallvnodes
4873Syntax: (gdb) showallvnodes
4874| Display info about all vnodes
4875end
4876
4877define _showvnodelockheader
4878    printf "*  type   W  held by        lock type  start               end\n"
4879    printf "-  -----  -  -------------  ---------  ------------------  ------------------\n"
4880end
4881
4882define _showvnodelock
4883    set $kgm_svl_lock = ((struct lockf *)$arg0)
4884
4885    # decode flags
4886    set $kgm_svl_flags = $kgm_svl_lock->lf_flags
4887    set $kgm_svl_type = $kgm_svl_lock->lf_type
4888    if ($kgm_svl_flags & 0x20)
4889	printf "flock"
4890    end
4891    if ($kgm_svl_flags & 0x40)
4892	printf "posix"
4893    end
4894    if ($kgm_svl_flags & 0x80)
4895	printf "prov "
4896    end
4897    if ($kgm_svl_flags & 0x10)
4898	printf "  W  "
4899    else
4900	printf "  .  "
4901    end
4902
4903    # POSIX file vs. advisory range locks
4904    if ($kgm_svl_flags & 0x40)
4905	set $kgm_svl_proc = (proc_t)$kgm_svl_lock->lf_id
4906	printf "PID %8d   ", $kgm_svl_proc->p_pid
4907    else
4908	printf "ID 0x%08x  ", $kgm_svl_lock->lf_id
4909    end
4910
4911    # lock type
4912    if ($kgm_svl_type == 1)
4913		printf "shared     "
4914    else
4915	if ($kgm_svl_type == 3)
4916		printf "exclusive  "
4917	else
4918	    if ($kgm_svl_type == 2)
4919		printf "unlock     "
4920	    else
4921		printf "unknown    "
4922	    end
4923	end
4924    end
4925
4926    # start and stop
4927    printf "0x%016x..", $kgm_svl_lock->lf_start
4928    printf "0x%016x  ", $kgm_svl_lock->lf_end
4929    printf "\n"
4930end
4931# Body of showvnodelocks, not including header
4932define _showvnodelocks
4933    set $kgm_svl_vnode = ((vnode_t)$arg0)
4934    set $kgm_svl_lockiter = $kgm_svl_vnode->v_lockf
4935    while ($kgm_svl_lockiter != 0)
4936	# locks that are held
4937    	printf "H  "
4938    	_showvnodelock $kgm_svl_lockiter
4939
4940	# and any locks blocked by them
4941	set $kgm_svl_blocker = $kgm_svl_lockiter->lf_blkhd.tqh_first
4942	while ($kgm_svl_blocker != 0)
4943	    printf ">  "
4944	    _showvnodelock $kgm_svl_blocker
4945	    set $kgm_svl_blocker = $kgm_svl_blocker->lf_block.tqe_next
4946	end
4947
4948	# and on to the next one...
4949    	set $kgm_svl_lockiter = $kgm_svl_lockiter->lf_next
4950    end
4951end
4952
4953
4954define showvnodelocks
4955    if ($argc == 1)
4956    	_showvnodelockheader
4957	_showvnodelocks $arg0
4958    else
4959    	printf "| Usage:\n|\n"
4960	help showvnodelocks
4961    end
4962end
4963
4964document showvnodelocks
4965Syntax: (gdb) showvnodelocks <vnode_t>
4966| Given a vnodet pointer, display the list of advisory record locks for the
4967| referenced pvnodes
4968end
4969
4970define showbootargs
4971	printf "%s\n", (char*)((boot_args*)PE_state.bootArgs).CommandLine
4972end
4973
4974document showbootargs
4975Syntax: showbootargs
4976| Display boot arguments passed to the target kernel
4977end
4978
4979define showbootermemorymap
4980       set $kgm_boot_args = kernelBootArgs
4981       set $kgm_msize = kernelBootArgs->MemoryMapDescriptorSize
4982       set $kgm_mcount = kernelBootArgs->MemoryMapSize / $kgm_msize
4983       set $kgm_i = 0
4984       
4985       printf "Type       Physical Start   Number of Pages\n"
4986       while $kgm_i < $kgm_mcount
4987	     set $kgm_mptr = (EfiMemoryRange *)((unsigned long)kernelBootArgs->MemoryMap + $kgm_i * $kgm_msize)
4988#	     p/x *$kgm_mptr
4989	     if $kgm_mptr->Type == 0
4990	       printf "reserved  "
4991	     end
4992	     if $kgm_mptr->Type == 1
4993	       printf "LoaderCode"
4994	     end
4995	     if $kgm_mptr->Type == 2
4996	       printf "LoaderData"
4997	     end
4998	     if $kgm_mptr->Type == 3
4999	       printf "BS_code   "
5000	     end
5001	     if $kgm_mptr->Type == 4
5002	       printf "BS_data   "
5003	     end
5004	     if $kgm_mptr->Type == 5
5005	       printf "RT_code   "
5006	     end
5007	     if $kgm_mptr->Type == 6
5008	       printf "RT_data   "
5009	     end
5010	     if $kgm_mptr->Type == 7
5011	       printf "available "
5012	     end
5013	     if $kgm_mptr->Type == 8
5014    	       printf "Unusable  "
5015	     end
5016	     if $kgm_mptr->Type == 9
5017               printf "ACPI_recl "
5018	     end
5019	     if $kgm_mptr->Type == 10
5020               printf "ACPI_NVS  "
5021	     end
5022	     if $kgm_mptr->Type == 11
5023               printf "MemMapIO  "
5024	     end
5025	     if $kgm_mptr->Type == 12
5026               printf "MemPortIO "
5027	     end
5028	     if $kgm_mptr->Type == 13
5029               printf "PAL_code  "
5030	     end
5031	     if $kgm_mptr->Type > 13
5032               printf "UNKNOWN   "
5033	     end
5034
5035       	     printf " %016llx %016llx\n", $kgm_mptr->PhysicalStart, $kgm_mptr->NumberOfPages
5036	     set $kgm_i = $kgm_i + 1
5037       end
5038end
5039
5040document showbootermemorymap
5041Syntax: (gdb) showbootermemorymap
5042| Prints out the phys memory map from kernelBootArgs
5043end
5044
5045
5046define showstacksaftertask
5047    set $kgm_head_taskp = &default_pset.tasks
5048    set $kgm_taskp = (struct task *)$arg0
5049    while $kgm_taskp != $kgm_head_taskp
5050        showtaskheader
5051        showtaskint $kgm_taskp
5052        set $kgm_head_actp = &($kgm_taskp->threads)
5053        set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) 
5054        while $kgm_actp != $kgm_head_actp
5055            showactheader
5056            if ($decode_wait_events > 0)
5057               showactint $kgm_actp 1
5058            else
5059               showactint $kgm_actp 2
5060            end
5061            set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
5062        end
5063        printf "\n"
5064        set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next)
5065    end
5066end
5067document showstacksaftertask
5068Syntax: (gdb) showstacksaftertask <task>
5069| Routine to print out all stacks (as in showallstacks) starting after a given task
5070| Useful if that gdb refuses to print a certain task's stack.
5071end
5072
5073define showpmworkqueueint
5074    set $kgm_pm_wq = (IOPMWorkQueue *)$arg0
5075    set $kgm_pm_node = (IOService *)$kgm_pm_wq->owner
5076    printf "0x%08x  0x%08x  ", $kgm_pm_wq, $kgm_pm_node
5077    printf "%02d ", $kgm_pm_node->pwrMgt->CurrentPowerState
5078    printf "%02d ", $kgm_pm_node->pwrMgt->MachineState
5079    printf "%02d  ", $kgm_pm_node->pwrMgt->WaitReason
5080    printf "%s\n", $kgm_pm_node->pwrMgt->Name
5081    set $kgm_pm_queue = &($kgm_pm_wq->fWorkQueue)
5082    set $kgm_pm_req = (IOPMRequest *) $kgm_pm_queue->next
5083    while ( (queue_entry_t) $kgm_pm_req != (queue_entry_t) $kgm_pm_queue)
5084        printf "   Request  0x%08x [%02x]  Args ", $kgm_pm_req, $kgm_pm_req->fType
5085        printf "0x%08x ", $kgm_pm_req->fArg0
5086        printf "0x%08x ", $kgm_pm_req->fArg1
5087        printf "0x%08x\n", $kgm_pm_req->fArg2
5088        set $kgm_pm_req = (IOPMRequest *)$kgm_pm_req->fCommandChain.next
5089    end
5090end
5091
5092define showallpmworkqueues
5093    set $kgm_pm_next = gIOPMWorkLoop->eventChain
5094    printf "WorkQueue   Owner       PS MS WT  Name\n"
5095    printf "--------------------------------------\n"
5096    while ( $kgm_pm_next )
5097        set $kgm_vt = *((void **) $kgm_pm_next)
5098        if ($kgm_vt == _ZTV13IOPMWorkQueue)
5099            showpmworkqueueint $kgm_pm_next
5100        end
5101        set $kgm_pm_next = $kgm_pm_next->eventChainNext
5102    end
5103end
5104
5105document showallpmworkqueues
5106Syntax: (gdb) showallpmworkqueues
5107| Display info about all IOPMWorkQueue objects
5108end
5109
5110define showioservicepm
5111	set $kgm_iopmpriv = (IOServicePM *)$arg0
5112	printf "{ this object = %08x", $kgm_iopmpriv->Owner
5113	if ( $kgm_iopmpriv->WeAreRoot )
5114		printf " (root)"
5115	end
5116	printf ", "
5117	
5118	printf "MachineState = %d (", $kgm_iopmpriv->MachineState
5119	if ( $kgm_iopmpriv->MachineState == 1 )
5120		printf "kIOPM_OurChangeTellClientsPowerDown"
5121	else
5122		if ( $kgm_iopmpriv->MachineState == 2 )
5123			printf "kIOPM_OurChangeTellPriorityClientsPowerDown"
5124		else
5125			if ( $kgm_iopmpriv->MachineState == 3 )
5126				printf "kIOPM_OurChangeNotifyInterestedDriversWillChange"
5127			else
5128				if ( $kgm_iopmpriv->MachineState == 4 )
5129					printf "kIOPM_OurChangeSetPowerState"
5130				else
5131					if ( $kgm_iopmpriv->MachineState == 5 )
5132						printf "kIOPM_OurChangeWaitForPowerSettle"
5133					else
5134						if ( $kgm_iopmpriv->MachineState == 6 )
5135							printf "kIOPM_OurChangeNotifyInterestedDriversDidChange"
5136						else
5137							if ( $kgm_iopmpriv->MachineState == 7 )
5138								printf "kIOPM_OurChangeFinish"
5139							else
5140								if ( $kgm_iopmpriv->MachineState == 8 )
5141									printf "kIOPM_ParentDownTellPriorityClientsPowerDown"
5142								else
5143									if ( $kgm_iopmpriv->MachineState == 9 )
5144										printf "kIOPM_ParentDownNotifyInterestedDriversWillChange"
5145									else
5146										if ( $kgm_iopmpriv->MachineState == 10 )
5147											printf "Unused_MachineState_10"
5148										else
5149											if ( $kgm_iopmpriv->MachineState == 11 )
5150												printf "kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange"
5151											else
5152												if ( $kgm_iopmpriv->MachineState == 12 )
5153													printf "kIOPM_ParentDownSetPowerState"
5154												else
5155													if ( $kgm_iopmpriv->MachineState == 13 )
5156														printf "kIOPM_ParentDownWaitForPowerSettle"
5157													else
5158														if ( $kgm_iopmpriv->MachineState == 14 )
5159															printf "kIOPM_ParentDownAcknowledgeChange"
5160														else
5161															if ( $kgm_iopmpriv->MachineState == 15)
5162																printf "kIOPM_ParentUpSetPowerState"
5163															else
5164																if ( $kgm_iopmpriv->MachineState == 16)
5165																	printf "Unused_MachineState_16"
5166																else
5167																	if ( $kgm_iopmpriv->MachineState == 17)
5168																		printf "kIOPM_ParentUpWaitForSettleTime"
5169																	else
5170																		if ( $kgm_iopmpriv->MachineState == 18)
5171																			printf "kIOPM_ParentUpNotifyInterestedDriversDidChange"
5172																		else
5173																			if ( $kgm_iopmpriv->MachineState == 19)
5174																				printf "kIOPM_ParentUpAcknowledgePowerChange"
5175																			else
5176																				if ( $kgm_iopmpriv->MachineState == 20)
5177																					printf "kIOPM_Finished"
5178                                                                                else
5179                                                                                    if ( $kgm_iopmpriv->MachineState == 21)
5180                                                                                        printf "kIOPM_DriverThreadCallDone"
5181                                                                                    else
5182                                                                                        if ( $kgm_iopmpriv->MachineState == 22)
5183                                                                                            printf "kIOPM_NotifyChildrenDone"
5184                                                                                        end
5185                                                                                    end
5186																				end
5187																			end
5188																		end
5189																	end
5190																end
5191															end
5192														end
5193													end
5194												end
5195											end
5196										end
5197									end
5198								end
5199							end
5200						end
5201					end
5202				end
5203			end
5204		end
5205	end
5206	printf "), "
5207	
5208	if ( $kgm_iopmpriv->MachineState != 20 )
5209        printf "DriverTimer = %d, ",(unsigned int)$kgm_iopmpriv->DriverTimer
5210        printf "SettleTime  = %d, ",(unsigned int)$kgm_iopmpriv->SettleTimeUS
5211        printf "HeadNoteFlags = %08x, ",(unsigned int)$kgm_iopmpriv->HeadNoteFlags
5212        printf "HeadNoteState = %d, ",(unsigned int)$kgm_iopmpriv->HeadNoteState
5213        printf "HeadNoteOutputFlags = %08x, ",(unsigned int)$kgm_iopmpriv->HeadNoteOutputFlags
5214        printf "HeadNoteDomainState = %08x, ",(unsigned int)$kgm_iopmpriv->HeadNoteDomainState
5215        printf "HeadNoteCapabilityFlags = %08x, ",(unsigned int)$kgm_iopmpriv->HeadNoteCapabilityFlags
5216        printf "HeadNotePendingAcks = %x, ",(unsigned int)$kgm_iopmpriv->HeadNotePendingAcks
5217	end
5218
5219    if ( $kgm_iopmpriv->DeviceOverrides != 0 )
5220        printf"DeviceOverrides, "
5221    end
5222	
5223    printf "DriverDesire = %d, ",(unsigned int)$kgm_iopmpriv->DriverDesire
5224    printf "DeviceDesire = %d, ",(unsigned int)$kgm_iopmpriv->DeviceDesire
5225    printf "DesiredPowerState = %d, ",(unsigned int)$kgm_iopmpriv->DesiredPowerState
5226    printf "PreviousRequest = %d }",(unsigned int)$kgm_iopmpriv->PreviousRequest
5227end
5228
5229document showioservicepm
5230Syntax: (gdb) showioservicepm <IOServicePM pointer>
5231| Routine to dump the IOServicePM object
5232end
5233
5234define showregistryentryrecursepmstate
5235    set $kgm_re         = (IOService *)$arg1
5236    set $kgm$arg0_stack = (unsigned long long) $arg2
5237
5238    if ($arg3)
5239	set $kgm$arg0_stack = $kgm$arg0_stack | (1ULL << $kgm_reg_depth)
5240    else
5241	set $kgm$arg0_stack = $kgm$arg0_stack & ~(1ULL << $kgm_reg_depth)
5242    end
5243
5244    dictget $kgm_re->fRegistryTable $kgm_childkey
5245    set $kgm$arg0_child_array = (OSArray *) $kgm_result
5246
5247    if ($kgm$arg0_child_array)
5248	set $kgm$arg0_child_count = $kgm$arg0_child_array->count
5249    else
5250	set $kgm$arg0_child_count = 0
5251    end
5252
5253    if ($kgm$arg0_child_count)
5254	set $kgm$arg0_stack = $kgm$arg0_stack | (2ULL << $kgm_reg_depth)
5255    else
5256	set $kgm$arg0_stack = $kgm$arg0_stack & ~(2ULL << $kgm_reg_depth)
5257    end
5258
5259    indent $kgm_reg_depth $kgm$arg0_stack
5260    printf "+-o "
5261
5262    dictget $kgm_re->fRegistryTable $kgm_namekey
5263    if ($kgm_result == 0)
5264	dictget $kgm_re->fRegistryTable gIONameKey
5265    end
5266    if ($kgm_result == 0)
5267	dictget $kgm_re->fPropertyTable gIOClassKey
5268    end
5269
5270    if ($kgm_result != 0)
5271	printf "%s <%p>", ((OSString *)$kgm_result)->string, $kgm_re
5272    else
5273 	if (((IOService*)$kgm_re)->pwrMgt &&  ((IOService*)$kgm_re)->pwrMgt->Name)
5274 	    printf "%s <%p>", ((IOService*)$kgm_re)->pwrMgt->Name, $kgm_re
5275	else
5276	    printf "?? <%p>", $kgm_re
5277	end
5278    end
5279
5280    if (((IOService*)$kgm_re)->pwrMgt )
5281    	printf " Current Power State: %ld ", ((IOService*)$kgm_re)->pwrMgt->CurrentPowerState
5282    	#printf " Mach State %ld", ((IOService*)$kgm_re)->pwrMgt->MachineState
5283        showioservicepm ((IOService*)$kgm_re)->pwrMgt
5284    end
5285    printf "\n"
5286   
5287
5288    # recurse
5289    if ($kgm$arg0_child_count != 0)
5290
5291	set $kgm_reg_depth = $kgm_reg_depth + 1
5292	set $kgm$arg0_child_idx = 0
5293
5294	while ($kgm$arg0_child_idx < $kgm$arg0_child_count)
5295	    set $kgm_re = $kgm$arg0_child_array->array[$kgm$arg0_child_idx++]
5296	    set $kgm_more_sib = ($kgm$arg0_child_idx < $kgm$arg0_child_count)
5297	    showregistryentryrecursepmstate _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib
5298	end
5299
5300	set $kgm_reg_depth = $kgm_reg_depth - 1
5301    end
5302end
5303
5304define showregistryentryintpmstate
5305    set $kgm_namekey   = (OSSymbol *) $kgm_reg_plane[2]
5306    set $kgm_childkey  = (OSSymbol *) $kgm_reg_plane[4]
5307    showregistryentryrecursepmstate _ $arg0 0 0
5308end
5309
5310define showregistrypmstate
5311#    setregistryplane gIOPowerPlane
5312    set $kgm_reg_depth  = 0
5313    set $kgm_show_props = 1
5314    showregistryentryintpmstate gRegistryRoot
5315end
5316
5317document showregistrypmstate
5318Syntax: (gdb) showregistrypmstate
5319| Routine to dump the PM state of each IOPower registry entry
5320end
5321
5322define showstacksafterthread
5323    set $kgm_head_taskp = &default_pset.tasks
5324    set $kgm_actp = (struct thread *)$arg0
5325    set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
5326    set $kgm_taskp = (struct task *)$kgm_actp->task
5327    while $kgm_taskp != $kgm_head_taskp
5328        showtaskheader
5329        showtaskint $kgm_taskp
5330        set $kgm_head_actp = &($kgm_taskp->threads)
5331        while $kgm_actp != $kgm_head_actp
5332            showactheader
5333            if ($decode_wait_events > 0)
5334               showactint $kgm_actp 1
5335            else
5336               showactint $kgm_actp 2
5337            end
5338            set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
5339        end
5340        printf "\n"
5341        set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next) 
5342    end
5343end
5344
5345document showstacksafterthread
5346Syntax: (gdb) showstacksafterthread <thread>
5347| Routine to print out all stacks (as in showallstacks) starting after a given thread
5348| Useful if that gdb refuses to print a certain task's stack.
5349end
5350
5351define kdp-reenter
5352       set kdp_reentry_deadline = ((unsigned) $arg0)*1000
5353       continue
5354end
5355
5356document kdp-reenter
5357Syntax: (gdb) kdp-reenter <seconds>
5358| Schedules reentry into the debugger after <seconds> seconds, and resumes
5359| the target system.
5360end
5361
5362define _if_present
5363    if (!$arg0)
5364        printf " not"
5365    end
5366    printf " present"
5367end
5368
5369define showMCAstate
5370    if ($kgm_mtype != 7)
5371        printf "Not available for current architecture.\n"
5372    else
5373        printf "MCA"
5374        _if_present mca_MCA_present
5375        printf ", control MSR"
5376        _if_present mca_control_MSR_present
5377        printf ", threshold status"
5378        _if_present mca_threshold_status_present
5379        printf "\n%d error banks, ", mca_error_bank_count
5380        printf "family code 0x%x, ", mca_family
5381        printf "machine-check dump state: %d\n", mca_dump_state
5382        set $kgm_cpu = 0
5383        while cpu_data_ptr[$kgm_cpu] != 0
5384            set $kgm_mcp = cpu_data_ptr[$kgm_cpu]->cpu_mca_state
5385            if $kgm_mcp
5386                printf "CPU %d:", $kgm_cpu
5387                printf " mca_mcg_ctl: 0x%016llx", $kgm_mcp->mca_mcg_ctl
5388                printf " mca_mcg_status: 0x%016llx\n", $kgm_mcp->mca_mcg_status.u64
5389                printf "bank   "
5390                printf "mca_mci_ctl        "
5391                printf "mca_mci_status     "
5392                printf "mca_mci_addr       "
5393                printf "mca_mci_misc\n"
5394                set $kgm_bank = 0
5395                while $kgm_bank < mca_error_bank_count
5396                    set $kgm_bp = &$kgm_mcp->mca_error_bank[$kgm_bank]
5397                    printf " %2d:", $kgm_bank
5398                    printf " 0x%016llx", $kgm_bp->mca_mci_ctl
5399                    printf " 0x%016llx", $kgm_bp->mca_mci_status.u64
5400                    printf " 0x%016llx", $kgm_bp->mca_mci_addr
5401                    printf " 0x%016llx\n", $kgm_bp->mca_mci_misc
5402                    set $kgm_bank = $kgm_bank + 1
5403                end
5404            end
5405            set $kgm_cpu = $kgm_cpu + 1
5406        end
5407    end
5408end
5409
5410document showMCAstate
5411Syntax: showMCAstate
5412| Print machine-check register state after MC exception.
5413end
5414
5415define _pt_step
5416    #
5417    # Step to lower-level page table and print attributes
5418    #   $kgm_pt_paddr: current page table entry physical address
5419    #   $kgm_pt_index: current page table entry index (0..511)
5420    # returns
5421    #   $kgm_pt_paddr: next level page table entry physical address
5422    #                  or null if invalid
5423    # For $kgm_pt_verbose = 0: print nothing
5424    #                       1: print basic information
5425    #                       2: print basic information and hex table dump
5426    # The trickery with kdp_src_high32 is required for accesses above 4GB.
5427    #
5428    set $kgm_entryp = $kgm_pt_paddr + 8*$kgm_pt_index
5429    set kdp_src_high32 = $kgm_pt_paddr >> 32
5430    set kdp_trans_off = 1
5431    set $entry =  *(pt_entry_t *)($kgm_entryp & 0x0ffffffffULL)
5432    if $kgm_pt_verbose == 2
5433        x/512g ($kgm_pt_paddr & 0x0ffffffffULL)
5434    end
5435    set kdp_trans_off = 0
5436    set kdp_src_high32 = 0
5437    set $kgm_paddr_mask = ~((0xffffULL<<48) | 0xfffULL)
5438    if $kgm_pt_verbose == 0
5439        if $entry & (0x1 << 0)
5440            set $kgm_pt_paddr = $entry & $kgm_paddr_mask
5441        else
5442            set $kgm_pt_paddr = 0
5443        end
5444    else
5445        printf "0x%016llx:\n\t0x%016llx\n\t", $kgm_entryp, $entry
5446        if $entry & (0x1 << 0)
5447            printf "valid"	
5448            set $kgm_pt_paddr = $entry & $kgm_paddr_mask
5449        else
5450            printf "invalid"
5451            set $kgm_pt_paddr = 0
5452        end
5453        if $entry & (0x1 << 1)
5454            printf " writeable" 
5455        else
5456            printf " read-only" 
5457        end
5458        if $entry & (0x1 << 2)
5459            printf " user" 
5460        else
5461            printf " supervisor" 
5462        end
5463        if $entry & (0x1 << 3)
5464            printf " PWT" 
5465        end
5466        if $entry & (0x1 << 4)
5467            printf " PCD" 
5468        end
5469        if $entry & (0x1 << 5)
5470            printf " accessed" 
5471        end
5472        if $entry & (0x1 << 6)
5473            printf " dirty" 
5474        end
5475        if $entry & (0x1 << 7)
5476            printf " PAT" 
5477        end
5478        if $entry & (0x1 << 8)
5479            printf " global" 
5480        end
5481        if $entry & (0x3 << 9)
5482            printf " avail:0x%x", ($entry >> 9) & 0x3
5483        end
5484        if $entry & (0x1 << 63)
5485            printf " noexec" 
5486        end
5487        printf "\n"
5488    end
5489end
5490
5491define _pmap_walk
5492    set $kgm_pmap = (pmap_t) $arg0
5493    set $kgm_vaddr = $arg1
5494    set $kgm_pt_paddr = $kgm_pmap->pm_cr3
5495    if $kgm_pt_paddr && cpu_64bit
5496        set $kgm_pt_index = ($kgm_vaddr >> 39) & 0x1ffULL
5497        if $kgm_pt_verbose
5498            printf "pml4 (index %d):\n", $kgm_pt_index
5499        end
5500        _pt_step
5501    end
5502    if $kgm_pt_paddr
5503        set $kgm_pt_index = ($kgm_vaddr >> 30) & 0x1ffULL
5504        if $kgm_pt_verbose
5505            printf "pdpt (index %d):\n", $kgm_pt_index
5506        end
5507        _pt_step
5508    end
5509    if $kgm_pt_paddr
5510        set $kgm_pt_index = ($kgm_vaddr >> 21) & 0x1ffULL
5511        if $kgm_pt_verbose
5512            printf "pdt (index %d):\n", $kgm_pt_index
5513        end
5514        _pt_step
5515    end
5516    if $kgm_pt_paddr
5517        set $kgm_pt_index = ($kgm_vaddr >> 12) & 0x1ffULL
5518        if $kgm_pt_verbose
5519            printf "pt (index %d):\n", $kgm_pt_index
5520        end
5521        _pt_step
5522    end
5523    if $kgm_pt_paddr
5524        set $kgm_paddr = $kgm_pt_paddr + ($kgm_vaddr & 0xfffULL)
5525        set kdp_trans_off = 1
5526        set kdp_src_high32 = $kgm_paddr >> 32
5527        set $kgm_value = *($kgm_paddr & 0x0ffffffffULL)
5528        set kdp_trans_off = 0
5529        set kdp_src_high32 = 0
5530        printf "phys 0x%016llx: 0x%08x\n", $kgm_paddr, $kgm_value
5531    else
5532        set $kgm_paddr = 0
5533        printf "(no translation)\n"
5534    end
5535end
5536
5537define pmap_walk
5538    if $kgm_mtype != 7
5539        printf "Not available for current architecture.\n"
5540    else
5541        if $argc != 2
5542            printf "pmap_walk <pmap> <vaddr>\n"
5543        else
5544            if !$kgm_pt_verbose
5545                set $kgm_pt_verbose = 1
5546            else
5547                if $kgm_pt_verbose != 2
5548                    set $kgm_pt_verbose = 1
5549                end
5550            end
5551            _pmap_walk $arg0 $arg1
5552        end
5553    end
5554end
5555
5556document pmap_walk
5557Syntax: (gdb) pmap_walk <pmap> <virtual_address>
5558| Perform a page-table walk in <pmap> for <virtual_address>.
5559| Set $kgm_pt_verbose=2 for full hex dump of page tables.
5560end
5561
5562define pmap_vtop
5563    if $kgm_mtype != 7
5564        printf "Not available for current architecture.\n"
5565    else
5566        if $argc != 2
5567            printf "pmap_vtop <pamp> <vaddr>\n"
5568        else
5569            set $kgm_pt_verbose = 0
5570            _pmap_walk $arg0 $arg1
5571        end
5572    end
5573end
5574
5575document pmap_vtop
5576Syntax: (gdb) pmap_vtop <pmap> <virtual_address>
5577| For page-tables in <pmap> translate <virtual_address> to physical address.
5578end
5579
5580define zstack
5581	set $index = $arg0
5582
5583	if (log_records == 0)
5584		set $count = 0
5585		printf "Zone logging not enabled.  Add 'zlog=<zone name>' to boot-args.\n"
5586	else 
5587		if ($argc == 2)
5588			set $count = $arg1
5589		else
5590			set $count = 1
5591		end
5592	end
5593
5594	while ($count)
5595		printf "\n--------------- "
5596
5597		if (zrecords[$index].z_opcode == 1)
5598			printf "ALLOC "
5599		else
5600			printf "FREE "
5601		end
5602
5603		printf " 0x%x : index %d  :  ztime %d -------------\n", zrecords[$index].z_element, $index, zrecords[$index].z_time
5604
5605		set $frame = 0
5606
5607		while ($frame < 15)
5608			set $frame_pc = zrecords[$index].z_pc[$frame]
5609
5610			if ($frame_pc == 0)
5611				loop_break
5612			end
5613
5614			x/i $frame_pc
5615			set $frame = $frame + 1
5616		end
5617
5618		set $index = $index + 1
5619		set $count = $count - 1
5620	end
5621end
5622
5623document zstack
5624Syntax: (gdb) zstack <index> [<count>]
5625| Zone leak debugging: print the stack trace of log element at <index>.
5626| If a <count> is supplied, it prints <count> log elements starting at <index>.
5627|
5628| The suggested usage is to look at indexes below zcurrent and look for common stack traces.
5629| The stack trace that occurs the most is probably the cause of the leak.  Find the pc of the
5630| function calling into zalloc and use the countpcs kgmacro to find out how often that pc occurs in the log.
5631| The pc occuring in a high percentage of records is most likely the source of the leak.
5632|
5633| The findoldest kgmacro is also useful for leak debugging since it identifies the oldest record
5634| in the log, which may indicate the leaker.
5635end
5636
5637define findoldest
5638	set $index = 0
5639	set $count = log_records
5640	set $cur_min = 2000000000
5641	set $cur_index = 0
5642
5643	if (log_records == 0)
5644		printf "Zone logging not enabled.  Add 'zlog=<zone name>' to boot-args.\n"
5645	else
5646
5647		while ($count)
5648			if (zrecords[$index].z_element && zrecords[$index].z_time < $cur_min)
5649				set $cur_index = $index
5650				set $cur_min = zrecords[$index].z_time
5651			end
5652	
5653			set $count = $count - 1
5654			set $index = $index + 1
5655		end
5656	
5657		printf "oldest record is at log index %d:\n", $cur_index
5658		zstack $cur_index
5659	end
5660end
5661
5662document findoldest
5663Syntax: (gdb) findoldest
5664| Zone leak debugging: find and print the oldest record in the log.  Note that this command
5665| can take several minutes to run since it uses linear search.
5666|
5667| Once it prints a stack trace, find the pc of the caller above all the zalloc, kalloc and
5668| IOKit layers.  Then use the countpcs kgmacro to see how often this caller has allocated
5669| memory.  A caller with a high percentage of records in the log is probably the leaker.
5670end
5671
5672define countpcs
5673	set $target_pc = $arg0
5674	set $index = 0
5675	set $count = log_records
5676	set $found = 0
5677
5678	if (log_records == 0)
5679		printf "Zone logging not enabled.  Add 'zlog=<zone name>' to boot-args.\n"
5680	else
5681
5682		while ($count)
5683			set $frame = 0
5684	
5685			if (zrecords[$index].z_element != 0)
5686				while ($frame < 15)
5687					if (zrecords[$index].z_pc[$frame] == $target_pc)
5688						set $found = $found + 1
5689						set $frame = 15
5690					end
5691		
5692					set $frame = $frame + 1
5693				end
5694			end
5695	
5696			set $index = $index + 1
5697			set $count = $count - 1
5698		end
5699	
5700		printf "occurred %d times in log (%d%c of records)\n", $found, ($found * 100) / zrecorded, '%'
5701	end
5702end
5703
5704document countpcs
5705Syntax: (gdb) countpcs <pc>
5706| Zone leak debugging: search the log and print a count of all log entries that contain the given <pc>
5707| in the stack trace.  This is useful for verifying a suspected <pc> as being the source of
5708| the leak.  If a high percentage of the log entries contain the given <pc>, then it's most
5709| likely the source of the leak.  Note that this command can take several minutes to run.
5710end
5711
5712define findelem
5713	set $fe_index = zcurrent
5714	set $fe_count = log_records
5715	set $fe_elem = $arg0
5716	set $fe_prev_op = -1
5717
5718	if (log_records == 0)
5719		printf "Zone logging not enabled.  Add 'zlog=<zone name>' to boot-args.\n"
5720	end
5721
5722	while ($fe_count)
5723		if (zrecords[$fe_index].z_element == $fe_elem)
5724			zstack $fe_index
5725
5726			if (zrecords[$fe_index].z_opcode == $fe_prev_op)
5727				printf "***************   DOUBLE OP!   *********************\n
5728			end
5729
5730			set $fe_prev_op = zrecords[$fe_index].z_opcode
5731		end
5732
5733		set $fe_count = $fe_count - 1
5734		set $fe_index = $fe_index + 1
5735
5736		if ($fe_index >= log_records)
5737			set $fe_index = 0
5738		end
5739	end
5740end
5741
5742document findelem
5743Syntax: (gdb) findelem <elem addr>
5744| Zone corruption debugging: search the log and print out the stack traces for all log entries that
5745| refer to the given zone element.  When the kernel panics due to a corrupted zone element, get the
5746| element address and use this macro.  This will show you the stack traces of all logged zalloc and
5747| zfree operations which tells you who touched the element in the recent past.  This also makes
5748| double-frees readily apparent.
5749end
5750