+set $DLIF_INUSE = 0x1
+set $DLIF_REUSE = 0x2
+
+define showifnets
+ set $all = 0
+ if ($argc == 1)
+ set $all = 1
+ end
+ set $dlifp = (struct dlil_ifnet *)(dlil_ifnet_head->tqh_first)
+ while ($dlifp != 0)
+ set $ifp = (struct ifnet *)$dlifp
+ if ($dlifp->dl_if_flags & $DLIF_REUSE)
+ printf "*"
+ end
+ if ($dlifp->dl_if_flags & $DLIF_INUSE)
+ printf "%s%d: ", $ifp->if_name, $ifp->if_unit
+ else
+ printf "[%s%d]: ", $ifp->if_name, $ifp->if_unit
+ end
+ printf "flags=%hx", (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 ($all == 1)
+ showifaddrs $ifp
+ end
+ set $dlifp = $dlifp->dl_if_link->tqe_next
+ end
+end
+
+document showifnets
+Syntax: (gdb) showifnets
+| Display ifconfig-like output for all attached and detached interfaces
+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 <socket_address>
+| 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 <proc_address>
+| 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_RECV_ANYIF=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_RECV_ANYIF)
+ printf "recv_anyif "
+ 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 $snd_buf = (unsigned int)0
+ set $rcv_cc = 0
+ set $rcv_buf = (unsigned int)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 $mp = $so->so_snd.sb_mb
+ while $mp
+ set $snd_buf += 256
+ if ($mp->m_hdr.mh_flags & 0x01)
+ set $snd_buf += $mp->M_dat.MH.MH_dat.MH_ext.ext_size
+ end
+ set $mp = $mp->m_hdr.mh_next
+ end
+ set $rcv_cc += $so->so_rcv.sb_cc
+ set $mp = $so->so_rcv.sb_mb
+ while $mp
+ set $rcv_buf += 256
+ if ($mp->m_hdr.mh_flags & 0x01)
+ set $rcv_buf += $mp->M_dat.MH.MH_dat.MH_ext.ext_size
+ end
+ set $mp = $mp->m_hdr.mh_next
+ end
+ 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 "total snd_buf %u rcv_buf %u \n", (unsigned int)$snd_buf, (unsigned int)$rcv_buf
+ 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 <vnode>
+| 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
+ # If this is HFS vnode, get name from the cnode
+ if ($kgm_vnode->v_tag == 16)
+ set $kgm_cnode = (struct cnode *)$kgm_vnode->v_data
+ printf "hfs: %s\n", (char *)$kgm_cnode->c_desc->cd_nameptr
+ else
+ printf "\n"
+ end
+ end
+end
+
+define showvnode
+ showvnodeheader
+ showvnodeint $arg0
+end
+
+document showvnode
+Syntax: (gdb) showvnode <vnode>
+| 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 <mouont_t>
+| 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 <mount_t>
+| 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 <vnode>
+| 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 <vnode_t>
+| 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 "Convention"
+ 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 = &tasks
+ set $kgm_taskp = (struct task *)$arg0
+ set $kgm_taskp = (struct task *)$kgm_taskp->tasks.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 showstacksaftertask
+Syntax: (gdb) showstacksaftertask <task>
+| 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_workqueue = (IOPMWorkQueue *)$arg0
+ set $kgm_pm_wq = &($kgm_pm_workqueue->fWorkQueue)
+ set $kgm_pm_wqe = (IOServicePM *)$kgm_pm_wq->next
+ while ((queue_entry_t) $kgm_pm_wqe != (queue_entry_t) $kgm_pm_wq)
+ printf "service "
+ showptrhdrpad
+ printf " ps ms wr name\n"
+ showptr $kgm_pm_wqe->Owner
+ printf " "
+ printf "%02d ", $kgm_pm_wqe->CurrentPowerState
+ printf "%02d ", $kgm_pm_wqe->MachineState
+ printf "%02d ", $kgm_pm_wqe->WaitReason
+ printf "%s\n", $kgm_pm_wqe->Name
+ printf "request "
+ showptrhdrpad
+ printf " type next "
+ showptrhdrpad
+ printf " root "
+ showptrhdrpad
+ printf " work_wait free_wait\n"
+ set $kgm_pm_rq = &($kgm_pm_wqe->RequestHead)
+ set $kgm_pm_rqe = (IOPMRequest *)$kgm_pm_rq->next
+ while ((queue_entry_t) $kgm_pm_rqe != (queue_entry_t) $kgm_pm_rq)
+ showptr $kgm_pm_rqe
+ printf " 0x%02x ", $kgm_pm_rqe->fType
+ showptr $kgm_pm_rqe->fRequestNext
+ printf " "
+ showptr $kgm_pm_rqe->fRequestRoot
+ printf " 0x%08x 0x%08x\n", $kgm_pm_rqe->fWorkWaitCount, $kgm_pm_rqe->fFreeWaitCount
+ showptrhdrpad
+ printf " args "
+ showptr $kgm_pm_rqe->fArg0
+ printf " "
+ showptr $kgm_pm_rqe->fArg1
+ printf " "
+ showptr $kgm_pm_rqe->fArg2
+ printf "\n"
+ set $kgm_pm_rqe = (IOPMRequest *)$kgm_pm_rqe->fCommandChain.next
+ end
+ printf "\n"
+ set $kgm_pm_wqe = (IOServicePM *)$kgm_pm_wqe->WorkChain.next
+ end
+end
+
+define showpmworkqueue
+ printf "IOPMWorkQueue "
+ showptr gIOPMWorkQueue
+ printf " length "
+ printf "%u", gIOPMWorkQueue->fQueueLength
+ printf "\n"
+ if (gIOPMWorkQueue->fQueueLength > 0)
+ showpmworkqueueint gIOPMWorkQueue
+ end
+end
+
+document showpmworkqueue
+Syntax: (gdb) showpmworkqueue
+| Display the IOPMWorkQueue object
+end
+
+define showioservicepm
+ set $kgm_iopmpriv = (IOServicePM *)$arg0
+ printf "{ "
+ printf "MachineState = %d (", $kgm_iopmpriv->MachineState
+ if ( $kgm_iopmpriv->MachineState == 0 )
+ printf "kIOPM_Finished"
+ else
+ 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_OurChangeTellCapabilityDidChange"
+ else
+ if ( $kgm_iopmpriv->MachineState == 8 )
+ printf "kIOPM_OurChangeFinish"
+ else
+ if ( $kgm_iopmpriv->MachineState == 9 )
+ printf "Unused_MachineState_9"
+ else
+ if ( $kgm_iopmpriv->MachineState == 10 )
+ printf "kIOPM_ParentChangeTellPriorityClientsPowerDown"
+ else
+ if ( $kgm_iopmpriv->MachineState == 11 )
+ printf "kIOPM_ParentChangeNotifyInterestedDriversWillChange"
+ else
+ if ( $kgm_iopmpriv->MachineState == 12 )
+ printf "kIOPM_ParentChangeSetPowerState"
+ else
+ if ( $kgm_iopmpriv->MachineState == 13 )
+ printf "kIOPM_ParentChangeWaitForPowerSettle"
+ else
+ if ( $kgm_iopmpriv->MachineState == 14)
+ printf "kIOPM_ParentChangeNotifyInterestedDriversDidChange"
+ else
+ if ( $kgm_iopmpriv->MachineState == 15)
+ printf "kIOPM_ParentChangeTellCapabilityDidChange"
+ else
+ if ( $kgm_iopmpriv->MachineState == 16)
+ printf "kIOPM_ParentChangeAcknowledgePowerChange"
+ else
+ if ( $kgm_iopmpriv->MachineState == 17)
+ printf "kIOPM_NotifyChildrenStart"
+ else
+ if ( $kgm_iopmpriv->MachineState == 18)
+ printf "kIOPM_NotifyChildrenOrdered"
+ else
+ if ( $kgm_iopmpriv->MachineState == 19)
+ printf "kIOPM_NotifyChildrenDelayed"
+ else
+ if ( $kgm_iopmpriv->MachineState == 20)
+ printf "kIOPM_SyncTellClientsPowerDown"
+ else
+ if ( $kgm_iopmpriv->MachineState == 21)
+ printf "kIOPM_SyncTellPriorityClientsPowerDown"
+ else
+ if ( $kgm_iopmpriv->MachineState == 22)
+ printf "kIOPM_SyncNotifyWillChange"
+ else
+ if ( $kgm_iopmpriv->MachineState == 23)
+ printf "kIOPM_SyncNotifyDidChange"
+ else
+ if ( $kgm_iopmpriv->MachineState == 24)
+ printf "kIOPM_SyncTellCapabilityDidChange"
+ else
+ if ( $kgm_iopmpriv->MachineState == 25)
+ printf "kIOPM_SyncFinish"
+ else
+ if ( $kgm_iopmpriv->MachineState == 26)
+ printf "kIOPM_TellCapabilityChangeDone"
+ else
+ if ( $kgm_iopmpriv->MachineState == 27)
+ printf "kIOPM_DriverThreadCallDone"
+ else
+ printf "Unknown_MachineState"
+ end
+ end
+ end
+ end
+ end
+ end
+ 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->HeadNoteChangeFlags
+ printf "HeadNotePendingAcks = %x, ",(unsigned int)$kgm_iopmpriv->HeadNotePendingAcks
+ end
+
+ if ( $kgm_iopmpriv->DeviceOverrideEnabled != 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->PreviousRequestPowerFlags
+end
+
+document showioservicepm
+Syntax: (gdb) showioservicepm <IOServicePM pointer>
+| 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 = &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)
+ if $kgm_actp == 0
+ set $kgm_actp = (struct thread *)($kgm_taskp->threads.next)
+ end
+ 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)
+ set $kgm_actp = 0
+ end
+end
+
+document showstacksafterthread
+Syntax: (gdb) showstacksafterthread <thread>
+| 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 <seconds>
+| Schedules reentry into the debugger after <seconds> 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 >= 3
+ 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 < 2
+ 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 & (0x1ULL << 63)
+ printf " noexec"
+ end
+ printf "\n"
+ end
+end
+
+define _pml4_walk
+ set $kgm_pt_paddr = $arg0
+ set $kgm_vaddr = $arg1
+ 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 >= 2
+ 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 >= 2
+ 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 >= 2
+ 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 >= 2
+ 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
+ set $kgm_paddr_isvalid = 1
+ else
+ set $kgm_paddr = 0
+ set $kgm_paddr_isvalid = 0
+ end
+
+ if $kgm_pt_verbose >= 1
+ if $kgm_paddr_isvalid
+ 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
+ printf "(no translation)\n"
+ end
+ end
+end
+
+define _pmap_walk_x86
+ set $kgm_pmap = (pmap_t) $arg0
+ _pml4_walk $kgm_pmap->pm_cr3 $arg1
+end
+
+define _pmap_walk_arm_level1_section
+ set $kgm_tte_p = $arg0
+ set $kgm_tte = *$kgm_tte_p
+ set $kgm_vaddr = $arg1
+
+ # Supersection or just section?
+ if (($kgm_tte & 0x00040000) == 0x00040000)
+ set $kgm_paddr = ($kgm_tte & 0xFF000000) | ($kgm_vaddr & 0x00FFFFFF)
+ set $kgm_paddr_isvalid = 1
+ else
+ set $kgm_paddr = ($kgm_tte & 0xFFF00000) | ($kgm_vaddr & 0x000FFFFF)
+ set $kgm_paddr_isvalid = 1
+ end
+
+ if $kgm_pt_verbose >= 2
+ printf "0x%08x\n\t0x%08x\n\t", (unsigned long)$kgm_tte_p, $kgm_tte
+
+ # bit [1:0] evaluated in _pmap_walk_arm
+
+ # B bit 2
+ set $kgm_b_bit = (($kgm_tte & 0x00000004) >> 2)
+
+ # C bit 3
+ set $kgm_c_bit = (($kgm_tte & 0x00000008) >> 3)
+
+ # XN bit 4
+ if ($kgm_tte & 0x00000010)
+ printf "no-execute"
+ else
+ printf "execute"
+ end
+
+ # Domain bit [8:5] if not supersection
+ if (($kgm_tte & 0x00040000) == 0x00000000)
+ printf " domain(%d)", (($kgm_tte & 0x000001e0) >> 5)
+ end
+
+ # IMP bit 9
+ printf " imp(%d)", (($kgm_tte & 0x00000200) >> 9)
+
+ # AP bit 15 and [11:10], merged to a single 3-bit value
+ set $kgm_access = (($kgm_tte & 0x00000c00) >> 10) | (($kgm_tte & 0x00008000) >> 13)
+ if ($kgm_access == 0x0)
+ printf " noaccess"
+ end
+ if ($kgm_access == 0x1)
+ printf " supervisor(readwrite) user(noaccess)"
+ end
+ if ($kgm_access == 0x2)
+ printf " supervisor(readwrite) user(readonly)"
+ end
+ if ($kgm_access == 0x3)
+ printf " supervisor(readwrite) user(readwrite)"
+ end
+ if ($kgm_access == 0x4)
+ printf " noaccess(reserved)"
+ end
+ if ($kgm_access == 0x5)
+ printf " supervisor(readonly) user(noaccess)"
+ end
+ if ($kgm_access == 0x6)
+ printf " supervisor(readonly) user(readonly)"
+ end
+ if ($kgm_access == 0x7)
+ printf " supervisor(readonly) user(readonly)"
+ end
+
+ # TEX bit [14:12]
+ set $kgm_tex_bits = (($kgm_tte & 0x00007000) >> 12)
+
+ # Print TEX, C, B all together
+ printf " TEX:C:B(%d%d%d:%d:%d)", ($kgm_tex_bits & 0x4 ? 1 : 0), ($kgm_tex_bits & 0x2 ? 1 : 0), ($kgm_tex_bits & 0x1 ? 1 : 0), $kgm_c_bit, $kgm_b_bit
+
+ # S bit 16
+ if ($kgm_tte & 0x00010000)
+ printf " shareable"
+ else
+ printf " not-shareable"
+ end
+
+ # nG bit 17
+ if ($kgm_tte & 0x00020000)
+ printf " not-global"
+ else
+ printf " global"
+ end
+
+ # Supersection bit 18
+ if ($kgm_tte & 0x00040000)
+ printf " supersection"
+ else
+ printf " section"
+ end
+
+ # NS bit 19
+ if ($kgm_tte & 0x00080000)
+ printf " no-secure"
+ else
+ printf " secure"
+ end
+
+ printf "\n"
+ end
+end
+
+define _pmap_walk_arm_level2
+ set $kgm_tte_p = $arg0
+ set $kgm_tte = *$kgm_tte_p
+ set $kgm_vaddr = $arg1
+
+ set $kgm_pte_pbase = (($kgm_tte & 0xFFFFFC00) - gPhysBase + gVirtBase)
+ set $kgm_pte_index = ($kgm_vaddr >> 12) & 0x000000FF
+ set $kgm_pte_p = &((pt_entry_t *)$kgm_pte_pbase)[$kgm_pte_index]
+ set $kgm_pte = *$kgm_pte_p
+
+ # Print first level symbolically
+ if $kgm_pt_verbose >= 2
+ printf "0x%08x\n\t0x%08x\n\t", (unsigned long)$kgm_tte_p, $kgm_tte
+
+ # bit [1:0] evaluated in _pmap_walk_arm
+
+ # NS bit 3
+ if ($kgm_tte & 0x00000008)
+ printf "no-secure"
+ else
+ printf "secure"
+ end
+
+ # Domain bit [8:5]
+ printf " domain(%d)", (($kgm_tte & 0x000001e0) >> 5)
+
+ # IMP bit 9
+ printf " imp(%d)", (($kgm_tte & 0x00000200) >> 9)
+
+ printf "\n"
+ end
+
+ if $kgm_pt_verbose >= 2
+ printf "second-level table (index %d):\n", $kgm_pte_index
+ end
+ if $kgm_pt_verbose >= 3
+ set $kgm_pte_loop = 0
+ while $kgm_pte_loop < 256
+ set $kgm_pte_p_tmp = &((pt_entry_t *)$kgm_pte_pbase)[$kgm_pte_loop]
+ printf "0x%08x:\t0x%08x\n", (unsigned long)$kgm_pte_p_tmp, *$kgm_pte_p_tmp
+ set $kgm_pte_loop = $kgm_pte_loop + 1
+ end
+ end
+
+ if ($kgm_pte & 0x00000003)
+ set $kgm_pve_p = (pv_entry_t *)($kgm_pte_pbase + 0x100*sizeof(pt_entry_t) + $kgm_pte_index*sizeof(pv_entry_t))
+ if ($kgm_pve_p->shadow != 0)
+ set $kgm_spte = $kgm_pve_p->shadow ^ ($kgm_vaddr & ~0xFFF)
+ set $kgm_paddr = ($kgm_spte & 0xFFFFF000) | ($kgm_vaddr & 0xFFF)
+ set $kgm_paddr_isvalid = 1
+ else
+ set $kgm_paddr = (*$kgm_pte_p & 0xFFFFF000) | ($kgm_vaddr & 0xFFF)
+ set $kgm_paddr_isvalid = 1
+ end
+ else
+ set $kgm_paddr = 0
+ set $kgm_paddr_isvalid = 0
+ end
+
+ if $kgm_pt_verbose >= 2
+ printf "0x%08x\n\t0x%08x\n\t", (unsigned long)$kgm_pte_p, $kgm_pte
+ if (($kgm_pte & 0x00000003) == 0x00000000)
+ printf "invalid"
+ else
+ if (($kgm_pte & 0x00000003) == 0x00000001)
+ printf "large"
+
+ # XN bit 15
+ if ($kgm_pte & 0x00008000) == 0x00008000
+ printf " no-execute"
+ else
+ printf " execute"
+ end
+ else
+ printf "small"
+
+ # XN bit 0
+ if ($kgm_pte & 0x00000001) == 0x00000001
+ printf " no-execute"
+ else
+ printf " execute"
+ end
+ end
+
+ # B bit 2
+ set $kgm_b_bit = (($kgm_pte & 0x00000004) >> 2)
+
+ # C bit 3
+ set $kgm_c_bit = (($kgm_pte & 0x00000008) >> 3)
+
+ # AP bit 9 and [5:4], merged to a single 3-bit value
+ set $kgm_access = (($kgm_pte & 0x00000030) >> 4) | (($kgm_pte & 0x00000200) >> 7)
+ if ($kgm_access == 0x0)
+ printf " noaccess"
+ end
+ if ($kgm_access == 0x1)
+ printf " supervisor(readwrite) user(noaccess)"
+ end
+ if ($kgm_access == 0x2)
+ printf " supervisor(readwrite) user(readonly)"
+ end
+ if ($kgm_access == 0x3)
+ printf " supervisor(readwrite) user(readwrite)"
+ end
+ if ($kgm_access == 0x4)
+ printf " noaccess(reserved)"
+ end
+ if ($kgm_access == 0x5)
+ printf " supervisor(readonly) user(noaccess)"
+ end
+ if ($kgm_access == 0x6)
+ printf " supervisor(readonly) user(readonly)"
+ end
+ if ($kgm_access == 0x7)
+ printf " supervisor(readonly) user(readonly)"
+ end
+
+ # TEX bit [14:12] for large, [8:6] for small
+ if (($kgm_pte & 0x00000003) == 0x00000001)
+ set $kgm_tex_bits = (($kgm_pte & 0x00007000) >> 12)
+ else
+ set $kgm_tex_bits = (($kgm_pte & 0x000001c0) >> 6)
+ end
+
+ # Print TEX, C, B all together
+ printf " TEX:C:B(%d%d%d:%d:%d)", ($kgm_tex_bits & 0x4 ? 1 : 0), ($kgm_tex_bits & 0x2 ? 1 : 0), ($kgm_tex_bits & 0x1 ? 1 : 0), $kgm_c_bit, $kgm_b_bit
+
+ # S bit 10
+ if ($kgm_pte & 0x00000400)
+ printf " shareable"
+ else
+ printf " not-shareable"
+ end
+
+ # nG bit 11
+ if ($kgm_pte & 0x00000800)
+ printf " not-global"
+ else
+ printf " global"
+ end
+
+ end
+ printf "\n"
+ end
+end
+
+# See ARM ARM Section B3.3
+define _pmap_walk_arm
+ set $kgm_pmap = (pmap_t) $arg0
+ set $kgm_vaddr = $arg1
+ set $kgm_paddr = 0
+ set $kgm_paddr_isvalid = 0
+
+ # Shift by TTESHIFT (20) to get tte index
+ set $kgm_tte_index = (($kgm_vaddr - $kgm_pmap->min) >> 20)
+ set $kgm_tte_p = &$kgm_pmap->tte[$kgm_tte_index]
+ set $kgm_tte = *$kgm_tte_p
+ if $kgm_pt_verbose >= 2
+ printf "first-level table (index %d):\n", $kgm_tte_index
+ end
+ if $kgm_pt_verbose >= 3
+ set $kgm_tte_loop = 0
+ while $kgm_tte_loop < 4096
+ set $kgm_tte_p_tmp = &$kgm_pmap->tte[$kgm_tte_loop]
+ printf "0x%08x:\t0x%08x\n", (unsigned long)$kgm_tte_p_tmp, *$kgm_tte_p_tmp
+ set $kgm_tte_loop = $kgm_tte_loop + 1
+ end
+ end
+
+ if (($kgm_tte & 0x00000003) == 0x00000001)
+ _pmap_walk_arm_level2 $kgm_tte_p $kgm_vaddr
+ else
+ if (($kgm_tte & 0x00000003) == 0x00000002)
+ _pmap_walk_arm_level1_section $kgm_tte_p $kgm_vaddr
+ else
+ set $kgm_paddr = 0
+ set $kgm_paddr_isvalid = 0
+ if $kgm_pt_verbose >= 2
+ printf "Invalid First-Level Translation Table Entry: 0x%08x\n", $kgm_tte
+ end
+ end
+ end
+
+ if $kgm_pt_verbose >= 1
+ if $kgm_paddr_isvalid
+ 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
+ printf "(no translation)\n"
+ end
+ end
+end
+
+define pmap_walk
+ if $argc != 2
+ printf "pmap_walk <pmap> <vaddr>\n"
+ else
+ if !$kgm_pt_verbose
+ set $kgm_pt_verbose = 2
+ else
+ if $kgm_pt_verbose > 3
+ set $kgm_pt_verbose = 2
+ end
+ end
+ if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any)
+ _pmap_walk_x86 $arg0 $arg1
+ else
+ if ($kgm_mtype == $kgm_mtype_arm)
+ _pmap_walk_arm $arg0 $arg1
+ else
+ printf "Not available for current architecture.\n"
+ end
+ end
+ end
+end
+
+document pmap_walk
+Syntax: (gdb) pmap_walk <pmap> <virtual_address>
+| Perform a page-table walk in <pmap> for <virtual_address>.
+| Set:
+| $kgm_pt_verbose=0 for no output, $kgm_paddr will be set
+| if $kgm_paddr_isvalid is 1
+| $kgm_pt_verbose=1 for final physical address
+| $kgm_pt_verbose=2 for dump of page table entry.
+| $kgm_pt_verbose=3 for full hex dump of page tables.
+end
+
+define pmap_vtop
+ if $argc != 2
+ printf "pmap_vtop <pamp> <vaddr>\n"
+ else
+ set $kgm_pt_verbose = 1
+ if (($kgm_mtype & $kgm_mtype_x86_mask) == $kgm_mtype_x86_any)
+ _pmap_walk_x86 $arg0 $arg1
+ else
+ if ($kgm_mtype == $kgm_mtype_arm)
+ _pmap_walk_arm $arg0 $arg1
+ else
+ printf "Not available for current architecture.\n"
+ end
+ end
+ end
+end
+
+document pmap_vtop
+Syntax: (gdb) pmap_vtop <pmap> <virtual_address>
+| For page-tables in <pmap> translate <virtual_address> to physical address.
+end
+
+define zstack
+ set $index = $arg0
+
+ if (log_records == 0)
+ set $count = 0
+ printf "Zone logging not enabled. Add 'zlog=<zone name>' 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
+ showptr zrecords[$index].z_element
+ printf " : index %d : ztime %d -------------\n", $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 <index> [<count>]
+| Zone leak debugging: print the stack trace of log element at <index>.
+| If a <count> is supplied, it prints <count> log elements starting at <index>.
+|
+| 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=<zone name>' 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=<zone name>' 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 <pc>
+| Zone leak debugging: search the log and print a count of all log entries that contain the given <pc>
+| in the stack trace. This is useful for verifying a suspected <pc> as being the source of
+| the leak. If a high percentage of the log entries contain the given <pc>, 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=<zone name>' 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 <elem addr>
+| 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, and
+# $kgm_readphys_use_kdp/$kgm_readphys_force_physmap to override
+# how the user pages are accessed ($kgm_readphys_force_physmap
+# implies walking the user task's pagetables to get a physical
+# address and then shadowing data from there using the
+# physical mapping of memory).
+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_readphys_force_kdp != 0)
+ set $kgm_readphys_use_kdp = 1
+ else
+ if ($kgm_readphys_force_physmap)
+ set $kgm_readphys_use_kdp = 0
+ else
+ set $kgm_readphys_use_kdp = ( kdp->is_conn > 0 )
+ end
+ end
+
+ if ($kgm_readphys_use_kdp)
+
+ 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
+
+ else
+ # without the benefit of a KDP stub on the target, try to
+ # find the user task's physical mapping and memcpy the data.
+ # If it straddles a page boundary, copy in two passes
+ set $kgm_vaddr_range1_start = (unsigned long long)$arg1
+ set $kgm_vaddr_range1_count = (unsigned long long)$arg2
+ if (($kgm_vaddr_range1_start + $kgm_vaddr_range1_count) & 0xFFF) < $kgm_vaddr_range1_count
+ set $kgm_vaddr_range2_start = ($kgm_vaddr_range1_start + $kgm_vaddr_range1_count) & ~((unsigned long long)0xFFF)
+ set $kgm_vaddr_range2_count = $kgm_vaddr_range1_start + $kgm_vaddr_range1_count - $kgm_vaddr_range2_start
+ set $kgm_vaddr_range1_count = $kgm_vaddr_range2_start - $kgm_vaddr_range1_start
+ else
+ set $kgm_vaddr_range2_start = 0
+ set $kgm_vaddr_range2_count = 0
+ end
+ set $kgm_paddr_range1_in_kva = 0
+ set $kgm_paddr_range2_in_kva = 0
+
+ if ($kgm_mtype == $kgm_mtype_x86_64)
+ set $kgm_pt_verbose = 0
+ _pmap_walk_x86 $kgm_map_user_pmap $kgm_vaddr_range1_start
+ if $kgm_paddr_isvalid
+ set $kgm_paddr_range1_in_kva = $kgm_paddr + physmap_base
+ end
+ if $kgm_vaddr_range2_start
+ _pmap_walk_x86 $kgm_map_user_pmap $kgm_vaddr_range2_start
+ if $kgm_paddr_isvalid
+ set $kgm_paddr_range2_in_kva = $kgm_paddr + physmap_base
+ end
+ end
+ else
+ if ($kgm_mtype == $kgm_mtype_arm)
+ set $kgm_pt_verbose = 0
+ _pmap_walk_arm $kgm_map_user_pmap $kgm_vaddr_range1_start
+ if $kgm_paddr_isvalid
+ set $kgm_paddr_range1_in_kva = $kgm_paddr - gPhysBase + gVirtBase
+ end
+ if $kgm_vaddr_range2_start
+ _pmap_walk_arm $kgm_map_user_pmap $kgm_vaddr_range2_start
+ if $kgm_paddr_isvalid
+ set $kgm_paddr_range2_in_kva = $kgm_paddr - gPhysBase + gVirtBase
+ end
+ end
+ else
+ printf "Not available for current architecture.\n"
+ set $kgm_paddr_isvalid = 0
+ end
+ end
+ if $kgm_paddr_range1_in_kva
+ set $kgm_pkt = (kdp_readmem64_reply_t *)&manual_pkt.data
+ memcpy $kgm_pkt->data $kgm_paddr_range1_in_kva $kgm_vaddr_range1_count
+ if $kgm_paddr_range2_in_kva
+ memcpy &$kgm_pkt->data[$kgm_vaddr_range1_count] $kgm_paddr_range2_in_kva $kgm_vaddr_range2_count
+ end
+ 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
+
+ if ($kgm_print_path_address == 0)
+ set $kgm_path_str_notdone = 0
+ end
+
+ 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
+
+ # break out if we terminated on NUL
+ 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. May modify $kgm_dyld_load_path
+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
+ if $kgm_lc_cmd == 0xe
+ set $kgm_load_dylinker_data = $kgm_lc_data
+ set $kgm_dyld_load_path = $kgm_lc_address + *((unsigned int *)$kgm_load_dylinker_data)
+ end
+ _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 112
+
+ set $kgm_dyld_all_image_infos = (unsigned int *)$kgm_map_user_window
+ set $kgm_dyld_all_image_infos_version = $kgm_dyld_all_image_infos[0]
+ if ($kgm_dyld_all_image_infos_version > 12)
+ printf "Unknown dyld all_image_infos version number %d\n", $kgm_dyld_all_image_infos_version
+ end
+ set $kgm_image_info_count = $kgm_dyld_all_image_infos[1]
+
+ set $kgm_dyld_load_path = 0
+ 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]
+ set $kgm_dyld_load_address = ((unsigned long long *)$kgm_dyld_all_image_infos)[4]
+ set $kgm_dyld_all_image_infos_address_from_struct = ((unsigned long long *)$kgm_dyld_all_image_infos)[13]
+ else
+ set $kgm_image_info_size = 12
+ set $kgm_image_info_array_address = ((unsigned int *)$kgm_dyld_all_image_infos)[2]
+ set $kgm_dyld_load_address = ((unsigned int *)$kgm_dyld_all_image_infos)[5]
+ set $kgm_dyld_all_image_infos_address_from_struct = ((unsigned int *)$kgm_dyld_all_image_infos)[14]
+ end
+
+ _unmap_user_data_from_task $kgm_taskp
+
+ # Account for ASLR slide before dyld can fix the structure
+ set $kgm_dyld_load_address = $kgm_dyld_load_address + ($kgm_dyld_all_image_infos_address - $kgm_dyld_all_image_infos_address_from_struct)
+
+ 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
+
+ # $kgm_dyld_load_path may get set when the main executable is processed
+ # printf "[dyld] = image address %llx path address %llx\n", $kgm_dyld_load_address, $kgm_dyld_load_path
+ _print_image_info $kgm_dyld_load_address $kgm_dyld_load_path
+
+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 <task_t>
+| For a given user task, inspect the dyld shared library state and print
+| information about all Mach-O images.
+end
+
+define showuserdyldinfo
+ set $kgm_taskp = (task_t)$arg0
+ set $kgm_dyld_all_image_infos_address = (unsigned long long)$kgm_taskp->all_image_info_addr
+
+ set $kgm_map = $kgm_taskp->map
+ set $kgm_task_64 = ( $kgm_taskp->taskFeatures[0] & 0x80000000)
+
+ if ($kgm_dyld_all_image_infos_address != 0)
+
+ _map_user_data_from_task $kgm_taskp $kgm_dyld_all_image_infos_address 112
+
+ set $kgm_dyld_all_image_infos = (unsigned char *)$kgm_map_user_window
+ set $kgm_dyld_all_image_infos_version = ((unsigned int *)$kgm_dyld_all_image_infos)[0]
+ if ($kgm_dyld_all_image_infos_version > 12)
+ printf "Unknown dyld all_image_infos version number %d\n", $kgm_dyld_all_image_infos_version
+ end
+
+ # Find fields by byte offset. We assume at least version 9 is supported
+ if $kgm_task_64
+ set $kgm_dyld_all_image_infos_infoArrayCount = *(unsigned int *)(&$kgm_dyld_all_image_infos[4])
+ set $kgm_dyld_all_image_infos_infoArray = *(unsigned long long *)(&$kgm_dyld_all_image_infos[8])
+ set $kgm_dyld_all_image_infos_notification = *(unsigned long long *)(&$kgm_dyld_all_image_infos[16])
+ set $kgm_dyld_all_image_infos_processDetachedFromSharedRegion = *(unsigned char *)(&$kgm_dyld_all_image_infos[24])
+ set $kgm_dyld_all_image_infos_libSystemInitialized = *(unsigned char *)(&$kgm_dyld_all_image_infos[25])
+ set $kgm_dyld_all_image_infos_dyldImageLoadAddress = *(unsigned long long *)(&$kgm_dyld_all_image_infos[32])
+ set $kgm_dyld_all_image_infos_jitInfo = *(unsigned long long *)(&$kgm_dyld_all_image_infos[40])
+ set $kgm_dyld_all_image_infos_dyldVersion = *(unsigned long long *)(&$kgm_dyld_all_image_infos[48])
+ set $kgm_dyld_all_image_infos_errorMessage = *(unsigned long long *)(&$kgm_dyld_all_image_infos[56])
+ set $kgm_dyld_all_image_infos_terminationFlags = *(unsigned long long *)(&$kgm_dyld_all_image_infos[64])
+ set $kgm_dyld_all_image_infos_coreSymbolicationShmPage = *(unsigned long long *)(&$kgm_dyld_all_image_infos[72])
+ set $kgm_dyld_all_image_infos_systemOrderFlag = *(unsigned long long *)(&$kgm_dyld_all_image_infos[80])
+ set $kgm_dyld_all_image_infos_uuidArrayCount = *(unsigned long long *)(&$kgm_dyld_all_image_infos[88])
+ set $kgm_dyld_all_image_infos_uuidArray = *(unsigned long long *)(&$kgm_dyld_all_image_infos[96])
+ set $kgm_dyld_all_image_infos_dyldAllImageInfosAddress = *(unsigned long long *)(&$kgm_dyld_all_image_infos[104])
+ else
+ set $kgm_dyld_all_image_infos_infoArrayCount = *(unsigned int *)(&$kgm_dyld_all_image_infos[4])
+ set $kgm_dyld_all_image_infos_infoArray = *(unsigned int *)(&$kgm_dyld_all_image_infos[8])
+ set $kgm_dyld_all_image_infos_notification = *(unsigned int *)(&$kgm_dyld_all_image_infos[12])
+ set $kgm_dyld_all_image_infos_processDetachedFromSharedRegion = *(unsigned char *)(&$kgm_dyld_all_image_infos[16])
+ set $kgm_dyld_all_image_infos_libSystemInitialized = *(unsigned char *)(&$kgm_dyld_all_image_infos[17])
+ set $kgm_dyld_all_image_infos_dyldImageLoadAddress = *(unsigned int *)(&$kgm_dyld_all_image_infos[20])
+ set $kgm_dyld_all_image_infos_jitInfo = *(unsigned int *)(&$kgm_dyld_all_image_infos[24])
+ set $kgm_dyld_all_image_infos_dyldVersion = *(unsigned int *)(&$kgm_dyld_all_image_infos[28])
+ set $kgm_dyld_all_image_infos_errorMessage = *(unsigned int *)(&$kgm_dyld_all_image_infos[32])
+ set $kgm_dyld_all_image_infos_terminationFlags = *(unsigned int *)(&$kgm_dyld_all_image_infos[36])
+ set $kgm_dyld_all_image_infos_coreSymbolicationShmPage = *(unsigned int *)(&$kgm_dyld_all_image_infos[40])
+ set $kgm_dyld_all_image_infos_systemOrderFlag = *(unsigned int *)(&$kgm_dyld_all_image_infos[44])
+ set $kgm_dyld_all_image_infos_uuidArrayCount = *(unsigned int *)(&$kgm_dyld_all_image_infos[48])
+ set $kgm_dyld_all_image_infos_uuidArray = *(unsigned int *)(&$kgm_dyld_all_image_infos[52])
+ set $kgm_dyld_all_image_infos_dyldAllImageInfosAddress = *(unsigned int *)(&$kgm_dyld_all_image_infos[56])
+ end
+
+ _unmap_user_data_from_task $kgm_taskp
+
+ set $kgm_dyld_all_imfo_infos_slide = ( $kgm_dyld_all_image_infos_address - $kgm_dyld_all_image_infos_dyldAllImageInfosAddress )
+ set $kgm_dyld_all_image_infos_dyldVersion_postslide = ( $kgm_dyld_all_image_infos_dyldVersion + $kgm_dyld_all_imfo_infos_slide )
+
+ printf " version %u\n", $kgm_dyld_all_image_infos_version
+ printf " infoArrayCount %u\n", $kgm_dyld_all_image_infos_infoArrayCount
+ printf " infoArray "
+ showuserptr $kgm_dyld_all_image_infos_infoArray
+ printf "\n"
+ printf " notification "
+ showuserptr $kgm_dyld_all_image_infos_notification
+ printf "\n"
+ printf "processDetachedFromSharedRegion %d\n", $kgm_dyld_all_image_infos_processDetachedFromSharedRegion
+ printf " libSystemInitialized %d\n", $kgm_dyld_all_image_infos_libSystemInitialized
+ printf " dyldImageLoadAddress "
+ showuserptr $kgm_dyld_all_image_infos_dyldImageLoadAddress
+ printf "\n"
+ printf " jitInfo "
+ showuserptr $kgm_dyld_all_image_infos_jitInfo
+ printf "\n"
+ printf " dyldVersion "
+ showuserptr $kgm_dyld_all_image_infos_dyldVersion
+ printf "\n"
+ printf " "
+ _print_path_for_image $kgm_dyld_all_image_infos_dyldVersion_postslide
+ if ($kgm_dyld_all_imfo_infos_slide != 0)
+ printf " (currently "
+ showuserptr $kgm_dyld_all_image_infos_dyldVersion_postslide
+ printf ")"
+ end
+ printf "\n"
+
+ printf " errorMessage "
+ showuserptr $kgm_dyld_all_image_infos_errorMessage
+ printf "\n"
+ if $kgm_dyld_all_image_infos_errorMessage != 0
+ printf " "
+ _print_path_for_image $kgm_dyld_all_image_infos_errorMessage
+ printf "\n"
+ end
+
+ printf " terminationFlags "
+ showuserptr $kgm_dyld_all_image_infos_terminationFlags
+ printf "\n"
+ printf " coreSymbolicationShmPage "
+ showuserptr $kgm_dyld_all_image_infos_coreSymbolicationShmPage
+ printf "\n"
+ printf " systemOrderFlag "
+ showuserptr $kgm_dyld_all_image_infos_systemOrderFlag
+ printf "\n"
+ printf " uuidArrayCount "
+ showuserptr $kgm_dyld_all_image_infos_uuidArrayCount
+ printf "\n"
+ printf " uuidArray "
+ showuserptr $kgm_dyld_all_image_infos_uuidArray
+ printf "\n"
+ printf " dyldAllImageInfosAddress "
+ showuserptr $kgm_dyld_all_image_infos_dyldAllImageInfosAddress
+ printf "\n"
+ printf " (currently "
+ showuserptr $kgm_dyld_all_image_infos_address
+ printf ")\n"
+
+ if $kgm_task_64
+ set $kgm_dyld_all_image_infos_address = $kgm_dyld_all_image_infos_address + 112
+ _map_user_data_from_task $kgm_taskp $kgm_dyld_all_image_infos_address 64
+ set $kgm_dyld_all_image_infos_v10 = (unsigned char *)$kgm_map_user_window
+ set $kgm_dyld_all_image_infos_initialImageCount = *(unsigned long long *)(&$kgm_dyld_all_image_infos_v10[112-112])
+ set $kgm_dyld_all_image_infos_errorKind = *(unsigned long long *)(&$kgm_dyld_all_image_infos_v10[120-112])
+ set $kgm_dyld_all_image_infos_errorClientOfDylibPath = *(unsigned long long *)(&$kgm_dyld_all_image_infos_v10[128-112])
+ set $kgm_dyld_all_image_infos_errorTargetDylibPath = *(unsigned long long *)(&$kgm_dyld_all_image_infos_v10[136-112])
+ set $kgm_dyld_all_image_infos_errorSymbol = *(unsigned long long *)(&$kgm_dyld_all_image_infos_v10[144-112])
+ set $kgm_dyld_all_image_infos_sharedCacheSlide = *(unsigned long long *)(&$kgm_dyld_all_image_infos_v10[152-112])
+
+ _unmap_user_data_from_task $kgm_taskp
+ else
+ set $kgm_dyld_all_image_infos_address = $kgm_dyld_all_image_infos_address + 60
+ _map_user_data_from_task $kgm_taskp $kgm_dyld_all_image_infos_address 64
+ set $kgm_dyld_all_image_infos_v10 = (unsigned char *)$kgm_map_user_window
+ set $kgm_dyld_all_image_infos_initialImageCount = *(unsigned int *)(&$kgm_dyld_all_image_infos_v10[60-60])
+ set $kgm_dyld_all_image_infos_errorKind = *(unsigned int *)(&$kgm_dyld_all_image_infos_v10[64-60])
+ set $kgm_dyld_all_image_infos_errorClientOfDylibPath = *(unsigned int *)(&$kgm_dyld_all_image_infos_v10[68-60])
+ set $kgm_dyld_all_image_infos_errorTargetDylibPath = *(unsigned int *)(&$kgm_dyld_all_image_infos_v10[72-60])
+ set $kgm_dyld_all_image_infos_errorSymbol = *(unsigned int *)(&$kgm_dyld_all_image_infos_v10[76-60])
+ set $kgm_dyld_all_image_infos_sharedCacheSlide = *(unsigned int *)(&$kgm_dyld_all_image_infos_v10[80-60])
+ _unmap_user_data_from_task $kgm_taskp
+ end
+
+ if $kgm_dyld_all_image_infos_version >= 10
+ printf " initialImageCount "
+ showuserptr $kgm_dyld_all_image_infos_initialImageCount
+ printf "\n"
+ end
+
+ if $kgm_dyld_all_image_infos_version >= 11
+ printf " errorKind "
+ showuserptr $kgm_dyld_all_image_infos_errorKind
+ printf "\n"
+ printf " errorClientOfDylibPath "
+ showuserptr $kgm_dyld_all_image_infos_errorClientOfDylibPath
+ printf "\n"
+ if $kgm_dyld_all_image_infos_errorClientOfDylibPath != 0
+ printf " "
+ _print_path_for_image $kgm_dyld_all_image_infos_errorClientOfDylibPath
+ printf "\n"
+ end
+ printf " errorTargetDylibPath "
+ showuserptr $kgm_dyld_all_image_infos_errorTargetDylibPath
+ printf "\n"
+ if $kgm_dyld_all_image_infos_errorTargetDylibPath != 0
+ printf " "
+ _print_path_for_image $kgm_dyld_all_image_infos_errorTargetDylibPath
+ printf "\n"
+ end
+ printf " errorSymbol "
+ showuserptr $kgm_dyld_all_image_infos_errorSymbol
+ printf "\n"
+ if $kgm_dyld_all_image_infos_errorSymbol != 0
+ printf " "
+ _print_path_for_image $kgm_dyld_all_image_infos_errorSymbol
+ printf "\n"
+ end
+ end
+
+ if $kgm_dyld_all_image_infos_version >= 12
+ printf " sharedCacheSlide "
+ showuserptr $kgm_dyld_all_image_infos_sharedCacheSlide
+ printf "\n"
+ end
+
+ else
+ printf "No dyld information available for task\n"
+ end
+end
+document showuserdyldinfo
+Syntax: (gdb) showuserdyldinfo <task_t>
+| For a given user task, inspect the dyld global info and print
+| out all fields, including error messages.
+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
+ # 0x80000000 == KDBG_BFINIT
+ if (kd_ctrl_page.kdebug_flags & 0x80000000)
+ showkerneldebugheader
+
+ if $kgm_entry_count == 0
+ printf "<count> 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.raw != 0) && ($kgm_entry_count > 0))
+ set $kgm_kdsp_actual = &kd_bufs[$kgm_kdsp.buffer_index].kdsb_addr[$kgm_kdsp.offset]
+ if $kgm_kdsp_actual->kds_readlast != $kgm_kdsp_actual->kds_bufindx
+ set $kgm_kds_bufptr = &$kgm_kdsp_actual->kds_records[$kgm_kdsp_actual->kds_bufindx]
+ while (($kgm_kds_bufptr > &$kgm_kdsp_actual->kds_records[$kgm_kdsp_actual->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_actual->kds_next
+ end
+ end
+ else
+ printf "Trace buffer not enabled\n"
+ end
+end
+
+document showkerneldebugbuffercpu
+Syntax: showkerneldebugbuffercpu <cpu> <count>
+| Prints the last N entries in the kernel debug buffer for CPU x.
+end
+
+define showkerneldebugbuffer
+ # 0x80000000 == KDBG_BFINIT
+ if (kd_ctrl_page.kdebug_flags & 0x80000000)
+
+ set $kgm_entrycount = (int) $arg0
+
+ if $kgm_entrycount == 0
+ printf "<count> 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 <count>
+| 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 memstats
+ if ($kgm_mtype == $kgm_mtype_arm)
+ printf "kern_memorystatus_level: %8d\n", kern_memorystatus_level
+ end
+ printf "vm_page_throttled_count: %8d\n", vm_page_throttled_count
+ printf "vm_page_active_count: %8d\n", vm_page_active_count
+ printf "vm_page_inactive_count: %8d\n", vm_page_inactive_count
+ printf "vm_page_wire_count: %8d\n", vm_page_wire_count
+ printf "vm_page_free_count: %8d\n", vm_page_free_count
+ printf "vm_page_purgeable_count: %8d\n", vm_page_purgeable_count
+ printf "vm_page_inactive_target: %8d\n", vm_page_inactive_target
+ printf "vm_page_free_target: %8d\n", vm_page_free_target
+ printf "inuse_ptepages_count: %8d\n", inuse_ptepages_count
+ printf "vm_page_free_reserved: %8d\n", vm_page_free_reserved
+end
+
+document memstats
+Syntax: (gdb) memstats
+| Prints out a summary of various memory statistics. In particular vm_page_wire_count should
+| be greater than 2K or you are under memory pressure.
+end
+
+define show_user_registers
+ showuserregisters $arg0
+end
+
+document show_user_registers
+Syntax: show_user_registers <thread_address>
+| 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 <a> <b> <c> <d> <e <f> <g> <h>
+| 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 <string> <a> [b] [c] [d] [e] [f] [g] [h] [i]
+| Given a pre-allocated <string>, 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
+
+define memcpy
+ set $kgm_dst = (unsigned char *)$arg0
+ set $kgm_src = (unsigned char *)$arg1
+ set $kgm_count = $arg2
+
+ # printf "src %p dst %p len %d\n", $kgm_src, $kgm_dst, $kgm_count
+
+ while ($kgm_count >= 8)
+ set *(unsigned long long *)$kgm_dst = *(unsigned long long *)$kgm_src
+
+ set $kgm_dst = $kgm_dst + 8
+ set $kgm_src = $kgm_src + 8
+ set $kgm_count = $kgm_count - 8
+ end
+ while ($kgm_count > 0)
+ set *$kgm_dst = *$kgm_src
+
+ set $kgm_dst = $kgm_dst + 1
+ set $kgm_src = $kgm_src + 1
+ set $kgm_count = $kgm_count - 1
+ end
+end
+
+document memcpy
+Syntax: memcpy <dst> <src> <n>
+| Given two addresses that are accessible by the debugger, perform
+| a memory copy of <n> bytes from <src> to <dst>
+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
+
+ # search for 0:0:0 in likely places if the above fails
+ 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 <bus> <dev> <fcn> <off>
+| read 8 bits for the given <off> of the pci device located at
+| <bus>:<dev>:<fcn>.
+end
+
+document pci_cfg_read16
+Syntax: (gdb) pci_cfg_read <bus> <dev> <fcn> <off>
+| read 16 bits for the given <off> of the pci device located at
+| <bus>:<dev>:<fcn>.
+end
+
+document pci_cfg_read32
+Syntax: (gdb) pci_cfg_read <bus> <dev> <fcn> <off>
+| read 32 bits for the given <off> of the pci device located at
+| <bus>:<dev>:<fcn>.
+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 <bus> <dev> <fcn> <off> <value>
+| write an 8-bit <value> into the given <off> of the pci device located at
+| <bus>:<dev>:<fcn>.
+end
+
+document pci_cfg_write16
+Syntax: (gdb) pci_cfg_write16 <bus> <dev> <fcn> <off> <value>
+| write a 16-bit <value> into the given <off> of the pci device located at
+| <bus>:<dev>:<fcn>.
+end
+
+document pci_cfg_write32
+Syntax: (gdb) pci_cfg_write32 <bus> <dev> <fcn> <off> <value>
+| write a 32-bit <value> into the given <off> of the pci device located at
+| <bus>:<dev>:<fcn>.
+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 <bus> <dev> <fcn>
+| dump config space for the pci device located at <bus>:<dev>:<fcn>
+| 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 <port> [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 <port> <value> [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 <msr> <value> [lcpu (kernel's numbering convention)]
+| Write <value> to the specified MSR. The CPU can be optionally specified.
+end
+
+document readmsr64
+Syntax: (gdb) readmsr64 <msr> [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_timer_tsc_deadline = 0x40000
+set $_apic_timer_periodic = 0x20000
+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"
+ else
+ printf " PEND=no "
+ end
+
+ if $value & $_apic_timer_periodic
+ printf " PERIODIC"
+ end
+ if $value & $_apic_timer_tsc_deadline
+ printf " TSC_DEADLINE"
+ end
+
+ printf "]\n"
+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 <offset>
+| 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 <offset> <value>
+| 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 <offset> [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 <offset> <value> [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"