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