Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
10331 lines (9450 sloc) 285 KB
# 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
# 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.
set backtrace sanity-checks off
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
| showallbusyports Display a listing of all ports with unread messages
|
| 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)
|
| setfindregistrystr Set the encoded string for matching with
| findregistryentry or findregistryprop (created from
| strcmp_arg_pack64)
| findregistryentry Find a registry entry that matches the encoded string
| findregistryentries Find all the registry entries that match the encoded string
| findregistryprop Search the registry entry for a property that matches
| the encoded string
|
| 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
| showtaskrightsbt Display info about the task's ipc space entries with back traces
| showtaskbusyports Display all of the task's ports with unread messages
|
| 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
| sendsyslog Configure kernel to send a system log to the specified IP
| sendpaniclog Configure kernel to send a panic log to the specified IP
| disablecore Configure the kernel to disable coredump transmission
| getdumpinfo Retrieve the current remote dump parameters
| setdumpinfo Configure the remote dump parameters
|
| switchtocorethread Corefile version of "switchtoact"
| resetcorectx Corefile version of "resetctx"
|
| readphys8 Reads the specified untranslated address (8-bit read)
| readphys16 Reads the specified untranslated address (16-bit read)
| readphys32 Reads the specified untranslated address (32-bit read)
| readphys64 Reads the specified untranslated address (64-bit read)
| writephys8 Writes to the specified untranslated address (8-bit write)
| writephys16 Writes to the specified untranslated address (16-bit write)
| writephys32 Writes to the specified untranslated address (32-bit write)
| writephys64 Writes to the specified untranslated address (64-bit write)
|
| readioport8 Read 8-bits from the specified I/O Port
| readioport16 Read 16-bits from the specified I/O Port
| readioport32 Read 32-bits from the specified I/O Port
| writeioport8 Write 8-bits into the specified I/O Port
| writeioport16 Write 16-bits into the specified I/O Port
| writeioport32 Write 32-bits into the specified I/O Port
|
| readmsr64 Read 64-bits from the specified MSR
| writemsr64 Write 64-bits into the specified MSR
|
| rtentry_showdbg Print the debug information of a route entry
| rtentry_trash Walk the list of trash route entries
|
| inifa_showdbg Print the debug information of an IPv4 interface address
| in6ifa_showdbg Print the debug information of an IPv6 interface address
|
| 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
|
| showbootargs Display boot arguments passed to the target kernel
| showbootermemorymap Dump phys memory map from EFI
|
| systemlog Display the kernel's printf ring buffer
|
| hexdump Show the contents of memory as a hex/ASCII dump
|
| showvnodepath Print the path for a vnode
| showvnodelocks Display list of advisory locks held/blocked on a vnode
| showvnodedev Display information about a device vnode
| showtty Display information about a struct tty
| 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
|
| showsocket Display information about a socket
| showprocsockets Given a proc_t pointer, display information about its sockets
| showallprocsockets Display information about the sockets of all the processes
|
| show_tcp_pcbinfo Display the list of the TCP protocol control blocks
| show_tcp_timewaitslots Display the list of the TCP protocol control blocks in TIMEWAIT
| show_udp_pcbinfo Display the list of UDP protocol control blocks
|
| show_rt_inet Display the IPv4 routing table
| show_rt_inet6 Display the IPv6 routing table
|
| 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
| kdp-version Get KDP version number
| kdp-connect "shorthand" connection macro
|
| 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
|
| pmap_walk Perform a page-table walk
| pmap_vtop Translate a virtual address to physical address
|
| showuserlibraries Show binary images known by dyld in the target task
|
| showthreadfortid Displays the address of the thread structure for a given thread_id value.
|
| strcmp_nomalloc A version of strcmp that avoids the use of malloc
| through the use of encoded strings created via
| strcmp_arg_pack64.
| strcmp_arg_pack64 Pack a string into a 64-bit quantity for use by
| strcmp_nomalloc
|
| pci_cfg_read8 Read 8-bits from a PCI config space register
| pci_cfg_read16 Read 16-bits from a PCI config space register
| pci_cfg_read32 Read 32-bits from a PCI config space register
| pci_cfg_write8 Write 8-bits into a PCI config space register
| pci_cfg_write16 Write 16-bits into a PCI config space register
| pci_cfg_write32 Write 32-bits into a PCI config space register
| pci_cfg_dump Dump entire config space for a PCI device
| pci_cfg_scan Perform a scan for PCI devices
| pci_cfg_dump_all Dump config spaces for all detected PCI devices
|
| lapic_read32 Read APIC entry
| lapic_write32 Write APIC entry
| lapic_dump Dump APIC entries
|
| ioapic_read32 Read IOAPIC entry
| ioapic_write32 Write IOAPIC entry
| ioapic_dump Dump IOAPIC entries
|
| 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
kdp-kernelversion
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_ppc = 0x00000012
set $kgm_mtype_arm = 0x0000000C
set $kgm_mtype_i386 = 0x00000007
set $kgm_mtype_x86_64 = 0x01000007
set $kgm_mtype_x86_any = $kgm_mtype_i386
set $kgm_mtype_x86_mask = 0xFEFFFFFF
set $kgm_mtype = ((unsigned int *)&_mh_execute_header)[1]
set $kgm_lp64 = $kgm_mtype & 0x01000000
set $kgm_manual_pkt_ppc = 0x549C
set $kgm_manual_pkt_i386 = 0x249C
set $kgm_manual_pkt_x86_64 = 0xFFFFFF8000002930
set $kgm_manual_pkt_arm = 0xFFFF04A0
set $kgm_kdp_pkt_data_len = 128
# part of data packet
set $kgm_kdp_pkt_hdr_req_off = 0
set $kgm_kdp_pkt_hdr_seq_off = 1
set $kgm_kdp_pkt_hdr_len_off = 2
set $kgm_kdp_pkt_hdr_key_off = 4
# after data packet
set $kgm_kdp_pkt_len_off = $kgm_kdp_pkt_data_len
set $kgm_kdp_pkt_input_off = $kgm_kdp_pkt_data_len + 4
set $kgm_kdp_pkt_hostreboot = 0x13
set $kgm_kdp_pkt_hdr_size = 8
set $kgm_lcpu_self = 0xFFFE
set $kgm_reg_depth = 0
set $kgm_reg_depth_max = 0xFFFF
set $kgm_reg_plane = (IORegistryPlane *) 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_data_alwaysbytes = 0
set $kgm_show_kmod_syms = 0
# send a manual packet header that doesn't require knowing the location
# of everything.
define manualhdrint
set $req = $arg0
set $hdrp = (uint32_t *) $kgm_manual_pkt_i386
if ($kgm_mtype == $kgm_mtype_ppc)
set $hdrp = (uint32_t *) $kgm_manual_pkt_ppc
set $req = $req << 1 # shift to deal with endiannness
end
if ($kgm_mtype == $kgm_mtype_x86_64)
set $hdrp = (uint64_t *) $kgm_manual_pkt_x86_64
end
if ($kgm_mtype == $kgm_mtype_arm)
set $hdrp = (uint32_t *) $kgm_manual_pkt_arm
end
set $pkt_hdr = *$hdrp
set *((uint8_t *) ($pkt_hdr + $kgm_kdp_pkt_input_off)) = 0
set *((uint32_t *) ($pkt_hdr + $kgm_kdp_pkt_len_off)) = $kgm_kdp_pkt_hdr_size
set *((uint8_t *) ($pkt_hdr + $kgm_kdp_pkt_hdr_req_off)) = $req
set *((uint8_t *) ($pkt_hdr + $kgm_kdp_pkt_hdr_seq_off)) = 0
set *((uint16_t *) ($pkt_hdr + $kgm_kdp_pkt_hdr_len_off)) = $kgm_kdp_pkt_hdr_size
set *((uint32_t *) ($pkt_hdr + $kgm_kdp_pkt_hdr_key_off)) = 0
set *((uint8_t *) ($pkt_hdr + $kgm_kdp_pkt_input_off)) = 1
# dummy to make sure manual packet is executed
set $kgm_dummy = &_mh_execute_header
end
# Print a pointer
define showptr
if $kgm_lp64
printf "0x%016llx", $arg0
else
printf "0x%08x", $arg0
end
end
# for headers, leave 8 chars for LP64 pointers
define showptrhdrpad
if $kgm_lp64
printf " "
end
end
define showkmodheader
printf "kmod "
showptrhdrpad
printf " address "
showptrhdrpad
printf " size "
showptrhdrpad
printf " id refs version name\n"
end
define showkmodint
set $kgm_kmodp = (struct kmod_info *)$arg0
showptr $kgm_kmodp
printf " "
showptr $kgm_kmodp->address
printf " "
showptr $kgm_kmodp->size
printf " "
printf "%3d ", $kgm_kmodp->id
printf "%5d ", $kgm_kmodp->reference_count
printf "%10s ", $kgm_kmodp->version
printf "%s\n", $kgm_kmodp->name
end
# cached info of the last kext found, to speed up subsequent lookups
set $kgm_pkmod = 0
set $kgm_pkmodst = 0
set $kgm_pkmoden = 0
define showkmodaddrint
showptr $arg0
if ((unsigned long)$arg0 >= (unsigned long)$kgm_pkmodst) && ((unsigned long)$arg0 < (unsigned long)$kgm_pkmoden)
set $kgm_off = ((unsigned long)$arg0 - (unsigned long)$kgm_pkmodst)
printf " <%s + 0x%x>", $kgm_pkmod->name, $kgm_off
else
set $kgm_kmodp = (struct kmod_info *)kmod
if ($kgm_mtype == $kgm_mtype_x86_64) && ($arg0 >= (unsigned long)&_mh_execute_header)
# kexts are loaded below the kernel for x86_64
set $kgm_kmodp = 0
end
while $kgm_kmodp
set $kgm_off = ((unsigned long)$arg0 - (unsigned long)$kgm_kmodp->address)
if ($kgm_kmodp->address <= $arg0) && ($kgm_off < $kgm_kmodp->size)
printf " <%s + 0x%x>", $kgm_kmodp->name, $kgm_off
set $kgm_pkmod = $kgm_kmodp
set $kgm_pkmodst = $kgm_kmodp->address
set $kgm_pkmoden = $kgm_pkmodst + $kgm_kmodp->size
set $kgm_kmodp = 0
else
set $kgm_kmodp = $kgm_kmodp->next
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 " "
showptrhdrpad
printf " thread "
showptrhdrpad
printf " thread_id "
showptrhdrpad
printf " processor "
showptrhdrpad
printf " pri io_policy state wait_queue"
showptrhdrpad
printf " wait_event\n"
end
define showactint
printf " "
showptrhdrpad
set $kgm_thread = *(struct thread *)$arg0
showptr $arg0
if ($kgm_thread.static_param)
printf "[WQ]"
else
printf " "
end
printf " %7ld ", $kgm_thread.thread_id
showptr $kgm_thread.last_processor
printf " %3d ", $kgm_thread.sched_pri
if ($kgm_thread.uthread != 0)
set $kgm_printed = 0
set $kgm_uthread = (struct uthread *)$kgm_thread.uthread
if ($kgm_uthread->uu_flag & 0x400)
printf "RAGE "
else
printf " "
end
if ($kgm_uthread->uu_iopol_disk == 1)
printf "NORM "
set $kgm_printed = 1
end
if ($kgm_uthread->uu_iopol_disk == 2)
printf "PASS "
set $kgm_printed = 1
end
if ($kgm_uthread->uu_iopol_disk == 3)
printf "THROT "
set $kgm_printed = 1
end
if ($kgm_printed == 0)
printf " "
end
end
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"
printf "\t "
showptr $kgm_thread.wait_queue
printf " "
if (((unsigned long)$kgm_thread.wait_event > (unsigned long)&last_kernel_symbol) \
&& ($arg1 != 2) && ($kgm_show_kmod_syms == 0))
showkmodaddr $kgm_thread.wait_event
else
output /a $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 "\t \"%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 "
showptrhdrpad
printf " reserved_stack="
showptr $kgm_thread.reserved_stack
end
printf "\n "
showptrhdrpad
printf " kernel_stack="
showptr $kgm_thread.kernel_stack
if ($kgm_mtype == $kgm_mtype_ppc)
set $mysp = $kgm_thread.machine.pcb->save_r1
end
if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any)
set $kgm_statep = (struct x86_kernel_state *) \
($kgm_thread->kernel_stack + kernel_stack_size \
- sizeof(struct x86_kernel_state))
if ($kgm_mtype == $kgm_mtype_i386)
set $mysp = $kgm_statep->k_ebp
else
set $mysp = $kgm_statep->k_rbp
end
end
if ($kgm_mtype == $kgm_mtype_arm)
if (((unsigned long)$r7 < ((unsigned long) ($kgm_thread->kernel_stack+kernel_stack_size))) \
&& ((unsigned long)$r7 > (unsigned long) ($kgm_thread->kernel_stack)))
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 "
showptrhdrpad
printf " stacktop="
showptr $mysp
if ($kgm_mtype == $kgm_mtype_ppc)
set $stkmask = 0xf
else
set $stkmask = 0x3
end
set $kgm_return = 0
while ($mysp != 0) && (($mysp & $stkmask) == 0) \
&& ($mysp != $prevsp) \
&& ((((unsigned long) $mysp ^ (unsigned long) $prevsp) < 0x2000) \
|| (((unsigned long)$mysp < ((unsigned long) ($kgm_thread->kernel_stack+kernel_stack_size))) \
&& ((unsigned long)$mysp > (unsigned long) ($kgm_thread->kernel_stack))))
printf "\n "
showptrhdrpad
printf " "
showptr $mysp
printf " "
if ($kgm_mtype == $kgm_mtype_ppc)
set $kgm_return = *($mysp + 8)
end
if ($kgm_mtype == $kgm_mtype_i386)
set $kgm_return = *($mysp + 4)
end
if ($kgm_mtype == $kgm_mtype_x86_64)
set $kgm_return = *(unsigned long *)($mysp + 8)
end
if ($kgm_mtype == $kgm_mtype_arm)
set $kgm_return = *($mysp + 4)
end
if (((unsigned long) $kgm_return < (unsigned long) &_mh_execute_header || \
(unsigned long) $kgm_return >= (unsigned long) &last_kernel_symbol ) \
&& ($kgm_show_kmod_syms == 0))
showkmodaddr $kgm_return
else
output /a $kgm_return
end
set $prevsp = $mysp
set $mysp = *(unsigned long *)$mysp
end
set $kgm_return = 0
printf "\n "
showptrhdrpad
printf " stackbottom="
showptr $prevsp
else
printf "\n "
showptrhdrpad
printf " continuation="
output /a $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_id
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_id
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 thread "
printf "processor pri state wait_queue wait_event\n"
end
define showwaitqwaiters
set $kgm_w_waitqp = (WaitQueue*)$arg0
set $kgm_w_linksp = &($kgm_w_waitqp->wq_queue)
set $kgm_w_wqe = (WaitQueueElement *)$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 = (WaitQueueElement *)$kgm_w_wqe->wqe_links.next
end
end
define showwaitqwaitercount
set $kgm_wc_waitqp = (WaitQueue*)$arg0
set $kgm_wc_linksp = &($kgm_wc_waitqp->wq_queue)
set $kgm_wc_wqe = (WaitQueueElement *)$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) && ($kgm_wc_wqe->wqe_type != &_wait_queue_link_noalloc)
set $kgm_wc_count = $kgm_wc_count + 1
end
set $kgm_wc_wqe = (WaitQueueElement *)$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 = (WaitQueueLink *)$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 = (WaitQueueLink *)$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 = (WaitQueue*)$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 = (WaitQueue*)$arg0
set $kgm_mo_linksp = &($kgm_mo_waitqp->wq_queue)
set $kgm_mo_wqe = (WaitQueueElement *)$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 = (WaitQueueLink *)$kgm_mo_wqe
set $kgm_mo_wqsetp = (WaitQueue*)($kgm_mo_wqlp->wql_setqueue)
showwaitqmemberint $kgm_mo_wqsetp
end
set $kgm_mo_wqe = (WaitQueueElement *)$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 = (WaitQueueLink *)$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 = (WaitQueueLink *)$kgm_ms_wql->wql_setlinks.next
end
end
define showwaitqheader
printf "wait_queue prepostq interlock "
printf "pol type member_cnt waiter_cnt\n"
end
define showwaitqint
set $kgm_waitqp = (WaitQueue *)$arg0
printf "0x%08x ", $kgm_waitqp
if ($kgm_waitqp->wq_type == 0xf1d1)
printf "0x%08x ", &((struct wait_queue_set *)$kgm_waitqp)->wqs_preposts
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 = (WaitQueue*)$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 "
showptrhdrpad
printf " pmap "
showptrhdrpad
printf " vm_size "
showptrhdrpad
printf " #ents rpage hint "
showptrhdrpad
printf " first_free\n"
end
define showvmeheader
printf " entry "
showptrhdrpad
printf " start prot #page object "
showptrhdrpad
printf " offset\n"
end
define showvmint
set $kgm_mapp = (vm_map_t)$arg0
set $kgm_map = *$kgm_mapp
showptr $arg0
printf " "
showptr $kgm_map.pmap
printf " "
showptr $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
showptr $kgm_map.hint
printf " "
showptr $kgm_map.first_free
printf "\n"
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 " "
showptr $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 "%6d ",($kgm_vme.links.end - $kgm_vme.links.start) >> 12
showptr $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 showmapwiredp
set $kgm_mapp = (vm_map_t)$arg0
set $kgm_map = *$kgm_mapp
set $kgm_head_vmep = &($kgm_mapp->hdr.links)
set $kgm_vmep = $kgm_map.hdr.links.next
set $kgm_objp_prev = (struct vm_object *)0
if $arg1 == 0
set $kgm_saw_kernel_obj = 0
set $kgm_wired_count = 0
set $kgm_objp_print_space = 1
else
set $kgm_objp_print_space = 0
end
while (($kgm_vmep != 0) && ($kgm_vmep != $kgm_head_vmep))
set $kgm_vme = *$kgm_vmep
set $kgm_objp = $kgm_vme.object.vm_object
if $kgm_vme.is_sub_map
if $arg1 == 0
set $kgm_mapp_orig = $kgm_mapp
set $kgm_vmep_orig = $kgm_vmep
set $kgm_vme_orig = $kgm_vme
set $kgm_head_vmep_orig = $kgm_head_vmep
printf "\n****"
showptr $kgm_objp
showmapwiredp $kgm_objp 1
set $kgm_vme = $kgm_vme_orig
set $kgm_vmep = $kgm_vmep_orig
set $kgm_mapp = $kgm_mapp_orig
set $kgm_head_vmep = $kgm_head_vmep_orig
set $kgm_objp = (struct vm_object *)0
else
printf "\n????"
showptr $kgm_mapp
printf " "
showptr $kgm_vmep
set $kgm_objp = (struct vm_object *)0
printf "\n"
end
end
if ($kgm_objp == $kgm_objp_prev)
set $kgm_objp = (struct vm_object *)0
end
if $kgm_objp == kernel_object
if $kgm_saw_kernel_obj
set $kgm_objp = (struct vm_object *)0
end
set $kgm_saw_kernel_obj = 1
end
if $kgm_objp && $kgm_objp->wired_page_count
if $kgm_objp_print_space == 1
printf " "
showptr $kgm_mapp
end
set $kgm_objp_print_space = 1
printf " "
showptr $kgm_vmep
printf " 0x%016llx ", $kgm_vme.links.start
printf "%5d", $kgm_vme.alias
printf "%6d ",($kgm_vme.links.end - $kgm_vme.links.start) >> 12
showptr $kgm_objp
printf "[%3d]", $kgm_objp->ref_count
printf "%7d\n", $kgm_objp->wired_page_count
set $kgm_wired_count = $kgm_wired_count + $kgm_objp->wired_page_count
set $kgm_objp_prev = $kgm_objp
end
set $kgm_vmep = $kgm_vme.links.next
end
if $arg1 == 0
printf "total wired count = %d\n", $kgm_wired_count
end
end
define showmapwired
printf " map "
showptrhdrpad
printf " entry "
showptrhdrpad
printf " start alias #page object "
showptrhdrpad
printf " wired\n"
showmapwiredp $arg0 0
end
document showmapwired
Syntax: (gdb) showmapwired <vm_map>
| Routine to print out a summary listing of all the entries with wired pages in a vm_map
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 "
showptrhdrpad
printf " is_table "
showptrhdrpad
printf " table_next"
showptrhdrpad
printf " flags tsize splaytree splaybase\n"
end
define showipceheader
printf " name object "
showptrhdrpad
printf " rite urefs destname destination\n"
end
define showipceint
set $kgm_ie = *(ipc_entry_t)$arg0
printf " 0x%08x ", $arg1
showptr $kgm_ie.ie_object
printf " "
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
showptr $arg0
printf " "
showptr $kgm_is.is_table
printf " "
showptr $kgm_is.is_table_next
printf " "
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
showptr &$kgm_isp->is_tree
printf "\n"
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
if $arg2 != 0 && ipc_portbt != 0
if $kgm_ie.ie_object != 0 && ($kgm_ie.ie_bits & 0x00070000) && ((ipc_port_t) $kgm_ie.ie_object)->ip_callstack[0] != 0
printf " user bt: "
showportbt $kgm_ie.ie_object $kgm_is.is_task
end
end
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 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 0
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 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 0
end
document showtaskrights
Syntax: (gdb) showtaskrights <task>
| Routine to print info about the ipc rights for a task
end
define showtaskrightsbt
set $kgm_taskp = (task_t)$arg0
showtaskheader
showipcheader
showtaskint $kgm_taskp
showipcint $kgm_taskp->itk_space 1 1
end
document showtaskrightsbt
Syntax: (gdb) showtaskrightsbt <task>
| Routine to print info about the ipc rights for a task with backtraces
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 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 0
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 "
showptrhdrpad
printf " vm_map "
showptrhdrpad
printf " ipc_space "
showptrhdrpad
printf " #acts "
showprocheader
end
define showtaskint
set $kgm_taskp = (struct task *)$arg0
showptr $arg0
printf " "
showptr $kgm_taskp->map
printf " "
showptr $kgm_taskp->itk_space
printf " %5d ", $kgm_taskp->thread_count
showprocint $kgm_taskp->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
| wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items"
| if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung
| io_policy -> RAGE - rapid aging of vnodes requested
| NORM - normal I/O explicitly requested (this is the default)
| PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions)
| THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes)
end
define showprocheader
printf " pid process io_policy wq_state"
showptrhdrpad
printf " command\n"
end
define showprocint
set $kgm_procp = (struct proc *)$arg0
if $kgm_procp != 0
set $kgm_printed = 0
printf "%5d ", $kgm_procp->p_pid
showptr $kgm_procp
if ($kgm_procp->p_lflag & 0x400000)
printf " RAGE "
else
printf " "
end
if ($kgm_procp->p_iopol_disk == 1)
printf "NORM "
set $kgm_printed = 1
end
if ($kgm_procp->p_iopol_disk == 2)
printf "PASS "
set $kgm_printed = 1
end
if ($kgm_procp->p_iopol_disk == 3)
printf "THROT "
set $kgm_printed = 1
end
if ($kgm_printed == 0)
printf " "
end
set $kgm_wqp = (struct workqueue *)$kgm_procp->p_wqptr
if $kgm_wqp != 0
printf " %2d %2d %2d ", $kgm_wqp->wq_nthreads, $kgm_wqp->wq_thidlecount, $kgm_wqp->wq_itemcount
else
printf " "
end
printf " %s\n", $kgm_procp->p_comm
else
printf " *0* "
showptr 0
printf " --\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
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
showptr $kgm_portp->ip_kobject
printf " 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
if ($kgm_kotype == 34)
printf "FD"
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 "
showptr $kgm_desttaskp
printf "\n"
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)
showptr $kgm_portp->ip_messages.data.port.receiver_name
printf " "
showportdestproc $kgm_portp
else
showptr $kgm_portp
printf " inactive-port\n"
end
end
end
define showportmember
printf " 0x%08x ", $arg0
set $kgm_portp = (struct ipc_port *)$arg0
printf "0x%08x ", $kgm_portp->ip_messages.data.port.receiver_name
if ($kgm_portp->ip_object.io_bits & 0x80000000)
printf "A"
else
printf " "
end
printf "Port"
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 showportbt
set $kgm_iebt = ((ipc_port_t) $arg0)->ip_callstack
set $kgm_iepid = ((ipc_port_t) $arg0)->ip_spares[0]
set $kgm_procpid = ((proc_t) (((task_t) $arg1)->bsd_info))->p_pid
if $kgm_iebt[0] != 0
showptr $kgm_iebt[0]
set $kgm_iebt_loop_ctr = 1
while ($kgm_iebt_loop_ctr < 16 && $kgm_iebt[$kgm_iebt_loop_ctr])
printf " "
showptr $kgm_iebt[$kgm_iebt_loop_ctr]
set $kgm_iebt_loop_ctr = $kgm_iebt_loop_ctr + 1
end
if $kgm_iepid != $kgm_procpid
printf " (%d)", $kgm_iepid
end
printf "\n"
end
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_messages.data.port.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_messages.data.pset.local_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_messages.data.pset.local_name
set $kgm_setlinksp = &($kgm_psetp->ips_messages.data.pset.set_queue.wqs_setlinks)
set $kgm_wql = (WaitQueueLink *)$kgm_setlinksp->next
set $kgm_found = 0
while ( (queue_entry_t)$kgm_wql != (queue_entry_t)$kgm_setlinksp)
set $kgm_portp = (struct ipc_port *)((uintptr_t)$kgm_wql->wql_element.wqe_queue - $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 = (WaitQueueLink *)$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 = (uintptr_t)&(((struct ipc_pset *)0)->ips_messages)
set $kgm_portoff = (uintptr_t)&(((struct ipc_port *)0)->ip_messages)
if ($kgm_mqueue.data.pset.set_queue.wqs_wait_queue.wq_type == 0xf1d1)
set $kgm_psetp = (struct ipc_pset *)(((uintptr_t)$arg0) - $kgm_psetoff)
showpsetheader
showpsetint $kgm_psetp 1
end
if ($kgm_mqueue.data.pset.set_queue.wqs_wait_queue.wq_type == 0xf1d0)
set $kgm_portp = (struct ipc_port *)(((uintptr_t)$arg0) - $kgm_portoff)
showportheader
showportint $kgm_portp 1
end
end
define zprint_one
set $kgm_zone = (struct zone *)$arg0
showptr $kgm_zone
printf " %6d ",$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
if ($kgm_zone->noencrypt)
printf "$"
end
printf "\n"
end
define zprint
printf "ZONE "
showptrhdrpad
printf " 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)
showptr $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 "
showptrhdrpad
printf " 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)
showptr $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 "
showptrhdrpad
printf " 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 == $kgm_mtype_ppc)
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 == $kgm_mtype_i386)
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_state *) \
($newact->kernel_stack + kernel_stack_size \
- sizeof(struct x86_kernel_state))
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 == $kgm_mtype_x86_64)
set $kdpstatep = (struct x86_saved_state64 *) 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_state *) \
($newact->kernel_stack + kernel_stack_size \
- sizeof(struct x86_kernel_state))
set $kdpstatep->rbx = $kgm_statep->k_rbx
set $kdpstatep->rbp = $kgm_statep->k_rbp
set $kdpstatep->r12 = $kgm_statep->k_r12
set $kdpstatep->r13 = $kgm_statep->k_r13
set $kdpstatep->r14 = $kgm_statep->k_r14
set $kdpstatep->r15 = $kgm_statep->k_r15
set $kdpstatep->isf.rsp = $kgm_statep->k_rsp
flushregs
flushstack
set $pc = $kgm_statep->k_rip
update
end
if ($kgm_mtype == $kgm_mtype_arm)
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 == $kgm_mtype_ppc)
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 == $kgm_mtype_arm)
set arm disassembler std
select-frame 0
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 == $kgm_mtype_ppc)
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 == $kgm_mtype_i386)
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 == $kgm_mtype_x86_64)
set $kdpstatep = (struct x86_saved_state64 *) kdp.saved_state
set *($kdpstatep)=$kdpstate
flushregs
flushstack
set $pc=$kdpstatep->isf.rip
update
set $kdp_act_counter = 0
end
if ($kgm_mtype == $kgm_mtype_arm)
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 $resume = KDP_DUMPINFO_SETINFO | KDP_DUMPINFO_RESUME
dumpinfoint $resume
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 = KDP_DUMPINFO_SETINFO | KDP_DUMPINFO_NORESUME
dumpinfoint $noresume
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", *(char *)$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 = $arg0
set $kgm_callentry = $kgm_callhead->next
set $kgm_i = 0
while $kgm_callentry != $kgm_callhead
set $kgm_call = (struct call_entry *)$kgm_callentry
printf "0x%08x ", $kgm_call
printf "0x%08x 0x%08x ", $kgm_call->param0, $kgm_call->param1
output $kgm_call->deadline
printf "\t"
output $kgm_call->func
printf "\n"
set $kgm_i = $kgm_i + 1
set $kgm_callentry = $kgm_callentry->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
# Internal routine used by "_loadfrom" to read from 64-bit addresses
# on 32-bit kernels
define _loadk32m64
# set up the manual KDP packet
set manual_pkt.input = 0
set manual_pkt.len = sizeof(kdp_readmem64_req_t)
set $kgm_pkt = (kdp_readmem64_req_t *)&manual_pkt.data
set $kgm_pkt->hdr.request = KDP_READMEM64
set $kgm_pkt->hdr.len = sizeof(kdp_readmem64_req_t)
set $kgm_pkt->hdr.is_reply = 0
set $kgm_pkt->hdr.seq = 0
set $kgm_pkt->hdr.key = 0
set $kgm_pkt->address = (uint64_t)$arg0
set $kgm_pkt->nbytes = sizeof(uint64_t)
set manual_pkt.input = 1
# dummy to make sure manual packet is executed
set $kgm_dummy = &_mh_execute_header
set $kgm_pkt = (kdp_readmem64_reply_t *)&manual_pkt.data
if ($kgm_pkt->error == 0)
set $kgm_k32read64 = *(uint64_t *)$kgm_pkt->data
else
set $kgm_k32read64 = 0
end
end
# Internal routine used by "showx86backtrace" to abstract possible loads from
# user space
define _loadfrom
if (kdp_pmap == 0)
set $kgm_loadval = *(uintptr_t *)$arg0
else
if ($kgm_x86_abi == 0xe)
set $kgm_loadval = *(uint32_t *)$arg0
else
if ($kgm_x86_abi == 0xf)
if ($kgm_mtype == $kgm_mtype_i386)
_loadk32m64 $arg0
set $kgm_loadval = $kgm_k32read64
else
set $kgm_loadval = *(uint64_t *)$arg0
end
end
end
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_frame = 0
set $kgm_cur_pc = 0
set $kgm_x86_abi = 0
define showx86backtrace
if ($kgm_mtype == $kgm_mtype_i386)
set $kgm_frame_reg = $ebp
set $kgm_pc = $eip
set $kgm_ret_off = 4
end
if ($kgm_mtype == $kgm_mtype_x86_64)
set $kgm_frame_reg = $rbp
set $kgm_pc = $rip
set $kgm_ret_off = 8
end
if ($kgm_x86_abi == 0xe)
set $kgm_ret_off = 4
end
if ($kgm_x86_abi == 0xf)
set $kgm_ret_off = 8
end
if ($kgm_cur_frame == 0)
set $kgm_cur_frame = $kgm_frame_reg
end
if ($kgm_cur_pc == 0)
set $kgm_cur_pc = $kgm_pc
end
printf "0: Frame: 0x%016llx PC: 0x%016llx\n", $kgm_cur_frame, $kgm_cur_pc
if (!(($kgm_x86_abi == 0xf) && ($kgm_mtype == $kgm_mtype_i386)))
x/i $kgm_cur_pc
end
set $kgm_tmp_frame = $kgm_cur_frame
set $kgm_cur_frame = 0
set $kgm_cur_pc = 0
_loadfrom ($kgm_tmp_frame)
set $kgm_prev_frame = $kgm_loadval
_loadfrom ($kgm_tmp_frame+$kgm_ret_off)
set $kgm_prev_pc = $kgm_loadval
set $kgm_frameno = 1
while $kgm_prev_frame != 0
printf "%d: Saved frame: 0x%016llx Saved PC: 0x%016llx\n", $kgm_frameno, $kgm_prev_frame, $kgm_prev_pc
if (!(($kgm_x86_abi == 0xf) && ($kgm_mtype == $kgm_mtype_i386)))
x/i $kgm_prev_pc
end
_loadfrom ($kgm_prev_frame+$kgm_ret_off)
set $kgm_prev_pc = $kgm_loadval
_loadfrom ($kgm_prev_frame)
set $kgm_prev_frame = $kgm_loadval
set $kgm_frameno = $kgm_frameno + 1
end
set kdp_pmap = 0
set $kgm_x86_abi = 0
end
define showx86backtrace2
set $kgm_cur_frame = $arg0
set $kgm_cur_pc = $arg1
showx86backtrace
end
define showuserstack
select 0
if ($kgm_mtype == $kgm_mtype_ppc)
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 & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any)
set $newact = (struct thread *) $arg0
set $newiss = (x86_saved_state_t *) ($newact->machine.pcb->iss)
set $kgm_x86_abi = $newiss.flavor
if ($newiss.flavor == 0xf)
set $checkpc = $newiss.uss.ss_64.isf.rip
set $checkframe = $newiss.uss.ss_64.rbp
else
set $checkpc = $newiss.uss.ss_32.eip
set $checkframe = $newiss.uss.ss_32.ebp
end
if ($checkpc == 0)
echo This activation does not appear to have
echo \20 a valid user context.\n
else
set $kgm_cur_frame = $checkframe
set $kgm_cur_pc = $checkpc
printf "You may now issue the showx86backtrace command to see the user space backtrace for this thread ("
showptr $arg0
printf "); you can also examine memory locations in this address space (pmap "
showptr $newact->task->map->pmap
printf ") 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"
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
define kdp-reboot
# Alternatively, set *(*(unsigned **) 0x2498) = 1
# (or 0x5498 on PPC, 0xffffff8000002928 on x86_64, 0xffff049c on arm)
manualhdrint $kgm_kdp_pkt_hostreboot
continue
end
document kdp-reboot
Syntax: kdp-reboot
|Reboot the remote target machine; not guaranteed to succeed.
end
define kdpversionint
# set up the manual KDP packet
set manual_pkt.input = 0
set manual_pkt.len = sizeof(kdp_version_req_t)
set $kgm_pkt = (kdp_version_req_t *)&manual_pkt.data
set $kgm_pkt->hdr.request = KDP_VERSION
set $kgm_pkt->hdr.len = sizeof(kdp_version_req_t)
set $kgm_pkt->hdr.is_reply = 0
set $kgm_pkt->hdr.seq = 0
set $kgm_pkt->hdr.key = 0
set manual_pkt.input = 1
# dummy to make sure manual packet is executed
set $kgm_dummy = &_mh_execute_header
set $kgm_pkt = (kdp_version_reply_t *)&manual_pkt.data
set $kgm_kdp_version = $kgm_pkt->version
set $kgm_kdp_feature = $kgm_pkt->feature
end
define kdp-version
kdpversionint
printf "KDP VERSION = %d, FEATURE = 0x%x\n", $kgm_kdp_version, $kgm_kdp_feature
end
document kdp-version
Syntax: kdp-version
|Get the KDP protocol version being used by the kernel.
end
define dumpinfoint
# set up the manual KDP packet
set manual_pkt.input = 0
set manual_pkt.len = sizeof(kdp_dumpinfo_req_t)
set $kgm_pkt = (kdp_dumpinfo_req_t *)manual_pkt.data
set $kgm_pkt->hdr.request = KDP_DUMPINFO
set $kgm_pkt->hdr.len = sizeof(kdp_dumpinfo_req_t)
set $kgm_pkt->hdr.is_reply = 0
set $kgm_pkt->hdr.seq = 0
set $kgm_pkt->hdr.key = 0
set $kgm_pkt->type = $arg0
set $kgm_pkt->name = ""
set $kgm_pkt->destip = ""
set $kgm_pkt->routerip = ""
set $kgm_pkt->port = 0
if $argc > 1
set $kgm_pkt->name = "$arg1"
end
if $argc > 2
set $kgm_pkt->destip = "$arg2"
end
if $argc > 3
set $kgm_pkt->routerip = "$arg3"
end
if $argc > 4
set $kgm_pkt->port = $arg4
end
set manual_pkt.input = 1
# dummy to make sure manual packet is executed
set $kgm_dummy = &_mh_execute_header
end
define sendcore
if $argc > 1
dumpinfoint KDP_DUMPINFO_CORE $arg1 $arg0
else
dumpinfoint KDP_DUMPINFO_CORE \0 $arg0
end
end
document sendcore
Syntax: sendcore <IP address> [filename]
|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. You can
|optionally specify the filename to be used for the generated core file.
end
define sendsyslog
if $argc > 1
dumpinfoint KDP_DUMPINFO_SYSTEMLOG $arg1 $arg0
else
dumpinfoint KDP_DUMPINFO_SYSTEMLOG \0 $arg0
end
end
document sendsyslog
Syntax: sendsyslog <IP address> [filename]
|Configure the kernel to transmit a kernel system log to a server (kdumpd)
|at the specified IP address. NOTE: You must issue a "continue"
|command after using this macro to trigger the kernel system log. The kernel
|will resume waiting in the debugger after completion. You can optionally
|specify the name to be used for the generated system log.
end
define sendpaniclog
if panicstr
if $argc > 1
dumpinfoint KDP_DUMPINFO_PANICLOG $arg1 $arg0
else
dumpinfoint KDP_DUMPINFO_PANICLOG \0 $arg0
end
else
printf "No panic log available.\n"
end
end
document sendpaniclog
Syntax: sendpaniclog <IP address> [filename]
|Configure the kernel to transmit a kernel paniclog to a server (kdumpd)
|at the specified IP address. NOTE: You must issue a "continue"
|command after using this macro to trigger the kernel panic log. The kernel
|will resume waiting in the debugger after completion. You can optionally
|specify the name to be used for the generated panic log.
end
define getdumpinfo
dumpinfoint KDP_DUMPINFO_GETINFO
set $kgm_dumpinfo = (kdp_dumpinfo_reply_t *) manual_pkt.data
if $kgm_dumpinfo->type & KDP_DUMPINFO_REBOOT
printf "System will reboot after kernel info gets dumped.\n"
else
printf "Sysem will not reboot after kernel info gets dumped.\n"
end
if $kgm_dumpinfo->type & KDP_DUMPINFO_NORESUME
printf "System will allow a re-attach after a KDP disconnect.\n"
else
printf "System will resume after a KDP disconnect.\n"
end
set $kgm_dumpinfo_type = $kgm_dumpinfo->type & KDP_DUMPINFO_MASK
if $kgm_dumpinfo_type == KDP_DUMPINFO_DISABLE
printf "Kernel not setup for remote dumps.\n"
else
printf "Remote dump type: "
if $kgm_dumpinfo_type == KDP_DUMPINFO_CORE
printf "Core file\n"
end
if $kgm_dumpinfo_type == KDP_DUMPINFO_PANICLOG
printf "Panic log\n"
end
if $kgm_dumpinfo_type == KDP_DUMPINFO_SYSTEMLOG
printf "System log\n"
end
printf "Name: "
if $kgm_dumpinfo->name[0] == '\0'
printf "(autogenerated)\n"
else
printf "%s\n", $kgm_dumpinfo->name
end
printf "Network Info: %s[%d] ", $kgm_dumpinfo->destip, $kgm_dumpinfo->port
if $kgm_dumpinfo->routerip[0] == '\0'
printf "\n"
else
printf "Router: %s\n", $kgm_dumpinfo->routerip
end
end
end
document getdumpinfo
Syntax: getdumpinfo
|Retrieve the current remote dump settings.
end
define setdumpinfo
dumpinfoint KDP_DUMPINFO_SETINFO $arg0 $arg1 $arg2 $arg3
end
document setdumpinfo
Syntax: setdumpinfo <filename> <ip> <router> <port>
|Configure the current remote dump settings. Specify \0 if you
|want to use the defaults (filename) or previously configured
|settings (ip/router). Specify 0 for the port if you wish to
|use the previously configured/default setting for that.
end
define disablecore
dumpinfoint KDP_DUMPINFO_DISABLE
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 == $kgm_mtype_ppc)
loadcontext $newact->machine->pcb
flushstack
set $pc = $newact->machine->pcb.save_srr0
else
if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any)
set $kgm_cstatep = (struct x86_kernel_state *) \
($newact->kernel_stack + kernel_stack_size \
- sizeof(struct x86_kernel_state))
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 == $kgm_mtype_ppc)
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 == $kgm_mtype_i386)
set $kgm_contextp = (struct x86_kernel_state *) $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
if ($kgm_mtype == $kgm_mtype_x86_64)
set $kgm_contextp = (struct x86_kernel_state *) $arg0
set $rbx = $kgm_contextp->k_rbx
set $rbp = $kgm_contextp->k_rbp
set $r12 = $kgm_contextp->k_r12
set $r13 = $kgm_contextp->k_r13
set $r14 = $kgm_contextp->k_r14
set $r15 = $kgm_contextp->k_r15
set $rip = $kgm_contextp->k_rip
set $pc = $kgm_contextp->k_rip
else
echo loadcontext not supported on this architecture\n
end
end
end
end
define resetcorectx
select 0
if ($kgm_mtype == $kgm_mtype_ppc)
set $kgm_corecontext = (struct savearea *) kdp.saved_state
loadcontext $kgm_corecontext
else
if ($kgm_mtype == $kgm_mtype_i386)
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 == $kgm_mtype_ppc)
set $mysp = $kgm_thread.machine.pcb->save_r1
end
if ($kgm_mtype == $kgm_mtype_i386)
set $kgm_statep = (struct x86_kernel_state *) \
($kgm_thread->kernel_stack + kernel_stack_size \
- sizeof(struct x86_kernel_state))
set $mysp = $kgm_statep->k_ebp
end
if ($kgm_mtype == $kgm_mtype_arm)
if (((unsigned long)$r7 < ((unsigned long) ($kgm_thread->kernel_stack+kernel_stack_size))) \
&& ((unsigned long)$r7 > (unsigned long) ($kgm_thread->kernel_stack)))
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 == $kgm_mtype_ppc)
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 showdatabytes
set $kgm_data = (OSData *)$arg0
printf "<"
set $kgm_datap = (const unsigned char *) $kgm_data->data
set $kgm_idx = 0
while ( $kgm_idx < $kgm_data->length )
printf "%02X", *$kgm_datap
set $kgm_datap = $kgm_datap + 1
set $kgm_idx = $kgm_idx + 1
end
printf ">\n"
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_lp64 || $kgm_mtype == $kgm_mtype_arm)
set $kgm_vt = $kgm_vt - 2 * sizeof(void *)
end
if ($kgm_show_object_addrs)
printf "`object "
showptr $arg1
printf ", vt "
output /a (unsigned long) $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
# No multiple-inheritance
set $kgm_shown = 0
if ($kgm_vt == &_ZTV8OSString)
showstring $arg1
set $kgm_shown = 1
end
if ($kgm_vt == &_ZTV8OSSymbol)
showstring $arg1
set $kgm_shown = 1
end
if ($kgm_vt == &_ZTV8OSNumber)
shownumber $arg1
set $kgm_shown = 1
end
if ($kgm_vt == &_ZTV6OSData)
if $kgm_show_data_alwaysbytes == 1
showdatabytes $arg1
else
showdata $arg1
end
set $kgm_shown = 1
end
if ($kgm_vt == &_ZTV9OSBoolean)
showboolean $arg1
set $kgm_shown = 1
end
if ($kgm_vt == &_ZTV12OSDictionary)
showdictionaryint _$arg0 $arg1
set $kgm_shown = 1
end
if ($kgm_vt == &_ZTV7OSArray)
showarrayint _$arg0 $arg1
set $kgm_shown = 1
end
if ($kgm_vt == &_ZTV5OSSet)
showsetint _$arg0 $arg1
set $kgm_shown = 1
end
if ($kgm_shown != 1)
if ($kgm_show_object_addrs == 0)
printf "`object "
showptr $arg1
printf ", vt "
output /a (unsigned long) $kgm_vt
printf "`"
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 _registryentryrecurseinit
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
end
define findregistryentryrecurse
set $kgm_registry_entry = 0
_registryentryrecurseinit $arg0 $arg1 $arg2 $arg3
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)
set $str = ((OSString *) $kgm_result)->string
strcmp_nomalloc $str $kgm_reg_find_str0 $kgm_reg_find_str1 $kgm_reg_find_str2 $kgm_reg_find_str3 $kgm_reg_find_str4 $kgm_reg_find_str5 $kgm_reg_find_str6 $kgm_reg_find_str7 $kgm_reg_find_str8
if $kgm_findregistry_verbose
echo .
end
if $kgm_strcmp_result == 0
if $kgm_findregistry_verbose
printf "\n%s:\n | ", ((OSString *) $kgm_result)->string
showobject $kgm_re
printf " | "
print $kgm_re
end
# if we want to show everything, then don't populate $kgm_registry_entry
if !$kgm_findregistry_continue
set $kgm_registry_entry = $kgm_re
end
end
end
# recurse
if (!$kgm_registry_entry && ($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)
if $kgm_reg_depth >= $kgm_reg_depth_max + 1
loop_break
end
findregistryentryrecurse _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib
if $kgm_registry_entry
loop_break
end
end
set $kgm_reg_depth = $kgm_reg_depth - 1
end
end
define findregdictvalue
set $kgm_registry_value = 0
set $kgm_reg_idx = 0
while ($kgm_reg_idx < $arg0->count)
set $kgm_obj = $arg0->dictionary + $kgm_reg_idx
set $str = ((OSString *)$kgm_obj->key)->string
strcmp_nomalloc $str $kgm_reg_find_str0 $kgm_reg_find_str1 $kgm_reg_find_str2 $kgm_reg_find_str3 $kgm_reg_find_str4 $kgm_reg_find_str5 $kgm_reg_find_str6 $kgm_reg_find_str7 $kgm_reg_find_str8
if $kgm_strcmp_result == 0
set $kgm_registry_value = $kgm_obj->value
if $kgm_findregistry_verbose
showobject $kgm_registry_value
print $kgm_registry_value
end
loop_break
end
set $kgm_reg_idx = $kgm_reg_idx + 1
end
end
define setfindregistrystr
set $kgm_reg_find_str0 = 0
set $kgm_reg_find_str1 = 0
set $kgm_reg_find_str2 = 0
set $kgm_reg_find_str3 = 0
set $kgm_reg_find_str4 = 0
set $kgm_reg_find_str5 = 0
set $kgm_reg_find_str6 = 0
set $kgm_reg_find_str7 = 0
set $kgm_reg_find_str8 = 0
if $argc > 0
set $kgm_reg_find_str0 = $arg0
end
if $argc > 1
set $kgm_reg_find_str1 = $arg1
end
if $argc > 2
set $kgm_reg_find_str2 = $arg2
end
if $argc > 3
set $kgm_reg_find_str3 = $arg3
end
if $argc > 4
set $kgm_reg_find_str4 = $arg4
end
if $argc > 5
set $kgm_reg_find_str5 = $arg5
end
if $argc > 6
set $kgm_reg_find_str6 = $arg6
end
if $argc > 7
set $kgm_reg_find_str7 = $arg7
end
if $argc > 8
set $kgm_reg_find_str8 = $arg8
end
end
document setfindregistrystr
Syntax: (gdb) setfindregistrystr [a] [b] [c] [d] [e] [f] [g] [h] [i]
| Store an encoded string into up to 9 arguments for use by
| findregistryprop or findregistryentry. The arguments are created
| through calls to strcmp_arg_pack64
end
define _findregistryprop
set $reg = (IOService *) $arg0
set $kgm_props = $reg->fPropertyTable
set $kgm_findregistry_verbose = 0
findregdictvalue $kgm_props
end
define findregistryprop
set $reg = (IOService *) $arg0
set $kgm_props = $reg->fPropertyTable
set $kgm_findregistry_verbose = 1
findregdictvalue $kgm_props
end
document findregistryprop
Syntax: (gdb) findregistryprop <entry>
| Given a registry entry, print out the contents for the property that matches
| the encoded string specified via setfindregistrystr.
|
| For example, the following will print out the "intel-pic" property stored in
| the AppleACPIPlatformExpert registry entry $pe_entry:
| strcmp_arg_pack64 'i' 'n' 't' 'e' 'l' '-' 'p' 'i'
| set $intel_pi = $kgm_strcmp_arg
| strcmp_arg_pack64 'c' 0 0 0 0 0 0 0
| set $c = $kgm_strcmp_arg
| setfindregistrystr $intel_pi $c
| findregistryprop $pe_entry
end
define findregistryentryint
if !$kgm_reg_plane
set $kgm_reg_plane = (IORegistryPlane *) gIOServicePlane
end
if !$kgm_reg_plane
printf "Please load kgmacros after KDP attaching to the target.\n"
else
set $kgm_namekey = (OSSymbol *) $kgm_reg_plane->nameKey
set $kgm_childkey = (OSSymbol *) $kgm_reg_plane->keys[1]
if $kgm_findregistry_verbose
printf "Searching"
end
findregistryentryrecurse _ $arg0 0 0
end
end
define _findregistryentry
set $kgm_findregistry_verbose = 0
set $kgm_findregistry_continue = 0
set $kgm_reg_depth = 0
findregistryentryint gRegistryRoot
end
define findregistryentry
set $kgm_findregistry_verbose = 1
set $kgm_findregistry_continue = 0
set $kgm_reg_depth = 0
findregistryentryint gRegistryRoot
end
define findregistryentries
set $kgm_findregistry_verbose = 1
set $kgm_findregistry_continue = 1
set $kgm_reg_depth = 0
findregistryentryint gRegistryRoot
end
document findregistryentry
Syntax: (gdb) findregistryentry
| Search for a registry entry that matches the encoded string specified through
| setfindregistrystr. You can alter the search depth through use of
| $kgm_reg_depth_max.
|
| For example, the following will pull out the AppleACPIPlatformExpert registry
| entry:
| strcmp_arg_pack64 'A' 'p' 'p' 'l' 'e' 'A' 'C' 'P'
| set $AppleACP = $kgm_strcmp_arg
| strcmp_arg_pack64 'I' 'P' 'l' 'a' 't' 'f' 'o' 'r'
| set $IPlatfor = $kgm_strcmp_arg
| strcmp_arg_pack64 'm' 'E' 'x' 'p' 'e' 'r' 't' 0
| set $mExpert = $kgm_strcmp_arg
| setfindregistrystr $AppleACP $IPlatfor $mExpert
| findregistryentry
end
document findregistryentries
Syntax: (gdb) findregistryentries
| Search for all registry entries that match the encoded string specified through
| setfindregistrystr. You can alter the search depth through use of
| $kgm_reg_depth_max. See findregistryentry for an example of how to encode a string.
end
define showregistryentryrecurse
_registryentryrecurseinit $arg0 $arg1 $arg2 $arg3
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 "
showptr $kgm_re
printf ", id 0x%llx, ", $kgm_re->IORegistryEntry::reserved->fRegistryEntryID
printf "vtable "
set $kgm_vt = (unsigned long) *(void**) $kgm_re
if ($kgm_lp64 || $kgm_mtype == $kgm_mtype_arm)
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)
if $kgm_reg_depth >= $kgm_reg_depth_max + 1
loop_break
end
showregistryentryrecurse _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib
end
set $kgm_reg_depth = $kgm_reg_depth - 1
end
end
define showregistryentryint
if !$kgm_reg_plane
set $kgm_reg_plane = (IORegistryPlane *) gIOServicePlane
end
if !$kgm_reg_plane
printf "Please load kgmacros after KDP attaching to the target.\n"
else
set $kgm_namekey = (OSSymbol *) $kgm_reg_plane->nameKey
set $kgm_childkey = (OSSymbol *) $kgm_reg_plane->keys[1]
showregistryentryrecurse _ $arg0 0 0
end
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. You can specify the maximum
| display depth with $kgm_reg_depth_max.
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 != 0)
set $kgm_reg_plane = (IORegistryPlane *) $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 long) $kgm_next->bt[$kgm_idx] > (unsigned long) &last_kernel_symbol)
showkmodaddr $kgm_next->bt[$kgm_idx]
printf "\n"
else
if ((unsigned long) $kgm_next->bt[$kgm_idx] > 0)
output /a $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 readphysint
set $kgm_readphysint_result = 0xBAD10AD
# set up the manual KDP packet
set manual_pkt.input = 0
set manual_pkt.len = sizeof(kdp_readphysmem64_req_t)
set $kgm_pkt = (kdp_readphysmem64_req_t *)&manual_pkt.data
set $kgm_pkt->hdr.request = KDP_READPHYSMEM64
set $kgm_pkt->hdr.len = sizeof(kdp_readphysmem64_req_t)
set $kgm_pkt->hdr.is_reply = 0
set $kgm_pkt->hdr.seq = 0
set $kgm_pkt->hdr.key = 0
set $kgm_pkt->address = (uint64_t)$arg0
set $kgm_pkt->nbytes = $arg1 >> 3
set $kgm_pkt->lcpu = $arg2
set manual_pkt.input = 1
# dummy to make sure manual packet is executed
set $kgm_dummy = &_mh_execute_header
set $kgm_pkt = (kdp_readphysmem64_reply_t *)&manual_pkt.data
if ($kgm_pkt->error == 0)
if $arg1 == 8
set $kgm_readphysint_result = *((uint8_t *)$kgm_pkt->data)
end
if $arg1 == 16
set $kgm_readphysint_result = *((uint16_t *)$kgm_pkt->data)
end
if $arg1 == 32
set $kgm_readphysint_result = *((uint32_t *)$kgm_pkt->data)
end
if $arg1 == 64
set $kgm_readphysint_result = *((uint64_t *)$kgm_pkt->data)
end
end
end
define readphys8
readphysint $arg0 8 $kgm_lcpu_self
output /a $arg0
printf ":\t0x%02hhx\n", $kgm_readphysint_result
set $kgm_readphys_result = (uint64_t)$kgm_readphysint_result
end
define readphys16
readphysint $arg0 16 $kgm_lcpu_self
output /a $arg0
printf ":\t0x%04hx\n", $kgm_readphysint_result
set $kgm_readphys_result = (uint64_t)$kgm_readphysint_result
end
define readphys32
readphysint $arg0 32 $kgm_lcpu_self
output /a $arg0
printf ":\t0x%08x\n", $kgm_readphysint_result
set $kgm_readphys_result = (uint64_t)$kgm_readphysint_result
end
define readphys64
readphysint $arg0 64 $kgm_lcpu_self
output /a $arg0
printf ":\t0x%016llx\n", $kgm_readphysint_result
set $kgm_readphys_result = (uint64_t)$kgm_readphysint_result
end
define readphys
readphys32 $arg0
end
document readphys8
| See readphys64
end
document readphys16
| See readphys64
end
document readphys32
| See readphys64
end
document readphys64
| The argument is interpreted as a physical address, and the 64-bit word
| addressed is displayed. Saves 64-bit result in $kgm_readphys_result.
end
define writephysint
# set up the manual KDP packet
set manual_pkt.input = 0
set manual_pkt.len = sizeof(kdp_writephysmem64_req_t)
set $kgm_pkt = (kdp_writephysmem64_req_t *)&manual_pkt.data
set $kgm_pkt->hdr.request = KDP_WRITEPHYSMEM64
set $kgm_pkt->hdr.len = sizeof(kdp_writephysmem64_req_t)
set $kgm_pkt->hdr.is_reply = 0
set $kgm_pkt->hdr.seq = 0
set $kgm_pkt->hdr.key = 0
set $kgm_pkt->address = (uint64_t)$arg0
set $kgm_pkt->nbytes = $arg1 >> 3
set $kgm_pkt->lcpu = $arg3
if $arg1 == 8
set *(uint8_t *)$kgm_pkt->data = (uint8_t)$arg2
end
if $arg1 == 16
set *(uint16_t *)$kgm_pkt->data = (uint16_t)$arg2
end
if $arg1 == 32
set *(uint32_t *)$kgm_pkt->data = (uint32_t)$arg2
end
if $arg1 == 64
set *(uint64_t *)$kgm_pkt->data = (uint64_t)$arg2
end
set manual_pkt.input = 1
# dummy to make sure manual packet is executed
set $kgm_dummy = &_mh_execute_header
set $kgm_pkt = (kdp_writephysmem64_reply_t *)&manual_pkt.data
set $kgm_writephysint_result = $kgm_pkt->error
end
define writephys8
writephysint $arg0 8 $arg1 $kgm_lcpu_self
end
define writephys16
writephysint $arg0 16 $arg1 $kgm_lcpu_self
end
define writephys32
writephysint $arg0 32 $arg1 $kgm_lcpu_self
end
define writephys64
writephysint $arg0 64 $arg1 $kgm_lcpu_self
end
document writephys8
| See writephys64
end
document writephys16
| See writephys64
end
document writephys32
| See writephys64
end
document writephys64
| The argument is interpreted as a physical address, and the second argument is
| written to that address as a 64-bit word.
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 "
showptrhdrpad
printf " fg flags fg type fg data "
showptrhdrpad
printf " info\n"
printf "----- ----------"
if $kgm_lp64
printf "--------"
end
printf " ---------- -------- ----------"
if $kgm_lp64
printf "--------"
end
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 ", $kgm_spf_count
showptr $kgm_spf_fg
printf " 0x%08x ", $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 " "
showptr $kgm_spf_fgd
printf " "
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 ", $kgm_spl_seen
showptr $arg0
printf "\n"
end
define showprocinfo
set $kgm_spi_proc = (proc_t)$arg0
printf "Process "
showptr $kgm_spi_proc
printf "\n"
printf " name %s\n", $kgm_spi_proc->p_comm
printf " pid:%.8d", $kgm_spi_proc->p_pid
printf " task:"
showptr $kgm_spi_proc->task
printf " p_stat:%.1d", $kgm_spi_proc->p_stat
printf " parent pid:%.8d", $kgm_spi_proc->p_ppid
printf "\n"
# 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 - has thread cwd\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 "
showptr $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 "
showptr $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 "
showptr $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
if (((unsigned long) $arg0 < (unsigned long) &_mh_execute_header || \
(unsigned long) $arg0 >= (unsigned long) &last_kernel_symbol ))
showkmodaddr $arg0
else
output /a $arg0
end
end
define mbuf_walkpkt
set $mp = (struct mbuf *)$arg0
set $cnt = 1
set $tot = 0
while $mp
printf "%4d: %p [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: %p [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 "%p", $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: %p", $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 $kgm_pc = $mca->mca_stack[$cnt]
printf "%4d: ", $cnt + 1
pcprint $kgm_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 $kgm_pc = $mca->mca_pstack[$cnt]
printf "%4d: ", $cnt + 1
pcprint $kgm_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
if $kgm_lp64
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"
else
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"
end
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 " %p %6d %5d ",$mc, \
$mc->mc_bufsize, $mc->mc_align
if $mc->mc_slab_zone != 0
printf "%p", $mc->mc_slab_zone
else
if $kgm_lp64
printf " custom"