# Kernel gdb macros
#
# These gdb macros should be useful during kernel development in
# determining what's going on in the kernel.
#
# All the convenience variables used by these macros begin with $kgm_
set print asm-demangle on
set cp-abi gnu-v2
echo Loading Kernel GDB Macros package. Type "help kgm" for more info.\n
define kgm
printf ""
echo These are the gdb macros for kernel debugging. Type "help kgm" for more info.\n
end
document kgm
| These are the kernel gdb macros. These gdb macros are intended to be
| used when debugging a remote kernel via the kdp protocol. Typically, you
| would connect to your remote target like so:
| (gdb) target remote-kdp
| (gdb) attach <name-of-remote-host>
|
| The following macros are available in this package:
| showversion Displays a string describing the remote kernel version
|
| showalltasks Display a summary listing of all tasks
| showallthreads Display info about all threads in the system
| showallstacks Display the stack for each thread in the system
| showcurrentthreads Display info about the thread running on each cpu
| showcurrentstacks Display the stack for the thread running on each cpu
| showallvm Display a summary listing of all the vm maps
| showallvme Display a summary listing of all the vm map entries
| showallipc Display a summary listing of all the ipc spaces
| showallrights Display a summary listing of all the ipc rights
| showallkmods Display a summary listing of all the kernel modules
|
| showallclasses Display info about all OSObject subclasses in the system
| showobject Show info about an OSObject - its vtable ptr and retain count, & more info for simple container classes.
| showregistry Show info about all registry entries in the current plane
| showregistryprops Show info about all registry entries in the current plane, and their properties
| showregistryentry Show info about a registry entry; its properties and descendants in the current plane
| setregistryplane Set the plane to be used for the iokit registry macros (pass zero for list)
|
| showtask Display info about the specified task
| showtaskthreads Display info about the threads in the task
| showtaskstacks Display the stack for each thread in the task
| showtaskvm Display info about the specified task's vm_map
| showtaskvme Display info about the task's vm_map entries
| showtaskipc Display info about the specified task's ipc space
| showtaskrights Display info about the task's ipc space entries
|
| showact Display info about a thread specified by activation
| showactstack Display the stack for a thread specified by activation
|
| showmap Display info about the specified vm_map
| showmapvme Display a summary list of the specified vm_map's entries
|
| showipc Display info about the specified ipc space
| showrights Display a summary list of all the rights in an ipc space
|
| showpid Display info about the process identified by pid
| showproc Display info about the process identified by proc struct
| showprocinfo Display detailed info about the process identified by proc struct
| showprocfiles Given a proc_t pointer, display the list of open file descriptors
| showproclocks Given a proc_t pointer, display the list of advisory file locks
| zombproc Print out all procs in the zombie list
| allproc Print out all process in the system not in the zombie list
| zombstacks Print out all stacks of tasks that are exiting
|
| showinitchild Print out all processes in the system which are children of init process
|
| showkmod Display info about a kernel module
| showkmodaddr Given an address, display the kernel module and offset
|
| dumpcallqueue Dump out all the entries given a queue head
|
| showallmtx Display info about mutexes usage
| showallrwlck Display info about reader/writer locks usage
|
| zprint Display info about the memory zones
| showioalloc Display info about iokit allocations
| paniclog Display the panic log info
|
| switchtoact Switch to different context specified by activation
| switchtoctx Switch to different context
| showuserstack Display numeric backtrace of the user stack for an
| activation
|
| switchtouserthread Switch to the user context of the specified thread
| resetstacks Return to the original kernel context
|
| resetctx Reset context
| resume_on Resume when detaching from gdb
| resume_off Don't resume when detaching from gdb
|
| sendcore Configure kernel to send a coredump to the specified IP
| disablecore Configure the kernel to disable coredump transmission
| switchtocorethread Corefile version of "switchtoact"
| resetcorectx Corefile version of "resetctx"
|
| readphys Reads the specified untranslated address
| readphys64 Reads the specified untranslated 64-bit address
|
| rtentry_showdbg Print the debug information of a route entry
| rtentry_trash Walk the list of trash route entries
|
| mbuf_walkpkt Walk the mbuf packet chain (m_nextpkt)
| mbuf_walk Walk the mbuf chain (m_next)
| mbuf_buf2slab Find the slab structure of the corresponding buffer
| mbuf_buf2mca Find the mcache audit structure of the corresponding mbuf
| mbuf_showmca Print the contents of an mbuf mcache audit structure
| mbuf_showactive Print all active/in-use mbuf objects
| mbuf_showinactive Print all freed/in-cache mbuf objects
| mbuf_showall Print all mbuf objects
| mbuf_slabs Print all slabs in the group
| mbuf_slabstbl Print slabs table
| mbuf_stat Print extended mbuf allocator statistics
|
| mcache_walkobj Walk the mcache object chain (obj_next)
| mcache_stat Print all mcaches in the system
| mcache_showcache Display the number of objects in the cache
|
| showbootermemorymap Dump phys memory map from EFI
|
| systemlog Display the kernel's printf ring buffer
|
| showvnodepath Print the path for a vnode
| showvnodelocks Display list of advisory locks held/blocked on a vnode
| showallvols Display a summary of mounted volumes
| showvnode Display info about one vnode
| showvolvnodes Display info about all vnodes of a given volume
| showvolbusyvnodes Display info about busy (iocount!=0) vnodes of a given volume
| showallbusyvnodes Display info about all busy (iocount!=0) vnodes
| showallvnodes Display info about all vnodes
| print_vnode Print out the fields of a vnode struct
| showprocvnodes Print out all the open fds which are vnodes in a process
| showallprocvnodes Print out all the open fds which are vnodes in any process
| showmountvnodes Print the vnode list
| showmountallvnodes Print the vnode inactive list
| showworkqvnodes Print the vnode worker list
| shownewvnodes Print the new vnode list
|
| ifconfig display ifconfig-like output
| showifaddrs show the list of addresses for the given ifp
| showifmultiaddrs show the list of multicast addresses for the given ifp
|
| showallpmworkqueues Display info about all IOPMWorkQueue objects
| showregistrypmstate Display power management state for all IOPower registry entries
| showioservicepm Display the IOServicePM object
| showstacksaftertask showallstacks starting after a given task
| showstacksafterthread showallstacks starting after a given thread
|
| showMCAstate Print machine-check register state after MC exception.
|
| showallgdbstacks Cause GDB to trace all thread stacks
| showallgdbcorestacks Corefile equivalent of "showallgdbstacks"
| kdp-reenter Schedule reentry into the debugger and continue.
| kdp-reboot Restart remote target
|
| zstack Print zalloc caller stack (zone leak debugging)
| findoldest Find oldest zone leak debugging record
| countpcs Print how often a pc occurs in the zone leak log
|
|
| Type "help <macro>" for more specific help on a particular macro.
| Type "show user <macro>" to see what the macro is really doing.
end
# This macro should appear before any symbol references, to facilitate
# a gdb "source" without a loaded symbol file.
define showversion
printf "%s\n", *(char **)0x501C
end
document showversion
Syntax: showversion
| Read the kernel version string from a fixed address in low
| memory. Useful if you don't know which kernel is on the other end,
| and need to find the appropriate symbols. Beware that if you've
| loaded a symbol file, but aren't connected to a remote target,
| the version string from the symbol file will be displayed instead.
| This macro expects to be connected to the remote kernel to function
| correctly.
end
set $kgm_mtype = ((struct mach_header)_mh_execute_header).cputype
# This option tells gdb to relax its stack tracing heuristics
# Useful for debugging across stack switches
# (to the interrupt stack, for instance). Requires gdb-675 or greater.
# Don't do this for arm as a workaround to 5486905
if ($kgm_mtype != 12)
set backtrace sanity-checks off
end
set $kgm_dummy = &proc0
set $kgm_dummy = &kmod
set $kgm_reg_depth = 0
set $kgm_reg_plane = (void **) gIOServicePlane
set $kgm_namekey = (OSSymbol *) 0
set $kgm_childkey = (OSSymbol *) 0
set $kgm_show_object_addrs = 0
set $kgm_show_object_retain = 0
set $kgm_show_props = 0
set $kgm_show_kmod_syms = 0
define showkmodheader
printf "kmod address size "
printf "id refs version name\n"
end
define showkmodint
set $kgm_kmodp = (struct kmod_info *)$arg0
printf "0x%08x ", $arg0
printf "0x%08x ", $kgm_kmodp->address
printf "0x%08x ", $kgm_kmodp->size
printf "%3d ", $kgm_kmodp->id
printf "%5d ", $kgm_kmodp->reference_count
printf "%10s ", &$kgm_kmodp->version
printf "%s\n", &$kgm_kmodp->name
end
set $kgm_kmodmin = 0xffffffff
set $kgm_fkmodmin = 0x00000000
set $kgm_kmodmax = 0x00000000
set $kgm_fkmodmax = 0xffffffff
set $kgm_pkmod = 0
set $kgm_pkmodst = 0
set $kgm_pkmoden = 0
define showkmodaddrint
printf "0x%x" , $arg0
if ((unsigned int)$arg0 >= (unsigned int)$kgm_pkmodst) && ((unsigned int)$arg0 <= (unsigned int)$kgm_pkmoden)
set $kgm_off = ((unsigned int)$arg0 - (unsigned int)$kgm_pkmodst)
printf " <%s + 0x%x>", $kgm_pkmod->name, $kgm_off
else
if ((unsigned int)$arg0 <= (unsigned int)$kgm_fkmodmax) && ((unsigned int)$arg0 >= (unsigned int)$kgm_fkmodmin)
set $kgm_kmodp = (struct kmod_info *)kmod
while $kgm_kmodp
set $kgm_kmod = *$kgm_kmodp
if $kgm_kmod.address && ($kgm_kmod.address < $kgm_kmodmin)
set $kgm_kmodmin = $kgm_kmod.address
end
if ($kgm_kmod.address + $kgm_kmod.size) > $kgm_kmodmax
set $kgm_kmodmax = $kgm_kmod.address + $kgm_kmod.size
end
set $kgm_off = ((unsigned int)$arg0 - (unsigned int)$kgm_kmod.address)
if ($kgm_kmod.address <= $arg0) && ($kgm_off <= $kgm_kmod.size)
printf " <%s + 0x%x>", $kgm_kmodp->name, $kgm_off
set $kgm_pkmod = $kgm_kmodp
set $kgm_pkmodst = $kgm_kmod.address
set $kgm_pkmoden = $kgm_pkmodst + $kgm_kmod.size
set $kgm_kmodp = 0
else
set $kgm_kmodp = $kgm_kmod.next
end
end
if !$kgm_pkmod
set $kgm_fkmodmin = $kgm_kmodmin
set $kgm_fkmodmax = $kgm_kmodmax
end
end
end
end
define showkmodaddr
showkmodaddrint $arg0
end
document showkmodaddr
Syntax: (gdb) showkmodaddr <addr>
| Given an address, print the offset and name for the kmod containing it
end
define showkmod
showkmodheader
showkmodint $arg0
end
document showkmod
Syntax: (gdb) showkmod <kmod>
| Routine to print info about a kernel module
end
define showallkmods
showkmodheader
set $kgm_kmodp = (struct kmod_info *)kmod
while $kgm_kmodp
showkmodint $kgm_kmodp
set $kgm_kmodp = $kgm_kmodp->next
end
end
document showallkmods
Syntax: (gdb) showallkmods
| Routine to print a summary listing of all the kernel modules
end
define showactheader
printf " thread "
printf "processor pri state wait_queue wait_event\n"
end
define showactint
printf " 0x%08x ", $arg0
set $kgm_thread = *(struct thread *)$arg0
printf "0x%08x ", $kgm_thread.last_processor
printf "%3d ", $kgm_thread.sched_pri
set $kgm_state = $kgm_thread.state
if $kgm_state & 0x80
printf "I"
end
if $kgm_state & 0x40
printf "P"
end
if $kgm_state & 0x20
printf "A"
end
if $kgm_state & 0x10
printf "H"
end
if $kgm_state & 0x08
printf "U"
end
if $kgm_state & 0x04
printf "R"
end
if $kgm_state & 0x02
printf "S"
end
if $kgm_state & 0x01
printf "W\t"
printf "0x%08x ", $kgm_thread.wait_queue
if (((unsigned)$kgm_thread.wait_event > (unsigned)sectPRELINKB) \
&& ($arg1 != 2) && ($kgm_show_kmod_syms == 0))
showkmodaddr $kgm_thread.wait_event
else
output /a (unsigned) $kgm_thread.wait_event
end
if ($kgm_thread.uthread != 0)
set $kgm_uthread = (struct uthread *)$kgm_thread.uthread
if ($kgm_uthread->uu_wmesg != 0)
printf " \"%s\"", $kgm_uthread->uu_wmesg
end
end
end
if $arg1 != 0
if ($kgm_thread.kernel_stack != 0)
if ($kgm_thread.reserved_stack != 0)
printf "\n\t\treserved_stack=0x%08x", $kgm_thread.reserved_stack
end
printf "\n\t\tkernel_stack=0x%08x", $kgm_thread.kernel_stack
if ($kgm_mtype == 18)
set $mysp = $kgm_thread.machine.pcb->save_r1
end
if ($kgm_mtype == 7)
set $kgm_statep = (struct x86_kernel_state32 *) \
($kgm_thread->kernel_stack + 0x4000 \
- sizeof(struct x86_kernel_state32))
set $mysp = $kgm_statep->k_ebp
end
if ($kgm_mtype == 12)
if ($arg0 == $r9)
set $mysp = $r7
else
set $kgm_statep = (struct arm_saved_state *)$kgm_thread.machine.kstackptr
set $mysp = $kgm_statep->r[7]
end
end
set $prevsp = $mysp - 16
printf "\n\t\tstacktop=0x%08x", $mysp
if ($kgm_mtype == 18)
set $stkmask = 0xf
else
set $stkmask = 0x3
end
set $kgm_return = 0
while ($mysp != 0) && (($mysp & $stkmask) == 0) \
&& ($mysp != $prevsp) \
&& ((((unsigned) $mysp ^ (unsigned) $prevsp) < 0x2000) \
|| (((unsigned)$mysp < ((unsigned) ($kgm_thread->kernel_stack+0x4000))) \
&& ((unsigned)$mysp > (unsigned) ($kgm_thread->kernel_stack))))
printf "\n\t\t0x%08x ", $mysp
if ($kgm_mtype == 18)
set $kgm_return = *($mysp + 8)
end
if ($kgm_mtype == 7)
set $kgm_return = *($mysp + 4)
end
if ($kgm_mtype == 12)
set $kgm_return = *($mysp + 4)
end
if (((unsigned) $kgm_return > (unsigned) sectPRELINKB) \
&& ($kgm_show_kmod_syms == 0))
showkmodaddr $kgm_return
else
output /a (unsigned) $kgm_return
end
set $prevsp = $mysp
set $mysp = * $mysp
end
set $kgm_return = 0
printf "\n\t\tstackbottom=0x%08x", $prevsp
else
printf "\n\t\t\tcontinuation="
output /a (unsigned) $kgm_thread.continuation
end
printf "\n"
else
printf "\n"
end
end
define showact
showactheader
showactint $arg0 0
end
document showact
Syntax: (gdb) showact <activation>
| Routine to print out the state of a specific thread.
end
define showactstack
showactheader
showactint $arg0 1
end
document showactstack
Syntax: (gdb) showactstack <activation>
| Routine to print out the stack of a specific thread.
end
define showallthreads
set $kgm_head_taskp = &tasks
set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
while $kgm_taskp != $kgm_head_taskp
showtaskheader
showtaskint $kgm_taskp
showactheader
set $kgm_head_actp = &($kgm_taskp->threads)
set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
while $kgm_actp != $kgm_head_actp
showactint $kgm_actp 0
set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
end
printf "\n"
set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
end
end
document showallthreads
Syntax: (gdb) showallthreads
| Routine to print out info about all threads in the system.
end
define showcurrentthreads
set $kgm_prp = (struct processor *)processor_list
while $kgm_prp != 0
printf "Processor 0x%08x State %d (cpu_id %x)\n", $kgm_prp, ($kgm_prp)->state, ($kgm_prp)->cpu_num
if ($kgm_prp)->active_thread != 0
set $kgm_actp = ($kgm_prp)->active_thread
showtaskheader
showtaskint ($kgm_actp)->task
showactheader
showactint $kgm_actp 0
printf "\n"
end
set $kgm_prp = ($kgm_prp)->processor_list
end
end
document showcurrentthreads
Syntax: (gdb) showcurrentthreads
| Routine to print out info about the thread running on each cpu.
end
set $decode_wait_events = 0
define showallstacks
set $kgm_head_taskp = &tasks
set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
while $kgm_taskp != $kgm_head_taskp
showtaskheader
showtaskint $kgm_taskp
set $kgm_head_actp = &($kgm_taskp->threads)
set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
while $kgm_actp != $kgm_head_actp
showactheader
if ($decode_wait_events > 0)
showactint $kgm_actp 1
else
showactint $kgm_actp 2
end
set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
end
printf "\n"
set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
end
end
document showallstacks
Syntax: (gdb) showallstacks
| Routine to print out the stack for each thread in the system.
| If the variable $decode_wait_events is non-zero, the routine attempts to
| interpret thread wait_events as kernel module offsets, which can add to
| processing time.
end
define showcurrentstacks
set $kgm_prp = processor_list
while $kgm_prp != 0
printf "Processor 0x%08x State %d (cpu_id %x)\n", $kgm_prp, ($kgm_prp)->state, ($kgm_prp)->cpu_num
if ($kgm_prp)->active_thread != 0
set $kgm_actp = ($kgm_prp)->active_thread
showtaskheader
showtaskint ($kgm_actp)->task
showactheader
showactint $kgm_actp 1
printf "\n"
end
set $kgm_prp = ($kgm_prp)->processor_list
end
end
document showcurrentstacks
Syntax: (gdb) showcurrentstacks
| Routine to print out the thread running on each cpu (incl. its stack)
end
define showwaiterheader
printf "waiters activation "
printf "thread pri state wait_queue wait_event\n"
end
define showwaitqwaiters
set $kgm_w_waitqp = (struct wait_queue *)$arg0
set $kgm_w_linksp = &($kgm_w_waitqp->wq_queue)
set $kgm_w_wqe = (struct wait_queue_element *)$kgm_w_linksp->next
set $kgm_w_found = 0
while ( (queue_entry_t)$kgm_w_wqe != (queue_entry_t)$kgm_w_linksp)
if ($kgm_w_wqe->wqe_type != &_wait_queue_link)
if !$kgm_w_found
set $kgm_w_found = 1
showwaiterheader
end
set $kgm_w_shuttle = (struct thread *)$kgm_w_wqe
showactint $kgm_w_shuttle 0
end
set $kgm_w_wqe = (struct wait_queue_element *)$kgm_w_wqe->wqe_links.next
end
end
define showwaitqwaitercount
set $kgm_wc_waitqp = (struct wait_queue *)$arg0
set $kgm_wc_linksp = &($kgm_wc_waitqp->wq_queue)
set $kgm_wc_wqe = (struct wait_queue_element *)$kgm_wc_linksp->next
set $kgm_wc_count = 0
while ( (queue_entry_t)$kgm_wc_wqe != (queue_entry_t)$kgm_wc_linksp)
if ($kgm_wc_wqe->wqe_type != &_wait_queue_link)
set $kgm_wc_count = $kgm_wc_count + 1
end
set $kgm_wc_wqe = (struct wait_queue_element *)$kgm_wc_wqe->wqe_links.next
end
printf "0x%08x ", $kgm_wc_count
end
define showwaitqmembercount
set $kgm_mc_waitqsetp = (struct wait_queue_set *)$arg0
set $kgm_mc_setlinksp = &($kgm_mc_waitqsetp->wqs_setlinks)
set $kgm_mc_wql = (struct wait_queue_link *)$kgm_mc_setlinksp->next
set $kgm_mc_count = 0
while ( (queue_entry_t)$kgm_mc_wql != (queue_entry_t)$kgm_mc_setlinksp)
set $kgm_mc_count = $kgm_mc_count + 1
set $kgm_mc_wql = (struct wait_queue_link *)$kgm_mc_wql->wql_setlinks.next
end
printf "0x%08x ", $kgm_mc_count
end
define showwaitqmemberheader
printf "set-members wait_queue interlock "
printf "pol type member_cnt waiter_cnt\n"
end
define showwaitqmemberint
set $kgm_m_waitqp = (struct wait_queue *)$arg0
printf " 0x%08x ", $kgm_m_waitqp
printf "0x%08x ", $kgm_m_waitqp->wq_interlock.lock_data
if ($kgm_m_waitqp->wq_fifo)
printf "Fifo "
else
printf "Prio "
end
if ($kgm_m_waitqp->wq_type == 0xf1d1)
printf "Set "
showwaitqmembercount $kgm_m_waitqp
else
printf "Que 0x00000000 "
end
showwaitqwaitercount $kgm_m_waitqp
printf "\n"
end
define showwaitqmemberofheader
printf "member-of wait_queue interlock "
printf "pol type member_cnt waiter_cnt\n"
end
define showwaitqmemberof
set $kgm_mo_waitqp = (struct wait_queue *)$arg0
set $kgm_mo_linksp = &($kgm_mo_waitqp->wq_queue)
set $kgm_mo_wqe = (struct wait_queue_element *)$kgm_mo_linksp->next
set $kgm_mo_found = 0
while ( (queue_entry_t)$kgm_mo_wqe != (queue_entry_t)$kgm_mo_linksp)
if ($kgm_mo_wqe->wqe_type == &_wait_queue_link)
if !$kgm_mo_found
set $kgm_mo_found = 1
showwaitqmemberofheader
end
set $kgm_mo_wqlp = (struct wait_queue_link *)$kgm_mo_wqe
set $kgm_mo_wqsetp = (struct wait_queue *)($kgm_mo_wqlp->wql_setqueue)
showwaitqmemberint $kgm_mo_wqsetp
end
set $kgm_mo_wqe = (struct wait_queue_element *)$kgm_mo_wqe->wqe_links.next
end
end
define showwaitqmembers
set $kgm_ms_waitqsetp = (struct wait_queue_set *)$arg0
set $kgm_ms_setlinksp = &($kgm_ms_waitqsetp->wqs_setlinks)
set $kgm_ms_wql = (struct wait_queue_link *)$kgm_ms_setlinksp->next
set $kgm_ms_found = 0
while ( (queue_entry_t)$kgm_ms_wql != (queue_entry_t)$kgm_ms_setlinksp)
set $kgm_ms_waitqp = $kgm_ms_wql->wql_element.wqe_queue
if !$kgm_ms_found
showwaitqmemberheader
set $kgm_ms_found = 1
end
showwaitqmemberint $kgm_ms_waitqp
set $kgm_ms_wql = (struct wait_queue_link *)$kgm_ms_wql->wql_setlinks.next
end
end
define showwaitqheader
printf "wait_queue ref_count interlock "
printf "pol type member_cnt waiter_cnt\n"
end
define showwaitqint
set $kgm_waitqp = (struct wait_queue *)$arg0
printf "0x%08x ", $kgm_waitqp
if ($kgm_waitqp->wq_type == 0xf1d1)
printf "0x%08x ", ((struct wait_queue_set *)$kgm_waitqp)->wqs_refcount
else
printf "0x00000000 "
end
printf "0x%08x ", $kgm_waitqp->wq_interlock.lock_data
if ($kgm_waitqp->wq_fifo)
printf "Fifo "
else
printf "Prio "
end
if ($kgm_waitqp->wq_type == 0xf1d1)
printf "Set "
showwaitqmembercount $kgm_waitqp
else
printf "Que 0x00000000 "
end
showwaitqwaitercount $kgm_waitqp
printf "\n"
end
define showwaitq
set $kgm_waitq1p = (wait_queue_t)$arg0
showwaitqheader
showwaitqint $kgm_waitq1p
if ($kgm_waitq1p->wq_type == 0xf1d1)
showwaitqmembers $kgm_waitq1p
else
showwaitqmemberof $kgm_waitq1p
end
showwaitqwaiters $kgm_waitq1p
end
define showmapheader
printf "vm_map pmap vm_size "
printf "#ents rpage hint first_free\n"
end
define showvmeheader
printf " entry start "
printf " prot #page object offset\n"
end
define showvmint
set $kgm_mapp = (vm_map_t)$arg0
set $kgm_map = *$kgm_mapp
printf "0x%08x ", $arg0
printf "0x%08x ", $kgm_map.pmap
printf "0x%08x ", $kgm_map.size
printf "%3d ", $kgm_map.hdr.nentries
if $kgm_map.pmap
printf "%5d ", $kgm_map.pmap->stats.resident_count
else
printf "<n/a> "
end
printf "0x%08x ", $kgm_map.hint
printf "0x%08x\n", $kgm_map.first_free
if $arg1 != 0
showvmeheader
set $kgm_head_vmep = &($kgm_mapp->hdr.links)
set $kgm_vmep = $kgm_map.hdr.links.next
while (($kgm_vmep != 0) && ($kgm_vmep != $kgm_head_vmep))
set $kgm_vme = *$kgm_vmep
printf " 0x%08x ", $kgm_vmep
printf "0x%016llx ", $kgm_vme.links.start
printf "%1x", $kgm_vme.protection
printf "%1x", $kgm_vme.max_protection
if $kgm_vme.inheritance == 0x0
printf "S"
end
if $kgm_vme.inheritance == 0x1
printf "C"
end
if $kgm_vme.inheritance == 0x2
printf "-"
end
if $kgm_vme.inheritance == 0x3
printf "D"
end
if $kgm_vme.is_sub_map
printf "s "
else
if $kgm_vme.needs_copy
printf "n "
else
printf " "
end
end
printf "%5d ",($kgm_vme.links.end - $kgm_vme.links.start) >> 12
printf "0x%08x ", $kgm_vme.object.vm_object
printf "0x%016llx\n", $kgm_vme.offset
set $kgm_vmep = $kgm_vme.links.next
end
end
printf "\n"
end
define showmapvme
showmapheader
showvmint $arg0 1
end
document showmapvme
Syntax: (gdb) showmapvme <vm_map>
| Routine to print out a summary listing of all the entries in a vm_map
end
define showmap
showmapheader
showvmint $arg0 0
end
document showmap
Syntax: (gdb) showmap <vm_map>
| Routine to print out info about the specified vm_map
end
define showallvm
set $kgm_head_taskp = &tasks
set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
while $kgm_taskp != $kgm_head_taskp
showtaskheader
showmapheader
showtaskint $kgm_taskp
showvmint $kgm_taskp->map 0
set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
end
end
document showallvm
Syntax: (gdb) showallvm
| Routine to print a summary listing of all the vm maps
end
define showallvme
set $kgm_head_taskp = &tasks
set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
while $kgm_taskp != $kgm_head_taskp
showtaskheader
showmapheader
showtaskint $kgm_taskp
showvmint $kgm_taskp->map 1
set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
end
end
document showallvme
Syntax: (gdb) showallvme
| Routine to print a summary listing of all the vm map entries
end
define showipcheader
printf "ipc_space is_table table_next "
printf "flags tsize splaytree splaybase\n"
end
define showipceheader
printf " name object "
printf "rite urefs destname destination\n"
end
define showipceint
set $kgm_ie = *(ipc_entry_t)$arg0
printf " 0x%08x ", $arg1
printf "0x%08x ", $kgm_ie.ie_object
if $kgm_ie.ie_bits & 0x00100000
printf "Dead "
printf "%5d\n", $kgm_ie.ie_bits & 0xffff
else
if $kgm_ie.ie_bits & 0x00080000
printf "SET "
printf "%5d\n", $kgm_ie.ie_bits & 0xffff
else
if $kgm_ie.ie_bits & 0x00010000
if $kgm_ie.ie_bits & 0x00020000
printf " SR"
else
printf " S"
end
else
if $kgm_ie.ie_bits & 0x00020000
printf " R"
end
end
if $kgm_ie.ie_bits & 0x00040000
printf " O"
end
if $kgm_ie.index.request
printf "n"
else
printf " "
end
if $kgm_ie.ie_bits & 0x00800000
printf "c"
else
printf " "
end
printf "%5d ", $kgm_ie.ie_bits & 0xffff
showportdest $kgm_ie.ie_object
end
end
end
define showipcint
set $kgm_isp = (ipc_space_t)$arg0
set $kgm_is = *$kgm_isp
printf "0x%08x ", $arg0
printf "0x%08x ", $kgm_is.is_table
printf "0x%08x ", $kgm_is.is_table_next
if $kgm_is.is_growing != 0
printf "G"
else
printf " "
end
if $kgm_is.is_fast != 0
printf "F"
else
printf " "
end
if $kgm_is.is_active != 0
printf "A "
else
printf " "
end
printf "%5d ", $kgm_is.is_table_size
printf "0x%08x ", $kgm_is.is_tree_total
printf "0x%08x\n", &$kgm_isp->is_tree
if $arg1 != 0
showipceheader
set $kgm_iindex = 0
set $kgm_iep = $kgm_is.is_table
set $kgm_destspacep = (ipc_space_t)0
while ( $kgm_iindex < $kgm_is.is_table_size )
set $kgm_ie = *$kgm_iep
if $kgm_ie.ie_bits & 0x001f0000
set $kgm_name = (($kgm_iindex << 8)|($kgm_ie.ie_bits >> 24))
showipceint $kgm_iep $kgm_name
end
set $kgm_iindex = $kgm_iindex + 1
set $kgm_iep = &($kgm_is.is_table[$kgm_iindex])
end
if $kgm_is.is_tree_total
printf "Still need to write tree traversal\n"
end
end
printf "\n"
end
define showipc
set $kgm_isp = (ipc_space_t)$arg0
showipcheader
showipcint $kgm_isp 0
end
document showipc
Syntax: (gdb) showipc <ipc_space>
| Routine to print the status of the specified ipc space
end
define showrights
set $kgm_isp = (ipc_space_t)$arg0
showipcheader
showipcint $kgm_isp 1
end
document showrights
Syntax: (gdb) showrights <ipc_space>
| Routine to print a summary list of all the rights in a specified ipc space
end
define showtaskipc
set $kgm_taskp = (task_t)$arg0
showtaskheader
showipcheader
showtaskint $kgm_taskp
showipcint $kgm_taskp->itk_space 0
end
document showtaskipc
Syntax: (gdb) showtaskipc <task>
| Routine to print info about the ipc space for a task
end
define showtaskrights
set $kgm_taskp = (task_t)$arg0
showtaskheader
showipcheader
showtaskint $kgm_taskp
showipcint $kgm_taskp->itk_space 1
end
document showtaskrights
Syntax: (gdb) showtaskrights <task>
| Routine to print info about the ipc rights for a task
end
define showallipc
set $kgm_head_taskp = &tasks
set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next)
while $kgm_cur_taskp != $kgm_head_taskp
showtaskheader
showipcheader
showtaskint $kgm_cur_taskp
showipcint $kgm_cur_taskp->itk_space 0
set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->tasks.next)
end
end
document showallipc
Syntax: (gdb) showallipc
| Routine to print a summary listing of all the ipc spaces
end
define showallrights
set $kgm_head_taskp = &tasks
set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next)
while $kgm_cur_taskp != $kgm_head_taskp
showtaskheader
showipcheader
showtaskint $kgm_cur_taskp
showipcint $kgm_cur_taskp->itk_space 1
set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->tasks.next)
end
end
document showallrights
Syntax: (gdb) showallrights
| Routine to print a summary listing of all the ipc rights
end
define showtaskvm
set $kgm_taskp = (task_t)$arg0
showtaskheader
showmapheader
showtaskint $kgm_taskp
showvmint $kgm_taskp->map 0
end
document showtaskvm
Syntax: (gdb) showtaskvm <task>
| Routine to print out info about a task's vm_map
end
define showtaskvme
set $kgm_taskp = (task_t)$arg0
showtaskheader
showmapheader
showtaskint $kgm_taskp
showvmint $kgm_taskp->map 1
end
document showtaskvme
Syntax: (gdb) showtaskvme <task>
| Routine to print out info about a task's vm_map_entries
end
define showtaskheader
printf "task vm_map ipc_space #acts "
showprocheader
end
define showtaskint
set $kgm_task = *(struct task *)$arg0
printf "0x%08x ", $arg0
printf "0x%08x ", $kgm_task.map
printf "0x%08x ", $kgm_task.itk_space
printf "%3d ", $kgm_task.thread_count
showprocint $kgm_task.bsd_info
end
define showtask
showtaskheader
showtaskint $arg0
end
document showtask
Syntax (gdb) showtask <task>
| Routine to print out info about a task.
end
define showtaskthreads
showtaskheader
set $kgm_taskp = (struct task *)$arg0
showtaskint $kgm_taskp
showactheader
set $kgm_head_actp = &($kgm_taskp->threads)
set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
while $kgm_actp != $kgm_head_actp
showactint $kgm_actp 0
set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
end
end
document showtaskthreads
Syntax: (gdb) showtaskthreads <task>
| Routine to print info about the threads in a task.
end
define showtaskstacks
showtaskheader
set $kgm_taskp = (struct task *)$arg0
showtaskint $kgm_taskp
set $kgm_head_actp = &($kgm_taskp->threads)
set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
while $kgm_actp != $kgm_head_actp
showactheader
showactint $kgm_actp 1
set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
end
end
document showtaskstacks
Syntax: (gdb) showtaskstacks <task>
| Routine to print out the stack for each thread in a task.
end
define showalltasks
showtaskheader
set $kgm_head_taskp = &tasks
set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
while $kgm_taskp != $kgm_head_taskp
showtaskint $kgm_taskp
set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
end
end
document showalltasks
Syntax: (gdb) showalltasks
| Routine to print a summary listing of all the tasks
end
define showprocheader
printf " pid proc command\n"
end
define showprocint
set $kgm_procp = (struct proc *)$arg0
if $kgm_procp != 0
printf "%5d ", $kgm_procp->p_pid
printf "0x%08x ", $kgm_procp
printf "%s\n", $kgm_procp->p_comm
else
printf " *0* 0x00000000 --\n"
end
end
define showpid
showtaskheader
set $kgm_head_taskp = &tasks
set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
while $kgm_taskp != $kgm_head_taskp
set $kgm_procp = (struct proc *)$kgm_taskp->bsd_info
if (($kgm_procp != 0) && ($kgm_procp->p_pid == $arg0))
showtaskint $kgm_taskp
set $kgm_taskp = $kgm_head_taskp
else
set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
end
end
end
document showpid
Syntax: (gdb) showpid <pid>
| Routine to print a single process by pid
end
define showproc
showtaskheader
set $kgm_procp = (struct proc *)$arg0
showtaskint $kgm_procp->task $arg1 $arg2
end
define kdb
set switch_debugger=1
continue
end
document kdb
| kdb - Switch to the inline kernel debugger
|
| usage: kdb
|
| The kdb macro allows you to invoke the inline kernel debugger.
end
define showpsetheader
printf "portset waitqueue recvname "
printf "flags refs recvname process\n"
end
define showportheader
printf "port mqueue recvname "
printf "flags refs recvname process\n"
end
define showportmemberheader
printf "members port recvname "
printf "flags refs mqueue msgcount\n"
end
define showkmsgheader
printf "messages kmsg size "
printf "disp msgid remote-port local-port\n"
end
define showkmsgint
printf " 0x%08x ", $arg0
set $kgm_kmsgh = ((ipc_kmsg_t)$arg0)->ikm_header
printf "0x%08x ", $kgm_kmsgh.msgh_size
if (($kgm_kmsgh.msgh_bits & 0xff) == 19)
printf "rC"
else
printf "rM"
end
if (($kgm_kmsgh.msgh_bits & 0xff00) == (19 < 8))
printf "lC"
else
printf "lM"
end
if ($kgm_kmsgh.msgh_bits & 0xf0000000)
printf "c"
else
printf "s"
end
printf "%5d ", $kgm_kmsgh.msgh_id
printf "0x%08x ", $kgm_kmsgh.msgh_remote_port
printf "0x%08x\n", $kgm_kmsgh.msgh_local_port
end
define showkobject
set $kgm_portp = (struct ipc_port *)$arg0
printf "0x%08x kobject(", $kgm_portp->ip_kobject
set $kgm_kotype = ($kgm_portp->ip_object.io_bits & 0x00000fff)
if ($kgm_kotype == 1)
printf "THREAD"
end
if ($kgm_kotype == 2)
printf "TASK"
end
if ($kgm_kotype == 3)
printf "HOST"
end
if ($kgm_kotype == 4)
printf "HOST_PRIV"
end
if ($kgm_kotype == 5)
printf "PROCESSOR"
end
if ($kgm_kotype == 6)
printf "PSET"
end
if ($kgm_kotype == 7)
printf "PSET_NAME"
end
if ($kgm_kotype == 8)
printf "TIMER"
end
if ($kgm_kotype == 9)
printf "PAGER_REQ"
end
if ($kgm_kotype == 10)
printf "DEVICE"
end
if ($kgm_kotype == 11)
printf "XMM_OBJECT"
end
if ($kgm_kotype == 12)
printf "XMM_PAGER"
end
if ($kgm_kotype == 13)
printf "XMM_KERNEL"
end
if ($kgm_kotype == 14)
printf "XMM_REPLY"
end
if ($kgm_kotype == 15)
printf "NOTDEF 15"
end
if ($kgm_kotype == 16)
printf "NOTDEF 16"
end
if ($kgm_kotype == 17)
printf "HOST_SEC"
end
if ($kgm_kotype == 18)
printf "LEDGER"
end
if ($kgm_kotype == 19)
printf "MASTER_DEV"
end
if ($kgm_kotype == 20)
printf "ACTIVATION"
end
if ($kgm_kotype == 21)
printf "SUBSYSTEM"
end
if ($kgm_kotype == 22)
printf "IO_DONE_QUE"
end
if ($kgm_kotype == 23)
printf "SEMAPHORE"
end
if ($kgm_kotype == 24)
printf "LOCK_SET"
end
if ($kgm_kotype == 25)
printf "CLOCK"
end
if ($kgm_kotype == 26)
printf "CLOCK_CTRL"
end
if ($kgm_kotype == 27)
printf "IOKIT_SPARE"
end
if ($kgm_kotype == 28)
printf "NAMED_MEM"
end
if ($kgm_kotype == 29)
printf "IOKIT_CON"
end
if ($kgm_kotype == 30)
printf "IOKIT_OBJ"
end
if ($kgm_kotype == 31)
printf "UPL"
end
printf ")\n"
end
define showportdestproc
set $kgm_portp = (struct ipc_port *)$arg0
set $kgm_spacep = $kgm_portp->data.receiver
# check against the previous cached value - this is slow
if ($kgm_spacep != $kgm_destspacep)
set $kgm_destprocp = (struct proc *)0
set $kgm_head_taskp = &tasks
set $kgm_desttaskp = (struct task *)($kgm_head_taskp->next)
while (($kgm_destprocp == 0) && ($kgm_desttaskp != $kgm_head_taskp))
set $kgm_destspacep = $kgm_desttaskp->itk_space
if ($kgm_destspacep == $kgm_spacep)
set $kgm_destprocp = (struct proc *)$kgm_desttaskp->bsd_info
else
set $kgm_desttaskp = (struct task *)($kgm_desttaskp->tasks.next)
end
end
end
if $kgm_destprocp != 0
printf "%s(%d)\n", $kgm_destprocp->p_comm, $kgm_destprocp->p_pid
else
printf "task 0x%08x\n", $kgm_desttaskp
end
end
define showportdest
set $kgm_portp = (struct ipc_port *)$arg0
set $kgm_spacep = $kgm_portp->data.receiver
if ($kgm_spacep == ipc_space_kernel)
showkobject $kgm_portp
else
if ($kgm_portp->ip_object.io_bits & 0x80000000)
printf "0x%08x ", $kgm_portp->ip_object.io_receiver_name
showportdestproc $kgm_portp
else
printf "0x%08x inactive-port\n", $kgm_portp
end
end
end
define showportmember
printf " 0x%08x ", $arg0
set $kgm_portp = (struct ipc_port *)$arg0
printf "0x%08x ", $kgm_portp->ip_object.io_receiver_name
if ($kgm_portp->ip_object.io_bits & 0x80000000)
printf "A"
else
printf " "
end
if ($kgm_portp->ip_object.io_bits & 0x7fff0000)
printf "Set "
else
printf "Port"
end
printf "%5d ", $kgm_portp->ip_object.io_references
printf "0x%08x ", &($kgm_portp->ip_messages)
printf "0x%08x\n", $kgm_portp->ip_messages.data.port.msgcount
end
define showportint
printf "0x%08x ", $arg0
set $kgm_portp = (struct ipc_port *)$arg0
printf "0x%08x ", &($kgm_portp->ip_messages)
printf "0x%08x ", $kgm_portp->ip_object.io_receiver_name
if ($kgm_portp->ip_object.io_bits & 0x80000000)
printf "A"
else
printf "D"
end
printf "Port"
printf "%5d ", $kgm_portp->ip_object.io_references
set $kgm_destspacep = (struct ipc_space *)0
showportdest $kgm_portp
set $kgm_kmsgp = (ipc_kmsg_t)$kgm_portp->ip_messages.data.port.messages.ikmq_base
if $arg1 && $kgm_kmsgp
showkmsgheader
showkmsgint $kgm_kmsgp
set $kgm_kmsgheadp = $kgm_kmsgp
set $kgm_kmsgp = $kgm_kmsgp->ikm_next
while $kgm_kmsgp != $kgm_kmsgheadp
showkmsgint $kgm_kmsgp
set $kgm_kmsgp = $kgm_kmsgp->ikm_next
end
end
end
define showpsetint
printf "0x%08x ", $arg0
set $kgm_psetp = (struct ipc_pset *)$arg0
printf "0x%08x ", &($kgm_psetp->ips_messages)
printf "0x%08x ", $kgm_psetp->ips_object.io_receiver_name
if ($kgm_psetp->ips_object.io_bits & 0x80000000)
printf "A"
else
printf "D"
end
printf "Set "
printf "%5d ", $kgm_psetp->ips_object.io_references
printf "0x%08x ", $kgm_psetp->ips_object.io_receiver_name
set $kgm_setlinksp = &($kgm_psetp->ips_messages.data.set_queue.wqs_setlinks)
set $kgm_wql = (struct wait_queue_link *)$kgm_setlinksp->next
set $kgm_found = 0
while ( (queue_entry_t)$kgm_wql != (queue_entry_t)$kgm_setlinksp)
set $kgm_portp = (struct ipc_port *)((int)($kgm_wql->wql_element->wqe_queue) - ((int)$kgm_portoff))
if !$kgm_found
set $kgm_destspacep = (struct ipc_space *)0
showportdestproc $kgm_portp
showportmemberheader
set $kgm_found = 1
end
showportmember $kgm_portp 0
set $kgm_wql = (struct wait_queue_link *)$kgm_wql->wql_setlinks.next
end
if !$kgm_found
printf "--n/e--\n"
end
end
define showpset
showpsetheader
showpsetint $arg0 1
end
define showport
showportheader
showportint $arg0 1
end
define showipcobject
set $kgm_object = (ipc_object_t)$arg0
if ($kgm_objectp->io_bits & 0x7fff0000)
showpset $kgm_objectp
else
showport $kgm_objectp
end
end
define showmqueue
set $kgm_mqueue = *(struct ipc_mqueue *)$arg0
set $kgm_psetoff = &(((struct ipc_pset *)0)->ips_messages)
set $kgm_portoff = &(((struct ipc_port *)0)->ip_messages)
if ($kgm_mqueue.data.set_queue.wqs_wait_queue.wq_type == 0xf1d1)
set $kgm_pset = (((int)$arg0) - ((int)$kgm_psetoff))
showpsetheader
showpsetint $kgm_pset 1
end
if ($kgm_mqueue.data.set_queue.wqs_wait_queue.wq_type == 0xf1d0)
showportheader
set $kgm_port = (((int)$arg0) - ((int)$kgm_portoff))
showportint $kgm_port 1
end
end
define zprint_one
set $kgm_zone = (struct zone *)$arg0
printf "0x%08x ", $kgm_zone
printf "%8d ",$kgm_zone->count
printf "%8x ",$kgm_zone->cur_size
printf "%8x ",$kgm_zone->max_size
printf "%6d ",$kgm_zone->elem_size
printf "%8x ",$kgm_zone->alloc_size
printf "%s ",$kgm_zone->zone_name
if ($kgm_zone->exhaustible)
printf "H"
end
if ($kgm_zone->collectable)
printf "C"
end
if ($kgm_zone->expandable)
printf "X"
end
printf "\n"
end
define zprint
printf "ZONE COUNT TOT_SZ MAX_SZ ELT_SZ ALLOC_SZ NAME\n"
set $kgm_zone_ptr = (struct zone *)first_zone
while ($kgm_zone_ptr != 0)
zprint_one $kgm_zone_ptr
set $kgm_zone_ptr = $kgm_zone_ptr->next_zone
end
printf "\n"
end
document zprint
Syntax: (gdb) zprint
| Routine to print a summary listing of all the kernel zones
end
define showmtxgrp
set $kgm_mtxgrp = (struct _lck_grp_ *)$arg0
if ($kgm_mtxgrp->lck_grp_mtxcnt)
printf "0x%08x ", $kgm_mtxgrp
printf "%8d ",$kgm_mtxgrp->lck_grp_mtxcnt
printf "%12u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_util_cnt
printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_miss_cnt
printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_wait_cnt
printf "%s ",&$kgm_mtxgrp->lck_grp_name
printf "\n"
end
end
define showallmtx
printf "LCK GROUP CNT UTIL MISS WAIT NAME\n"
set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)&lck_grp_queue
set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)$kgm_mtxgrp_ptr->lck_grp_link.next
while ($kgm_mtxgrp_ptr != (struct _lck_grp_ *)&lck_grp_queue)
showmtxgrp $kgm_mtxgrp_ptr
set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)$kgm_mtxgrp_ptr->lck_grp_link.next
end
printf "\n"
end
document showallmtx
Syntax: (gdb) showallmtx
| Routine to print a summary listing of all mutexes
end
define showrwlckgrp
set $kgm_rwlckgrp = (struct _lck_grp_ *)$arg0
if ($kgm_rwlckgrp->lck_grp_rwcnt)
printf "0x%08x ", $kgm_rwlckgrp
printf "%8d ",$kgm_rwlckgrp->lck_grp_rwcnt
printf "%12u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_util_cnt
printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_miss_cnt
printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_wait_cnt
printf "%s ",&$kgm_rwlckgrp->lck_grp_name
printf "\n"
end
end
define showallrwlck
printf "LCK GROUP CNT UTIL MISS WAIT NAME\n"
set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)&lck_grp_queue
set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)$kgm_rwlckgrp_ptr->lck_grp_link.next
while ($kgm_rwlckgrp_ptr != (struct _lck_grp_ *)&lck_grp_queue)
showrwlckgrp $kgm_rwlckgrp_ptr
set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)$kgm_rwlckgrp_ptr->lck_grp_link.next
end
printf "\n"
end
document showallrwlck
Syntax: (gdb) showallrwlck
| Routine to print a summary listing of all read/writer locks
end
set $kdp_act_counter = 0
set $r0_save = 0
set $r1_save = 0
set $r2_save = 0
set $r3_save = 0
set $r4_save = 0
set $r5_save = 0
set $r6_save = 0
set $r7_save = 0
set $r8_save = 0
set $r9_save = 0
set $r10_save = 0
set $r11_save = 0
set $r12_save = 0
set $sp_save = 0
set $lr_save = 0
set $pc_save = 0
define showcontext_int
echo Context switched, current instruction pointer:
output/a $pc
echo \n
end
define switchtoact
set $newact = (struct thread *) $arg0
select 0
if ($newact->kernel_stack == 0)
echo This activation does not have a stack.\n
echo continuation:
output/a (unsigned) $newact.continuation
echo \n
else
if ($kgm_mtype == 18)
if ($kdp_act_counter == 0)
set $kdpstate = (struct savearea *) kdp.saved_state
end
set $kdp_act_counter = $kdp_act_counter + 1
set (struct savearea *) kdp.saved_state=$newact->machine->pcb
flushregs
flushstack
set $pc=$newact->machine->pcb.save_srr0
update
end
if ($kgm_mtype == 7)
set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state
if ($kdp_act_counter == 0)
set $kdpstate = *($kdpstatep)
end
set $kdp_act_counter = $kdp_act_counter + 1
set $kgm_statep = (struct x86_kernel_state32 *) \
($newact->kernel_stack + 0x4000 \
- sizeof(struct x86_kernel_state32))
set $kdpstatep->ebx = $kgm_statep->k_ebx
set $kdpstatep->ebp = $kgm_statep->k_ebp
set $kdpstatep->edi = $kgm_statep->k_edi
set $kdpstatep->esi = $kgm_statep->k_esi
set $kdpstatep->eip = $kgm_statep->k_eip
flushregs
flushstack
set $pc = $kgm_statep->k_eip
update
end
if ($kgm_mtype == 12)
set $r0_save = $r0
set $r1_save = $r1
set $r2_save = $r2
set $r3_save = $r3
set $r4_save = $r4
set $r5_save = $r5
set $r6_save = $r6
set $r7_save = $r7
set $r8_save = $r8
set $r9_save = $r9
set $r10_save = $r10
set $r11_save = $r11
set $r12_save = $r12
set $sp_save = $sp
set $lr_save = $lr
set $pc_save = $pc
set $pc_ctx = load_reg+8
set $kgm_statep = (struct arm_saved_state *)((struct thread*)$arg0)->machine.kstackptr
set $r0 = $kgm_statep->r[0]
set $r1 = $kgm_statep->r[1]
set $r2 = $kgm_statep->r[2]
set $r3 = $kgm_statep->r[3]
set $r4 = $kgm_statep->r[4]
set $r5 = $kgm_statep->r[5]
set $r6 = $kgm_statep->r[6]
set $r8 = $kgm_statep->r[8]
set $r9 = $kgm_statep->r[9]
set $r10 = $kgm_statep->r[10]
set $r11 = $kgm_statep->r[11]
set $r12 = $kgm_statep->r[12]
set $sp = $kgm_statep->sp
set $lr = $kgm_statep->lr
set $pc = $pc_ctx
set $r7 = $kgm_statep->r[7]
flushregs
flushstack
end
end
showcontext_int
end
document switchtoact
Syntax: switchtoact <address of activation>
| This command allows gdb to examine the execution context and call
| stack for the specified activation. For example, to view the backtrace
| for an activation issue "switchtoact <address>", followed by "bt".
| Before resuming execution, issue a "resetctx" command, to
| return to the original execution context.
end
define switchtoctx
select 0
if ($kgm_mtype == 18)
if ($kdp_act_counter == 0)
set $kdpstate = (struct savearea *) kdp.saved_state
end
set $kdp_act_counter = $kdp_act_counter + 1
set (struct savearea *) kdp.saved_state=(struct savearea *) $arg0
flushregs
flushstack
set $pc=((struct savearea *) $arg0)->save_srr0
update
else
if ($kgm_mtype == 12)
set $r0_save = $r0
set $r1_save = $r1
set $r2_save = $r2
set $r3_save = $r3
set $r4_save = $r4
set $r5_save = $r5
set $r6_save = $r6
set $r7_save = $r7
set $r8_save = $r8
set $r9_save = $r9
set $r10_save = $r10
set $r11_save = $r11
set $r12_save = $r12
set $sp_save = $sp
set $lr_save = $lr
set $pc_save = $pc
set $kgm_statep = (struct arm_saved_state *)$arg0
set $r0 = $kgm_statep->r[0]
set $r1 = $kgm_statep->r[1]
set $r2 = $kgm_statep->r[2]
set $r3 = $kgm_statep->r[3]
set $r4 = $kgm_statep->r[4]
set $r5 = $kgm_statep->r[5]
set $r6 = $kgm_statep->r[6]
set $r8 = $kgm_statep->r[8]
set $r9 = $kgm_statep->r[9]
set $r10 = $kgm_statep->r[10]
set $r11 = $kgm_statep->r[11]
set $r12 = $kgm_statep->r[12]
set $sp = $kgm_statep->sp
set $lr = $kgm_statep->lr
set $r7 = $kgm_statep->r[7]
set $pc = $kgm_statep->pc
flushregs
flushstack
update
else
echo switchtoctx not implemented for this architecture.\n
end
end
document switchtoctx
Syntax: switchtoctx <address of pcb>
| This command allows gdb to examine an execution context and dump the
| backtrace for this execution context.
| Before resuming execution, issue a "resetctx" command, to
| return to the original execution context.
end
define resetctx
select 0
if ($kdp_act_counter != 0)
if ($kgm_mtype == 18)
set (struct savearea *)kdp.saved_state=$kdpstate
flushregs
flushstack
set $pc=((struct savearea *) kdp.saved_state)->save_srr0
update
set $kdp_act_counter = 0
end
if ($kgm_mtype == 7)
set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state
set *($kdpstatep)=$kdpstate
flushregs
flushstack
set $pc=$kdpstatep->eip
update
set $kdp_act_counter = 0
end
if ($kgm_mtype == 12)
set $r0 = $r0_save
flushregs
set $r1 = $r1_save
flushregs
set $r2 = $r2_save
flushregs
set $r3 = $r3_save
flushregs
set $r4 = $r4_save
flushregs
set $r5 = $r5_save
flushregs
set $r6 = $r6_save
flushregs
set $r8 = $r8_save
flushregs
set $r9 = $r9_save
flushregs
set $r10 = $r10_save
flushregs
set $r11 = $r11_save
flushregs
set $r12 = $r12_save
flushregs
set $sp = $sp_save
flushregs
set $lr = $lr_save
flushregs
set $pc = $pc_save
flushregs
set $r7 = $r7_save
flushregs
end
showcontext_int
end
end
document resetctx
| Syntax: resetctx
| Returns to the original execution context. This command should be
| issued if you wish to resume execution after using the "switchtoact"
| or "switchtoctx" commands.
end
# This is a pre-hook for the continue command, to prevent inadvertent attempts
# to resume from the context switched to for examination.
define hook-continue
resetctx
end
# This is a pre-hook for the detach command, to prevent inadvertent attempts
# to resume from the context switched to for examination.
define hook-detach
resetctx
end
define resume_on
set noresume_on_disconnect = 0
end
document resume_on
| Syntax: resume_on
| The target system will resume when detaching or exiting from gdb.
| This is the default behavior.
end
define resume_off
set noresume_on_disconnect = 1
end
document resume_off
| Syntax: resume_off
| The target system won't resume after detaching from gdb and
| can be attached with a new gdb session
end
define paniclog
set $kgm_panic_bufptr = debug_buf
set $kgm_panic_bufptr_max = debug_buf_ptr
while $kgm_panic_bufptr < $kgm_panic_bufptr_max
if *(char *)$kgm_panic_bufptr == 10
printf "\n"
else
printf "%c", *$kgm_panic_bufptr
end
set $kgm_panic_bufptr= (char *)$kgm_panic_bufptr + 1
end
end
document paniclog
| Syntax: paniclog
| Display the panic log information
|
end
define dumpcallqueue
set $kgm_callhead = (queue_t)&$arg0
set $kgm_call = (struct call_entry *)$kgm_callhead.next
set $kgm_i = 0
while $kgm_call != $kgm_callhead
printf "0x%08x ", $kgm_call
printf "0x%08x 0x%08x ", $kgm_call->param0, $kgm_call->param1
output $kgm_call->state
printf "\t"
output $kgm_call->deadline
printf "\t"
output $kgm_call->func
printf "\n"
set $kgm_i = $kgm_i + 1
set $kgm_call = (struct call_entry *)$kgm_call->q_link.next
end
printf "%d entries\n", $kgm_i
end
document dumpcallqueue
| Syntax: dumpcallqueue <queue head>
| Displays the contents of the specified call_entry queue.
end
define showtaskacts
showtaskthreads $arg0
end
document showtaskacts
| See help showtaskthreads.
end
define showallacts
showallthreads
end
document showallacts
| See help showallthreads.
end
define resetstacks
_kgm_flush_loop
set kdp_pmap = 0
_kgm_flush_loop
resetctx
_kgm_flush_loop
_kgm_update_loop
resetctx
_kgm_update_loop
end
document resetstacks
| Syntax: resetstacks
| Internal kgmacro routine used by the "showuserstack" macro
| to reset the target pmap to the kernel pmap.
end
#Barely effective hacks to work around bugs in the "flush" and "update"
#gdb commands in Tiger (up to 219); these aren't necessary with Panther
#gdb, but do no harm.
define _kgm_flush_loop
set $kgm_flush_loop_ctr = 0
while ($kgm_flush_loop_ctr < 30)
flushregs
flushstack
set $kgm_flush_loop_ctr = $kgm_flush_loop_ctr + 1
end
end
define _kgm_update_loop
set $kgm_update_loop_ctr = 0
while ($kgm_update_loop_ctr < 30)
update
set $kgm_update_loop_ctr = $kgm_update_loop_ctr + 1
end
end
#This is necessary since gdb often doesn't do backtraces on x86 correctly
#in the absence of symbols.The code below in showuserstack and
#showx86backtrace also contains several workarouds for the gdb bug where
#gdb stops macro evaluation because of spurious "Cannot read memory"
#errors on x86. These errors appear on ppc as well, but they don't
#always stop macro evaluation.
set $kgm_cur_ebp = 0
set $kgm_cur_eip = 0
define showx86backtrace
if ($kgm_cur_ebp == 0)
set $kgm_cur_ebp = $ebp
end
if ($kgm_cur_eip == 0)
set $kgm_cur_eip = $eip
end
printf "0: EBP: 0x%08x EIP: 0x%08x\n", $kgm_cur_ebp, $kgm_cur_eip
x/i $kgm_cur_eip
set $kgm_prev_ebp = *((uint32_t *) $kgm_cur_ebp)
set $kgm_prev_eip = *((uint32_t *) ($kgm_cur_ebp + 4))
set $kgm_cur_ebp = 0
set $kgm_cur_eip = 0
set $kgm_frameno = 1
while $kgm_prev_ebp != 0
printf "%d: saved EBP: 0x%08x saved EIP: 0x%08x\n", $kgm_frameno, $kgm_prev_ebp, $kgm_prev_eip
x/i $kgm_prev_eip
set $kgm_prev_eip = *((uint32_t *) ($kgm_prev_ebp + 4))
set $kgm_prev_ebp = *((uint32_t *) $kgm_prev_ebp)
set $kgm_frameno = $kgm_frameno + 1
end
set kdp_pmap = 0
end
define showuserstack
select 0
if ($kgm_mtype == 18)
if ($kdp_act_counter == 0)
set $kdpstate = (struct savearea *) kdp.saved_state
end
set $kdp_act_counter = $kdp_act_counter + 1
set $newact = (struct thread *) $arg0
_kgm_flush_loop
set $checkpc = $newact->machine->upcb.save_srr0
if ($checkpc == 0)
echo This activation does not appear to have
echo \20 a valid user context.\n
else
set (struct savearea *) kdp.saved_state=$newact->machine->upcb
set $pc = $checkpc
#flush and update seem to be executed lazily by gdb on Tiger, hence the
#repeated invocations - see 3743135
_kgm_flush_loop
# This works because the new pmap is used only for reads
set kdp_pmap = $newact->task->map->pmap
_kgm_flush_loop
_kgm_update_loop
bt
resetstacks
_kgm_flush_loop
_kgm_update_loop
resetstacks
_kgm_flush_loop
_kgm_update_loop
end
else
if ($kgm_mtype == 7)
set $newact = (struct thread *) $arg0
#This needs to identify 64-bit processes as well
set $newiss = (x86_saved_state32_t) ($newact->machine.pcb->iss.uss.ss_32)
set $checkpc = $newiss.eip
if ($checkpc == 0)
echo This activation does not appear to have
echo \20 a valid user context.\n
else
set $kgm_cur_ebp = $newiss.ebp
set $kgm_cur_eip = $checkpc
printf "You may now issue the showx86backtrace command to see the user space backtrace for this thread (0x%08x); you can also examine memory locations in this address space (pmap 0x%08x) before issuing the backtrace. This two-step process is necessary to work around various bugs in x86 gdb, which cause it to stop memory evaluation on spurious memory read errors. Additionally, you may need to issue a set kdp_pmap = 0 command after the showx86backtrace completes, to resume reading from the kernel address space.\n", $arg0, $newact->task->map->pmap
set kdp_pmap = $newact->task->map->pmap
_kgm_flush_loop
_kgm_update_loop
end
else
echo showuserstack not supported on this architecture\n
end
end
end
document showuserstack
Syntax: showuserstack <address of thread activation>
|This command displays a numeric backtrace for the user space stack of
|the given thread activation. It may, of course, fail to display a
|complete backtrace if portions of the user stack are not mapped in.
|Symbolic backtraces can be obtained either by running gdb on the
|user space binary, or a tool such as "symbolicate".
|Note that while this command works on Panther's gdb, an issue
|with Tiger gdb (3743135) appears to hamper the evaluation of this
|macro in some cases.
end
#Stopgap until gdb can generate the HOSTREBOOT packet
define kdp-reboot
#Alternatively, set *(*(unsigned **) 0x2498) = 1 (or 0x5498 on PPC)
set flag_kdp_trigger_reboot = 1
continue
end
document kdp-reboot
Syntax: kdp-reboot
|Reboot the remote target machine; not guaranteed to succeed. Requires symbols
|until gdb support for the HOSTREBOOT packet is implemented.
end
define sendcore
set kdp_trigger_core_dump = 1
set kdp_flag |= 0x40
set panicd_ip_str = "$arg0"
set panicd_specified = 1
set disable_debug_output = 0
set disableConsoleOutput = 0
set logPanicDataToScreen = 1
set reattach_wait = 1
resume_off
end
document sendcore
Syntax: sendcore <IP address>
|Configure the kernel to transmit a kernel coredump to a server (kdumpd)
|at the specified IP address. This is useful when the remote target has
|not been previously configured to transmit coredumps, and you wish to
|preserve kernel state for later examination. NOTE: You must issue a "continue"
|command after using this macro to trigger the kernel coredump. The kernel
|will resume waiting in the debugger after completion of the coredump. You
|may disable coredumps by executing the "disablecore" macro.
end
define disablecore
set kdp_trigger_core_dump = 0
set kdp_flag |= 0x40
set kdp_flag &= ~0x10
set panicd_specified = 0
end
document disablecore
Syntax: disablecore
|Reconfigures the kernel so that it no longer transmits kernel coredumps. This
|complements the "sendcore" macro, but it may be used if the kernel has been
|configured to transmit coredumps through boot-args as well.
end
define switchtocorethread
set $newact = (struct thread *) $arg0
select 0
if ($newact->kernel_stack == 0)
echo This thread does not have a stack.\n
echo continuation:
output/a (unsigned) $newact.continuation
echo \n
else
if ($kgm_mtype == 18)
loadcontext $newact->machine->pcb
flushstack
set $pc = $newact->machine->pcb.save_srr0
else
if ($kgm_mtype == 7)
set $kgm_cstatep = (struct x86_kernel_state32 *) \
($newact->kernel_stack + 0x4000 \
- sizeof(struct x86_kernel_state32))
loadcontext $kgm_cstatep
flushstack
else
echo switchtocorethread not supported on this architecture\n
end
end
showcontext_int
end
end
document switchtocorethread
Syntax: switchtocorethread <address of activation>
| The corefile equivalent of "switchtoact". When debugging a kernel coredump
| file, this command can be used to examine the execution context and stack
| trace for a given thread activation. For example, to view the backtrace
| for a thread issue "switchtocorethread <address>", followed by "bt".
| Before resuming execution, issue a "resetcorectx" command, to
| return to the original execution context. Note that this command
| requires gdb support, as documented in Radar 3401283.
end
define loadcontext
select 0
if ($kgm_mtype == 18)
set $kgm_contextp = (struct savearea *) $arg0
set $pc = $kgm_contextp.save_srr0
set $r1 = $kgm_contextp.save_r1
set $lr = $kgm_contextp.save_lr
set $r2 = $kgm_contextp.save_r2
set $r3 = $kgm_contextp.save_r3
set $r4 = $kgm_contextp.save_r4
set $r5 = $kgm_contextp.save_r5
set $r6 = $kgm_contextp.save_r6
set $r7 = $kgm_contextp.save_r7
set $r8 = $kgm_contextp.save_r8
set $r9 = $kgm_contextp.save_r9
set $r10 = $kgm_contextp.save_r10
set $r11 = $kgm_contextp.save_r11
set $r12 = $kgm_contextp.save_r12
set $r13 = $kgm_contextp.save_r13
set $r14 = $kgm_contextp.save_r14
set $r15 = $kgm_contextp.save_r15
set $r16 = $kgm_contextp.save_r16
set $r17 = $kgm_contextp.save_r17
set $r18 = $kgm_contextp.save_r18
set $r19 = $kgm_contextp.save_r19
set $r20 = $kgm_contextp.save_r20
set $r21 = $kgm_contextp.save_r21
set $r22 = $kgm_contextp.save_r22
set $r23 = $kgm_contextp.save_r23
set $r24 = $kgm_contextp.save_r24
set $r25 = $kgm_contextp.save_r25
set $r26 = $kgm_contextp.save_r26
set $r27 = $kgm_contextp.save_r27
set $r28 = $kgm_contextp.save_r28
set $r29 = $kgm_contextp.save_r29
set $r30 = $kgm_contextp.save_r30
set $r31 = $kgm_contextp.save_r31
set $cr = $kgm_contextp.save_cr
set $ctr = $kgm_contextp.save_ctr
else
if ($kgm_mtype == 7)
set $kgm_contextp = (struct x86_kernel_state32 *) $arg0
set $ebx = $kgm_contextp->k_ebx
set $ebp = $kgm_contextp->k_ebp
set $edi = $kgm_contextp->k_edi
set $esi = $kgm_contextp->k_esi
set $eip = $kgm_contextp->k_eip
set $pc = $kgm_contextp->k_eip
else
echo loadcontext not supported on this architecture\n
end
end
end
define resetcorectx
select 0
if ($kgm_mtype == 18)
set $kgm_corecontext = (struct savearea *) kdp.saved_state
loadcontext $kgm_corecontext
else
if ($kgm_mtype == 7)
set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state
set $ebx = $kdpstatep->ebx
set $ebp = $kdpstatep->ebp
set $edi = $kdpstatep->edi
set $esi = $kdpstatep->esi
set $eip = $kdpstatep->eip
set $eax = $kdpstatep->eax
set $ecx = $kdpstatep->ecx
set $edx = $kdpstatep->edx
flushregs
flushstack
set $pc = $kdpstatep->eip
update
else
echo resetcorectx not supported on this architecture\n
end
end
showcontext_int
end
document resetcorectx
Syntax: resetcorectx
| The corefile equivalent of "resetctx". Returns to the original
| execution context (that of the active thread at the time of the NMI or
| panic). This command should be issued if you wish to resume
| execution after using the "switchtocorethread" command.
end
#Helper function for "showallgdbstacks"
define showgdbthread
printf " 0x%08x ", $arg0
set $kgm_thread = *(struct thread *)$arg0
printf "0x%08x ", $arg0
printf "%3d ", $kgm_thread.sched_pri
set $kgm_state = $kgm_thread.state
if $kgm_state & 0x80
printf "I"
end
if $kgm_state & 0x40
printf "P"
end
if $kgm_state & 0x20
printf "A"
end
if $kgm_state & 0x10
printf "H"
end
if $kgm_state & 0x08
printf "U"
end
if $kgm_state & 0x04
printf "R"
end
if $kgm_state & 0x02
printf "S"
end
if $kgm_state & 0x01
printf "W\t"
printf "0x%08x ", $kgm_thread.wait_queue
output /a (unsigned) $kgm_thread.wait_event
if ($kgm_thread.uthread != 0)
set $kgm_uthread = (struct uthread *)$kgm_thread.uthread
if ($kgm_uthread->uu_wmesg != 0)
printf " \"%s\"", $kgm_uthread->uu_wmesg
end
end
end
if $arg1 != 0
if ($kgm_thread.kernel_stack != 0)
if ($kgm_thread.reserved_stack != 0)
printf "\n\t\treserved_stack=0x%08x", $kgm_thread.reserved_stack
end
printf "\n\t\tkernel_stack=0x%08x", $kgm_thread.kernel_stack
if ($kgm_mtype == 18)
set $mysp = $kgm_thread.machine.pcb->save_r1
end
if ($kgm_mtype == 7)
set $kgm_statep = (struct x86_kernel_state32 *) \
($kgm_thread->kernel_stack + 0x4000 \
- sizeof(struct x86_kernel_state32))
set $mysp = $kgm_statep->k_ebp
end
if ($kgm_mtype == 12)
if ($arg0 == $r9)
set $mysp = $r7
else
set $kgm_statep = (struct arm_saved_state *)$kgm_thread.machine.kstackptr
set $mysp = $kgm_statep->r[7]
end
end
set $prevsp = 0
printf "\n\t\tstacktop=0x%08x", $mysp
if ($arg2 == 0)
switchtoact $arg0
else
switchtocorethread $arg0
end
bt
else
printf "\n\t\t\tcontinuation="
output /a (unsigned) $kgm_thread.continuation
end
printf "\n"
else
printf "\n"
end
end
#Use of this macro is currently (8/04) blocked by the fact that gdb
#stops evaluating macros when encountering an error, such as a failure
#to read memory from a certain location. Until this issue (described in
#3758949) is addressed, evaluation of this macro may stop upon
#encountering such an error.
define showallgdbstacks
set $kgm_head_taskp = &tasks
set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
while $kgm_taskp != $kgm_head_taskp
showtaskheader
showtaskint $kgm_taskp
set $kgm_head_actp = &($kgm_taskp->threads)
set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
while $kgm_actp != $kgm_head_actp
showactheader
showgdbthread $kgm_actp 1 0
set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
end
printf "\n"
set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
end
resetctx
end
document showallgdbstacks
Syntax: showallgdbstacks
| An alternative to "showallstacks". Iterates through the task list and
| displays a gdb generated backtrace for each kernel thread. It is
| advantageous in that it is much faster than "showallstacks", and
| decodes function call arguments and displays source level traces, but
| it has the drawback that it doesn't determine if frames belong to
| functions from kernel extensions, as with "showallstacks".
| This command may terminate prematurely because of a gdb bug
| (Radar 3758949), which stops macro evaluation on memory read
| errors.
end
define showallgdbcorestacks
select 0
set $kgm_head_taskp = &tasks
set $kgm_taskp = (struct task *)($kgm_head_taskp->next)
while $kgm_taskp != $kgm_head_taskp
showtaskheader
showtaskint $kgm_taskp
set $kgm_head_actp = &($kgm_taskp->threads)
set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
while $kgm_actp != $kgm_head_actp
showactheader
showgdbthread $kgm_actp 1 1
set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
end
printf "\n"
set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next)
end
resetcorectx
end
document showallgdbcorestacks
Syntax: showallgdbcorestacks
|Corefile version of "showallgdbstacks"
end
define switchtouserthread
select 0
if ($kgm_mtype == 18)
if ($kdp_act_counter == 0)
set $kdpstate = (struct savearea *) kdp.saved_state
end
set $kdp_act_counter = $kdp_act_counter + 1
set $newact = (struct thread *) $arg0
_kgm_flush_loop
set $checkpc = $newact->machine->upcb.save_srr0
if ($checkpc == 0)
echo This activation does not appear to have
echo \20 a valid user context.\n
else
set (struct savearea *) kdp.saved_state=$newact->machine->upcb
set $pc = $checkpc
#flush and update seem to be executed lazily by gdb on Tiger, hence the
#repeated invocations - see 3743135
_kgm_flush_loop
# This works because the new pmap is used only for reads
set kdp_pmap = $newact->task->map->pmap
_kgm_flush_loop
_kgm_update_loop
end
else
echo switchtouserthread not implemented for this architecture.\n
end
end
document switchtouserthread
Syntax: switchtouserthread <address of thread>
| Analogous to switchtoact, but switches to the user context of a
| specified thread address. Similar to the "showuserstack"
| command, but this command does not return gdb to the kernel context
| immediately. This is to assist with the following (rather risky)
| manoeuvre - upon switching to the user context and virtual address
| space, the user may choose to call remove-symbol-file on the
| mach_kernel symbol file, and then add-symbol-file on the user space
| binary's symfile. gdb can then generate symbolic backtraces
| for the user space thread. To return to the
| kernel context and virtual address space, the process must be
| reversed, i.e. call remove-symbol-file on the user space symbols, and
| then add-symbol-file on the appropriate mach_kernel, and issue the
| "resetstacks" command. Note that gdb may not react kindly to all these
| symbol file switches. The same restrictions that apply to "showuserstack"
| apply here - pages that have been paged out cannot be read while in the
| debugger context, so backtraces may terminate early.
| If the virtual addresses in the stack trace do not conflict with those
| of symbols in the kernel's address space, it may be sufficient to
| just do an add-symbol-file on the user space binary's symbol file.
| Note that while this command works on Panther's gdb, an issue
| with Tiger gdb (3743135) appears to hamper the evaluation of this
| macro in some cases.
end
define showmetaclass
set $kgm_metaclassp = (OSMetaClass *)$arg0
printf "%-5d", $kgm_metaclassp->instanceCount
printf "x %5d bytes", $kgm_metaclassp->classSize
printf " %s\n", $kgm_metaclassp->className->string
end
define showstring
printf "\"%s\"", ((OSString *)$arg0)->string
end
define shownumber
printf "%lld", ((OSNumber *)$arg0)->value
end
define showboolean
if ($arg0 == gOSBooleanFalse)
printf "No"
else
printf "Yes"
end
end
define showdata
set $kgm_data = (OSData *)$arg0
printf "<"
set $kgm_datap = (const unsigned char *) $kgm_data->data
set $kgm_printstr = 0
if (0 == (3 & (unsigned int)$kgm_datap) && ($kgm_data->length >= 3))
set $kgm_bytes = *(unsigned int *) $kgm_datap
if (0xffff0000 & $kgm_bytes)
set $kgm_idx = 0
set $kgm_printstr = 1
while ($kgm_idx++ < 4)
set $kgm_bytes = $kgm_bytes >> 8
set $kgm_char = 0xff & $kgm_bytes
if ($kgm_char && (($kgm_char < 0x20) || ($kgm_char > 0x7e)))
set $kgm_printstr = 0
end
end
end
end
set $kgm_idx = 0
if ($kgm_printstr)
set $kgm_quoted = 0
while ($kgm_idx < $kgm_data->length)
set $kgm_char = $kgm_datap[$kgm_idx++]
if ($kgm_char)
if (0 == $kgm_quoted)
set $kgm_quoted = 1
if ($kgm_idx > 1)
printf ",\""
else
printf "\""
end
end
printf "%c", $kgm_char
else
if ($kgm_quoted)
set $kgm_quoted = 0
printf "\""
end
end
end
if ($kgm_quoted)
printf "\""
end
else
if (0 == (3 & (unsigned int)$kgm_datap))
while (($kgm_idx + 3) <= $kgm_data->length)
printf "%08x", *(unsigned int *) &$kgm_datap[$kgm_idx]
set $kgm_idx = $kgm_idx + 4
end
end
while ($kgm_idx < $kgm_data->length)
printf "%02x", $kgm_datap[$kgm_idx++]
end
end
printf ">"
end
define showdictionaryint
set $kgm$arg0_dict = (OSDictionary *)$arg1
printf "{"
set $kgm$arg0_idx = 0
while ($kgm$arg0_idx < $kgm$arg0_dict->count)
set $kgm_obj = $kgm$arg0_dict->dictionary[$kgm$arg0_idx].key
showobjectint _$arg0 $kgm_obj
printf "="
set $kgm_obj = $kgm$arg0_dict->dictionary[$kgm$arg0_idx++].value
showobjectint _$arg0 $kgm_obj
if ($kgm$arg0_idx < $kgm$arg0_dict->count)
printf ","
end
end
printf "}"
end
define indent
set $kgm_idx = 0
while ($kgm_idx < $arg0)
if ($arg1 & (1 << $kgm_idx++))
printf "| "
else
printf " "
end
end
end
define showregdictionary
indent $kgm_reg_depth+2 $arg1
printf "{\n"
set $kgm_reg_idx = 0
while ($kgm_reg_idx < $arg0->count)
indent $kgm_reg_depth+2 $arg1
printf " "
set $kgm_obj = $arg0->dictionary[$kgm_reg_idx].key
showobjectint _ $kgm_obj
printf " = "
set $kgm_obj = $arg0->dictionary[$kgm_reg_idx++].value
showobjectint _ $kgm_obj
printf "\n"
end
indent $kgm_reg_depth+2 $arg1
printf "}\n"
end
define showarraysetint
set $kgm$arg0_array = (OSArray *)$arg1
set $kgm$arg0_idx = 0
while ($kgm$arg0_idx < $kgm$arg0_array->count)
set $kgm_obj = $kgm$arg0_array->array[$kgm$arg0_idx++]
showobjectint _$arg0 $kgm_obj
if ($kgm$arg0_idx < $kgm$arg0_array->count)
printf ","
end
end
end
define showarrayint
printf "("
showarraysetint $arg0 $arg1
printf ")"
end
define showsetint
set $kgm_array = ((OSSet *)$arg1)->members
printf "["
showarraysetint $arg0 $kgm_array
printf "]"
end
define showobjectint
set $kgm_obj = (OSObject *) $arg1
set $kgm_vt = *((void **) $arg1)
if ($kgm_mtype == 12)
set $kgm_vt = $kgm_vt - 2 * sizeof(void *)
end
if ($kgm_show_object_addrs)
printf "`object %p, vt ", $arg1
output /a (unsigned) $kgm_vt
if ($kgm_show_object_retain)
printf ", retain count %d, container retain %d", (0xffff & $kgm_obj->retainCount), $kgm_obj->retainCount >> 16
end
printf "` "
end
if ($kgm_vt == _ZTV8OSString)
showstring $arg1
else
if ($kgm_vt == _ZTV8OSSymbol)
showstring $arg1
else
if ($kgm_vt == _ZTV8OSNumber)
shownumber $arg1
else
if ($kgm_vt == _ZTV6OSData)
showdata $arg1
else
if ($kgm_vt == _ZTV9OSBoolean)
showboolean $arg1
else
if ($kgm_vt == _ZTV12OSDictionary)
showdictionaryint _$arg0 $arg1
else
if ($kgm_vt == _ZTV7OSArray)
showarrayint _$arg0 $arg1
else
if ($kgm_vt == _ZTV5OSSet)
showsetint _$arg0 $arg1
else
if ($kgm_show_object_addrs == 0)
printf "`object %p, vt ", $arg1
output /a (unsigned) $kgm_vt
printf "`"
end
end
end
end
end
end
end
end
end
end
define showobject
set $kgm_save = $kgm_show_object_addrs
set $kgm_show_object_addrs = 1
set $kgm_show_object_retain = 1
showobjectint _ $arg0
set $kgm_show_object_addrs = $kgm_save
set $kgm_show_object_retain = 0
printf "\n"
end
document showobject
Syntax: (gdb) showobject <object address>
| Show info about an OSObject - its vtable ptr and retain count.
| If the object is a simple container class, more info will be shown.
end
define dictget
set $kgm_dictp = (OSDictionary *)$arg0
set $kgm_keyp = (const OSSymbol *)$arg1
set $kgm_idx = 0
set $kgm_result = 0
while (($kgm_idx < $kgm_dictp->count) && ($kgm_result == 0))
if ($kgm_keyp == $kgm_dictp->dictionary[$kgm_idx].key)
set $kgm_result = $kgm_dictp->dictionary[$kgm_idx].value
end
set $kgm_idx = $kgm_idx + 1
end
end
define showregistryentryrecurse
set $kgm_re = (IOService *)$arg1
set $kgm$arg0_stack = (unsigned long long) $arg2
if ($arg3)
set $kgm$arg0_stack = $kgm$arg0_stack | (1ULL << $kgm_reg_depth)
else
set $kgm$arg0_stack = $kgm$arg0_stack & ~(1ULL << $kgm_reg_depth)
end
dictget $kgm_re->fRegistryTable $kgm_childkey
set $kgm$arg0_child_array = (OSArray *) $kgm_result
if ($kgm$arg0_child_array)
set $kgm$arg0_child_count = $kgm$arg0_child_array->count
else
set $kgm$arg0_child_count = 0
end
if ($kgm$arg0_child_count)
set $kgm$arg0_stack = $kgm$arg0_stack | (2ULL << $kgm_reg_depth)
else
set $kgm$arg0_stack = $kgm$arg0_stack & ~(2ULL << $kgm_reg_depth)
end
indent $kgm_reg_depth $kgm$arg0_stack
printf "+-o "
dictget $kgm_re->fRegistryTable $kgm_namekey
if ($kgm_result == 0)
dictget $kgm_re->fRegistryTable gIONameKey
end
if ($kgm_result == 0)
dictget $kgm_re->fPropertyTable gIOClassKey
end
if ($kgm_result != 0)
printf "%s", ((OSString *)$kgm_result)->string
else
if (((IOService*)$kgm_re)->pwrMgt && ((IOService*)$kgm_re)->pwrMgt->Name)
printf "%s", ((IOService*)$kgm_re)->pwrMgt->Name
else
# printf ", guessclass "
# guessclass $kgm_re
printf "??"
end
end
printf " <object %p, ", $kgm_re
printf "vtable "
set $kgm_vt = (unsigned) *(void**) $kgm_re
if ($kgm_mtype == 12)
set $kgm_vt = $kgm_vt - 2 * sizeof(void *)
end
output /a $kgm_vt
if ($kgm_vt != _ZTV15IORegistryEntry)
printf ", "
set $kgm_state = $kgm_re->__state[0]
# kIOServiceRegisteredState
if (0 == ($kgm_state & 2))
printf "!"
end
printf "registered, "
# kIOServiceMatchedState
if (0 == ($kgm_state & 4))
printf "!"
end
printf "matched, "
# kIOServiceInactiveState
if ($kgm_state & 1)
printf "in"
end
printf "active, busy %d, retain count %d", (0xff & $kgm_re->__state[1]), (0xffff & $kgm_re->retainCount)
end
printf ">\n"
if ($kgm_show_props)
set $kgm_props = $kgm_re->fPropertyTable
showregdictionary $kgm_props $kgm$arg0_stack
end
# recurse
if ($kgm$arg0_child_count != 0)
set $kgm_reg_depth = $kgm_reg_depth + 1
set $kgm$arg0_child_idx = 0
while ($kgm$arg0_child_idx < $kgm$arg0_child_count)
set $kgm_re = $kgm$arg0_child_array->array[$kgm$arg0_child_idx++]
set $kgm_more_sib = ($kgm$arg0_child_idx < $kgm$arg0_child_count)
showregistryentryrecurse _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib
end
set $kgm_reg_depth = $kgm_reg_depth - 1
end
end
define showregistryentryint
set $kgm_namekey = (OSSymbol *) $kgm_reg_plane[2]
set $kgm_childkey = (OSSymbol *) $kgm_reg_plane[4]
showregistryentryrecurse _ $arg0 0 0
end
define showregistry
set $kgm_reg_depth = 0
set $kgm_show_props = 0
showregistryentryint gRegistryRoot
end
document showregistry
Syntax: (gdb) showregistry
| Show info about all registry entries in the current plane.
end
define showregistryprops
set $kgm_reg_depth = 0
set $kgm_show_props = 1
showregistryentryint gRegistryRoot
end
document showregistryprops
Syntax: (gdb) showregistryprops
| Show info about all registry entries in the current plane, and their properties.
| set $kgm_show_object_addrs = 1 and/or set $kgm_show_object_retain = 1 will display
| more verbose information
end
define showregistryentry
set $kgm_reg_depth = 0
set $kgm_show_props = 1
showregistryentryint $arg0
end
document showregistryentry
Syntax: (gdb) showregistryentry <object address>
| Show info about a registry entry; its properties and descendants in the current plane.
end
define setregistryplane
if ($arg0)
set $kgm_reg_plane = (void **) $arg0
else
showobjectint _ gIORegistryPlanes
printf "\n"
end
end
document setregistryplane
Syntax: (gdb) setregistryplane <plane object address>
| Set the plane to be used for the iokit registry macros. An argument of zero will
| display known planes.
end
define guessclass
set $kgm_classidx = 0
set $kgm_lookvt = *((void **) $arg0)
set $kgm_bestvt = (void *) 0
set $kgm_bestidx = 0
while $kgm_classidx < sAllClassesDict->count
set $kgm_meta = (OSMetaClass *) sAllClassesDict->dictionary[$kgm_classidx].value
set $kgm_vt = *((void **) $kgm_meta)
if (($kgm_vt > $kgm_bestvt) && ($kgm_vt < $kgm_lookvt))
set $kgm_bestvt = $kgm_vt
set $kgm_bestidx = $kgm_classidx
end
set $kgm_classidx = $kgm_classidx + 1
end
printf "%s", sAllClassesDict->dictionary[$kgm_bestidx].key->string
end
define showallclasses
set $kgm_classidx = 0
while $kgm_classidx < sAllClassesDict->count
set $kgm_meta = (OSMetaClass *) sAllClassesDict->dictionary[$kgm_classidx++].value
showmetaclass $kgm_meta
end
end
document showallclasses
Syntax: (gdb) showallclasses
| Show the instance counts and ivar size of all OSObject subclasses. See ioclasscount man page for details.
end
define showioalloc
printf " Instance allocation = 0x%08lx = %4ld K\n", (int) debug_ivars_size, ((int) debug_ivars_size) / 1024
printf "Container allocation = 0x%08lx = %4ld K\n", (int) debug_container_malloc_size, ((int) debug_container_malloc_size) / 1024
printf " IOMalloc allocation = 0x%08lx = %4ld K\n", (int) debug_iomalloc_size, ((int) debug_iomalloc_size) / 1024
printf " Pageable allocation = 0x%08lx = %4ld K\n", (vm_size_t) debug_iomallocpageable_size, ((vm_size_t) debug_iomallocpageable_size) / 1024
end
document showioalloc
Syntax: (gdb) showioalloc
| Show some accounting of memory allocated by IOKit allocators. See ioalloccount man page for details.
end
define showosobjecttracking
set $kgm_next = (OSObjectTracking *) gOSObjectTrackList.next
while $kgm_next != &gOSObjectTrackList
set $obj = (OSObject *) ($kgm_next+1)
showobject $obj
set $kgm_idx = 0
while $kgm_idx < (sizeof($kgm_next->bt) / sizeof($kgm_next->bt[0]))
if ((unsigned) $kgm_next->bt[$kgm_idx] > (unsigned) sectPRELINKB)
showkmodaddr $kgm_next->bt[$kgm_idx]
printf "\n"
else
if ((unsigned) $kgm_next->bt[$kgm_idx] > 0)
output /a (unsigned) $kgm_next->bt[$kgm_idx]
printf "\n"
end
end
set $kgm_idx = $kgm_idx + 1
end
printf "\n"
set $kgm_next = (OSObjectTracking *) $kgm_next->link.next
end
end
document showosobjecttracking
Syntax: (gdb) showosobjecttracking
| Show the list of tracked OSObject allocations with backtraces.
| Boot with the kOSTraceObjectAlloc (0x00400000) io debug flag set.
| Set gOSObjectTrackThread to 1 or a thread_t to capture new OSObjects allocated by a thread or all threads.
end
define readphys
set kdp_trans_off = 1
x/x $arg0
set kdp_trans_off = 0
end
define readphys64
if ($kgm_mtype == 18)
set kdp_src_high32 = ((uint32_t) ($arg0)) >> 32
x/x (uint32_t) (($arg0) & 0x00000000ffffffffUL)
set kdp_src_high32 = 0
else
echo readphys64 not available on this architecture.\n
end
end
document readphys
| The argument is interpreted as a physical address, and the word addressed is
| displayed. While this fails if no physical page exists at the given address,
| it must be used with caution.
end
document readphys64
| The argument is interpreted as a 64-bit physical address, and the word
| addressed is displayed. While this fails if no physical page exists at the
| given address, it must be used with caution.
end
define addkextsyms
shell ls $arg0/* | xargs -n 1 echo add-symbol-file > /tmp/gdb-syms
source /tmp/gdb-syms
set $kgm_show_kmod_syms = 1
end
document addkextsyms
| Takes a directory of symbols for kexts generated with kextcache -y and loads them
| into gdb.
| (gdb) addkextsyms /path/to/symboldir
end
define showprocfiles
if ($argc == 1)
_showprocheader
_showprocfiles $arg0
else
printf "| Usage:\n|\n"
help showprocfiles
end
end
document showprocfiles
Syntax: (gdb) showprocfiles <proc_t>
| Given a proc_t pointer, display the list of open file descriptors for the
| referenced process.
end
define _showprocheader
printf "fd fileglob fg flags fg type fg data info\n"
printf "----- ---------- ---------- -------- ---------- -------------------\n"
end
define _showprocfiles
set $kgm_spf_filedesc = ((proc_t)$arg0)->p_fd
set $kgm_spf_last = $kgm_spf_filedesc->fd_lastfile
set $kgm_spf_ofiles = $kgm_spf_filedesc->fd_ofiles
set $kgm_spf_count = 0
while ($kgm_spf_count <= $kgm_spf_last)
if ($kgm_spf_ofiles[$kgm_spf_count] == 0)
# DEBUG: For files that were open, but are now closed
# printf "%-5d FILEPROC_NULL\n", $kgm_spf_count
else
# display fd #, fileglob address, fileglob flags
set $kgm_spf_flags = $kgm_spf_ofiles[$kgm_spf_count].f_flags
set $kgm_spf_fg = $kgm_spf_ofiles[$kgm_spf_count].f_fglob
printf "%-5d 0x%08x 0x%08x ", $kgm_spf_count, $kgm_spf_fg, $kgm_spf_flags
# decode fileglob type
set $kgm_spf_fgt = $kgm_spf_fg->fg_type
if ($kgm_spf_fgt == 1)
printf "VNODE "
end
if ($kgm_spf_fgt == 2)
printf "SOCKET "
end
if ($kgm_spf_fgt == 3)
printf "PSXSHM "
end
if ($kgm_spf_fgt == 4)
printf "PSXSEM "
end
if ($kgm_spf_fgt == 5)
printf "KQUEUE "
end
if ($kgm_spf_fgt == 6)
printf "PIPE "
end
if ($kgm_spf_fgt == 7)
printf "FSEVENTS"
end
if ($kgm_spf_fgt < 1 || $kgm_spf_fgt > 7)
printf "?: %-5d", $kgm_spf_fgt
end
# display fileglob data address and decode interesting fact(s)
# about data, if we know any
set $kgm_spf_fgd = $kgm_spf_fg->fg_data
printf " 0x%08x ", $kgm_spf_fgd
if ($kgm_spf_fgt == 1)
set $kgm_spf_name = ((struct vnode *)$kgm_spf_fgd)->v_name
if ($kgm_spf_name == 0)
printf "(null)"
else
printf "%s", $kgm_spf_name
end
end
printf "\n"
end
set $kgm_spf_count = $kgm_spf_count + 1
end
end
#
# Show all the advisory file locks held by a process for each of the vnode
# type files that it has open; do this by walking the per process open file
# table and looking at any vnode type fileglob that has a non-NULL lock list
# associated with it.
#
define showproclocks
if ($argc == 1)
_showproclocks $arg0
else
printf "| Usage:\n|\n"
help showproclocks
end
end
document showproclocks
Syntax: (gdb) showproclocks <proc_t>
| Given a proc_t pointer, display the list of advisory file locks held by the
| referenced process.
end
define _showproclocks
set $kgm_spl_filedesc = ((proc_t)$arg0)->p_fd
set $kgm_spl_last = $kgm_spl_filedesc->fd_lastfile
set $kgm_spl_ofiles = $kgm_spl_filedesc->fd_ofiles
set $kgm_spl_count = 0
set $kgm_spl_seen = 0
while ($kgm_spl_count <= $kgm_spl_last)
if ($kgm_spl_ofiles[$kgm_spl_count] == 0)
# DEBUG: For files that were open, but are now closed
# printf "%-5d FILEPROC_NULL\n", $kgm_spl_count
else
set $kgm_spl_fg = $kgm_spl_ofiles[$kgm_spl_count].f_fglob
# decode fileglob type
set $kgm_spl_fgt = $kgm_spl_fg->fg_type
if ($kgm_spl_fgt == 1)
set $kgm_spl_fgd = $kgm_spl_fg->fg_data
set $kgm_spl_name = ((struct vnode *)$kgm_spl_fgd)->v_name
set $kgm_spl_vnode = ((vnode_t)$kgm_spl_fgd)
set $kgm_spl_lockiter = $kgm_spl_vnode->v_lockf
if ($kgm_spl_lockiter != 0)
if ($kgm_spl_seen == 0)
_showvnodelockheader
end
set $kgm_spl_seen = $kgm_spl_seen + 1
printf "( fd %d, name ", $kgm_spl_count
if ($kgm_spl_name == 0)
printf "(null) )"
else
printf "%s )\n", $kgm_spl_name
end
_showvnodelocks $kgm_spl_fgd
end
end
end
set $kgm_spl_count = $kgm_spf_count + 1
end
printf "%d total locks for 0x%08x\n", $kgm_spl_seen, $arg0
end
define showprocinfo
set $kgm_spi_proc = (proc_t)$arg0
printf "Process 0x%08x\n", $kgm_spi_proc
printf " name %s\n", $kgm_spi_proc->p_comm
printf " pid:%.8d", $kgm_spi_proc->p_pid
printf " task:0x%.8x", $kgm_spi_proc->task
printf " p_stat:%.1d", $kgm_spi_proc->p_stat
printf " parent pid:%.8d", $kgm_spi_proc->p_ppid
# decode part of credential
set $kgm_spi_cred = $kgm_spi_proc->p_ucred
if ($kgm_spi_cred != 0)
printf "Cred: euid %d ruid %d svuid %d\n", $kgm_spi_cred->cr_uid, $kgm_spi_cred->cr_ruid, $kgm_spi_cred->cr_svuid
else
printf "Cred: (null)\n"
end
# decode flags
set $kgm_spi_flag = $kgm_spi_proc->p_flag
printf "Flags: 0x%08x\n", $kgm_spi_flag
if ($kgm_spi_flag & 0x00000001)
printf " 0x00000001 - may hold advisory locks\n"
end
if ($kgm_spi_flag & 0x00000002)
printf " 0x00000002 - has a controlling tty\n"
end
if ($kgm_spi_flag & 0x00000004)
printf " 0x00000004 - process is 64 bit\n"
else
printf " !0x00000004 - process is 32 bit\n"
end
if ($kgm_spi_flag & 0x00000008)
printf " 0x00000008 - no SIGCHLD on child stop\n"
end
if ($kgm_spi_flag & 0x00000010)
printf " 0x00000010 - waiting for child exec/exit\n"
end
if ($kgm_spi_flag & 0x00000020)
printf " 0x00000020 - has started profiling\n"
end
if ($kgm_spi_flag & 0x00000040)
printf " 0x00000040 - in select; wakeup/waiting danger\n"
end
if ($kgm_spi_flag & 0x00000080)
printf " 0x00000080 - was stopped and continued\n"
end
if ($kgm_spi_flag & 0x00000100)
printf " 0x00000100 - has set privileges since exec\n"
end
if ($kgm_spi_flag & 0x00000200)
printf " 0x00000200 - system process: no signals, stats, or swap\n"
end
if ($kgm_spi_flag & 0x00000400)
printf " 0x00000400 - timing out during a sleep\n"
end
if ($kgm_spi_flag & 0x00000800)
printf " 0x00000800 - debugged process being traced\n"
end
if ($kgm_spi_flag & 0x00001000)
printf " 0x00001000 - debugging process has waited for child\n"
end
if ($kgm_spi_flag & 0x00002000)
printf " 0x00002000 - exit in progress\n"
end
if ($kgm_spi_flag & 0x00004000)
printf " 0x00004000 - process has called exec\n"
end
if ($kgm_spi_flag & 0x00008000)
printf " 0x00008000 - owe process an addupc() XXX\n"
end
if ($kgm_spi_flag & 0x00010000)
printf " 0x00010000 - affinity for Rosetta children\n"
end
if ($kgm_spi_flag & 0x00020000)
printf " 0x00020000 - wants to run Rosetta\n"
end
if ($kgm_spi_flag & 0x00040000)
printf " 0x00040000 - has wait() in progress\n"
end
if ($kgm_spi_flag & 0x00080000)
printf " 0x00080000 - kdebug tracing on for this process\n"
end
if ($kgm_spi_flag & 0x00100000)
printf " 0x00100000 - blocked due to SIGTTOU or SIGTTIN\n"
end
if ($kgm_spi_flag & 0x00200000)
printf " 0x00200000 - has called reboot()\n"
end
if ($kgm_spi_flag & 0x00400000)
printf " 0x00400000 - is TBE state\n"
end
if ($kgm_spi_flag & 0x00800000)
printf " 0x00800000 - signal exceptions\n"
end
if ($kgm_spi_flag & 0x01000000)
printf " 0x01000000 - being branch traced\n"
end
if ($kgm_spi_flag & 0x02000000)
printf " 0x02000000 - has vfork() children\n"
end
if ($kgm_spi_flag & 0x04000000)
printf " 0x04000000 - not allowed to attach\n"
end
if ($kgm_spi_flag & 0x08000000)
printf " 0x08000000 - vfork() in progress\n"
end
if ($kgm_spi_flag & 0x10000000)
printf " 0x10000000 - no shared libraries\n"
end
if ($kgm_spi_flag & 0x20000000)
printf " 0x20000000 - force quota for root\n"
end
if ($kgm_spi_flag & 0x40000000)
printf " 0x40000000 - no zombies when children exit\n"
end
if ($kgm_spi_flag & 0x80000000)
printf " 0x80000000 - don't hang on remote FS ops\n"
end
# decode state
set $kgm_spi_state = $kgm_spi_proc->p_stat
printf "State: "
if ($kgm_spi_state == 1)
printf "Idle\n"
end
if ($kgm_spi_state == 2)
printf "Run\n"
end
if ($kgm_spi_state == 3)
printf "Sleep\n"
end
if ($kgm_spi_state == 4)
printf "Stop\n"
end
if ($kgm_spi_state == 5)
printf "Zombie\n"
end
if ($kgm_spi_state == 6)
printf "Reaping\n"
end
if ($kgm_spi_state < 1 || $kgm_spi_state > 6)
printf "(Unknown)\n"
end
end
document showprocinfo
Syntax: (gdb) showprocinfo <proc_t>
| Displays name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields.
end
#
# dump the zombprocs
#
define zombproc
set $basep = (struct proc *)zombproc->lh_first
set $pp = $basep
while $pp
showprocinfo $pp
set $pp = $pp->p_list.le_next
end
end
document zombproc
Syntax: (gdb) zombproc
| Routine to print out all procs in the zombie list
end
#
# dump the zombstacks
#
define zombstacks
set $basep = (struct proc *)zombproc->lh_first
set $pp = $basep
while $pp
if $pp->p_stat != 5
showtaskstacks $pp->task
end
set $pp = $pp->p_list.le_next
end
end
document zombstacks
Syntax: (gdb) zombstacks
| Routine to print out all stacks of tasks that are exiting
end
#
# dump the allprocs
#
define allproc
set $basep = (struct proc *)allproc->lh_first
set $pp = $basep
while $pp
showprocinfo $pp
set $pp = $pp->p_list.le_next
end
end
document allproc
Syntax: (gdb) allproc
| Routine to print out all process in the system
| which are not in the zombie list
end
define print_vnode
set $vp = (struct vnode *)$arg0
printf " "
printf " vp 0x%.8x", $vp
printf " use %d", $vp->v_usecount
printf " io %d", $vp->v_iocount
printf " kuse %d", $vp->v_kusecount
printf " type %d", $vp->v_type
printf " flg 0x%.8x", $vp->v_flag
printf " lflg 0x%.8x", $vp->v_lflag
printf " par 0x%.8x", $vp->v_parent
set $_name = (char *)$vp->v_name
if ($_name != 0)
printf " %s", $_name
end
if ($vp->v_type == VREG) && ($vp->v_un.vu_ubcinfo != 0)
printf " mapped %d", ($vp->v_un.vu_ubcinfo.ui_flags & 0x08) ? 1 : 0
end
printf "\n"
end
document print_vnode
Syntax: (gdb) print_vnode <vnode>
| Prints out the fields of a vnode struct
end
define showprocvnodes
set $pp = (struct proc *)$arg0
set $fdp = (struct filedesc *)$pp->p_fd
set $cvp = $fdp->fd_cdir
set $rvp = $fdp->fd_rdir
if $cvp
printf "Current Working Directory \n"
print_vnode $cvp
printf "\n"
end
if $rvp
printf "Current Root Directory \n"
print_vnode $rvp
printf "\n"
end
set $count = 0
set $fpp = (struct fileproc **)($fdp->fd_ofiles)
set $fpo = (char)($fdp->fd_ofileflags[0])
while $count < $fdp->fd_nfiles
#printf"fpp %x ", *$fpp
if *$fpp
set $fg =(struct fileglob *)((**$fpp)->f_fglob)
if $fg && (($fg)->fg_type == 1)
if $fdp->fd_ofileflags[$count] & 4
printf "U: "
else
printf " "
end
printf "fd = %d ", $count
print_vnode $fg->fg_data
end
end
set $fpp = $fpp + 1
set $count = $count + 1
end
end
document showprocvnodes
Syntax: (gdb) showprocvnodes <proc_address>
| Routine to print out all the open fds
| which are vnodes in a process
end
define showallprocvnodes
set $basep = (struct proc *)allproc->lh_first
set $pp = $basep
while $pp
printf "============================================ \n"
showprocinfo $pp
showprocvnodes $pp
set $pp = $pp->p_list.le_next
end
end
document showallprocvnodes
Syntax: (gdb) showallprocvnodes
| Routine to print out all the open fds
| which are vnodes
end
#
# dump the childrent of a proc
#
define showinitchild
set $basep = (struct proc *)initproc->p_children.lh_first
set $pp = $basep
while $pp
showprocinfo $pp
set $pp = $pp->p_sibling.le_next
end
end
document showinitchild
Syntax: (gdb) showinitchild
| Routine to print out all processes in the system
| which are children of init process
end
define showmountallvnodes
set $mp = (struct mount *)$arg0
set $basevp = (struct vnode *)$mp->mnt_vnodelist.tqh_first
set $vp = $basevp
printf "____________________ Vnode list Queue ---------------\n"
while $vp
print_vnode $vp
set $vp = $vp->v_mntvnodes->tqe_next
end
set $basevp = (struct vnode *)$mp->mnt_workerqueue.tqh_first
set $vp = $basevp
printf "____________________ Worker Queue ---------------\n"
while $vp
print_vnode $vp
set $vp = $vp->v_mntvnodes->tqe_next
end
set $basevp = (struct vnode *)$mp->mnt_newvnodes.tqh_first
set $vp = $basevp
printf "____________________ New vnodes Queue ---------------\n"
while $vp
print_vnode $vp
set $vp = $vp->v_mntvnodes->tqe_next
end
end
document showmountallvnodes
Syntax: showmountallvnodes <struct mount *>
| Print the vnode inactive list
end
define showmountvnodes
set $mp = (struct mount *)$arg0
set $basevp = (struct vnode *)$mp->mnt_vnodelist.tqh_first
set $vp = $basevp
printf "____________________ Vnode list Queue ---------------\n"
while $vp
print_vnode $vp
set $vp = $vp->v_mntvnodes->tqe_next
end
end
document showmountvnodes
Syntax: showmountvnodes <struct mount *>
| Print the vnode list
end
define showworkqvnodes
set $mp = (struct mount *)$arg0
set $basevp = (struct vnode *)$mp->mnt_workerqueue.tqh_first
set $vp = $basevp
printf "____________________ Worker Queue ---------------\n"
while $vp
print_vnode $vp
set $vp = $vp->v_mntvnodes->tqe_next
end
end
document showworkqvnodes
Syntax: showworkqvnodes <struct mount *>
| Print the vnode worker list
end
define shownewvnodes
set $mp = (struct mount *)$arg0
set $basevp = (struct vnode *)$mp->mnt_newvnodes.tqh_first
set $vp = $basevp
printf "____________________ New vnodes Queue ---------------\n"
while $vp
print_vnode $vp
set $vp = $vp->v_mntvnodes->tqe_next
end
end
document shownewvnodes
Syntax: shownewvnodes <struct mount *>
| Print the new vnode list
end
#
# print mount point info
define print_mount
set $mp = (struct mount *)$arg0
printf " "
printf " mp 0x%.8x", $mp
printf " flag %x", $mp->mnt_flag
printf " kern_flag %x", $mp->mnt_kern_flag
printf " lflag %x", $mp->mnt_lflag
printf " type: %s", $mp->mnt_vfsstat.f_fstypename
printf " mnton: %s", $mp->mnt_vfsstat.f_mntonname
printf " mntfrom: %s", $mp->mnt_vfsstat.f_mntfromname
printf "\n"
end
define showallmounts
set $mp=(struct mount *)mountlist.tqh_first
while $mp
print_mount $mp
set $mp = $mp->mnt_list.tqe_next
end
end
document showallmounts
Syntax: showallmounts
| Print all mount points
end
define pcprint
set $pc = $arg0
if ((unsigned int)$pc <= (unsigned int) $kgm_fkmodmax) && \
((unsigned int)$pc >= (unsigned int)$kgm_fkmodmin)
showkmodaddr $pc
else
output/a $pc
end
end
define mbuf_walkpkt
set $mp = (struct mbuf *)$arg0
set $cnt = 1
set $tot = 0
while $mp
printf "%4d: 0x%08x [len %4d, type %2d, ", $cnt, $mp, \
$mp->m_hdr.mh_len, $mp->m_hdr.mh_type
if mclaudit != 0
mbuf_buf2mca $mp
printf ", "
end
set $tot = $tot + $mp->m_hdr.mh_len
printf "total %d]\n", $tot
set $mp = $mp->m_hdr.mh_nextpkt
set $cnt = $cnt + 1
end
end
document mbuf_walkpkt
Syntax: (gdb) mbuf_walkpkt <addr>
| Given an mbuf address, walk its m_nextpkt pointer
end
define mbuf_walk
set $mp = (struct mbuf *)$arg0
set $cnt = 1
set $tot = 0
while $mp
printf "%4d: 0x%08x [len %4d, type %2d, ", $cnt, $mp, \
$mp->m_hdr.mh_len, $mp->m_hdr.mh_type
if mclaudit != 0
mbuf_buf2mca $mp
printf ", "
end
set $tot = $tot + $mp->m_hdr.mh_len
printf "total %d]\n", $tot
set $mp = $mp->m_hdr.mh_next
set $cnt = $cnt + 1
end
end
document mbuf_walk
Syntax: (gdb) mbuf_walk <addr>
| Given an mbuf address, walk its m_next pointer
end
define mbuf_buf2slab
set $addr = $arg0
set $gix = ((char *)$addr - (char *)mbutl) >> 20
set $ix = ((char *)$addr - (char *)mbutl) >> 11
set $slab = &slabstbl[$gix].slg_slab[$ix]
printf "0x%08x", $slab
end
document mbuf_buf2slab
| Given an mbuf object, find its corresponding slab address.
end
define mbuf_buf2mca
set $addr = $arg0
set $ix = ((char *)$addr - (char *)mbutl) >> 11
set $clbase = ((union mcluster *)(mbutl + $ix))
set $mclidx = (((char *)$addr - (char *)$clbase) >> 8)
set $mca = mclaudit[$ix].cl_audit[$mclidx]
printf "mca: 0x%08x", $mca
end
document mbuf_buf2mca
Syntax: (gdb) mbuf_buf2mca <addr>
| Given an mbuf object, find its buffer audit structure address.
| This requires mbuf buffer auditing to be turned on, by setting
| the appropriate flags to the "mbuf_debug" boot-args parameter.
end
define mbuf_showmca
set language c
set $mca = (mcache_audit_t *)$arg0
set $cp = (mcache_t *)$mca->mca_cache
printf "object type:\t\t"
mbuf_mca_ctype $mca 1
printf "\ncontrolling mcache:\t%p (%s)\n", $mca->mca_cache, $cp->mc_name
if $mca->mca_uflags & $MB_SCVALID
set $ix = ((char *)$mca->mca_addr - (char *)mbutl) >> 11
set $clbase = ((union mcluster *)(mbutl + $ix))
set $mclidx = (((char *)$mca->mca_addr - (char *)$clbase) >> 8)
printf "mbuf obj:\t\t%p\n", $mca->mca_addr
printf "mbuf index:\t\t%d (out of 8) in cluster base %p\n", \
$mclidx + 1, $clbase
if $mca->mca_uptr != 0
set $peer_mca = (mcache_audit_t *)$mca->mca_uptr
printf "paired cluster obj:\t%p (mca %p)\n", \
$peer_mca->mca_addr, $peer_mca
end
printf "saved contents:\t\t%p (%d bytes)\n", \
$mca->mca_contents, $mca->mca_contents_size
else
printf "cluster obj:\t\t%p\n", $mca->mca_addr
if $mca->mca_uptr != 0
set $peer_mca = (mcache_audit_t *)$mca->mca_uptr
printf "paired mbuf obj:\t%p (mca %p)\n", \
$peer_mca->mca_addr, $peer_mca
end
end
printf "recent transaction for this buffer (thread %p):\n", \
$mca->mca_thread
set $cnt = 0
while $cnt < $mca->mca_depth
set $pc = $mca->mca_stack[$cnt]
printf "%4d: ", $cnt + 1
pcprint $pc
printf "\n"
set $cnt = $cnt + 1
end
if $mca->mca_pdepth > 0
printf "previous transaction for this buffer (thread %p):\n", \
$mca->mca_pthread
end
set $cnt = 0
while $cnt < $mca->mca_pdepth
set $pc = $mca->mca_pstack[$cnt]
printf "%4d: ", $cnt + 1
pcprint $pc
printf "\n"
set $cnt = $cnt + 1
end
set language auto
end
document mbuf_showmca
Syntax: (gdb) mbuf_showmca <addr>
| Given an mbuf/cluster buffer audit structure address, print the audit
| records including the stack trace of the last buffer transaction.
end
set $MCF_NOCPUCACHE = 0x10
define mcache_stat
set $head = (mcache_t *)mcache_head
set $mc = $head
printf "cache cache cache buf buf backing (# of retries) bufs\n"
printf "name state addr size align zone wait nowait failed incache\n"
printf "------------------------- -------- ---------- ------ ----- ---------- -------------------------- --------\n"
while $mc != 0
set $bktsize = $mc->mc_cpu.cc_bktsize
printf "%-25s ", $mc->mc_name
if ($mc->mc_flags & $MCF_NOCPUCACHE)
printf "disabled"
else
if $mc->mc_purge_cnt > 0
printf " purging"
else
if $bktsize == 0
printf " offline"
else
printf " online"
end
end
end
printf " 0x%08x %6d %5d ",$mc, \
$mc->mc_bufsize, $mc->mc_align
if $mc->mc_slab_zone != 0
printf "0x%08x", $mc->mc_slab_zone
else
printf " custom"
end
set $tot = 0
set $tot += $mc->mc_full.bl_total * $bktsize
set $ccp = (mcache_cpu_t *)$mc->mc_cpu
set $n = 0
while $n < ncpu
if $ccp->cc_objs > 0
set $tot += $ccp->cc_objs
end
if $ccp->cc_pobjs > 0
set $tot += $ccp->cc_pobjs
end
set $n += 1
set $ccp += 1
end
printf " %8d %8d %8d %8d", $mc->mc_wretry_cnt, \
$mc->mc_nwretry_cnt, $mc->mc_nwfail_cnt, $tot
printf "\n"
set $mc = (mcache_t *)$mc->mc_list.le_next
end
end
document mcache_stat
Syntax: (gdb) mcache_stat
| Print all mcaches in the system.
end
define mcache_showzone
set $mc = (mcache_t *)$arg0
if $mc->mc_slab_zone != 0
printf "%p", $mc->mc_slab_zone
else
printf " custom"
end
document mcache_showzone
Syntax: (gdb) mcache_showzone <mcache_addr>
| Print the type of backend (custom or zone) of a mcache.
end
define mcache_walkobj
set $p = (mcache_obj_t *)$arg0
set $cnt = 1
set $tot = 0
while $p
printf "%4d: 0x%08x\n", $cnt, $p,
set $p = $p->obj_next
set $cnt = $cnt + 1
end
end
document mcache_walkobj
Syntax: (gdb) mcache_walkobj <addr>
| Given a mcache object address, walk its obj_next pointer
end
define mcache_showcache
set $cp = (mcache_t *)$arg0
set $ccp = (mcache_cpu_t *)$cp->mc_cpu
set $bktsize = $cp->mc_cpu.cc_bktsize
set $cnt = 0
set $tot = 0
printf "Showing cache '%s':\n\n", $cp->mc_name
printf " CPU cc_objs cc_pobjs total\n"
printf "---- -------- -------- --------\n"
while $cnt < ncpu
set $objs = $ccp->cc_objs
if $objs <= 0
set $objs = 0
end
set $pobjs = $ccp->cc_pobjs
if $pobjs <= 0
set $pobjs = 0
end
set $tot_cpu = $objs + $pobjs
set $tot += $tot_cpu
printf "%4d %8d %8d %8d\n", $cnt, $objs, $pobjs, $tot_cpu
set $ccp += 1
set $cnt += 1
end
printf " ========\n"
printf " %8d\n", $tot
printf "\n"
set $tot += $cp->mc_full.bl_total * $bktsize
printf "Total # of full buckets (%d objs/bkt):\t%-8d\n", \
$bktsize, $cp->mc_full.bl_total
printf "Total # of objects cached:\t\t%-8d\n", $tot
end
document mcache_showcache
| Display the number of objects in the cache
end
set $NSLABSPMB = sizeof(mcl_slabg_t)/sizeof(mcl_slab_t)
define mbuf_slabstbl
set $x = 0
printf "slot addr slabs range\n"
printf "---- ---------- -----------------------\n"
while $x < maxslabgrp
set $slg = slabstbl[$x]
printf "%3d: ", $x
if $slg == 0
printf "-\n"
else
printf "%p [%p-%p]\n", $slg, &$slg->slg_slab[0], \
&$slg->slg_slab[$NSLABSPMB-1]
end
set $x += 1
end
end
document mbuf_slabstbl
| Display the mbuf slabs table
end
set $SLF_MAPPED=0x0001
set $SLF_PARTIAL=0x0002
set $SLF_DETACHED=0x0004
define mbuf_slabs
set $slg = (mcl_slabg_t *)$arg0
set $x = 0
printf "slot addr next base C R N size flags\n"
printf "---- ---------- ---------- ---------- -- -- -- ------ -----\n"
while $x < $NSLABSPMB
set $sl = &$slg->slg_slab[$x]
printf "%3d: 0x%08x 0x%08x 0x%08x %2d %2d %2d %6d 0x%04x ", \
$x + 1, $sl, $sl->sl_next, $sl->sl_base, $sl->sl_class, \
$sl->sl_refcnt, $sl->sl_chunks, $sl->sl_len, \
$sl->sl_flags
if $sl->sl_flags != 0
printf "<"
if $sl->sl_flags & $SLF_MAPPED
printf "mapped"
end
if $sl->sl_flags & $SLF_PARTIAL
printf ",partial"
end
if $sl->sl_flags & $SLF_DETACHED
printf ",detached"
end
printf ">"
end
printf "\n"
set $x += 1
end
end
document mbuf_slabs
| Display all mbuf slabs in the group
end
define mbuf_stat
set $x = 0
printf "class total cached uncached inuse failed waiter notified purge\n"
printf "name objs objs objs / slabs objs alloc count count count count\n"
printf "---------------- -------- -------- ------------------- -------- ---------------- -------- -------- --------\n"
while $x < (sizeof(mbuf_table) / sizeof(mbuf_table[0]))
set $mbt = mbuf_table[$x]
set $mcs = (mb_class_stat_t *)mbuf_table[$x].mtbl_stats
set $tot = 0
set $mc = $mbt->mtbl_cache
set $bktsize = $mc->mc_cpu.cc_bktsize
set $tot += $mc->mc_full.bl_total * $bktsize
set $ccp = (mcache_cpu_t *)$mc->mc_cpu
set $n = 0
while $n < ncpu
if $ccp->cc_objs > 0
set $tot += $ccp->cc_objs
end
if $ccp->cc_pobjs > 0
set $tot += $ccp->cc_pobjs
end
set $n += 1
set $ccp += 1
end
printf "%-16s %8d %8d %8d / %-8d %8d %16llu %8d %8llu %8llu", \
$mcs->mbcl_cname, $mcs->mbcl_total, $tot, \
$mcs->mbcl_infree, $mcs->mbcl_slab_cnt, \
($mcs->mbcl_total - $tot - $mcs->mbcl_infree), \
$mcs->mbcl_fail_cnt, $mc->mc_waiter_cnt, \
$mcs->mbcl_notified, $mcs->mbcl_purge_cnt
printf "\n"
set $x += 1
end
end
document mbuf_stat
| Print extended mbuf allocator statistics.
end
set $MB_INUSE = 0x1
set $MB_COMP_INUSE = 0x2
set $MB_SCVALID = 0x4
set $MCLBYTES = 2048
set $MSIZE = 256
set $NBPG = 4096
set $M16KCLBYTES = 16384
define mbuf_mca_ctype
set $mca = (mcache_audit_t *)$arg0
set $vopt = $arg1
set $cp = $mca->mca_cache
set $class = (unsigned int)$cp->mc_private
set $csize = mbuf_table[$class].mtbl_stats->mbcl_size
set $done = 0
if $csize == $MSIZE
if $vopt
printf "M (mbuf) "
else
printf "M "
end
set $done = 1
end
if !$done && $csize == $MCLBYTES
if $vopt
printf "CL (2K cluster) "
else
printf "CL "
end
set $done = 1
end
if !$done && $csize == $NBPG
if $vopt
printf "BCL (4K cluster) "
else
printf "BCL "
end
set $done = 1
end
if !$done && $csize == $M16KCLBYTES
if $vopt
printf "JCL (16K cluster) "
else
printf "JCL "
end
set $done = 1
end
if !$done && $csize == ($MSIZE+$MCLBYTES)
if $mca->mca_uflags & $MB_SCVALID
if $mca->mca_uptr
printf "M+CL "
if $vopt
printf "(paired mbuf, 2K cluster)"
end
else
printf "M-CL "
if $vopt
printf "(unpaired mbuf, 2K cluster) "
end
end
else
if $mca->mca_uptr
printf "CL+M "
if $vopt
printf "(paired 2K cluster, mbuf) "
end
else
printf "CL-M "
if $vopt
printf "(paired 2K cluster, mbuf) "
end
end
end
set $done = 1
end
if !$done && $csize == ($MSIZE+$NBPG)
if $mca->mca_uflags & $MB_SCVALID
if $mca->mca_uptr
printf "M+BCL "
if $vopt
printf "(paired mbuf, 4K cluster) "
end
else
printf "M-BCL "
if $vopt
printf "(unpaired mbuf, 4K cluster) "
end
end
else
if $mca->mca_uptr
printf "BCL+M "
if $vopt
printf "(paired 4K cluster, mbuf) "
end
else
printf "BCL-M "
if $vopt
printf "(unpaired 4K cluster, mbuf) "
end
end
end
set $done = 1
end
if !$done && $csize == ($MSIZE+$M16KCLBYTES)
if $mca->mca_uflags & $MB_SCVALID
if $mca->mca_uptr
printf "M+JCL "
if $vopt
printf "(paired mbuf, 16K cluster) "
end
else
printf "M-JCL "
if $vopt
printf "(unpaired mbuf, 16K cluster) "
end
end
else
if $mca->mca_uptr
printf "JCL+M "
if $vopt
printf "(paired 16K cluster, mbuf) "
end
else
printf "JCL-M "
if $vopt
printf "(unpaired 16K cluster, mbuf) "
end
end
end
set $done = 1
end
if !$done
printf "unknown: %s ", $cp->mc_name
end
end
document mbuf_mca_ctype
| This is a helper macro for mbuf_show{active,inactive,all} that prints
| out the mbuf object type represented by a given mcache audit structure.
end
define mbuf_showactive
mbuf_walkallslabs 1 0
end
document mbuf_showactive
Syntax: (gdb) mbuf_showactive
| Walk the mbuf objects pool and print only the active ones; this
| requires mbuf debugging to be turned on, by setting the appropriate flags
| to the "mbuf_debug" boot-args parameter. Active objects are those that
| are outstanding (have not returned to the mbuf slab layer) and in use
| by the client (have not been freed).
end
define mbuf_showinactive
mbuf_walkallslabs 0 1
end
document mbuf_showinactive
Syntax: (gdb) mbuf_showinactive
| Walk the mbuf objects pool and print only the inactive ones; this
| requires mbuf debugging to be turned on, by setting the appropriate flags
| to the "mbuf_debug" boot-args parameter. Inactive objects are those that
| are outstanding (have not returned to the mbuf slab layer) but have been
| freed by the client, i.e. they still reside in the mcache layer ready to
| be used for subsequent allocation requests.
end
define mbuf_showall
mbuf_walkallslabs 1 1
end
document mbuf_showall
Syntax: (gdb) mbuf_showall
| Walk the mbuf objects pool and print them all; this requires
| mbuf debugging to be turned on, by setting the appropriate flags to the
| "mbuf_debug" boot-args parameter.
end
define mbuf_mcaobjs
end
define mbuf_walkallslabs
set $show_a = $arg0
set $show_f = $arg1
set $x = 0
set $total = 0
set $total_a = 0
set $total_f = 0
printf "("
if $show_a && !$show_f
printf "Searching only for active "
end
if !$show_a && $show_f
printf "Searching only for inactive "
end
if $show_a && $show_f
printf "Displaying all "
end
printf "objects; this may take a while ...)\n\n"
printf " slab mca obj allocation\n"
printf "slot idx address address address type state\n"
printf "---- ---- ---------- ---------- ---------- ----- -----------\n"
while $x < slabgrp
set $slg = slabstbl[$x]
set $y = 0
set $stop = 0
while $y < $NSLABSPMB && $stop == 0
set $sl = &$slg->slg_slab[$y]
set $base = (char *)$sl->sl_base
set $ix = ($base - (char *)mbutl) >> 11
set $clbase = ((union mcluster *)(mbutl + $ix))
set $mclidx = ($base - (char *)$clbase) >> 8
set $mca = mclaudit[$ix].cl_audit[$mclidx]
set $first = 1
while $mca != 0 && $mca->mca_addr != 0
set $printmca = 0
if $mca->mca_uflags & ($MB_INUSE|$MB_COMP_INUSE)
set $total_a = $total_a + 1
set $printmca = $show_a
else
set $total_f = $total_f + 1
set $printmca = $show_f
end
if $printmca != 0
if $first == 1
printf "%4d %4d 0x%08x ", $x, $y, $sl
else
printf " "
end
printf "0x%08x 0x%08x ", $mca, $mca->mca_addr
mbuf_mca_ctype $mca 0
if $mca->mca_uflags & ($MB_INUSE|$MB_COMP_INUSE)
printf "active "
else
printf " freed "
end
if $first == 1
set $first = 0
end
printf "\n"
set $total = $total + 1
end
set $mca = $mca->mca_next
end
set $y += 1
if $slg->slg_slab[$y].sl_base == 0
set $stop = 1
end
end
set $x += 1
end
if $total && $show_a && $show_f
printf "\ntotal objects:\t%d\n", $total
printf "active/unfreed:\t%d\n", $total_a
printf "freed/in_cache:\t%d\n", $total_f
end
end
document mbuf_walkallslabs
| Walk the mbuf objects pool; this requires mbuf debugging to be
| turned on, by setting the appropriate flags to the "mbuf_debug" boot-args
| parameter. This is a backend routine for mbuf_show{active,inactive,all}.
end
define rtentry_trash
set $rtd = (struct rtentry_dbg *)rttrash_head.tqh_first
set $cnt = 0
while $rtd != 0
if $cnt == 0
printf " rtentry_dbg ref flags\n"
printf " ------------ --- ----------\n"
end
printf "%4d: %p %3d 0x%08x\n", $cnt + 1, $rtd, \
$rtd->rtd_refhold_cnt - $rtd->rtd_refrele_cnt, \
$rtd->rtd_entry.rt_flags
set $rtd = $rtd->rtd_trash_link.tqe_next
set $cnt = $cnt + 1
end
end
document rtentry_trash
Syntax: (gdb) rtentry_trash
| Walk the list of trash route entries; this requires route entry
| debugging to be turned on, by setting the appropriate flags to the
| "rte_debug" boot-args parameter.
end
set $RTD_TRSTACK_SIZE = 8
set $RTD_REFHIST_SIZE = 4
define rtentry_showdbg
set $rtd = (struct rtentry_dbg *)$arg0
set $cnt = 0
printf "Total holds: %d\n", $rtd->rtd_refhold_cnt
printf "Next hold slot: %d\n", $rtd->rtd_refhold_next
printf "Total releases: %d\n", $rtd->rtd_refrele_cnt
printf "Next release slot: %d\n", $rtd->rtd_refrele_next
set $ix = 0
while $ix < $RTD_TRSTACK_SIZE
set $pc = $rtd->rtd_alloc_stk_pc[$ix]
if $pc != 0
if $ix == 0
printf "\nAlloc (thread %p):\n", \
$rtd->rtd_alloc_thread
end
printf "%4d: ", $ix + 1
pcprint $pc
printf "\n"
end
set $ix = $ix + 1
end
set $ix = 0
while $ix < $RTD_TRSTACK_SIZE
set $pc = $rtd->rtd_free_stk_pc[$ix]
if $pc != 0
if $ix == 0
printf "\nFree: (thread %p)\n", \
$rtd->rtd_free_thread
end
printf "%4d: ", $ix + 1
pcprint $pc
printf "\n"
end
set $ix = $ix + 1
end
while $cnt < $RTD_REFHIST_SIZE
set $ix = 0
while $ix < $RTD_TRSTACK_SIZE
set $pc = $rtd->rtd_refhold[$cnt].pc[$ix]
if $pc != 0
if $ix == 0
printf "\nHold [%d] (thread %p):\n", \
$cnt, $rtd->rtd_refhold[$cnt].th
end
printf "%4d: ", $ix + 1
pcprint $pc
printf "\n"
end
set $ix = $ix + 1
end
set $cnt = $cnt + 1
end
set $cnt = 0
while $cnt < $RTD_REFHIST_SIZE
set $ix = 0
while $ix < $RTD_TRSTACK_SIZE
set $pc = $rtd->rtd_refrele[$cnt].pc[$ix]
if $pc != 0
if $ix == 0
printf "\nRelease [%d] (thread %p):\n",\
$cnt, $rtd->rtd_refrele[$cnt].th
end
printf "%4d: ", $ix + 1
pcprint $pc
printf "\n"
end
set $ix = $ix + 1
end
set $cnt = $cnt + 1
end
end
document rtentry_showdbg
Syntax: (gdb) rtentry_showdbg <addr>
| Given a route entry structure address, print the debug information
| related to it. This requires route entry debugging to be turned
| on, by setting the appropriate flags to the "rte_debug" boot-args
| parameter.
end
#
# print all OSMalloc stats
define ostag_print
set $kgm_tagp = (OSMallocTag)$arg0
printf "0x%08x: ", $kgm_tagp
printf "%8d ",$kgm_tagp->OSMT_refcnt
printf "%8x ",$kgm_tagp->OSMT_state
printf "%8x ",$kgm_tagp->OSMT_attr
printf "%s ",$kgm_tagp->OSMT_name
printf "\n"
end
define showosmalloc
printf "TAG COUNT STATE ATTR NAME\n"
set $kgm_tagheadp = (OSMallocTag)&OSMalloc_tag_list
set $kgm_tagptr = (OSMallocTag )($kgm_tagheadp->OSMT_link.next)
while $kgm_tagptr != $kgm_tagheadp
ostag_print $kgm_tagptr
set $kgm_tagptr = (OSMallocTag)$kgm_tagptr->OSMT_link.next
end
printf "\n"
end
document showosmalloc
Syntax: (gdb) showosmalloc
| Print the outstanding allocation count by OSMallocTags.
end
define systemlog
if msgbufp->msg_bufc[msgbufp->msg_bufx] == 0
# The buffer hasn't wrapped, so take the easy (and fast!) path
printf "%s", msgbufp->msg_bufc
else
set $kgm_msgbuf = *msgbufp
set $kgm_syslog_bufsize = $kgm_msgbuf.msg_size
set $kgm_syslog_bufend = $kgm_msgbuf.msg_bufx
if $kgm_syslog_bufend >= $kgm_syslog_bufsize
set $kgm_syslog_bufend = 0
end
# print older messages from msg_bufx to end of buffer
set $kgm_i = $kgm_syslog_bufend
while $kgm_i < $kgm_syslog_bufsize
set $kgm_syslog_char = $kgm_msgbuf.msg_bufc[$kgm_i]
if $kgm_syslog_char == 0
# break out of loop
set $kgm_i = $kgm_syslog_bufsize
else
printf "%c", $kgm_syslog_char
end
set $kgm_i = $kgm_i + 1
end
# print newer messages from start of buffer to msg_bufx
set $kgm_i = 0
while $kgm_i < $kgm_syslog_bufend
set $kgm_syslog_char = $kgm_msgbuf.msg_bufc[$kgm_i]
printf "%c", $kgm_syslog_char
set $kgm_i = $kgm_i + 1
end
end
printf "\n"
end
document systemlog
| Syntax: systemlog
| Display the kernel's printf ring buffer
end
define printvnodepathint_recur
if $arg0 != 0
if ($arg0->v_flag & 0x000001) && ($arg0->v_mount != 0)
if $arg0->v_mount->mnt_vnodecovered != 0
printvnodepathint_recur $arg0->v_mount->mnt_vnodecovered $arg0->v_mount->mnt_vnodecovered->v_name
end
else
printvnodepathint_recur $arg0->v_parent $arg0->v_parent->v_name
printf "/%s", $arg1
end
end
end
#
# Show the locks held on a vnode by range, type, and holder.
#
define showvnodelocks
if ($argc == 1)
_showvnodelockheader
_showvnodelocks $arg0
else
printf "| Usage:\n|\n"
help showvnodelocks
end
end
document showvnodelocks
| Given a vnodet pointer, display the list of advisory record locks for the
| referenced pvnode.
| The following is the syntax:
| (gdb) showvnodelocks <vnode_t>
end
define _showvnodelockheader
printf "* type W held by lock type start end\n"
printf "- ----- - ------------- --------- ------------------ ------------------\n"
end
#
# Macro to display a single lock; used to display both held locks and
# blocked locks
#
define _showvnodelock
set $kgm_svl_lock = ((struct lockf *)$arg0)
# decode flags
set $kgm_svl_flags = $kgm_svl_lock->lf_flags
set $kgm_svl_type = $kgm_svl_lock->lf_type
if ($kgm_svl_flags & 0x20)
printf "flock"
end
if ($kgm_svl_flags & 0x40)
printf "posix"
end
if ($kgm_svl_flags & 0x80)
printf "prov "
end
if ($kgm_svl_flags & 0x10)
printf " W "
else
printf " . "
end
# POSIX file vs. advisory range locks
if ($kgm_svl_flags & 0x40)
set $kgm_svl_proc = (proc_t)$kgm_svl_lock->lf_id
printf "PID %8d ", $kgm_svl_proc->p_pid
else
printf "ID 0x%08x ", $kgm_svl_lock->lf_id
end
# lock type
if ($kgm_svl_type == 1)
printf "shared "
else
if ($kgm_svl_type == 3)
printf "exclusive "
else
if ($kgm_svl_type == 2)
printf "unlock "
else
printf "unknown "
end
end
end
# start and stop
printf "0x%016x..", $kgm_svl_lock->lf_start
printf "0x%016x ", $kgm_svl_lock->lf_end
printf "\n"
end
# Body of showvnodelocks, not including header
define _showvnodelocks
set $kgm_svl_vnode = ((vnode_t)$arg0)
set $kgm_svl_lockiter = $kgm_svl_vnode->v_lockf
while ($kgm_svl_lockiter != 0)
# locks that are held
printf "H "
_showvnodelock $kgm_svl_lockiter
# and any locks blocked by them
set $kgm_svl_blocker = $kgm_svl_lockiter->lf_blkhd.tqh_first
while ($kgm_svl_blocker != 0)
printf "> "
_showvnodelock $kgm_svl_blocker
set $kgm_svl_blocker = $kgm_svl_blocker->lf_block.tqe_next
end
# and on to the next one...
set $kgm_svl_lockiter = $kgm_svl_lockiter->lf_next
end
end
define showvnodepath
set $vp = (struct vnode *)$arg0
if $vp != 0
if ($vp->v_flag & 0x000001) && ($vp->v_mount != 0) && ($vp->v_mount->mnt_flag & 0x00004000)
printf "/"
else
printvnodepathint_recur $vp $vp->v_name
end
end
printf "\n"
end
document showvnodepath
Syntax: (gdb) showvnodepath <vnode>
| Prints the path for a vnode
end
define printcolonhex
if ($argc == 2)
set $addr = $arg0
set $count = $arg1
set $li = 0
while ($li < $count)
if ($li == 0)
printf "%02x", (u_char)$addr[$li]
end
if ($li != 0)
printf ":%02x", (u_char)$addr[$li]
end
set $li = $li + 1
end
end
end
define showsockaddr_dl
set $sdl = (struct sockaddr_dl *)$arg0
printf "LINK "
if ($sdl == 0)
printf "(null)"
else
set $addr = $sdl->sdl_data + $sdl->sdl_nlen
set $count = $sdl->sdl_alen
printcolonhex $addr $count
end
end
define showsockaddr_unspec
set $sockaddr = (struct sockaddr *)$arg0
set $addr = $sockaddr->sa_data
set $count = $sockaddr->sa_len - 2
printf "UNSP "
printcolonhex $addr $count
end
define showsockaddr_at
set $sockaddr = (struct sockaddr *)$arg0
set $addr = $sockaddr->sa_data
set $count = $sockaddr->sa_len - 2
printf "ATLK "
printcolonhex $addr $count
end
define showsockaddr_in
set $sin = (struct sockaddr_in *)$arg0
set $sa_bytes = (unsigned char *)&($sin->sin_addr)
printf "IPV4 %d.%d.%d.%d", $sa_bytes[0], $sa_bytes[1], $sa_bytes[2], $sa_bytes[3]
end
define showsockaddr_in6
set $sin6 = (struct sockaddr_in6 *)$arg0
set $sa_bytes = $sin6->sin6_addr.__u6_addr.__u6_addr8
printf "IPV6 %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", $sa_bytes[0], $sa_bytes[1], $sa_bytes[2], $sa_bytes[3], $sa_bytes[4], $sa_bytes[5], $sa_bytes[6], $sa_bytes[7], $sa_bytes[8], $sa_bytes[9], $sa_bytes[10], $sa_bytes[11], $sa_bytes[12], $sa_bytes[13], $sa_bytes[14], $sa_bytes[15]
end
define showifmultiaddrs
set $ifp = (struct ifnet *)$arg0
set $if_multi = (struct ifmultiaddr *)$ifp->if_multiaddrs->lh_first
set $mymulti = $if_multi
set $myi = 0
while ($mymulti != 0)
printf "%2d. ", $myi
set $sa_family = $mymulti->ifma_addr.sa_family
if ($sa_family == 2)
if ($mymulti->ifma_ll != 0)
showsockaddr_dl $mymulti->ifma_ll->ifma_addr
printf " "
end
showsockaddr_in $mymulti->ifma_addr
end
if ($sa_family == 30)
if ($mymulti->ifma_ll != 0)
showsockaddr_dl $mymulti->ifma_ll->ifma_addr
printf " "
end
showsockaddr_in6 $mymulti->ifma_addr
end
if ($sa_family == 18)
showsockaddr_dl $mymulti->ifma_addr
end
if ($sa_family == 0)
showsockaddr_unspec $mymulti->ifma_addr 6
end
printf " [%d]", $mymulti->ifma_refcount
printf "\n"
set $mymulti = $mymulti->ifma_link.le_next
set $myi = $myi + 1
end
end
document showifmultiaddrs
Syntax showifmultiaddrs <ifp>
| show the (struct ifnet).if_multiaddrs list of multicast addresses for the given ifp
end
define showsockaddr
set $mysock = (struct sockaddr *)$arg0
set $showsockaddr_handled = 0
if ($mysock == 0)
printf "(null)"
else
if ($mysock->sa_family == 0)
showsockaddr_unspec $mysock
set $showsockaddr_handled = 1
end
if ($mysock->sa_family == 2)
showsockaddr_in $mysock
set $showsockaddr_handled = 1
end
if ($mysock->sa_family == 30)
showsockaddr_in6 $mysock
set $showsockaddr_handled = 1
end
if ($mysock->sa_family == 18)
showsockaddr_dl $mysock
set $showsockaddr_handled = 1
end
if ($mysock->sa_family == 16)
showsockaddr_at $mysock
set $showsockaddr_handled = 1
end
if ($showsockaddr_handled == 0)
printf "%d ", $mysock->sa_family
set $addr = $mysock->sa_data
set $count = $mysock->sa_len
printcolonhex $addr $count
end
end
end
define showifflags
set $flags = (u_short)$arg0
set $first = 1
printf "<"
if ($flags & 0x1)
printf "UP"
set $first = 0
end
if ($flags & 0x2)
if ($first == 1)
set $first = 0
else
printf ","
end
printf "BROADCAST"
end
if ($flags & 0x4)
printf "DEBUG"
end
if ($flags & 0x8)
if ($first == 1)
set $first = 0
else
printf ","
end
printf "LOOPBACK"
end
if ($flags & 0x10)
if ($first == 1)
set $first = 0
else
printf ","
end
printf "POINTTOPOINT"
end
# if ($flags & 0x20)
# if ($first == 1)
# set $first = 0
# else
# printf ","
# end
# printf "NOTRAILERS"
# end
if ($flags & 0x40)
if ($first == 1)
set $first = 0
else
printf ","
end
printf "RUNNING"
end
if ($flags & 0x80)
if ($first == 1)
set $first = 0
else
printf ","
end
printf "NOARP"
end
if ($flags & 0x100)
if ($first == 1)
set $first = 0
else
printf ","
end
printf "PROMISC"
end
if ($flags & 0x200)
if ($first == 1)
set $first = 0
else
printf ","
end
printf "ALLMULTI"
end
if ($flags & 0x400)
if ($first == 1)
set $first = 0
else
printf ","
end
printf "OACTIVE"
end
if ($flags & 0x800)
if ($first == 1)
set $first = 0
else
printf ","
end
printf "SIMPLEX"
end
if ($flags & 0x1000)
if ($first == 1)
set $first = 0
else
printf ","
end
printf "LINK0"
end
if ($flags & 0x2000)
if ($first == 1)
set $first = 0
else
printf ","
end
printf "LINK1"
end
if ($flags & 0x4000)
if ($first == 1)
set $first = 0
else
printf ","
end
printf "LINK2-ALTPHYS"
end
if ($flags & 0x8000)
if ($first == 1)
set $first = 0
else
printf ","
end
printf "MULTICAST"
end
printf ">"
end
define showifaddrs
set $ifp = (struct ifnet *)$arg0
set $myifaddr = (struct ifaddr *)$ifp->if_addrhead->tqh_first
set $myi = 0
while ($myifaddr != 0)
printf "\t%d. ", $myi
showsockaddr $myifaddr->ifa_addr
printf " [%d]\n", $myifaddr->ifa_refcnt
set $myifaddr = $myifaddr->ifa_link->tqe_next
set $myi = $myi + 1
end
end
document showifaddrs
Syntax: showifaddrs <ifp>
| show the (struct ifnet).if_addrhead list of addresses for the given ifp
end
define ifconfig
set $ifconfig_all = 0
if ($argc == 1)
set $ifconfig_all = 1
end
set $ifp = (struct ifnet *)(ifnet->tqh_first)
while ($ifp != 0)
printf "%s%d: flags=%x", $ifp->if_name, $ifp->if_unit, (u_short)$ifp->if_flags
showifflags $ifp->if_flags
printf " mtu %d\n", $ifp->if_data.ifi_mtu
printf "\t(struct ifnet *)0x%x\n", $ifp
if ($ifconfig_all == 1)
showifaddrs $ifp
end
set $ifp = $ifp->if_link->tqe_next
end
end
document ifconfig
Syntax: (gdb) ifconfig
| display ifconfig-like output, and print the (struct ifnet *) pointers for further inspection
end
define showbpfdtab
set $myi = 0
while ($myi < bpf_dtab_size)
if (bpf_dtab[$myi] != 0)
printf "Address 0x%x, bd_next 0x%x\n", bpf_dtab[$myi], bpf_dtab[$myi]->bd_next
print *bpf_dtab[$myi]
end
set $myi = $myi + 1
end
end
define showallvols
printf "volume mnt_data mnt_devvp typename mountpoint\n"
set $kgm_vol = (mount_t) mountlist.tqh_first
while $kgm_vol
printf "0x%08x ", $kgm_vol
printf "0x%08x ", $kgm_vol->mnt_data
printf "0x%08x ", $kgm_vol->mnt_devvp
if ($kgm_vol->mnt_vtable->vfc_name[0] == 'h') && \
($kgm_vol->mnt_vtable->vfc_name[1] == 'f') && \
($kgm_vol->mnt_vtable->vfc_name[2] == 's') && \
($kgm_vol->mnt_vtable->vfc_name[3] == '\0')
set $kgm_hfsmount = \
(struct hfsmount *) $kgm_vol->mnt_data
if $kgm_hfsmount->hfs_freezing_proc != 0
printf "FROZEN hfs "
else
printf "hfs "
end
else
printf "%-10s ", $kgm_vol->mnt_vtable->vfc_name
end
printf "%s\n", $kgm_vol->mnt_vfsstat.f_mntonname
set $kgm_vol = (mount_t) $kgm_vol->mnt_list.tqe_next
end
end
document showallvols
Syntax: (gdb) showallvols
| Display a summary of mounted volumes
end
define showvnodeheader
printf "vnode usecount iocount v_data vtype parent name\n"
end
define showvnodeint
set $kgm_vnode = (vnode_t) $arg0
printf "0x%08x ", $kgm_vnode
printf "%8d ", $kgm_vnode->v_usecount
printf "%7d ", $kgm_vnode->v_iocount
# print information about clean/dirty blocks?
printf "0x%08x ", $kgm_vnode->v_data
# print the vtype, using the enum tag
set $kgm_vtype = $kgm_vnode->v_type
if $kgm_vtype == VNON
printf "VNON "
end
if $kgm_vtype == VREG
printf "VREG "
end
if $kgm_vtype == VDIR
printf "VDIR "
end
if $kgm_vtype == VBLK
printf "VBLK "
end
if $kgm_vtype == VCHR
printf "VCHR "
end
if $kgm_vtype == VLNK
printf "VLNK "
end
if $kgm_vtype == VSOCK
printf "VSOCK "
end
if $kgm_vtype == VFIFO
printf "VFIFO "
end
if $kgm_vtype == VBAD
printf "VBAD "
end
if ($kgm_vtype < VNON) || ($kgm_vtype > VBAD)
printf "%5d ", $kgm_vtype
end
printf "0x%08x ", $kgm_vnode->v_parent
if $kgm_vnode->v_name != 0
printf "%s\n", $kgm_vnode->v_name
else
printf "\n"
end
end
define showvnode
showvnodeheader
showvnodeint $arg0
end
document showvnode
Syntax: (gdb) showvnode <vnode>
| Display info about one vnode
end
define showvolvnodes
showvnodeheader
set $kgm_vol = (mount_t) $arg0
set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first
while $kgm_vnode
showvnodeint $kgm_vnode
set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next
end
end
document showvolvnodes
Syntax: (gdb) showvolvnodes <mouont_t>
| Display info about all vnodes of a given mount_t
end
define showvolbusyvnodes
showvnodeheader
set $kgm_vol = (mount_t) $arg0
set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first
while $kgm_vnode
if $kgm_vnode->v_iocount != 0
showvnodeint $kgm_vnode
end
set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next
end
end
document showvolbusyvnodes
Syntax: (gdb) showvolbusyvnodes <mount_t>
| Display info about busy (iocount!=0) vnodes of a given mount_t
end
define showallbusyvnodes
showvnodeheader
set $kgm_vol = (mount_t) mountlist.tqh_first
while $kgm_vol
set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first
while $kgm_vnode
if $kgm_vnode->v_iocount != 0
showvnodeint $kgm_vnode
end
set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next
end
set $kgm_vol = (mount_t) $kgm_vol->mnt_list.tqe_next
end
end
document showallbusyvnodes
Syntax: (gdb) showallbusyvnodes <vnode>
| Display info about all busy (iocount!=0) vnodes
end
define showallvnodes
showvnodeheader
set $kgm_vol = (mount_t) mountlist.tqh_first
while $kgm_vol
set $kgm_vnode = (vnode_t) $kgm_vol.mnt_vnodelist.tqh_first
while $kgm_vnode
showvnodeint $kgm_vnode
set $kgm_vnode = (vnode_t) $kgm_vnode->v_mntvnodes.tqe_next
end
set $kgm_vol = (mount_t) $kgm_vol->mnt_list.tqe_next
end
end
document showallvnodes
Syntax: (gdb) showallvnodes
| Display info about all vnodes
end
define _showvnodelockheader
printf "* type W held by lock type start end\n"
printf "- ----- - ------------- --------- ------------------ ------------------\n"
end
define _showvnodelock
set $kgm_svl_lock = ((struct lockf *)$arg0)
# decode flags
set $kgm_svl_flags = $kgm_svl_lock->lf_flags
set $kgm_svl_type = $kgm_svl_lock->lf_type
if ($kgm_svl_flags & 0x20)
printf "flock"
end
if ($kgm_svl_flags & 0x40)
printf "posix"
end
if ($kgm_svl_flags & 0x80)
printf "prov "
end
if ($kgm_svl_flags & 0x10)
printf " W "
else
printf " . "
end
# POSIX file vs. advisory range locks
if ($kgm_svl_flags & 0x40)
set $kgm_svl_proc = (proc_t)$kgm_svl_lock->lf_id
printf "PID %8d ", $kgm_svl_proc->p_pid
else
printf "ID 0x%08x ", $kgm_svl_lock->lf_id
end
# lock type
if ($kgm_svl_type == 1)
printf "shared "
else
if ($kgm_svl_type == 3)
printf "exclusive "
else
if ($kgm_svl_type == 2)
printf "unlock "
else
printf "unknown "
end
end
end
# start and stop
printf "0x%016x..", $kgm_svl_lock->lf_start
printf "0x%016x ", $kgm_svl_lock->lf_end
printf "\n"
end
# Body of showvnodelocks, not including header
define _showvnodelocks
set $kgm_svl_vnode = ((vnode_t)$arg0)
set $kgm_svl_lockiter = $kgm_svl_vnode->v_lockf
while ($kgm_svl_lockiter != 0)
# locks that are held
printf "H "
_showvnodelock $kgm_svl_lockiter
# and any locks blocked by them
set $kgm_svl_blocker = $kgm_svl_lockiter->lf_blkhd.tqh_first
while ($kgm_svl_blocker != 0)
printf "> "
_showvnodelock $kgm_svl_blocker
set $kgm_svl_blocker = $kgm_svl_blocker->lf_block.tqe_next
end
# and on to the next one...
set $kgm_svl_lockiter = $kgm_svl_lockiter->lf_next
end
end
define showvnodelocks
if ($argc == 1)
_showvnodelockheader
_showvnodelocks $arg0
else
printf "| Usage:\n|\n"
help showvnodelocks
end
end
document showvnodelocks
Syntax: (gdb) showvnodelocks <vnode_t>
| Given a vnodet pointer, display the list of advisory record locks for the
| referenced pvnodes
end
define showbootargs
printf "%s\n", (char*)((boot_args*)PE_state.bootArgs).CommandLine
end
document showbootargs
Syntax: showbootargs
| Display boot arguments passed to the target kernel
end
define showbootermemorymap
set $kgm_boot_args = kernelBootArgs
set $kgm_msize = kernelBootArgs->MemoryMapDescriptorSize
set $kgm_mcount = kernelBootArgs->MemoryMapSize / $kgm_msize
set $kgm_i = 0
printf "Type Physical Start Number of Pages\n"
while $kgm_i < $kgm_mcount
set $kgm_mptr = (EfiMemoryRange *)((unsigned long)kernelBootArgs->MemoryMap + $kgm_i * $kgm_msize)
# p/x *$kgm_mptr
if $kgm_mptr->Type == 0
printf "reserved "
end
if $kgm_mptr->Type == 1
printf "LoaderCode"
end
if $kgm_mptr->Type == 2
printf "LoaderData"
end
if $kgm_mptr->Type == 3
printf "BS_code "
end
if $kgm_mptr->Type == 4
printf "BS_data "
end
if $kgm_mptr->Type == 5
printf "RT_code "
end
if $kgm_mptr->Type == 6
printf "RT_data "
end
if $kgm_mptr->Type == 7
printf "available "
end
if $kgm_mptr->Type == 8
printf "Unusable "
end
if $kgm_mptr->Type == 9
printf "ACPI_recl "
end
if $kgm_mptr->Type == 10
printf "ACPI_NVS "
end
if $kgm_mptr->Type == 11
printf "MemMapIO "
end
if $kgm_mptr->Type == 12
printf "MemPortIO "
end
if $kgm_mptr->Type == 13
printf "PAL_code "
end
if $kgm_mptr->Type > 13
printf "UNKNOWN "
end
printf " %016llx %016llx\n", $kgm_mptr->PhysicalStart, $kgm_mptr->NumberOfPages
set $kgm_i = $kgm_i + 1
end
end
document showbootermemorymap
Syntax: (gdb) showbootermemorymap
| Prints out the phys memory map from kernelBootArgs
end
define showstacksaftertask
set $kgm_head_taskp = &default_pset.tasks
set $kgm_taskp = (struct task *)$arg0
while $kgm_taskp != $kgm_head_taskp
showtaskheader
showtaskint $kgm_taskp
set $kgm_head_actp = &($kgm_taskp->threads)
set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
while $kgm_actp != $kgm_head_actp
showactheader
if ($decode_wait_events > 0)
showactint $kgm_actp 1
else
showactint $kgm_actp 2
end
set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
end
printf "\n"
set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next)
end
end
document showstacksaftertask
Syntax: (gdb) showstacksaftertask <task>
| Routine to print out all stacks (as in showallstacks) starting after a given task
| Useful if that gdb refuses to print a certain task's stack.
end
define showpmworkqueueint
set $kgm_pm_wq = (IOPMWorkQueue *)$arg0
set $kgm_pm_node = (IOService *)$kgm_pm_wq->owner
printf "0x%08x 0x%08x ", $kgm_pm_wq, $kgm_pm_node
printf "%02d ", $kgm_pm_node->pwrMgt->CurrentPowerState
printf "%02d ", $kgm_pm_node->pwrMgt->MachineState
printf "%02d ", $kgm_pm_node->pwrMgt->WaitReason
printf "%s\n", $kgm_pm_node->pwrMgt->Name
set $kgm_pm_queue = &($kgm_pm_wq->fWorkQueue)
set $kgm_pm_req = (IOPMRequest *) $kgm_pm_queue->next
while ( (queue_entry_t) $kgm_pm_req != (queue_entry_t) $kgm_pm_queue)
printf " Request 0x%08x [%02x] Args ", $kgm_pm_req, $kgm_pm_req->fType
printf "0x%08x ", $kgm_pm_req->fArg0
printf "0x%08x ", $kgm_pm_req->fArg1
printf "0x%08x\n", $kgm_pm_req->fArg2
set $kgm_pm_req = (IOPMRequest *)$kgm_pm_req->fCommandChain.next
end
end
define showallpmworkqueues
set $kgm_pm_next = gIOPMWorkLoop->eventChain
printf "WorkQueue Owner PS MS WT Name\n"
printf "--------------------------------------\n"
while ( $kgm_pm_next )
set $kgm_vt = *((void **) $kgm_pm_next)
if ($kgm_vt == _ZTV13IOPMWorkQueue)
showpmworkqueueint $kgm_pm_next
end
set $kgm_pm_next = $kgm_pm_next->eventChainNext
end
end
document showallpmworkqueues
Syntax: (gdb) showallpmworkqueues
| Display info about all IOPMWorkQueue objects
end
define showioservicepm
set $kgm_iopmpriv = (IOServicePM *)$arg0
printf "{ this object = %08x", $kgm_iopmpriv->Owner
if ( $kgm_iopmpriv->WeAreRoot )
printf " (root)"
end
printf ", "
printf "MachineState = %d (", $kgm_iopmpriv->MachineState
if ( $kgm_iopmpriv->MachineState == 1 )
printf "kIOPM_OurChangeTellClientsPowerDown"
else
if ( $kgm_iopmpriv->MachineState == 2 )
printf "kIOPM_OurChangeTellPriorityClientsPowerDown"
else
if ( $kgm_iopmpriv->MachineState == 3 )
printf "kIOPM_OurChangeNotifyInterestedDriversWillChange"
else
if ( $kgm_iopmpriv->MachineState == 4 )
printf "kIOPM_OurChangeSetPowerState"
else
if ( $kgm_iopmpriv->MachineState == 5 )
printf "kIOPM_OurChangeWaitForPowerSettle"
else
if ( $kgm_iopmpriv->MachineState == 6 )
printf "kIOPM_OurChangeNotifyInterestedDriversDidChange"
else
if ( $kgm_iopmpriv->MachineState == 7 )
printf "kIOPM_OurChangeFinish"
else
if ( $kgm_iopmpriv->MachineState == 8 )
printf "kIOPM_ParentDownTellPriorityClientsPowerDown"
else
if ( $kgm_iopmpriv->MachineState == 9 )
printf "kIOPM_ParentDownNotifyInterestedDriversWillChange"
else
if ( $kgm_iopmpriv->MachineState == 10 )
printf "Unused_MachineState_10"
else
if ( $kgm_iopmpriv->MachineState == 11 )
printf "kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange"
else
if ( $kgm_iopmpriv->MachineState == 12 )
printf "kIOPM_ParentDownSetPowerState"
else
if ( $kgm_iopmpriv->MachineState == 13 )
printf "kIOPM_ParentDownWaitForPowerSettle"
else
if ( $kgm_iopmpriv->MachineState == 14 )
printf "kIOPM_ParentDownAcknowledgeChange"
else
if ( $kgm_iopmpriv->MachineState == 15)
printf "kIOPM_ParentUpSetPowerState"
else
if ( $kgm_iopmpriv->MachineState == 16)
printf "Unused_MachineState_16"
else
if ( $kgm_iopmpriv->MachineState == 17)
printf "kIOPM_ParentUpWaitForSettleTime"
else
if ( $kgm_iopmpriv->MachineState == 18)
printf "kIOPM_ParentUpNotifyInterestedDriversDidChange"
else
if ( $kgm_iopmpriv->MachineState == 19)
printf "kIOPM_ParentUpAcknowledgePowerChange"
else
if ( $kgm_iopmpriv->MachineState == 20)
printf "kIOPM_Finished"
else
if ( $kgm_iopmpriv->MachineState == 21)
printf "kIOPM_DriverThreadCallDone"
else
if ( $kgm_iopmpriv->MachineState == 22)
printf "kIOPM_NotifyChildrenDone"
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
end
printf "), "
if ( $kgm_iopmpriv->MachineState != 20 )
printf "DriverTimer = %d, ",(unsigned int)$kgm_iopmpriv->DriverTimer
printf "SettleTime = %d, ",(unsigned int)$kgm_iopmpriv->SettleTimeUS
printf "HeadNoteFlags = %08x, ",(unsigned int)$kgm_iopmpriv->HeadNoteFlags
printf "HeadNoteState = %d, ",(unsigned int)$kgm_iopmpriv->HeadNoteState
printf "HeadNoteOutputFlags = %08x, ",(unsigned int)$kgm_iopmpriv->HeadNoteOutputFlags
printf "HeadNoteDomainState = %08x, ",(unsigned int)$kgm_iopmpriv->HeadNoteDomainState
printf "HeadNoteCapabilityFlags = %08x, ",(unsigned int)$kgm_iopmpriv->HeadNoteCapabilityFlags
printf "HeadNotePendingAcks = %x, ",(unsigned int)$kgm_iopmpriv->HeadNotePendingAcks
end
if ( $kgm_iopmpriv->DeviceOverrides != 0 )
printf"DeviceOverrides, "
end
printf "DriverDesire = %d, ",(unsigned int)$kgm_iopmpriv->DriverDesire
printf "DeviceDesire = %d, ",(unsigned int)$kgm_iopmpriv->DeviceDesire
printf "DesiredPowerState = %d, ",(unsigned int)$kgm_iopmpriv->DesiredPowerState
printf "PreviousRequest = %d }",(unsigned int)$kgm_iopmpriv->PreviousRequest
end
document showioservicepm
Syntax: (gdb) showioservicepm <IOServicePM pointer>
| Routine to dump the IOServicePM object
end
define showregistryentryrecursepmstate
set $kgm_re = (IOService *)$arg1
set $kgm$arg0_stack = (unsigned long long) $arg2
if ($arg3)
set $kgm$arg0_stack = $kgm$arg0_stack | (1ULL << $kgm_reg_depth)
else
set $kgm$arg0_stack = $kgm$arg0_stack & ~(1ULL << $kgm_reg_depth)
end
dictget $kgm_re->fRegistryTable $kgm_childkey
set $kgm$arg0_child_array = (OSArray *) $kgm_result
if ($kgm$arg0_child_array)
set $kgm$arg0_child_count = $kgm$arg0_child_array->count
else
set $kgm$arg0_child_count = 0
end
if ($kgm$arg0_child_count)
set $kgm$arg0_stack = $kgm$arg0_stack | (2ULL << $kgm_reg_depth)
else
set $kgm$arg0_stack = $kgm$arg0_stack & ~(2ULL << $kgm_reg_depth)
end
indent $kgm_reg_depth $kgm$arg0_stack
printf "+-o "
dictget $kgm_re->fRegistryTable $kgm_namekey
if ($kgm_result == 0)
dictget $kgm_re->fRegistryTable gIONameKey
end
if ($kgm_result == 0)
dictget $kgm_re->fPropertyTable gIOClassKey
end
if ($kgm_result != 0)
printf "%s <%p>", ((OSString *)$kgm_result)->string, $kgm_re
else
if (((IOService*)$kgm_re)->pwrMgt && ((IOService*)$kgm_re)->pwrMgt->Name)
printf "%s <%p>", ((IOService*)$kgm_re)->pwrMgt->Name, $kgm_re
else
printf "?? <%p>", $kgm_re
end
end
if (((IOService*)$kgm_re)->pwrMgt )
printf " Current Power State: %ld ", ((IOService*)$kgm_re)->pwrMgt->CurrentPowerState
#printf " Mach State %ld", ((IOService*)$kgm_re)->pwrMgt->MachineState
showioservicepm ((IOService*)$kgm_re)->pwrMgt
end
printf "\n"
# recurse
if ($kgm$arg0_child_count != 0)
set $kgm_reg_depth = $kgm_reg_depth + 1
set $kgm$arg0_child_idx = 0
while ($kgm$arg0_child_idx < $kgm$arg0_child_count)
set $kgm_re = $kgm$arg0_child_array->array[$kgm$arg0_child_idx++]
set $kgm_more_sib = ($kgm$arg0_child_idx < $kgm$arg0_child_count)
showregistryentryrecursepmstate _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib
end
set $kgm_reg_depth = $kgm_reg_depth - 1
end
end
define showregistryentryintpmstate
set $kgm_namekey = (OSSymbol *) $kgm_reg_plane[2]
set $kgm_childkey = (OSSymbol *) $kgm_reg_plane[4]
showregistryentryrecursepmstate _ $arg0 0 0
end
define showregistrypmstate
# setregistryplane gIOPowerPlane
set $kgm_reg_depth = 0
set $kgm_show_props = 1
showregistryentryintpmstate gRegistryRoot
end
document showregistrypmstate
Syntax: (gdb) showregistrypmstate
| Routine to dump the PM state of each IOPower registry entry
end
define showstacksafterthread
set $kgm_head_taskp = &default_pset.tasks
set $kgm_actp = (struct thread *)$arg0
set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
set $kgm_taskp = (struct task *)$kgm_actp->task
while $kgm_taskp != $kgm_head_taskp
showtaskheader
showtaskint $kgm_taskp
set $kgm_head_actp = &($kgm_taskp->threads)
while $kgm_actp != $kgm_head_actp
showactheader
if ($decode_wait_events > 0)
showactint $kgm_actp 1
else
showactint $kgm_actp 2
end
set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
end
printf "\n"
set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next)
end
end
document showstacksafterthread
Syntax: (gdb) showstacksafterthread <thread>
| Routine to print out all stacks (as in showallstacks) starting after a given thread
| Useful if that gdb refuses to print a certain task's stack.
end
define kdp-reenter
set kdp_reentry_deadline = ((unsigned) $arg0)*1000
continue
end
document kdp-reenter
Syntax: (gdb) kdp-reenter <seconds>
| Schedules reentry into the debugger after <seconds> seconds, and resumes
| the target system.
end
define _if_present
if (!$arg0)
printf " not"
end
printf " present"
end
define showMCAstate
if ($kgm_mtype != 7)
printf "Not available for current architecture.\n"
else
printf "MCA"
_if_present mca_MCA_present
printf ", control MSR"
_if_present mca_control_MSR_present
printf ", threshold status"
_if_present mca_threshold_status_present
printf "\n%d error banks, ", mca_error_bank_count
printf "family code 0x%x, ", mca_family
printf "machine-check dump state: %d\n", mca_dump_state
set $kgm_cpu = 0
while cpu_data_ptr[$kgm_cpu] != 0
set $kgm_mcp = cpu_data_ptr[$kgm_cpu]->cpu_mca_state
if $kgm_mcp
printf "CPU %d:", $kgm_cpu
printf " mca_mcg_ctl: 0x%016llx", $kgm_mcp->mca_mcg_ctl
printf " mca_mcg_status: 0x%016llx\n", $kgm_mcp->mca_mcg_status.u64
printf "bank "
printf "mca_mci_ctl "
printf "mca_mci_status "
printf "mca_mci_addr "
printf "mca_mci_misc\n"
set $kgm_bank = 0
while $kgm_bank < mca_error_bank_count
set $kgm_bp = &$kgm_mcp->mca_error_bank[$kgm_bank]
printf " %2d:", $kgm_bank
printf " 0x%016llx", $kgm_bp->mca_mci_ctl
printf " 0x%016llx", $kgm_bp->mca_mci_status.u64
printf " 0x%016llx", $kgm_bp->mca_mci_addr
printf " 0x%016llx\n", $kgm_bp->mca_mci_misc
set $kgm_bank = $kgm_bank + 1
end
end
set $kgm_cpu = $kgm_cpu + 1
end
end
end
document showMCAstate
Syntax: showMCAstate
| Print machine-check register state after MC exception.
end
define _pt_step
#
# Step to lower-level page table and print attributes
# $kgm_pt_paddr: current page table entry physical address
# $kgm_pt_index: current page table entry index (0..511)
# returns
# $kgm_pt_paddr: next level page table entry physical address
# or null if invalid
# For $kgm_pt_verbose = 0: print nothing
# 1: print basic information
# 2: print basic information and hex table dump
# The trickery with kdp_src_high32 is required for accesses above 4GB.
#
set $kgm_entryp = $kgm_pt_paddr + 8*$kgm_pt_index
set kdp_src_high32 = $kgm_pt_paddr >> 32
set kdp_trans_off = 1
set $entry = *(pt_entry_t *)($kgm_entryp & 0x0ffffffffULL)
if $kgm_pt_verbose == 2
x/512g ($kgm_pt_paddr & 0x0ffffffffULL)
end
set kdp_trans_off = 0
set kdp_src_high32 = 0
set $kgm_paddr_mask = ~((0xffffULL<<48) | 0xfffULL)
if $kgm_pt_verbose == 0
if $entry & (0x1 << 0)
set $kgm_pt_paddr = $entry & $kgm_paddr_mask
else
set $kgm_pt_paddr = 0
end
else
printf "0x%016llx:\n\t0x%016llx\n\t", $kgm_entryp, $entry
if $entry & (0x1 << 0)
printf "valid"
set $kgm_pt_paddr = $entry & $kgm_paddr_mask
else
printf "invalid"
set $kgm_pt_paddr = 0
end
if $entry & (0x1 << 1)
printf " writeable"
else
printf " read-only"
end
if $entry & (0x1 << 2)
printf " user"
else
printf " supervisor"
end
if $entry & (0x1 << 3)
printf " PWT"
end
if $entry & (0x1 << 4)
printf " PCD"
end
if $entry & (0x1 << 5)
printf " accessed"
end
if $entry & (0x1 << 6)
printf " dirty"
end
if $entry & (0x1 << 7)
printf " PAT"
end
if $entry & (0x1 << 8)
printf " global"
end
if $entry & (0x3 << 9)
printf " avail:0x%x", ($entry >> 9) & 0x3
end
if $entry & (0x1 << 63)
printf " noexec"
end
printf "\n"
end
end
define _pmap_walk
set $kgm_pmap = (pmap_t) $arg0
set $kgm_vaddr = $arg1
set $kgm_pt_paddr = $kgm_pmap->pm_cr3
if $kgm_pt_paddr && cpu_64bit
set $kgm_pt_index = ($kgm_vaddr >> 39) & 0x1ffULL
if $kgm_pt_verbose
printf "pml4 (index %d):\n", $kgm_pt_index
end
_pt_step
end
if $kgm_pt_paddr
set $kgm_pt_index = ($kgm_vaddr >> 30) & 0x1ffULL
if $kgm_pt_verbose
printf "pdpt (index %d):\n", $kgm_pt_index
end
_pt_step
end
if $kgm_pt_paddr
set $kgm_pt_index = ($kgm_vaddr >> 21) & 0x1ffULL
if $kgm_pt_verbose
printf "pdt (index %d):\n", $kgm_pt_index
end
_pt_step
end
if $kgm_pt_paddr
set $kgm_pt_index = ($kgm_vaddr >> 12) & 0x1ffULL
if $kgm_pt_verbose
printf "pt (index %d):\n", $kgm_pt_index
end
_pt_step
end
if $kgm_pt_paddr
set $kgm_paddr = $kgm_pt_paddr + ($kgm_vaddr & 0xfffULL)
set kdp_trans_off = 1
set kdp_src_high32 = $kgm_paddr >> 32
set $kgm_value = *($kgm_paddr & 0x0ffffffffULL)
set kdp_trans_off = 0
set kdp_src_high32 = 0
printf "phys 0x%016llx: 0x%08x\n", $kgm_paddr, $kgm_value
else
set $kgm_paddr = 0
printf "(no translation)\n"
end
end
define pmap_walk
if $kgm_mtype != 7
printf "Not available for current architecture.\n"
else
if $argc != 2
printf "pmap_walk <pmap> <vaddr>\n"
else
if !$kgm_pt_verbose
set $kgm_pt_verbose = 1
else
if $kgm_pt_verbose != 2
set $kgm_pt_verbose = 1
end
end
_pmap_walk $arg0 $arg1
end
end
end
document pmap_walk
Syntax: (gdb) pmap_walk <pmap> <virtual_address>
| Perform a page-table walk in <pmap> for <virtual_address>.
| Set $kgm_pt_verbose=2 for full hex dump of page tables.
end
define pmap_vtop
if $kgm_mtype != 7
printf "Not available for current architecture.\n"
else
if $argc != 2
printf "pmap_vtop <pamp> <vaddr>\n"
else
set $kgm_pt_verbose = 0
_pmap_walk $arg0 $arg1
end
end
end
document pmap_vtop
Syntax: (gdb) pmap_vtop <pmap> <virtual_address>
| For page-tables in <pmap> translate <virtual_address> to physical address.
end
define zstack
set $index = $arg0
if (log_records == 0)
set $count = 0
printf "Zone logging not enabled. Add 'zlog=<zone name>' to boot-args.\n"
else
if ($argc == 2)
set $count = $arg1
else
set $count = 1
end
end
while ($count)
printf "\n--------------- "
if (zrecords[$index].z_opcode == 1)
printf "ALLOC "
else
printf "FREE "
end
printf " 0x%x : index %d : ztime %d -------------\n", zrecords[$index].z_element, $index, zrecords[$index].z_time
set $frame = 0
while ($frame < 15)
set $frame_pc = zrecords[$index].z_pc[$frame]
if ($frame_pc == 0)
loop_break
end
x/i $frame_pc
set $frame = $frame + 1
end
set $index = $index + 1
set $count = $count - 1
end
end
document zstack
Syntax: (gdb) zstack <index> [<count>]
| Zone leak debugging: print the stack trace of log element at <index>.
| If a <count> is supplied, it prints <count> log elements starting at <index>.
|
| The suggested usage is to look at indexes below zcurrent and look for common stack traces.
| The stack trace that occurs the most is probably the cause of the leak. Find the pc of the
| function calling into zalloc and use the countpcs kgmacro to find out how often that pc occurs in the log.
| The pc occuring in a high percentage of records is most likely the source of the leak.
|
| The findoldest kgmacro is also useful for leak debugging since it identifies the oldest record
| in the log, which may indicate the leaker.
end
define findoldest
set $index = 0
set $count = log_records
set $cur_min = 2000000000
set $cur_index = 0
if (log_records == 0)
printf "Zone logging not enabled. Add 'zlog=<zone name>' to boot-args.\n"
else
while ($count)
if (zrecords[$index].z_element && zrecords[$index].z_time < $cur_min)
set $cur_index = $index
set $cur_min = zrecords[$index].z_time
end
set $count = $count - 1
set $index = $index + 1
end
printf "oldest record is at log index %d:\n", $cur_index
zstack $cur_index
end
end
document findoldest
Syntax: (gdb) findoldest
| Zone leak debugging: find and print the oldest record in the log. Note that this command
| can take several minutes to run since it uses linear search.
|
| Once it prints a stack trace, find the pc of the caller above all the zalloc, kalloc and
| IOKit layers. Then use the countpcs kgmacro to see how often this caller has allocated
| memory. A caller with a high percentage of records in the log is probably the leaker.
end
define countpcs
set $target_pc = $arg0
set $index = 0
set $count = log_records
set $found = 0
if (log_records == 0)
printf "Zone logging not enabled. Add 'zlog=<zone name>' to boot-args.\n"
else
while ($count)
set $frame = 0
if (zrecords[$index].z_element != 0)
while ($frame < 15)
if (zrecords[$index].z_pc[$frame] == $target_pc)
set $found = $found + 1
set $frame = 15
end
set $frame = $frame + 1
end
end
set $index = $index + 1
set $count = $count - 1
end
printf "occurred %d times in log (%d%c of records)\n", $found, ($found * 100) / zrecorded, '%'
end
end
document countpcs
Syntax: (gdb) countpcs <pc>
| Zone leak debugging: search the log and print a count of all log entries that contain the given <pc>
| in the stack trace. This is useful for verifying a suspected <pc> as being the source of
| the leak. If a high percentage of the log entries contain the given <pc>, then it's most
| likely the source of the leak. Note that this command can take several minutes to run.
end
define findelem
set $fe_index = zcurrent
set $fe_count = log_records
set $fe_elem = $arg0
set $fe_prev_op = -1
if (log_records == 0)
printf "Zone logging not enabled. Add 'zlog=<zone name>' to boot-args.\n"
end
while ($fe_count)
if (zrecords[$fe_index].z_element == $fe_elem)
zstack $fe_index
if (zrecords[$fe_index].z_opcode == $fe_prev_op)
printf "*************** DOUBLE OP! *********************\n
end
set $fe_prev_op = zrecords[$fe_index].z_opcode
end
set $fe_count = $fe_count - 1
set $fe_index = $fe_index + 1
if ($fe_index >= log_records)
set $fe_index = 0
end
end
end
document findelem
Syntax: (gdb) findelem <elem addr>
| Zone corruption debugging: search the log and print out the stack traces for all log entries that
| refer to the given zone element. When the kernel panics due to a corrupted zone element, get the
| element address and use this macro. This will show you the stack traces of all logged zalloc and
| zfree operations which tells you who touched the element in the recent past. This also makes
| double-frees readily apparent.
end