# Kernel gdb macros # # These gdb macros should be useful during kernel development in # determining what's going on in the kernel. # # All the convenience variables used by these macros begin with $kgm_ set print asm-demangle on set cp-abi gnu-v2 # This option tells gdb to relax its stack tracing heuristics # Useful for debugging across stack switches # (to the interrupt stack, for instance). Requires gdb-675 or greater. set backtrace sanity-checks off echo Loading Kernel GDB Macros package. Type "help kgm" for more info.\n define kgm printf "" echo These are the gdb macros for kernel debugging. Type "help kgm" for more info.\n end document kgm | These are the kernel gdb macros. These gdb macros are intended to be | used when debugging a remote kernel via the kdp protocol. Typically, you | would connect to your remote target like so: | (gdb) target remote-kdp | (gdb) attach | | The following macros are available in this package: | showversion Displays a string describing the remote kernel version | | showalltasks Display a summary listing of all tasks | showallthreads Display info about all threads in the system | showallstacks Display the stack for each thread in the system | showcurrentthreads Display info about the thread running on each cpu | showcurrentstacks Display the stack for the thread running on each cpu | showallvm Display a summary listing of all the vm maps | showallvme Display a summary listing of all the vm map entries | showallipc Display a summary listing of all the ipc spaces | showallrights Display a summary listing of all the ipc rights | showallkmods Display a summary listing of all the kernel modules | showallbusyports Display a listing of all ports with unread messages | | showallclasses Display info about all OSObject subclasses in the system | showobject Show info about an OSObject - its vtable ptr and retain count, & more info for simple container classes. | showregistry Show info about all registry entries in the current plane | showregistryprops Show info about all registry entries in the current plane, and their properties | showregistryentry Show info about a registry entry; its properties and descendants in the current plane | setregistryplane Set the plane to be used for the iokit registry macros (pass zero for list) | | setfindregistrystr Set the encoded string for matching with | findregistryentry or findregistryprop (created from | strcmp_arg_pack64) | findregistryentry Find a registry entry that matches the encoded string | findregistryentries Find all the registry entries that match the encoded string | findregistryprop Search the registry entry for a property that matches | the encoded string | | showtask Display info about the specified task | showtaskthreads Display info about the threads in the task | showtaskstacks Display the stack for each thread in the task | showtaskvm Display info about the specified task's vm_map | showtaskvme Display info about the task's vm_map entries | showtaskipc Display info about the specified task's ipc space | showtaskrights Display info about the task's ipc space entries | showtaskrightsbt Display info about the task's ipc space entries with back traces | showtaskbusyports Display all of the task's ports with unread messages | | showact Display info about a thread specified by activation | showactstack Display the stack for a thread specified by activation | | showmap Display info about the specified vm_map | showmapvme Display a summary list of the specified vm_map's entries | | showipc Display info about the specified ipc space | showrights Display a summary list of all the rights in an ipc space | | showpid Display info about the process identified by pid | showproc Display info about the process identified by proc struct | showprocinfo Display detailed info about the process identified by proc struct | showprocfiles Given a proc_t pointer, display the list of open file descriptors | showproclocks Given a proc_t pointer, display the list of advisory file locks | zombproc Print out all procs in the zombie list | allproc Print out all process in the system not in the zombie list | zombstacks Print out all stacks of tasks that are exiting | | showinitchild Print out all processes in the system which are children of init process | | showkmod Display info about a kernel module | showkmodaddr Given an address, display the kernel module and offset | | dumpcallqueue Dump out all the entries given a queue head | | showallmtx Display info about mutexes usage | showallrwlck Display info about reader/writer locks usage | | zprint Display info about the memory zones | showioalloc Display info about iokit allocations | paniclog Display the panic log info | | switchtoact Switch to different context specified by activation | switchtoctx Switch to different context | showuserstack Display numeric backtrace of the user stack for an | activation | | switchtouserthread Switch to the user context of the specified thread | resetstacks Return to the original kernel context | | resetctx Reset context | resume_on Resume when detaching from gdb | resume_off Don't resume when detaching from gdb | | sendcore Configure kernel to send a coredump to the specified IP | sendsyslog Configure kernel to send a system log to the specified IP | sendpaniclog Configure kernel to send a panic log to the specified IP | disablecore Configure the kernel to disable coredump transmission | getdumpinfo Retrieve the current remote dump parameters | setdumpinfo Configure the remote dump parameters | | switchtocorethread Corefile version of "switchtoact" | resetcorectx Corefile version of "resetctx" | | readphys8 Reads the specified untranslated address (8-bit read) | readphys16 Reads the specified untranslated address (16-bit read) | readphys32 Reads the specified untranslated address (32-bit read) | readphys64 Reads the specified untranslated address (64-bit read) | writephys8 Writes to the specified untranslated address (8-bit write) | writephys16 Writes to the specified untranslated address (16-bit write) | writephys32 Writes to the specified untranslated address (32-bit write) | writephys64 Writes to the specified untranslated address (64-bit write) | | readioport8 Read 8-bits from the specified I/O Port | readioport16 Read 16-bits from the specified I/O Port | readioport32 Read 32-bits from the specified I/O Port | writeioport8 Write 8-bits into the specified I/O Port | writeioport16 Write 16-bits into the specified I/O Port | writeioport32 Write 32-bits into the specified I/O Port | | readmsr64 Read 64-bits from the specified MSR | writemsr64 Write 64-bits into the specified MSR | | rtentry_showdbg Print the debug information of a route entry | rtentry_trash Walk the list of trash route entries | | inifa_showdbg Print the debug information of an IPv4 interface address | in6ifa_showdbg Print the debug information of an IPv6 interface address | | mbuf_walkpkt Walk the mbuf packet chain (m_nextpkt) | mbuf_walk Walk the mbuf chain (m_next) | mbuf_buf2slab Find the slab structure of the corresponding buffer | mbuf_buf2mca Find the mcache audit structure of the corresponding mbuf | mbuf_showmca Print the contents of an mbuf mcache audit structure | mbuf_showactive Print all active/in-use mbuf objects | mbuf_showinactive Print all freed/in-cache mbuf objects | mbuf_showall Print all mbuf objects | mbuf_slabs Print all slabs in the group | mbuf_slabstbl Print slabs table | mbuf_stat Print extended mbuf allocator statistics | | mcache_walkobj Walk the mcache object chain (obj_next) | mcache_stat Print all mcaches in the system | mcache_showcache Display the number of objects in the cache | | showbootargs Display boot arguments passed to the target kernel | showbootermemorymap Dump phys memory map from EFI | | systemlog Display the kernel's printf ring buffer | | hexdump Show the contents of memory as a hex/ASCII dump | | showvnodepath Print the path for a vnode | showvnodelocks Display list of advisory locks held/blocked on a vnode | showvnodedev Display information about a device vnode | showtty Display information about a struct tty | showallvols Display a summary of mounted volumes | showvnode Display info about one vnode | showvolvnodes Display info about all vnodes of a given volume | showvolbusyvnodes Display info about busy (iocount!=0) vnodes of a given volume | showallbusyvnodes Display info about all busy (iocount!=0) vnodes | showallvnodes Display info about all vnodes | print_vnode Print out the fields of a vnode struct | showprocvnodes Print out all the open fds which are vnodes in a process | showallprocvnodes Print out all the open fds which are vnodes in any process | showmountvnodes Print the vnode list | showmountallvnodes Print the vnode inactive list | showworkqvnodes Print the vnode worker list | shownewvnodes Print the new vnode list | | ifconfig display ifconfig-like output | showifaddrs show the list of addresses for the given ifp | showifmultiaddrs show the list of multicast addresses for the given ifp | | showsocket Display information about a socket | showprocsockets Given a proc_t pointer, display information about its sockets | showallprocsockets Display information about the sockets of all the processes | | show_tcp_pcbinfo Display the list of the TCP protocol control blocks | show_tcp_timewaitslots Display the list of the TCP protocol control blocks in TIMEWAIT | show_udp_pcbinfo Display the list of UDP protocol control blocks | | show_rt_inet Display the IPv4 routing table | show_rt_inet6 Display the IPv6 routing table | | showallpmworkqueues Display info about all IOPMWorkQueue objects | showregistrypmstate Display power management state for all IOPower registry entries | showioservicepm Display the IOServicePM object | showstacksaftertask showallstacks starting after a given task | showstacksafterthread showallstacks starting after a given thread | | showMCAstate Print machine-check register state after MC exception. | | showallgdbstacks Cause GDB to trace all thread stacks | showallgdbcorestacks Corefile equivalent of "showallgdbstacks" | kdp-reenter Schedule reentry into the debugger and continue. | kdp-reboot Restart remote target | kdp-version Get KDP version number | kdp-connect "shorthand" connection macro | | zstack Print zalloc caller stack (zone leak debugging) | findoldest Find oldest zone leak debugging record | countpcs Print how often a pc occurs in the zone leak log | | pmap_walk Perform a page-table walk | pmap_vtop Translate a virtual address to physical address | | showuserlibraries Show binary images known by dyld in the target task | | showthreadfortid Displays the address of the thread structure for a given thread_id value. | | strcmp_nomalloc A version of strcmp that avoids the use of malloc | through the use of encoded strings created via | strcmp_arg_pack64. | strcmp_arg_pack64 Pack a string into a 64-bit quantity for use by | strcmp_nomalloc | | pci_cfg_read8 Read 8-bits from a PCI config space register | pci_cfg_read16 Read 16-bits from a PCI config space register | pci_cfg_read32 Read 32-bits from a PCI config space register | pci_cfg_write8 Write 8-bits into a PCI config space register | pci_cfg_write16 Write 16-bits into a PCI config space register | pci_cfg_write32 Write 32-bits into a PCI config space register | pci_cfg_dump Dump entire config space for a PCI device | pci_cfg_scan Perform a scan for PCI devices | pci_cfg_dump_all Dump config spaces for all detected PCI devices | | lapic_read32 Read APIC entry | lapic_write32 Write APIC entry | lapic_dump Dump APIC entries | | ioapic_read32 Read IOAPIC entry | ioapic_write32 Write IOAPIC entry | ioapic_dump Dump IOAPIC entries | | Type "help " 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_manual_pkt_ppc = 0x549C set $kgm_manual_pkt_i386 = 0x249C set $kgm_manual_pkt_x86_64 = 0xFFFFFF8000002930 set $kgm_manual_pkt_arm = 0xFFFF04A0 set $kgm_kdp_pkt_data_len = 128 # part of data packet set $kgm_kdp_pkt_hdr_req_off = 0 set $kgm_kdp_pkt_hdr_seq_off = 1 set $kgm_kdp_pkt_hdr_len_off = 2 set $kgm_kdp_pkt_hdr_key_off = 4 # after data packet set $kgm_kdp_pkt_len_off = $kgm_kdp_pkt_data_len set $kgm_kdp_pkt_input_off = $kgm_kdp_pkt_data_len + 4 set $kgm_kdp_pkt_hostreboot = 0x13 set $kgm_kdp_pkt_hdr_size = 8 set $kgm_lcpu_self = 0xFFFE set $kgm_reg_depth = 0 set $kgm_reg_depth_max = 0xFFFF set $kgm_reg_plane = (IORegistryPlane *) gIOServicePlane set $kgm_namekey = (OSSymbol *) 0 set $kgm_childkey = (OSSymbol *) 0 set $kgm_show_object_addrs = 0 set $kgm_show_object_retain = 0 set $kgm_show_props = 0 set $kgm_show_data_alwaysbytes = 0 set $kgm_show_kmod_syms = 0 # send a manual packet header that doesn't require knowing the location # of everything. define manualhdrint set $req = $arg0 set $hdrp = (uint32_t *) $kgm_manual_pkt_i386 if ($kgm_mtype == $kgm_mtype_ppc) set $hdrp = (uint32_t *) $kgm_manual_pkt_ppc set $req = $req << 1 # shift to deal with endiannness end if ($kgm_mtype == $kgm_mtype_x86_64) set $hdrp = (uint64_t *) $kgm_manual_pkt_x86_64 end if ($kgm_mtype == $kgm_mtype_arm) set $hdrp = (uint32_t *) $kgm_manual_pkt_arm end set $pkt_hdr = *$hdrp set *((uint8_t *) ($pkt_hdr + $kgm_kdp_pkt_input_off)) = 0 set *((uint32_t *) ($pkt_hdr + $kgm_kdp_pkt_len_off)) = $kgm_kdp_pkt_hdr_size set *((uint8_t *) ($pkt_hdr + $kgm_kdp_pkt_hdr_req_off)) = $req set *((uint8_t *) ($pkt_hdr + $kgm_kdp_pkt_hdr_seq_off)) = 0 set *((uint16_t *) ($pkt_hdr + $kgm_kdp_pkt_hdr_len_off)) = $kgm_kdp_pkt_hdr_size set *((uint32_t *) ($pkt_hdr + $kgm_kdp_pkt_hdr_key_off)) = 0 set *((uint8_t *) ($pkt_hdr + $kgm_kdp_pkt_input_off)) = 1 # dummy to make sure manual packet is executed set $kgm_dummy = &_mh_execute_header end # Print a pointer define showptr if $kgm_lp64 printf "0x%016llx", $arg0 else printf "0x%08x", $arg0 end end # for headers, leave 8 chars for LP64 pointers define showptrhdrpad if $kgm_lp64 printf " " end end define showkmodheader printf "kmod " showptrhdrpad printf " address " showptrhdrpad printf " size " showptrhdrpad printf " id refs version name\n" end define showkmodint set $kgm_kmodp = (struct kmod_info *)$arg0 showptr $kgm_kmodp printf " " showptr $kgm_kmodp->address printf " " showptr $kgm_kmodp->size printf " " printf "%3d ", $kgm_kmodp->id printf "%5d ", $kgm_kmodp->reference_count printf "%10s ", $kgm_kmodp->version printf "%s\n", $kgm_kmodp->name end # cached info of the last kext found, to speed up subsequent lookups set $kgm_pkmod = 0 set $kgm_pkmodst = 0 set $kgm_pkmoden = 0 define showkmodaddrint showptr $arg0 if ((unsigned long)$arg0 >= (unsigned long)$kgm_pkmodst) && ((unsigned long)$arg0 < (unsigned long)$kgm_pkmoden) set $kgm_off = ((unsigned long)$arg0 - (unsigned long)$kgm_pkmodst) printf " <%s + 0x%x>", $kgm_pkmod->name, $kgm_off else set $kgm_kmodp = (struct kmod_info *)kmod if ($kgm_mtype == $kgm_mtype_x86_64) && ($arg0 >= (unsigned long)&_mh_execute_header) # kexts are loaded below the kernel for x86_64 set $kgm_kmodp = 0 end while $kgm_kmodp set $kgm_off = ((unsigned long)$arg0 - (unsigned long)$kgm_kmodp->address) if ($kgm_kmodp->address <= $arg0) && ($kgm_off < $kgm_kmodp->size) printf " <%s + 0x%x>", $kgm_kmodp->name, $kgm_off set $kgm_pkmod = $kgm_kmodp set $kgm_pkmodst = $kgm_kmodp->address set $kgm_pkmoden = $kgm_pkmodst + $kgm_kmodp->size set $kgm_kmodp = 0 else set $kgm_kmodp = $kgm_kmodp->next end end end end define showkmodaddr showkmodaddrint $arg0 end document showkmodaddr Syntax: (gdb) showkmodaddr | Given an address, print the offset and name for the kmod containing it end define showkmod showkmodheader showkmodint $arg0 end document showkmod Syntax: (gdb) showkmod | Routine to print info about a kernel module end define showallkmods showkmodheader set $kgm_kmodp = (struct kmod_info *)kmod while $kgm_kmodp showkmodint $kgm_kmodp set $kgm_kmodp = $kgm_kmodp->next end end document showallkmods Syntax: (gdb) showallkmods | Routine to print a summary listing of all the kernel modules end define showactheader printf " " showptrhdrpad printf " thread " showptrhdrpad printf " thread_id " showptrhdrpad printf " processor " showptrhdrpad printf " pri io_policy state wait_queue" showptrhdrpad printf " wait_event\n" end define showactint printf " " showptrhdrpad set $kgm_thread = *(struct thread *)$arg0 showptr $arg0 if ($kgm_thread.static_param) printf "[WQ]" else printf " " end printf " %7ld ", $kgm_thread.thread_id showptr $kgm_thread.last_processor printf " %3d ", $kgm_thread.sched_pri if ($kgm_thread.uthread != 0) set $kgm_printed = 0 set $kgm_uthread = (struct uthread *)$kgm_thread.uthread if ($kgm_uthread->uu_flag & 0x400) printf "RAGE " else printf " " end if ($kgm_uthread->uu_iopol_disk == 1) printf "NORM " set $kgm_printed = 1 end if ($kgm_uthread->uu_iopol_disk == 2) printf "PASS " set $kgm_printed = 1 end if ($kgm_uthread->uu_iopol_disk == 3) printf "THROT " set $kgm_printed = 1 end if ($kgm_printed == 0) printf " " end end set $kgm_state = $kgm_thread.state if $kgm_state & 0x80 printf "I" end if $kgm_state & 0x40 printf "P" end if $kgm_state & 0x20 printf "A" end if $kgm_state & 0x10 printf "H" end if $kgm_state & 0x08 printf "U" end if $kgm_state & 0x04 printf "R" end if $kgm_state & 0x02 printf "S" end if $kgm_state & 0x01 printf "W" printf "\t " showptr $kgm_thread.wait_queue printf " " if (((unsigned long)$kgm_thread.wait_event > (unsigned long)&last_kernel_symbol) \ && ($arg1 != 2) && ($kgm_show_kmod_syms == 0)) showkmodaddr $kgm_thread.wait_event else output /a $kgm_thread.wait_event end if ($kgm_thread.uthread != 0) set $kgm_uthread = (struct uthread *)$kgm_thread.uthread if ($kgm_uthread->uu_wmesg != 0) printf "\t \"%s\"", $kgm_uthread->uu_wmesg end end end if $arg1 != 0 if ($kgm_thread.kernel_stack != 0) if ($kgm_thread.reserved_stack != 0) printf "\n " showptrhdrpad printf " reserved_stack=" showptr $kgm_thread.reserved_stack end printf "\n " showptrhdrpad printf " kernel_stack=" showptr $kgm_thread.kernel_stack if ($kgm_mtype == $kgm_mtype_ppc) set $mysp = $kgm_thread.machine.pcb->save_r1 end if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) set $kgm_statep = (struct x86_kernel_state *) \ ($kgm_thread->kernel_stack + kernel_stack_size \ - sizeof(struct x86_kernel_state)) if ($kgm_mtype == $kgm_mtype_i386) set $mysp = $kgm_statep->k_ebp else set $mysp = $kgm_statep->k_rbp end end if ($kgm_mtype == $kgm_mtype_arm) if (((unsigned long)$r7 < ((unsigned long) ($kgm_thread->kernel_stack+kernel_stack_size))) \ && ((unsigned long)$r7 > (unsigned long) ($kgm_thread->kernel_stack))) set $mysp = $r7 else set $kgm_statep = (struct arm_saved_state *)$kgm_thread.machine.kstackptr set $mysp = $kgm_statep->r[7] end end set $prevsp = $mysp - 16 printf "\n " showptrhdrpad printf " stacktop=" showptr $mysp if ($kgm_mtype == $kgm_mtype_ppc) set $stkmask = 0xf else set $stkmask = 0x3 end set $kgm_return = 0 while ($mysp != 0) && (($mysp & $stkmask) == 0) \ && ($mysp != $prevsp) \ && ((((unsigned long) $mysp ^ (unsigned long) $prevsp) < 0x2000) \ || (((unsigned long)$mysp < ((unsigned long) ($kgm_thread->kernel_stack+kernel_stack_size))) \ && ((unsigned long)$mysp > (unsigned long) ($kgm_thread->kernel_stack)))) printf "\n " showptrhdrpad printf " " showptr $mysp printf " " if ($kgm_mtype == $kgm_mtype_ppc) set $kgm_return = *($mysp + 8) end if ($kgm_mtype == $kgm_mtype_i386) set $kgm_return = *($mysp + 4) end if ($kgm_mtype == $kgm_mtype_x86_64) set $kgm_return = *(unsigned long *)($mysp + 8) end if ($kgm_mtype == $kgm_mtype_arm) set $kgm_return = *($mysp + 4) end if (((unsigned long) $kgm_return < (unsigned long) &_mh_execute_header || \ (unsigned long) $kgm_return >= (unsigned long) &last_kernel_symbol ) \ && ($kgm_show_kmod_syms == 0)) showkmodaddr $kgm_return else output /a $kgm_return end set $prevsp = $mysp set $mysp = *(unsigned long *)$mysp end set $kgm_return = 0 printf "\n " showptrhdrpad printf " stackbottom=" showptr $prevsp else printf "\n " showptrhdrpad printf " continuation=" output /a $kgm_thread.continuation end printf "\n" else printf "\n" end end define showact showactheader showactint $arg0 0 end document showact Syntax: (gdb) showact | Routine to print out the state of a specific thread. end define showactstack showactheader showactint $arg0 1 end document showactstack Syntax: (gdb) showactstack | Routine to print out the stack of a specific thread. end define showallthreads set $kgm_head_taskp = &tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader showtaskint $kgm_taskp showactheader set $kgm_head_actp = &($kgm_taskp->threads) set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) while $kgm_actp != $kgm_head_actp showactint $kgm_actp 0 set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) end printf "\n" set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) end end document showallthreads Syntax: (gdb) showallthreads | Routine to print out info about all threads in the system. end define showcurrentthreads set $kgm_prp = (struct processor *)processor_list while $kgm_prp != 0 printf "Processor 0x%08x State %d (cpu_id %x)\n", $kgm_prp, ($kgm_prp)->state, ($kgm_prp)->cpu_id if ($kgm_prp)->active_thread != 0 set $kgm_actp = ($kgm_prp)->active_thread showtaskheader showtaskint ($kgm_actp)->task showactheader showactint $kgm_actp 0 printf "\n" end set $kgm_prp = ($kgm_prp)->processor_list end end document showcurrentthreads Syntax: (gdb) showcurrentthreads | Routine to print out info about the thread running on each cpu. end set $decode_wait_events = 0 define showallstacks set $kgm_head_taskp = &tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader showtaskint $kgm_taskp set $kgm_head_actp = &($kgm_taskp->threads) set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) while $kgm_actp != $kgm_head_actp showactheader if ($decode_wait_events > 0) showactint $kgm_actp 1 else showactint $kgm_actp 2 end set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) end printf "\n" set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) end end document showallstacks Syntax: (gdb) showallstacks | Routine to print out the stack for each thread in the system. | If the variable $decode_wait_events is non-zero, the routine attempts to | interpret thread wait_events as kernel module offsets, which can add to | processing time. end define showcurrentstacks set $kgm_prp = processor_list while $kgm_prp != 0 printf "Processor 0x%08x State %d (cpu_id %x)\n", $kgm_prp, ($kgm_prp)->state, ($kgm_prp)->cpu_id if ($kgm_prp)->active_thread != 0 set $kgm_actp = ($kgm_prp)->active_thread showtaskheader showtaskint ($kgm_actp)->task showactheader showactint $kgm_actp 1 printf "\n" end set $kgm_prp = ($kgm_prp)->processor_list end end document showcurrentstacks Syntax: (gdb) showcurrentstacks | Routine to print out the thread running on each cpu (incl. its stack) end define showwaiterheader printf "waiters thread " printf "processor pri state wait_queue wait_event\n" end define showwaitqwaiters set $kgm_w_waitqp = (WaitQueue*)$arg0 set $kgm_w_linksp = &($kgm_w_waitqp->wq_queue) set $kgm_w_wqe = (WaitQueueElement *)$kgm_w_linksp->next set $kgm_w_found = 0 while ( (queue_entry_t)$kgm_w_wqe != (queue_entry_t)$kgm_w_linksp) if ($kgm_w_wqe->wqe_type != &_wait_queue_link) if !$kgm_w_found set $kgm_w_found = 1 showwaiterheader end set $kgm_w_shuttle = (struct thread *)$kgm_w_wqe showactint $kgm_w_shuttle 0 end set $kgm_w_wqe = (WaitQueueElement *)$kgm_w_wqe->wqe_links.next end end define showwaitqwaitercount set $kgm_wc_waitqp = (WaitQueue*)$arg0 set $kgm_wc_linksp = &($kgm_wc_waitqp->wq_queue) set $kgm_wc_wqe = (WaitQueueElement *)$kgm_wc_linksp->next set $kgm_wc_count = 0 while ( (queue_entry_t)$kgm_wc_wqe != (queue_entry_t)$kgm_wc_linksp) if ($kgm_wc_wqe->wqe_type != &_wait_queue_link) && ($kgm_wc_wqe->wqe_type != &_wait_queue_link_noalloc) set $kgm_wc_count = $kgm_wc_count + 1 end set $kgm_wc_wqe = (WaitQueueElement *)$kgm_wc_wqe->wqe_links.next end printf "0x%08x ", $kgm_wc_count end define showwaitqmembercount set $kgm_mc_waitqsetp = (struct wait_queue_set *)$arg0 set $kgm_mc_setlinksp = &($kgm_mc_waitqsetp->wqs_setlinks) set $kgm_mc_wql = (WaitQueueLink *)$kgm_mc_setlinksp->next set $kgm_mc_count = 0 while ( (queue_entry_t)$kgm_mc_wql != (queue_entry_t)$kgm_mc_setlinksp) set $kgm_mc_count = $kgm_mc_count + 1 set $kgm_mc_wql = (WaitQueueLink *)$kgm_mc_wql->wql_setlinks.next end printf "0x%08x ", $kgm_mc_count end define showwaitqmemberheader printf "set-members wait_queue interlock " printf "pol type member_cnt waiter_cnt\n" end define showwaitqmemberint set $kgm_m_waitqp = (WaitQueue*)$arg0 printf " 0x%08x ", $kgm_m_waitqp printf "0x%08x ", $kgm_m_waitqp->wq_interlock.lock_data if ($kgm_m_waitqp->wq_fifo) printf "Fifo " else printf "Prio " end if ($kgm_m_waitqp->wq_type == 0xf1d1) printf "Set " showwaitqmembercount $kgm_m_waitqp else printf "Que 0x00000000 " end showwaitqwaitercount $kgm_m_waitqp printf "\n" end define showwaitqmemberofheader printf "member-of wait_queue interlock " printf "pol type member_cnt waiter_cnt\n" end define showwaitqmemberof set $kgm_mo_waitqp = (WaitQueue*)$arg0 set $kgm_mo_linksp = &($kgm_mo_waitqp->wq_queue) set $kgm_mo_wqe = (WaitQueueElement *)$kgm_mo_linksp->next set $kgm_mo_found = 0 while ( (queue_entry_t)$kgm_mo_wqe != (queue_entry_t)$kgm_mo_linksp) if ($kgm_mo_wqe->wqe_type == &_wait_queue_link) if !$kgm_mo_found set $kgm_mo_found = 1 showwaitqmemberofheader end set $kgm_mo_wqlp = (WaitQueueLink *)$kgm_mo_wqe set $kgm_mo_wqsetp = (WaitQueue*)($kgm_mo_wqlp->wql_setqueue) showwaitqmemberint $kgm_mo_wqsetp end set $kgm_mo_wqe = (WaitQueueElement *)$kgm_mo_wqe->wqe_links.next end end define showwaitqmembers set $kgm_ms_waitqsetp = (struct wait_queue_set *)$arg0 set $kgm_ms_setlinksp = &($kgm_ms_waitqsetp->wqs_setlinks) set $kgm_ms_wql = (WaitQueueLink *)$kgm_ms_setlinksp->next set $kgm_ms_found = 0 while ( (queue_entry_t)$kgm_ms_wql != (queue_entry_t)$kgm_ms_setlinksp) set $kgm_ms_waitqp = $kgm_ms_wql->wql_element.wqe_queue if !$kgm_ms_found showwaitqmemberheader set $kgm_ms_found = 1 end showwaitqmemberint $kgm_ms_waitqp set $kgm_ms_wql = (WaitQueueLink *)$kgm_ms_wql->wql_setlinks.next end end define showwaitqheader printf "wait_queue prepostq interlock " printf "pol type member_cnt waiter_cnt\n" end define showwaitqint set $kgm_waitqp = (WaitQueue *)$arg0 printf "0x%08x ", $kgm_waitqp if ($kgm_waitqp->wq_type == 0xf1d1) printf "0x%08x ", &((struct wait_queue_set *)$kgm_waitqp)->wqs_preposts else printf "0x00000000 " end printf "0x%08x ", $kgm_waitqp->wq_interlock.lock_data if ($kgm_waitqp->wq_fifo) printf "Fifo " else printf "Prio " end if ($kgm_waitqp->wq_type == 0xf1d1) printf "Set " showwaitqmembercount $kgm_waitqp else printf "Que 0x00000000 " end showwaitqwaitercount $kgm_waitqp printf "\n" end define showwaitq set $kgm_waitq1p = (WaitQueue*)$arg0 showwaitqheader showwaitqint $kgm_waitq1p if ($kgm_waitq1p->wq_type == 0xf1d1) showwaitqmembers $kgm_waitq1p else showwaitqmemberof $kgm_waitq1p end showwaitqwaiters $kgm_waitq1p end define showmapheader printf "vm_map " showptrhdrpad printf " pmap " showptrhdrpad printf " vm_size " showptrhdrpad printf " #ents rpage hint " showptrhdrpad printf " first_free\n" end define showvmeheader printf " entry " showptrhdrpad printf " start prot #page object " showptrhdrpad printf " offset\n" end define showvmint set $kgm_mapp = (vm_map_t)$arg0 set $kgm_map = *$kgm_mapp showptr $arg0 printf " " showptr $kgm_map.pmap printf " " showptr $kgm_map.size printf " %3d ", $kgm_map.hdr.nentries if $kgm_map.pmap printf "%5d ", $kgm_map.pmap->stats.resident_count else printf " " end showptr $kgm_map.hint printf " " showptr $kgm_map.first_free printf "\n" if $arg1 != 0 showvmeheader set $kgm_head_vmep = &($kgm_mapp->hdr.links) set $kgm_vmep = $kgm_map.hdr.links.next while (($kgm_vmep != 0) && ($kgm_vmep != $kgm_head_vmep)) set $kgm_vme = *$kgm_vmep printf " " showptr $kgm_vmep printf " 0x%016llx ", $kgm_vme.links.start printf "%1x", $kgm_vme.protection printf "%1x", $kgm_vme.max_protection if $kgm_vme.inheritance == 0x0 printf "S" end if $kgm_vme.inheritance == 0x1 printf "C" end if $kgm_vme.inheritance == 0x2 printf "-" end if $kgm_vme.inheritance == 0x3 printf "D" end if $kgm_vme.is_sub_map printf "s " else if $kgm_vme.needs_copy printf "n " else printf " " end end printf "%6d ",($kgm_vme.links.end - $kgm_vme.links.start) >> 12 showptr $kgm_vme.object.vm_object printf " 0x%016llx\n", $kgm_vme.offset set $kgm_vmep = $kgm_vme.links.next end end printf "\n" end define showmapwiredp set $kgm_mapp = (vm_map_t)$arg0 set $kgm_map = *$kgm_mapp set $kgm_head_vmep = &($kgm_mapp->hdr.links) set $kgm_vmep = $kgm_map.hdr.links.next set $kgm_objp_prev = (struct vm_object *)0 if $arg1 == 0 set $kgm_saw_kernel_obj = 0 set $kgm_wired_count = 0 set $kgm_objp_print_space = 1 else set $kgm_objp_print_space = 0 end while (($kgm_vmep != 0) && ($kgm_vmep != $kgm_head_vmep)) set $kgm_vme = *$kgm_vmep set $kgm_objp = $kgm_vme.object.vm_object if $kgm_vme.is_sub_map if $arg1 == 0 set $kgm_mapp_orig = $kgm_mapp set $kgm_vmep_orig = $kgm_vmep set $kgm_vme_orig = $kgm_vme set $kgm_head_vmep_orig = $kgm_head_vmep printf "\n****" showptr $kgm_objp showmapwiredp $kgm_objp 1 set $kgm_vme = $kgm_vme_orig set $kgm_vmep = $kgm_vmep_orig set $kgm_mapp = $kgm_mapp_orig set $kgm_head_vmep = $kgm_head_vmep_orig set $kgm_objp = (struct vm_object *)0 else printf "\n????" showptr $kgm_mapp printf " " showptr $kgm_vmep set $kgm_objp = (struct vm_object *)0 printf "\n" end end if ($kgm_objp == $kgm_objp_prev) set $kgm_objp = (struct vm_object *)0 end if $kgm_objp == kernel_object if $kgm_saw_kernel_obj set $kgm_objp = (struct vm_object *)0 end set $kgm_saw_kernel_obj = 1 end if $kgm_objp && $kgm_objp->wired_page_count if $kgm_objp_print_space == 1 printf " " showptr $kgm_mapp end set $kgm_objp_print_space = 1 printf " " showptr $kgm_vmep printf " 0x%016llx ", $kgm_vme.links.start printf "%5d", $kgm_vme.alias printf "%6d ",($kgm_vme.links.end - $kgm_vme.links.start) >> 12 showptr $kgm_objp printf "[%3d]", $kgm_objp->ref_count printf "%7d\n", $kgm_objp->wired_page_count set $kgm_wired_count = $kgm_wired_count + $kgm_objp->wired_page_count set $kgm_objp_prev = $kgm_objp end set $kgm_vmep = $kgm_vme.links.next end if $arg1 == 0 printf "total wired count = %d\n", $kgm_wired_count end end define showmapwired printf " map " showptrhdrpad printf " entry " showptrhdrpad printf " start alias #page object " showptrhdrpad printf " wired\n" showmapwiredp $arg0 0 end document showmapwired Syntax: (gdb) showmapwired | Routine to print out a summary listing of all the entries with wired pages in a vm_map end define showmapvme showmapheader showvmint $arg0 1 end document showmapvme Syntax: (gdb) showmapvme | Routine to print out a summary listing of all the entries in a vm_map end define showmap showmapheader showvmint $arg0 0 end document showmap Syntax: (gdb) showmap | Routine to print out info about the specified vm_map end define showallvm set $kgm_head_taskp = &tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader showmapheader showtaskint $kgm_taskp showvmint $kgm_taskp->map 0 set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) end end document showallvm Syntax: (gdb) showallvm | Routine to print a summary listing of all the vm maps end define showallvme set $kgm_head_taskp = &tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader showmapheader showtaskint $kgm_taskp showvmint $kgm_taskp->map 1 set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) end end document showallvme Syntax: (gdb) showallvme | Routine to print a summary listing of all the vm map entries end define showipcheader printf "ipc_space " showptrhdrpad printf " is_table " showptrhdrpad printf " table_next" showptrhdrpad printf " flags tsize splaytree splaybase\n" end define showipceheader printf " name object " showptrhdrpad printf " rite urefs destname destination\n" end define showipceint set $kgm_ie = *(ipc_entry_t)$arg0 printf " 0x%08x ", $arg1 showptr $kgm_ie.ie_object printf " " if $kgm_ie.ie_bits & 0x00100000 printf "Dead " printf "%5d\n", $kgm_ie.ie_bits & 0xffff else if $kgm_ie.ie_bits & 0x00080000 printf "SET " printf "%5d\n", $kgm_ie.ie_bits & 0xffff else if $kgm_ie.ie_bits & 0x00010000 if $kgm_ie.ie_bits & 0x00020000 printf " SR" else printf " S" end else if $kgm_ie.ie_bits & 0x00020000 printf " R" end end if $kgm_ie.ie_bits & 0x00040000 printf " O" end if $kgm_ie.index.request printf "n" else printf " " end if $kgm_ie.ie_bits & 0x00800000 printf "c" else printf " " end printf "%5d ", $kgm_ie.ie_bits & 0xffff showportdest $kgm_ie.ie_object end end end define showipcint set $kgm_isp = (ipc_space_t)$arg0 set $kgm_is = *$kgm_isp showptr $arg0 printf " " showptr $kgm_is.is_table printf " " showptr $kgm_is.is_table_next printf " " if $kgm_is.is_growing != 0 printf "G" else printf " " end if $kgm_is.is_fast != 0 printf "F" else printf " " end if $kgm_is.is_active != 0 printf "A " else printf " " end printf "%5d ", $kgm_is.is_table_size printf "0x%08x ", $kgm_is.is_tree_total showptr &$kgm_isp->is_tree printf "\n" if $arg1 != 0 showipceheader set $kgm_iindex = 0 set $kgm_iep = $kgm_is.is_table set $kgm_destspacep = (ipc_space_t)0 while ( $kgm_iindex < $kgm_is.is_table_size ) set $kgm_ie = *$kgm_iep if $kgm_ie.ie_bits & 0x001f0000 set $kgm_name = (($kgm_iindex << 8)|($kgm_ie.ie_bits >> 24)) showipceint $kgm_iep $kgm_name if $arg2 != 0 && ipc_portbt != 0 if $kgm_ie.ie_object != 0 && ($kgm_ie.ie_bits & 0x00070000) && ((ipc_port_t) $kgm_ie.ie_object)->ip_callstack[0] != 0 printf " user bt: " showportbt $kgm_ie.ie_object $kgm_is.is_task end end end set $kgm_iindex = $kgm_iindex + 1 set $kgm_iep = &($kgm_is.is_table[$kgm_iindex]) end if $kgm_is.is_tree_total printf "Still need to write tree traversal\n" end end printf "\n" end define showipc set $kgm_isp = (ipc_space_t)$arg0 showipcheader showipcint $kgm_isp 0 0 end document showipc Syntax: (gdb) showipc | Routine to print the status of the specified ipc space end define showrights set $kgm_isp = (ipc_space_t)$arg0 showipcheader showipcint $kgm_isp 1 0 end document showrights Syntax: (gdb) showrights | Routine to print a summary list of all the rights in a specified ipc space end define showtaskipc set $kgm_taskp = (task_t)$arg0 showtaskheader showipcheader showtaskint $kgm_taskp showipcint $kgm_taskp->itk_space 0 0 end document showtaskipc Syntax: (gdb) showtaskipc | Routine to print info about the ipc space for a task end define showtaskrights set $kgm_taskp = (task_t)$arg0 showtaskheader showipcheader showtaskint $kgm_taskp showipcint $kgm_taskp->itk_space 1 0 end document showtaskrights Syntax: (gdb) showtaskrights | Routine to print info about the ipc rights for a task end define showtaskrightsbt set $kgm_taskp = (task_t)$arg0 showtaskheader showipcheader showtaskint $kgm_taskp showipcint $kgm_taskp->itk_space 1 1 end document showtaskrightsbt Syntax: (gdb) showtaskrightsbt | Routine to print info about the ipc rights for a task with backtraces end define showallipc set $kgm_head_taskp = &tasks set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_cur_taskp != $kgm_head_taskp showtaskheader showipcheader showtaskint $kgm_cur_taskp showipcint $kgm_cur_taskp->itk_space 0 0 set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->tasks.next) end end document showallipc Syntax: (gdb) showallipc | Routine to print a summary listing of all the ipc spaces end define showallrights set $kgm_head_taskp = &tasks set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_cur_taskp != $kgm_head_taskp showtaskheader showipcheader showtaskint $kgm_cur_taskp showipcint $kgm_cur_taskp->itk_space 1 0 set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->tasks.next) end end document showallrights Syntax: (gdb) showallrights | Routine to print a summary listing of all the ipc rights end define showtaskvm set $kgm_taskp = (task_t)$arg0 showtaskheader showmapheader showtaskint $kgm_taskp showvmint $kgm_taskp->map 0 end document showtaskvm Syntax: (gdb) showtaskvm | Routine to print out info about a task's vm_map end define showtaskvme set $kgm_taskp = (task_t)$arg0 showtaskheader showmapheader showtaskint $kgm_taskp showvmint $kgm_taskp->map 1 end document showtaskvme Syntax: (gdb) showtaskvme | Routine to print out info about a task's vm_map_entries end define showtaskheader printf "task " showptrhdrpad printf " vm_map " showptrhdrpad printf " ipc_space " showptrhdrpad printf " #acts " showprocheader end define showtaskint set $kgm_taskp = (struct task *)$arg0 showptr $arg0 printf " " showptr $kgm_taskp->map printf " " showptr $kgm_taskp->itk_space printf " %5d ", $kgm_taskp->thread_count showprocint $kgm_taskp->bsd_info end define showtask showtaskheader showtaskint $arg0 end document showtask Syntax (gdb) showtask | Routine to print out info about a task. end define showtaskthreads showtaskheader set $kgm_taskp = (struct task *)$arg0 showtaskint $kgm_taskp showactheader set $kgm_head_actp = &($kgm_taskp->threads) set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) while $kgm_actp != $kgm_head_actp showactint $kgm_actp 0 set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) end end document showtaskthreads Syntax: (gdb) showtaskthreads | Routine to print info about the threads in a task. end define showtaskstacks showtaskheader set $kgm_taskp = (struct task *)$arg0 showtaskint $kgm_taskp set $kgm_head_actp = &($kgm_taskp->threads) set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) while $kgm_actp != $kgm_head_actp showactheader showactint $kgm_actp 1 set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) end end document showtaskstacks Syntax: (gdb) showtaskstacks | Routine to print out the stack for each thread in a task. end define showalltasks showtaskheader set $kgm_head_taskp = &tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskint $kgm_taskp set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) end end document showalltasks Syntax: (gdb) showalltasks | Routine to print a summary listing of all the tasks | wq_state -> reports "number of workq threads", "number of scheduled workq threads", "number of pending work items" | if "number of pending work items" seems stuck at non-zero, it may indicate that the workqueue mechanism is hung | io_policy -> RAGE - rapid aging of vnodes requested | NORM - normal I/O explicitly requested (this is the default) | PASS - passive I/O requested (i.e. I/Os do not affect throttling decisions) | THROT - throttled I/O requested (i.e. thread/task may be throttled after each I/O completes) end define showprocheader printf " pid process io_policy wq_state" showptrhdrpad printf " command\n" end define showprocint set $kgm_procp = (struct proc *)$arg0 if $kgm_procp != 0 set $kgm_printed = 0 printf "%5d ", $kgm_procp->p_pid showptr $kgm_procp if ($kgm_procp->p_lflag & 0x400000) printf " RAGE " else printf " " end if ($kgm_procp->p_iopol_disk == 1) printf "NORM " set $kgm_printed = 1 end if ($kgm_procp->p_iopol_disk == 2) printf "PASS " set $kgm_printed = 1 end if ($kgm_procp->p_iopol_disk == 3) printf "THROT " set $kgm_printed = 1 end if ($kgm_printed == 0) printf " " end set $kgm_wqp = (struct workqueue *)$kgm_procp->p_wqptr if $kgm_wqp != 0 printf " %2d %2d %2d ", $kgm_wqp->wq_nthreads, $kgm_wqp->wq_thidlecount, $kgm_wqp->wq_itemcount else printf " " end printf " %s\n", $kgm_procp->p_comm else printf " *0* " showptr 0 printf " --\n" end end define showpid showtaskheader set $kgm_head_taskp = &tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp set $kgm_procp = (struct proc *)$kgm_taskp->bsd_info if (($kgm_procp != 0) && ($kgm_procp->p_pid == $arg0)) showtaskint $kgm_taskp set $kgm_taskp = $kgm_head_taskp else set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) end end end document showpid Syntax: (gdb) showpid | Routine to print a single process by pid end define showproc showtaskheader set $kgm_procp = (struct proc *)$arg0 showtaskint $kgm_procp->task end define kdb set switch_debugger=1 continue end document kdb | kdb - Switch to the inline kernel debugger | | usage: kdb | | The kdb macro allows you to invoke the inline kernel debugger. end define showpsetheader printf "portset waitqueue recvname " printf "flags refs recvname process\n" end define showportheader printf "port mqueue recvname " printf "flags refs recvname process\n" end define showportmemberheader printf "members port recvname " printf "flags refs mqueue msgcount\n" end define showkmsgheader printf "messages kmsg size " printf "disp msgid remote-port local-port\n" end define showkmsgint printf " 0x%08x ", $arg0 set $kgm_kmsgh = ((ipc_kmsg_t)$arg0)->ikm_header printf "0x%08x ", $kgm_kmsgh.msgh_size if (($kgm_kmsgh.msgh_bits & 0xff) == 19) printf "rC" else printf "rM" end if (($kgm_kmsgh.msgh_bits & 0xff00) == (19 << 8)) printf "lC" else printf "lM" end if ($kgm_kmsgh.msgh_bits & 0xf0000000) printf "c" else printf "s" end printf "%5d ", $kgm_kmsgh.msgh_id printf "0x%08x ", $kgm_kmsgh.msgh_remote_port printf "0x%08x\n", $kgm_kmsgh.msgh_local_port end define showkobject set $kgm_portp = (struct ipc_port *)$arg0 showptr $kgm_portp->ip_kobject printf " kobject(" set $kgm_kotype = ($kgm_portp->ip_object.io_bits & 0x00000fff) if ($kgm_kotype == 1) printf "THREAD" end if ($kgm_kotype == 2) printf "TASK" end if ($kgm_kotype == 3) printf "HOST" end if ($kgm_kotype == 4) printf "HOST_PRIV" end if ($kgm_kotype == 5) printf "PROCESSOR" end if ($kgm_kotype == 6) printf "PSET" end if ($kgm_kotype == 7) printf "PSET_NAME" end if ($kgm_kotype == 8) printf "TIMER" end if ($kgm_kotype == 9) printf "PAGER_REQ" end if ($kgm_kotype == 10) printf "DEVICE" end if ($kgm_kotype == 11) printf "XMM_OBJECT" end if ($kgm_kotype == 12) printf "XMM_PAGER" end if ($kgm_kotype == 13) printf "XMM_KERNEL" end if ($kgm_kotype == 14) printf "XMM_REPLY" end if ($kgm_kotype == 15) printf "NOTDEF 15" end if ($kgm_kotype == 16) printf "NOTDEF 16" end if ($kgm_kotype == 17) printf "HOST_SEC" end if ($kgm_kotype == 18) printf "LEDGER" end if ($kgm_kotype == 19) printf "MASTER_DEV" end if ($kgm_kotype == 20) printf "ACTIVATION" end if ($kgm_kotype == 21) printf "SUBSYSTEM" end if ($kgm_kotype == 22) printf "IO_DONE_QUE" end if ($kgm_kotype == 23) printf "SEMAPHORE" end if ($kgm_kotype == 24) printf "LOCK_SET" end if ($kgm_kotype == 25) printf "CLOCK" end if ($kgm_kotype == 26) printf "CLOCK_CTRL" end if ($kgm_kotype == 27) printf "IOKIT_SPARE" end if ($kgm_kotype == 28) printf "NAMED_MEM" end if ($kgm_kotype == 29) printf "IOKIT_CON" end if ($kgm_kotype == 30) printf "IOKIT_OBJ" end if ($kgm_kotype == 31) printf "UPL" end if ($kgm_kotype == 34) printf "FD" end printf ")\n" end define showportdestproc set $kgm_portp = (struct ipc_port *)$arg0 set $kgm_spacep = $kgm_portp->data.receiver # check against the previous cached value - this is slow if ($kgm_spacep != $kgm_destspacep) set $kgm_destprocp = (struct proc *)0 set $kgm_head_taskp = &tasks set $kgm_desttaskp = (struct task *)($kgm_head_taskp->next) while (($kgm_destprocp == 0) && ($kgm_desttaskp != $kgm_head_taskp)) set $kgm_destspacep = $kgm_desttaskp->itk_space if ($kgm_destspacep == $kgm_spacep) set $kgm_destprocp = (struct proc *)$kgm_desttaskp->bsd_info else set $kgm_desttaskp = (struct task *)($kgm_desttaskp->tasks.next) end end end if $kgm_destprocp != 0 printf "%s(%d)\n", $kgm_destprocp->p_comm, $kgm_destprocp->p_pid else printf "task " showptr $kgm_desttaskp printf "\n" end end define showportdest set $kgm_portp = (struct ipc_port *)$arg0 set $kgm_spacep = $kgm_portp->data.receiver if ($kgm_spacep == ipc_space_kernel) showkobject $kgm_portp else if ($kgm_portp->ip_object.io_bits & 0x80000000) showptr $kgm_portp->ip_messages.data.port.receiver_name printf " " showportdestproc $kgm_portp else showptr $kgm_portp printf " inactive-port\n" end end end define showportmember printf " 0x%08x ", $arg0 set $kgm_portp = (struct ipc_port *)$arg0 printf "0x%08x ", $kgm_portp->ip_messages.data.port.receiver_name if ($kgm_portp->ip_object.io_bits & 0x80000000) printf "A" else printf " " end printf "Port" printf "%5d ", $kgm_portp->ip_object.io_references printf "0x%08x ", &($kgm_portp->ip_messages) printf "0x%08x\n", $kgm_portp->ip_messages.data.port.msgcount end define showportbt set $kgm_iebt = ((ipc_port_t) $arg0)->ip_callstack set $kgm_iepid = ((ipc_port_t) $arg0)->ip_spares[0] set $kgm_procpid = ((proc_t) (((task_t) $arg1)->bsd_info))->p_pid if $kgm_iebt[0] != 0 showptr $kgm_iebt[0] set $kgm_iebt_loop_ctr = 1 while ($kgm_iebt_loop_ctr < 16 && $kgm_iebt[$kgm_iebt_loop_ctr]) printf " " showptr $kgm_iebt[$kgm_iebt_loop_ctr] set $kgm_iebt_loop_ctr = $kgm_iebt_loop_ctr + 1 end if $kgm_iepid != $kgm_procpid printf " (%d)", $kgm_iepid end printf "\n" end end define showportint printf "0x%08x ", $arg0 set $kgm_portp = (struct ipc_port *)$arg0 printf "0x%08x ", &($kgm_portp->ip_messages) printf "0x%08x ", $kgm_portp->ip_messages.data.port.receiver_name if ($kgm_portp->ip_object.io_bits & 0x80000000) printf "A" else printf "D" end printf "Port" printf "%5d ", $kgm_portp->ip_object.io_references set $kgm_destspacep = (struct ipc_space *)0 showportdest $kgm_portp set $kgm_kmsgp = (ipc_kmsg_t)$kgm_portp->ip_messages.data.port.messages.ikmq_base if $arg1 && $kgm_kmsgp showkmsgheader showkmsgint $kgm_kmsgp set $kgm_kmsgheadp = $kgm_kmsgp set $kgm_kmsgp = $kgm_kmsgp->ikm_next while $kgm_kmsgp != $kgm_kmsgheadp showkmsgint $kgm_kmsgp set $kgm_kmsgp = $kgm_kmsgp->ikm_next end end end define showpsetint printf "0x%08x ", $arg0 set $kgm_psetp = (struct ipc_pset *)$arg0 printf "0x%08x ", &($kgm_psetp->ips_messages) printf "0x%08x ", $kgm_psetp->ips_messages.data.pset.local_name if ($kgm_psetp->ips_object.io_bits & 0x80000000) printf "A" else printf "D" end printf "Set " printf "%5d ", $kgm_psetp->ips_object.io_references printf "0x%08x ", $kgm_psetp->ips_messages.data.pset.local_name set $kgm_setlinksp = &($kgm_psetp->ips_messages.data.pset.set_queue.wqs_setlinks) set $kgm_wql = (WaitQueueLink *)$kgm_setlinksp->next set $kgm_found = 0 while ( (queue_entry_t)$kgm_wql != (queue_entry_t)$kgm_setlinksp) set $kgm_portp = (struct ipc_port *)((uintptr_t)$kgm_wql->wql_element.wqe_queue - $kgm_portoff) if !$kgm_found set $kgm_destspacep = (struct ipc_space *)0 showportdestproc $kgm_portp showportmemberheader set $kgm_found = 1 end showportmember $kgm_portp 0 set $kgm_wql = (WaitQueueLink *)$kgm_wql->wql_setlinks.next end if !$kgm_found printf "--n/e--\n" end end define showpset showpsetheader showpsetint $arg0 1 end define showport showportheader showportint $arg0 1 end define showipcobject set $kgm_object = (ipc_object_t)$arg0 if ($kgm_objectp->io_bits & 0x7fff0000) showpset $kgm_objectp else showport $kgm_objectp end end define showmqueue set $kgm_mqueue = *(struct ipc_mqueue *)$arg0 set $kgm_psetoff = (uintptr_t)&(((struct ipc_pset *)0)->ips_messages) set $kgm_portoff = (uintptr_t)&(((struct ipc_port *)0)->ip_messages) if ($kgm_mqueue.data.pset.set_queue.wqs_wait_queue.wq_type == 0xf1d1) set $kgm_psetp = (struct ipc_pset *)(((uintptr_t)$arg0) - $kgm_psetoff) showpsetheader showpsetint $kgm_psetp 1 end if ($kgm_mqueue.data.pset.set_queue.wqs_wait_queue.wq_type == 0xf1d0) set $kgm_portp = (struct ipc_port *)(((uintptr_t)$arg0) - $kgm_portoff) showportheader showportint $kgm_portp 1 end end define zprint_one set $kgm_zone = (struct zone *)$arg0 showptr $kgm_zone printf " %6d ",$kgm_zone->count printf "%8x ",$kgm_zone->cur_size printf "%8x ",$kgm_zone->max_size printf "%6d ",$kgm_zone->elem_size printf "%8x ",$kgm_zone->alloc_size printf "%s ",$kgm_zone->zone_name if ($kgm_zone->exhaustible) printf "H" end if ($kgm_zone->collectable) printf "C" end if ($kgm_zone->expandable) printf "X" end if ($kgm_zone->noencrypt) printf "$" end printf "\n" end define zprint printf "ZONE " showptrhdrpad printf " COUNT TOT_SZ MAX_SZ ELT_SZ ALLOC_SZ NAME\n" set $kgm_zone_ptr = (struct zone *)first_zone while ($kgm_zone_ptr != 0) zprint_one $kgm_zone_ptr set $kgm_zone_ptr = $kgm_zone_ptr->next_zone end printf "\n" end document zprint Syntax: (gdb) zprint | Routine to print a summary listing of all the kernel zones end define showmtxgrp set $kgm_mtxgrp = (struct _lck_grp_ *)$arg0 if ($kgm_mtxgrp->lck_grp_mtxcnt) showptr $kgm_mtxgrp printf " %8d ",$kgm_mtxgrp->lck_grp_mtxcnt printf "%12u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_util_cnt printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_miss_cnt printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_wait_cnt printf "%s ",&$kgm_mtxgrp->lck_grp_name printf "\n" end end define showallmtx printf "LCK GROUP " showptrhdrpad printf " CNT UTIL MISS WAIT NAME\n" set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)&lck_grp_queue set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)$kgm_mtxgrp_ptr->lck_grp_link.next while ($kgm_mtxgrp_ptr != (struct _lck_grp_ *)&lck_grp_queue) showmtxgrp $kgm_mtxgrp_ptr set $kgm_mtxgrp_ptr = (struct _lck_grp_ *)$kgm_mtxgrp_ptr->lck_grp_link.next end printf "\n" end document showallmtx Syntax: (gdb) showallmtx | Routine to print a summary listing of all mutexes end define showrwlckgrp set $kgm_rwlckgrp = (struct _lck_grp_ *)$arg0 if ($kgm_rwlckgrp->lck_grp_rwcnt) showptr $kgm_rwlckgrp printf " %8d ",$kgm_rwlckgrp->lck_grp_rwcnt printf "%12u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_util_cnt printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_miss_cnt printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_wait_cnt printf "%s ",&$kgm_rwlckgrp->lck_grp_name printf "\n" end end define showallrwlck printf "LCK GROUP " showptrhdrpad printf " CNT UTIL MISS WAIT NAME\n" set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)&lck_grp_queue set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)$kgm_rwlckgrp_ptr->lck_grp_link.next while ($kgm_rwlckgrp_ptr != (struct _lck_grp_ *)&lck_grp_queue) showrwlckgrp $kgm_rwlckgrp_ptr set $kgm_rwlckgrp_ptr = (struct _lck_grp_ *)$kgm_rwlckgrp_ptr->lck_grp_link.next end printf "\n" end document showallrwlck Syntax: (gdb) showallrwlck | Routine to print a summary listing of all read/writer locks end set $kdp_act_counter = 0 set $r0_save = 0 set $r1_save = 0 set $r2_save = 0 set $r3_save = 0 set $r4_save = 0 set $r5_save = 0 set $r6_save = 0 set $r7_save = 0 set $r8_save = 0 set $r9_save = 0 set $r10_save = 0 set $r11_save = 0 set $r12_save = 0 set $sp_save = 0 set $lr_save = 0 set $pc_save = 0 define showcontext_int echo Context switched, current instruction pointer: output/a $pc echo \n end define switchtoact set $newact = (struct thread *) $arg0 select 0 if ($newact->kernel_stack == 0) echo This activation does not have a stack.\n echo continuation: output/a (unsigned) $newact.continuation echo \n else if ($kgm_mtype == $kgm_mtype_ppc) if ($kdp_act_counter == 0) set $kdpstate = (struct savearea *) kdp.saved_state end set $kdp_act_counter = $kdp_act_counter + 1 set (struct savearea *) kdp.saved_state=$newact->machine->pcb flushregs flushstack set $pc=$newact->machine->pcb.save_srr0 update end if ($kgm_mtype == $kgm_mtype_i386) set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state if ($kdp_act_counter == 0) set $kdpstate = *($kdpstatep) end set $kdp_act_counter = $kdp_act_counter + 1 set $kgm_statep = (struct x86_kernel_state *) \ ($newact->kernel_stack + kernel_stack_size \ - sizeof(struct x86_kernel_state)) set $kdpstatep->ebx = $kgm_statep->k_ebx set $kdpstatep->ebp = $kgm_statep->k_ebp set $kdpstatep->edi = $kgm_statep->k_edi set $kdpstatep->esi = $kgm_statep->k_esi set $kdpstatep->eip = $kgm_statep->k_eip flushregs flushstack set $pc = $kgm_statep->k_eip update end if ($kgm_mtype == $kgm_mtype_x86_64) set $kdpstatep = (struct x86_saved_state64 *) kdp.saved_state if ($kdp_act_counter == 0) set $kdpstate = *($kdpstatep) end set $kdp_act_counter = $kdp_act_counter + 1 set $kgm_statep = (struct x86_kernel_state *) \ ($newact->kernel_stack + kernel_stack_size \ - sizeof(struct x86_kernel_state)) set $kdpstatep->rbx = $kgm_statep->k_rbx set $kdpstatep->rbp = $kgm_statep->k_rbp set $kdpstatep->r12 = $kgm_statep->k_r12 set $kdpstatep->r13 = $kgm_statep->k_r13 set $kdpstatep->r14 = $kgm_statep->k_r14 set $kdpstatep->r15 = $kgm_statep->k_r15 set $kdpstatep->isf.rsp = $kgm_statep->k_rsp flushregs flushstack set $pc = $kgm_statep->k_rip update end if ($kgm_mtype == $kgm_mtype_arm) set $r0_save = $r0 set $r1_save = $r1 set $r2_save = $r2 set $r3_save = $r3 set $r4_save = $r4 set $r5_save = $r5 set $r6_save = $r6 set $r7_save = $r7 set $r8_save = $r8 set $r9_save = $r9 set $r10_save = $r10 set $r11_save = $r11 set $r12_save = $r12 set $sp_save = $sp set $lr_save = $lr set $pc_save = $pc set $pc_ctx = load_reg+8 set $kgm_statep = (struct arm_saved_state *)((struct thread*)$arg0)->machine.kstackptr set $r0 = $kgm_statep->r[0] set $r1 = $kgm_statep->r[1] set $r2 = $kgm_statep->r[2] set $r3 = $kgm_statep->r[3] set $r4 = $kgm_statep->r[4] set $r5 = $kgm_statep->r[5] set $r6 = $kgm_statep->r[6] set $r8 = $kgm_statep->r[8] set $r9 = $kgm_statep->r[9] set $r10 = $kgm_statep->r[10] set $r11 = $kgm_statep->r[11] set $r12 = $kgm_statep->r[12] set $sp = $kgm_statep->sp set $lr = $kgm_statep->lr set $pc = $pc_ctx set $r7 = $kgm_statep->r[7] flushregs flushstack end end showcontext_int end document switchtoact Syntax: switchtoact
| This command allows gdb to examine the execution context and call | stack for the specified activation. For example, to view the backtrace | for an activation issue "switchtoact
", followed by "bt". | Before resuming execution, issue a "resetctx" command, to | return to the original execution context. end define switchtoctx select 0 if ($kgm_mtype == $kgm_mtype_ppc) if ($kdp_act_counter == 0) set $kdpstate = (struct savearea *) kdp.saved_state end set $kdp_act_counter = $kdp_act_counter + 1 set (struct savearea *) kdp.saved_state=(struct savearea *) $arg0 flushregs flushstack set $pc=((struct savearea *) $arg0)->save_srr0 update else if ($kgm_mtype == $kgm_mtype_arm) set arm disassembler std select-frame 0 set $r0_save = $r0 set $r1_save = $r1 set $r2_save = $r2 set $r3_save = $r3 set $r4_save = $r4 set $r5_save = $r5 set $r6_save = $r6 set $r7_save = $r7 set $r8_save = $r8 set $r9_save = $r9 set $r10_save = $r10 set $r11_save = $r11 set $r12_save = $r12 set $sp_save = $sp set $lr_save = $lr set $pc_save = $pc set $kgm_statep = (struct arm_saved_state *)$arg0 set $r0 = $kgm_statep->r[0] set $r1 = $kgm_statep->r[1] set $r2 = $kgm_statep->r[2] set $r3 = $kgm_statep->r[3] set $r4 = $kgm_statep->r[4] set $r5 = $kgm_statep->r[5] set $r6 = $kgm_statep->r[6] set $r8 = $kgm_statep->r[8] set $r9 = $kgm_statep->r[9] set $r10 = $kgm_statep->r[10] set $r11 = $kgm_statep->r[11] set $r12 = $kgm_statep->r[12] set $sp = $kgm_statep->sp set $lr = $kgm_statep->lr set $r7 = $kgm_statep->r[7] set $pc = $kgm_statep->pc flushregs flushstack update else echo switchtoctx not implemented for this architecture.\n end end document switchtoctx Syntax: switchtoctx
| This command allows gdb to examine an execution context and dump the | backtrace for this execution context. | Before resuming execution, issue a "resetctx" command, to | return to the original execution context. end define resetctx select 0 if ($kdp_act_counter != 0) if ($kgm_mtype == $kgm_mtype_ppc) set (struct savearea *)kdp.saved_state=$kdpstate flushregs flushstack set $pc=((struct savearea *) kdp.saved_state)->save_srr0 update set $kdp_act_counter = 0 end if ($kgm_mtype == $kgm_mtype_i386) set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state set *($kdpstatep)=$kdpstate flushregs flushstack set $pc=$kdpstatep->eip update set $kdp_act_counter = 0 end if ($kgm_mtype == $kgm_mtype_x86_64) set $kdpstatep = (struct x86_saved_state64 *) kdp.saved_state set *($kdpstatep)=$kdpstate flushregs flushstack set $pc=$kdpstatep->isf.rip update set $kdp_act_counter = 0 end if ($kgm_mtype == $kgm_mtype_arm) set $r0 = $r0_save flushregs set $r1 = $r1_save flushregs set $r2 = $r2_save flushregs set $r3 = $r3_save flushregs set $r4 = $r4_save flushregs set $r5 = $r5_save flushregs set $r6 = $r6_save flushregs set $r8 = $r8_save flushregs set $r9 = $r9_save flushregs set $r10 = $r10_save flushregs set $r11 = $r11_save flushregs set $r12 = $r12_save flushregs set $sp = $sp_save flushregs set $lr = $lr_save flushregs set $pc = $pc_save flushregs set $r7 = $r7_save flushregs end showcontext_int end end document resetctx | Syntax: resetctx | Returns to the original execution context. This command should be | issued if you wish to resume execution after using the "switchtoact" | or "switchtoctx" commands. end # This is a pre-hook for the continue command, to prevent inadvertent attempts # to resume from the context switched to for examination. define hook-continue resetctx end # This is a pre-hook for the detach command, to prevent inadvertent attempts # to resume from the context switched to for examination. define hook-detach resetctx end define resume_on set $resume = KDP_DUMPINFO_SETINFO | KDP_DUMPINFO_RESUME dumpinfoint $resume end document resume_on | Syntax: resume_on | The target system will resume when detaching or exiting from gdb. | This is the default behavior. end define resume_off set $noresume = KDP_DUMPINFO_SETINFO | KDP_DUMPINFO_NORESUME dumpinfoint $noresume end document resume_off | Syntax: resume_off | The target system won't resume after detaching from gdb and | can be attached with a new gdb session end define paniclog set $kgm_panic_bufptr = debug_buf set $kgm_panic_bufptr_max = debug_buf_ptr while $kgm_panic_bufptr < $kgm_panic_bufptr_max if *(char *)$kgm_panic_bufptr == 10 printf "\n" else printf "%c", *(char *)$kgm_panic_bufptr end set $kgm_panic_bufptr= (char *)$kgm_panic_bufptr + 1 end end document paniclog | Syntax: paniclog | Display the panic log information | end define dumpcallqueue set $kgm_callhead = $arg0 set $kgm_callentry = $kgm_callhead->next set $kgm_i = 0 while $kgm_callentry != $kgm_callhead set $kgm_call = (struct call_entry *)$kgm_callentry printf "0x%08x ", $kgm_call printf "0x%08x 0x%08x ", $kgm_call->param0, $kgm_call->param1 output $kgm_call->deadline printf "\t" output $kgm_call->func printf "\n" set $kgm_i = $kgm_i + 1 set $kgm_callentry = $kgm_callentry->next end printf "%d entries\n", $kgm_i end document dumpcallqueue | Syntax: dumpcallqueue | Displays the contents of the specified call_entry queue. end define showtaskacts showtaskthreads $arg0 end document showtaskacts | See help showtaskthreads. end define showallacts showallthreads end document showallacts | See help showallthreads. end define resetstacks _kgm_flush_loop set kdp_pmap = 0 _kgm_flush_loop resetctx _kgm_flush_loop _kgm_update_loop resetctx _kgm_update_loop end document resetstacks | Syntax: resetstacks | Internal kgmacro routine used by the "showuserstack" macro | to reset the target pmap to the kernel pmap. end #Barely effective hacks to work around bugs in the "flush" and "update" #gdb commands in Tiger (up to 219); these aren't necessary with Panther #gdb, but do no harm. define _kgm_flush_loop set $kgm_flush_loop_ctr = 0 while ($kgm_flush_loop_ctr < 30) flushregs flushstack set $kgm_flush_loop_ctr = $kgm_flush_loop_ctr + 1 end end define _kgm_update_loop set $kgm_update_loop_ctr = 0 while ($kgm_update_loop_ctr < 30) update set $kgm_update_loop_ctr = $kgm_update_loop_ctr + 1 end end # Internal routine used by "_loadfrom" to read from 64-bit addresses # on 32-bit kernels define _loadk32m64 # set up the manual KDP packet set manual_pkt.input = 0 set manual_pkt.len = sizeof(kdp_readmem64_req_t) set $kgm_pkt = (kdp_readmem64_req_t *)&manual_pkt.data set $kgm_pkt->hdr.request = KDP_READMEM64 set $kgm_pkt->hdr.len = sizeof(kdp_readmem64_req_t) set $kgm_pkt->hdr.is_reply = 0 set $kgm_pkt->hdr.seq = 0 set $kgm_pkt->hdr.key = 0 set $kgm_pkt->address = (uint64_t)$arg0 set $kgm_pkt->nbytes = sizeof(uint64_t) set manual_pkt.input = 1 # dummy to make sure manual packet is executed set $kgm_dummy = &_mh_execute_header set $kgm_pkt = (kdp_readmem64_reply_t *)&manual_pkt.data if ($kgm_pkt->error == 0) set $kgm_k32read64 = *(uint64_t *)$kgm_pkt->data else set $kgm_k32read64 = 0 end end # Internal routine used by "showx86backtrace" to abstract possible loads from # user space define _loadfrom if (kdp_pmap == 0) set $kgm_loadval = *(uintptr_t *)$arg0 else if ($kgm_x86_abi == 0xe) set $kgm_loadval = *(uint32_t *)$arg0 else if ($kgm_x86_abi == 0xf) if ($kgm_mtype == $kgm_mtype_i386) _loadk32m64 $arg0 set $kgm_loadval = $kgm_k32read64 else set $kgm_loadval = *(uint64_t *)$arg0 end end end end end #This is necessary since gdb often doesn't do backtraces on x86 correctly #in the absence of symbols.The code below in showuserstack and #showx86backtrace also contains several workarouds for the gdb bug where #gdb stops macro evaluation because of spurious "Cannot read memory" #errors on x86. These errors appear on ppc as well, but they don't #always stop macro evaluation. set $kgm_cur_frame = 0 set $kgm_cur_pc = 0 set $kgm_x86_abi = 0 define showx86backtrace if ($kgm_mtype == $kgm_mtype_i386) set $kgm_frame_reg = $ebp set $kgm_pc = $eip set $kgm_ret_off = 4 end if ($kgm_mtype == $kgm_mtype_x86_64) set $kgm_frame_reg = $rbp set $kgm_pc = $rip set $kgm_ret_off = 8 end if ($kgm_x86_abi == 0xe) set $kgm_ret_off = 4 end if ($kgm_x86_abi == 0xf) set $kgm_ret_off = 8 end if ($kgm_cur_frame == 0) set $kgm_cur_frame = $kgm_frame_reg end if ($kgm_cur_pc == 0) set $kgm_cur_pc = $kgm_pc end printf "0: Frame: 0x%016llx PC: 0x%016llx\n", $kgm_cur_frame, $kgm_cur_pc if (!(($kgm_x86_abi == 0xf) && ($kgm_mtype == $kgm_mtype_i386))) x/i $kgm_cur_pc end set $kgm_tmp_frame = $kgm_cur_frame set $kgm_cur_frame = 0 set $kgm_cur_pc = 0 _loadfrom ($kgm_tmp_frame) set $kgm_prev_frame = $kgm_loadval _loadfrom ($kgm_tmp_frame+$kgm_ret_off) set $kgm_prev_pc = $kgm_loadval set $kgm_frameno = 1 while $kgm_prev_frame != 0 printf "%d: Saved frame: 0x%016llx Saved PC: 0x%016llx\n", $kgm_frameno, $kgm_prev_frame, $kgm_prev_pc if (!(($kgm_x86_abi == 0xf) && ($kgm_mtype == $kgm_mtype_i386))) x/i $kgm_prev_pc end _loadfrom ($kgm_prev_frame+$kgm_ret_off) set $kgm_prev_pc = $kgm_loadval _loadfrom ($kgm_prev_frame) set $kgm_prev_frame = $kgm_loadval set $kgm_frameno = $kgm_frameno + 1 end set kdp_pmap = 0 set $kgm_x86_abi = 0 end define showx86backtrace2 set $kgm_cur_frame = $arg0 set $kgm_cur_pc = $arg1 showx86backtrace end define showuserstack select 0 if ($kgm_mtype == $kgm_mtype_ppc) if ($kdp_act_counter == 0) set $kdpstate = (struct savearea *) kdp.saved_state end set $kdp_act_counter = $kdp_act_counter + 1 set $newact = (struct thread *) $arg0 _kgm_flush_loop set $checkpc = $newact->machine->upcb.save_srr0 if ($checkpc == 0) echo This activation does not appear to have echo \20 a valid user context.\n else set (struct savearea *) kdp.saved_state=$newact->machine->upcb set $pc = $checkpc #flush and update seem to be executed lazily by gdb on Tiger, hence the #repeated invocations - see 3743135 _kgm_flush_loop # This works because the new pmap is used only for reads set kdp_pmap = $newact->task->map->pmap _kgm_flush_loop _kgm_update_loop bt resetstacks _kgm_flush_loop _kgm_update_loop resetstacks _kgm_flush_loop _kgm_update_loop end else if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) set $newact = (struct thread *) $arg0 set $newiss = (x86_saved_state_t *) ($newact->machine.pcb->iss) set $kgm_x86_abi = $newiss.flavor if ($newiss.flavor == 0xf) set $checkpc = $newiss.uss.ss_64.isf.rip set $checkframe = $newiss.uss.ss_64.rbp else set $checkpc = $newiss.uss.ss_32.eip set $checkframe = $newiss.uss.ss_32.ebp end if ($checkpc == 0) echo This activation does not appear to have echo \20 a valid user context.\n else set $kgm_cur_frame = $checkframe set $kgm_cur_pc = $checkpc printf "You may now issue the showx86backtrace command to see the user space backtrace for this thread (" showptr $arg0 printf "); you can also examine memory locations in this address space (pmap " showptr $newact->task->map->pmap printf ") before issuing the backtrace. This two-step process is necessary to work around various bugs in x86 gdb, which cause it to stop memory evaluation on spurious memory read errors. Additionally, you may need to issue a set kdp_pmap = 0 command after the showx86backtrace completes, to resume reading from the kernel address space.\n" set kdp_pmap = $newact->task->map->pmap _kgm_flush_loop _kgm_update_loop end else echo showuserstack not supported on this architecture\n end end end document showuserstack Syntax: showuserstack
|This command displays a numeric backtrace for the user space stack of |the given thread activation. It may, of course, fail to display a |complete backtrace if portions of the user stack are not mapped in. |Symbolic backtraces can be obtained either by running gdb on the |user space binary, or a tool such as "symbolicate". |Note that while this command works on Panther's gdb, an issue |with Tiger gdb (3743135) appears to hamper the evaluation of this |macro in some cases. end define kdp-reboot # Alternatively, set *(*(unsigned **) 0x2498) = 1 # (or 0x5498 on PPC, 0xffffff8000002928 on x86_64, 0xffff049c on arm) manualhdrint $kgm_kdp_pkt_hostreboot continue end document kdp-reboot Syntax: kdp-reboot |Reboot the remote target machine; not guaranteed to succeed. end define kdpversionint # set up the manual KDP packet set manual_pkt.input = 0 set manual_pkt.len = sizeof(kdp_version_req_t) set $kgm_pkt = (kdp_version_req_t *)&manual_pkt.data set $kgm_pkt->hdr.request = KDP_VERSION set $kgm_pkt->hdr.len = sizeof(kdp_version_req_t) set $kgm_pkt->hdr.is_reply = 0 set $kgm_pkt->hdr.seq = 0 set $kgm_pkt->hdr.key = 0 set manual_pkt.input = 1 # dummy to make sure manual packet is executed set $kgm_dummy = &_mh_execute_header set $kgm_pkt = (kdp_version_reply_t *)&manual_pkt.data set $kgm_kdp_version = $kgm_pkt->version set $kgm_kdp_feature = $kgm_pkt->feature end define kdp-version kdpversionint printf "KDP VERSION = %d, FEATURE = 0x%x\n", $kgm_kdp_version, $kgm_kdp_feature end document kdp-version Syntax: kdp-version |Get the KDP protocol version being used by the kernel. end define dumpinfoint # set up the manual KDP packet set manual_pkt.input = 0 set manual_pkt.len = sizeof(kdp_dumpinfo_req_t) set $kgm_pkt = (kdp_dumpinfo_req_t *)manual_pkt.data set $kgm_pkt->hdr.request = KDP_DUMPINFO set $kgm_pkt->hdr.len = sizeof(kdp_dumpinfo_req_t) set $kgm_pkt->hdr.is_reply = 0 set $kgm_pkt->hdr.seq = 0 set $kgm_pkt->hdr.key = 0 set $kgm_pkt->type = $arg0 set $kgm_pkt->name = "" set $kgm_pkt->destip = "" set $kgm_pkt->routerip = "" set $kgm_pkt->port = 0 if $argc > 1 set $kgm_pkt->name = "$arg1" end if $argc > 2 set $kgm_pkt->destip = "$arg2" end if $argc > 3 set $kgm_pkt->routerip = "$arg3" end if $argc > 4 set $kgm_pkt->port = $arg4 end set manual_pkt.input = 1 # dummy to make sure manual packet is executed set $kgm_dummy = &_mh_execute_header end define sendcore if $argc > 1 dumpinfoint KDP_DUMPINFO_CORE $arg1 $arg0 else dumpinfoint KDP_DUMPINFO_CORE \0 $arg0 end end document sendcore Syntax: sendcore [filename] |Configure the kernel to transmit a kernel coredump to a server (kdumpd) |at the specified IP address. This is useful when the remote target has |not been previously configured to transmit coredumps, and you wish to |preserve kernel state for later examination. NOTE: You must issue a "continue" |command after using this macro to trigger the kernel coredump. The kernel |will resume waiting in the debugger after completion of the coredump. You |may disable coredumps by executing the "disablecore" macro. You can |optionally specify the filename to be used for the generated core file. end define sendsyslog if $argc > 1 dumpinfoint KDP_DUMPINFO_SYSTEMLOG $arg1 $arg0 else dumpinfoint KDP_DUMPINFO_SYSTEMLOG \0 $arg0 end end document sendsyslog Syntax: sendsyslog [filename] |Configure the kernel to transmit a kernel system log to a server (kdumpd) |at the specified IP address. NOTE: You must issue a "continue" |command after using this macro to trigger the kernel system log. The kernel |will resume waiting in the debugger after completion. You can optionally |specify the name to be used for the generated system log. end define sendpaniclog if panicstr if $argc > 1 dumpinfoint KDP_DUMPINFO_PANICLOG $arg1 $arg0 else dumpinfoint KDP_DUMPINFO_PANICLOG \0 $arg0 end else printf "No panic log available.\n" end end document sendpaniclog Syntax: sendpaniclog [filename] |Configure the kernel to transmit a kernel paniclog to a server (kdumpd) |at the specified IP address. NOTE: You must issue a "continue" |command after using this macro to trigger the kernel panic log. The kernel |will resume waiting in the debugger after completion. You can optionally |specify the name to be used for the generated panic log. end define getdumpinfo dumpinfoint KDP_DUMPINFO_GETINFO set $kgm_dumpinfo = (kdp_dumpinfo_reply_t *) manual_pkt.data if $kgm_dumpinfo->type & KDP_DUMPINFO_REBOOT printf "System will reboot after kernel info gets dumped.\n" else printf "Sysem will not reboot after kernel info gets dumped.\n" end if $kgm_dumpinfo->type & KDP_DUMPINFO_NORESUME printf "System will allow a re-attach after a KDP disconnect.\n" else printf "System will resume after a KDP disconnect.\n" end set $kgm_dumpinfo_type = $kgm_dumpinfo->type & KDP_DUMPINFO_MASK if $kgm_dumpinfo_type == KDP_DUMPINFO_DISABLE printf "Kernel not setup for remote dumps.\n" else printf "Remote dump type: " if $kgm_dumpinfo_type == KDP_DUMPINFO_CORE printf "Core file\n" end if $kgm_dumpinfo_type == KDP_DUMPINFO_PANICLOG printf "Panic log\n" end if $kgm_dumpinfo_type == KDP_DUMPINFO_SYSTEMLOG printf "System log\n" end printf "Name: " if $kgm_dumpinfo->name[0] == '\0' printf "(autogenerated)\n" else printf "%s\n", $kgm_dumpinfo->name end printf "Network Info: %s[%d] ", $kgm_dumpinfo->destip, $kgm_dumpinfo->port if $kgm_dumpinfo->routerip[0] == '\0' printf "\n" else printf "Router: %s\n", $kgm_dumpinfo->routerip end end end document getdumpinfo Syntax: getdumpinfo |Retrieve the current remote dump settings. end define setdumpinfo dumpinfoint KDP_DUMPINFO_SETINFO $arg0 $arg1 $arg2 $arg3 end document setdumpinfo Syntax: setdumpinfo |Configure the current remote dump settings. Specify \0 if you |want to use the defaults (filename) or previously configured |settings (ip/router). Specify 0 for the port if you wish to |use the previously configured/default setting for that. end define disablecore dumpinfoint KDP_DUMPINFO_DISABLE end document disablecore Syntax: disablecore |Reconfigures the kernel so that it no longer transmits kernel coredumps. This |complements the "sendcore" macro, but it may be used if the kernel has been |configured to transmit coredumps through boot-args as well. end define switchtocorethread set $newact = (struct thread *) $arg0 select 0 if ($newact->kernel_stack == 0) echo This thread does not have a stack.\n echo continuation: output/a (unsigned) $newact.continuation echo \n else if ($kgm_mtype == $kgm_mtype_ppc) loadcontext $newact->machine->pcb flushstack set $pc = $newact->machine->pcb.save_srr0 else if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any) set $kgm_cstatep = (struct x86_kernel_state *) \ ($newact->kernel_stack + kernel_stack_size \ - sizeof(struct x86_kernel_state)) loadcontext $kgm_cstatep flushstack else echo switchtocorethread not supported on this architecture\n end end showcontext_int end end document switchtocorethread Syntax: switchtocorethread
| The corefile equivalent of "switchtoact". When debugging a kernel coredump | file, this command can be used to examine the execution context and stack | trace for a given thread activation. For example, to view the backtrace | for a thread issue "switchtocorethread
", followed by "bt". | Before resuming execution, issue a "resetcorectx" command, to | return to the original execution context. Note that this command | requires gdb support, as documented in Radar 3401283. end define loadcontext select 0 if ($kgm_mtype == $kgm_mtype_ppc) set $kgm_contextp = (struct savearea *) $arg0 set $pc = $kgm_contextp.save_srr0 set $r1 = $kgm_contextp.save_r1 set $lr = $kgm_contextp.save_lr set $r2 = $kgm_contextp.save_r2 set $r3 = $kgm_contextp.save_r3 set $r4 = $kgm_contextp.save_r4 set $r5 = $kgm_contextp.save_r5 set $r6 = $kgm_contextp.save_r6 set $r7 = $kgm_contextp.save_r7 set $r8 = $kgm_contextp.save_r8 set $r9 = $kgm_contextp.save_r9 set $r10 = $kgm_contextp.save_r10 set $r11 = $kgm_contextp.save_r11 set $r12 = $kgm_contextp.save_r12 set $r13 = $kgm_contextp.save_r13 set $r14 = $kgm_contextp.save_r14 set $r15 = $kgm_contextp.save_r15 set $r16 = $kgm_contextp.save_r16 set $r17 = $kgm_contextp.save_r17 set $r18 = $kgm_contextp.save_r18 set $r19 = $kgm_contextp.save_r19 set $r20 = $kgm_contextp.save_r20 set $r21 = $kgm_contextp.save_r21 set $r22 = $kgm_contextp.save_r22 set $r23 = $kgm_contextp.save_r23 set $r24 = $kgm_contextp.save_r24 set $r25 = $kgm_contextp.save_r25 set $r26 = $kgm_contextp.save_r26 set $r27 = $kgm_contextp.save_r27 set $r28 = $kgm_contextp.save_r28 set $r29 = $kgm_contextp.save_r29 set $r30 = $kgm_contextp.save_r30 set $r31 = $kgm_contextp.save_r31 set $cr = $kgm_contextp.save_cr set $ctr = $kgm_contextp.save_ctr else if ($kgm_mtype == $kgm_mtype_i386) set $kgm_contextp = (struct x86_kernel_state *) $arg0 set $ebx = $kgm_contextp->k_ebx set $ebp = $kgm_contextp->k_ebp set $edi = $kgm_contextp->k_edi set $esi = $kgm_contextp->k_esi set $eip = $kgm_contextp->k_eip set $pc = $kgm_contextp->k_eip else if ($kgm_mtype == $kgm_mtype_x86_64) set $kgm_contextp = (struct x86_kernel_state *) $arg0 set $rbx = $kgm_contextp->k_rbx set $rbp = $kgm_contextp->k_rbp set $r12 = $kgm_contextp->k_r12 set $r13 = $kgm_contextp->k_r13 set $r14 = $kgm_contextp->k_r14 set $r15 = $kgm_contextp->k_r15 set $rip = $kgm_contextp->k_rip set $pc = $kgm_contextp->k_rip else echo loadcontext not supported on this architecture\n end end end end define resetcorectx select 0 if ($kgm_mtype == $kgm_mtype_ppc) set $kgm_corecontext = (struct savearea *) kdp.saved_state loadcontext $kgm_corecontext else if ($kgm_mtype == $kgm_mtype_i386) set $kdpstatep = (struct x86_saved_state32 *) kdp.saved_state set $ebx = $kdpstatep->ebx set $ebp = $kdpstatep->ebp set $edi = $kdpstatep->edi set $esi = $kdpstatep->esi set $eip = $kdpstatep->eip set $eax = $kdpstatep->eax set $ecx = $kdpstatep->ecx set $edx = $kdpstatep->edx flushregs flushstack set $pc = $kdpstatep->eip update else echo resetcorectx not supported on this architecture\n end end showcontext_int end document resetcorectx Syntax: resetcorectx | The corefile equivalent of "resetctx". Returns to the original | execution context (that of the active thread at the time of the NMI or | panic). This command should be issued if you wish to resume | execution after using the "switchtocorethread" command. end #Helper function for "showallgdbstacks" define showgdbthread printf " 0x%08x ", $arg0 set $kgm_thread = *(struct thread *)$arg0 printf "0x%08x ", $arg0 printf "%3d ", $kgm_thread.sched_pri set $kgm_state = $kgm_thread.state if $kgm_state & 0x80 printf "I" end if $kgm_state & 0x40 printf "P" end if $kgm_state & 0x20 printf "A" end if $kgm_state & 0x10 printf "H" end if $kgm_state & 0x08 printf "U" end if $kgm_state & 0x04 printf "R" end if $kgm_state & 0x02 printf "S" end if $kgm_state & 0x01 printf "W\t" printf "0x%08x ", $kgm_thread.wait_queue output /a (unsigned) $kgm_thread.wait_event if ($kgm_thread.uthread != 0) set $kgm_uthread = (struct uthread *)$kgm_thread.uthread if ($kgm_uthread->uu_wmesg != 0) printf " \"%s\"", $kgm_uthread->uu_wmesg end end end if $arg1 != 0 if ($kgm_thread.kernel_stack != 0) if ($kgm_thread.reserved_stack != 0) printf "\n\t\treserved_stack=0x%08x", $kgm_thread.reserved_stack end printf "\n\t\tkernel_stack=0x%08x", $kgm_thread.kernel_stack if ($kgm_mtype == $kgm_mtype_ppc) set $mysp = $kgm_thread.machine.pcb->save_r1 end if ($kgm_mtype == $kgm_mtype_i386) set $kgm_statep = (struct x86_kernel_state *) \ ($kgm_thread->kernel_stack + kernel_stack_size \ - sizeof(struct x86_kernel_state)) set $mysp = $kgm_statep->k_ebp end if ($kgm_mtype == $kgm_mtype_arm) if (((unsigned long)$r7 < ((unsigned long) ($kgm_thread->kernel_stack+kernel_stack_size))) \ && ((unsigned long)$r7 > (unsigned long) ($kgm_thread->kernel_stack))) set $mysp = $r7 else set $kgm_statep = (struct arm_saved_state *)$kgm_thread.machine.kstackptr set $mysp = $kgm_statep->r[7] end end set $prevsp = 0 printf "\n\t\tstacktop=0x%08x", $mysp if ($arg2 == 0) switchtoact $arg0 else switchtocorethread $arg0 end bt else printf "\n\t\t\tcontinuation=" output /a (unsigned) $kgm_thread.continuation end printf "\n" else printf "\n" end end #Use of this macro is currently (8/04) blocked by the fact that gdb #stops evaluating macros when encountering an error, such as a failure #to read memory from a certain location. Until this issue (described in #3758949) is addressed, evaluation of this macro may stop upon #encountering such an error. define showallgdbstacks set $kgm_head_taskp = &tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader showtaskint $kgm_taskp set $kgm_head_actp = &($kgm_taskp->threads) set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) while $kgm_actp != $kgm_head_actp showactheader showgdbthread $kgm_actp 1 0 set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) end printf "\n" set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) end resetctx end document showallgdbstacks Syntax: showallgdbstacks | An alternative to "showallstacks". Iterates through the task list and | displays a gdb generated backtrace for each kernel thread. It is | advantageous in that it is much faster than "showallstacks", and | decodes function call arguments and displays source level traces, but | it has the drawback that it doesn't determine if frames belong to | functions from kernel extensions, as with "showallstacks". | This command may terminate prematurely because of a gdb bug | (Radar 3758949), which stops macro evaluation on memory read | errors. end define showallgdbcorestacks select 0 set $kgm_head_taskp = &tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader showtaskint $kgm_taskp set $kgm_head_actp = &($kgm_taskp->threads) set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) while $kgm_actp != $kgm_head_actp showactheader showgdbthread $kgm_actp 1 1 set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) end printf "\n" set $kgm_taskp = (struct task *)($kgm_taskp->tasks.next) end resetcorectx end document showallgdbcorestacks Syntax: showallgdbcorestacks |Corefile version of "showallgdbstacks" end define switchtouserthread select 0 if ($kgm_mtype == $kgm_mtype_ppc) if ($kdp_act_counter == 0) set $kdpstate = (struct savearea *) kdp.saved_state end set $kdp_act_counter = $kdp_act_counter + 1 set $newact = (struct thread *) $arg0 _kgm_flush_loop set $checkpc = $newact->machine->upcb.save_srr0 if ($checkpc == 0) echo This activation does not appear to have echo \20 a valid user context.\n else set (struct savearea *) kdp.saved_state=$newact->machine->upcb set $pc = $checkpc #flush and update seem to be executed lazily by gdb on Tiger, hence the #repeated invocations - see 3743135 _kgm_flush_loop # This works because the new pmap is used only for reads set kdp_pmap = $newact->task->map->pmap _kgm_flush_loop _kgm_update_loop end else echo switchtouserthread not implemented for this architecture.\n end end document switchtouserthread Syntax: switchtouserthread
| Analogous to switchtoact, but switches to the user context of a | specified thread address. Similar to the "showuserstack" | command, but this command does not return gdb to the kernel context | immediately. This is to assist with the following (rather risky) | manoeuvre - upon switching to the user context and virtual address | space, the user may choose to call remove-symbol-file on the | mach_kernel symbol file, and then add-symbol-file on the user space | binary's symfile. gdb can then generate symbolic backtraces | for the user space thread. To return to the | kernel context and virtual address space, the process must be | reversed, i.e. call remove-symbol-file on the user space symbols, and | then add-symbol-file on the appropriate mach_kernel, and issue the | "resetstacks" command. Note that gdb may not react kindly to all these | symbol file switches. The same restrictions that apply to "showuserstack" | apply here - pages that have been paged out cannot be read while in the | debugger context, so backtraces may terminate early. | If the virtual addresses in the stack trace do not conflict with those | of symbols in the kernel's address space, it may be sufficient to | just do an add-symbol-file on the user space binary's symbol file. | Note that while this command works on Panther's gdb, an issue | with Tiger gdb (3743135) appears to hamper the evaluation of this | macro in some cases. end define showmetaclass set $kgm_metaclassp = (OSMetaClass *)$arg0 printf "%-5d", $kgm_metaclassp->instanceCount printf "x %5d bytes", $kgm_metaclassp->classSize printf " %s\n", $kgm_metaclassp->className->string end define showstring printf "\"%s\"", ((OSString *)$arg0)->string end define shownumber printf "%lld", ((OSNumber *)$arg0)->value end define showboolean if ($arg0 == gOSBooleanFalse) printf "No" else printf "Yes" end end define showdatabytes set $kgm_data = (OSData *)$arg0 printf "<" set $kgm_datap = (const unsigned char *) $kgm_data->data set $kgm_idx = 0 while ( $kgm_idx < $kgm_data->length ) printf "%02X", *$kgm_datap set $kgm_datap = $kgm_datap + 1 set $kgm_idx = $kgm_idx + 1 end printf ">\n" end define showdata set $kgm_data = (OSData *)$arg0 printf "<" set $kgm_datap = (const unsigned char *) $kgm_data->data set $kgm_printstr = 0 if (0 == (3 & (unsigned int)$kgm_datap) && ($kgm_data->length >= 3)) set $kgm_bytes = *(unsigned int *) $kgm_datap if (0xffff0000 & $kgm_bytes) set $kgm_idx = 0 set $kgm_printstr = 1 while ($kgm_idx++ < 4) set $kgm_bytes = $kgm_bytes >> 8 set $kgm_char = 0xff & $kgm_bytes if ($kgm_char && (($kgm_char < 0x20) || ($kgm_char > 0x7e))) set $kgm_printstr = 0 end end end end set $kgm_idx = 0 if ($kgm_printstr) set $kgm_quoted = 0 while ($kgm_idx < $kgm_data->length) set $kgm_char = $kgm_datap[$kgm_idx++] if ($kgm_char) if (0 == $kgm_quoted) set $kgm_quoted = 1 if ($kgm_idx > 1) printf ",\"" else printf "\"" end end printf "%c", $kgm_char else if ($kgm_quoted) set $kgm_quoted = 0 printf "\"" end end end if ($kgm_quoted) printf "\"" end else if (0 == (3 & (unsigned int)$kgm_datap)) while (($kgm_idx + 3) <= $kgm_data->length) printf "%08x", *(unsigned int *) &$kgm_datap[$kgm_idx] set $kgm_idx = $kgm_idx + 4 end end while ($kgm_idx < $kgm_data->length) printf "%02x", $kgm_datap[$kgm_idx++] end end printf ">" end define showdictionaryint set $kgm$arg0_dict = (OSDictionary *)$arg1 printf "{" set $kgm$arg0_idx = 0 while ($kgm$arg0_idx < $kgm$arg0_dict->count) set $kgm_obj = $kgm$arg0_dict->dictionary[$kgm$arg0_idx].key showobjectint _$arg0 $kgm_obj printf "=" set $kgm_obj = $kgm$arg0_dict->dictionary[$kgm$arg0_idx++].value showobjectint _$arg0 $kgm_obj if ($kgm$arg0_idx < $kgm$arg0_dict->count) printf "," end end printf "}" end define indent set $kgm_idx = 0 while ($kgm_idx < $arg0) if ($arg1 & (1 << $kgm_idx++)) printf "| " else printf " " end end end define showregdictionary indent $kgm_reg_depth+2 $arg1 printf "{\n" set $kgm_reg_idx = 0 while ($kgm_reg_idx < $arg0->count) indent $kgm_reg_depth+2 $arg1 printf " " set $kgm_obj = $arg0->dictionary[$kgm_reg_idx].key showobjectint _ $kgm_obj printf " = " set $kgm_obj = $arg0->dictionary[$kgm_reg_idx++].value showobjectint _ $kgm_obj printf "\n" end indent $kgm_reg_depth+2 $arg1 printf "}\n" end define showarraysetint set $kgm$arg0_array = (OSArray *)$arg1 set $kgm$arg0_idx = 0 while ($kgm$arg0_idx < $kgm$arg0_array->count) set $kgm_obj = $kgm$arg0_array->array[$kgm$arg0_idx++] showobjectint _$arg0 $kgm_obj if ($kgm$arg0_idx < $kgm$arg0_array->count) printf "," end end end define showarrayint printf "(" showarraysetint $arg0 $arg1 printf ")" end define showsetint set $kgm_array = ((OSSet *)$arg1)->members printf "[" showarraysetint $arg0 $kgm_array printf "]" end define showobjectint set $kgm_obj = (OSObject *) $arg1 set $kgm_vt = *((void **) $arg1) if ($kgm_lp64 || $kgm_mtype == $kgm_mtype_arm) set $kgm_vt = $kgm_vt - 2 * sizeof(void *) end if ($kgm_show_object_addrs) printf "`object " showptr $arg1 printf ", vt " output /a (unsigned long) $kgm_vt if ($kgm_show_object_retain) printf ", retain count %d, container retain %d", (0xffff & $kgm_obj->retainCount), $kgm_obj->retainCount >> 16 end printf "` " end # No multiple-inheritance set $kgm_shown = 0 if ($kgm_vt == &_ZTV8OSString) showstring $arg1 set $kgm_shown = 1 end if ($kgm_vt == &_ZTV8OSSymbol) showstring $arg1 set $kgm_shown = 1 end if ($kgm_vt == &_ZTV8OSNumber) shownumber $arg1 set $kgm_shown = 1 end if ($kgm_vt == &_ZTV6OSData) if $kgm_show_data_alwaysbytes == 1 showdatabytes $arg1 else showdata $arg1 end set $kgm_shown = 1 end if ($kgm_vt == &_ZTV9OSBoolean) showboolean $arg1 set $kgm_shown = 1 end if ($kgm_vt == &_ZTV12OSDictionary) showdictionaryint _$arg0 $arg1 set $kgm_shown = 1 end if ($kgm_vt == &_ZTV7OSArray) showarrayint _$arg0 $arg1 set $kgm_shown = 1 end if ($kgm_vt == &_ZTV5OSSet) showsetint _$arg0 $arg1 set $kgm_shown = 1 end if ($kgm_shown != 1) if ($kgm_show_object_addrs == 0) printf "`object " showptr $arg1 printf ", vt " output /a (unsigned long) $kgm_vt printf "`" end end end define showobject set $kgm_save = $kgm_show_object_addrs set $kgm_show_object_addrs = 1 set $kgm_show_object_retain = 1 showobjectint _ $arg0 set $kgm_show_object_addrs = $kgm_save set $kgm_show_object_retain = 0 printf "\n" end document showobject Syntax: (gdb) showobject | 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 if !$kgm_reg_plane set $kgm_reg_plane = (IORegistryPlane *) gIOServicePlane end if !$kgm_reg_plane printf "Please load kgmacros after KDP attaching to the target.\n" else set $kgm_namekey = (OSSymbol *) $kgm_reg_plane->nameKey set $kgm_childkey = (OSSymbol *) $kgm_reg_plane->keys[1] if $kgm_findregistry_verbose printf "Searching" end findregistryentryrecurse _ $arg0 0 0 end end define _findregistryentry set $kgm_findregistry_verbose = 0 set $kgm_findregistry_continue = 0 set $kgm_reg_depth = 0 findregistryentryint gRegistryRoot end define findregistryentry set $kgm_findregistry_verbose = 1 set $kgm_findregistry_continue = 0 set $kgm_reg_depth = 0 findregistryentryint gRegistryRoot end define findregistryentries set $kgm_findregistry_verbose = 1 set $kgm_findregistry_continue = 1 set $kgm_reg_depth = 0 findregistryentryint gRegistryRoot end document findregistryentry Syntax: (gdb) findregistryentry | Search for a registry entry that matches the encoded string specified through | setfindregistrystr. You can alter the search depth through use of | $kgm_reg_depth_max. | | For example, the following will pull out the AppleACPIPlatformExpert registry | entry: | strcmp_arg_pack64 'A' 'p' 'p' 'l' 'e' 'A' 'C' 'P' | set $AppleACP = $kgm_strcmp_arg | strcmp_arg_pack64 'I' 'P' 'l' 'a' 't' 'f' 'o' 'r' | set $IPlatfor = $kgm_strcmp_arg | strcmp_arg_pack64 'm' 'E' 'x' 'p' 'e' 'r' 't' 0 | set $mExpert = $kgm_strcmp_arg | setfindregistrystr $AppleACP $IPlatfor $mExpert | findregistryentry end document findregistryentries Syntax: (gdb) findregistryentries | Search for all registry entries that match the encoded string specified through | setfindregistrystr. You can alter the search depth through use of | $kgm_reg_depth_max. See findregistryentry for an example of how to encode a string. end define showregistryentryrecurse _registryentryrecurseinit $arg0 $arg1 $arg2 $arg3 indent $kgm_reg_depth $kgm$arg0_stack printf "+-o " dictget $kgm_re->fRegistryTable $kgm_namekey if ($kgm_result == 0) dictget $kgm_re->fRegistryTable gIONameKey end if ($kgm_result == 0) dictget $kgm_re->fPropertyTable gIOClassKey end if ($kgm_result != 0) printf "%s", ((OSString *)$kgm_result)->string else if (((IOService*)$kgm_re)->pwrMgt && ((IOService*)$kgm_re)->pwrMgt->Name) printf "%s", ((IOService*)$kgm_re)->pwrMgt->Name else # printf ", guessclass " # guessclass $kgm_re printf "??" end end printf " IORegistryEntry::reserved->fRegistryEntryID printf "vtable " set $kgm_vt = (unsigned long) *(void**) $kgm_re if ($kgm_lp64 || $kgm_mtype == $kgm_mtype_arm) set $kgm_vt = $kgm_vt - 2 * sizeof(void *) end output /a $kgm_vt if ($kgm_vt != &_ZTV15IORegistryEntry) printf ", " set $kgm_state = $kgm_re->__state[0] # kIOServiceRegisteredState if (0 == ($kgm_state & 2)) printf "!" end printf "registered, " # kIOServiceMatchedState if (0 == ($kgm_state & 4)) printf "!" end printf "matched, " # kIOServiceInactiveState if ($kgm_state & 1) printf "in" end printf "active, busy %d, retain count %d", (0xff & $kgm_re->__state[1]), (0xffff & $kgm_re->retainCount) end printf ">\n" if ($kgm_show_props) set $kgm_props = $kgm_re->fPropertyTable showregdictionary $kgm_props $kgm$arg0_stack end # recurse if ($kgm$arg0_child_count != 0) set $kgm_reg_depth = $kgm_reg_depth + 1 set $kgm$arg0_child_idx = 0 while ($kgm$arg0_child_idx < $kgm$arg0_child_count) set $kgm_re = $kgm$arg0_child_array->array[$kgm$arg0_child_idx++] set $kgm_more_sib = ($kgm$arg0_child_idx < $kgm$arg0_child_count) if $kgm_reg_depth >= $kgm_reg_depth_max + 1 loop_break end showregistryentryrecurse _$arg0 $kgm_re $kgm$arg0_stack $kgm_more_sib end set $kgm_reg_depth = $kgm_reg_depth - 1 end end define showregistryentryint if !$kgm_reg_plane set $kgm_reg_plane = (IORegistryPlane *) gIOServicePlane end if !$kgm_reg_plane printf "Please load kgmacros after KDP attaching to the target.\n" else set $kgm_namekey = (OSSymbol *) $kgm_reg_plane->nameKey set $kgm_childkey = (OSSymbol *) $kgm_reg_plane->keys[1] showregistryentryrecurse _ $arg0 0 0 end end define showregistry set $kgm_reg_depth = 0 set $kgm_show_props = 0 showregistryentryint gRegistryRoot end document showregistry Syntax: (gdb) showregistry | Show info about all registry entries in the current plane. You can specify the maximum | display depth with $kgm_reg_depth_max. end define showregistryprops set $kgm_reg_depth = 0 set $kgm_show_props = 1 showregistryentryint gRegistryRoot end document showregistryprops Syntax: (gdb) showregistryprops | Show info about all registry entries in the current plane, and their properties. | set $kgm_show_object_addrs = 1 and/or set $kgm_show_object_retain = 1 will display | more verbose information end define showregistryentry set $kgm_reg_depth = 0 set $kgm_show_props = 1 showregistryentryint $arg0 end document showregistryentry Syntax: (gdb) showregistryentry | 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 if !$kgm_reg_plane set $kgm_reg_plane = (IORegistryPlane *) gIOServicePlane end if !$kgm_reg_plane printf "Please load kgmacros after KDP attaching to the target.\n" else set $kgm_namekey = (OSSymbol *) $kgm_reg_plane->nameKey set $kgm_childkey = (OSSymbol *) $kgm_reg_plane->keys[1] showregistryentryrecursepmstate _ $arg0 0 0 end 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 define kdp-connect if $argc > 0 kdp-reattach $arg0 else printf "Attempting to attach to localhost...\n" kdp-reattach localhost end end document kdp-connect Syntax: (gdb) kdpconnect | Attach to the machine with given hostname or IP address, or 'localhost' if blank end