X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/6601e61aa18bf4f09af135ff61fc7f4771d23b06..b0d623f7f2ae71ed96e60569f61f9a9a27016e80:/kgmacros diff --git a/kgmacros b/kgmacros index 2356ffe9e..216fcd4cd 100644 --- a/kgmacros +++ b/kgmacros @@ -1,4 +1,3 @@ -# # Kernel gdb macros # # These gdb macros should be useful during kernel development in @@ -6,26 +5,13 @@ # # All the convenience variables used by these macros begin with $kgm_ -define showversion -#Display version string, a pointer to which is pinned at 0x501C in the kernel's -#low memory globals - p (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 print asm-demangle on +set cp-abi gnu-v2 -set $kgm_dummy = &proc0 -set $kgm_dummy = &kmod -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. +set backtrace sanity-checks off echo Loading Kernel GDB Macros package. Type "help kgm" for more info.\n @@ -38,8 +24,8 @@ 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 +| (gdb) target remote-kdp +| (gdb) attach | | The following macros are available in this package: | showversion Displays a string describing the remote kernel version @@ -54,7 +40,22 @@ document kgm | 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 +| showallbusyports Display a listing of all ports with unread messages +| +| showallclasses Display info about all OSObject subclasses in the system +| showobject Show info about an OSObject - its vtable ptr and retain count, & more info for simple container classes. +| showregistry Show info about all registry entries in the current plane +| showregistryprops Show info about all registry entries in the current plane, and their properties +| showregistryentry Show info about a registry entry; its properties and descendants in the current plane +| setregistryplane Set the plane to be used for the iokit registry macros (pass zero for list) +| +| setfindregistrystr Set the encoded string for matching with +| findregistryentry or findregistryprop (created from +| strcmp_arg_pack64) +| findregistryentry Find a registry entry that matches the encoded string +| findregistryentries Find all the registry entries that match the encoded string +| findregistryprop Search the registry entry for a property that matches +| the encoded string | | showtask Display info about the specified task | showtaskthreads Display info about the threads in the task @@ -63,6 +64,7 @@ document kgm | 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 +| showtaskbusyports Display all of the task's ports with unread messages | | showact Display info about a thread specified by activation | showactstack Display the stack for a thread specified by activation @@ -75,6 +77,14 @@ document kgm | | 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 @@ -104,75 +114,261 @@ document kgm | disablecore Configure the kernel to disable coredump transmission | switchtocorethread Corefile version of "switchtoact" | resetcorectx Corefile version of "resetctx" +| +| readphys8 Reads the specified untranslated address (8-bit read) +| readphys16 Reads the specified untranslated address (16-bit read) +| readphys32 Reads the specified untranslated address (32-bit read) +| readphys64 Reads the specified untranslated address (64-bit read) +| writephys8 Writes to the specified untranslated address (8-bit write) +| writephys16 Writes to the specified untranslated address (16-bit write) +| writephys32 Writes to the specified untranslated address (32-bit write) +| writephys64 Writes to the specified untranslated address (64-bit write) +| +| readioport8 Read 8-bits from the specified I/O Port +| readioport16 Read 16-bits from the specified I/O Port +| readioport32 Read 32-bits from the specified I/O Port +| writeioport8 Write 8-bits into the specified I/O Port +| writeioport16 Write 16-bits into the specified I/O Port +| writeioport32 Write 32-bits into the specified I/O Port +| +| readmsr64 Read 64-bits from the specified MSR +| writemsr64 Write 64-bits into the specified MSR +| +| rtentry_showdbg Print the debug information of a route entry +| rtentry_trash Walk the list of trash route entries +| +| inifa_showdbg Print the debug information of an IPv4 interface address +| in6ifa_showdbg Print the debug information of an IPv6 interface address +| +| mbuf_walkpkt Walk the mbuf packet chain (m_nextpkt) +| mbuf_walk Walk the mbuf chain (m_next) +| mbuf_buf2slab Find the slab structure of the corresponding buffer +| mbuf_buf2mca Find the mcache audit structure of the corresponding mbuf +| mbuf_showmca Print the contents of an mbuf mcache audit structure +| mbuf_showactive Print all active/in-use mbuf objects +| mbuf_showinactive Print all freed/in-cache mbuf objects +| mbuf_showall Print all mbuf objects +| mbuf_slabs Print all slabs in the group +| mbuf_slabstbl Print slabs table +| mbuf_stat Print extended mbuf allocator statistics +| +| mcache_walkobj Walk the mcache object chain (obj_next) +| mcache_stat Print all mcaches in the system +| mcache_showcache Display the number of objects in the cache +| +| showbootargs Display boot arguments passed to the target kernel +| showbootermemorymap Dump phys memory map from EFI +| +| systemlog Display the kernel's printf ring buffer +| +| hexdump Show the contents of memory as a hex/ASCII dump +| +| showvnodepath Print the path for a vnode +| showvnodelocks Display list of advisory locks held/blocked on a vnode +| showvnodedev Display information about a device vnode +| showtty Display information about a struct tty +| showallvols Display a summary of mounted volumes +| showvnode Display info about one vnode +| showvolvnodes Display info about all vnodes of a given volume +| showvolbusyvnodes Display info about busy (iocount!=0) vnodes of a given volume +| showallbusyvnodes Display info about all busy (iocount!=0) vnodes +| showallvnodes Display info about all vnodes +| print_vnode Print out the fields of a vnode struct +| showprocvnodes Print out all the open fds which are vnodes in a process +| showallprocvnodes Print out all the open fds which are vnodes in any process +| showmountvnodes Print the vnode list +| showmountallvnodes Print the vnode inactive list +| showworkqvnodes Print the vnode worker list +| shownewvnodes Print the new vnode list +| +| ifconfig display ifconfig-like output +| showifaddrs show the list of addresses for the given ifp +| showifmultiaddrs show the list of multicast addresses for the given ifp +| +| showsocket Display information about a socket +| showprocsockets Given a proc_t pointer, display information about its sockets +| showallprocsockets Display information about the sockets of all the processes +| +| show_tcp_pcbinfo Display the list of the TCP protocol control blocks +| show_tcp_timewaitslots Display the list of the TCP protocol control blocks in TIMEWAIT +| show_udp_pcbinfo Display the list of UDP protocol control blocks +| +| show_rt_inet Display the IPv4 routing table +| show_rt_inet6 Display the IPv6 routing table +| +| showallpmworkqueues Display info about all IOPMWorkQueue objects +| showregistrypmstate Display power management state for all IOPower registry entries +| showioservicepm Display the IOServicePM object +| showstacksaftertask showallstacks starting after a given task +| showstacksafterthread showallstacks starting after a given thread +| +| showMCAstate Print machine-check register state after MC exception. +| +| showallgdbstacks Cause GDB to trace all thread stacks +| showallgdbcorestacks Corefile equivalent of "showallgdbstacks" +| kdp-reenter Schedule reentry into the debugger and continue. +| kdp-reboot Restart remote target +| +| zstack Print zalloc caller stack (zone leak debugging) +| findoldest Find oldest zone leak debugging record +| countpcs Print how often a pc occurs in the zone leak log +| +| pmap_walk Perform a page-table walk +| pmap_vtop Translate a virtual address to physical address +| +| showuserlibraries Show binary images known by dyld in the target task +| +| showthreadfortid Displays the address of the thread structure for a given thread_id value. | -| kdp-reboot Restart remote target -| +| strcmp_nomalloc A version of strcmp that avoids the use of malloc +| through the use of encoded strings created via +| strcmp_arg_pack64. +| strcmp_arg_pack64 Pack a string into a 64-bit quantity for use by +| strcmp_nomalloc +| +| pci_cfg_read8 Read 8-bits from a PCI config space register +| pci_cfg_read16 Read 16-bits from a PCI config space register +| pci_cfg_read32 Read 32-bits from a PCI config space register +| pci_cfg_write8 Write 8-bits into a PCI config space register +| pci_cfg_write16 Write 16-bits into a PCI config space register +| pci_cfg_write32 Write 32-bits into a PCI config space register +| pci_cfg_dump Dump entire config space for a PCI device +| pci_cfg_scan Perform a scan for PCI devices +| pci_cfg_dump_all Dump config spaces for all detected PCI devices +| +| lapic_read32 Read APIC entry +| lapic_write32 Write APIC entry +| lapic_dump Dump APIC entries +| +| ioapic_read32 Read IOAPIC entry +| ioapic_write32 Write IOAPIC entry +| ioapic_dump Dump IOAPIC entries +| | Type "help " 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 + kdp-kernelversion +end + +document showversion +Syntax: showversion +| Read the kernel version string from a fixed address in low +| memory. Useful if you don't know which kernel is on the other end, +| and need to find the appropriate symbols. Beware that if you've +| loaded a symbol file, but aren't connected to a remote target, +| the version string from the symbol file will be displayed instead. +| This macro expects to be connected to the remote kernel to function +| correctly. +end + +set $kgm_mtype_ppc = 0x00000012 +set $kgm_mtype_arm = 0x0000000C + +set $kgm_mtype_i386 = 0x00000007 +set $kgm_mtype_x86_64 = 0x01000007 +set $kgm_mtype_x86_any = $kgm_mtype_i386 +set $kgm_mtype_x86_mask = 0xFEFFFFFF + +set $kgm_mtype = ((unsigned int *)&_mh_execute_header)[1] +set $kgm_lp64 = $kgm_mtype & 0x01000000 + +set $kgm_lcpu_self = 0xFFFE + +set $kgm_reg_depth = 0 +set $kgm_reg_depth_max = 0xFFFF +set $kgm_reg_plane = (IORegistryPlane *) gIOServicePlane +set $kgm_namekey = (OSSymbol *) 0 +set $kgm_childkey = (OSSymbol *) 0 + +set $kgm_show_object_addrs = 0 +set $kgm_show_object_retain = 0 +set $kgm_show_props = 0 +set $kgm_show_data_alwaysbytes = 0 + +set $kgm_show_kmod_syms = 0 + +# Print a pointer +define showptr + if $kgm_lp64 + printf "0x%016llx", $arg0 + else + printf "0x%08x", $arg0 + end +end + +# for headers, leave 8 chars for LP64 pointers +define showptrhdrpad + if $kgm_lp64 + printf " " + end +end define showkmodheader - printf "kmod address size " - printf "id refs version name\n" + printf "kmod " + showptrhdrpad + printf " address " + showptrhdrpad + printf " size " + showptrhdrpad + printf " id refs version name\n" end define showkmodint set $kgm_kmodp = (struct kmod_info *)$arg0 - printf "0x%08x ", $arg0 - printf "0x%08x ", $kgm_kmodp->address - printf "0x%08x ", $kgm_kmodp->size + showptr $kgm_kmodp + printf " " + showptr $kgm_kmodp->address + printf " " + showptr $kgm_kmodp->size + printf " " printf "%3d ", $kgm_kmodp->id printf "%5d ", $kgm_kmodp->reference_count - printf "%10s ", &$kgm_kmodp->version - printf "%s\n", &$kgm_kmodp->name + 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 +# cached info of the last kext found, to speed up subsequent lookups set $kgm_pkmod = 0 set $kgm_pkmodst = 0 set $kgm_pkmoden = 0 -define showkmodaddr - 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) + +define showkmodaddrint + showptr $arg0 + if ((unsigned long)$arg0 >= (unsigned long)$kgm_pkmodst) && ((unsigned long)$arg0 < (unsigned long)$kgm_pkmoden) + set $kgm_off = ((unsigned long)$arg0 - (unsigned long)$kgm_pkmodst) printf " <%s + 0x%x>", $kgm_pkmod->name, $kgm_off else - 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 - 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 + set $kgm_kmodp = (struct kmod_info *)kmod + if ($kgm_mtype == $kgm_mtype_x86_64) && ($arg0 >= (unsigned long)&_mh_execute_header) + # kexts are loaded below the kernel for x86_64 + set $kgm_kmodp = 0 + end + while $kgm_kmodp + set $kgm_off = ((unsigned long)$arg0 - (unsigned long)$kgm_kmodp->address) + if ($kgm_kmodp->address <= $arg0) && ($kgm_off < $kgm_kmodp->size) + printf " <%s + 0x%x>", $kgm_kmodp->name, $kgm_off + set $kgm_pkmod = $kgm_kmodp + set $kgm_pkmodst = $kgm_kmodp->address + set $kgm_pkmoden = $kgm_pkmodst + $kgm_kmodp->size + set $kgm_kmodp = 0 + else + set $kgm_kmodp = $kgm_kmodp->next end end end end + +define showkmodaddr + showkmodaddrint $arg0 +end + document showkmodaddr +Syntax: (gdb) showkmodaddr | Given an address, print the offset and name for the kmod containing it -| The following is the syntax: -| (gdb) showkmodaddr end define showkmod @@ -180,9 +376,8 @@ define showkmod showkmodint $arg0 end document showkmod +Syntax: (gdb) showkmod | Routine to print info about a kernel module -| The following is the syntax: -| (gdb) showkmod end define showallkmods @@ -194,22 +389,62 @@ define showallkmods end end document showallkmods +Syntax: (gdb) showallkmods | Routine to print a summary listing of all the kernel modules -| The following is the syntax: -| (gdb) showallkmods end define showactheader - printf " activation " - printf "thread pri state wait_queue wait_event\n" + printf " " + showptrhdrpad + printf " thread " + showptrhdrpad + printf " thread_id " + showptrhdrpad + printf " processor " + showptrhdrpad + printf " pri io_policy state wait_queue" + showptrhdrpad + printf " wait_event\n" end define showactint - printf " 0x%08x ", $arg0 + printf " " + showptrhdrpad set $kgm_thread = *(struct thread *)$arg0 - printf "0x%08x ", $arg0 - printf "%3d ", $kgm_thread.sched_pri + showptr $arg0 + if ($kgm_thread.static_param) + printf "[WQ]" + else + printf " " + end + printf " %7ld ", $kgm_thread.thread_id + showptr $kgm_thread.last_processor + printf " %3d ", $kgm_thread.sched_pri + if ($kgm_thread.uthread != 0) + set $kgm_printed = 0 + set $kgm_uthread = (struct uthread *)$kgm_thread.uthread + if ($kgm_uthread->uu_flag & 0x400) + printf "RAGE " + else + printf " " + end + if ($kgm_uthread->uu_iopol_disk == 1) + printf "NORM " + set $kgm_printed = 1 + end + if ($kgm_uthread->uu_iopol_disk == 2) + printf "PASS " + set $kgm_printed = 1 + end + if ($kgm_uthread->uu_iopol_disk == 3) + printf "THROT " + set $kgm_printed = 1 + end + if ($kgm_printed == 0) + printf " " + end + end set $kgm_state = $kgm_thread.state if $kgm_state & 0x80 printf "I" @@ -233,59 +468,110 @@ define showactint 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) - showkmodaddr $kgm_thread.wait_event - else - output /a (unsigned) $kgm_thread.wait_event + printf "W" + printf "\t " + showptr $kgm_thread.wait_queue + printf " " + if (((unsigned long)$kgm_thread.wait_event > (unsigned long)&last_kernel_symbol) \ + && ($arg1 != 2) && ($kgm_show_kmod_syms == 0)) + showkmodaddr $kgm_thread.wait_event + else + output /a $kgm_thread.wait_event + end + if ($kgm_thread.uthread != 0) + set $kgm_uthread = (struct uthread *)$kgm_thread.uthread + if ($kgm_uthread->uu_wmesg != 0) + printf "\t \"%s\"", $kgm_uthread->uu_wmesg + end end end if $arg1 != 0 if ($kgm_thread.kernel_stack != 0) if ($kgm_thread.reserved_stack != 0) - printf "\n\t\treserved_stack=0x%08x", $kgm_thread.reserved_stack + printf "\n " + showptrhdrpad + printf " reserved_stack=" + showptr $kgm_thread.reserved_stack end - printf "\n\t\tkernel_stack=0x%08x", $kgm_thread.kernel_stack - if ($kgm_mtype == 18) + printf "\n " + showptrhdrpad + printf " kernel_stack=" + showptr $kgm_thread.kernel_stack + if ($kgm_mtype == $kgm_mtype_ppc) set $mysp = $kgm_thread.machine.pcb->save_r1 - else - set $kgm_statep = (struct i386_kernel_state *) \ - ($kgm_thread->kernel_stack + 0x4000 \ - - sizeof(struct i386_kernel_state)) - set $mysp = $kgm_statep->k_ebp end - set $prevsp = 0 - printf "\n\t\tstacktop=0x%08x", $mysp - if ($kgm_mtype == 18) + if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) + set $kgm_statep = (struct x86_kernel_state *) \ + ($kgm_thread->kernel_stack + kernel_stack_size \ + - sizeof(struct x86_kernel_state)) + if ($kgm_mtype == $kgm_mtype_i386) + set $mysp = $kgm_statep->k_ebp + else + set $mysp = $kgm_statep->k_rbp + end + end + if ($kgm_mtype == $kgm_mtype_arm) + if (((unsigned long)$r7 < ((unsigned long) ($kgm_thread->kernel_stack+kernel_stack_size))) \ + && ((unsigned long)$r7 > (unsigned long) ($kgm_thread->kernel_stack))) + set $mysp = $r7 + else + set $kgm_statep = (struct arm_saved_state *)$kgm_thread.machine.kstackptr + set $mysp = $kgm_statep->r[7] + end + end + set $prevsp = $mysp - 16 + printf "\n " + showptrhdrpad + printf " stacktop=" + showptr $mysp + if ($kgm_mtype == $kgm_mtype_ppc) set $stkmask = 0xf - set $stklimit = 0xb0000000 else set $stkmask = 0x3 - set $stklimit = 0xfc000000 end + set $kgm_return = 0 while ($mysp != 0) && (($mysp & $stkmask) == 0) \ - && ($mysp < $stklimit) \ - && ((unsigned)$mysp > (unsigned)$prevsp) - printf "\n\t\t0x%08x ", $mysp - if ($kgm_mtype == 18) + && ($mysp != $prevsp) \ + && ((((unsigned long) $mysp ^ (unsigned long) $prevsp) < 0x2000) \ + || (((unsigned long)$mysp < ((unsigned long) ($kgm_thread->kernel_stack+kernel_stack_size))) \ + && ((unsigned long)$mysp > (unsigned long) ($kgm_thread->kernel_stack)))) + printf "\n " + showptrhdrpad + printf " " + showptr $mysp + printf " " + if ($kgm_mtype == $kgm_mtype_ppc) set $kgm_return = *($mysp + 8) - else + end + if ($kgm_mtype == $kgm_mtype_i386) + set $kgm_return = *($mysp + 4) + end + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kgm_return = *(unsigned long *)($mysp + 8) + end + if ($kgm_mtype == $kgm_mtype_arm) set $kgm_return = *($mysp + 4) end - if ((unsigned) $kgm_return > (unsigned) sectPRELINKB) - showkmodaddr $kgm_return + if (((unsigned long) $kgm_return < (unsigned long) &_mh_execute_header || \ + (unsigned long) $kgm_return >= (unsigned long) &last_kernel_symbol ) \ + && ($kgm_show_kmod_syms == 0)) + showkmodaddr $kgm_return else - output /a (unsigned) $kgm_return + output /a $kgm_return end set $prevsp = $mysp - set $mysp = * $mysp + set $mysp = *(unsigned long *)$mysp end - printf "\n\t\tstackbottom=0x%08x", $prevsp + set $kgm_return = 0 + printf "\n " + showptrhdrpad + printf " stackbottom=" + showptr $prevsp else - printf "\n\t\t\tcontinuation=" - output /a (unsigned) $kgm_thread.continuation + printf "\n " + showptrhdrpad + printf " continuation=" + output /a $kgm_thread.continuation end printf "\n" else @@ -298,9 +584,8 @@ define showact showactint $arg0 0 end document showact +Syntax: (gdb) showact | Routine to print out the state of a specific thread. -| The following is the syntax: -| (gdb) showact end @@ -309,14 +594,13 @@ define showactstack showactint $arg0 1 end document showactstack +Syntax: (gdb) showactstack | Routine to print out the stack of a specific thread. -| The following is the syntax: -| (gdb) showactstack end define showallthreads - set $kgm_head_taskp = &default_pset.tasks + set $kgm_head_taskp = &tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader @@ -329,18 +613,18 @@ define showallthreads set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) end printf "\n" - set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next) + 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. -| The following is the syntax: -| (gdb) showallthreads end define showcurrentthreads -set $kgm_prp = processor_list +set $kgm_prp = (struct processor *)processor_list while $kgm_prp != 0 + printf "Processor 0x%08x State %d (cpu_id %x)\n", $kgm_prp, ($kgm_prp)->state, ($kgm_prp)->cpu_id if ($kgm_prp)->active_thread != 0 set $kgm_actp = ($kgm_prp)->active_thread showtaskheader @@ -353,13 +637,13 @@ set $kgm_prp = processor_list end end document showcurrentthreads +Syntax: (gdb) showcurrentthreads | Routine to print out info about the thread running on each cpu. -| The following is the syntax: -| (gdb) showcurrentthreads end +set $decode_wait_events = 0 define showallstacks - set $kgm_head_taskp = &default_pset.tasks + set $kgm_head_taskp = &tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader @@ -368,22 +652,30 @@ define showallstacks set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) while $kgm_actp != $kgm_head_actp showactheader - showactint $kgm_actp 1 + 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) + 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. -| The following is the syntax: -| (gdb) showallstacks +| If the variable $decode_wait_events is non-zero, the routine attempts to +| interpret thread wait_events as kernel module offsets, which can add to +| processing time. end define showcurrentstacks set $kgm_prp = processor_list while $kgm_prp != 0 + printf "Processor 0x%08x State %d (cpu_id %x)\n", $kgm_prp, ($kgm_prp)->state, ($kgm_prp)->cpu_id if ($kgm_prp)->active_thread != 0 set $kgm_actp = ($kgm_prp)->active_thread showtaskheader @@ -395,21 +687,21 @@ set $kgm_prp = processor_list 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) -| The following is the syntax: -| (gdb) showcurrentstacks end define showwaiterheader - printf "waiters activation " - printf "thread pri state wait_queue wait_event\n" + printf "waiters thread " + printf "processor pri state wait_queue wait_event\n" end define showwaitqwaiters - set $kgm_w_waitqp = (struct wait_queue *)$arg0 + set $kgm_w_waitqp = (WaitQueue*)$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_wqe = (WaitQueueElement *)$kgm_w_linksp->next set $kgm_w_found = 0 while ( (queue_entry_t)$kgm_w_wqe != (queue_entry_t)$kgm_w_linksp) if ($kgm_w_wqe->wqe_type != &_wait_queue_link) @@ -420,32 +712,32 @@ define showwaitqwaiters 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 + set $kgm_w_wqe = (WaitQueueElement *)$kgm_w_wqe->wqe_links.next end end define showwaitqwaitercount - set $kgm_wc_waitqp = (struct wait_queue *)$arg0 + set $kgm_wc_waitqp = (WaitQueue*)$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_wqe = (WaitQueueElement *)$kgm_wc_linksp->next set $kgm_wc_count = 0 while ( (queue_entry_t)$kgm_wc_wqe != (queue_entry_t)$kgm_wc_linksp) if ($kgm_wc_wqe->wqe_type != &_wait_queue_link) set $kgm_wc_count = $kgm_wc_count + 1 end - set $kgm_wc_wqe = (struct wait_queue_element *)$kgm_wc_wqe->wqe_links.next + set $kgm_wc_wqe = (WaitQueueElement *)$kgm_wc_wqe->wqe_links.next end printf "0x%08x ", $kgm_wc_count end define showwaitqmembercount - set $kgm_mc_waitqsetp = (struct wait_queue_set *)$arg0 + set $kgm_mc_waitqsetp = (WaitQueueSet*)$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_wql = (WaitQueueLink *)$kgm_mc_setlinksp->next set $kgm_mc_count = 0 while ( (queue_entry_t)$kgm_mc_wql != (queue_entry_t)$kgm_mc_setlinksp) set $kgm_mc_count = $kgm_mc_count + 1 - set $kgm_mc_wql = (struct wait_queue_link *)$kgm_mc_wql->wql_setlinks.next + set $kgm_mc_wql = (WaitQueueLink *)$kgm_mc_wql->wql_setlinks.next end printf "0x%08x ", $kgm_mc_count end @@ -457,7 +749,7 @@ define showwaitqmemberheader end define showwaitqmemberint - set $kgm_m_waitqp = (struct wait_queue *)$arg0 + set $kgm_m_waitqp = (WaitQueue*)$arg0 printf " 0x%08x ", $kgm_m_waitqp printf "0x%08x ", $kgm_m_waitqp->wq_interlock.lock_data if ($kgm_m_waitqp->wq_fifo) @@ -482,9 +774,9 @@ define showwaitqmemberofheader end define showwaitqmemberof - set $kgm_mo_waitqp = (struct wait_queue *)$arg0 + set $kgm_mo_waitqp = (WaitQueue*)$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_wqe = (WaitQueueElement *)$kgm_mo_linksp->next set $kgm_mo_found = 0 while ( (queue_entry_t)$kgm_mo_wqe != (queue_entry_t)$kgm_mo_linksp) if ($kgm_mo_wqe->wqe_type == &_wait_queue_link) @@ -492,18 +784,18 @@ define showwaitqmemberof 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) + set $kgm_mo_wqlp = (WaitQueueLink *)$kgm_mo_wqe + set $kgm_mo_wqsetp = (WaitQueue*)($kgm_mo_wqlp->wql_setqueue) showwaitqmemberint $kgm_mo_wqsetp end - set $kgm_mo_wqe = (struct wait_queue_element *)$kgm_mo_wqe->wqe_links.next + set $kgm_mo_wqe = (WaitQueueElement *)$kgm_mo_wqe->wqe_links.next end end define showwaitqmembers - set $kgm_ms_waitqsetp = (struct wait_queue_set *)$arg0 + set $kgm_ms_waitqsetp = (WaitQueueSet*)$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_wql = (WaitQueueLink *)$kgm_ms_setlinksp->next set $kgm_ms_found = 0 while ( (queue_entry_t)$kgm_ms_wql != (queue_entry_t)$kgm_ms_setlinksp) set $kgm_ms_waitqp = $kgm_ms_wql->wql_element.wqe_queue @@ -512,7 +804,7 @@ define showwaitqmembers set $kgm_ms_found = 1 end showwaitqmemberint $kgm_ms_waitqp - set $kgm_ms_wql = (struct wait_queue_link *)$kgm_ms_wql->wql_setlinks.next + set $kgm_ms_wql = (WaitQueueLink *)$kgm_ms_wql->wql_setlinks.next end end @@ -522,10 +814,10 @@ define showwaitqheader end define showwaitqint - set $kgm_waitqp = (struct wait_queue *)$arg0 + set $kgm_waitqp = (WaitQueue*)$arg0 printf "0x%08x ", $kgm_waitqp if ($kgm_waitqp->wq_type == 0xf1d1) - printf "0x%08x ", ((struct wait_queue_set *)$kgm_waitqp)->wqs_refcount + printf "0x%08x ", ((WaitQueueSet*)$kgm_waitqp)->wqs_refcount else printf "0x00000000 " end @@ -546,7 +838,7 @@ define showwaitqint end define showwaitq - set $kgm_waitq1p = (wait_queue_t)$arg0 + set $kgm_waitq1p = (WaitQueue*)$arg0 showwaitqheader showwaitqint $kgm_waitq1p if ($kgm_waitq1p->wq_type == 0xf1d1) @@ -558,64 +850,79 @@ define showwaitq end define showmapheader - printf "vm_map pmap vm_size " - printf "#ents rpage hint first_free\n" + printf "vm_map " + showptrhdrpad + printf " pmap " + showptrhdrpad + printf " vm_size " + showptrhdrpad + printf " #ents rpage hint " + showptrhdrpad + printf " first_free\n" end define showvmeheader - printf " entry start " - printf " prot #page object offset\n" + printf " entry " + showptrhdrpad + printf " start prot #page object " + showptrhdrpad + printf " offset\n" end define showvmint set $kgm_mapp = (vm_map_t)$arg0 set $kgm_map = *$kgm_mapp - printf "0x%08x ", $arg0 - printf "0x%08x ", $kgm_map.pmap - printf "0x%08x ", $kgm_map.size - printf "%3d ", $kgm_map.hdr.nentries + showptr $arg0 + printf " " + showptr $kgm_map.pmap + printf " " + showptr $kgm_map.size + printf " %3d ", $kgm_map.hdr.nentries if $kgm_map.pmap printf "%5d ", $kgm_map.pmap->stats.resident_count else printf " " end - printf "0x%08x ", $kgm_map.hint - printf "0x%08x\n", $kgm_map.first_free + showptr $kgm_map.hint + printf " " + showptr $kgm_map.first_free + printf "\n" if $arg1 != 0 - showvmeheader - set $kgm_head_vmep = &($kgm_mapp->hdr.links) - set $kgm_vmep = $kgm_map.hdr.links.next - while (($kgm_vmep != 0) && ($kgm_vmep != $kgm_head_vmep)) - set $kgm_vme = *$kgm_vmep - printf " 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 + showvmeheader + set $kgm_head_vmep = &($kgm_mapp->hdr.links) + set $kgm_vmep = $kgm_map.hdr.links.next + while (($kgm_vmep != 0) && ($kgm_vmep != $kgm_head_vmep)) + set $kgm_vme = *$kgm_vmep + printf " " + showptr $kgm_vmep + printf " 0x%016llx ", $kgm_vme.links.start + printf "%1x", $kgm_vme.protection + printf "%1x", $kgm_vme.max_protection + if $kgm_vme.inheritance == 0x0 + printf "S" + end + if $kgm_vme.inheritance == 0x1 + printf "C" + end + if $kgm_vme.inheritance == 0x2 + printf "-" + end + if $kgm_vme.inheritance == 0x3 + printf "D" + end + if $kgm_vme.is_sub_map + printf "s " + else + if $kgm_vme.needs_copy + printf "n " + else + printf " " + end + end + printf "%6d ",($kgm_vme.links.end - $kgm_vme.links.start) >> 12 + showptr $kgm_vme.object.vm_object + printf " 0x%016llx\n", $kgm_vme.offset + set $kgm_vmep = $kgm_vme.links.next end end printf "\n" @@ -627,9 +934,8 @@ define showmapvme showvmint $arg0 1 end document showmapvme +Syntax: (gdb) showmapvme | Routine to print out a summary listing of all the entries in a vm_map -| The following is the syntax: -| (gdb) showmapvme end @@ -638,92 +944,96 @@ define showmap showvmint $arg0 0 end document showmap +Syntax: (gdb) showmap | Routine to print out info about the specified vm_map -| The following is the syntax: -| (gdb) showmap end define showallvm - set $kgm_head_taskp = &default_pset.tasks + 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->pset_tasks.next) + 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 -| The following is the syntax: -| (gdb) showallvm end define showallvme - set $kgm_head_taskp = &default_pset.tasks + 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->pset_tasks.next) + 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 -| The following is the syntax: -| (gdb) showallvme end define showipcheader - printf "ipc_space is_table table_next " - printf "flags tsize splaytree splaybase\n" + printf "ipc_space " + showptrhdrpad + printf " is_table " + showptrhdrpad + printf " table_next" + showptrhdrpad + printf " flags tsize splaytree splaybase\n" end define showipceheader - printf " name object " - printf "rite urefs destname destination\n" + printf " name object " + showptrhdrpad + 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 + showptr $kgm_ie.ie_object + printf " " if $kgm_ie.ie_bits & 0x00100000 - printf "Dead " + printf "Dead " printf "%5d\n", $kgm_ie.ie_bits & 0xffff else if $kgm_ie.ie_bits & 0x00080000 - printf "SET " + 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 + if $kgm_ie.ie_bits & 0x00020000 + printf " SR" + else + printf " S" + end else - if $kgm_ie.ie_bits & 0x00020000 - printf " R" - end + if $kgm_ie.ie_bits & 0x00020000 + printf " R" + end end if $kgm_ie.ie_bits & 0x00040000 - printf " O" + printf " O" end if $kgm_ie.index.request - printf "n" + printf "n" else printf " " end if $kgm_ie.ie_bits & 0x00800000 - printf "c" + printf "c" else - printf " " + printf " " end printf "%5d ", $kgm_ie.ie_bits & 0xffff showportdest $kgm_ie.ie_object @@ -734,69 +1044,71 @@ 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 + showptr $arg0 + printf " " + showptr $kgm_is.is_table + printf " " + showptr $kgm_is.is_table_next + printf " " if $kgm_is.is_growing != 0 - printf "G" + printf "G" else - printf " " + printf " " end if $kgm_is.is_fast != 0 - printf "F" + printf "F" else - printf " " + printf " " end if $kgm_is.is_active != 0 - printf "A " + printf "A " else - printf " " + 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 + showptr &$kgm_isp->is_tree + printf "\n" if $arg1 != 0 - showipceheader - set $kgm_iindex = 0 - set $kgm_iep = $kgm_is.is_table - set $kgm_destspacep = (ipc_space_t)0 + 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 + 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 + 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 -| The following is the syntax: -| (gdb) showipc end define showrights set $kgm_isp = (ipc_space_t)$arg0 - showipcheader + 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 -| The following is the syntax: -| (gdb) showrights end @@ -808,58 +1120,54 @@ define showtaskipc showipcint $kgm_taskp->itk_space 0 end document showtaskipc +Syntax: (gdb) showtaskipc | Routine to print info about the ipc space for a task -| The following is the syntax: -| (gdb) showtaskipc end define showtaskrights set $kgm_taskp = (task_t)$arg0 showtaskheader - showipcheader + 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 -| The following is the syntax: -| (gdb) showtaskrights end define showallipc - set $kgm_head_taskp = &default_pset.tasks + 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->pset_tasks.next) + 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 -| The following is the syntax: -| (gdb) showallipc end define showallrights - set $kgm_head_taskp = &default_pset.tasks + 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->pset_tasks.next) + 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 -| The following is the syntax: -| (gdb) showallrights end @@ -871,9 +1179,8 @@ define showtaskvm showvmint $kgm_taskp->map 0 end document showtaskvm +Syntax: (gdb) showtaskvm | Routine to print out info about a task's vm_map -| The following is the syntax: -| (gdb) showtaskvm end define showtaskvme @@ -884,25 +1191,32 @@ define showtaskvme showvmint $kgm_taskp->map 1 end document showtaskvme +Syntax: (gdb) showtaskvme | Routine to print out info about a task's vm_map_entries -| The following is the syntax: -| (gdb) showtaskvme end define showtaskheader - printf "task vm_map ipc_space #acts " + printf "task " + showptrhdrpad + printf " vm_map " + showptrhdrpad + printf " ipc_space " + showptrhdrpad + printf " #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 + set $kgm_taskp = (struct task *)$arg0 + showptr $arg0 + printf " " + showptr $kgm_taskp->map + printf " " + showptr $kgm_taskp->itk_space + printf " %5d ", $kgm_taskp->thread_count + showprocint $kgm_taskp->bsd_info end define showtask @@ -910,9 +1224,8 @@ define showtask showtaskint $arg0 end document showtask +Syntax (gdb) showtask | Routine to print out info about a task. -| The following is the syntax: -| (gdb) showtask end @@ -929,9 +1242,8 @@ define showtaskthreads end end document showtaskthreads +Syntax: (gdb) showtaskthreads | Routine to print info about the threads in a task. -| The following is the syntax: -| (gdb) showtaskthreads end @@ -948,46 +1260,80 @@ define showtaskstacks end end document showtaskstacks +Syntax: (gdb) showtaskstacks | Routine to print out the stack for each thread in a task. -| The following is the syntax: -| (gdb) showtaskstacks end define showalltasks showtaskheader - set $kgm_head_taskp = &default_pset.tasks + 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->pset_tasks.next) + 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 -| The following is the syntax: -| (gdb) showalltasks +| wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items" +| if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung +| io_policy -> RAGE - rapid aging of vnodes requested +| NORM - normal I/O explicitly requested (this is the default) +| PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions) +| THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes) end - define showprocheader - printf " pid proc command\n" + printf " pid process io_policy wq_state" + showptrhdrpad + printf " command\n" end define showprocint set $kgm_procp = (struct proc *)$arg0 if $kgm_procp != 0 + set $kgm_printed = 0 printf "%5d ", $kgm_procp->p_pid - printf "0x%08x ", $kgm_procp - printf "%s\n", $kgm_procp->p_comm + showptr $kgm_procp + if ($kgm_procp->p_lflag & 0x400000) + printf " RAGE " + else + printf " " + end + if ($kgm_procp->p_iopol_disk == 1) + printf "NORM " + set $kgm_printed = 1 + end + if ($kgm_procp->p_iopol_disk == 2) + printf "PASS " + set $kgm_printed = 1 + end + if ($kgm_procp->p_iopol_disk == 3) + printf "THROT " + set $kgm_printed = 1 + end + if ($kgm_printed == 0) + printf " " + end + set $kgm_wqp = (struct workqueue *)$kgm_procp->p_wqptr + if $kgm_wqp != 0 + printf " %2d %2d %2d ", $kgm_wqp->wq_nthreads, $kgm_wqp->wq_thidlecount, $kgm_wqp->wq_itemcount + else + printf " " + end + printf " %s\n", $kgm_procp->p_comm else - printf " *0* 0x00000000 --\n" + printf " *0* " + showptr 0 + printf " --\n" end end define showpid showtaskheader - set $kgm_head_taskp = &default_pset.tasks + 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 @@ -995,20 +1341,19 @@ define showpid showtaskint $kgm_taskp set $kgm_taskp = $kgm_head_taskp else - set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next) + 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 -| The following is the syntax: -| (gdb) showpid end define showproc showtaskheader set $kgm_procp = (struct proc *)$arg0 - showtaskint $kgm_procp->task $arg1 $arg2 + showtaskint $kgm_procp->task end @@ -1053,7 +1398,7 @@ define showkmsgint else printf "rM" end - if (($kgm_kmsgh.msgh_bits & 0xff00) == (19 < 8)) + if (($kgm_kmsgh.msgh_bits & 0xff00) == (19 << 8)) printf "lC" else printf "lM" @@ -1072,7 +1417,8 @@ end define showkobject set $kgm_portp = (struct ipc_port *)$arg0 - printf "0x%08x kobject(", $kgm_portp->ip_kobject + showptr $kgm_portp->ip_kobject + printf " kobject(" set $kgm_kotype = ($kgm_portp->ip_object.io_bits & 0x00000fff) if ($kgm_kotype == 1) printf "THREAD" @@ -1176,21 +1522,23 @@ define showportdestproc # check against the previous cached value - this is slow if ($kgm_spacep != $kgm_destspacep) set $kgm_destprocp = (struct proc *)0 - set $kgm_head_taskp = &default_pset.tasks + set $kgm_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->pset_tasks.next) + 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 + printf "task " + showptr $kgm_desttaskp + printf "\n" end end @@ -1201,10 +1549,12 @@ define showportdest showkobject $kgm_portp else if ($kgm_portp->ip_object.io_bits & 0x80000000) - printf "0x%08x ", $kgm_portp->ip_object.io_receiver_name + showptr $kgm_portp->ip_messages.data.port.receiver_name + printf " " showportdestproc $kgm_portp else - printf "0x%08x inactive-port\n", $kgm_portp + showptr $kgm_portp + printf " inactive-port\n" end end end @@ -1212,17 +1562,13 @@ end define showportmember printf " 0x%08x ", $arg0 set $kgm_portp = (struct ipc_port *)$arg0 - printf "0x%08x ", $kgm_portp->ip_object.io_receiver_name + printf "0x%08x ", $kgm_portp->ip_messages.data.port.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 "Port" printf "%5d ", $kgm_portp->ip_object.io_references printf "0x%08x ", &($kgm_portp->ip_messages) printf "0x%08x\n", $kgm_portp->ip_messages.data.port.msgcount @@ -1232,7 +1578,7 @@ 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 + printf "0x%08x ", $kgm_portp->ip_messages.data.port.receiver_name if ($kgm_portp->ip_object.io_bits & 0x80000000) printf "A" else @@ -1259,7 +1605,7 @@ 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 + printf "0x%08x ", $kgm_psetp->ips_messages.data.pset.local_name if ($kgm_psetp->ips_object.io_bits & 0x80000000) printf "A" else @@ -1267,9 +1613,9 @@ define showpsetint end printf "Set " printf "%5d ", $kgm_psetp->ips_object.io_references - printf "0x%08x ", $kgm_psetp->ips_object.io_receiver_name + printf "0x%08x ", $kgm_psetp->ips_messages.data.pset.local_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_wql = (WaitQueueLink *)$kgm_setlinksp->next set $kgm_found = 0 while ( (queue_entry_t)$kgm_wql != (queue_entry_t)$kgm_setlinksp) set $kgm_portp = (struct ipc_port *)((int)($kgm_wql->wql_element->wqe_queue) - ((int)$kgm_portoff)) @@ -1280,7 +1626,7 @@ define showpsetint set $kgm_found = 1 end showportmember $kgm_portp 0 - set $kgm_wql = (struct wait_queue_link *)$kgm_wql->wql_setlinks.next + set $kgm_wql = (WaitQueueLink *)$kgm_wql->wql_setlinks.next end if !$kgm_found printf "--n/e--\n" @@ -1308,165 +1654,314 @@ 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)) + if ($kgm_mqueue.data.pset.set_queue.wqs_wait_queue.wq_type == 0xf1d1) + set $kgm_psetoff = &(((struct ipc_pset *)0)->ips_messages) + set $kgm_pset = (((long)$arg0) - ((long)$kgm_psetoff)) showpsetheader showpsetint $kgm_pset 1 end - if ($kgm_mqueue.data.set_queue.wqs_wait_queue.wq_type == 0xf1d0) + if ($kgm_mqueue.data.pset.set_queue.wqs_wait_queue.wq_type == 0xf1d0) + set $kgm_portoff = &(((struct ipc_port *)0)->ip_messages) + set $kgm_port = (((long)$arg0) - ((long)$kgm_portoff)) 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" + set $kgm_zone = (struct zone *)$arg0 + + showptr $kgm_zone + printf " %6d ",$kgm_zone->count + printf "%8x ",$kgm_zone->cur_size + printf "%8x ",$kgm_zone->max_size + printf "%6d ",$kgm_zone->elem_size + printf "%8x ",$kgm_zone->alloc_size + printf "%s ",$kgm_zone->zone_name + + if ($kgm_zone->exhaustible) + printf "H" + end + if ($kgm_zone->collectable) + printf "C" + end + if ($kgm_zone->expandable) + printf "X" + end + 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" + printf "ZONE " + showptrhdrpad + printf " COUNT TOT_SZ MAX_SZ ELT_SZ ALLOC_SZ NAME\n" + set $kgm_zone_ptr = (struct zone *)first_zone + while ($kgm_zone_ptr != 0) + zprint_one $kgm_zone_ptr + set $kgm_zone_ptr = $kgm_zone_ptr->next_zone + end + printf "\n" end document zprint +Syntax: (gdb) zprint | Routine to print a summary listing of all the kernel zones -| The following is the syntax: -| (gdb) zprint end define showmtxgrp -set $kgm_mtxgrp = (lck_grp_t *)$arg0 - -if ($kgm_mtxgrp->lck_grp_mtxcnt) -printf "0x%08x ", $kgm_mtxgrp -printf "%8d ",$kgm_mtxgrp->lck_grp_mtxcnt -printf "%12u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_util_cnt -printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_miss_cnt -printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_wait_cnt -printf "%s ",&$kgm_mtxgrp->lck_grp_name -printf "\n" -end + set $kgm_mtxgrp = (struct _lck_grp_ *)$arg0 + + if ($kgm_mtxgrp->lck_grp_mtxcnt) + showptr $kgm_mtxgrp + printf " %8d ",$kgm_mtxgrp->lck_grp_mtxcnt + printf "%12u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_util_cnt + printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_miss_cnt + printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_wait_cnt + printf "%s ",&$kgm_mtxgrp->lck_grp_name + printf "\n" + end end define showallmtx -printf "LCK GROUP CNT UTIL MISS WAIT NAME\n" -set $kgm_mtxgrp_ptr = (lck_grp_t *)&lck_grp_queue -set $kgm_mtxgrp_ptr = (lck_grp_t *)$kgm_mtxgrp_ptr->lck_grp_link.next -while ($kgm_mtxgrp_ptr != (lck_grp_t *)&lck_grp_queue) - showmtxgrp $kgm_mtxgrp_ptr - set $kgm_mtxgrp_ptr = (lck_grp_t *)$kgm_mtxgrp_ptr->lck_grp_link.next -end -printf "\n" + printf "LCK GROUP " + showptrhdrpad + printf " CNT UTIL MISS WAIT NAME\n" + set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)&lck_grp_queue + set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)$kgm_mtxgrp_ptr->lck_grp_link.next + while ($kgm_mtxgrp_ptr != (struct _lck_grp_ *)&lck_grp_queue) + showmtxgrp $kgm_mtxgrp_ptr + set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)$kgm_mtxgrp_ptr->lck_grp_link.next + end + printf "\n" end document showallmtx +Syntax: (gdb) showallmtx | Routine to print a summary listing of all mutexes -| The following is the syntax: -| (gdb) showallmtx end define showrwlckgrp -set $kgm_rwlckgrp = (lck_grp_t *)$arg0 - -if ($kgm_rwlckgrp->lck_grp_rwcnt) -printf "0x%08x ", $kgm_rwlckgrp -printf "%8d ",$kgm_rwlckgrp->lck_grp_rwcnt -printf "%12u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_util_cnt -printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_miss_cnt -printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_wait_cnt -printf "%s ",&$kgm_rwlckgrp->lck_grp_name -printf "\n" -end + set $kgm_rwlckgrp = (struct _lck_grp_ *)$arg0 + + if ($kgm_rwlckgrp->lck_grp_rwcnt) + showptr $kgm_rwlckgrp + printf " %8d ",$kgm_rwlckgrp->lck_grp_rwcnt + printf "%12u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_util_cnt + printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_miss_cnt + printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_wait_cnt + printf "%s ",&$kgm_rwlckgrp->lck_grp_name + printf "\n" + end end define showallrwlck -printf "LCK GROUP CNT UTIL MISS WAIT NAME\n" -set $kgm_rwlckgrp_ptr = (lck_grp_t *)&lck_grp_queue -set $kgm_rwlckgrp_ptr = (lck_grp_t *)$kgm_rwlckgrp_ptr->lck_grp_link.next -while ($kgm_rwlckgrp_ptr != (lck_grp_t *)&lck_grp_queue) - showrwlckgrp $kgm_rwlckgrp_ptr - set $kgm_rwlckgrp_ptr = (lck_grp_t *)$kgm_rwlckgrp_ptr->lck_grp_link.next -end -printf "\n" + printf "LCK GROUP " + showptrhdrpad + printf " CNT UTIL MISS WAIT NAME\n" + set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)&lck_grp_queue + set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)$kgm_rwlckgrp_ptr->lck_grp_link.next + while ($kgm_rwlckgrp_ptr != (struct _lck_grp_ *)&lck_grp_queue) + showrwlckgrp $kgm_rwlckgrp_ptr + set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)$kgm_rwlckgrp_ptr->lck_grp_link.next + end + printf "\n" end document showallrwlck +Syntax: (gdb) showallrwlck | Routine to print a summary listing of all read/writer locks -| The following is the syntax: -| (gdb) showallrwlck 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 - if ($kgm_mtype == 18) + set $newact = (struct thread *) $arg0 + select 0 + if ($newact->kernel_stack == 0) + echo This activation does not have a stack.\n + echo continuation: + output/a (unsigned) $newact.continuation + echo \n + else + if ($kgm_mtype == $kgm_mtype_ppc) if ($kdp_act_counter == 0) - set $kdpstate = (struct savearea *) kdp.saved_state + set $kdpstate = (struct savearea *) kdp.saved_state end set $kdp_act_counter = $kdp_act_counter + 1 - set $newact = (struct thread *) $arg0 - if ($newact->kernel_stack == 0) - echo This activation does not have a stack.\n - echo continuation: - output/a (unsigned) $newact.continuation - echo \n - else - set (struct savearea *) kdp.saved_state=$newact->machine->pcb - flush - set $pc=$newact->machine->pcb.save_srr0 - update - end - else - echo switchtoact not implemented for this architecture.\n + set (struct savearea *) kdp.saved_state=$newact->machine->pcb + flushregs + flushstack + set $pc=$newact->machine->pcb.save_srr0 + update end -end + if ($kgm_mtype == $kgm_mtype_i386) + set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state + if ($kdp_act_counter == 0) + set $kdpstate = *($kdpstatep) + end + set $kdp_act_counter = $kdp_act_counter + 1 -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 + set $kgm_statep = (struct x86_kernel_state *) \ + ($newact->kernel_stack + kernel_stack_size \ + - sizeof(struct x86_kernel_state)) + set $kdpstatep->ebx = $kgm_statep->k_ebx + set $kdpstatep->ebp = $kgm_statep->k_ebp + set $kdpstatep->edi = $kgm_statep->k_edi + set $kdpstatep->esi = $kgm_statep->k_esi + set $kdpstatep->eip = $kgm_statep->k_eip + flushregs + flushstack + set $pc = $kgm_statep->k_eip + update + end + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kdpstatep = (struct x86_saved_state64 *) kdp.saved_state + if ($kdp_act_counter == 0) + set $kdpstate = *($kdpstatep) + end + set $kdp_act_counter = $kdp_act_counter + 1 + + set $kgm_statep = (struct x86_kernel_state *) \ + ($newact->kernel_stack + kernel_stack_size \ + - sizeof(struct x86_kernel_state)) + set $kdpstatep->rbx = $kgm_statep->k_rbx + set $kdpstatep->rbp = $kgm_statep->k_rbp + set $kdpstatep->r12 = $kgm_statep->k_r12 + set $kdpstatep->r13 = $kgm_statep->k_r13 + set $kdpstatep->r14 = $kgm_statep->k_r14 + set $kdpstatep->r15 = $kgm_statep->k_r15 + set $kdpstatep->isf.rsp = $kgm_statep->k_rsp + flushregs + flushstack + set $pc = $kgm_statep->k_rip + update + end + if ($kgm_mtype == $kgm_mtype_arm) + set $r0_save = $r0 + set $r1_save = $r1 + set $r2_save = $r2 + set $r3_save = $r3 + set $r4_save = $r4 + set $r5_save = $r5 + set $r6_save = $r6 + set $r7_save = $r7 + set $r8_save = $r8 + set $r9_save = $r9 + set $r10_save = $r10 + set $r11_save = $r11 + set $r12_save = $r12 + set $sp_save = $sp + set $lr_save = $lr + set $pc_save = $pc + set $pc_ctx = load_reg+8 + set $kgm_statep = (struct arm_saved_state *)((struct thread*)$arg0)->machine.kstackptr + set $r0 = $kgm_statep->r[0] + set $r1 = $kgm_statep->r[1] + set $r2 = $kgm_statep->r[2] + set $r3 = $kgm_statep->r[3] + set $r4 = $kgm_statep->r[4] + set $r5 = $kgm_statep->r[5] + set $r6 = $kgm_statep->r[6] + set $r8 = $kgm_statep->r[8] + set $r9 = $kgm_statep->r[9] + set $r10 = $kgm_statep->r[10] + set $r11 = $kgm_statep->r[11] + set $r12 = $kgm_statep->r[12] + set $sp = $kgm_statep->sp + set $lr = $kgm_statep->lr + set $pc = $pc_ctx + set $r7 = $kgm_statep->r[7] + flushregs + flushstack + end + end + showcontext_int +end + +document switchtoact +Syntax: switchtoact
+| 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 - if ($kgm_mtype == 18) + select 0 + if ($kgm_mtype == $kgm_mtype_ppc) if ($kdp_act_counter == 0) set $kdpstate = (struct savearea *) kdp.saved_state end set $kdp_act_counter = $kdp_act_counter + 1 set (struct savearea *) kdp.saved_state=(struct savearea *) $arg0 - flush + flushregs + flushstack set $pc=((struct savearea *) $arg0)->save_srr0 update + else + if ($kgm_mtype == $kgm_mtype_arm) + set arm disassembler std + select-frame 0 + set $r0_save = $r0 + set $r1_save = $r1 + set $r2_save = $r2 + set $r3_save = $r3 + set $r4_save = $r4 + set $r5_save = $r5 + set $r6_save = $r6 + set $r7_save = $r7 + set $r8_save = $r8 + set $r9_save = $r9 + set $r10_save = $r10 + set $r11_save = $r11 + set $r12_save = $r12 + set $sp_save = $sp + set $lr_save = $lr + set $pc_save = $pc + set $kgm_statep = (struct arm_saved_state *)$arg0 + set $r0 = $kgm_statep->r[0] + set $r1 = $kgm_statep->r[1] + set $r2 = $kgm_statep->r[2] + set $r3 = $kgm_statep->r[3] + set $r4 = $kgm_statep->r[4] + set $r5 = $kgm_statep->r[5] + set $r6 = $kgm_statep->r[6] + set $r8 = $kgm_statep->r[8] + set $r9 = $kgm_statep->r[9] + set $r10 = $kgm_statep->r[10] + set $r11 = $kgm_statep->r[11] + set $r12 = $kgm_statep->r[12] + set $sp = $kgm_statep->sp + set $lr = $kgm_statep->lr + set $r7 = $kgm_statep->r[7] + set $pc = $kgm_statep->pc + flushregs + flushstack + update else echo switchtoctx not implemented for this architecture.\n end @@ -1481,14 +1976,69 @@ Syntax: switchtoctx
end define resetctx - if ($kgm_mtype == 18) + select 0 + if ($kdp_act_counter != 0) + if ($kgm_mtype == $kgm_mtype_ppc) set (struct savearea *)kdp.saved_state=$kdpstate - flush + flushregs + flushstack set $pc=((struct savearea *) kdp.saved_state)->save_srr0 update set $kdp_act_counter = 0 - else - echo resetctx not implemented for this architecture.\n + end + if ($kgm_mtype == $kgm_mtype_i386) + set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state + set *($kdpstatep)=$kdpstate + flushregs + flushstack + set $pc=$kdpstatep->eip + update + set $kdp_act_counter = 0 + end + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kdpstatep = (struct x86_saved_state64 *) kdp.saved_state + set *($kdpstatep)=$kdpstate + flushregs + flushstack + set $pc=$kdpstatep->isf.rip + update + set $kdp_act_counter = 0 + end + if ($kgm_mtype == $kgm_mtype_arm) + set $r0 = $r0_save + flushregs + set $r1 = $r1_save + flushregs + set $r2 = $r2_save + flushregs + set $r3 = $r3_save + flushregs + set $r4 = $r4_save + flushregs + set $r5 = $r5_save + flushregs + set $r6 = $r6_save + flushregs + set $r8 = $r8_save + flushregs + set $r9 = $r9_save + flushregs + set $r10 = $r10_save + flushregs + set $r11 = $r11_save + flushregs + set $r12 = $r12_save + flushregs + set $sp = $sp_save + flushregs + set $lr = $lr_save + flushregs + set $pc = $pc_save + flushregs + set $r7 = $r7_save + flushregs + end + showcontext_int end end @@ -1499,6 +2049,18 @@ document resetctx | 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 @@ -1526,7 +2088,7 @@ define paniclog if *(char *)$kgm_panic_bufptr == 10 printf "\n" else - printf "%c", *$kgm_panic_bufptr + printf "%c", *(char *)$kgm_panic_bufptr end set $kgm_panic_bufptr= (char *)$kgm_panic_bufptr + 1 end @@ -1539,20 +2101,19 @@ document paniclog end define dumpcallqueue - set $kgm_callhead = (queue_t)&$arg0 - set $kgm_call = (struct call_entry *)$kgm_callhead.next + set $kgm_callhead = $arg0 + set $kgm_callentry = $kgm_callhead->next set $kgm_i = 0 - while $kgm_call != $kgm_callhead + while $kgm_callentry != $kgm_callhead + set $kgm_call = (struct call_entry *)$kgm_callentry printf "0x%08x ", $kgm_call printf "0x%08x 0x%08x ", $kgm_call->param0, $kgm_call->param1 - output $kgm_call->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 + set $kgm_callentry = $kgm_callentry->next end printf "%d entries\n", $kgm_i end @@ -1600,7 +2161,8 @@ end define _kgm_flush_loop set $kgm_flush_loop_ctr = 0 while ($kgm_flush_loop_ctr < 30) - flush + flushregs + flushstack set $kgm_flush_loop_ctr = $kgm_flush_loop_ctr + 1 end end @@ -1612,9 +2174,124 @@ define _kgm_update_loop set $kgm_update_loop_ctr = $kgm_update_loop_ctr + 1 end end +# Internal routine used by "_loadfrom" to read from 64-bit addresses +# on 32-bit kernels +define _loadk32m64 + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_readmem64_req_t) + set $kgm_pkt = (kdp_readmem64_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_READMEM64 + set $kgm_pkt->hdr.len = sizeof(kdp_readmem64_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint64_t)$arg0 + set $kgm_pkt->nbytes = sizeof(uint64_t) + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_readmem64_reply_t *)&manual_pkt.data + if ($kgm_pkt->error == 0) + set $kgm_k32read64 = *(uint64_t *)$kgm_pkt->data + else + set $kgm_k32read64 = 0 + end +end + +# Internal routine used by "showx86backtrace" to abstract possible loads from +# user space +define _loadfrom + if (kdp_pmap == 0) + set $kgm_loadval = *(uintptr_t *)$arg0 + else + if ($kgm_x86_abi == 0xe) + set $kgm_loadval = *(uint32_t *)$arg0 + else + if ($kgm_x86_abi == 0xf) + if ($kgm_mtype == $kgm_mtype_i386) + _loadk32m64 $arg0 + set $kgm_loadval = $kgm_k32read64 + else + set $kgm_loadval = *(uint64_t *)$arg0 + end + end + end +end +end + + +#This is necessary since gdb often doesn't do backtraces on x86 correctly +#in the absence of symbols.The code below in showuserstack and +#showx86backtrace also contains several workarouds for the gdb bug where +#gdb stops macro evaluation because of spurious "Cannot read memory" +#errors on x86. These errors appear on ppc as well, but they don't +#always stop macro evaluation. + +set $kgm_cur_frame = 0 +set $kgm_cur_pc = 0 +set $kgm_x86_abi = 0 +define showx86backtrace + if ($kgm_mtype == $kgm_mtype_i386) + set $kgm_frame_reg = $ebp + set $kgm_pc = $eip + set $kgm_ret_off = 4 + end + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kgm_frame_reg = $rbp + set $kgm_pc = $rip + set $kgm_ret_off = 8 + end + + if ($kgm_x86_abi == 0xe) + set $kgm_ret_off = 4 + end + if ($kgm_x86_abi == 0xf) + set $kgm_ret_off = 8 + end + + if ($kgm_cur_frame == 0) + set $kgm_cur_frame = $kgm_frame_reg + end + if ($kgm_cur_pc == 0) + set $kgm_cur_pc = $kgm_pc + end + printf "0: Frame: 0x%016llx PC: 0x%016llx\n", $kgm_cur_frame, $kgm_cur_pc + if (!(($kgm_x86_abi == 0xf) && ($kgm_mtype == $kgm_mtype_i386))) + x/i $kgm_cur_pc + end + set $kgm_tmp_frame = $kgm_cur_frame + set $kgm_cur_frame = 0 + set $kgm_cur_pc = 0 + _loadfrom ($kgm_tmp_frame) + set $kgm_prev_frame = $kgm_loadval + _loadfrom ($kgm_tmp_frame+$kgm_ret_off) + set $kgm_prev_pc = $kgm_loadval + set $kgm_frameno = 1 + while $kgm_prev_frame != 0 + printf "%d: Saved frame: 0x%016llx Saved PC: 0x%016llx\n", $kgm_frameno, $kgm_prev_frame, $kgm_prev_pc + if (!(($kgm_x86_abi == 0xf) && ($kgm_mtype == $kgm_mtype_i386))) + x/i $kgm_prev_pc + end + _loadfrom ($kgm_prev_frame+$kgm_ret_off) + set $kgm_prev_pc = $kgm_loadval + _loadfrom ($kgm_prev_frame) + set $kgm_prev_frame = $kgm_loadval + set $kgm_frameno = $kgm_frameno + 1 + end + set kdp_pmap = 0 + set $kgm_x86_abi = 0 +end + +define showx86backtrace2 + set $kgm_cur_frame = $arg0 + set $kgm_cur_pc = $arg1 + showx86backtrace +end define showuserstack - if ($kgm_mtype == 18) + select 0 + if ($kgm_mtype == $kgm_mtype_ppc) if ($kdp_act_counter == 0) set $kdpstate = (struct savearea *) kdp.saved_state end @@ -1644,10 +2321,39 @@ define showuserstack _kgm_update_loop end else - echo showuserstack not implemented for this architecture.\n - end -end + if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) + set $newact = (struct thread *) $arg0 + set $newiss = (x86_saved_state_t *) ($newact->machine.pcb->iss) + set $kgm_x86_abi = $newiss.flavor + if ($newiss.flavor == 0xf) + set $checkpc = $newiss.uss.ss_64.isf.rip + set $checkframe = $newiss.uss.ss_64.rbp + else + set $checkpc = $newiss.uss.ss_32.eip + set $checkframe = $newiss.uss.ss_32.ebp + end + + if ($checkpc == 0) + echo This activation does not appear to have + echo \20 a valid user context.\n + else + set $kgm_cur_frame = $checkframe + set $kgm_cur_pc = $checkpc + printf "You may now issue the showx86backtrace command to see the user space backtrace for this thread (" + showptr $arg0 + printf "); you can also examine memory locations in this address space (pmap " + showptr $newact->task->map->pmap + printf ") before issuing the backtrace. This two-step process is necessary to work around various bugs in x86 gdb, which cause it to stop memory evaluation on spurious memory read errors. Additionally, you may need to issue a set kdp_pmap = 0 command after the showx86backtrace completes, to resume reading from the kernel address space.\n" + set kdp_pmap = $newact->task->map->pmap + _kgm_flush_loop + _kgm_update_loop + end + else + echo showuserstack not supported on this architecture\n + end + end +end document showuserstack Syntax: showuserstack
|This command displays a numeric backtrace for the user space stack of @@ -1662,6 +2368,7 @@ 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 @@ -1677,7 +2384,7 @@ define sendcore set kdp_flag |= 0x40 set panicd_ip_str = "$arg0" set panicd_specified = 1 - set disableDebugOuput = 0 + set disable_debug_output = 0 set disableConsoleOutput = 0 set logPanicDataToScreen = 1 set reattach_wait = 1 @@ -1709,27 +2416,31 @@ Syntax: disablecore |configured to transmit coredumps through boot-args as well. end -#Use of this macro requires the gdb submission from 3401283 define switchtocorethread - if ($kgm_mtype == 18) - if ($kdp_act_counter == 0) - set $kdpstate = (struct savearea *) kdp.saved_state - end - set $kdp_act_counter = $kdp_act_counter + 1 - set $newact = (struct thread *) $arg0 - if ($newact->kernel_stack == 0) - echo This thread does not have a stack.\n - echo continuation: - output/a (unsigned) $newact.continuation - echo \n - else - loadcontext $newact->machine->pcb -# flushstack will be introduced in a gdb version > gdb-357 - flushstack - set $pc = $newact->machine->pcb.save_srr0 - end + set $newact = (struct thread *) $arg0 + select 0 + if ($newact->kernel_stack == 0) + echo This thread does not have a stack.\n + echo continuation: + output/a (unsigned) $newact.continuation + echo \n + else + if ($kgm_mtype == $kgm_mtype_ppc) + loadcontext $newact->machine->pcb + flushstack + set $pc = $newact->machine->pcb.save_srr0 + else + if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) + set $kgm_cstatep = (struct x86_kernel_state *) \ + ($newact->kernel_stack + kernel_stack_size \ + - sizeof(struct x86_kernel_state)) + loadcontext $kgm_cstatep + flushstack else - echo switchtocorethread not implemented for this architecture.\n + echo switchtocorethread not supported on this architecture\n + end + end + showcontext_int end end @@ -1745,51 +2456,98 @@ Syntax: switchtocorethread
end define loadcontext - set $pc = $arg0.save_srr0 - set $r1 = $arg0.save_r1 - set $lr = $arg0.save_lr - - set $r2 = $arg0.save_r2 - set $r3 = $arg0.save_r3 - set $r4 = $arg0.save_r4 - set $r5 = $arg0.save_r5 - set $r6 = $arg0.save_r6 - set $r7 = $arg0.save_r7 - set $r8 = $arg0.save_r8 - set $r9 = $arg0.save_r9 - set $r10 = $arg0.save_r10 - set $r11 = $arg0.save_r11 - set $r12 = $arg0.save_r12 - set $r13 = $arg0.save_r13 - set $r14 = $arg0.save_r14 - set $r15 = $arg0.save_r15 - set $r16 = $arg0.save_r16 - set $r17 = $arg0.save_r17 - set $r18 = $arg0.save_r18 - set $r19 = $arg0.save_r19 - set $r20 = $arg0.save_r20 - set $r21 = $arg0.save_r21 - set $r22 = $arg0.save_r22 - set $r23 = $arg0.save_r23 - set $r24 = $arg0.save_r24 - set $r25 = $arg0.save_r25 - set $r26 = $arg0.save_r26 - set $r27 = $arg0.save_r27 - set $r28 = $arg0.save_r28 - set $r29 = $arg0.save_r29 - set $r30 = $arg0.save_r30 - set $r31 = $arg0.save_r31 - - set $cr = $arg0.save_cr - set $ctr = $arg0.save_ctr + select 0 + if ($kgm_mtype == $kgm_mtype_ppc) + set $kgm_contextp = (struct savearea *) $arg0 + set $pc = $kgm_contextp.save_srr0 + set $r1 = $kgm_contextp.save_r1 + set $lr = $kgm_contextp.save_lr + + set $r2 = $kgm_contextp.save_r2 + set $r3 = $kgm_contextp.save_r3 + set $r4 = $kgm_contextp.save_r4 + set $r5 = $kgm_contextp.save_r5 + set $r6 = $kgm_contextp.save_r6 + set $r7 = $kgm_contextp.save_r7 + set $r8 = $kgm_contextp.save_r8 + set $r9 = $kgm_contextp.save_r9 + set $r10 = $kgm_contextp.save_r10 + set $r11 = $kgm_contextp.save_r11 + set $r12 = $kgm_contextp.save_r12 + set $r13 = $kgm_contextp.save_r13 + set $r14 = $kgm_contextp.save_r14 + set $r15 = $kgm_contextp.save_r15 + set $r16 = $kgm_contextp.save_r16 + set $r17 = $kgm_contextp.save_r17 + set $r18 = $kgm_contextp.save_r18 + set $r19 = $kgm_contextp.save_r19 + set $r20 = $kgm_contextp.save_r20 + set $r21 = $kgm_contextp.save_r21 + set $r22 = $kgm_contextp.save_r22 + set $r23 = $kgm_contextp.save_r23 + set $r24 = $kgm_contextp.save_r24 + set $r25 = $kgm_contextp.save_r25 + set $r26 = $kgm_contextp.save_r26 + set $r27 = $kgm_contextp.save_r27 + set $r28 = $kgm_contextp.save_r28 + set $r29 = $kgm_contextp.save_r29 + set $r30 = $kgm_contextp.save_r30 + set $r31 = $kgm_contextp.save_r31 + + set $cr = $kgm_contextp.save_cr + set $ctr = $kgm_contextp.save_ctr + else + if ($kgm_mtype == $kgm_mtype_i386) + set $kgm_contextp = (struct x86_kernel_state *) $arg0 + set $ebx = $kgm_contextp->k_ebx + set $ebp = $kgm_contextp->k_ebp + set $edi = $kgm_contextp->k_edi + set $esi = $kgm_contextp->k_esi + set $eip = $kgm_contextp->k_eip + set $pc = $kgm_contextp->k_eip + else + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kgm_contextp = (struct x86_kernel_state *) $arg0 + set $rbx = $kgm_contextp->k_rbx + set $rbp = $kgm_contextp->k_rbp + set $r12 = $kgm_contextp->k_r12 + set $r13 = $kgm_contextp->k_r13 + set $r14 = $kgm_contextp->k_r14 + set $r15 = $kgm_contextp->k_r15 + set $rip = $kgm_contextp->k_rip + set $pc = $kgm_contextp->k_rip + else + echo loadcontext not supported on this architecture\n + end + end + end end define resetcorectx - set $kgm_corecontext = (struct savearea *) kdp.saved_state - loadcontext $kgm_corecontext -# Maintaining this act counter wouldn't be necessary if we just initialized -# $kdpstate at the beginning of the macro.. - set $kdp_act_counter = 0 + select 0 + if ($kgm_mtype == $kgm_mtype_ppc) + set $kgm_corecontext = (struct savearea *) kdp.saved_state + loadcontext $kgm_corecontext + else + if ($kgm_mtype == $kgm_mtype_i386) + set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state + set $ebx = $kdpstatep->ebx + set $ebp = $kdpstatep->ebp + set $edi = $kdpstatep->edi + set $esi = $kdpstatep->esi + set $eip = $kdpstatep->eip + set $eax = $kdpstatep->eax + set $ecx = $kdpstatep->ecx + set $edx = $kdpstatep->edx + flushregs + flushstack + set $pc = $kdpstatep->eip + update + else + echo resetcorectx not supported on this architecture\n + end + end + showcontext_int end document resetcorectx @@ -1833,6 +2591,12 @@ define showgdbthread 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) @@ -1840,17 +2604,31 @@ define showgdbthread 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) + if ($kgm_mtype == $kgm_mtype_ppc) set $mysp = $kgm_thread.machine.pcb->save_r1 - else - set $kgm_statep = (struct i386_kernel_state *) \ - ($kgm_thread->kernel_stack + 0x4000 \ - - sizeof(struct i386_kernel_state)) + end + if ($kgm_mtype == $kgm_mtype_i386) + set $kgm_statep = (struct x86_kernel_state *) \ + ($kgm_thread->kernel_stack + kernel_stack_size \ + - sizeof(struct x86_kernel_state)) set $mysp = $kgm_statep->k_ebp end + if ($kgm_mtype == $kgm_mtype_arm) + if (((unsigned long)$r7 < ((unsigned long) ($kgm_thread->kernel_stack+kernel_stack_size))) \ + && ((unsigned long)$r7 > (unsigned long) ($kgm_thread->kernel_stack))) + set $mysp = $r7 + else + set $kgm_statep = (struct arm_saved_state *)$kgm_thread.machine.kstackptr + set $mysp = $kgm_statep->r[7] + end + end set $prevsp = 0 printf "\n\t\tstacktop=0x%08x", $mysp - switchtoact $arg0 + if ($arg2 == 0) + switchtoact $arg0 + else + switchtocorethread $arg0 + end bt else printf "\n\t\t\tcontinuation=" @@ -1869,7 +2647,7 @@ end #encountering such an error. define showallgdbstacks - set $kgm_head_taskp = &default_pset.tasks + set $kgm_head_taskp = &tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader @@ -1878,11 +2656,11 @@ define showallgdbstacks set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) while $kgm_actp != $kgm_head_actp showactheader - showgdbthread $kgm_actp 1 + 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->pset_tasks.next) + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) end resetctx end @@ -1900,8 +2678,36 @@ Syntax: showallgdbstacks | 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 - if ($kgm_mtype == 18) + select 0 + if ($kgm_mtype == $kgm_mtype_ppc) if ($kdp_act_counter == 0) set $kdpstate = (struct savearea *) kdp.saved_state end @@ -1955,37 +2761,7186 @@ Syntax: switchtouserthread
end define showmetaclass - set cp-abi gnu-v2 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 showallclasses - set cp-abi gnu-v2 - set $kgm_classidx = 0 - while $kgm_classidx < sAllClassesDict->count - set $kgm_meta = (OSMetaClass *) sAllClassesDict->dictionary[$kgm_classidx].value - showmetaclass $kgm_meta - set $kgm_classidx = $kgm_classidx + 1 +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 -document showallclasses -| Show the instance counts and ivar size of all OSObject subclasses. See ioclasscount man page for details. -| The following is the syntax: -| (gdb) showallclasses + +define showdatabytes + set $kgm_data = (OSData *)$arg0 + + printf "<" + set $kgm_datap = (const unsigned char *) $kgm_data->data + set $kgm_idx = 0 + while ( $kgm_idx < $kgm_data->length ) + printf "%02X", *$kgm_datap + set $kgm_datap = $kgm_datap + 1 + set $kgm_idx = $kgm_idx + 1 + end + printf ">\n" +end + +define showdata + set $kgm_data = (OSData *)$arg0 + + printf "<" + set $kgm_datap = (const unsigned char *) $kgm_data->data + + set $kgm_printstr = 0 + if (0 == (3 & (unsigned int)$kgm_datap) && ($kgm_data->length >= 3)) + set $kgm_bytes = *(unsigned int *) $kgm_datap + if (0xffff0000 & $kgm_bytes) + set $kgm_idx = 0 + set $kgm_printstr = 1 + while ($kgm_idx++ < 4) + set $kgm_bytes = $kgm_bytes >> 8 + set $kgm_char = 0xff & $kgm_bytes + if ($kgm_char && (($kgm_char < 0x20) || ($kgm_char > 0x7e))) + set $kgm_printstr = 0 + end + end + end + end + + set $kgm_idx = 0 + if ($kgm_printstr) + set $kgm_quoted = 0 + while ($kgm_idx < $kgm_data->length) + set $kgm_char = $kgm_datap[$kgm_idx++] + if ($kgm_char) + if (0 == $kgm_quoted) + set $kgm_quoted = 1 + if ($kgm_idx > 1) + printf ",\"" + else + printf "\"" + end + end + printf "%c", $kgm_char + else + if ($kgm_quoted) + set $kgm_quoted = 0 + printf "\"" + end + end + end + if ($kgm_quoted) + printf "\"" + end + else + if (0 == (3 & (unsigned int)$kgm_datap)) + while (($kgm_idx + 3) <= $kgm_data->length) + printf "%08x", *(unsigned int *) &$kgm_datap[$kgm_idx] + set $kgm_idx = $kgm_idx + 4 + end + end + while ($kgm_idx < $kgm_data->length) + printf "%02x", $kgm_datap[$kgm_idx++] + end + end + printf ">" +end + +define showdictionaryint + set $kgm$arg0_dict = (OSDictionary *)$arg1 + + printf "{" + set $kgm$arg0_idx = 0 + while ($kgm$arg0_idx < $kgm$arg0_dict->count) + set $kgm_obj = $kgm$arg0_dict->dictionary[$kgm$arg0_idx].key + showobjectint _$arg0 $kgm_obj + printf "=" + set $kgm_obj = $kgm$arg0_dict->dictionary[$kgm$arg0_idx++].value + showobjectint _$arg0 $kgm_obj + if ($kgm$arg0_idx < $kgm$arg0_dict->count) + printf "," + end + end + printf "}" end -define 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 +define indent + set $kgm_idx = 0 + while ($kgm_idx < $arg0) + if ($arg1 & (1 << $kgm_idx++)) + printf "| " + else + printf " " + end + end end -document showioalloc -| Show some accounting of memory allocated by IOKit allocators. See ioalloccount man page for details. -| The following is the syntax: -| (gdb) showioalloc +define showregdictionary + indent $kgm_reg_depth+2 $arg1 + printf "{\n" + + set $kgm_reg_idx = 0 + while ($kgm_reg_idx < $arg0->count) + indent $kgm_reg_depth+2 $arg1 + printf " " + set $kgm_obj = $arg0->dictionary[$kgm_reg_idx].key + showobjectint _ $kgm_obj + printf " = " + + set $kgm_obj = $arg0->dictionary[$kgm_reg_idx++].value + showobjectint _ $kgm_obj + printf "\n" + end + indent $kgm_reg_depth+2 $arg1 + printf "}\n" +end + + +define showarraysetint + set $kgm$arg0_array = (OSArray *)$arg1 + + set $kgm$arg0_idx = 0 + while ($kgm$arg0_idx < $kgm$arg0_array->count) + set $kgm_obj = $kgm$arg0_array->array[$kgm$arg0_idx++] + showobjectint _$arg0 $kgm_obj + if ($kgm$arg0_idx < $kgm$arg0_array->count) + printf "," + end + end +end + +define showarrayint + printf "(" + showarraysetint $arg0 $arg1 + printf ")" +end + +define showsetint + set $kgm_array = ((OSSet *)$arg1)->members + printf "[" + showarraysetint $arg0 $kgm_array + printf "]" +end + + +define showobjectint + set $kgm_obj = (OSObject *) $arg1 + set $kgm_vt = *((void **) $arg1) + + if ($kgm_lp64 || $kgm_mtype == $kgm_mtype_arm) + set $kgm_vt = $kgm_vt - 2 * sizeof(void *) + end + + if ($kgm_show_object_addrs) + printf "`object " + showptr $arg1 + printf ", vt " + output /a (unsigned long) $kgm_vt + if ($kgm_show_object_retain) + printf ", retain count %d, container retain %d", (0xffff & $kgm_obj->retainCount), $kgm_obj->retainCount >> 16 + end + printf "` " + end + + # No multiple-inheritance + set $kgm_shown = 0 + if ($kgm_vt == &_ZTV8OSString) + showstring $arg1 + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV8OSSymbol) + showstring $arg1 + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV8OSNumber) + shownumber $arg1 + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV6OSData) + if $kgm_show_data_alwaysbytes == 1 + showdatabytes $arg1 + else + showdata $arg1 + end + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV9OSBoolean) + showboolean $arg1 + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV12OSDictionary) + showdictionaryint _$arg0 $arg1 + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV7OSArray) + showarrayint _$arg0 $arg1 + set $kgm_shown = 1 + end + if ($kgm_vt == &_ZTV5OSSet) + showsetint _$arg0 $arg1 + set $kgm_shown = 1 + end + + if ($kgm_shown != 1) + if ($kgm_show_object_addrs == 0) + printf "`object " + showptr $arg1 + printf ", vt " + output /a (unsigned long) $kgm_vt + printf "`" + end + end +end + +define showobject + set $kgm_save = $kgm_show_object_addrs + set $kgm_show_object_addrs = 1 + set $kgm_show_object_retain = 1 + showobjectint _ $arg0 + set $kgm_show_object_addrs = $kgm_save + set $kgm_show_object_retain = 0 + printf "\n" +end +document showobject +Syntax: (gdb) showobject +| Show info about an OSObject - its vtable ptr and retain count. +| If the object is a simple container class, more info will be shown. +end + +define dictget + set $kgm_dictp = (OSDictionary *)$arg0 + set $kgm_keyp = (const OSSymbol *)$arg1 + set $kgm_idx = 0 + set $kgm_result = 0 + while (($kgm_idx < $kgm_dictp->count) && ($kgm_result == 0)) + if ($kgm_keyp == $kgm_dictp->dictionary[$kgm_idx].key) + set $kgm_result = $kgm_dictp->dictionary[$kgm_idx].value + end + set $kgm_idx = $kgm_idx + 1 + end +end + + +define _registryentryrecurseinit + set $kgm_re = (IOService *)$arg1 + set $kgm$arg0_stack = (unsigned long long) $arg2 + + if ($arg3) + set $kgm$arg0_stack = $kgm$arg0_stack | (1ULL << $kgm_reg_depth) + else + set $kgm$arg0_stack = $kgm$arg0_stack & ~(1ULL << $kgm_reg_depth) + end + + dictget $kgm_re->fRegistryTable $kgm_childkey + set $kgm$arg0_child_array = (OSArray *) $kgm_result + + if ($kgm$arg0_child_array) + set $kgm$arg0_child_count = $kgm$arg0_child_array->count + else + set $kgm$arg0_child_count = 0 + end + + if ($kgm$arg0_child_count) + set $kgm$arg0_stack = $kgm$arg0_stack | (2ULL << $kgm_reg_depth) + else + set $kgm$arg0_stack = $kgm$arg0_stack & ~(2ULL << $kgm_reg_depth) + end +end + +define findregistryentryrecurse + set $kgm_registry_entry = 0 + _registryentryrecurseinit $arg0 $arg1 $arg2 $arg3 + + dictget $kgm_re->fRegistryTable $kgm_namekey + if ($kgm_result == 0) + dictget $kgm_re->fRegistryTable gIONameKey + end + if ($kgm_result == 0) + dictget $kgm_re->fPropertyTable gIOClassKey + end + + if ($kgm_result != 0) + set $str = ((OSString *) $kgm_result)->string + strcmp_nomalloc $str $kgm_reg_find_str0 $kgm_reg_find_str1 $kgm_reg_find_str2 $kgm_reg_find_str3 $kgm_reg_find_str4 $kgm_reg_find_str5 $kgm_reg_find_str6 $kgm_reg_find_str7 $kgm_reg_find_str8 + if $kgm_findregistry_verbose + echo . + end + + if $kgm_strcmp_result == 0 + if $kgm_findregistry_verbose + printf "\n%s:\n | ", ((OSString *) $kgm_result)->string + showobject $kgm_re + printf " | " + print $kgm_re + end + + # if we want to show everything, then don't populate $kgm_registry_entry + if !$kgm_findregistry_continue + set $kgm_registry_entry = $kgm_re + end + end + end + + # recurse + if (!$kgm_registry_entry && ($kgm$arg0_child_count != 0)) + set $kgm_reg_depth = $kgm_reg_depth + 1 + set $kgm$arg0_child_idx = 0 + + while ($kgm$arg0_child_idx < $kgm$arg0_child_count) + set $kgm_re = $kgm$arg0_child_array->array[$kgm$arg0_child_idx++] + set $kgm_more_sib = ($kgm$arg0_child_idx < $kgm$arg0_child_count) + if $kgm_reg_depth >= $kgm_reg_depth_max + 1 + loop_break + end + findregistryentryrecurse _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib + if $kgm_registry_entry + loop_break + end + end + set $kgm_reg_depth = $kgm_reg_depth - 1 + end +end + +define findregdictvalue + set $kgm_registry_value = 0 + set $kgm_reg_idx = 0 + while ($kgm_reg_idx < $arg0->count) + set $kgm_obj = $arg0->dictionary + $kgm_reg_idx + set $str = ((OSString *)$kgm_obj->key)->string + strcmp_nomalloc $str $kgm_reg_find_str0 $kgm_reg_find_str1 $kgm_reg_find_str2 $kgm_reg_find_str3 $kgm_reg_find_str4 $kgm_reg_find_str5 $kgm_reg_find_str6 $kgm_reg_find_str7 $kgm_reg_find_str8 + + if $kgm_strcmp_result == 0 + set $kgm_registry_value = $kgm_obj->value + if $kgm_findregistry_verbose + showobject $kgm_registry_value + print $kgm_registry_value + end + loop_break + end + set $kgm_reg_idx = $kgm_reg_idx + 1 + end +end + +define setfindregistrystr + set $kgm_reg_find_str0 = 0 + set $kgm_reg_find_str1 = 0 + set $kgm_reg_find_str2 = 0 + set $kgm_reg_find_str3 = 0 + set $kgm_reg_find_str4 = 0 + set $kgm_reg_find_str5 = 0 + set $kgm_reg_find_str6 = 0 + set $kgm_reg_find_str7 = 0 + set $kgm_reg_find_str8 = 0 + + if $argc > 0 + set $kgm_reg_find_str0 = $arg0 + end + if $argc > 1 + set $kgm_reg_find_str1 = $arg1 + end + if $argc > 2 + set $kgm_reg_find_str2 = $arg2 + end + if $argc > 3 + set $kgm_reg_find_str3 = $arg3 + end + if $argc > 4 + set $kgm_reg_find_str4 = $arg4 + end + if $argc > 5 + set $kgm_reg_find_str5 = $arg5 + end + if $argc > 6 + set $kgm_reg_find_str6 = $arg6 + end + if $argc > 7 + set $kgm_reg_find_str7 = $arg7 + end + if $argc > 8 + set $kgm_reg_find_str8 = $arg8 + end +end + +document setfindregistrystr +Syntax: (gdb) setfindregistrystr [a] [b] [c] [d] [e] [f] [g] [h] [i] +| Store an encoded string into up to 9 arguments for use by +| findregistryprop or findregistryentry. The arguments are created +| through calls to strcmp_arg_pack64 +end + +define _findregistryprop + set $reg = (IOService *) $arg0 + set $kgm_props = $reg->fPropertyTable + set $kgm_findregistry_verbose = 0 + + findregdictvalue $kgm_props +end + +define findregistryprop + set $reg = (IOService *) $arg0 + set $kgm_props = $reg->fPropertyTable + + set $kgm_findregistry_verbose = 1 + findregdictvalue $kgm_props +end + +document findregistryprop +Syntax: (gdb) findregistryprop +| Given a registry entry, print out the contents for the property that matches +| the encoded string specified via setfindregistrystr. +| +| For example, the following will print out the "intel-pic" property stored in +| the AppleACPIPlatformExpert registry entry $pe_entry: +| strcmp_arg_pack64 'i' 'n' 't' 'e' 'l' '-' 'p' 'i' +| set $intel_pi = $kgm_strcmp_arg +| strcmp_arg_pack64 'c' 0 0 0 0 0 0 0 +| set $c = $kgm_strcmp_arg +| setfindregistrystr $intel_pi $c +| findregistryprop $pe_entry +end + +define findregistryentryint + set $kgm_namekey = (OSSymbol *) $kgm_reg_plane->nameKey + set $kgm_childkey = (OSSymbol *) $kgm_reg_plane->keys[1] + if $kgm_findregistry_verbose + printf "Searching" + end + findregistryentryrecurse _ $arg0 0 0 +end + +define _findregistryentry + set $kgm_findregistry_verbose = 0 + set $kgm_findregistry_continue = 0 + set $kgm_reg_depth = 0 + + findregistryentryint gRegistryRoot +end + +define findregistryentry + set $kgm_findregistry_verbose = 1 + set $kgm_findregistry_continue = 0 + set $kgm_reg_depth = 0 + + findregistryentryint gRegistryRoot +end + +define findregistryentries + set $kgm_findregistry_verbose = 1 + set $kgm_findregistry_continue = 1 + set $kgm_reg_depth = 0 + + findregistryentryint gRegistryRoot +end + +document findregistryentry +Syntax: (gdb) findregistryentry +| Search for a registry entry that matches the encoded string specified through +| setfindregistrystr. You can alter the search depth through use of +| $kgm_reg_depth_max. +| +| For example, the following will pull out the AppleACPIPlatformExpert registry +| entry: +| strcmp_arg_pack64 'A' 'p' 'p' 'l' 'e' 'A' 'C' 'P' +| set $AppleACP = $kgm_strcmp_arg +| strcmp_arg_pack64 'I' 'P' 'l' 'a' 't' 'f' 'o' 'r' +| set $IPlatfor = $kgm_strcmp_arg +| strcmp_arg_pack64 'm' 'E' 'x' 'p' 'e' 'r' 't' 0 +| set $mExpert = $kgm_strcmp_arg +| setfindregistrystr $AppleACP $IPlatfor $mExpert +| findregistryentry +end + +document findregistryentries +Syntax: (gdb) findregistryentries +| Search for all registry entries that match the encoded string specified through +| setfindregistrystr. You can alter the search depth through use of +| $kgm_reg_depth_max. See findregistryentry for an example of how to encode a string. +end + + +define showregistryentryrecurse + _registryentryrecurseinit $arg0 $arg1 $arg2 $arg3 + + indent $kgm_reg_depth $kgm$arg0_stack + printf "+-o " + + dictget $kgm_re->fRegistryTable $kgm_namekey + if ($kgm_result == 0) + dictget $kgm_re->fRegistryTable gIONameKey + end + if ($kgm_result == 0) + dictget $kgm_re->fPropertyTable gIOClassKey + end + + if ($kgm_result != 0) + printf "%s", ((OSString *)$kgm_result)->string + else + if (((IOService*)$kgm_re)->pwrMgt && ((IOService*)$kgm_re)->pwrMgt->Name) + printf "%s", ((IOService*)$kgm_re)->pwrMgt->Name + else +# printf ", guessclass " +# guessclass $kgm_re + printf "??" + end + end + + + printf " IORegistryEntry::reserved->fRegistryEntryID + printf "vtable " + set $kgm_vt = (unsigned long) *(void**) $kgm_re + if ($kgm_lp64 || $kgm_mtype == $kgm_mtype_arm) + set $kgm_vt = $kgm_vt - 2 * sizeof(void *) + end + output /a $kgm_vt + + if ($kgm_vt != &_ZTV15IORegistryEntry) + printf ", " + set $kgm_state = $kgm_re->__state[0] + # kIOServiceRegisteredState + if (0 == ($kgm_state & 2)) + printf "!" + end + printf "registered, " + # kIOServiceMatchedState + if (0 == ($kgm_state & 4)) + printf "!" + end + printf "matched, " + # kIOServiceInactiveState + if ($kgm_state & 1) + printf "in" + end + printf "active, busy %d, retain count %d", (0xff & $kgm_re->__state[1]), (0xffff & $kgm_re->retainCount) + end + printf ">\n" + + if ($kgm_show_props) + set $kgm_props = $kgm_re->fPropertyTable + showregdictionary $kgm_props $kgm$arg0_stack + end + + # recurse + if ($kgm$arg0_child_count != 0) + + set $kgm_reg_depth = $kgm_reg_depth + 1 + set $kgm$arg0_child_idx = 0 + + while ($kgm$arg0_child_idx < $kgm$arg0_child_count) + set $kgm_re = $kgm$arg0_child_array->array[$kgm$arg0_child_idx++] + set $kgm_more_sib = ($kgm$arg0_child_idx < $kgm$arg0_child_count) + if $kgm_reg_depth >= $kgm_reg_depth_max + 1 + loop_break + end + showregistryentryrecurse _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib + end + + set $kgm_reg_depth = $kgm_reg_depth - 1 + end +end + +define showregistryentryint + set $kgm_namekey = (OSSymbol *) $kgm_reg_plane->nameKey + set $kgm_childkey = (OSSymbol *) $kgm_reg_plane->keys[1] + + 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. You can specify the maximum +| display depth with $kgm_reg_depth_max. +end + +define showregistryprops + set $kgm_reg_depth = 0 + set $kgm_show_props = 1 + showregistryentryint gRegistryRoot +end +document showregistryprops +Syntax: (gdb) showregistryprops +| Show info about all registry entries in the current plane, and their properties. +| set $kgm_show_object_addrs = 1 and/or set $kgm_show_object_retain = 1 will display +| more verbose information +end + +define showregistryentry + set $kgm_reg_depth = 0 + set $kgm_show_props = 1 + showregistryentryint $arg0 +end +document showregistryentry +Syntax: (gdb) showregistryentry +| Show info about a registry entry; its properties and descendants in the current plane. +end + +define setregistryplane + if ($arg0 != 0) + set $kgm_reg_plane = (IORegistryPlane *) $arg0 + else + showobjectint _ gIORegistryPlanes + printf "\n" + end +end +document setregistryplane +Syntax: (gdb) setregistryplane +| Set the plane to be used for the iokit registry macros. An argument of zero will +| display known planes. +end + +define guessclass + set $kgm_classidx = 0 + set $kgm_lookvt = *((void **) $arg0) + set $kgm_bestvt = (void *) 0 + set $kgm_bestidx = 0 + + while $kgm_classidx < sAllClassesDict->count + set $kgm_meta = (OSMetaClass *) sAllClassesDict->dictionary[$kgm_classidx].value + + set $kgm_vt = *((void **) $kgm_meta) + + if (($kgm_vt > $kgm_bestvt) && ($kgm_vt < $kgm_lookvt)) + set $kgm_bestvt = $kgm_vt + set $kgm_bestidx = $kgm_classidx + end + set $kgm_classidx = $kgm_classidx + 1 + end + printf "%s", sAllClassesDict->dictionary[$kgm_bestidx].key->string +end + +define showallclasses + set $kgm_classidx = 0 + while $kgm_classidx < sAllClassesDict->count + set $kgm_meta = (OSMetaClass *) sAllClassesDict->dictionary[$kgm_classidx++].value + showmetaclass $kgm_meta + end +end + +document showallclasses +Syntax: (gdb) showallclasses +| Show the instance counts and ivar size of all OSObject subclasses. See ioclasscount man page for details. +end + +define showioalloc + printf " Instance allocation = 0x%08lx = %4ld K\n", (int) debug_ivars_size, ((int) debug_ivars_size) / 1024 + printf "Container allocation = 0x%08lx = %4ld K\n", (int) debug_container_malloc_size, ((int) debug_container_malloc_size) / 1024 + printf " IOMalloc allocation = 0x%08lx = %4ld K\n", (int) debug_iomalloc_size, ((int) debug_iomalloc_size) / 1024 + printf " Pageable allocation = 0x%08lx = %4ld K\n", (vm_size_t) debug_iomallocpageable_size, ((vm_size_t) debug_iomallocpageable_size) / 1024 +end + +document showioalloc +Syntax: (gdb) showioalloc +| Show some accounting of memory allocated by IOKit allocators. See ioalloccount man page for details. +end + +define showosobjecttracking + set $kgm_next = (OSObjectTracking *) gOSObjectTrackList.next + while $kgm_next != &gOSObjectTrackList + set $obj = (OSObject *) ($kgm_next+1) + showobject $obj + set $kgm_idx = 0 + while $kgm_idx < (sizeof($kgm_next->bt) / sizeof($kgm_next->bt[0])) + if ((unsigned long) $kgm_next->bt[$kgm_idx] > (unsigned long) &last_kernel_symbol) + showkmodaddr $kgm_next->bt[$kgm_idx] + printf "\n" + else + if ((unsigned long) $kgm_next->bt[$kgm_idx] > 0) + output /a $kgm_next->bt[$kgm_idx] + printf "\n" + end + end + set $kgm_idx = $kgm_idx + 1 + end + printf "\n" + set $kgm_next = (OSObjectTracking *) $kgm_next->link.next + end +end + +document showosobjecttracking +Syntax: (gdb) showosobjecttracking +| Show the list of tracked OSObject allocations with backtraces. +| Boot with the kOSTraceObjectAlloc (0x00400000) io debug flag set. +| Set gOSObjectTrackThread to 1 or a thread_t to capture new OSObjects allocated by a thread or all threads. +end + +define readphysint + set $kgm_readphysint_result = 0xBAD10AD + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_readphysmem64_req_t) + set $kgm_pkt = (kdp_readphysmem64_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_READPHYSMEM64 + set $kgm_pkt->hdr.len = sizeof(kdp_readphysmem64_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint64_t)$arg0 + set $kgm_pkt->nbytes = $arg1 >> 3 + set $kgm_pkt->lcpu = $arg2 + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_readphysmem64_reply_t *)&manual_pkt.data + if ($kgm_pkt->error == 0) + if $arg1 == 8 + set $kgm_readphysint_result = *((uint8_t *)$kgm_pkt->data) + end + if $arg1 == 16 + set $kgm_readphysint_result = *((uint16_t *)$kgm_pkt->data) + end + if $arg1 == 32 + set $kgm_readphysint_result = *((uint32_t *)$kgm_pkt->data) + end + if $arg1 == 64 + set $kgm_readphysint_result = *((uint64_t *)$kgm_pkt->data) + end + end +end + +define readphys8 + readphysint $arg0 8 $kgm_lcpu_self + output /a $arg0 + printf ":\t0x%02hhx\n", $kgm_readphysint_result + set $kgm_readphys_result = (uint64_t)$kgm_readphysint_result +end + +define readphys16 + readphysint $arg0 16 $kgm_lcpu_self + output /a $arg0 + printf ":\t0x%04hx\n", $kgm_readphysint_result + set $kgm_readphys_result = (uint64_t)$kgm_readphysint_result +end + +define readphys32 + readphysint $arg0 32 $kgm_lcpu_self + output /a $arg0 + printf ":\t0x%08x\n", $kgm_readphysint_result + set $kgm_readphys_result = (uint64_t)$kgm_readphysint_result +end + +define readphys64 + readphysint $arg0 64 $kgm_lcpu_self + output /a $arg0 + printf ":\t0x%016llx\n", $kgm_readphysint_result + set $kgm_readphys_result = (uint64_t)$kgm_readphysint_result +end + +define readphys + readphys32 $arg0 +end + +document readphys8 +| See readphys64 +end + +document readphys16 +| See readphys64 +end + +document readphys32 +| See readphys64 +end + +document readphys64 +| The argument is interpreted as a physical address, and the 64-bit word +| addressed is displayed. Saves 64-bit result in $kgm_readphys_result. +end + +define writephysint + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_writephysmem64_req_t) + set $kgm_pkt = (kdp_writephysmem64_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_WRITEPHYSMEM64 + set $kgm_pkt->hdr.len = sizeof(kdp_writephysmem64_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint64_t)$arg0 + set $kgm_pkt->nbytes = $arg1 >> 3 + set $kgm_pkt->lcpu = $arg3 + if $arg1 == 8 + set *(uint8_t *)$kgm_pkt->data = (uint8_t)$arg2 + end + if $arg1 == 16 + set *(uint16_t *)$kgm_pkt->data = (uint16_t)$arg2 + end + if $arg1 == 32 + set *(uint32_t *)$kgm_pkt->data = (uint32_t)$arg2 + end + if $arg1 == 64 + set *(uint64_t *)$kgm_pkt->data = (uint64_t)$arg2 + end + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_writephysmem64_reply_t *)&manual_pkt.data + set $kgm_writephysint_result = $kgm_pkt->error +end + +define writephys8 + writephysint $arg0 8 $arg1 $kgm_lcpu_self +end + +define writephys16 + writephysint $arg0 16 $arg1 $kgm_lcpu_self +end + +define writephys32 + writephysint $arg0 32 $arg1 $kgm_lcpu_self +end + +define writephys64 + writephysint $arg0 64 $arg1 $kgm_lcpu_self +end + +document writephys8 +| See writephys64 +end + +document writephys16 +| See writephys64 +end + +document writephys32 +| See writephys64 +end + +document writephys64 +| The argument is interpreted as a physical address, and the second argument is +| written to that address as a 64-bit word. +end + +define addkextsyms + shell ls $arg0/* | xargs -n 1 echo add-symbol-file > /tmp/gdb-syms + source /tmp/gdb-syms + set $kgm_show_kmod_syms = 1 +end + +document addkextsyms +| Takes a directory of symbols for kexts generated with kextcache -y and loads them +| into gdb. +| (gdb) addkextsyms /path/to/symboldir +end + +define showprocfiles + if ($argc == 1) + _showprocheader + _showprocfiles $arg0 + else + printf "| Usage:\n|\n" + help showprocfiles + end +end +document showprocfiles +Syntax: (gdb) showprocfiles +| Given a proc_t pointer, display the list of open file descriptors for the +| referenced process. +end + +define _showprocheader + printf "fd fileglob " + showptrhdrpad + printf " fg flags fg type fg data " + showptrhdrpad + printf " info\n" + printf "----- ----------" + if $kgm_lp64 + printf "--------" + end + printf " ---------- -------- ----------" + if $kgm_lp64 + printf "--------" + end + printf " -------------------\n" +end + +define _showprocfiles + set $kgm_spf_filedesc = ((proc_t)$arg0)->p_fd + set $kgm_spf_last = $kgm_spf_filedesc->fd_lastfile + set $kgm_spf_ofiles = $kgm_spf_filedesc->fd_ofiles + set $kgm_spf_count = 0 + while ($kgm_spf_count <= $kgm_spf_last) + if ($kgm_spf_ofiles[$kgm_spf_count] == 0) + # DEBUG: For files that were open, but are now closed + # printf "%-5d FILEPROC_NULL\n", $kgm_spf_count + else + # display fd #, fileglob address, fileglob flags + set $kgm_spf_flags = $kgm_spf_ofiles[$kgm_spf_count].f_flags + set $kgm_spf_fg = $kgm_spf_ofiles[$kgm_spf_count].f_fglob + printf "%-5d ", $kgm_spf_count + showptr $kgm_spf_fg + printf " 0x%08x ", $kgm_spf_flags + # decode fileglob type + set $kgm_spf_fgt = $kgm_spf_fg->fg_type + if ($kgm_spf_fgt == 1) + printf "VNODE " + end + if ($kgm_spf_fgt == 2) + printf "SOCKET " + end + if ($kgm_spf_fgt == 3) + printf "PSXSHM " + end + if ($kgm_spf_fgt == 4) + printf "PSXSEM " + end + if ($kgm_spf_fgt == 5) + printf "KQUEUE " + end + if ($kgm_spf_fgt == 6) + printf "PIPE " + end + if ($kgm_spf_fgt == 7) + printf "FSEVENTS" + end + if ($kgm_spf_fgt < 1 || $kgm_spf_fgt > 7) + printf "?: %-5d", $kgm_spf_fgt + end + + # display fileglob data address and decode interesting fact(s) + # about data, if we know any + set $kgm_spf_fgd = $kgm_spf_fg->fg_data + printf " " + showptr $kgm_spf_fgd + printf " " + if ($kgm_spf_fgt == 1) + set $kgm_spf_name = ((struct vnode *)$kgm_spf_fgd)->v_name + if ($kgm_spf_name == 0) + printf "(null)" + else + printf "%s", $kgm_spf_name + end + end + printf "\n" + end + set $kgm_spf_count = $kgm_spf_count + 1 + end +end + +# +# Show all the advisory file locks held by a process for each of the vnode +# type files that it has open; do this by walking the per process open file +# table and looking at any vnode type fileglob that has a non-NULL lock list +# associated with it. +# +define showproclocks + if ($argc == 1) + _showproclocks $arg0 + else + printf "| Usage:\n|\n" + help showproclocks + end +end +document showproclocks +Syntax: (gdb) showproclocks +| Given a proc_t pointer, display the list of advisory file locks held by the +| referenced process. +end + +define _showproclocks + set $kgm_spl_filedesc = ((proc_t)$arg0)->p_fd + set $kgm_spl_last = $kgm_spl_filedesc->fd_lastfile + set $kgm_spl_ofiles = $kgm_spl_filedesc->fd_ofiles + set $kgm_spl_count = 0 + set $kgm_spl_seen = 0 + while ($kgm_spl_count <= $kgm_spl_last) + if ($kgm_spl_ofiles[$kgm_spl_count] == 0) + # DEBUG: For files that were open, but are now closed + # printf "%-5d FILEPROC_NULL\n", $kgm_spl_count + else + set $kgm_spl_fg = $kgm_spl_ofiles[$kgm_spl_count].f_fglob + # decode fileglob type + set $kgm_spl_fgt = $kgm_spl_fg->fg_type + if ($kgm_spl_fgt == 1) + set $kgm_spl_fgd = $kgm_spl_fg->fg_data + set $kgm_spl_name = ((struct vnode *)$kgm_spl_fgd)->v_name + set $kgm_spl_vnode = ((vnode_t)$kgm_spl_fgd) + set $kgm_spl_lockiter = $kgm_spl_vnode->v_lockf + if ($kgm_spl_lockiter != 0) + if ($kgm_spl_seen == 0) + _showvnodelockheader + end + set $kgm_spl_seen = $kgm_spl_seen + 1 + printf "( fd %d, name ", $kgm_spl_count + if ($kgm_spl_name == 0) + printf "(null) )" + else + printf "%s )\n", $kgm_spl_name + end + _showvnodelocks $kgm_spl_fgd + end + end + end + set $kgm_spl_count = $kgm_spf_count + 1 + end + printf "%d total locks for ", $kgm_spl_seen + showptr $arg0 + printf "\n" +end + +define showprocinfo + set $kgm_spi_proc = (proc_t)$arg0 + printf "Process " + showptr $kgm_spi_proc + printf "\n" + printf " name %s\n", $kgm_spi_proc->p_comm + printf " pid:%.8d", $kgm_spi_proc->p_pid + printf " task:" + showptr $kgm_spi_proc->task + printf " p_stat:%.1d", $kgm_spi_proc->p_stat + printf " parent pid:%.8d", $kgm_spi_proc->p_ppid + printf "\n" + # decode part of credential + set $kgm_spi_cred = $kgm_spi_proc->p_ucred + if ($kgm_spi_cred != 0) + printf "Cred: euid %d ruid %d svuid %d\n", $kgm_spi_cred->cr_uid, $kgm_spi_cred->cr_ruid, $kgm_spi_cred->cr_svuid + else + printf "Cred: (null)\n" + end + # decode flags + set $kgm_spi_flag = $kgm_spi_proc->p_flag + printf "Flags: 0x%08x\n", $kgm_spi_flag + if ($kgm_spi_flag & 0x00000001) + printf " 0x00000001 - may hold advisory locks\n" + end + if ($kgm_spi_flag & 0x00000002) + printf " 0x00000002 - has a controlling tty\n" + end + if ($kgm_spi_flag & 0x00000004) + printf " 0x00000004 - process is 64 bit\n" + else + printf " !0x00000004 - process is 32 bit\n" + end + if ($kgm_spi_flag & 0x00000008) + printf " 0x00000008 - no SIGCHLD on child stop\n" + end + if ($kgm_spi_flag & 0x00000010) + printf " 0x00000010 - waiting for child exec/exit\n" + end + if ($kgm_spi_flag & 0x00000020) + printf " 0x00000020 - has started profiling\n" + end + if ($kgm_spi_flag & 0x00000040) + printf " 0x00000040 - in select; wakeup/waiting danger\n" + end + if ($kgm_spi_flag & 0x00000080) + printf " 0x00000080 - was stopped and continued\n" + end + if ($kgm_spi_flag & 0x00000100) + printf " 0x00000100 - has set privileges since exec\n" + end + if ($kgm_spi_flag & 0x00000200) + printf " 0x00000200 - system process: no signals, stats, or swap\n" + end + if ($kgm_spi_flag & 0x00000400) + printf " 0x00000400 - timing out during a sleep\n" + end + if ($kgm_spi_flag & 0x00000800) + printf " 0x00000800 - debugged process being traced\n" + end + if ($kgm_spi_flag & 0x00001000) + printf " 0x00001000 - debugging process has waited for child\n" + end + if ($kgm_spi_flag & 0x00002000) + printf " 0x00002000 - exit in progress\n" + end + if ($kgm_spi_flag & 0x00004000) + printf " 0x00004000 - process has called exec\n" + end + if ($kgm_spi_flag & 0x00008000) + printf " 0x00008000 - owe process an addupc() XXX\n" + end + if ($kgm_spi_flag & 0x00010000) + printf " 0x00010000 - affinity for Rosetta children\n" + end + if ($kgm_spi_flag & 0x00020000) + printf " 0x00020000 - wants to run Rosetta\n" + end + if ($kgm_spi_flag & 0x00040000) + printf " 0x00040000 - has wait() in progress\n" + end + if ($kgm_spi_flag & 0x00080000) + printf " 0x00080000 - kdebug tracing on for this process\n" + end + if ($kgm_spi_flag & 0x00100000) + printf " 0x00100000 - blocked due to SIGTTOU or SIGTTIN\n" + end + if ($kgm_spi_flag & 0x00200000) + printf " 0x00200000 - has called reboot()\n" + end + if ($kgm_spi_flag & 0x00400000) + printf " 0x00400000 - is TBE state\n" + end + if ($kgm_spi_flag & 0x00800000) + printf " 0x00800000 - signal exceptions\n" + end + if ($kgm_spi_flag & 0x01000000) + printf " 0x01000000 - has thread cwd\n" + end + if ($kgm_spi_flag & 0x02000000) + printf " 0x02000000 - has vfork() children\n" + end + if ($kgm_spi_flag & 0x04000000) + printf " 0x04000000 - not allowed to attach\n" + end + if ($kgm_spi_flag & 0x08000000) + printf " 0x08000000 - vfork() in progress\n" + end + if ($kgm_spi_flag & 0x10000000) + printf " 0x10000000 - no shared libraries\n" + end + if ($kgm_spi_flag & 0x20000000) + printf " 0x20000000 - force quota for root\n" + end + if ($kgm_spi_flag & 0x40000000) + printf " 0x40000000 - no zombies when children exit\n" + end + if ($kgm_spi_flag & 0x80000000) + printf " 0x80000000 - don't hang on remote FS ops\n" + end + # decode state + set $kgm_spi_state = $kgm_spi_proc->p_stat + printf "State: " + if ($kgm_spi_state == 1) + printf "Idle\n" + end + if ($kgm_spi_state == 2) + printf "Run\n" + end + if ($kgm_spi_state == 3) + printf "Sleep\n" + end + if ($kgm_spi_state == 4) + printf "Stop\n" + end + if ($kgm_spi_state == 5) + printf "Zombie\n" + end + if ($kgm_spi_state == 6) + printf "Reaping\n" + end + if ($kgm_spi_state < 1 || $kgm_spi_state > 6) + printf "(Unknown)\n" + end +end + +document showprocinfo +Syntax: (gdb) showprocinfo +| Displays name, pid, parent and task for a proc_t. Decodes cred, flag and p_stat fields. +end + +# +# dump the zombprocs +# +define zombproc + set $basep = (struct proc *)zombproc->lh_first + set $pp = $basep + while $pp + showprocinfo $pp + set $pp = $pp->p_list.le_next + end +end + +document zombproc +Syntax: (gdb) zombproc +| Routine to print out all procs in the zombie list +end + +# +# dump the zombstacks +# +define zombstacks + set $basep = (struct proc *)zombproc->lh_first + set $pp = $basep + while $pp + if $pp->p_stat != 5 + showtaskstacks $pp->task + end + set $pp = $pp->p_list.le_next + end +end + +document zombstacks +Syntax: (gdb) zombstacks +| Routine to print out all stacks of tasks that are exiting +end + + +# +# dump the allprocs +# +define allproc + set $basep = (struct proc *)allproc->lh_first + set $pp = $basep + while $pp + showprocinfo $pp + set $pp = $pp->p_list.le_next + end +end + +document allproc +Syntax: (gdb) allproc +| Routine to print out all process in the system +| which are not in the zombie list +end + + + +define print_vnode + set $vp = (struct vnode *)$arg0 + printf " " + printf " vp " + showptr $vp + printf " use %d", $vp->v_usecount + printf " io %d", $vp->v_iocount + printf " kuse %d", $vp->v_kusecount + printf " type %d", $vp->v_type + printf " flg 0x%.8x", $vp->v_flag + printf " lflg 0x%.8x", $vp->v_lflag + printf " par " + showptr $vp->v_parent + set $_name = (char *)$vp->v_name + if ($_name != 0) + printf " %s", $_name + end + if ($vp->v_type == VREG) && ($vp->v_un.vu_ubcinfo != 0) + printf " mapped %d", ($vp->v_un.vu_ubcinfo.ui_flags & 0x08) ? 1 : 0 + end + printf "\n" +end + +document print_vnode +Syntax: (gdb) print_vnode +| 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 " + showptr $mp + printf " flag %x", $mp->mnt_flag + printf " kern_flag %x", $mp->mnt_kern_flag + printf " lflag %x", $mp->mnt_lflag + printf " type: %s", $mp->mnt_vfsstat.f_fstypename + printf " mnton: %s", $mp->mnt_vfsstat.f_mntonname + printf " mntfrom: %s", $mp->mnt_vfsstat.f_mntfromname + printf "\n" +end + +define showallmounts + set $mp=(struct mount *)mountlist.tqh_first + while $mp + print_mount $mp + set $mp = $mp->mnt_list.tqe_next + end +end + +document showallmounts +Syntax: showallmounts +| Print all mount points +end + +define pcprint + if (((unsigned long) $arg0 < (unsigned long) &_mh_execute_header || \ + (unsigned long) $arg0 >= (unsigned long) &last_kernel_symbol )) + showkmodaddr $arg0 + else + output /a $arg0 + end +end + +define mbuf_walkpkt + set $mp = (struct mbuf *)$arg0 + set $cnt = 1 + set $tot = 0 + while $mp + printf "%4d: %p [len %4d, type %2d, ", $cnt, $mp, \ + $mp->m_hdr.mh_len, $mp->m_hdr.mh_type + if mclaudit != 0 + mbuf_buf2mca $mp + printf ", " + end + set $tot = $tot + $mp->m_hdr.mh_len + printf "total %d]\n", $tot + set $mp = $mp->m_hdr.mh_nextpkt + set $cnt = $cnt + 1 + end +end + +document mbuf_walkpkt +Syntax: (gdb) mbuf_walkpkt +| Given an mbuf address, walk its m_nextpkt pointer +end + +define mbuf_walk + set $mp = (struct mbuf *)$arg0 + set $cnt = 1 + set $tot = 0 + while $mp + printf "%4d: %p [len %4d, type %2d, ", $cnt, $mp, \ + $mp->m_hdr.mh_len, $mp->m_hdr.mh_type + if mclaudit != 0 + mbuf_buf2mca $mp + printf ", " + end + set $tot = $tot + $mp->m_hdr.mh_len + printf "total %d]\n", $tot + set $mp = $mp->m_hdr.mh_next + set $cnt = $cnt + 1 + end +end + +document mbuf_walk +Syntax: (gdb) mbuf_walk +| Given an mbuf address, walk its m_next pointer +end + +define mbuf_buf2slab + set $addr = $arg0 + set $gix = ((char *)$addr - (char *)mbutl) >> 20 + set $ix = ((char *)$addr - (char *)mbutl) >> 11 + set $slab = &slabstbl[$gix].slg_slab[$ix] + printf "%p", $slab +end + +document mbuf_buf2slab +| Given an mbuf object, find its corresponding slab address. +end + +define mbuf_buf2mca + set $addr = $arg0 + set $ix = ((char *)$addr - (char *)mbutl) >> 11 + set $clbase = ((union mcluster *)(mbutl + $ix)) + set $mclidx = (((char *)$addr - (char *)$clbase) >> 8) + set $mca = mclaudit[$ix].cl_audit[$mclidx] + printf "mca: %p", $mca +end + +document mbuf_buf2mca +Syntax: (gdb) mbuf_buf2mca +| Given an mbuf object, find its buffer audit structure address. +| This requires mbuf buffer auditing to be turned on, by setting +| the appropriate flags to the "mbuf_debug" boot-args parameter. +end + +define mbuf_showmca + set language c + set $mca = (mcache_audit_t *)$arg0 + set $cp = (mcache_t *)$mca->mca_cache + printf "object type:\t\t" + mbuf_mca_ctype $mca 1 + printf "\ncontrolling mcache:\t%p (%s)\n", $mca->mca_cache, $cp->mc_name + if $mca->mca_uflags & $MB_SCVALID + set $ix = ((char *)$mca->mca_addr - (char *)mbutl) >> 11 + set $clbase = ((union mcluster *)(mbutl + $ix)) + set $mclidx = (((char *)$mca->mca_addr - (char *)$clbase) >> 8) + printf "mbuf obj:\t\t%p\n", $mca->mca_addr + printf "mbuf index:\t\t%d (out of 8) in cluster base %p\n", \ + $mclidx + 1, $clbase + if $mca->mca_uptr != 0 + set $peer_mca = (mcache_audit_t *)$mca->mca_uptr + printf "paired cluster obj:\t%p (mca %p)\n", \ + $peer_mca->mca_addr, $peer_mca + end + printf "saved contents:\t\t%p (%d bytes)\n", \ + $mca->mca_contents, $mca->mca_contents_size + else + printf "cluster obj:\t\t%p\n", $mca->mca_addr + if $mca->mca_uptr != 0 + set $peer_mca = (mcache_audit_t *)$mca->mca_uptr + printf "paired mbuf obj:\t%p (mca %p)\n", \ + $peer_mca->mca_addr, $peer_mca + end + end + printf "recent transaction for this buffer (thread %p):\n", \ + $mca->mca_thread + set $cnt = 0 + while $cnt < $mca->mca_depth + set $kgm_pc = $mca->mca_stack[$cnt] + printf "%4d: ", $cnt + 1 + pcprint $kgm_pc + printf "\n" + set $cnt = $cnt + 1 + end + if $mca->mca_pdepth > 0 + printf "previous transaction for this buffer (thread %p):\n", \ + $mca->mca_pthread + end + set $cnt = 0 + while $cnt < $mca->mca_pdepth + set $kgm_pc = $mca->mca_pstack[$cnt] + printf "%4d: ", $cnt + 1 + pcprint $kgm_pc + printf "\n" + set $cnt = $cnt + 1 + end + set language auto +end + +document mbuf_showmca +Syntax: (gdb) mbuf_showmca +| Given an mbuf/cluster buffer audit structure address, print the audit +| records including the stack trace of the last buffer transaction. +end + +set $MCF_NOCPUCACHE = 0x10 + +define mcache_stat + set $head = (mcache_t *)mcache_head + set $mc = $head + + if $kgm_lp64 + printf "cache cache cache buf buf backing (# of retries) bufs\n" + printf "name state addr size align zone wait nowait failed incache\n" + printf "------------------------- -------- ------------------ ------ ----- ------------------ -------------------------- --------\n" + else + printf "cache cache cache buf buf backing (# of retries) bufs\n" + printf "name state addr size align zone wait nowait failed incache\n" + printf "------------------------- -------- ---------- ------ ----- ---------- -------------------------- --------\n" + end + while $mc != 0 + set $bktsize = $mc->mc_cpu.cc_bktsize + printf "%-25s ", $mc->mc_name + if ($mc->mc_flags & $MCF_NOCPUCACHE) + printf "disabled" + else + if $mc->mc_purge_cnt > 0 + printf " purging" + else + if $bktsize == 0 + printf " offline" + else + printf " online" + end + end + end + printf " %p %6d %5d ",$mc, \ + $mc->mc_bufsize, $mc->mc_align + if $mc->mc_slab_zone != 0 + printf "%p", $mc->mc_slab_zone + else + if $kgm_lp64 + printf " custom" + else + printf " custom" + end + 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: %p\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 + + if $kgm_lp64 + printf "slot addr next base C R N size flags\n" + printf "---- ------------------ ------------------ ------------------ -- -- -- ------ -----\n" + else + printf "slot addr next base C R N size flags\n" + printf "---- ---------- ---------- ---------- -- -- -- ------ -----\n" + end + while $x < $NSLABSPMB + set $sl = &$slg->slg_slab[$x] + printf "%3d: %p %p %p %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 + if $argc == 0 + mbuf_walkallslabs 1 0 + else + mbuf_walkallslabs 1 0 $arg0 + end +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 + if $argc == 3 + set $show_tr = $arg2 + else + set $show_tr = 0 + end + 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" + + if $kgm_lp64 + printf " slab mca obj allocation\n" + printf "slot idx address address address type state\n" + printf "---- ---- ------------------ ------------------ ------------------ ----- -----------\n" + else + printf " slab mca obj allocation\n" + printf "slot idx address address address type state\n" + printf "---- ---- ---------- ---------- ---------- ----- -----------\n" + end + + 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 %p ", $x, $y, $sl + else + if $kgm_lp64 + printf " " + else + printf " " + end + end + + printf "%p %p ", $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 + + if $show_tr != 0 + printf "recent transaction for this buffer (thread %p):\n", \ + $mca->mca_thread + set $cnt = 0 + while $cnt < $mca->mca_depth + set $kgm_pc = $mca->mca_stack[$cnt] + printf "%4d: ", $cnt + 1 + pcprint $kgm_pc + printf "\n" + set $cnt = $cnt + 1 + end + end + 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 + +set $RTF_UP = 0x1 +set $RTF_GATEWAY = 0x2 +set $RTF_HOST = 0x4 +set $RTF_REJECT = 0x8 +set $RTF_DYNAMIC = 0x10 +set $RTF_MODIFIED = 0x20 +set $RTF_DONE = 0x40 +set $RTF_DELCLONE = 0x80 +set $RTF_CLONING = 0x100 +set $RTF_XRESOLVE = 0x200 +set $RTF_LLINFO = 0x400 +set $RTF_STATIC = 0x800 +set $RTF_BLACKHOLE = 0x1000 +set $RTF_PROTO2 = 0x4000 +set $RTF_PROTO1 = 0x8000 +set $RTF_PRCLONING = 0x10000 +set $RTF_WASCLONED = 0x20000 +set $RTF_PROTO3 = 0x40000 +set $RTF_PINNED = 0x100000 +set $RTF_LOCAL = 0x200000 +set $RTF_BROADCAST = 0x400000 +set $RTF_MULTICAST = 0x800000 +set $RTF_IFSCOPE = 0x1000000 +set $RTF_CONDEMNED = 0x2000000 + +set $AF_INET = 2 +set $AF_INET6 = 30 +set $AF_LINK = 18 + +define rtentry_prdetails + set $rt = (struct rtentry *)$arg0 + set $is_v6 = 0 + + set $dst = (struct sockaddr *)$rt->rt_nodes->rn_u.rn_leaf.rn_Key + if $dst->sa_family == $AF_INET + showsockaddr_in $dst + printf " " + else + if $dst->sa_family == $AF_INET6 + showsockaddr_in6 $dst + printf " " + set $is_v6 = 1 + else + if $dst->sa_family == $AF_LINK + showsockaddr_dl $dst + printf " " + else + showsockaddr_unspec $dst + end + end + end + + set $dst = (struct sockaddr *)$rt->rt_gateway + if $dst->sa_family == $AF_INET + showsockaddr_in $dst + printf " " + else + if $dst->sa_family == $AF_INET6 + set $is_v6 = 1 + showsockaddr_in6 $dst + printf " " + else + if $dst->sa_family == $AF_LINK + showsockaddr_dl $dst + if $is_v6 + printf " " + else + printf " " + end + else + showsockaddr_unspec $dst + end + end + end + + if $rt->rt_flags & $RTF_WASCLONED + if $kgm_lp64 + printf "%18p ", $rt->rt_parent + else + printf "%10p ", $rt->rt_parent + end + else + if $kgm_lp64 + printf " " + else + printf " " + end + end + + printf "%6u %8u ", $rt->rt_refcnt, $rt->rt_rmx.rmx_pksent + + if $rt->rt_flags & $RTF_UP + printf "U" + end + if $rt->rt_flags & $RTF_GATEWAY + printf "G" + end + if $rt->rt_flags & $RTF_HOST + printf "H" + end + if $rt->rt_flags & $RTF_REJECT + printf "R" + end + if $rt->rt_flags & $RTF_DYNAMIC + printf "D" + end + if $rt->rt_flags & $RTF_MODIFIED + printf "M" + end + if $rt->rt_flags & $RTF_CLONING + printf "C" + end + if $rt->rt_flags & $RTF_PRCLONING + printf "c" + end + if $rt->rt_flags & $RTF_LLINFO + printf "L" + end + if $rt->rt_flags & $RTF_STATIC + printf "S" + end + if $rt->rt_flags & $RTF_PROTO1 + printf "1" + end + if $rt->rt_flags & $RTF_PROTO2 + printf "2" + end + if $rt->rt_flags & $RTF_PROTO3 + printf "3" + end + if $rt->rt_flags & $RTF_WASCLONED + printf "W" + end + if $rt->rt_flags & $RTF_BROADCAST + printf "b" + end + if $rt->rt_flags & $RTF_MULTICAST + printf "m" + end + if $rt->rt_flags & $RTF_XRESOLVE + printf "X" + end + if $rt->rt_flags & $RTF_BLACKHOLE + printf "B" + end + if $rt->rt_flags & $RTF_IFSCOPE + printf "I" + end + + printf "/%s%d", $rt->rt_ifp->if_name, $rt->rt_ifp->if_unit +end + +set $RNF_ROOT = 2 + +define _rttable_dump + set $rnh = $arg0 + set $rn = (struct radix_node *)$rnh->rnh_treetop + set $rnh_cnt = $rnh->rnh_cnt + + while $rn->rn_bit >= 0 + set $rn = $rn->rn_u.rn_node.rn_L + end + + while 1 + set $base = (struct radix_node *)$rn + while ($rn->rn_parent->rn_u.rn_node.rn_R == $rn) && ($rn->rn_flags & $RNF_ROOT) == 0 + set $rn = $rn->rn_parent + end + set $rn = $rn->rn_parent->rn_u.rn_node.rn_R + while $rn->rn_bit >= 0 + set $rn = $rn->rn_u.rn_node.rn_L + end + set $next = $rn + while $base != 0 + set $rn = $base + set $base = $rn->rn_u.rn_leaf.rn_Dupedkey + if ($rn->rn_flags & $RNF_ROOT) == 0 + + set $rt = (struct rtentry *)$rn + + if $kgm_lp64 + printf "%18p ", $rt + else + printf "%10p ", $rt + end + rtentry_prdetails $rt + printf "\n" + + end + end + set $rn = $next + if ($rn->rn_flags & $RNF_ROOT) != 0 + loop_break + end + end +end + + +define show_rt_inet + if $kgm_lp64 + printf " rtentry dst gw parent Refs Use flags/if\n" + printf " ----------------- --------------- ----------------- ------------------ ------ -------- -----------\n" + else + printf " rtentry dst gw parent Refs Use flags/if\n" + printf " --------- --------------- ----------------- ---------- ------ -------- -----------\n" + end + _rttable_dump rt_tables[2] +end + +document show_rt_inet +Syntax: (gdb) show_rt_inet +| Show the entries of the IPv4 routing table. +end + +define show_rt_inet6 + if $kgm_lp64 + printf " rtentry dst gw parent Refs Use flags/if\n" + printf " ----------------- --------------------------------------- --------------------------------------- ------------------ ------ -------- -----------\n" + else + printf " rtentry dst gw parent Refs Use flags/if\n" + printf " --------- --------------------------------------- --------------------------------------- ---------- ------ -------- -----------\n" + end + _rttable_dump rt_tables[30] +end + +document show_rt_inet6 +Syntax: (gdb) show_rt_inet6 +| Show the entries of the IPv6 routing table. +end + +define rtentry_trash + set $rtd = (struct rtentry_dbg *)rttrash_head.tqh_first + set $cnt = 0 + while $rtd != 0 + if $cnt == 0 + if $kgm_lp64 + printf " rtentry ref hold rele dst gw parent flags/if\n" + printf " ----------------- --- ------ ------ --------------- ----- ------------------ -----------\n" + else + printf " rtentry ref hold rele dst gw parent flags/if\n" + printf " --------- --- ------ ------ --------------- ----- ---------- -----------\n" + end + end + printf "%4d: %p %3d %6d %6d ", $cnt + 1, $rtd, \ + $rtd->rtd_refhold_cnt - $rtd->rtd_refrele_cnt, \ + $rtd->rtd_refhold_cnt, $rtd->rtd_refrele_cnt + rtentry_prdetails $rtd + printf "\n" + 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 $CTRACE_STACK_SIZE = ctrace_stack_size +set $CTRACE_HIST_SIZE = ctrace_hist_size + +define rtentry_showdbg + set $rtd = (struct rtentry_dbg *)$arg0 + set $cnt = 0 + + printf "Total holds:\t%d\n", $rtd->rtd_refhold_cnt + printf "Total releases:\t%d\n", $rtd->rtd_refrele_cnt + + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $rtd->rtd_alloc.pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nAlloc (thread %p):\n", \ + $rtd->rtd_alloc.th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $rtd->rtd_free.pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nFree: (thread %p)\n", \ + $rtd->rtd_free.th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + while $cnt < $CTRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $rtd->rtd_refhold[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nHold [%d] (thread %p):\n", \ + $cnt, $rtd->rtd_refhold[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $CTRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $rtd->rtd_refrele[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nRelease [%d] (thread %p):\n",\ + $cnt, $rtd->rtd_refrele[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + + printf "\nTotal locks:\t%d\n", $rtd->rtd_lock_cnt + printf "Total unlocks:\t%d\n", $rtd->rtd_unlock_cnt + + set $cnt = 0 + while $cnt < $CTRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $rtd->rtd_lock[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nLock [%d] (thread %p):\n",\ + $cnt, $rtd->rtd_lock[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $CTRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $rtd->rtd_unlock[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nUnlock [%d] (thread %p):\n",\ + $cnt, $rtd->rtd_unlock[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_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 + +define inifa_showdbg + set $inifa = (struct in_ifaddr_dbg *)$arg0 + set $cnt = 0 + + printf "Total holds:\t%d\n", $inifa->inifa_refhold_cnt + printf "Total releases:\t%d\n", $inifa->inifa_refrele_cnt + + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $inifa->inifa_alloc.pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nAlloc (thread %p):\n", \ + $inifa->inifa_alloc.th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $inifa->inifa_free.pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nFree: (thread %p)\n", \ + $inifa->inifa_free.th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + while $cnt < $CTRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $inifa->inifa_refhold[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nHold [%d] (thread %p):\n", \ + $cnt, $inifa->inifa_refhold[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $CTRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $inifa->inifa_refrele[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nRelease [%d] (thread %p):\n",\ + $cnt, $inifa->inifa_refrele[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end +end + +document inifa_showdbg +Syntax: (gdb) inifa_showdbg +| Given an IPv4 interface structure address, print the debug information +| related to it. This requires interface address debugging to be turned +| on, by setting the appropriate flags to the "ifa_debug" boot-args +| parameter. +end + +define in6ifa_showdbg + set $in6ifa = (struct in6_ifaddr_dbg *)$arg0 + set $cnt = 0 + + printf "Total holds:\t%d\n", $in6ifa->in6ifa_refhold_cnt + printf "Total releases:\t%d\n", $in6ifa->in6ifa_refrele_cnt + + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $in6ifa->in6ifa_alloc.pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nAlloc (thread %p):\n", \ + $in6ifa->in6ifa_alloc.th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $in6ifa->in6ifa_free.pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nFree: (thread %p)\n", \ + $in6ifa->in6ifa_free.th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + while $cnt < $CTRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $in6ifa->in6ifa_refhold[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nHold [%d] (thread %p):\n", \ + $cnt, $in6ifa->in6ifa_refhold[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end + set $cnt = 0 + while $cnt < $CTRACE_HIST_SIZE + set $ix = 0 + while $ix < $CTRACE_STACK_SIZE + set $kgm_pc = $in6ifa->in6ifa_refrele[$cnt].pc[$ix] + if $kgm_pc != 0 + if $ix == 0 + printf "\nRelease [%d] (thread %p):\n",\ + $cnt, $in6ifa->in6ifa_refrele[$cnt].th + end + printf "%4d: ", $ix + 1 + pcprint $kgm_pc + printf "\n" + end + set $ix = $ix + 1 + end + set $cnt = $cnt + 1 + end +end + +document in6ifa_showdbg +Syntax: (gdb) in6ifa_showdbg +| Given an IPv6 interface structure address, print the debug information +| related to it. This requires interface address debugging to be turned +| on, by setting the appropriate flags to the "ifa_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 hexdump + set $kgm_addr = (unsigned char *)$arg0 + set $kgm_len = $arg1 + while $kgm_len > 0 + showptr $kgm_addr + printf ": " + set $kgm_i = 0 + while $kgm_i < 16 + printf "%02x ", *($kgm_addr+$kgm_i) + set $kgm_i += 1 + end + printf " |" + set $kgm_i = 0 + while $kgm_i < 16 + set $kgm_temp = *($kgm_addr+$kgm_i) + if $kgm_temp < 32 || $kgm_temp >= 127 + printf "." + else + printf "%c", $kgm_temp + end + set $kgm_i += 1 + end + printf "|\n" + set $kgm_addr += 16 + set $kgm_len -= 16 + end +end +document hexdump +| Show the contents of memory as a hex/ASCII dump +| The following is the syntax: +| (gdb) hexdump
+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 + if ($sdl == 0) + printf "(null) " + else + if $sdl->sdl_nlen == 0 && $sdl->sdl_alen == 0 && $sdl->sdl_slen == 0 + printf "link#%3d ", $sdl->sdl_index + else + set $addr = $sdl->sdl_data + $sdl->sdl_nlen + set $count = $sdl->sdl_alen + printcolonhex $addr $count + end + end +end + +define showsockaddr_unspec + set $sockaddr = (struct sockaddr *)$arg0 + set $addr = $sockaddr->sa_data + set $count = $sockaddr->sa_len - 2 + printcolonhex $addr $count +end + +define showsockaddr_at + set $sockaddr = (struct sockaddr *)$arg0 + set $addr = $sockaddr->sa_data + set $count = $sockaddr->sa_len - 2 + printcolonhex $addr $count +end + +define showsockaddr_in + set $sin = (struct sockaddr_in *)$arg0 + set $sa_bytes = (unsigned char *)&($sin->sin_addr) + printf "%3u.%03u.%03u.%03u", $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 "%2x%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 showsockaddr_un + set $sun = (struct sockaddr_un *)$arg0 + if $sun == 0 + printf "(null)" + else + if $sun->sun_path[0] == 0 + printf "\"\"" + else + printf "%s", $sun->sun_path + end + end +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) + printf "UNSPC" + showsockaddr_unspec $mysock + set $showsockaddr_handled = 1 + end + if ($mysock->sa_family == 1) + printf "UNIX " + showsockaddr_un $mysock + set $showsockaddr_handled = 1 + end + if ($mysock->sa_family == 2) + printf "INET " + showsockaddr_in $mysock + set $showsockaddr_handled = 1 + end + if ($mysock->sa_family == 30) + printf "INET6 " + showsockaddr_in6 $mysock + set $showsockaddr_handled = 1 + end + if ($mysock->sa_family == 18) + printf "LINK " + showsockaddr_dl $mysock + set $showsockaddr_handled = 1 + end + if ($mysock->sa_family == 16) + printf "ATLK " + showsockaddr_at $mysock + set $showsockaddr_handled = 1 + end + if ($showsockaddr_handled == 0) + printf "FAM %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=%hx", $ifp->if_name, $ifp->if_unit, (u_short)$ifp->if_flags + showifflags $ifp->if_flags + printf " index %d", $ifp->if_index + printf " mtu %d\n", $ifp->if_data.ifi_mtu + printf "\t(struct ifnet *)" + showptr $ifp + printf "\n" + 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 _show_unix_domain_socket + set $so = (struct socket *)$arg0 + set $pcb = (struct unpcb *)$so->so_pcb + if $pcb == 0 + printf "unpcb: (null) " + else + printf "unpcb: %p ", $pcb + printf "unp_vnode: %p ", $pcb->unp_vnode + printf "unp_conn: %p ", $pcb->unp_conn + printf "unp_addr: " + showsockaddr_un $pcb->unp_addr + end +end + +define _show_in_port + set $str = (unsigned char *)$arg0 + set $port = *(unsigned short *)$arg0 + + if (((($port & 0xff00) >> 8) == $str[0])) && ((($port & 0x00ff) == $str[1])) + #printf "big endian " + printf ":%d ", $port + else + #printf "little endian " + printf ":%d ", (($port & 0xff00) >> 8) | (($port & 0x00ff) << 8) + end +end + +define _show_in_addr_4in6 + set $ia = (unsigned char *)$arg0 + if $ia + printf "%3u.%03u.%03u.%03u", $ia[0], $ia[1], $ia[2], $ia[3] + end +end + +define _show_in6_addr + set $ia = (unsigned char *)$arg0 + if $ia + printf "%2x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \ + $ia[0], $ia[1], $ia[2], $ia[3], $ia[4], $ia[5], $ia[6], $ia[7], \ + $ia[8], $ia[9], $ia[10], $ia[11], $ia[12], $ia[13], $ia[14], $ia[15] + end +end + +define _showtcpstate + set $tp = (struct tcpcb *)$arg0 + if $tp + if $tp->t_state == 0 + printf "CLOSED " + end + if $tp->t_state == 1 + printf "LISTEN " + end + if $tp->t_state == 2 + printf "SYN_SENT " + end + if $tp->t_state == 3 + printf "SYN_RCVD " + end + if $tp->t_state == 4 + printf "ESTABLISHED " + end + if $tp->t_state == 5 + printf "CLOSE_WAIT " + end + if $tp->t_state == 6 + printf "FIN_WAIT_1 " + end + if $tp->t_state == 7 + printf "CLOSING " + end + if $tp->t_state == 8 + printf "LAST_ACK " + end + if $tp->t_state == 9 + printf "FIN_WAIT_2 " + end + if $tp->t_state == 10 + printf "TIME_WAIT " + end + end +end + +define _showsockprotocol + set $so = (struct socket *)$arg0 + set $inpcb = (struct inpcb *)$so->so_pcb + + if $so->so_proto->pr_protocol == 6 + printf "TCP " + _showtcpstate $inpcb->inp_ppcb + end + if $so->so_proto->pr_protocol == 17 + printf "UDP " + end + if $so->so_proto->pr_protocol == 1 + printf "ICMP " + end + if $so->so_proto->pr_protocol == 254 + printf "DIVERT " + end + if $so->so_proto->pr_protocol == 255 + printf "RAW " + end +end + +define _show_ipv4_socket + set $so = (struct socket *)$arg0 + set $inpcb = (struct inpcb *)$so->so_pcb + if $inpcb == 0 + printf "inpcb: (null) " + else + printf "inpcb: %p ", $inpcb + + _showsockprotocol $so + + _show_in_addr_4in6 &$inpcb->inp_dependladdr.inp46_local + _show_in_port &$inpcb->inp_lport + printf "-> " + _show_in_addr_4in6 &$inpcb->inp_dependfaddr.inp46_foreign + _show_in_port &$inpcb->inp_fport + end +end + +define _show_ipv6_socket + set $so = (struct socket *)$arg0 + set $pcb = (struct inpcb *)$so->so_pcb + if $pcb == 0 + printf "inpcb: (null) " + else + printf "inpcb: %p ", $pcb + + _showsockprotocol $so + + _show_in6_addr &$pcb->inp_dependladdr.inp6_local + _show_in_port &$pcb->inp_lport + printf "-> " + _show_in6_addr &$pcb->inp_dependfaddr.inp6_foreign + _show_in_port &$pcb->inp_fport + end +end + + +define showsocket + set $so = (struct socket *)$arg0 + if $so == 0 + printf "so: (null) " + else + printf "so: %p ", $so + if $so && $so->so_proto && $so->so_proto->pr_domain + set $domain = (struct domain *) $so->so_proto->pr_domain + + printf "%s ", $domain->dom_name + if $domain->dom_family == 1 + _show_unix_domain_socket $so + end + if $domain->dom_family == 2 + _show_ipv4_socket $so + end + if $domain->dom_family == 30 + _show_ipv6_socket $so + end + end + end + printf "\n" +end +document showsocket +Syntax: (gdb) showsocket +| Routine to print out a socket +end + +define showprocsockets + set $pp = (struct proc *)$arg0 + set $fdp = (struct filedesc *)$pp->p_fd + + set $count = 0 + set $fpp = (struct fileproc **)($fdp->fd_ofiles) + set $fpo = (char)($fdp->fd_ofileflags[0]) + while $count < $fdp->fd_nfiles + if *$fpp + set $fg =(struct fileglob *)((**$fpp)->f_fglob) + if $fg && (($fg)->fg_type == 2) + if $fdp->fd_ofileflags[$count] & 4 + printf "U: " + else + printf " " + end + printf "fd = %d ", $count + if $fg->fg_data + showsocket $fg->fg_data + else + printf "\n" + end + end + end + set $fpp = $fpp + 1 + set $count = $count + 1 + end +end +document showprocsockets +Syntax: (gdb) showprocsockets +| Routine to print out all the open fds +| which are sockets in a process +end + +define showallprocsockets + set $basep = (struct proc *)allproc->lh_first + set $pp = $basep + while $pp + printf "============================================ \n" + showproc $pp + showprocsockets $pp + set $pp = $pp->p_list.le_next + end +end +document showallprocsockets +Syntax: (gdb) showallprocsockets +| Routine to print out all the open fds +| which are sockets +end + +define _print_ntohs + set $port = (unsigned short)$arg0 + set $port = (unsigned short)((($arg0 & 0xff00) >> 8) & 0xff) + set $port |= (unsigned short)(($arg0 & 0xff) << 8) + printf "%5d", $port +end + +set $INPCB_STATE_INUSE=0x1 +set $INPCB_STATE_CACHED=0x2 +set $INPCB_STATE_DEAD=0x3 + +set $INP_RECVOPTS=0x01 +set $INP_RECVRETOPTS=0x02 +set $INP_RECVDSTADDR=0x04 +set $INP_HDRINCL=0x08 +set $INP_HIGHPORT=0x10 +set $INP_LOWPORT=0x20 +set $INP_ANONPORT=0x40 +set $INP_RECVIF=0x80 +set $INP_MTUDISC=0x100 +set $INP_STRIPHDR=0x200 +set $INP_FAITH=0x400 +set $INP_INADDR_ANY=0x800 +set $INP_RECVTTL=0x1000 +set $INP_UDP_NOCKSUM=0x2000 +set $IN6P_IPV6_V6ONLY=0x008000 +set $IN6P_PKTINFO=0x010000 +set $IN6P_HOPLIMIT=0x020000 +set $IN6P_HOPOPTS=0x040000 +set $IN6P_DSTOPTS=0x080000 +set $IN6P_RTHDR=0x100000 +set $IN6P_RTHDRDSTOPTS=0x200000 +set $IN6P_AUTOFLOWLABEL=0x800000 +set $IN6P_BINDV6ONLY=0x10000000 + +set $INP_IPV4=0x1 +set $INP_IPV6=0x2 + +set $IPPROTO_TCP=6 +set $IPPROTO_UDP=17 + +define _dump_inpcb + set $pcb = (struct inpcb *)$arg0 + if $kgm_lp64 + printf "%18p", $pcb + else + printf "%10p ", $pcb + end + if $arg1 == $IPPROTO_TCP + printf "tcp" + else + if $arg1 == $IPPROTO_UDP + printf "udp" + else + printf "%2d.", $arg1 + end + end + if ($pcb->inp_vflag & $INP_IPV4) + printf "4 " + end + if ($pcb->inp_vflag & $INP_IPV6) + printf "6 " + end + + if ($pcb->inp_vflag & $INP_IPV4) + printf " " + _show_in_addr &$pcb->inp_dependladdr.inp46_local.ia46_addr4 + else + _show_in6_addr &$pcb->inp_dependladdr.inp6_local + end + printf " " + _print_ntohs $pcb->inp_lport + printf " " + if ($pcb->inp_vflag & $INP_IPV4) + printf " " + _show_in_addr &($pcb->inp_dependfaddr.inp46_foreign.ia46_addr4) + else + _show_in6_addr &($pcb->inp_dependfaddr.inp6_foreign) + end + printf " " + _print_ntohs $pcb->inp_fport + printf " " + + if $arg1 == $IPPROTO_TCP + _showtcpstate $pcb->inp_ppcb + end + +# printf "phd " +# set $phd = $pcb->inp_phd +# while $phd != 0 +# printf " " +# _print_ntohs $phd->phd_port +# set $phd = $phd->phd_hash.le_next +# end +# printf ", " + if ($pcb->inp_flags & $INP_RECVOPTS) + printf "recvopts " + end + if ($pcb->inp_flags & $INP_RECVRETOPTS) + printf "recvretopts " + end + if ($pcb->inp_flags & $INP_RECVDSTADDR) + printf "recvdstaddr " + end + if ($pcb->inp_flags & $INP_HDRINCL) + printf "hdrincl " + end + if ($pcb->inp_flags & $INP_HIGHPORT) + printf "highport " + end + if ($pcb->inp_flags & $INP_LOWPORT) + printf "lowport " + end + if ($pcb->inp_flags & $INP_ANONPORT) + printf "anonport " + end + if ($pcb->inp_flags & $INP_RECVIF) + printf "recvif " + end + if ($pcb->inp_flags & $INP_MTUDISC) + printf "mtudisc " + end + if ($pcb->inp_flags & $INP_STRIPHDR) + printf "striphdr " + end + if ($pcb->inp_flags & $INP_FAITH) + printf "faith " + end + if ($pcb->inp_flags & $INP_INADDR_ANY) + printf "inaddr_any " + end + if ($pcb->inp_flags & $INP_RECVTTL) + printf "recvttl " + end + if ($pcb->inp_flags & $INP_UDP_NOCKSUM) + printf "nocksum " + end + if ($pcb->inp_flags & $IN6P_IPV6_V6ONLY) + printf "v6only " + end + if ($pcb->inp_flags & $IN6P_PKTINFO) + printf "pktinfo " + end + if ($pcb->inp_flags & $IN6P_HOPLIMIT) + printf "hoplimit " + end + if ($pcb->inp_flags & $IN6P_HOPOPTS) + printf "hopopts " + end + if ($pcb->inp_flags & $IN6P_DSTOPTS) + printf "dstopts " + end + if ($pcb->inp_flags & $IN6P_RTHDR) + printf "rthdr " + end + if ($pcb->inp_flags & $IN6P_RTHDRDSTOPTS) + printf "rthdrdstopts " + end + if ($pcb->inp_flags & $IN6P_AUTOFLOWLABEL) + printf "autoflowlabel " + end + if ($pcb->inp_flags & $IN6P_BINDV6ONLY) + printf "bindv6only " + end + set $so = (struct socket *)$pcb->inp_socket + if $so != 0 + printf "[so=%p s=%ld r=%ld usecnt=%ld] ", $so, $so->so_snd.sb_cc, \ + $so->so_rcv.sb_cc, $so->so_usecount + end + if ($pcb->inp_state == 0 || $pcb->inp_state == $INPCB_STATE_INUSE) + printf "inuse, " + else + if ($pcb->inp_state == $INPCB_STATE_CACHED) + printf "cached, " + else + if ($pcb->inp_state == $INPCB_STATE_DEAD) + printf "dead, " + else + printf "unknown (%d), ", $pcb->inp_state + end + end + end +end + +define _dump_inpcbport + set $ppcb = (struct inpcbport *)$arg0 + printf "%p: lport ", $ppcb + _print_ntohs $ppcb->phd_port +end + +set $UDBHASHSIZE=16 + +define _dump_pcbinfo + set $snd_cc = 0 + set $rcv_cc = 0 + set $pcbseen = 0 + set $pcbi = (struct inpcbinfo *)$arg0 + printf "lastport %d lastlow %d lasthi %d\n", \ + $pcbi->lastport, $pcbi->lastlow, $pcbi->lasthi + printf "active pcb count is %d\n", $pcbi->ipi_count + set $hashsize = $pcbi->hashmask + 1 + printf "hash size is %d\n", $hashsize + printf "hash base %p has the following inpcb(s):\n", $pcbi->hashbase + if $kgm_lp64 + printf "pcb prot source address port destination address port\n" + printf "------------------ ---- --------------------------------------- ----- --------------------------------------- -----\n" + else + printf "pcb prot source address port destination address port\n" + printf "---------- ---- --------------------------------------- ----- --------------------------------------- -----\n" + end + set $i = 0 + set $hashbase = $pcbi->hashbase + set $head = *(uintptr_t *)$hashbase + while $i < $hashsize + if $head != 0 + set $pcb0 = (struct inpcb *)$head + while $pcb0 != 0 + set $pcbseen += 1 + _dump_inpcb $pcb0 $arg1 + set $so = (struct socket *)$pcb->inp_socket + if $so != 0 + set $snd_cc += $so->so_snd.sb_cc + set $rcv_cc += $so-> so_rcv.sb_cc + end + set $pcb0 = $pcb0->inp_hash.le_next + printf "\n" + end + end + set $i += 1 + set $hashbase += 1 + set $head = *(uintptr_t *)$hashbase + end + printf "total seen %ld snd_cc %ld rcv_cc %ld\n", $pcbseen, $snd_cc, $rcv_cc + printf "port hash base is %p\n", $pcbi->porthashbase + set $i = 0 + set $hashbase = $pcbi->porthashbase + set $head = *(uintptr_t *)$hashbase + while $i < $hashsize + if $head != 0 + set $pcb0 = (struct inpcbport *)$head + while $pcb0 != 0 + printf "\t" + _dump_inpcbport $pcb0 + printf "\n" + set $pcb0 = $pcb0->phd_hash.le_next + end + end + set $i += 1 + set $hashbase += 1 + set $head = *(uintptr_t *)$hashbase + end +end + +set $N_TIME_WAIT_SLOTS=128 + +define show_tcp_timewaitslots + set $slot = -1 + set $all = 0 + if $argc == 1 + if (int)$arg0 == -1 + set $all = 1 + else + set $slot = (int)$arg0 + end + end + printf "time wait slot size %d cur_tw_slot %ld\n", $N_TIME_WAIT_SLOTS, cur_tw_slot + set $i = 0 + while $i < $N_TIME_WAIT_SLOTS + set $perslot = 0 + set $head = (uintptr_t *)time_wait_slots[$i] + if $i == $slot || $slot == -1 + if $head != 0 + set $pcb0 = (struct inpcb *)$head + while $pcb0 != 0 + set $perslot += 1 + set $pcb0 = $pcb0->inp_list.le_next + end + end + printf " slot %ld count %ld\n", $i, $perslot + end + if $all || $i == $slot + if $head != 0 + set $pcb0 = (struct inpcb *)$head + while $pcb0 != 0 + printf "\t" + _dump_inpcb $pcb0 $IPPROTO_TCP + printf "\n" + set $pcb0 = $pcb0->inp_list.le_next + end + end + end + set $i += 1 + end +end +document show_tcp_timewaitslots +Syntax: (gdb) show_tcp_timewaitslots +| Print the list of TCP protocol control block in the TIMEWAIT state +| Pass -1 to see the list of PCB for each slot +| Pass a slot number to see information for that slot with the list of PCB +end + +define show_tcp_pcbinfo + _dump_pcbinfo &tcbinfo $IPPROTO_TCP +end +document show_tcp_pcbinfo +Syntax: (gdb) show_tcp_pcbinfo +| Print the list of TCP protocol control block information +end + + +define show_udp_pcbinfo + _dump_pcbinfo &udbinfo $IPPROTO_UDP +end +document show_udp_pcbinfo +Syntax: (gdb) show_udp_pcbinfo +| Print the list of UDP protocol control block information +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 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 + +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 showallvols + printf "volume " + showptrhdrpad + printf " mnt_data " + showptrhdrpad + printf " mnt_devvp " + showptrhdrpad + printf " typename mountpoint\n" + set $kgm_vol = (mount_t) mountlist.tqh_first + while $kgm_vol + showptr $kgm_vol + printf " " + showptr $kgm_vol->mnt_data + printf " " + showptr $kgm_vol->mnt_devvp + printf " " + 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 " + showptrhdrpad + printf " usecount iocount v_data " + showptrhdrpad + printf " vtype parent " + showptrhdrpad + printf " name\n" +end + +define showvnodeint + set $kgm_vnode = (vnode_t) $arg0 + showptr $kgm_vnode + printf " %8d ", $kgm_vnode->v_usecount + printf "%7d ", $kgm_vnode->v_iocount +# print information about clean/dirty blocks? + showptr $kgm_vnode->v_data + printf " " + # 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 + + showptr $kgm_vnode->v_parent + printf " " + 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 + if ($kgm_mtype == $kgm_mtype_i386) + set $kgm_voffset = 0 + else + if ($kgm_mtype == $kgm_mtype_x86_64) + set $kgm_voffset = 0xFFFFFF8000000000ULL + else + echo showbootermemorymap not supported on this architecture + end + end + + 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 Virtual Start Attributes\n" + while $kgm_i < $kgm_mcount + set $kgm_mptr = (EfiMemoryRange *)((unsigned long)kernelBootArgs->MemoryMap + $kgm_voffset + $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", $kgm_mptr->PhysicalStart, $kgm_mptr->NumberOfPages + if $kgm_mptr->VirtualStart != 0 + printf " %016llx", $kgm_mptr->VirtualStart + else + printf " " + end + printf " %016llx\n", $kgm_mptr->Attribute + 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 + showptr $kgm_pm_wq + printf " " + showptr $kgm_pm_node + printf " " + 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 + if ((queue_entry_t) $kgm_pm_req != (queue_entry_t) $kgm_pm_queue) + printf "\n" + printf "request " + showptrhdrpad + printf " type next " + showptrhdrpad + printf " root " + showptrhdrpad + printf " work_wait free_wait\n" + while ((queue_entry_t) $kgm_pm_req != (queue_entry_t) $kgm_pm_queue) + showptr $kgm_pm_req + printf " 0x%02x ", $kgm_pm_req->fType + showptr $kgm_pm_req->fRequestNext + printf " " + showptr $kgm_pm_req->fRequestRoot + printf " 0x%08x 0x%08x\n", $kgm_pm_req->fWorkWaitCount, $kgm_pm_req->fFreeWaitCount + showptrhdrpad + printf " args " + showptr $kgm_pm_req->fArg0 + printf " " + showptr $kgm_pm_req->fArg1 + printf " " + showptr $kgm_pm_req->fArg2 + printf "\n" + set $kgm_pm_req = (IOPMRequest *)$kgm_pm_req->fCommandChain.next + end + printf "\n" + end +end + +define showallpmworkqueues + set $kgm_pm_next = gIOPMWorkLoop->eventChain + printf "queue " + showptrhdrpad + printf " owner " + showptrhdrpad + printf " ps ms wr name\n" + while ( $kgm_pm_next ) + set $kgm_vt = *((void **) $kgm_pm_next) + if ($kgm_lp64 || $kgm_mtype == $kgm_mtype_arm) + set $kgm_vt = $kgm_vt - 2 * sizeof(void *) + end + 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 "{ " + 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 "HeadNotePendingAcks = %x, ",(unsigned int)$kgm_iopmpriv->HeadNotePendingAcks + end + + if ( $kgm_iopmpriv->DeviceOverrides != 0 ) + printf"DeviceOverrides, " + end + + printf "DeviceDesire = %d, ",(unsigned int)$kgm_iopmpriv->DeviceDesire + printf "DesiredPowerState = %d, ",(unsigned int)$kgm_iopmpriv->DesiredPowerState + printf "PreviousRequest = %d }\n",(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 <", ((IOService*)$kgm_re)->pwrMgt->Name + showptr $kgm_re + printf ">" + else + printf "?? <" + showptr $kgm_re + printf ">" + 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) + if $kgm_reg_depth >= $kgm_reg_depth_max + 1 + loop_break + end + 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->nameKey + set $kgm_childkey = (OSSymbol *) $kgm_reg_plane->keys[1] + 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 & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + 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 + # $kgm_pt_valid: 1 if $kgm_pt_paddr is valid, 0 if the walk + # should be aborted + # $kgm_pt_large: 1 if kgm_pt_paddr is a page frame address + # of a large page and not another page table entry + # For $kgm_pt_verbose = 0: print nothing + # 1: print basic information + # 2: print basic information and hex table dump + # + set $kgm_entryp = $kgm_pt_paddr + 8*$kgm_pt_index + readphysint $kgm_entryp 64 $kgm_lcpu_self + set $entry = $kgm_readphysint_result + if $kgm_pt_verbose == 2 + set $kgm_pte_loop = 0 + while $kgm_pte_loop < 512 + set $kgm_pt_paddr_tmp = $kgm_pt_paddr + $kgm_pte_loop*8 + readphys64 $kgm_pt_paddr_tmp + set $kgm_pte_loop = $kgm_pte_loop + 1 + end + end + set $kgm_paddr_mask = ~((0xfffULL<<52) | 0xfffULL) + set $kgm_paddr_largemask = ~((0xfffULL<<52) | 0x1fffffULL) + if $kgm_pt_verbose == 0 + if $entry & (0x1 << 0) + set $kgm_pt_valid = 1 + if $entry & (0x1 << 7) + set $kgm_pt_large = 1 + set $kgm_pt_paddr = $entry & $kgm_paddr_largemask + else + set $kgm_pt_large = 0 + set $kgm_pt_paddr = $entry & $kgm_paddr_mask + end + else + set $kgm_pt_valid = 0 + set $kgm_pt_large = 0 + 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 + set $kgm_pt_valid = 1 + else + printf "invalid" + set $kgm_pt_paddr = 0 + set $kgm_pt_valid = 0 + # stop decoding other bits + set $entry = 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 " large" + set $kgm_pt_large = 1 + else + set $kgm_pt_large = 0 + 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 + set $kgm_pt_valid = $kgm_pt_paddr != 0 + set $kgm_pt_large = 0 + set $kgm_pframe_offset = 0 + if $kgm_pt_valid && cpu_64bit + # Look up bits 47:39 of the linear address in PML4T + set $kgm_pt_index = ($kgm_vaddr >> 39) & 0x1ffULL + set $kgm_pframe_offset = $kgm_vaddr & 0x7fffffffffULL + if $kgm_pt_verbose + printf "pml4 (index %d):\n", $kgm_pt_index + end + _pt_step + end + if $kgm_pt_valid + # Look up bits 38:30 of the linear address in PDPT + set $kgm_pt_index = ($kgm_vaddr >> 30) & 0x1ffULL + set $kgm_pframe_offset = $kgm_vaddr & 0x3fffffffULL + if $kgm_pt_verbose + printf "pdpt (index %d):\n", $kgm_pt_index + end + _pt_step + end + if $kgm_pt_valid && !$kgm_pt_large + # Look up bits 29:21 of the linear address in PDT + set $kgm_pt_index = ($kgm_vaddr >> 21) & 0x1ffULL + set $kgm_pframe_offset = $kgm_vaddr & 0x1fffffULL + if $kgm_pt_verbose + printf "pdt (index %d):\n", $kgm_pt_index + end + _pt_step + end + if $kgm_pt_valid && !$kgm_pt_large + # Look up bits 20:21 of the linear address in PT + set $kgm_pt_index = ($kgm_vaddr >> 12) & 0x1ffULL + set $kgm_pframe_offset = $kgm_vaddr & 0xfffULL + if $kgm_pt_verbose + printf "pt (index %d):\n", $kgm_pt_index + end + _pt_step + end + if $kgm_pt_valid + set $kgm_paddr = $kgm_pt_paddr + $kgm_pframe_offset + readphysint $kgm_paddr 32 $kgm_lcpu_self + set $kgm_value = $kgm_readphysint_result + 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 & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + 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 & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + 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 + +define zstack + set $index = $arg0 + + if (log_records == 0) + set $count = 0 + printf "Zone logging not enabled. Add 'zlog=' to boot-args.\n" + else + if ($argc == 2) + set $count = $arg1 + else + set $count = 1 + end + end + + while ($count) + printf "\n--------------- " + + if (zrecords[$index].z_opcode == 1) + printf "ALLOC " + else + printf "FREE " + end + + printf " 0x%x : index %d : ztime %d -------------\n", zrecords[$index].z_element, $index, zrecords[$index].z_time + + set $frame = 0 + + while ($frame < 15) + set $frame_pc = zrecords[$index].z_pc[$frame] + + if ($frame_pc == 0) + loop_break + end + + x/i $frame_pc + set $frame = $frame + 1 + end + + set $index = $index + 1 + set $count = $count - 1 + end +end + +document zstack +Syntax: (gdb) zstack [] +| Zone leak debugging: print the stack trace of log element at . +| If a is supplied, it prints log elements starting at . +| +| The suggested usage is to look at indexes below zcurrent and look for common stack traces. +| The stack trace that occurs the most is probably the cause of the leak. Find the pc of the +| function calling into zalloc and use the countpcs kgmacro to find out how often that pc occurs in the log. +| The pc occuring in a high percentage of records is most likely the source of the leak. +| +| The findoldest kgmacro is also useful for leak debugging since it identifies the oldest record +| in the log, which may indicate the leaker. +end + +define findoldest + set $index = 0 + set $count = log_records + set $cur_min = 2000000000 + set $cur_index = 0 + + if (log_records == 0) + printf "Zone logging not enabled. Add 'zlog=' to boot-args.\n" + else + + while ($count) + if (zrecords[$index].z_element && zrecords[$index].z_time < $cur_min) + set $cur_index = $index + set $cur_min = zrecords[$index].z_time + end + + set $count = $count - 1 + set $index = $index + 1 + end + + printf "oldest record is at log index %d:\n", $cur_index + zstack $cur_index + end +end + +document findoldest +Syntax: (gdb) findoldest +| Zone leak debugging: find and print the oldest record in the log. Note that this command +| can take several minutes to run since it uses linear search. +| +| Once it prints a stack trace, find the pc of the caller above all the zalloc, kalloc and +| IOKit layers. Then use the countpcs kgmacro to see how often this caller has allocated +| memory. A caller with a high percentage of records in the log is probably the leaker. +end + +define countpcs + set $target_pc = $arg0 + set $index = 0 + set $count = log_records + set $found = 0 + + if (log_records == 0) + printf "Zone logging not enabled. Add 'zlog=' to boot-args.\n" + else + + while ($count) + set $frame = 0 + + if (zrecords[$index].z_element != 0) + while ($frame < 15) + if (zrecords[$index].z_pc[$frame] == $target_pc) + set $found = $found + 1 + set $frame = 15 + end + + set $frame = $frame + 1 + end + end + + set $index = $index + 1 + set $count = $count - 1 + end + + printf "occurred %d times in log (%d%c of records)\n", $found, ($found * 100) / zrecorded, '%' + end +end + +document countpcs +Syntax: (gdb) countpcs +| Zone leak debugging: search the log and print a count of all log entries that contain the given +| in the stack trace. This is useful for verifying a suspected as being the source of +| the leak. If a high percentage of the log entries contain the given , then it's most +| likely the source of the leak. Note that this command can take several minutes to run. +end + +define findelem + set $fe_index = zcurrent + set $fe_count = log_records + set $fe_elem = $arg0 + set $fe_prev_op = -1 + + if (log_records == 0) + printf "Zone logging not enabled. Add 'zlog=' to boot-args.\n" + end + + while ($fe_count) + if (zrecords[$fe_index].z_element == $fe_elem) + zstack $fe_index + + if (zrecords[$fe_index].z_opcode == $fe_prev_op) + printf "*************** DOUBLE OP! *********************\n + end + + set $fe_prev_op = zrecords[$fe_index].z_opcode + end + + set $fe_count = $fe_count - 1 + set $fe_index = $fe_index + 1 + + if ($fe_index >= log_records) + set $fe_index = 0 + end + end +end + +document findelem +Syntax: (gdb) findelem +| Zone corruption debugging: search the log and print out the stack traces for all log entries that +| refer to the given zone element. When the kernel panics due to a corrupted zone element, get the +| element address and use this macro. This will show you the stack traces of all logged zalloc and +| zfree operations which tells you who touched the element in the recent past. This also makes +| double-frees readily apparent. +end + + +# This implements a shadowing scheme in kgmacros. If the +# current user data can be accessed by simply changing kdp_pmap, +# that is used. Otherwise, we copy data into a temporary buffer +# in the kernel's address space and use that instead. Don't rely on +# kdp_pmap between invocations of map/unmap. Since the shadow +# codepath uses a manual KDP packet, request no more than 128 bytes. +# Uses $kgm_lp64 for kernel address space size +define _map_user_data_from_task + set $kgm_map_user_taskp = (task_t)$arg0 + set $kgm_map_user_map = $kgm_map_user_taskp->map + set $kgm_map_user_pmap = $kgm_map_user_map->pmap + set $kgm_map_user_task_64 = ( $kgm_map_user_taskp->taskFeatures[0] & 0x80000000) + set $kgm_map_user_window = 0 + set $kgm_map_switch_map = 0 + + if $kgm_lp64 + set $kgm_map_switch_map = 1 + else + if !$kgm_map_user_task_64 + set $kgm_map_switch_map = 1 + end + end + + if ($kgm_map_switch_map) + # switch the map safely + set $kgm_map_user_window = $arg1 + set kdp_pmap = $kgm_map_user_pmap + else + # requires shadowing/copying + + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_readmem64_req_t) + set $kgm_pkt = (kdp_readmem64_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_READMEM64 + set $kgm_pkt->hdr.len = sizeof(kdp_readmem64_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint64_t)$arg1 + set $kgm_pkt->nbytes = (uint32_t)$arg2 + + set kdp_pmap = $kgm_map_user_pmap + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + # Go back to kernel map so that we can access buffer directly + set kdp_pmap = 0 + + set $kgm_pkt = (kdp_readmem64_reply_t *)&manual_pkt.data + if ($kgm_pkt->error == 0) + set $kgm_map_user_window = $kgm_pkt->data + else + set $kgm_map_user_window = 0 + end + + end +end + +define _unmap_user_data_from_task + set kdp_pmap = 0 +end + +# uses $kgm_taskp. Maps 32 bytes at a time and prints it +define _print_path_for_image + set $kgm_print_path_address = (unsigned long long)$arg0 + set $kgm_path_str_notdone = 1 + + while $kgm_path_str_notdone + _map_user_data_from_task $kgm_taskp $kgm_print_path_address 32 + + set $kgm_print_path_ptr = (char *)$kgm_map_user_window + set $kgm_path_i = 0 + while ($kgm_path_i < 32 && $kgm_print_path_ptr[$kgm_path_i] != '\0') + set $kgm_path_i = $kgm_path_i + 1 + end + printf "%.32s", $kgm_print_path_ptr + + _unmap_user_data_from_task $kgm_taskp + + # if we terminated on NUL, break out + if $kgm_path_i < 32 + set $kgm_path_str_notdone = 0 + else + set $kgm_print_path_address = $kgm_print_path_address + 32 + end + end +end + +# uses $kgm_taskp and $kgm_task_64 +define _print_image_info + set $kgm_mh_image_address = (unsigned long long)$arg0 + set $kgm_mh_path_address = (unsigned long long)$arg1 + + # 32 bytes enough for mach_header/mach_header_64 + _map_user_data_from_task $kgm_taskp $kgm_mh_image_address 32 + + set $kgm_mh_ptr = (unsigned int*)$kgm_map_user_window + set $kgm_mh_magic = $kgm_mh_ptr[0] + set $kgm_mh_cputype = $kgm_mh_ptr[1] + set $kgm_mh_cpusubtype = $kgm_mh_ptr[2] + set $kgm_mh_filetype = $kgm_mh_ptr[3] + set $kgm_mh_ncmds = $kgm_mh_ptr[4] + set $kgm_mh_sizeofcmds = $kgm_mh_ptr[5] + set $kgm_mh_flags = $kgm_mh_ptr[6] + + _unmap_user_data_from_task $kgm_taskp + + if $kgm_mh_magic == 0xfeedfacf + set $kgm_mh_64 = 1 + set $kgm_lc_address = $kgm_mh_image_address + 32 + else + set $kgm_mh_64 = 0 + set $kgm_lc_address = $kgm_mh_image_address + 28 + end + + set $kgm_lc_idx = 0 + set $kgm_uuid_data = 0 + while $kgm_lc_idx < $kgm_mh_ncmds + + # 24 bytes is size of uuid_command + _map_user_data_from_task $kgm_taskp $kgm_lc_address 24 + + set $kgm_lc_ptr = (unsigned int *)$kgm_map_user_window + set $kgm_lc_cmd = $kgm_lc_ptr[0] + set $kgm_lc_cmd_size = $kgm_lc_ptr[1] + set $kgm_lc_data = (unsigned char *)$kgm_lc_ptr + 8 + + if $kgm_lc_cmd == 0x1b + set $kgm_uuid_data = $kgm_lc_data + if $kgm_mh_64 + printf "0x%016llx ", $kgm_mh_image_address + else + printf "0x%08x ", $kgm_mh_image_address + end + + set $kgm_printed_type = 0 + if $kgm_mh_filetype == 0x2 + printf "MH_EXECUTE " + set $kgm_printed_type = 1 + end + if $kgm_mh_filetype == 0x6 + printf "MH_DYLIB " + set $kgm_printed_type = 1 + end + if $kgm_mh_filetype == 0x7 + printf "MH_DYLINKER " + set $kgm_printed_type = 1 + end + if $kgm_mh_filetype == 0x8 + printf "MH_BUNDLE " + set $kgm_printed_type = 1 + end + if !$kgm_printed_type + printf "UNKNOWN " + end + printf "%02.2X%02.2X%02.2X%02.2X-", $kgm_uuid_data[0], $kgm_uuid_data[1], $kgm_uuid_data[2], $kgm_uuid_data[3] + printf "%02.2X%02.2X-", $kgm_uuid_data[4], $kgm_uuid_data[5] + printf "%02.2X%02.2X-", $kgm_uuid_data[6], $kgm_uuid_data[7] + printf "%02.2X%02.2X-", $kgm_uuid_data[8], $kgm_uuid_data[9] + printf "%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X", $kgm_uuid_data[10], $kgm_uuid_data[11], $kgm_uuid_data[12], $kgm_uuid_data[13], $kgm_uuid_data[14], $kgm_uuid_data[15] + + _unmap_user_data_from_task $kgm_taskp + + printf " " + _print_path_for_image $kgm_mh_path_address + printf "\n" + + loop_break + else + _unmap_user_data_from_task $kgm_taskp + end + + set $kgm_lc_address = $kgm_lc_address + $kgm_lc_cmd_size + set $kgm_lc_idx = $kgm_lc_idx + 1 + end + + if (!$kgm_uuid_data) + # didn't find LC_UUID, for a dylib, just print out basic info + if $kgm_mh_64 + printf "0x%016llx ", $kgm_mh_image_address + else + printf "0x%08x ", $kgm_mh_image_address + end + set $kgm_printed_type = 0 + if $kgm_mh_filetype == 0x2 + printf "MH_EXECUTE " + set $kgm_printed_type = 1 + end + if $kgm_mh_filetype == 0x6 + printf "MH_DYLIB " + set $kgm_printed_type = 1 + end + if $kgm_mh_filetype == 0x7 + printf "MH_DYLINKER " + set $kgm_printed_type = 1 + end + if $kgm_mh_filetype == 0x8 + printf "MH_BUNDLE " + set $kgm_printed_type = 1 + end + if !$kgm_printed_type + printf "UNKNOWN " + end + printf " ", + + printf " " + _print_path_for_image $kgm_mh_path_address + printf "\n" + + end + +end + +define _print_images_for_dyld_image_info + set $kgm_taskp = $arg0 + set $kgm_task_64 = $arg1 + set $kgm_dyld_all_image_infos_address = (unsigned long long)$arg2 + + _map_user_data_from_task $kgm_taskp $kgm_dyld_all_image_infos_address 16 + + set $kgm_dyld_all_image_infos = (unsigned int *)$kgm_map_user_window + if ($kgm_dyld_all_image_infos[0] != 6) + printf "Invalid version number %d\n", $kgm_dyld_all_image_infos[0] + end + set $kgm_image_info_count = $kgm_dyld_all_image_infos[1] + + if $kgm_task_64 + set $kgm_image_info_size = 24 + set $kgm_image_info_array_address = ((unsigned long long *)$kgm_dyld_all_image_infos)[1] + else + set $kgm_image_info_size = 12 + set $kgm_image_info_array_address = ((unsigned int *)$kgm_dyld_all_image_infos)[2] + end + + _unmap_user_data_from_task $kgm_taskp + + set $kgm_image_info_i = 0 + while $kgm_image_info_i < $kgm_image_info_count + + set $kgm_image_info_address = $kgm_image_info_array_address + $kgm_image_info_size*$kgm_image_info_i + + _map_user_data_from_task $kgm_taskp $kgm_image_info_address $kgm_image_info_size + if $kgm_task_64 + set $kgm_image_info_addr = ((unsigned long long *)$kgm_map_user_window)[0] + set $kgm_image_info_path = ((unsigned long long *)$kgm_map_user_window)[1] + else + set $kgm_image_info_addr = ((unsigned int *)$kgm_map_user_window)[0] + set $kgm_image_info_path = ((unsigned int *)$kgm_map_user_window)[1] + end + _unmap_user_data_from_task $kgm_taskp + + # printf "[%d] = image address %llx path address %llx\n", $kgm_image_info_i, $kgm_image_info_addr, $kgm_image_info_path + _print_image_info $kgm_image_info_addr $kgm_image_info_path + + set $kgm_image_info_i = $kgm_image_info_i + 1 + end +end + +define showuserlibraries + set $kgm_taskp = (task_t)$arg0 + set $kgm_dyld_image_info = $kgm_taskp->all_image_info_addr + + set $kgm_map = $kgm_taskp->map + set $kgm_task_64 = ( $kgm_taskp->taskFeatures[0] & 0x80000000) + + if ($kgm_dyld_image_info != 0) + printf "address " + if $kgm_task_64 + printf " " + end + printf " type " + printf " uuid " + printf "path\n" + + _print_images_for_dyld_image_info $kgm_taskp $kgm_task_64 $kgm_dyld_image_info + else + printf "No dyld shared library information available for task\n" + end +end +document showuserlibraries +Syntax: (gdb) showuserlibraries +| For a given user task, inspect the dyld shared library state and print +| information about all Mach-O images. +end + +define showkerneldebugheader + printf "kd_buf " + showptrhdrpad + printf "CPU Thread " + showptrhdrpad + printf "Timestamp S/E Class Sub Code Code Specific Info\n" +end + +define _printevflags + if $arg0 & 1 + printf "EV_RE " + end + if $arg0 & 2 + printf "EV_WR " + end + if $arg0 & 4 + printf "EV_EX " + end + if $arg0 & 8 + printf "EV_RM " + end + + if $arg0 & 0x00100 + printf "EV_RBYTES " + end + if $arg0 & 0x00200 + printf "EV_WBYTES " + end + if $arg0 & 0x00400 + printf "EV_RCLOSED " + end + if $arg0 & 0x00800 + printf "EV_RCONN " + end + if $arg0 & 0x01000 + printf "EV_WCLOSED " + end + if $arg0 & 0x02000 + printf "EV_WCONN " + end + if $arg0 & 0x04000 + printf "EV_OOB " + end + if $arg0 & 0x08000 + printf "EV_FIN " + end + if $arg0 & 0x10000 + printf "EV_RESET " + end + if $arg0 & 0x20000 + printf "EV_TIMEOUT " + end +end + +define showkerneldebugbufferentry + set $kgm_kdebug_entry = (kd_buf *) $arg0 + + set $kgm_debugid = $kgm_kdebug_entry->debugid + set $kgm_kdebug_arg1 = $kgm_kdebug_entry->arg1 + set $kgm_kdebug_arg2 = $kgm_kdebug_entry->arg2 + set $kgm_kdebug_arg3 = $kgm_kdebug_entry->arg3 + set $kgm_kdebug_arg4 = $kgm_kdebug_entry->arg4 + + if $kgm_lp64 + set $kgm_kdebug_cpu = $kgm_kdebug_entry->cpuid + set $kgm_ts_hi = ($kgm_kdebug_entry->timestamp >> 32) & 0xFFFFFFFF + set $kgm_ts_lo = $kgm_kdebug_entry->timestamp & 0xFFFFFFFF + else + set $kgm_kdebug_cpu = ($kgm_kdebug_entry->timestamp >> 56) + set $kgm_ts_hi = ($kgm_kdebug_entry->timestamp >> 32) & 0x00FFFFFF + set $kgm_ts_lo = $kgm_kdebug_entry->timestamp & 0xFFFFFFFF + end + + set $kgm_kdebug_class = ($kgm_debugid >> 24) & 0x000FF + set $kgm_kdebug_subclass = ($kgm_debugid >> 16) & 0x000FF + set $kgm_kdebug_code = ($kgm_debugid >> 2) & 0x03FFF + set $kgm_kdebug_qual = ($kgm_debugid ) & 0x00003 + + if $kgm_kdebug_qual == 0 + set $kgm_kdebug_qual = '-' + else + if $kgm_kdebug_qual == 1 + set $kgm_kdebug_qual = 'S' + else + if $kgm_kdebug_qual == 2 + set $kgm_kdebug_qual = 'E' + else + if $kgm_kdebug_qual == 3 + set $kgm_kdebug_qual = '?' + end + end + end + end + + # preamble and qual + + showptr $kgm_kdebug_entry + printf " %d ", $kgm_kdebug_cpu + showptr $kgm_kdebug_entry->arg5 + printf " 0x%08X%08X %c ", $kgm_ts_hi, $kgm_ts_lo, $kgm_kdebug_qual + + # class + + if $kgm_kdebug_class == 1 + printf "MACH" + else + if $kgm_kdebug_class == 2 + printf "NET " + else + if $kgm_kdebug_class == 3 + printf "FS " + else + if $kgm_kdebug_class == 4 + printf "BSD " + else + if $kgm_kdebug_class == 5 + printf "IOK " + else + if $kgm_kdebug_class == 6 + printf "DRVR" + else + if $kgm_kdebug_class == 7 + printf "TRAC" + else + if $kgm_kdebug_class == 8 + printf "DLIL" + else + if $kgm_kdebug_class == 8 + printf "SEC " + else + if $kgm_kdebug_class == 20 + printf "MISC" + else + if $kgm_kdebug_class == 31 + printf "DYLD" + else + if $kgm_kdebug_class == 32 + printf "QT " + else + if $kgm_kdebug_class == 33 + printf "APPS" + else + if $kgm_kdebug_class == 255 + printf "MIG " + else + printf "0x%02X", $kgm_kdebug_class + end + end + end + end + end + end + end + end + end + end + end + end + end + end + + # subclass and code + + printf " 0x%02X %5d ", $kgm_kdebug_subclass, $kgm_kdebug_code + + # space for debugid-specific processing + + # EVPROC from bsd/kern/sys_generic.c + + # MISCDBG_CODE(DBG_EVENT,DBG_WAIT) + if $kgm_debugid == 0x14100048 + printf "waitevent " + if $kgm_kdebug_arg1 == 1 + printf "before sleep" + else + if $kgm_kdebug_arg1 == 2 + printf "after sleep" + else + printf "????????????" + end + end + printf " chan=0x%08X ", $kgm_kdebug_arg2 + else + # MISCDBG_CODE(DBG_EVENT,DBG_WAIT|DBG_FUNC_START) + if $kgm_debugid == 0x14100049 + printf "waitevent " + else + # MISCDBG_CODE(DBG_EVENT,DBG_WAIT|DBG_FUNC_END) + if $kgm_debugid == 0x1410004a + printf "waitevent error=%d ", $kgm_kdebug_arg1 + printf "eqp=0x%08X ", $kgm_kdebug_arg4 + _printevflags $kgm_kdebug_arg3 + printf "er_handle=%d ", $kgm_kdebug_arg2 + else + # MISCDBG_CODE(DBG_EVENT,DBG_DEQUEUE|DBG_FUNC_START) + if $kgm_debugid == 0x14100059 + printf "evprocdeque proc=0x%08X ", $kgm_kdebug_arg1 + if $kgm_kdebug_arg2 == 0 + printf "remove first " + else + printf "remove 0x%08X ", $kgm_kdebug_arg2 + end + else + # MISCDBG_CODE(DBG_EVENT,DBG_DEQUEUE|DBG_FUNC_END) + if $kgm_debugid == 0x1410005a + printf "evprocdeque " + if $kgm_kdebug_arg1 == 0 + printf "result=NULL " + else + printf "result=0x%08X ", $kgm_kdebug_arg1 + end + else + # MISCDBG_CODE(DBG_EVENT,DBG_POST|DBG_FUNC_START) + if $kgm_debugid == 0x14100041 + printf "postevent " + _printevflags $kgm_kdebug_arg1 + else + # MISCDBG_CODE(DBG_EVENT,DBG_POST) + if $kgm_debugid == 0x14100040 + printf "postevent " + printf "evq=0x%08X ", $kgm_kdebug_arg1 + printf "er_eventbits=" + _printevflags $kgm_kdebug_arg2 + printf "mask=" + _printevflags $kgm_kdebug_arg3 + else + # MISCDBG_CODE(DBG_EVENT,DBG_POST|DBG_FUNC_END) + if $kgm_debugid == 0x14100042 + printf "postevent " + else + # MISCDBG_CODE(DBG_EVENT,DBG_ENQUEUE|DBG_FUNC_START) + if $kgm_debugid == 0x14100055 + printf "evprocenque eqp=0x%08d ", $kgm_kdebug_arg1 + if $kgm_kdebug_arg2 & 1 + printf "EV_QUEUED " + end + _printevflags $kgm_kdebug_arg3 + else + + # MISCDBG_CODE(DBG_EVENT,DBG_EWAKEUP) + if $kgm_debugid == 0x14100050 + printf "evprocenque before wakeup eqp=0x%08d ", $kgm_kdebug_arg4 + else + # MISCDBG_CODE(DBG_EVENT,DBG_ENQUEUE|DBG_FUNC_END) + if $kgm_debugid == 0x14100056 + printf "evprocenque " + else + # MISCDBG_CODE(DBG_EVENT,DBG_MOD|DBG_FUNC_START) + if $kgm_debugid == 0x1410004d + printf "modwatch " + else + # MISCDBG_CODE(DBG_EVENT,DBG_MOD) + if $kgm_debugid == 0x1410004c + printf "modwatch er_handle=%d ", $kgm_kdebug_arg1 + _printevflags $kgm_kdebug_arg2 + printf "evq=0x%08X ", $kgm_kdebug_arg3 + else + # MISCDBG_CODE(DBG_EVENT,DBG_MOD|DBG_FUNC_END) + if $kgm_debugid == 0x1410004e + printf "modwatch er_handle=%d ", $kgm_kdebug_arg1 + printf "ee_eventmask=" + _printevflags $kgm_kdebug_arg2 + printf "sp=0x%08X ", $kgm_kdebug_arg3 + printf "flag=" + _printevflags $kgm_kdebug_arg4 + else + printf "arg1=0x%08X ", $kgm_kdebug_arg1 + printf "arg2=0x%08X ", $kgm_kdebug_arg2 + printf "arg3=0x%08X ", $kgm_kdebug_arg3 + printf "arg4=0x%08X ", $kgm_kdebug_arg4 + end + end + end + end + end + end + end + end + end + end + end + end + end + end + + # finish up + + printf "\n" +end + +define showkerneldebugbuffercpu + set $kgm_cpu_number = (int) $arg0 + set $kgm_entry_count = (int) $arg1 + set $kgm_debugentriesfound = 0 + + #if kdebug_flags & KDBG_BFINIT + if (kdebug_flags & 0x80000000) + showkerneldebugheader + + if $kgm_entry_count == 0 + printf " is 0, dumping 50 entries\n" + set $kgm_entry_count = 50 + end + + if $kgm_cpu_number >= kd_cpus + printf "cpu number too big\n" + else + set $kgm_kdbp = &kdbip[$kgm_cpu_number] + set $kgm_kdsp = $kgm_kdbp->kd_list_head + while (($kgm_kdsp != 0) && ($kgm_entry_count > 0)) + if $kgm_kdsp->kds_readlast != $kgm_kdsp->kds_bufptr + set $kgm_kds_bufptr = $kgm_kdsp->kds_bufptr + while (($kgm_kds_bufptr > $kgm_kdsp->kds_readlast) && ($kgm_entry_count > 0)) + set $kgm_kds_bufptr = $kgm_kds_bufptr - 1 + set $kgm_entry_count = $kgm_entry_count - 1 + showkerneldebugbufferentry $kgm_kds_bufptr + end + end + set $kgm_kdsp = $kgm_kdsp->kds_next + end + end + else + printf "Trace buffer not enabled\n" + end +end + +document showkerneldebugbuffercpu +Syntax: showkerneldebugbuffercpu +| Prints the last N entries in the kernel debug buffer for CPU x. +end + +define showkerneldebugbuffer + + #if kdebug_flags & KDBG_BFINIT + if (kdebug_flags & 0x80000000) + + set $kgm_entrycount = (int) $arg0 + + if $kgm_entrycount == 0 + printf " is 0, dumping 50 entries per cpu\n" + set $kgm_entrycount = 50 + end + + set $kgm_cpu = (int) 0 + + while $kgm_cpu < kd_cpus + showkerneldebugbuffercpu $kgm_cpu $kgm_entrycount + set $kgm_cpu = $kgm_cpu + 1 + end + else + printf "Trace buffer not enabled\n" + end +end + +document showkerneldebugbuffer +Syntax: showkerneldebugbuffer +| Prints the last N entries in the kernel debug buffer per cpu. i.e. showkerneldebugbuffer 50 will +| display the last 50 entries in each CPU's debug buffer. +end + +define showallvmstats + printf " pid command #ents wired vsize rsize max rsize\n" + printf " (pages) (pages) (pages) (pages)\n" + 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) + set $kgm_mapp = (struct _vm_map *)($kgm_taskp->map) + printf "%8d %17s %8d %15d %15d %15d %15d\n", $kgm_procp->p_pid, $kgm_procp->p_comm, $kgm_mapp->hdr.nentries, $kgm_mapp->pmap->stats.wired_count, $kgm_mapp->size >> 12, $kgm_mapp->pmap->stats.resident_count, $kgm_mapp->pmap->stats.resident_max + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end +end + +document showallvmstats +Syntax: showallvmstats +| prints a summary of vm statistics in a table format +end + +define show_user_registers + if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) + set $kgm_thread = (thread_t)$arg0 + if ((*(thread_t)$kgm_thread)->machine.xxx_pcb.iss.flavor == 15) + p/x ($kgm_thread)->machine.xxx_pcb.iss->uss.ss_64 + else + p/x ($kgm_thread)->machine.xxx_pcb.iss->uss.ss_32 + end + end + if ($kgm_mtype == $kgm_mtype_ppc) + set $kgm_thread = (thread_t)$arg0 + p/x *($kgm_thread)->machine.pcb + end +end + +document show_user_registers +Syntax: show_user_registers +| Display user registers associated with a kernel thread +| properly displays the 32 bit or 64 bit registers for intel architecture +end + +define _cmp + set $cmp0 = $arg0 + set $cmp1 = $arg1 + + # check for end of string. cmp0 can be longer than cmp1. it + # can't be shorter. + if $cmp1 == '\0' + set $kgm_strcmp_result = 0 + set $kgm_strcmp_done = 1 + end + + if !$kgm_strcmp_done && $cmp0 == '\0' + set $kgm_strcmp_result = -1 + set $kgm_strcmp_done = 1 + end + + # do they match? + if !$kgm_strcmp_done + set $kgm_strcmp_result = (uint8_t) $cmp0 - (uint8_t) $cmp1 + if $kgm_strcmp_result != 0 + set $kgm_strcmp_done = 1 + end + end +end + +define _cmp_arg64 + set $cmp = $arg1 + set $masked = $cmp & 0xFF + _cmp $arg0[0] $masked + + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[1] $masked + end + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[2] $masked + end + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[3] $masked + end + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[4] $masked + end + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[5] $masked + end + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[6] $masked + end + if !$kgm_strcmp_done + set $cmp = $cmp >> 8 + set $masked = $cmp & 0xFF + _cmp $arg0[7] $masked + end +end + +define strcmp_arg_pack64 + set $kgm_strcmp_arg = ((((((((((((((uint64_t) $arg7 << 8) | $arg6) << 8) | $arg5) << 8) | $arg4) << 8) | $arg3) << 8) | $arg2) << 8) | $arg1) << 8) | $arg0 +end + +document strcmp_arg_pack64 +Syntax: strcmp_arg_pack64 +| Packs a string given as 8 character arguments into a 64-bit int stored in +| $kgm_strcmp_arg. Use 0 or '\0' for unused arguments. The encoded string +| is suitable for use by strcmp_nomalloc and setfindregistrystr. +| e.g., strcmp_arg_pack64 'H' 'e' 'l' 'l' 'o' 0 0 0 +| packs "Hello" into $kgm_strcmp_arg. +| +end + +define strcmp_nomalloc + set $str = $arg0 + set $count = $argc - 1 + + set $kgm_strcmp_result = 0 + set $kgm_strcmp_done = 0 + + if $count > 0 + _cmp_arg64 $str $arg1 + end + if !$kgm_strcmp_done && $count > 1 + set $str = $str + 8 + _cmp_arg64 $str $arg2 + end + if !$kgm_strcmp_done && $count > 2 + set $str = $str + 8 + _cmp_arg64 $str $arg3 + end + if !$kgm_strcmp_done && $count > 3 + set $str = $str + 8 + _cmp_arg64 $str $arg4 + end + if !$kgm_strcmp_done && $count > 4 + set $str = $str + 8 + _cmp_arg64 $str $arg5 + end + if !$kgm_strcmp_done && $count > 5 + set $str = $str + 8 + _cmp_arg64 $str $arg6 + end + if !$kgm_strcmp_done && $count > 6 + set $str = $str + 8 + _cmp_arg64 $str $arg7 + end + if !$kgm_strcmp_done && $count > 7 + set $str = $str + 8 + _cmp_arg64 $str $arg8 + end + if !$kgm_strcmp_done && $count > 8 + set $str = $str + 8 + _cmp_arg64 $str $arg9 + end +end + +document strcmp_nomalloc +Syntax: strcmp_nomalloc [b] [c] [d] [e] [f] [g] [h] [i] +| Given a pre-allocated , perform a string compare with the +| encoded string stored in arguments a - i. The result is stored in +| $kgm_strcmp_result. +| +| For example, the following will result in $kgm_strcmp_result == 0: +| strcmp_arg_pack64 'D' 'a' 'r' 'w' 'i' 'n' ' ' 'K' +| strcmp_nomalloc version $kgm_strcmp_arg +end + +# _pci_cfg_addr_value $addr $size +define _pci_cfg_addr_value + readphysint $arg0 $arg1 $kgm_lcpu_self + set $kgm_pci_cfg_value = $kgm_readphysint_result +end + + +set $kgm_pci_cfg_init = 0 +define _pci_cfg_init + # get this from the registry if it exists there + if $kgm_pci_cfg_init == 0 + strcmp_arg_pack64 'A' 'p' 'p' 'l' 'e' 'A' 'C' 'P' + set $AppleACP = $kgm_strcmp_arg + strcmp_arg_pack64 'I' 'P' 'l' 'a' 't' 'f' 'o' 'r' + set $IPlatfor = $kgm_strcmp_arg + strcmp_arg_pack64 'm' 'E' 'x' 'p' 'e' 'r' 't' 0 + set $mExpert = $kgm_strcmp_arg + setfindregistrystr $AppleACP $IPlatfor $mExpert + + set $olddepth = $kgm_reg_depth_max + set $kgm_reg_depth_max = 2 + _findregistryentry + set $kgm_reg_depth_max = $olddepth + + if $kgm_registry_entry + strcmp_arg_pack64 'a' 'c' 'p' 'i' '-' 'm' 'm' 'c' + set $acpi_mmc = $kgm_strcmp_arg + strcmp_arg_pack64 'f' 'g' '-' 's' 'e' 'g' '0' 0 + set $fg_seg0 = $kgm_strcmp_arg + setfindregistrystr $acpi_mmc $fg_seg0 + + _findregistryprop $kgm_registry_entry + if $kgm_registry_value + set $kgm_pci_cfg_base = ((OSNumber *) $kgm_registry_value)->value + set $kgm_pci_cfg_init = 1 + end + end + end + + # if the above fails, search for 0:0:0 in likely places. + if $kgm_pci_cfg_init == 0 + set $kgm_pci_cfg_base = 0xF0000000 + while $kgm_pci_cfg_init == 0 && $kgm_pci_cfg_base > 0xA0000000 + _pci_cfg_addr_value $kgm_pci_cfg_base 8 + if $kgm_pci_cfg_value > 0x0 && $kgm_pci_cfg_value < 0xFF + set $kgm_pci_cfg_init = 1 + else + set $kgm_pci_cfg_base = $kgm_pci_cfg_base - 0x10000000 + end + end + end +end + +# _pci_cfg_addr $bus $dev $fcn $off +define _pci_cfg_addr + set $bus = $arg0 + set $dev = $arg1 + set $fcn = $arg2 + set $off = $arg3 + + _pci_cfg_init + set $kgm_pci_cfg_addr = $kgm_pci_cfg_base | ($bus << 20) | ($dev << 15) | ($fcn << 12) | $off +end + +define _pci_cfg_value + _pci_cfg_addr $arg0 $arg1 $arg2 $arg3 + _pci_cfg_addr_value $kgm_pci_cfg_addr $arg4 +end + +define pci_cfg_read8 + _pci_cfg_value $arg0 $arg1 $arg2 $arg3 8 + printf "%08X: %02X\n", $kgm_pci_cfg_addr, $kgm_pci_cfg_value +end + +define pci_cfg_read16 + _pci_cfg_value $arg0 $arg1 $arg2 $arg3 16 + printf "%08X: %04X\n", $kgm_pci_cfg_addr, $kgm_pci_cfg_value +end + +define pci_cfg_read32 + _pci_cfg_value $arg0 $arg1 $arg2 $arg3 32 + printf "%08X: %08X\n", $kgm_pci_cfg_addr, $kgm_pci_cfg_value +end + +document pci_cfg_read8 +Syntax: (gdb) pci_cfg_read8 +| read 8 bits for the given of the pci device located at +| ::. +end + +document pci_cfg_read16 +Syntax: (gdb) pci_cfg_read +| read 16 bits for the given of the pci device located at +| ::. +end + +document pci_cfg_read32 +Syntax: (gdb) pci_cfg_read +| read 32 bits for the given of the pci device located at +| ::. +end + +define pci_cfg_write8 + _pci_cfg_addr $arg0 $arg1 $arg2 $arg3 + writephysint $kgm_pci_cfg_addr 8 $arg4 $kgm_lcpu_self +end + +define pci_cfg_write16 + _pci_cfg_addr $arg0 $arg1 $arg2 $arg3 + writephysint $kgm_pci_cfg_addr 16 $arg4 $kgm_lcpu_self +end + +define pci_cfg_write32 + _pci_cfg_addr $arg0 $arg1 $arg2 $arg3 + writephysint $kgm_pci_cfg_addr 32 $arg4 $kgm_lcpu_self +end + +document pci_cfg_write8 +Syntax: (gdb) pci_cfg_write8 +| write an 8-bit into the given of the pci device located at +| ::. +end + +document pci_cfg_write16 +Syntax: (gdb) pci_cfg_write16 +| write a 16-bit into the given of the pci device located at +| ::. +end + +document pci_cfg_write32 +Syntax: (gdb) pci_cfg_write32 +| write a 32-bit into the given of the pci device located at +| ::. +end + + +define pci_cfg_dump + set $bus = $arg0 + set $dev = $arg1 + set $fcn = $arg2 + set $off = 0 + + # check for a valid pci device + _pci_cfg_value $bus $dev $fcn $off 8 + if $kgm_pci_cfg_value > 0x0 && $kgm_pci_cfg_value < 0xff + printf " address: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n" + printf "---------------------------------------------------------" + + while $off < 256 + _pci_cfg_value $bus $dev $fcn $off 32 + if ($off & 0xF) == 0 + printf "\n%08X: ", $kgm_pci_cfg_addr + end + printf "%02X %02X %02X %02X ", $kgm_pci_cfg_value & 0xFF, ($kgm_pci_cfg_value >> 8) & 0xFF, ($kgm_pci_cfg_value >> 16) & 0xFF, ($kgm_pci_cfg_value >> 24) & 0xFF + set $off = $off + 4 + end + printf "\n" + + # check for pcie extended capability config space + _pci_cfg_value $bus $dev $fcn $off 8 + if $kgm_pci_cfg_value < 0xff + while $off < 4096 + _pci_cfg_value $bus $dev $fcn $off 32 + if ($off & 0xF) == 0 + printf "\n%08X: ", $kgm_pci_cfg_addr + end + printf "%02X %02X %02X %02X ", $kgm_pci_cfg_value & 0xFF, ($kgm_pci_cfg_value >> 8) & 0xFF, ($kgm_pci_cfg_value >> 16) & 0xFF, ($kgm_pci_cfg_value >> 24) & 0xFF + set $off = $off + 4 + end + printf "\n" + end + end +end + +document pci_cfg_dump +Syntax: (gdb) pci_cfg_dump +| dump config space for the pci device located at :: +| if you specify an invalid/inaccessible pci device, nothing will be +| printed out. +end + +set $kgm_pci_cfg_bus_start = 0 +set $kgm_pci_cfg_bus_max = 8 +set $kgm_pci_cfg_device_max = 32 +set $kgm_pci_cfg_function_max = 8 +define _pci_cfg_scan + set $dump = $arg0 + + set $bus = $kgm_pci_cfg_bus_start + while $bus < $kgm_pci_cfg_bus_max + # check for bus:0:0 to see if we should + # probe this bus further + _pci_cfg_value $bus 0x0 0x0 0x0 32 + if $kgm_pci_cfg_value > 0 && $kgm_pci_cfg_value < 0xFFFFFFFF + + set $dev = 0 + while $dev < $kgm_pci_cfg_device_max + + set $fcn = 0 + while $fcn < $kgm_pci_cfg_function_max + _pci_cfg_value $bus $dev $fcn 0x0 32 + if $kgm_pci_cfg_value > 0 && $kgm_pci_cfg_value < 0xFFFFFFFF + if $dump == 0 + printf "%03X:%03X:%03X: %02X%02X %02X%02X", $bus, $dev, $fcn, ($kgm_pci_cfg_value >> 8) & 0xFF, $kgm_pci_cfg_value & 0xFF, ($kgm_pci_cfg_value >> 24) & 0xFF, ($kgm_pci_cfg_value >> 16) & 0xFF + _pci_cfg_value $bus $dev $fcn 0x8 32 + printf " %02X | %02X%02X%02X\n", $kgm_pci_cfg_value & 0xFF, ($kgm_pci_cfg_value >> 24) & 0xFF, ($kgm_pci_cfg_value >> 16) & 0xFF, ($kgm_pci_cfg_value >> 8) & 0xFF + else + printf " device: %03X:%03X:%03X\n", $bus, $dev, $fcn + pci_cfg_dump $bus $dev $fcn + printf "\n" + end + end + set $fcn = $fcn + 1 + end + set $dev = $dev + 1 + end + end + set $bus = $bus + 1 + end +end + +define pci_cfg_dump_all + _pci_cfg_scan 1 +end + +document pci_cfg_dump_all +Syntax: (gdb) pci_cfg_dump_all +| dump config spaces for scanned pci devices. the number of busses to scan +| is stored in $kgm_pci_cfg_bus_max. the default for that is 8. you can also +| specify the starting bus with $kgm_pci_cfg_bus_start. +end + +define pci_cfg_scan + printf "bus:dev:fcn: vendor device rev | class\n" + printf "---------------------------------------\n" + _pci_cfg_scan 0 +end + +document pci_cfg_scan +Syntax: (gdb) pci_cfg_scan +| scan for pci devices. the number of busses to scan is stored in +| $kgm_pci_cfg_bus_max. the default for that is 8. you can also specify the +| starting bus with $kgm_pci_cfg_bus_start. +end + +define readioportint + set $kgm_readioportint_result = 0xBAD10AD + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_readioport_req_t) + set $kgm_pkt = (kdp_readioport_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_READIOPORT + set $kgm_pkt->hdr.len = sizeof(kdp_readioport_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint16_t)$arg0 + set $kgm_pkt->nbytes = $arg1 >> 3 + set $kgm_pkt->lcpu = (uint16_t)$arg2 + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_readioport_reply_t *)&manual_pkt.data + if ($kgm_pkt->error == 0) + if $arg1 == 8 + set $kgm_readioportint_result = *((uint8_t *) $kgm_pkt->data) + end + if $arg1 == 16 + set $kgm_readioportint_result = *((uint16_t *) $kgm_pkt->data) + end + if $arg1 == 32 + set $kgm_readioportint_result = *((uint32_t *) $kgm_pkt->data) + end + end +end + +define readioport8 + set $lcpu = $kgm_lcpu_self + if $argc > 1 + set $lcpu = $arg1 + end + readioportint $arg0 8 $lcpu + output /a $arg0 + printf ":\t0x%02hhx\n", $kgm_readioportint_result +end + +define readioport16 + set $lcpu = $kgm_lcpu_self + if $argc > 1 + set $lcpu = $arg1 + end + readioportint $arg0 16 $lcpu + output /a $arg0 + printf ":\t0x%04hx\n", $kgm_readioportint_result +end + +define readioport32 + set $lcpu = $kgm_lcpu_self + if $argc > 1 + set $lcpu = $arg1 + end + readioportint $arg0 32 $lcpu + output /a $arg0 + printf ":\t0x%08x\n", $kgm_readioportint_result +end + +document readioport8 +| See readioport32. +end + +document readioport16 +| See readioport32. +end + +document readioport32 +Syntax: (gdb) readioport32 [lcpu (kernel's numbering convention)] +| Read value stored in the specified IO port. The CPU can be optionally +| specified as well. +end + +define writeioportint + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_writeioport_req_t) + set $kgm_pkt = (kdp_writeioport_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_WRITEIOPORT + set $kgm_pkt->hdr.len = sizeof(kdp_writeioport_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint16_t)$arg0 + set $kgm_pkt->nbytes = $arg1 >> 3 + set $kgm_pkt->lcpu = (uint16_t)$arg3 + if $arg1 == 8 + set *(uint8_t *)$kgm_pkt->data = (uint8_t)$arg2 + end + if $arg1 == 16 + set *(uint16_t *)$kgm_pkt->data = (uint16_t)$arg2 + end + if $arg1 == 32 + set *(uint32_t *)$kgm_pkt->data = (uint32_t)$arg2 + end + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_writeioport_reply_t *)&manual_pkt.data + set $kgm_writeioportint_result = $kgm_pkt->error +end + +define writeioport8 + set $lcpu = $kgm_lcpu_self + if $argc > 2 + set $lcpu = $arg2 + end + writeioportint $arg0 8 $arg1 $lcpu +end + +define writeioport16 + set $lcpu = $kgm_lcpu_self + if $argc > 2 + set $lcpu = $arg2 + end + writeioportint $arg0 16 $arg1 $lcpu +end + +define writeioport32 + set $lcpu = $kgm_lcpu_self + if $argc > 2 + set $lcpu = $arg2 + end + writeioportint $arg0 32 $arg1 $lcpu +end + +document writeioport8 +| See writeioport32. +end + +document writeioport16 +| See writeioport32. +end + +document writeioport32 +Syntax: (gdb) writeioport32 [lcpu (kernel's numbering convention)] +| Write the value to the specified IO port. The size of the value is +| determined by the name of the command. The CPU used can be optionally +| specified. +end + +define readmsr64int + set $kgm_readmsr64int_result = 0xBAD10AD + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_readmsr64_req_t) + set $kgm_pkt = (kdp_readmsr64_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_READMSR64 + set $kgm_pkt->hdr.len = sizeof(kdp_readmsr64_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint32_t)$arg0 + set $kgm_pkt->lcpu = (uint16_t)$arg1 + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_readmsr64_reply_t *)&manual_pkt.data + if ($kgm_pkt->error == 0) + set $kgm_readmsr64int_result = *((uint64_t *) $kgm_pkt->data) + end +end + +define readmsr64 + set $lcpu = $kgm_lcpu_self + if $argc > 1 + set $lcpu = $arg1 + end + readmsr64int $arg0 $lcpu + output /a $arg0 + printf ":\t0x%016llx\n", $kgm_readmsr64int_result +end + +define writemsr64int + # set up the manual KDP packet + set manual_pkt.input = 0 + set manual_pkt.len = sizeof(kdp_writemsr64_req_t) + set $kgm_pkt = (kdp_writemsr64_req_t *)&manual_pkt.data + set $kgm_pkt->hdr.request = KDP_WRITEMSR64 + set $kgm_pkt->hdr.len = sizeof(kdp_writemsr64_req_t) + set $kgm_pkt->hdr.is_reply = 0 + set $kgm_pkt->hdr.seq = 0 + set $kgm_pkt->hdr.key = 0 + set $kgm_pkt->address = (uint32_t)$arg0 + set $kgm_pkt->lcpu = (uint16_t)$arg2 + set *(uint64_t *)$kgm_pkt->data = (uint64_t)$arg1 + set manual_pkt.input = 1 + # dummy to make sure manual packet is executed + set $kgm_dummy = &_mh_execute_header + set $kgm_pkt = (kdp_writemsr64_reply_t *)&manual_pkt.data + set $kgm_writemsr64int_result = $kgm_pkt->error +end + +define writemsr64 + set $lcpu = $kgm_lcpu_self + if $argc > 2 + set $lcpu = $arg2 + end + writemsr64int $arg0 $arg1 $lcpu +end + +document writemsr64 +Syntax: (gdb) writemsr64 [lcpu (kernel's numbering convention)] +| Write to the specified MSR. The CPU can be optionally specified. +end + +document readmsr64 +Syntax: (gdb) readmsr64 [lcpu (kernel's numbering convention)] +| Read the specified MSR. The CPU can be optionally specified. +end + +# default if we can't find a registry entry +set $kgm_ioapic_addr = 0xFEC00000 +set $kgm_ioapic_init = 0 + +set $_ioapic_index_off = 0x00 +set $_ioapic_data_off = 0x10 +set $_ioapic_eoi_off = 0x40 + +set $_ioapic_index_id = 0x00 +set $_ioapic_index_ver = 0x01 +set $_ioapic_index_redir_base = 0x10 + +set $_apic_vector_mask = 0xFF +set $_apic_masked = 0x10000 +set $_apic_trigger_level = 0x08000 +set $_apic_polarity_high = 0x02000 +set $_apic_pending = 0x01000 + +define _ioapic_init + if $kgm_ioapic_init == 0 + strcmp_arg_pack64 'i' 'o' '-' 'a' 'p' 'i' 'c' 0 + setfindregistrystr $kgm_strcmp_arg + + set $olddepth = $kgm_reg_depth_max + set $kgm_reg_depth_max = 3 + _findregistryentry + set $kgm_reg_depth_max = $olddepth + + if $kgm_registry_entry + strcmp_arg_pack64 'P' 'h' 'y' 's' 'i' 'c' 'a' 'l' + set $Physical = $kgm_strcmp_arg + strcmp_arg_pack64 ' ' 'A' 'd' 'd' 'r' 'e' 's' 's' + set $_Address = $kgm_strcmp_arg + setfindregistrystr $Physical $_Address + + _findregistryprop $kgm_registry_entry + if $kgm_registry_value + set $kgm_ioapic_addr = ((OSNumber *) $kgm_registry_value)->value + end + end + set $kgm_ioapic_index_addr = $kgm_ioapic_addr + $_ioapic_index_off + set $kgm_ioapic_data_addr = $kgm_ioapic_addr + $_ioapic_data_off + set $kgm_ioapic_init = 1 + end +end + +define _ioapic_addr_value + _ioapic_init + writephysint $kgm_ioapic_index_addr 8 $arg0 $kgm_lcpu_self + if $argc > 1 + writephysint $kgm_ioapic_data_addr 32 $arg1 $kgm_lcpu_self + else + readphysint $kgm_ioapic_data_addr 32 $kgm_lcpu_self + set $kgm_ioapic_value = $kgm_readphysint_result + end +end + +define _apic_print + set $value = $arg0 + + printf "[VEC=%3d ", $value & $_apic_vector_mask + if $value & $_apic_masked + printf "MASK=yes " + else + printf "MASK=no " + end + + if $value & $_apic_trigger_level + printf "TRIG=level " + else + printf "TRIG=edge " + end + + if $value & $_apic_polarity_high + printf "POL=high" + else + printf "POL=low " + end + + if $value & $_apic_pending + printf " PEND=yes]\n" + else + printf " PEND=no ]\n" + end +end + +define ioapic_read32 + if (($kgm_mtype & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + printf "ioapic_read32 not supported on this architecture.\n" + else + _ioapic_addr_value $arg0 + printf "IOAPIC[0x%02X]: 0x%08X\n", $arg0, $kgm_ioapic_value + end +end + +document ioapic_read32 +Syntax: (gdb) ioapic_read +| Read the IOAPIC register at the offset specified. +end + +define ioapic_write32 + if (($kgm_mtype & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + printf "ioapic_write32 not supported on this architecture.\n" + else + _ioapic_addr_value $arg0 $arg1 + end +end + +document ioapic_write32 +Syntax: (gdb) ioapic_write32 +| Write the IOAPIC register at the offset specified. +end + +define ioapic_dump + if (($kgm_mtype & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + printf "ioapic_dump not supported on this architecture.\n" + else + # id + _ioapic_addr_value $_ioapic_index_id + printf "IOAPIC[0x%02X] ID: 0x%08X\n", $_ioapic_index_id, $kgm_ioapic_value + + # version + _ioapic_addr_value $_ioapic_index_ver + set $maxredir = (($kgm_ioapic_value & 0xFF0000) >> 16) + 1 + + printf "IOAPIC[0x%02X] VERSION: 0x%08X [", $_ioapic_index_ver, $kgm_ioapic_value + printf "MAXREDIR=%02d PRQ=%d VERSION=0x%02X]\n", $maxredir, ($kgm_ioapic_value >> 15) & 0x1, $kgm_ioapic_value & 0xFF + + # all the redir entries + set $i = 0 + while $i < $maxredir + set $addr0 = $_ioapic_index_redir_base + ($i << 1) + set $addr1 = $addr0 + 1 + _ioapic_addr_value $addr1 + printf "IOAPIC[0x%02X] IOREDIR%02d: 0x%08X", $addr0, $i, $kgm_ioapic_value + + _ioapic_addr_value $addr0 + printf "%08X ", $kgm_ioapic_value + _apic_print $kgm_ioapic_value + set $i = $i + 1 + end + end +end + +document ioapic_dump +Syntax: (gdb) ioapic_dump +| Dump all the IOAPIC entries. +end + + +set $_lapic_base_addr = 0xFEE00000 +set $_lapic_id = 0x20 +set $_lapic_version = 0x30 +set $_lapic_tpr = 0x80 +set $_lapic_apr = 0x90 +set $_lapic_ppr = 0xA0 +set $_lapic_eoi = 0xB0 +set $_lapic_ldr = 0xD0 +set $_lapic_dfr = 0xE0 +set $_lapic_sivr = 0xF0 + +set $_lapic_isr_size = 0x10 +set $_lapic_isr_num = 8 +set $_lapic_isr0 = 0x100 +set $_lapic_tmr0 = 0x180 +set $_lapic_irr0 = 0x200 + +set $_lapic_esr = 0x280 +set $_lapic_esr_register = 0x80 +set $_lapic_esr_recv_vect = 0x40 +set $_lapic_esr_send_vect = 0x20 + +set $_lapic_icr0 = 0x300 +set $_lapic_icr1 = 0x310 + +set $_lapic_lvt_timer = 0x320 +set $_lapic_lvt_thermal = 0x330 +set $_lapic_lvt_pmcr = 0x340 +set $_lapic_lvt_lint0 = 0x350 +set $_lapic_lvt_lint1 = 0x360 +set $_lapic_lvt_error = 0x370 + +set $_lapic_icr = 0x380 +set $_lapic_ccr = 0x390 +set $_lapic_dcr = 0x3E0 + +set $_apic_cfg_msr = 0x1B +set $_apic_cfg_msr_x2EN = 0x00000C00 +set $_x2apic_enabled = -1 + +# _lapic_addr $offset returns the actual address to use +define _lapic_addr + if $_x2apic_enabled < 0 + readmsr64int $_apic_cfg_msr $kgm_lcpu_self + if ($kgm_readmsr64int_result & $_apic_cfg_msr_x2EN) == $_apic_cfg_msr_x2EN + set $_x2apic_enabled = 1 + else + set $_x2apic_enabled = 0 + end + end + + if $_x2apic_enabled + # x2APIC addresses are MSRs that use xAPIC offsets that + # are 4-bit shifted + set $kgm_lapic_addr = $arg0 >> 4 + else + set $kgm_lapic_addr = $_lapic_base_addr + $arg0 + end +end + +# _lapic_addr_value $offset $lcpu +define _lapic_addr_value + _lapic_addr $arg0 + if $_x2apic_enabled + readmsr64int $kgm_lapic_addr $arg1 + set $kgm_lapic_value = $kgm_readmsr64int_result + else + readphysint $kgm_lapic_addr 32 $arg1 + set $kgm_lapic_value = $kgm_readphysint_result + end +end + +# lapic_read32 $offset [$lcpu] +define lapic_read32 + if (($kgm_mtype & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + printf "lapic_read32 not supported on this architecture.\n" + else + set $lcpu = $kgm_lcpu_self + if $argc > 1 + set $lcpu = $arg1 + end + _lapic_addr_value $arg0 $lcpu + printf "LAPIC[0x%03X]: 0x%08X\n", $arg0, $kgm_lapic_value + end +end + +document lapic_read32 +Syntax: (gdb) apic_read32_cpu [lcpu (kernel's numbering convention)] +| Read the LAPIC register at the offset specified. The CPU can be optionally +| specified. +end + +# lapic_write32 $offset $value [$lcpu] +define lapic_write32 + if (($kgm_mtype & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + printf "lapic_write32_cpu not supported on this architecture.\n" + else + set $lcpu = $kgm_lcpu_self + if $argc > 2 + set $lcpu = $arg2 + end + + _lapic_addr $arg0 + if $_x2apic_enabled + writemsr64int $kgm_lapic_addr $arg1 $lcpu + else + writephysint $kgm_lapic_addr 32 $arg1 $lcpu + end + end +end + +document lapic_write32 +Syntax: (gdb) lapic_write32 [lcpu (kernel's numbering convention)] +| Write the LAPIC register at the offset specified. The CPU can be optionally +| specified. +end + +# lapic_dump [lcpu] +define lapic_dump + if (($kgm_mtype & $kgm_mtype_x86_mask) != $kgm_mtype_x86_any) + printf "lapic_dump not supported on this architecture.\n" + else + set $lcpu = $kgm_lcpu_self + if $argc > 0 + set $lcpu = $arg0 + end + + _lapic_addr_value $_lapic_id $lcpu + + # the above also figures out if we're using an xAPIC or an x2APIC + printf "LAPIC operating mode: " + if $_x2apic_enabled + printf " x2APIC\n" + else + printf " xAPIC\n" + end + + printf "LAPIC[0x%03X] ID: 0x%08X\n", $_lapic_id, $kgm_lapic_value + + _lapic_addr_value $_lapic_version $lcpu + set $lvt_num = ($kgm_lapic_value >> 16) + 1 + printf "LAPIC[0x%03X] VERSION: 0x%08X [VERSION=%d MaxLVT=%d]\n", $_lapic_version, $kgm_lapic_value, $kgm_lapic_value & 0xFF, $lvt_num + + _lapic_addr_value $_lapic_tpr $lcpu + printf "LAPIC[0x%03X] TASK PRIORITY: 0x%08X\n", $_lapic_tpr, $kgm_lapic_value + + _lapic_addr_value $_lapic_ppr $lcpu + printf "LAPIC[0x%03X] PROCESSOR PRIORITY: 0x%08X\n", $_lapic_ppr, $kgm_lapic_value + + _lapic_addr_value $_lapic_ldr $lcpu + printf "LAPIC[0x%03X] LOGICAL DEST: 0x%08X\n", $_lapic_ldr, $kgm_lapic_value + + _lapic_addr_value $_lapic_dfr $lcpu + printf "LAPIC[0x%03X] DEST FORMAT: 0x%08X\n", $_lapic_dfr, $kgm_lapic_value + + _lapic_addr_value $_lapic_sivr $lcpu + printf "LAPIC[0x%03X] SPURIOUS VECTOR: 0x%08X [VEC=%3d ENABLED=%d]\n", $_lapic_sivr, $kgm_lapic_value, $kgm_lapic_value & $_apic_vector_mask, ($kgm_lapic_value & 0x100) >> 8, + + set $i = 0 + while $i < $_lapic_isr_num + set $addr = $_lapic_isr0 + $i * $_lapic_isr_size + _lapic_addr_value $addr $lcpu + printf "LAPIC[0x%03X] ISR[%03d:%03d]: 0x%08X\n", $addr, 32*($i + 1) - 1, 32*$i, $kgm_lapic_value + set $i = $i + 1 + end + + set $i = 0 + while $i < $_lapic_isr_num + set $addr = $_lapic_tmr0 + $i * $_lapic_isr_size + _lapic_addr_value $addr $lcpu + printf "LAPIC[0x%03X] TMR[%03d:%03d]: 0x%08X\n", $addr, 32*($i + 1) - 1, 32*$i, $kgm_lapic_value + set $i = $i + 1 + end + + set $i = 0 + while $i < $_lapic_isr_num + set $addr = $_lapic_irr0 + $i * $_lapic_isr_size + _lapic_addr_value $addr $lcpu + printf "LAPIC[0x%03X] IRR[%03d:%03d]: 0x%08X\n", $addr, 32*($i + 1) - 1, 32*$i, $kgm_lapic_value + set $i = $i + 1 + end + + _lapic_addr_value $_lapic_esr $lcpu + printf "LAPIC[0x%03X] ERROR STATUS: 0x%08X ", $_lapic_esr, $kgm_lapic_value + if $kgm_lapic_value + printf "[" + end + if $kgm_lapic_value & $_lapic_esr_register + printf "Register " + end + if $kgm_lapic_value & $_lapic_esr_recv_vect + printf "Received Vector " + end + if $kgm_lapic_value & $_lapic_esr_send_vect + printf "Send Vector" + end + if $kgm_lapic_value + printf "]" + end + printf "\n" + + _lapic_addr_value $_lapic_icr1 $lcpu + printf "LAPIC[0x%03X] Interrupt Command: 0x%08X [DEST=%d]\n", $_lapic_icr0, $kgm_lapic_value, $kgm_lapic_value >> 24 + _lapic_addr_value $_lapic_icr0 $lcpu + printf " 0x%08X ", $kgm_lapic_value + _apic_print $kgm_lapic_value + + if $lvt_num > 0 + _lapic_addr_value $_lapic_lvt_timer $lcpu + printf "LAPIC[0x%03X] LVT Timer: 0x%08X ", $_lapic_lvt_timer, $kgm_lapic_value + _apic_print $kgm_lapic_value + end + + if $lvt_num > 1 + _lapic_addr_value $_lapic_lvt_lint0 $lcpu + printf "LAPIC[0x%03X] LVT LINT0: 0x%08X ", $_lapic_lvt_lint0, $kgm_lapic_value + _apic_print $kgm_lapic_value + end + + if $lvt_num > 2 + _lapic_addr_value $_lapic_lvt_lint1 $lcpu + printf "LAPIC[0x%03X] LVT LINT1: 0x%08X ", $_lapic_lvt_lint1, $kgm_lapic_value + _apic_print $kgm_lapic_value + end + + if $lvt_num > 3 + _lapic_addr_value $_lapic_lvt_error $lcpu + printf "LAPIC[0x%03X] LVT Error: 0x%08X ", $_lapic_lvt_error, $kgm_lapic_value + _apic_print $kgm_lapic_value + end + + if $lvt_num > 4 + _lapic_addr_value $_lapic_lvt_pmcr $lcpu + printf "LAPIC[0x%03X] LVT PerfMon: 0x%08X ", $_lapic_lvt_pmcr, $kgm_lapic_value + _apic_print $kgm_lapic_value + end + + if $lvt_num > 5 + _lapic_addr_value $_lapic_lvt_thermal $lcpu + printf "LAPIC[0x%03X] LVT Thermal: 0x%08X ", $_lapic_lvt_thermal, $kgm_lapic_value + _apic_print $kgm_lapic_value + end + + _lapic_addr_value $_lapic_dcr $lcpu + printf "LAPIC[0x%03X] Timer Divide: 0x%08X [Divide by ", $_lapic_dcr, $kgm_lapic_value + set $kgm_lapic_value = ($kgm_lapic_value & 0x8) >> 1 | $kgm_lapic_value & 0x3 + if $kgm_lapic_value == 0x7 + printf "1]\n" + else + printf "%d]\n", 2 << $kgm_lapic_value + end + + _lapic_addr_value $_lapic_icr $lcpu + printf "LAPIC[0x%03X] Timer Init Count: 0x%08X\n", $_lapic_icr, $kgm_lapic_value + + _lapic_addr_value $_lapic_ccr $lcpu + printf "LAPIC[0x%03X] Timer Cur Count: 0x%08X\n", $_lapic_ccr, $kgm_lapic_value + end +end + +document lapic_dump +Syntax: (gdb) lapic_dump [lcpu (kernel's numbering convention)] +| Dump all the LAPIC entries. The CPU can be optionally specified. +end + +define showknoteheader + printf " knote filter ident kn_ptr status\n" +end + +define showknoteint + set $kgm_knotep = ((struct knote *) $arg0) + printf " " + showptr $kgm_knotep + printf " " + set $kgm_filt = -$kgm_knotep->kn_kevent.filter + if ($kgm_filt == 1) + printf "EVFILT_READ " + end + if ($kgm_filt == 2) + printf "EVFILT_WRITE " + end + if ($kgm_filt == 3) + printf "EVFILT_AIO " + end + if ($kgm_filt == 4) + printf "EVFILT_VNODE " + end + if ($kgm_filt == 5) + printf "EVFILT_PROC " + end + if ($kgm_filt == 6) + printf "EVFILT_SIGNAL " + end + if ($kgm_filt == 7) + printf "EVFILT_TIMER " + end + if ($kgm_filt == 8) + printf "EVFILT_MACHPORT" + end + if ($kgm_filt == 9) + printf "EVFILT_FS " + end + if ($kgm_filt == 10) + printf "EVFILT_USER " + end + if ($kgm_filt == 11) + printf "EVFILT_SESSION " + end + printf "%7d ", $kgm_knotep->kn_kevent.ident + showptr $kgm_knotep->kn_ptr.p_fp + printf " " + if ($kgm_knotep->kn_status == 0) + printf "-" + else + if ($kgm_knotep->kn_status & 0x01) + printf "A" + end + if ($kgm_knotep->kn_status & 0x02) + printf "Q" + end + if ($kgm_knotep->kn_status & 0x04) + printf "Dis" + end + if ($kgm_knotep->kn_status & 0x08) + printf "Dr" + end + if ($kgm_knotep->kn_status & 0x10) + printf "Uw" + end + if ($kgm_knotep->kn_status & 0x20) + printf "Att" + end + if ($kgm_knotep->kn_status & 0x40) + printf "Stq" + end + end + printf "\n" +end + +define showprocknotes + showknoteheader + set $kgm_fdp = ((proc_t)$arg0)->p_fd + set $kgm_knlist = $kgm_fdp->fd_knlist + set $i = 0 + while (($i < $kgm_fdp->fd_knlistsize) && ($kgm_knlist != 0)) + set $kgm_kn = ((struct knote *)$kgm_knlist[$i].slh_first) + while ($kgm_kn != 0) + showknoteint $kgm_kn + set $kgm_kn = ((struct knote *)$kgm_kn->kn_link.sle_next) + end + set $i = $i + 1 + end + set $kgm_knhash = $kgm_fdp->fd_knhash + set $i = 0 + while (($i < $kgm_fdp->fd_knhashmask + 1) && ($kgm_knhash != 0)) + set $kgm_kn = ((struct knote *)$kgm_knhash[$i].slh_first) + while ($kgm_kn != 0) + showknoteint $kgm_kn + set $kgm_kn = ((struct knote *)$kgm_kn->kn_link.sle_next) + end + set $i = $i + 1 + end +end + +define showallknotes + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + showtaskheader + showtaskint $kgm_taskp + showprocknotes $kgm_taskp->bsd_info + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end +end +document showprocknotes +Syntax: showprocknotes +| Displays filter and status information for every kevent registered for +| the process. +end + +# +# Device node related debug macros +# + +define _showtty + set $kgm_tty = (struct tty *) $arg0 + printf "tty struct at " + showptr $kgm_tty + printf "\n" + printf "-last input to raw queue:\n" + p $kgm_tty->t_rawq->c_cs + printf "-last input to canonical queue:\n" + p $kgm_tty->t_canq->c_cs + printf "-last output data:\n" + p $kgm_tty->t_outq->c_cs + printf "state:\n" + if ($kgm_tty->t_state & 0x00000001) + printf " TS_SO_OLOWAT (Wake up when output <= low water)\n" + end + if ($kgm_tty->t_state & 0x00000002) + printf " TS_ASYNC (async I/O mode)\n" + else + printf " - (synchronous I/O mode)\n" + end + if ($kgm_tty->t_state & 0x00000004) + printf " TS_BUSY (Draining output)\n" + end + if ($kgm_tty->t_state & 0x00000008) + printf " TS_CARR_ON (Carrier is present)\n" + else + printf " - (Carrier is NOT present)\n" + end + if ($kgm_tty->t_state & 0x00000010) + printf " TS_FLUSH (Outq has been flushed during DMA)\n" + end + if ($kgm_tty->t_state & 0x00000020) + printf " TS_ISOPEN (Open has completed)\n" + else + printf " - (Open has NOT completed)\n" + end + if ($kgm_tty->t_state & 0x00000040) + printf " TS_TBLOCK (Further input blocked)\n" + end + if ($kgm_tty->t_state & 0x00000080) + printf " TS_TIMEOUT (Wait for output char processing)\n" + end + if ($kgm_tty->t_state & 0x00000100) + printf " TS_TTSTOP (Output paused)\n" + end + if ($kgm_tty->t_state & 0x00000200) + printf " TS_WOPEN (Open in progress)\n" + end + if ($kgm_tty->t_state & 0x00000400) + printf " TS_XCLUDE (Tty requires exclusivity)\n" + end + if ($kgm_tty->t_state & 0x00000800) + printf " TS_BKSL (State for lowercase \\ work)\n" + end + if ($kgm_tty->t_state & 0x00001000) + printf " TS_CNTTB (Counting tab width, ignore FLUSHO)\n" + end + if ($kgm_tty->t_state & 0x00002000) + printf " TS_ERASE (Within a \\.../ for PRTRUB)\n" + end + if ($kgm_tty->t_state & 0x00004000) + printf " TS_LNCH (Next character is literal)\n" + end + if ($kgm_tty->t_state & 0x00008000) + printf " TS_TYPEN (Retyping suspended input (PENDIN))\n" + end + if ($kgm_tty->t_state & 0x00010000) + printf " TS_CAN_BYPASS_L_RINT (Device in "raw" mode)\n" + end + if ($kgm_tty->t_state & 0x00020000) + printf " TS_CONNECTED (Connection open)\n" + else + printf " - (Connection NOT open)\n" + end + if ($kgm_tty->t_state & 0x00040000) + printf " TS_SNOOP (Device is being snooped on)\n" + end + if ($kgm_tty->t_state & 0x80000) + printf " TS_SO_OCOMPLETE (Wake up when output completes)\n" + end + if ($kgm_tty->t_state & 0x00100000) + printf " TS_ZOMBIE (Connection lost)\n" + end + if ($kgm_tty->t_state & 0x00200000) + printf " TS_CAR_OFLOW (For MDMBUF - handle in driver)\n" + end + if ($kgm_tty->t_state & 0x00400000) + printf " TS_CTS_OFLOW (For CCTS_OFLOW - handle in driver)\n" + end + if ($kgm_tty->t_state & 0x00800000) + printf " TS_DSR_OFLOW (For CDSR_OFLOW - handle in driver)\n" + end + # xxx todo: do we care about decoding flags? + printf "flags: 0x%08x\n", $kgm_tty->t_flags + printf "foreground process group: " + showptr $kgm_tty->t_pgrp + printf "\n" + printf "enclosing session: " + showptr $kgm_tty->t_session + printf "\n" + printf "Termios:\n" + # XXX todo: decode these flags, someday + printf " Input flags: 0x%08x\n", $kgm_tty->t_termios.c_iflag + printf " Output flags: 0x%08x\n", $kgm_tty->t_termios.c_oflag + printf " Control flags: 0x%08x\n", $kgm_tty->t_termios.c_cflag + printf " Local flags: 0x%08x\n", $kgm_tty->t_termios.c_lflag + printf " Input speed: %d\n", $kgm_tty->t_termios.c_ispeed + printf " Output speed: %d\n", $kgm_tty->t_termios.c_ospeed + # XXX todo: useful to decode t_winsize? t_iokit? c_cc? anything else? + printf "high watermark: %d bytes\n", $kgm_tty->t_hiwat + printf "low watermark: %d bytes\n", $kgm_tty->t_lowat +end + +define _showwhohas + # _showwhohas + printf "fd " + printf "fileglob " +showptrhdrpad + printf "vnode " +showptrhdrpad + printf "process " +showptrhdrpad + printf "name\n" + + set $kgm_swh_devnode_dev = (((int) $arg0) << 24) | (int) $arg1 + # iterate all tasks to iterate all processes to iterate all + # open files in each process to see who has a given major/minor + # device open + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + set $kgm_procp = (proc_t) $kgm_taskp->bsd_info + set $kgm_spf_filedesc = $kgm_procp->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_ofiles != 0) && ($kgm_spf_count <= $kgm_spf_last)) + # only files currently open + if ($kgm_spf_ofiles[$kgm_spf_count] != 0) + set $kgm_spf_fg = $kgm_spf_ofiles[$kgm_spf_count].f_fglob + if ($kgm_spf_fg->fg_type == 1) + # display fd #, fileglob & vnode address, proc name + set $kgm_swh_m_vnode = (vnode_t) $kgm_spf_fg->fg_data + set $kgm_swh_m_vtype = (enum vtype) $kgm_swh_m_vnode->v_type + if (($kgm_swh_m_vtype == VBLK) || ($kgm_swh_m_vtype == VCHR)) && ((((devnode_t *)$kgm_swh_m_vnode->v_data)->dn_typeinfo.dev) == $kgm_swh_devnode_dev) + printf "%-5d ", $kgm_spf_count + showptr $kgm_spf_fg + printf " " + showptr $kgm_swh_m_vnode + printf " " + showptr $kgm_procp + printf " %s\n", $kgm_procp->p_comm + end + end + end + set $kgm_spf_count = $kgm_spf_count + 1 + end + + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end +end + +define _showvnodedev_cpty + set $kgm_ptmx_major = (int) $arg0 + set $kgm_ptmx_minor = (int) $arg1 + set $kgm_ptmx_ioctl = _state.pis_ioctl_list[$kgm_ptmx_minor] + set $kgm_ptmx_ioctl = _state.pis_ioctl_list[$kgm_ptmx_minor] + printf " ptmx_ioctl struct at " + showptr $kgm_ptmx_ioctl + printf "\n" + printf " flags:\n" + if ($kgm_ptmx_ioctl->pt_flags & 0x0008) + printf " PF_PKT (packet mode)\n" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0010) + printf " PF_STOPPED (user told stopped)\n" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0020) + printf " PF_REMOTE (remote and flow controlled input)\n" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0040) + printf " PF_NOSTOP" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0080) + printf " PF_UCNTL (user control mode)\n" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0100) + printf " PF_UNLOCKED (slave unlock - master open resets)\n" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0200) + printf " PF_OPEN_M (master is open)\n" + # XXX we should search for who has the master open, but + # XXX each master gets the same minor, even though it + # XXX gets a different vnode. we chold probably change + # XXX this, but to do it we would need some way of + # XXX expressing the information in the vnode structure + # XXX somewhere. If we *did* change it, it would buy us + # XXX the ability to determine who has the corresponding + # XXX master end of the pty open + else + printf " PF_OPEN_M (master is closed)\n" + end + if ($kgm_ptmx_ioctl->pt_flags & 0x0400) + printf " PF_OPEN_S (slave is open)\n" + printf "---vvvvv--- fds open on this device ---vvvvv---\n" + _showwhohas ($kgm_ptmx_major) ($kgm_ptmx_minor) + printf "---^^^^^--- fds open on this device ---^^^^^---\n" + else + printf " - (slave is closed)\n" + end + printf "TTY Specific Information\n" + _showtty $kgm_ptmx_ioctl->pt_tty +end + +define showvnodedev + if ($argc == 1) + set $kgm_vnode = (vnode_t) $arg0 + set $kgm_vtype = (enum vtype) $kgm_vnode->v_type + if (($kgm_vtype == VBLK) || ($kgm_vtype == VCHR)) + set $kgm_devnode = (devnode_t *) $kgm_vnode->v_data + set $kgm_devnode_dev = $kgm_devnode->dn_typeinfo.dev + set $kgm_devnode_major = ($kgm_devnode_dev >> 24) & 0xff + set $kgm_devnode_minor = $kgm_devnode_dev & 0x00ffffff + + # boilerplate device information for a vnode + printf "Device Info:\n" + printf " vnode: " + showptr $kgm_vnode + printf "\n" + printf " type: " + if ($kgm_vtype == VBLK) + printf "VBLK " + end + if ($kgm_vtype == VCHR) + printf "VCHR" + end + printf "\n" + printf " name: %s\n", $kgm_vnode->v_name + printf " major, minor: %d, %d\n", $kgm_devnode_major, $kgm_devnode_minor + printf " mode 0%o\n", $kgm_devnode->dn_mode + printf " owner (u,g): %d %d", $kgm_devnode->dn_uid, $kgm_devnode->dn_gid + printf "\n" + + # decode device specific data + printf "Device Specific Information: " + if ($kgm_vtype == VBLK) + printf " Sorry, I do not know how to decode block devices yet!\n" + printf " Maybe you can write me!" + end + if ($kgm_vtype == VCHR) + # Device information; this is scanty + # range check + if ($kgm_devnode_major > 42) || ($kgm_devnode_major < 0) + printf "Invalid major #\n" + else + # static assignments in conf + if ($kgm_devnode_major == 0) + printf "Console mux device\n" + else + if ($kgm_devnode_major == 2) + printf "Current tty alias\n" + else + if ($kgm_devnode_major == 3) + printf "NULL device\n" + else + if ($kgm_devnode_major == 4) + printf "Old pty slave\n" + else + if ($kgm_devnode_major == 5) + printf "Old pty master\n" + else + if ($kgm_devnode_major == 6) + printf "Kernel log\n" + else + if ($kgm_devnode_major == 12) + printf "Memory devices\n" + else + # Statically linked dynamic assignments + if cdevsw[$kgm_devnode_major].d_open == ptmx_open + printf "Cloning pty master\n" + _showvnodedev_cpty ($kgm_devnode_major) ($kgm_devnode_minor) + else + if cdevsw[$kgm_devnode_major].d_open == ptsd_open + printf "Cloning pty slave\n" + _showvnodedev_cpty ($kgm_devnode_major) ($kgm_devnode_minor) + else + printf "RESERVED SLOT\n" + end + end + end + end + end + end + end + end + end + end + end + else + showptr $kgm_vnode + printf " is not a device\n" + end + else + printf "| Usage:\n|\n" + help showvnodedev + end +end +document showvnodedev +Syntax: (gdb) showvnodedev +| showvnodedev Display information about a device vnode +end + +define showtty + if ($argc == 1) + _showtty $arg0 + else + printf "| Usage:\n|\n" + help showtty + end +end +document showtty +Syntax: (gdb) showtty +| showtty Display information about a struct tty +end + +define showeventsourceobject + set $kgm_vt = *((void **) $arg1) + if $kgm_lp64 + set $kgm_vt = $kgm_vt - 16 + end + pcprint $kgm_vt +end +document showeventsourceobject +Syntax: (gdb) showeventsourceobject +| Routine to display information about an IOEventSource subclass. +end + +define showworkloopeventsources + set $kgm_eventsource = (struct IOEventSource*)$arg0 + while $kgm_eventsource != 0 + printf " " + printf "EventSource:\t" + showptr $kgm_eventsource + printf " Description: " + showeventsourceobject _ $kgm_eventsource + printf "\n" + if $kgm_eventsource->action != 0 + printf " " + printf "Action: \t" + pcprint $kgm_eventsource->action + printf "\n" + end + if $kgm_eventsource->owner != 0 + printf " " + printf "Owner: \t" + showptr $kgm_eventsource->owner + printf " Description: " + showeventsourceobject _ $kgm_eventsource->owner + printf "\n" + end + set $kgm_eventsource = $kgm_eventsource->eventChainNext + printf "\n" + end +end +document showworkloopeventsources +Syntax: (gdb) showworkloopeventsources +| Routine to walk an IOEventSource chain associated with an IOWorkLoop and print information +| about each event source in the chain. +end + +define showworkloopheader + printf "thread " + showptrhdrpad + printf " workloop " + showptrhdrpad + printf " pri state\tLockGroupName\n" +end +document showworkloopheader +Syntax: (gdb) showworkloopheader +| Routine to print out header info about an IOKit workloop. +end + +define showworkloop + set $kgm_workloopthread = (struct thread*)$arg0 + set $kgm_workloop = (struct IOWorkLoop*)$arg1 + showptr $kgm_workloopthread + printf " " + showptr $kgm_workloop + printf " %3d ", $kgm_workloopthread.sched_pri + set $kgm_state = $kgm_workloopthread.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" + end + printf "\t\t" + set $kgm_gateLock = ( struct _IORecursiveLock *)$kgm_workloop->gateLock + set $kgm_lockGroup = (struct _lck_grp_*)($kgm_gateLock->group) + printf "%s", $kgm_lockGroup->lck_grp_name + printf "\n" + showworkloopeventsources $kgm_workloop->eventChain +end +document showworkloop +Syntax: (gdb) showworkloop +| Routine to print out info about an IOKit workloop. +end + +define showallworkloopthreads + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + set $kgm_head_actp = &($kgm_taskp->threads) + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + while $kgm_actp != $kgm_head_actp + if ($kgm_actp->continuation == _ZN10IOWorkLoop10threadMainEv) + showworkloopheader + showworkloop $kgm_actp $kgm_actp->parameter + else + if ($kgm_actp->kernel_stack != 0) + if ($kgm_mtype == $kgm_mtype_x86_64) + #Warning: Grokking stack looking for hopeful workloops until we squirrel some info in thread_t. + set $kgm_workloop = *((struct IOWorkLoop **)($kgm_actp->kernel_stack + kernel_stack_size - 0xB8)) + else + if ($kgm_mtype == $kgm_mtype_i386) + set $kgm_workloop = *((struct IOWorkLoop **)($kgm_actp->kernel_stack + kernel_stack_size - 0x3C)) + end + end + if ($kgm_workloop != 0) + set $kgm_vt = *((void **) $kgm_workloop) + if $kgm_lp64 + set $kgm_vt = $kgm_vt - 16 + end + if ($kgm_vt == &_ZTV10IOWorkLoop) + showworkloopheader + showworkloop $kgm_actp $kgm_workloop + end + end + end + end + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + end + printf "\n" +end +document showallworkloopthreads +Syntax: (gdb) showallworkloopthreads +| Routine to print out info about all IOKit workloop threads in the system. This macro will find +| all IOWorkLoop threads blocked in continuations and on i386 and x86_64 systems will make a +| best-effort guess to find any workloops that are actually not blocked in a continuation. For a +| complete list, it is best to compare the output of this macro against the output of 'showallstacks'. +end +define showthreadfortid + set $kgm_id_found = 0 + + set $kgm_head_taskp = &tasks + set $kgm_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_taskp != $kgm_head_taskp + set $kgm_head_actp = &($kgm_taskp->threads) + set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) + while $kgm_actp != $kgm_head_actp + set $kgm_thread = *(struct thread *)$kgm_actp + set $kgm_thread_id = $kgm_thread.thread_id + if ($kgm_thread_id == $arg0) + showptr $kgm_actp + printf "\n" + set $kgm_id_found = 1 + loop_break + end + set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) + end + if ($kgm_id_found == 1) + loop_break + end + set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) + end + if ($kgm_id_found == 0) + printf "Not a valid thread_id\n" + end +end + +document showthreadfortid +Syntax: showthreadfortid +|The thread structure contains a unique thread_id value for each thread. +|This command is used to retrieve the address of the thread structure(thread_t) +|corresponding to a given thread_id. +end + +define showtaskbusyports + set $kgm_isp = ((task_t)$arg0)->itk_space + set $kgm_iindex = 0 + while ( $kgm_iindex < $kgm_isp->is_table_size ) + set $kgm_iep = &($kgm_isp->is_table[$kgm_iindex]) + if $kgm_iep->ie_bits & 0x00020000 + set $kgm_port = ((ipc_port_t)$kgm_iep->ie_object) + if $kgm_port->ip_messages.data.port.msgcount > 0 + showport $kgm_port + end + end + set $kgm_iindex = $kgm_iindex + 1 + end +end + +document showtaskbusyports +Syntax: showtaskbusyports +|Routine to print information about receive rights belonging to this task that +|have enqueued messages. This is often a sign of a blocked or hung process. +end + +define showallbusyports + set $kgm_head_taskp = &tasks + set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next) + while $kgm_cur_taskp != $kgm_head_taskp + showtaskbusyports $kgm_cur_taskp + set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->tasks.next) + end +end + +document showallbusyports +Syntax: showallbusyports +|Routine to print information about all receive rights on the system that +|have enqueued messages. end