blob: d1a666c741b14a424063b5f40908166e5d75bfa6 [file] [log] [blame]
#
# 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
|
| 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
|
| kdp-reboot Restart remote target
|
| 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_dummy = &proc0
set $kgm_dummy = &kmod
set $kgm_mtype = ((struct mach_header)_mh_execute_header).cputype
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
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
printf "\n"
end
document showkmodaddr
| Given an address, print the offset and name for the kmod containing it
| The following is the syntax:
| (gdb) showkmodaddr <addr>
end
define showkmod
showkmodheader
showkmodint $arg0
end
document showkmod
| Routine to print info about a kernel module
| The following is the syntax:
| (gdb) showkmod <kmod>
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
| Routine to print a summary listing of all the kernel modules
| The following is the syntax:
| (gdb) showallkmods
end
define showactheader
printf " activation "
printf "thread pri state wait_queue wait_event\n"
end
define showactint
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
if (((unsigned)$kgm_thread.wait_event > (unsigned)sectPRELINKB) \
&& ($arg1 != 2))
showkmodaddr $kgm_thread.wait_event
else
output /a (unsigned) $kgm_thread.wait_event
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
else
set $kgm_statep = (struct x86_kernel_state32 *) \
($kgm_thread->kernel_stack + 0x4000 \
- sizeof(struct x86_kernel_state32))
set $mysp = $kgm_statep->k_ebp
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))))
if ((unsigned) $kgm_return > (unsigned) sectPRELINKB)
showkmodaddr $kgm_return
else
if ((unsigned) $kgm_return > 0)
output /a (unsigned) $kgm_return
end
end
printf "\n\t\t0x%08x ", $mysp
if ($kgm_mtype == 18)
set $kgm_return = *($mysp + 8)
else
set $kgm_return = *($mysp + 4)
end
set $prevsp = $mysp
set $mysp = * $mysp
end
if ((unsigned) $kgm_return > 0)
output/a $kgm_return
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
| Routine to print out the state of a specific thread.
| The following is the syntax:
| (gdb) showact <activation>
end
define showactstack
showactheader
showactint $arg0 1
end
document showactstack
| Routine to print out the stack of a specific thread.
| The following is the syntax:
| (gdb) showactstack <activation>
end
define showallthreads
set $kgm_head_taskp = &default_pset.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->pset_tasks.next)
end
end
document showallthreads
| Routine to print out info about all threads in the system.
| The following is the syntax:
| (gdb) showallthreads
end
define showcurrentthreads
set $kgm_prp = processor_list
while $kgm_prp != 0
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
| Routine to print out info about the thread running on each cpu.
| The following is the syntax:
| (gdb) showcurrentthreads
end
set $decode_wait_events = 0
define showallstacks
set $kgm_head_taskp = &default_pset.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->pset_tasks.next)
end
end
document showallstacks
| Routine to print out the stack for each thread in the system.
| The following is the syntax:
| (gdb) showallstacks
| 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
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
| Routine to print out the thread running on each cpu (incl. its stack)
| The following is the syntax:
| (gdb) showcurrentstacks
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
| Routine to print out a summary listing of all the entries in a vm_map
| The following is the syntax:
| (gdb) showmapvme <vm_map>
end
define showmap
showmapheader
showvmint $arg0 0
end
document showmap
| Routine to print out info about the specified vm_map
| The following is the syntax:
| (gdb) showmap <vm_map>
end
define showallvm
set $kgm_head_taskp = &default_pset.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->pset_tasks.next)
end
end
document showallvm
| Routine to print a summary listing of all the vm maps
| The following is the syntax:
| (gdb) showallvm
end
define showallvme
set $kgm_head_taskp = &default_pset.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->pset_tasks.next)
end
end
document showallvme
| Routine to print a summary listing of all the vm map entries
| The following is the syntax:
| (gdb) showallvme
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
| Routine to print the status of the specified ipc space
| The following is the syntax:
| (gdb) showipc <ipc_space>
end
define showrights
set $kgm_isp = (ipc_space_t)$arg0
showipcheader
showipcint $kgm_isp 1
end
document showrights
| Routine to print a summary list of all the rights in a specified ipc space
| The following is the syntax:
| (gdb) showrights <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
| Routine to print info about the ipc space for a task
| The following is the syntax:
| (gdb) showtaskipc <task>
end
define showtaskrights
set $kgm_taskp = (task_t)$arg0
showtaskheader
showipcheader
showtaskint $kgm_taskp
showipcint $kgm_taskp->itk_space 1
end
document showtaskrights
| Routine to print info about the ipc rights for a task
| The following is the syntax:
| (gdb) showtaskrights <task>
end
define showallipc
set $kgm_head_taskp = &default_pset.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->pset_tasks.next)
end
end
document showallipc
| Routine to print a summary listing of all the ipc spaces
| The following is the syntax:
| (gdb) showallipc
end
define showallrights
set $kgm_head_taskp = &default_pset.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->pset_tasks.next)
end
end
document showallrights
| Routine to print a summary listing of all the ipc rights
| The following is the syntax:
| (gdb) showallrights
end
define showtaskvm
set $kgm_taskp = (task_t)$arg0
showtaskheader
showmapheader
showtaskint $kgm_taskp
showvmint $kgm_taskp->map 0
end
document showtaskvm
| Routine to print out info about a task's vm_map
| The following is the syntax:
| (gdb) showtaskvm <task>
end
define showtaskvme
set $kgm_taskp = (task_t)$arg0
showtaskheader
showmapheader
showtaskint $kgm_taskp
showvmint $kgm_taskp->map 1
end
document showtaskvme
| Routine to print out info about a task's vm_map_entries
| The following is the syntax:
| (gdb) showtaskvme <task>
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
| Routine to print out info about a task.
| The following is the syntax:
| (gdb) showtask <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
| Routine to print info about the threads in a task.
| The following is the syntax:
| (gdb) showtaskthreads <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
| Routine to print out the stack for each thread in a task.
| The following is the syntax:
| (gdb) showtaskstacks <task>
end
define showalltasks
showtaskheader
set $kgm_head_taskp = &default_pset.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->pset_tasks.next)
end
end
document showalltasks
| Routine to print a summary listing of all the tasks
| The following is the syntax:
| (gdb) showalltasks
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 = &default_pset.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->pset_tasks.next)
end
end
end
document showpid
| Routine to print a single process by pid
| The following is the syntax:
| (gdb) showpid <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 = &default_pset.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->pset_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
| Routine to print a summary listing of all the kernel zones
| The following is the syntax:
| (gdb) zprint
end
define showmtxgrp
set $kgm_mtxgrp = (lck_grp_t *)$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 = (lck_grp_t *)&lck_grp_queue
set $kgm_mtxgrp_ptr = (lck_grp_t *)$kgm_mtxgrp_ptr->lck_grp_link.next
while ($kgm_mtxgrp_ptr != (lck_grp_t *)&lck_grp_queue)
showmtxgrp $kgm_mtxgrp_ptr
set $kgm_mtxgrp_ptr = (lck_grp_t *)$kgm_mtxgrp_ptr->lck_grp_link.next
end
printf "\n"
end
document showallmtx
| Routine to print a summary listing of all mutexes
| The following is the syntax:
| (gdb) showallmtx
end
define showrwlckgrp
set $kgm_rwlckgrp = (lck_grp_t *)$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 = (lck_grp_t *)&lck_grp_queue
set $kgm_rwlckgrp_ptr = (lck_grp_t *)$kgm_rwlckgrp_ptr->lck_grp_link.next
while ($kgm_rwlckgrp_ptr != (lck_grp_t *)&lck_grp_queue)
showrwlckgrp $kgm_rwlckgrp_ptr
set $kgm_rwlckgrp_ptr = (lck_grp_t *)$kgm_rwlckgrp_ptr->lck_grp_link.next
end
printf "\n"
end
document showallrwlck
| Routine to print a summary listing of all read/writer locks
| The following is the syntax:
| (gdb) showallrwlck
end
set $kdp_act_counter = 0
define switchtoact
set $newact = (struct thread *) $arg0
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 $newact = (struct thread *) $arg0
set (struct savearea *) kdp.saved_state=$newact->machine->pcb
flushregs
flushstack
set $pc=$newact->machine->pcb.save_srr0
update
else
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
end
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
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
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
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
else
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
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
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_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_cur_ebp = $kgm_prev_ebp
set $kgm_prev_ebp = *((uint32_t *) $kgm_cur_ebp)
set $kgm_prev_eip = *((uint32_t *) ($kgm_cur_ebp + 4))
set $kgm_frameno = $kgm_frameno + 1
end
set $kgm_cur_ebp = 0
set $kgm_cur_eip = 0
set kdp_pmap = 0
end
define showuserstack
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
set $newact = (struct thread *) $arg0
set $newiss = (x86_saved_state32_t *) ($newact->machine.pcb->iss)
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
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
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 disableDebugOuput = 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
#Use of this macro requires the gdb submission from 3401283
define switchtocorethread
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
if ($newact->kernel_stack == 0)
echo This thread does not have a stack.\n
echo continuation:
output/a (unsigned) $newact.continuation
echo \n
else
loadcontext $newact->machine->pcb
# flushstack will be introduced in a gdb version > gdb-357
flushstack
set $pc = $newact->machine->pcb.save_srr0
end
else
echo switchtocorethread not implemented for this architecture.\n
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
set $pc = $arg0.save_srr0
set $r1 = $arg0.save_r1
set $lr = $arg0.save_lr
set $r2 = $arg0.save_r2
set $r3 = $arg0.save_r3
set $r4 = $arg0.save_r4
set $r5 = $arg0.save_r5
set $r6 = $arg0.save_r6
set $r7 = $arg0.save_r7
set $r8 = $arg0.save_r8
set $r9 = $arg0.save_r9
set $r10 = $arg0.save_r10
set $r11 = $arg0.save_r11
set $r12 = $arg0.save_r12
set $r13 = $arg0.save_r13
set $r14 = $arg0.save_r14
set $r15 = $arg0.save_r15
set $r16 = $arg0.save_r16
set $r17 = $arg0.save_r17
set $r18 = $arg0.save_r18
set $r19 = $arg0.save_r19
set $r20 = $arg0.save_r20
set $r21 = $arg0.save_r21
set $r22 = $arg0.save_r22
set $r23 = $arg0.save_r23
set $r24 = $arg0.save_r24
set $r25 = $arg0.save_r25
set $r26 = $arg0.save_r26
set $r27 = $arg0.save_r27
set $r28 = $arg0.save_r28
set $r29 = $arg0.save_r29
set $r30 = $arg0.save_r30
set $r31 = $arg0.save_r31
set $cr = $arg0.save_cr
set $ctr = $arg0.save_ctr
end
define resetcorectx
set $kgm_corecontext = (struct savearea *) kdp.saved_state
loadcontext $kgm_corecontext
# Maintaining this act counter wouldn't be necessary if we just initialized
# $kdpstate at the beginning of the macro..
set $kdp_act_counter = 0
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
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
else
set $kgm_statep = (struct x86_kernel_state32 *) \
($kgm_thread->kernel_stack + 0x4000 \
- sizeof(struct x86_kernel_state32))
set $mysp = $kgm_statep->k_ebp
end
set $prevsp = 0
printf "\n\t\tstacktop=0x%08x", $mysp
switchtoact $arg0
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 = &default_pset.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
set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next)
end
printf "\n"
set $kgm_taskp = (struct task *)($kgm_taskp->pset_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 switchtouserthread
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_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
| Show info about an OSObject - its vtable ptr and retain count.
| If the object is a simple container class, more info will be shown.
| The following is the syntax:
| (gdb) showobject <object address>
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)->pm_vars && ((IOService*)$kgm_re)->pm_vars->ourName)
printf "%s", ((IOService*)$kgm_re)->pm_vars->ourName
else
# printf ", guessclass "
# guessclass $kgm_re
printf "??"
end
end
printf " <object %p, ", $kgm_re
printf "vtable "
set $kgm_vt = (unsigned) *(void**) $kgm_re
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
| Show info about all registry entries in the current plane.
| The following is the syntax:
| (gdb) showregistry
end
define showregistryprops
set $kgm_reg_depth = 0
set $kgm_show_props = 1
showregistryentryint gRegistryRoot
end
document 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
| The following is the syntax:
| (gdb) showregistryprops
end
define showregistryentry
set $kgm_reg_depth = 0
set $kgm_show_props = 1
showregistryentryint $arg0
end
document showregistryentry
| Show info about a registry entry; its properties and descendants in the current plane.
| The following is the syntax:
| (gdb) showregistryentry <object address>
end
define setregistryplane
if ($arg0)
set $kgm_reg_plane = (void **) $arg0
else
showobjectint _ gIORegistryPlanes
printf "\n"
end
end
document setregistryplane
| Set the plane to be used for the iokit registry macros. An argument of zero will
| display known planes.
| The following is the syntax:
| (gdb) setregistryplane <plane object address>
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
| Show the instance counts and ivar size of all OSObject subclasses. See ioclasscount man page for details.
| The following is the syntax:
| (gdb) showallclasses
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
| Show some accounting of memory allocated by IOKit allocators. See ioalloccount man page for details.
| The following is the syntax:
| (gdb) showioalloc
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