# # Kernel gdb macros # # These gdb macros should be useful during kernel development in # determining what's going on in the kernel. # # All the convenience variables used by these macros begin with $kgm_ define showversion #Display version string, a pointer to which is pinned at 0x501C in the kernel's #low memory globals p (char *) *0x501c end document showversion Syntax: showversion | Read the kernel version string from a fixed address in low | memory. Useful if you don't know which kernel is on the other end, | and need to find the appropriate symbols. Beware that if you've | loaded a symbol file, but aren't connected to a remote target, | the version string from the symbol file will be displayed instead. | This macro expects to be connected to the remote kernel to function | correctly. end set $kgm_dummy = &proc0 set $kgm_dummy = &kmod set $kgm_mtype = ((struct mach_header)_mh_execute_header).cputype echo Loading Kernel GDB Macros package. Type "help kgm" for more info.\n define kgm printf "" echo These are the gdb macros for kernel debugging. Type "help kgm" for more info.\n end document kgm | These are the kernel gdb macros. These gdb macros are intended to be | used when debugging a remote kernel via the kdp protocol. Typically, you | would connect to your remote target like so: | (gdb) target remote-kdp | (gdb) attach | | The following macros are available in this package: | showversion Displays a string describing the remote kernel version | | showalltasks Display a summary listing of all tasks | showallthreads Display info about all threads in the system | showallstacks Display the stack for each thread in the system | showcurrentthreads Display info about the thread running on each cpu | showcurrentstacks Display the stack for the thread running on each cpu | showallvm Display a summary listing of all the vm maps | showallvme Display a summary listing of all the vm map entries | showallipc Display a summary listing of all the ipc spaces | showallrights Display a summary listing of all the ipc rights | showallkmods Display a summary listing of all the kernel modules | showallclasses Display info about all OSObject subclasses in the system | | showtask Display info about the specified task | showtaskthreads Display info about the threads in the task | showtaskstacks Display the stack for each thread in the task | showtaskvm Display info about the specified task's vm_map | showtaskvme Display info about the task's vm_map entries | showtaskipc Display info about the specified task's ipc space | showtaskrights Display info about the task's ipc space entries | | showact Display info about a thread specified by activation | showactstack Display the stack for a thread specified by activation | | showmap Display info about the specified vm_map | showmapvme Display a summary list of the specified vm_map's entries | | showipc Display info about the specified ipc space | showrights Display a summary list of all the rights in an ipc space | | showpid Display info about the process identified by pid | showproc Display info about the process identified by proc struct | | showkmod Display info about a kernel module | showkmodaddr Given an address, display the kernel module and offset | | dumpcallqueue Dump out all the entries given a queue head | | showallmtx Display info about mutexes usage | showallrwlck Display info about reader/writer locks usage | | zprint Display info about the memory zones | showioalloc Display info about iokit allocations | paniclog Display the panic log info | | switchtoact Switch to different context specified by activation | switchtoctx Switch to different context | showuserstack Display numeric backtrace of the user stack for an | activation | | switchtouserthread Switch to the user context of the specified thread | resetstacks Return to the original kernel context | | resetctx Reset context | resume_on Resume when detaching from gdb | resume_off Don't resume when detaching from gdb | | sendcore Configure kernel to send a coredump to the specified IP | disablecore Configure the kernel to disable coredump transmission | switchtocorethread Corefile version of "switchtoact" | resetcorectx Corefile version of "resetctx" | | kdp-reboot Restart remote target | | Type "help " for more specific help on a particular macro. | Type "show user " to see what the macro is really doing. end define showkmodheader printf "kmod address size " printf "id refs version name\n" end define showkmodint set $kgm_kmodp = (struct kmod_info *)$arg0 printf "0x%08x ", $arg0 printf "0x%08x ", $kgm_kmodp->address printf "0x%08x ", $kgm_kmodp->size printf "%3d ", $kgm_kmodp->id printf "%5d ", $kgm_kmodp->reference_count printf "%10s ", &$kgm_kmodp->version printf "%s\n", &$kgm_kmodp->name end set $kgm_kmodmin = 0xffffffff set $kgm_fkmodmin = 0x00000000 set $kgm_kmodmax = 0x00000000 set $kgm_fkmodmax = 0xffffffff set $kgm_pkmod = 0 set $kgm_pkmodst = 0 set $kgm_pkmoden = 0 define showkmodaddr printf "0x%x" , $arg0 if ((unsigned int)$arg0 >= (unsigned int)$kgm_pkmodst) && ((unsigned int)$arg0 <= (unsigned int)$kgm_pkmoden) set $kgm_off = ((unsigned int)$arg0 - (unsigned int)$kgm_pkmodst) printf " <%s + 0x%x>", $kgm_pkmod->name, $kgm_off else if ((unsigned int)$arg0 <= (unsigned int)$kgm_fkmodmax) && ((unsigned int)$arg0 >= (unsigned int)$kgm_fkmodmin) set $kgm_kmodp = (struct kmod_info *)kmod while $kgm_kmodp set $kgm_kmod = *$kgm_kmodp if $kgm_kmod.address && ($kgm_kmod.address < $kgm_kmodmin) set $kgm_kmodmin = $kgm_kmod.address end if ($kgm_kmod.address + $kgm_kmod.size) > $kgm_kmodmax set $kgm_kmodmax = $kgm_kmod.address end set $kgm_off = ((unsigned int)$arg0 - (unsigned int)$kgm_kmod.address) if ($kgm_kmod.address <= $arg0) && ($kgm_off <= $kgm_kmod.size) printf " <%s + 0x%x>", $kgm_kmodp->name, $kgm_off set $kgm_pkmod = $kgm_kmodp set $kgm_pkmodst = $kgm_kmod.address set $kgm_pkmoden = $kgm_pkmodst + $kgm_kmod.size set $kgm_kmodp = 0 else set $kgm_kmodp = $kgm_kmod.next end end if !$kgm_pkmod set $kgm_fkmodmin = $kgm_kmodmin set $kgm_fkmodmax = $kgm_kmodmax end end end end document showkmodaddr | Given an address, print the offset and name for the kmod containing it | The following is the syntax: | (gdb) showkmodaddr end define showkmod showkmodheader showkmodint $arg0 end document showkmod | Routine to print info about a kernel module | The following is the syntax: | (gdb) showkmod end define showallkmods showkmodheader set $kgm_kmodp = (struct kmod_info *)kmod while $kgm_kmodp showkmodint $kgm_kmodp set $kgm_kmodp = $kgm_kmodp->next end end document showallkmods | Routine to print a summary listing of all the kernel modules | The following is the syntax: | (gdb) showallkmods end define showactheader printf " activation " printf "thread pri state wait_queue wait_event\n" end define showactint printf " 0x%08x ", $arg0 set $kgm_thread = *(struct thread *)$arg0 printf "0x%08x ", $arg0 printf "%3d ", $kgm_thread.sched_pri set $kgm_state = $kgm_thread.state if $kgm_state & 0x80 printf "I" end if $kgm_state & 0x40 printf "P" end if $kgm_state & 0x20 printf "A" end if $kgm_state & 0x10 printf "H" end if $kgm_state & 0x08 printf "U" end if $kgm_state & 0x04 printf "R" end if $kgm_state & 0x02 printf "S" end if $kgm_state & 0x01 printf "W\t" printf "0x%08x ", $kgm_thread.wait_queue if ((unsigned)$kgm_thread.wait_event > (unsigned)sectPRELINKB) showkmodaddr $kgm_thread.wait_event else output /a (unsigned) $kgm_thread.wait_event end end if $arg1 != 0 if ($kgm_thread.kernel_stack != 0) if ($kgm_thread.reserved_stack != 0) printf "\n\t\treserved_stack=0x%08x", $kgm_thread.reserved_stack end printf "\n\t\tkernel_stack=0x%08x", $kgm_thread.kernel_stack if ($kgm_mtype == 18) set $mysp = $kgm_thread.machine.pcb->save_r1 else set $kgm_statep = (struct i386_kernel_state *) \ ($kgm_thread->kernel_stack + 0x4000 \ - sizeof(struct i386_kernel_state)) set $mysp = $kgm_statep->k_ebp end set $prevsp = 0 printf "\n\t\tstacktop=0x%08x", $mysp if ($kgm_mtype == 18) set $stkmask = 0xf set $stklimit = 0xb0000000 else set $stkmask = 0x3 set $stklimit = 0xfc000000 end while ($mysp != 0) && (($mysp & $stkmask) == 0) \ && ($mysp < $stklimit) \ && ((unsigned)$mysp > (unsigned)$prevsp) printf "\n\t\t0x%08x ", $mysp if ($kgm_mtype == 18) set $kgm_return = *($mysp + 8) else set $kgm_return = *($mysp + 4) end if ((unsigned) $kgm_return > (unsigned) sectPRELINKB) showkmodaddr $kgm_return else output /a (unsigned) $kgm_return end set $prevsp = $mysp set $mysp = * $mysp end printf "\n\t\tstackbottom=0x%08x", $prevsp else printf "\n\t\t\tcontinuation=" output /a (unsigned) $kgm_thread.continuation end printf "\n" else printf "\n" end end define showact showactheader showactint $arg0 0 end document showact | Routine to print out the state of a specific thread. | The following is the syntax: | (gdb) showact end define showactstack showactheader showactint $arg0 1 end document showactstack | Routine to print out the stack of a specific thread. | The following is the syntax: | (gdb) showactstack end define showallthreads set $kgm_head_taskp = &default_pset.tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader showtaskint $kgm_taskp showactheader set $kgm_head_actp = &($kgm_taskp->threads) set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) while $kgm_actp != $kgm_head_actp showactint $kgm_actp 0 set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) end printf "\n" set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next) end end document showallthreads | Routine to print out info about all threads in the system. | The following is the syntax: | (gdb) showallthreads end define showcurrentthreads set $kgm_prp = processor_list while $kgm_prp != 0 if ($kgm_prp)->active_thread != 0 set $kgm_actp = ($kgm_prp)->active_thread showtaskheader showtaskint ($kgm_actp)->task showactheader showactint $kgm_actp 0 printf "\n" end set $kgm_prp = ($kgm_prp)->processor_list end end document showcurrentthreads | Routine to print out info about the thread running on each cpu. | The following is the syntax: | (gdb) showcurrentthreads end define showallstacks set $kgm_head_taskp = &default_pset.tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader showtaskint $kgm_taskp set $kgm_head_actp = &($kgm_taskp->threads) set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) while $kgm_actp != $kgm_head_actp showactheader showactint $kgm_actp 1 set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) end printf "\n" set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next) end end document showallstacks | Routine to print out the stack for each thread in the system. | The following is the syntax: | (gdb) showallstacks end define showcurrentstacks set $kgm_prp = processor_list while $kgm_prp != 0 if ($kgm_prp)->active_thread != 0 set $kgm_actp = ($kgm_prp)->active_thread showtaskheader showtaskint ($kgm_actp)->task showactheader showactint $kgm_actp 1 printf "\n" end set $kgm_prp = ($kgm_prp)->processor_list end end document showcurrentstacks | Routine to print out the thread running on each cpu (incl. its stack) | The following is the syntax: | (gdb) showcurrentstacks end define showwaiterheader printf "waiters activation " printf "thread pri state wait_queue wait_event\n" end define showwaitqwaiters set $kgm_w_waitqp = (struct wait_queue *)$arg0 set $kgm_w_linksp = &($kgm_w_waitqp->wq_queue) set $kgm_w_wqe = (struct wait_queue_element *)$kgm_w_linksp->next set $kgm_w_found = 0 while ( (queue_entry_t)$kgm_w_wqe != (queue_entry_t)$kgm_w_linksp) if ($kgm_w_wqe->wqe_type != &_wait_queue_link) if !$kgm_w_found set $kgm_w_found = 1 showwaiterheader end set $kgm_w_shuttle = (struct thread *)$kgm_w_wqe showactint $kgm_w_shuttle 0 end set $kgm_w_wqe = (struct wait_queue_element *)$kgm_w_wqe->wqe_links.next end end define showwaitqwaitercount set $kgm_wc_waitqp = (struct wait_queue *)$arg0 set $kgm_wc_linksp = &($kgm_wc_waitqp->wq_queue) set $kgm_wc_wqe = (struct wait_queue_element *)$kgm_wc_linksp->next set $kgm_wc_count = 0 while ( (queue_entry_t)$kgm_wc_wqe != (queue_entry_t)$kgm_wc_linksp) if ($kgm_wc_wqe->wqe_type != &_wait_queue_link) set $kgm_wc_count = $kgm_wc_count + 1 end set $kgm_wc_wqe = (struct wait_queue_element *)$kgm_wc_wqe->wqe_links.next end printf "0x%08x ", $kgm_wc_count end define showwaitqmembercount set $kgm_mc_waitqsetp = (struct wait_queue_set *)$arg0 set $kgm_mc_setlinksp = &($kgm_mc_waitqsetp->wqs_setlinks) set $kgm_mc_wql = (struct wait_queue_link *)$kgm_mc_setlinksp->next set $kgm_mc_count = 0 while ( (queue_entry_t)$kgm_mc_wql != (queue_entry_t)$kgm_mc_setlinksp) set $kgm_mc_count = $kgm_mc_count + 1 set $kgm_mc_wql = (struct wait_queue_link *)$kgm_mc_wql->wql_setlinks.next end printf "0x%08x ", $kgm_mc_count end define showwaitqmemberheader printf "set-members wait_queue interlock " printf "pol type member_cnt waiter_cnt\n" end define showwaitqmemberint set $kgm_m_waitqp = (struct wait_queue *)$arg0 printf " 0x%08x ", $kgm_m_waitqp printf "0x%08x ", $kgm_m_waitqp->wq_interlock.lock_data if ($kgm_m_waitqp->wq_fifo) printf "Fifo " else printf "Prio " end if ($kgm_m_waitqp->wq_type == 0xf1d1) printf "Set " showwaitqmembercount $kgm_m_waitqp else printf "Que 0x00000000 " end showwaitqwaitercount $kgm_m_waitqp printf "\n" end define showwaitqmemberofheader printf "member-of wait_queue interlock " printf "pol type member_cnt waiter_cnt\n" end define showwaitqmemberof set $kgm_mo_waitqp = (struct wait_queue *)$arg0 set $kgm_mo_linksp = &($kgm_mo_waitqp->wq_queue) set $kgm_mo_wqe = (struct wait_queue_element *)$kgm_mo_linksp->next set $kgm_mo_found = 0 while ( (queue_entry_t)$kgm_mo_wqe != (queue_entry_t)$kgm_mo_linksp) if ($kgm_mo_wqe->wqe_type == &_wait_queue_link) if !$kgm_mo_found set $kgm_mo_found = 1 showwaitqmemberofheader end set $kgm_mo_wqlp = (struct wait_queue_link *)$kgm_mo_wqe set $kgm_mo_wqsetp = (struct wait_queue *)($kgm_mo_wqlp->wql_setqueue) showwaitqmemberint $kgm_mo_wqsetp end set $kgm_mo_wqe = (struct wait_queue_element *)$kgm_mo_wqe->wqe_links.next end end define showwaitqmembers set $kgm_ms_waitqsetp = (struct wait_queue_set *)$arg0 set $kgm_ms_setlinksp = &($kgm_ms_waitqsetp->wqs_setlinks) set $kgm_ms_wql = (struct wait_queue_link *)$kgm_ms_setlinksp->next set $kgm_ms_found = 0 while ( (queue_entry_t)$kgm_ms_wql != (queue_entry_t)$kgm_ms_setlinksp) set $kgm_ms_waitqp = $kgm_ms_wql->wql_element.wqe_queue if !$kgm_ms_found showwaitqmemberheader set $kgm_ms_found = 1 end showwaitqmemberint $kgm_ms_waitqp set $kgm_ms_wql = (struct wait_queue_link *)$kgm_ms_wql->wql_setlinks.next end end define showwaitqheader printf "wait_queue ref_count interlock " printf "pol type member_cnt waiter_cnt\n" end define showwaitqint set $kgm_waitqp = (struct wait_queue *)$arg0 printf "0x%08x ", $kgm_waitqp if ($kgm_waitqp->wq_type == 0xf1d1) printf "0x%08x ", ((struct wait_queue_set *)$kgm_waitqp)->wqs_refcount else printf "0x00000000 " end printf "0x%08x ", $kgm_waitqp->wq_interlock.lock_data if ($kgm_waitqp->wq_fifo) printf "Fifo " else printf "Prio " end if ($kgm_waitqp->wq_type == 0xf1d1) printf "Set " showwaitqmembercount $kgm_waitqp else printf "Que 0x00000000 " end showwaitqwaitercount $kgm_waitqp printf "\n" end define showwaitq set $kgm_waitq1p = (wait_queue_t)$arg0 showwaitqheader showwaitqint $kgm_waitq1p if ($kgm_waitq1p->wq_type == 0xf1d1) showwaitqmembers $kgm_waitq1p else showwaitqmemberof $kgm_waitq1p end showwaitqwaiters $kgm_waitq1p end define showmapheader printf "vm_map pmap vm_size " printf "#ents rpage hint first_free\n" end define showvmeheader printf " entry start " printf " prot #page object offset\n" end define showvmint set $kgm_mapp = (vm_map_t)$arg0 set $kgm_map = *$kgm_mapp printf "0x%08x ", $arg0 printf "0x%08x ", $kgm_map.pmap printf "0x%08x ", $kgm_map.size printf "%3d ", $kgm_map.hdr.nentries if $kgm_map.pmap printf "%5d ", $kgm_map.pmap->stats.resident_count else printf " " end printf "0x%08x ", $kgm_map.hint printf "0x%08x\n", $kgm_map.first_free if $arg1 != 0 showvmeheader set $kgm_head_vmep = &($kgm_mapp->hdr.links) set $kgm_vmep = $kgm_map.hdr.links.next while (($kgm_vmep != 0) && ($kgm_vmep != $kgm_head_vmep)) set $kgm_vme = *$kgm_vmep printf " 0x%08x ", $kgm_vmep printf "0x%016llx ", $kgm_vme.links.start printf "%1x", $kgm_vme.protection printf "%1x", $kgm_vme.max_protection if $kgm_vme.inheritance == 0x0 printf "S" end if $kgm_vme.inheritance == 0x1 printf "C" end if $kgm_vme.inheritance == 0x2 printf "-" end if $kgm_vme.inheritance == 0x3 printf "D" end if $kgm_vme.is_sub_map printf "s " else if $kgm_vme.needs_copy printf "n " else printf " " end end printf "%5d ",($kgm_vme.links.end - $kgm_vme.links.start) >> 12 printf "0x%08x ", $kgm_vme.object.vm_object printf "0x%016llx\n", $kgm_vme.offset set $kgm_vmep = $kgm_vme.links.next end end printf "\n" end define showmapvme showmapheader showvmint $arg0 1 end document showmapvme | Routine to print out a summary listing of all the entries in a vm_map | The following is the syntax: | (gdb) showmapvme end define showmap showmapheader showvmint $arg0 0 end document showmap | Routine to print out info about the specified vm_map | The following is the syntax: | (gdb) showmap end define showallvm set $kgm_head_taskp = &default_pset.tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader showmapheader showtaskint $kgm_taskp showvmint $kgm_taskp->map 0 set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next) end end document showallvm | Routine to print a summary listing of all the vm maps | The following is the syntax: | (gdb) showallvm end define showallvme set $kgm_head_taskp = &default_pset.tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader showmapheader showtaskint $kgm_taskp showvmint $kgm_taskp->map 1 set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next) end end document showallvme | Routine to print a summary listing of all the vm map entries | The following is the syntax: | (gdb) showallvme end define showipcheader printf "ipc_space is_table table_next " printf "flags tsize splaytree splaybase\n" end define showipceheader printf " name object " printf "rite urefs destname destination\n" end define showipceint set $kgm_ie = *(ipc_entry_t)$arg0 printf " 0x%08x ", $arg1 printf "0x%08x ", $kgm_ie.ie_object if $kgm_ie.ie_bits & 0x00100000 printf "Dead " printf "%5d\n", $kgm_ie.ie_bits & 0xffff else if $kgm_ie.ie_bits & 0x00080000 printf "SET " printf "%5d\n", $kgm_ie.ie_bits & 0xffff else if $kgm_ie.ie_bits & 0x00010000 if $kgm_ie.ie_bits & 0x00020000 printf " SR" else printf " S" end else if $kgm_ie.ie_bits & 0x00020000 printf " R" end end if $kgm_ie.ie_bits & 0x00040000 printf " O" end if $kgm_ie.index.request printf "n" else printf " " end if $kgm_ie.ie_bits & 0x00800000 printf "c" else printf " " end printf "%5d ", $kgm_ie.ie_bits & 0xffff showportdest $kgm_ie.ie_object end end end define showipcint set $kgm_isp = (ipc_space_t)$arg0 set $kgm_is = *$kgm_isp printf "0x%08x ", $arg0 printf "0x%08x ", $kgm_is.is_table printf "0x%08x ", $kgm_is.is_table_next if $kgm_is.is_growing != 0 printf "G" else printf " " end if $kgm_is.is_fast != 0 printf "F" else printf " " end if $kgm_is.is_active != 0 printf "A " else printf " " end printf "%5d ", $kgm_is.is_table_size printf "0x%08x ", $kgm_is.is_tree_total printf "0x%08x\n", &$kgm_isp->is_tree if $arg1 != 0 showipceheader set $kgm_iindex = 0 set $kgm_iep = $kgm_is.is_table set $kgm_destspacep = (ipc_space_t)0 while ( $kgm_iindex < $kgm_is.is_table_size ) set $kgm_ie = *$kgm_iep if $kgm_ie.ie_bits & 0x001f0000 set $kgm_name = (($kgm_iindex << 8)|($kgm_ie.ie_bits >> 24)) showipceint $kgm_iep $kgm_name end set $kgm_iindex = $kgm_iindex + 1 set $kgm_iep = &($kgm_is.is_table[$kgm_iindex]) end if $kgm_is.is_tree_total printf "Still need to write tree traversal\n" end end printf "\n" end define showipc set $kgm_isp = (ipc_space_t)$arg0 showipcheader showipcint $kgm_isp 0 end document showipc | Routine to print the status of the specified ipc space | The following is the syntax: | (gdb) showipc end define showrights set $kgm_isp = (ipc_space_t)$arg0 showipcheader showipcint $kgm_isp 1 end document showrights | Routine to print a summary list of all the rights in a specified ipc space | The following is the syntax: | (gdb) showrights end define showtaskipc set $kgm_taskp = (task_t)$arg0 showtaskheader showipcheader showtaskint $kgm_taskp showipcint $kgm_taskp->itk_space 0 end document showtaskipc | Routine to print info about the ipc space for a task | The following is the syntax: | (gdb) showtaskipc end define showtaskrights set $kgm_taskp = (task_t)$arg0 showtaskheader showipcheader showtaskint $kgm_taskp showipcint $kgm_taskp->itk_space 1 end document showtaskrights | Routine to print info about the ipc rights for a task | The following is the syntax: | (gdb) showtaskrights end define showallipc set $kgm_head_taskp = &default_pset.tasks set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_cur_taskp != $kgm_head_taskp showtaskheader showipcheader showtaskint $kgm_cur_taskp showipcint $kgm_cur_taskp->itk_space 0 set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->pset_tasks.next) end end document showallipc | Routine to print a summary listing of all the ipc spaces | The following is the syntax: | (gdb) showallipc end define showallrights set $kgm_head_taskp = &default_pset.tasks set $kgm_cur_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_cur_taskp != $kgm_head_taskp showtaskheader showipcheader showtaskint $kgm_cur_taskp showipcint $kgm_cur_taskp->itk_space 1 set $kgm_cur_taskp = (struct task *)($kgm_cur_taskp->pset_tasks.next) end end document showallrights | Routine to print a summary listing of all the ipc rights | The following is the syntax: | (gdb) showallrights end define showtaskvm set $kgm_taskp = (task_t)$arg0 showtaskheader showmapheader showtaskint $kgm_taskp showvmint $kgm_taskp->map 0 end document showtaskvm | Routine to print out info about a task's vm_map | The following is the syntax: | (gdb) showtaskvm end define showtaskvme set $kgm_taskp = (task_t)$arg0 showtaskheader showmapheader showtaskint $kgm_taskp showvmint $kgm_taskp->map 1 end document showtaskvme | Routine to print out info about a task's vm_map_entries | The following is the syntax: | (gdb) showtaskvme end define showtaskheader printf "task vm_map ipc_space #acts " showprocheader end define showtaskint set $kgm_task = *(struct task *)$arg0 printf "0x%08x ", $arg0 printf "0x%08x ", $kgm_task.map printf "0x%08x ", $kgm_task.itk_space printf "%3d ", $kgm_task.thread_count showprocint $kgm_task.bsd_info end define showtask showtaskheader showtaskint $arg0 end document showtask | Routine to print out info about a task. | The following is the syntax: | (gdb) showtask end define showtaskthreads showtaskheader set $kgm_taskp = (struct task *)$arg0 showtaskint $kgm_taskp showactheader set $kgm_head_actp = &($kgm_taskp->threads) set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) while $kgm_actp != $kgm_head_actp showactint $kgm_actp 0 set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) end end document showtaskthreads | Routine to print info about the threads in a task. | The following is the syntax: | (gdb) showtaskthreads end define showtaskstacks showtaskheader set $kgm_taskp = (struct task *)$arg0 showtaskint $kgm_taskp set $kgm_head_actp = &($kgm_taskp->threads) set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) while $kgm_actp != $kgm_head_actp showactheader showactint $kgm_actp 1 set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) end end document showtaskstacks | Routine to print out the stack for each thread in a task. | The following is the syntax: | (gdb) showtaskstacks end define showalltasks showtaskheader set $kgm_head_taskp = &default_pset.tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskint $kgm_taskp set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next) end end document showalltasks | Routine to print a summary listing of all the tasks | The following is the syntax: | (gdb) showalltasks end define showprocheader printf " pid proc command\n" end define showprocint set $kgm_procp = (struct proc *)$arg0 if $kgm_procp != 0 printf "%5d ", $kgm_procp->p_pid printf "0x%08x ", $kgm_procp printf "%s\n", $kgm_procp->p_comm else printf " *0* 0x00000000 --\n" end end define showpid showtaskheader set $kgm_head_taskp = &default_pset.tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp set $kgm_procp = (struct proc *)$kgm_taskp->bsd_info if (($kgm_procp != 0) && ($kgm_procp->p_pid == $arg0)) showtaskint $kgm_taskp set $kgm_taskp = $kgm_head_taskp else set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next) end end end document showpid | Routine to print a single process by pid | The following is the syntax: | (gdb) showpid end define showproc showtaskheader set $kgm_procp = (struct proc *)$arg0 showtaskint $kgm_procp->task $arg1 $arg2 end define kdb set switch_debugger=1 continue end document kdb | kdb - Switch to the inline kernel debugger | | usage: kdb | | The kdb macro allows you to invoke the inline kernel debugger. end define showpsetheader printf "portset waitqueue recvname " printf "flags refs recvname process\n" end define showportheader printf "port mqueue recvname " printf "flags refs recvname process\n" end define showportmemberheader printf "members port recvname " printf "flags refs mqueue msgcount\n" end define showkmsgheader printf "messages kmsg size " printf "disp msgid remote-port local-port\n" end define showkmsgint printf " 0x%08x ", $arg0 set $kgm_kmsgh = ((ipc_kmsg_t)$arg0)->ikm_header printf "0x%08x ", $kgm_kmsgh.msgh_size if (($kgm_kmsgh.msgh_bits & 0xff) == 19) printf "rC" else printf "rM" end if (($kgm_kmsgh.msgh_bits & 0xff00) == (19 < 8)) printf "lC" else printf "lM" end if ($kgm_kmsgh.msgh_bits & 0xf0000000) printf "c" else printf "s" end printf "%5d ", $kgm_kmsgh.msgh_id printf "0x%08x ", $kgm_kmsgh.msgh_remote_port printf "0x%08x\n", $kgm_kmsgh.msgh_local_port end define showkobject set $kgm_portp = (struct ipc_port *)$arg0 printf "0x%08x kobject(", $kgm_portp->ip_kobject set $kgm_kotype = ($kgm_portp->ip_object.io_bits & 0x00000fff) if ($kgm_kotype == 1) printf "THREAD" end if ($kgm_kotype == 2) printf "TASK" end if ($kgm_kotype == 3) printf "HOST" end if ($kgm_kotype == 4) printf "HOST_PRIV" end if ($kgm_kotype == 5) printf "PROCESSOR" end if ($kgm_kotype == 6) printf "PSET" end if ($kgm_kotype == 7) printf "PSET_NAME" end if ($kgm_kotype == 8) printf "TIMER" end if ($kgm_kotype == 9) printf "PAGER_REQ" end if ($kgm_kotype == 10) printf "DEVICE" end if ($kgm_kotype == 11) printf "XMM_OBJECT" end if ($kgm_kotype == 12) printf "XMM_PAGER" end if ($kgm_kotype == 13) printf "XMM_KERNEL" end if ($kgm_kotype == 14) printf "XMM_REPLY" end if ($kgm_kotype == 15) printf "NOTDEF 15" end if ($kgm_kotype == 16) printf "NOTDEF 16" end if ($kgm_kotype == 17) printf "HOST_SEC" end if ($kgm_kotype == 18) printf "LEDGER" end if ($kgm_kotype == 19) printf "MASTER_DEV" end if ($kgm_kotype == 20) printf "ACTIVATION" end if ($kgm_kotype == 21) printf "SUBSYSTEM" end if ($kgm_kotype == 22) printf "IO_DONE_QUE" end if ($kgm_kotype == 23) printf "SEMAPHORE" end if ($kgm_kotype == 24) printf "LOCK_SET" end if ($kgm_kotype == 25) printf "CLOCK" end if ($kgm_kotype == 26) printf "CLOCK_CTRL" end if ($kgm_kotype == 27) printf "IOKIT_SPARE" end if ($kgm_kotype == 28) printf "NAMED_MEM" end if ($kgm_kotype == 29) printf "IOKIT_CON" end if ($kgm_kotype == 30) printf "IOKIT_OBJ" end if ($kgm_kotype == 31) printf "UPL" end printf ")\n" end define showportdestproc set $kgm_portp = (struct ipc_port *)$arg0 set $kgm_spacep = $kgm_portp->data.receiver # check against the previous cached value - this is slow if ($kgm_spacep != $kgm_destspacep) set $kgm_destprocp = (struct proc *)0 set $kgm_head_taskp = &default_pset.tasks set $kgm_desttaskp = (struct task *)($kgm_head_taskp->next) while (($kgm_destprocp == 0) && ($kgm_desttaskp != $kgm_head_taskp)) set $kgm_destspacep = $kgm_desttaskp->itk_space if ($kgm_destspacep == $kgm_spacep) set $kgm_destprocp = (struct proc *)$kgm_desttaskp->bsd_info else set $kgm_desttaskp = (struct task *)($kgm_desttaskp->pset_tasks.next) end end end if $kgm_destprocp != 0 printf "%s(%d)\n", $kgm_destprocp->p_comm, $kgm_destprocp->p_pid else printf "task 0x%08x\n", $kgm_desttaskp end end define showportdest set $kgm_portp = (struct ipc_port *)$arg0 set $kgm_spacep = $kgm_portp->data.receiver if ($kgm_spacep == ipc_space_kernel) showkobject $kgm_portp else if ($kgm_portp->ip_object.io_bits & 0x80000000) printf "0x%08x ", $kgm_portp->ip_object.io_receiver_name showportdestproc $kgm_portp else printf "0x%08x inactive-port\n", $kgm_portp end end end define showportmember printf " 0x%08x ", $arg0 set $kgm_portp = (struct ipc_port *)$arg0 printf "0x%08x ", $kgm_portp->ip_object.io_receiver_name if ($kgm_portp->ip_object.io_bits & 0x80000000) printf "A" else printf " " end if ($kgm_portp->ip_object.io_bits & 0x7fff0000) printf "Set " else printf "Port" end printf "%5d ", $kgm_portp->ip_object.io_references printf "0x%08x ", &($kgm_portp->ip_messages) printf "0x%08x\n", $kgm_portp->ip_messages.data.port.msgcount end define showportint printf "0x%08x ", $arg0 set $kgm_portp = (struct ipc_port *)$arg0 printf "0x%08x ", &($kgm_portp->ip_messages) printf "0x%08x ", $kgm_portp->ip_object.io_receiver_name if ($kgm_portp->ip_object.io_bits & 0x80000000) printf "A" else printf "D" end printf "Port" printf "%5d ", $kgm_portp->ip_object.io_references set $kgm_destspacep = (struct ipc_space *)0 showportdest $kgm_portp set $kgm_kmsgp = (ipc_kmsg_t)$kgm_portp->ip_messages.data.port.messages.ikmq_base if $arg1 && $kgm_kmsgp showkmsgheader showkmsgint $kgm_kmsgp set $kgm_kmsgheadp = $kgm_kmsgp set $kgm_kmsgp = $kgm_kmsgp->ikm_next while $kgm_kmsgp != $kgm_kmsgheadp showkmsgint $kgm_kmsgp set $kgm_kmsgp = $kgm_kmsgp->ikm_next end end end define showpsetint printf "0x%08x ", $arg0 set $kgm_psetp = (struct ipc_pset *)$arg0 printf "0x%08x ", &($kgm_psetp->ips_messages) printf "0x%08x ", $kgm_psetp->ips_object.io_receiver_name if ($kgm_psetp->ips_object.io_bits & 0x80000000) printf "A" else printf "D" end printf "Set " printf "%5d ", $kgm_psetp->ips_object.io_references printf "0x%08x ", $kgm_psetp->ips_object.io_receiver_name set $kgm_setlinksp = &($kgm_psetp->ips_messages.data.set_queue.wqs_setlinks) set $kgm_wql = (struct wait_queue_link *)$kgm_setlinksp->next set $kgm_found = 0 while ( (queue_entry_t)$kgm_wql != (queue_entry_t)$kgm_setlinksp) set $kgm_portp = (struct ipc_port *)((int)($kgm_wql->wql_element->wqe_queue) - ((int)$kgm_portoff)) if !$kgm_found set $kgm_destspacep = (struct ipc_space *)0 showportdestproc $kgm_portp showportmemberheader set $kgm_found = 1 end showportmember $kgm_portp 0 set $kgm_wql = (struct wait_queue_link *)$kgm_wql->wql_setlinks.next end if !$kgm_found printf "--n/e--\n" end end define showpset showpsetheader showpsetint $arg0 1 end define showport showportheader showportint $arg0 1 end define showipcobject set $kgm_object = (ipc_object_t)$arg0 if ($kgm_objectp->io_bits & 0x7fff0000) showpset $kgm_objectp else showport $kgm_objectp end end define showmqueue set $kgm_mqueue = *(struct ipc_mqueue *)$arg0 set $kgm_psetoff = &(((struct ipc_pset *)0)->ips_messages) set $kgm_portoff = &(((struct ipc_port *)0)->ip_messages) if ($kgm_mqueue.data.set_queue.wqs_wait_queue.wq_type == 0xf1d1) set $kgm_pset = (((int)$arg0) - ((int)$kgm_psetoff)) showpsetheader showpsetint $kgm_pset 1 end if ($kgm_mqueue.data.set_queue.wqs_wait_queue.wq_type == 0xf1d0) showportheader set $kgm_port = (((int)$arg0) - ((int)$kgm_portoff)) showportint $kgm_port 1 end end define zprint_one set $kgm_zone = (struct zone *)$arg0 printf "0x%08x ", $kgm_zone printf "%8d ",$kgm_zone->count printf "%8x ",$kgm_zone->cur_size printf "%8x ",$kgm_zone->max_size printf "%6d ",$kgm_zone->elem_size printf "%8x ",$kgm_zone->alloc_size printf "%s ",$kgm_zone->zone_name if ($kgm_zone->exhaustible) printf "H" end if ($kgm_zone->collectable) printf "C" end if ($kgm_zone->expandable) printf "X" end printf "\n" end define zprint printf "ZONE COUNT TOT_SZ MAX_SZ ELT_SZ ALLOC_SZ NAME\n" set $kgm_zone_ptr = (struct zone *)first_zone while ($kgm_zone_ptr != 0) zprint_one $kgm_zone_ptr set $kgm_zone_ptr = $kgm_zone_ptr->next_zone end printf "\n" end document zprint | Routine to print a summary listing of all the kernel zones | The following is the syntax: | (gdb) zprint end define showmtxgrp set $kgm_mtxgrp = (lck_grp_t *)$arg0 if ($kgm_mtxgrp->lck_grp_mtxcnt) printf "0x%08x ", $kgm_mtxgrp printf "%8d ",$kgm_mtxgrp->lck_grp_mtxcnt printf "%12u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_util_cnt printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_miss_cnt printf "%8u ",$kgm_mtxgrp->lck_grp_stat.lck_grp_mtx_stat.lck_grp_mtx_wait_cnt printf "%s ",&$kgm_mtxgrp->lck_grp_name printf "\n" end end define showallmtx printf "LCK GROUP CNT UTIL MISS WAIT NAME\n" set $kgm_mtxgrp_ptr = (lck_grp_t *)&lck_grp_queue set $kgm_mtxgrp_ptr = (lck_grp_t *)$kgm_mtxgrp_ptr->lck_grp_link.next while ($kgm_mtxgrp_ptr != (lck_grp_t *)&lck_grp_queue) showmtxgrp $kgm_mtxgrp_ptr set $kgm_mtxgrp_ptr = (lck_grp_t *)$kgm_mtxgrp_ptr->lck_grp_link.next end printf "\n" end document showallmtx | Routine to print a summary listing of all mutexes | The following is the syntax: | (gdb) showallmtx end define showrwlckgrp set $kgm_rwlckgrp = (lck_grp_t *)$arg0 if ($kgm_rwlckgrp->lck_grp_rwcnt) printf "0x%08x ", $kgm_rwlckgrp printf "%8d ",$kgm_rwlckgrp->lck_grp_rwcnt printf "%12u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_util_cnt printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_miss_cnt printf "%8u ",$kgm_rwlckgrp->lck_grp_stat.lck_grp_rw_stat.lck_grp_rw_wait_cnt printf "%s ",&$kgm_rwlckgrp->lck_grp_name printf "\n" end end define showallrwlck printf "LCK GROUP CNT UTIL MISS WAIT NAME\n" set $kgm_rwlckgrp_ptr = (lck_grp_t *)&lck_grp_queue set $kgm_rwlckgrp_ptr = (lck_grp_t *)$kgm_rwlckgrp_ptr->lck_grp_link.next while ($kgm_rwlckgrp_ptr != (lck_grp_t *)&lck_grp_queue) showrwlckgrp $kgm_rwlckgrp_ptr set $kgm_rwlckgrp_ptr = (lck_grp_t *)$kgm_rwlckgrp_ptr->lck_grp_link.next end printf "\n" end document showallrwlck | Routine to print a summary listing of all read/writer locks | The following is the syntax: | (gdb) showallrwlck end set $kdp_act_counter = 0 define switchtoact if ($kgm_mtype == 18) if ($kdp_act_counter == 0) set $kdpstate = (struct savearea *) kdp.saved_state end set $kdp_act_counter = $kdp_act_counter + 1 set $newact = (struct thread *) $arg0 if ($newact->kernel_stack == 0) echo This activation does not have a stack.\n echo continuation: output/a (unsigned) $newact.continuation echo \n else set (struct savearea *) kdp.saved_state=$newact->machine->pcb flush set $pc=$newact->machine->pcb.save_srr0 update end else echo switchtoact not implemented for this architecture.\n end end document switchtoact Syntax: switchtoact
| This command allows gdb to examine the execution context and call | stack for the specified activation. For example, to view the backtrace | for an activation issue "switchtoact
", followed by "bt". | Before resuming execution, issue a "resetctx" command, to | return to the original execution context. end define switchtoctx if ($kgm_mtype == 18) if ($kdp_act_counter == 0) set $kdpstate = (struct savearea *) kdp.saved_state end set $kdp_act_counter = $kdp_act_counter + 1 set (struct savearea *) kdp.saved_state=(struct savearea *) $arg0 flush set $pc=((struct savearea *) $arg0)->save_srr0 update else echo switchtoctx not implemented for this architecture.\n end end document switchtoctx Syntax: switchtoctx
| This command allows gdb to examine an execution context and dump the | backtrace for this execution context. | Before resuming execution, issue a "resetctx" command, to | return to the original execution context. end define resetctx if ($kgm_mtype == 18) set (struct savearea *)kdp.saved_state=$kdpstate flush set $pc=((struct savearea *) kdp.saved_state)->save_srr0 update set $kdp_act_counter = 0 else echo resetctx not implemented for this architecture.\n end end document resetctx | Syntax: resetctx | Returns to the original execution context. This command should be | issued if you wish to resume execution after using the "switchtoact" | or "switchtoctx" commands. end define resume_on set noresume_on_disconnect = 0 end document resume_on | Syntax: resume_on | The target system will resume when detaching or exiting from gdb. | This is the default behavior. end define resume_off set noresume_on_disconnect = 1 end document resume_off | Syntax: resume_off | The target system won't resume after detaching from gdb and | can be attached with a new gdb session end define paniclog set $kgm_panic_bufptr = debug_buf set $kgm_panic_bufptr_max = debug_buf_ptr while $kgm_panic_bufptr < $kgm_panic_bufptr_max if *(char *)$kgm_panic_bufptr == 10 printf "\n" else printf "%c", *$kgm_panic_bufptr end set $kgm_panic_bufptr= (char *)$kgm_panic_bufptr + 1 end end document paniclog | Syntax: paniclog | Display the panic log information | end define dumpcallqueue set $kgm_callhead = (queue_t)&$arg0 set $kgm_call = (struct call_entry *)$kgm_callhead.next set $kgm_i = 0 while $kgm_call != $kgm_callhead printf "0x%08x ", $kgm_call printf "0x%08x 0x%08x ", $kgm_call->param0, $kgm_call->param1 output $kgm_call->state printf "\t" output $kgm_call->deadline printf "\t" output $kgm_call->func printf "\n" set $kgm_i = $kgm_i + 1 set $kgm_call = (struct call_entry *)$kgm_call->q_link.next end printf "%d entries\n", $kgm_i end document dumpcallqueue | Syntax: dumpcallqueue | Displays the contents of the specified call_entry queue. end define showtaskacts showtaskthreads $arg0 end document showtaskacts | See help showtaskthreads. end define showallacts showallthreads end document showallacts | See help showallthreads. end define resetstacks _kgm_flush_loop set kdp_pmap = 0 _kgm_flush_loop resetctx _kgm_flush_loop _kgm_update_loop resetctx _kgm_update_loop end document resetstacks | Syntax: resetstacks | Internal kgmacro routine used by the "showuserstack" macro | to reset the target pmap to the kernel pmap. end #Barely effective hacks to work around bugs in the "flush" and "update" #gdb commands in Tiger (up to 219); these aren't necessary with Panther #gdb, but do no harm. define _kgm_flush_loop set $kgm_flush_loop_ctr = 0 while ($kgm_flush_loop_ctr < 30) flush set $kgm_flush_loop_ctr = $kgm_flush_loop_ctr + 1 end end define _kgm_update_loop set $kgm_update_loop_ctr = 0 while ($kgm_update_loop_ctr < 30) update set $kgm_update_loop_ctr = $kgm_update_loop_ctr + 1 end end define showuserstack if ($kgm_mtype == 18) if ($kdp_act_counter == 0) set $kdpstate = (struct savearea *) kdp.saved_state end set $kdp_act_counter = $kdp_act_counter + 1 set $newact = (struct thread *) $arg0 _kgm_flush_loop set $checkpc = $newact->machine->upcb.save_srr0 if ($checkpc == 0) echo This activation does not appear to have echo \20 a valid user context.\n else set (struct savearea *) kdp.saved_state=$newact->machine->upcb set $pc = $checkpc #flush and update seem to be executed lazily by gdb on Tiger, hence the #repeated invocations - see 3743135 _kgm_flush_loop # This works because the new pmap is used only for reads set kdp_pmap = $newact->task->map->pmap _kgm_flush_loop _kgm_update_loop bt resetstacks _kgm_flush_loop _kgm_update_loop resetstacks _kgm_flush_loop _kgm_update_loop end else echo showuserstack not implemented for this architecture.\n end end document showuserstack Syntax: showuserstack
|This command displays a numeric backtrace for the user space stack of |the given thread activation. It may, of course, fail to display a |complete backtrace if portions of the user stack are not mapped in. |Symbolic backtraces can be obtained either by running gdb on the |user space binary, or a tool such as "symbolicate". |Note that while this command works on Panther's gdb, an issue |with Tiger gdb (3743135) appears to hamper the evaluation of this |macro in some cases. end #Stopgap until gdb can generate the HOSTREBOOT packet define kdp-reboot set flag_kdp_trigger_reboot = 1 continue end document kdp-reboot Syntax: kdp-reboot |Reboot the remote target machine; not guaranteed to succeed. Requires symbols |until gdb support for the HOSTREBOOT packet is implemented. end define sendcore set kdp_trigger_core_dump = 1 set kdp_flag |= 0x40 set panicd_ip_str = "$arg0" set panicd_specified = 1 set disableDebugOuput = 0 set disableConsoleOutput = 0 set logPanicDataToScreen = 1 set reattach_wait = 1 resume_off end document sendcore Syntax: sendcore |Configure the kernel to transmit a kernel coredump to a server (kdumpd) |at the specified IP address. This is useful when the remote target has |not been previously configured to transmit coredumps, and you wish to |preserve kernel state for later examination. NOTE: You must issue a "continue" |command after using this macro to trigger the kernel coredump. The kernel |will resume waiting in the debugger after completion of the coredump. You |may disable coredumps by executing the "disablecore" macro. end define disablecore set kdp_trigger_core_dump = 0 set kdp_flag |= 0x40 set kdp_flag &= ~0x10 set panicd_specified = 0 end document disablecore Syntax: disablecore |Reconfigures the kernel so that it no longer transmits kernel coredumps. This |complements the "sendcore" macro, but it may be used if the kernel has been |configured to transmit coredumps through boot-args as well. end #Use of this macro requires the gdb submission from 3401283 define switchtocorethread if ($kgm_mtype == 18) if ($kdp_act_counter == 0) set $kdpstate = (struct savearea *) kdp.saved_state end set $kdp_act_counter = $kdp_act_counter + 1 set $newact = (struct thread *) $arg0 if ($newact->kernel_stack == 0) echo This thread does not have a stack.\n echo continuation: output/a (unsigned) $newact.continuation echo \n else loadcontext $newact->machine->pcb # flushstack will be introduced in a gdb version > gdb-357 flushstack set $pc = $newact->machine->pcb.save_srr0 end else echo switchtocorethread not implemented for this architecture.\n end end document switchtocorethread Syntax: switchtocorethread
| The corefile equivalent of "switchtoact". When debugging a kernel coredump | file, this command can be used to examine the execution context and stack | trace for a given thread activation. For example, to view the backtrace | for a thread issue "switchtocorethread
", followed by "bt". | Before resuming execution, issue a "resetcorectx" command, to | return to the original execution context. Note that this command | requires gdb support, as documented in Radar 3401283. end define loadcontext set $pc = $arg0.save_srr0 set $r1 = $arg0.save_r1 set $lr = $arg0.save_lr set $r2 = $arg0.save_r2 set $r3 = $arg0.save_r3 set $r4 = $arg0.save_r4 set $r5 = $arg0.save_r5 set $r6 = $arg0.save_r6 set $r7 = $arg0.save_r7 set $r8 = $arg0.save_r8 set $r9 = $arg0.save_r9 set $r10 = $arg0.save_r10 set $r11 = $arg0.save_r11 set $r12 = $arg0.save_r12 set $r13 = $arg0.save_r13 set $r14 = $arg0.save_r14 set $r15 = $arg0.save_r15 set $r16 = $arg0.save_r16 set $r17 = $arg0.save_r17 set $r18 = $arg0.save_r18 set $r19 = $arg0.save_r19 set $r20 = $arg0.save_r20 set $r21 = $arg0.save_r21 set $r22 = $arg0.save_r22 set $r23 = $arg0.save_r23 set $r24 = $arg0.save_r24 set $r25 = $arg0.save_r25 set $r26 = $arg0.save_r26 set $r27 = $arg0.save_r27 set $r28 = $arg0.save_r28 set $r29 = $arg0.save_r29 set $r30 = $arg0.save_r30 set $r31 = $arg0.save_r31 set $cr = $arg0.save_cr set $ctr = $arg0.save_ctr end define resetcorectx set $kgm_corecontext = (struct savearea *) kdp.saved_state loadcontext $kgm_corecontext # Maintaining this act counter wouldn't be necessary if we just initialized # $kdpstate at the beginning of the macro.. set $kdp_act_counter = 0 end document resetcorectx Syntax: resetcorectx | The corefile equivalent of "resetctx". Returns to the original | execution context (that of the active thread at the time of the NMI or | panic). This command should be issued if you wish to resume | execution after using the "switchtocorethread" command. end #Helper function for "showallgdbstacks" define showgdbthread printf " 0x%08x ", $arg0 set $kgm_thread = *(struct thread *)$arg0 printf "0x%08x ", $arg0 printf "%3d ", $kgm_thread.sched_pri set $kgm_state = $kgm_thread.state if $kgm_state & 0x80 printf "I" end if $kgm_state & 0x40 printf "P" end if $kgm_state & 0x20 printf "A" end if $kgm_state & 0x10 printf "H" end if $kgm_state & 0x08 printf "U" end if $kgm_state & 0x04 printf "R" end if $kgm_state & 0x02 printf "S" end if $kgm_state & 0x01 printf "W\t" printf "0x%08x ", $kgm_thread.wait_queue output /a (unsigned) $kgm_thread.wait_event end if $arg1 != 0 if ($kgm_thread.kernel_stack != 0) if ($kgm_thread.reserved_stack != 0) printf "\n\t\treserved_stack=0x%08x", $kgm_thread.reserved_stack end printf "\n\t\tkernel_stack=0x%08x", $kgm_thread.kernel_stack if ($kgm_mtype == 18) set $mysp = $kgm_thread.machine.pcb->save_r1 else set $kgm_statep = (struct i386_kernel_state *) \ ($kgm_thread->kernel_stack + 0x4000 \ - sizeof(struct i386_kernel_state)) set $mysp = $kgm_statep->k_ebp end set $prevsp = 0 printf "\n\t\tstacktop=0x%08x", $mysp switchtoact $arg0 bt else printf "\n\t\t\tcontinuation=" output /a (unsigned) $kgm_thread.continuation end printf "\n" else printf "\n" end end #Use of this macro is currently (8/04) blocked by the fact that gdb #stops evaluating macros when encountering an error, such as a failure #to read memory from a certain location. Until this issue (described in #3758949) is addressed, evaluation of this macro may stop upon #encountering such an error. define showallgdbstacks set $kgm_head_taskp = &default_pset.tasks set $kgm_taskp = (struct task *)($kgm_head_taskp->next) while $kgm_taskp != $kgm_head_taskp showtaskheader showtaskint $kgm_taskp set $kgm_head_actp = &($kgm_taskp->threads) set $kgm_actp = (struct thread *)($kgm_taskp->threads.next) while $kgm_actp != $kgm_head_actp showactheader showgdbthread $kgm_actp 1 set $kgm_actp = (struct thread *)($kgm_actp->task_threads.next) end printf "\n" set $kgm_taskp = (struct task *)($kgm_taskp->pset_tasks.next) end resetctx end document showallgdbstacks Syntax: showallgdbstacks | An alternative to "showallstacks". Iterates through the task list and | displays a gdb generated backtrace for each kernel thread. It is | advantageous in that it is much faster than "showallstacks", and | decodes function call arguments and displays source level traces, but | it has the drawback that it doesn't determine if frames belong to | functions from kernel extensions, as with "showallstacks". | This command may terminate prematurely because of a gdb bug | (Radar 3758949), which stops macro evaluation on memory read | errors. end define switchtouserthread if ($kgm_mtype == 18) if ($kdp_act_counter == 0) set $kdpstate = (struct savearea *) kdp.saved_state end set $kdp_act_counter = $kdp_act_counter + 1 set $newact = (struct thread *) $arg0 _kgm_flush_loop set $checkpc = $newact->machine->upcb.save_srr0 if ($checkpc == 0) echo This activation does not appear to have echo \20 a valid user context.\n else set (struct savearea *) kdp.saved_state=$newact->machine->upcb set $pc = $checkpc #flush and update seem to be executed lazily by gdb on Tiger, hence the #repeated invocations - see 3743135 _kgm_flush_loop # This works because the new pmap is used only for reads set kdp_pmap = $newact->task->map->pmap _kgm_flush_loop _kgm_update_loop end else echo switchtouserthread not implemented for this architecture.\n end end document switchtouserthread Syntax: switchtouserthread
| Analogous to switchtoact, but switches to the user context of a | specified thread address. Similar to the "showuserstack" | command, but this command does not return gdb to the kernel context | immediately. This is to assist with the following (rather risky) | manoeuvre - upon switching to the user context and virtual address | space, the user may choose to call remove-symbol-file on the | mach_kernel symbol file, and then add-symbol-file on the user space | binary's symfile. gdb can then generate symbolic backtraces | for the user space thread. To return to the | kernel context and virtual address space, the process must be | reversed, i.e. call remove-symbol-file on the user space symbols, and | then add-symbol-file on the appropriate mach_kernel, and issue the | "resetstacks" command. Note that gdb may not react kindly to all these | symbol file switches. The same restrictions that apply to "showuserstack" | apply here - pages that have been paged out cannot be read while in the | debugger context, so backtraces may terminate early. | If the virtual addresses in the stack trace do not conflict with those | of symbols in the kernel's address space, it may be sufficient to | just do an add-symbol-file on the user space binary's symbol file. | Note that while this command works on Panther's gdb, an issue | with Tiger gdb (3743135) appears to hamper the evaluation of this | macro in some cases. end define showmetaclass set cp-abi gnu-v2 set $kgm_metaclassp = (OSMetaClass *)$arg0 printf "%-5d", $kgm_metaclassp->instanceCount printf "x %5d bytes", $kgm_metaclassp->classSize printf " %s\n", $kgm_metaclassp->className->string end define showallclasses set cp-abi gnu-v2 set $kgm_classidx = 0 while $kgm_classidx < sAllClassesDict->count set $kgm_meta = (OSMetaClass *) sAllClassesDict->dictionary[$kgm_classidx].value showmetaclass $kgm_meta set $kgm_classidx = $kgm_classidx + 1 end end document showallclasses | Show the instance counts and ivar size of all OSObject subclasses. See ioclasscount man page for details. | The following is the syntax: | (gdb) showallclasses end define showioalloc printf " Instance allocation = 0x%08lx = %4ld K\n", (int) debug_ivars_size, ((int) debug_ivars_size) / 1024 printf "Container allocation = 0x%08lx = %4ld K\n", (int) debug_container_malloc_size, ((int) debug_container_malloc_size) / 1024 printf " IOMalloc allocation = 0x%08lx = %4ld K\n", (int) debug_iomalloc_size, ((int) debug_iomalloc_size) / 1024 printf " Pageable allocation = 0x%08lx = %4ld K\n", (vm_size_t) debug_iomallocpageable_size, ((vm_size_t) debug_iomallocpageable_size) / 1024 end document showioalloc | Show some accounting of memory allocated by IOKit allocators. See ioalloccount man page for details. | The following is the syntax: | (gdb) showioalloc end