1/* 2 * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23inline int UT_VFORK = 0x02000000; /* thread has vfork children */ 24#pragma D binding "1.0" UT_VFORK 25 26inline uthread_t uthread = (mach_kernel`uthread_t)(curthread->uthread); /* ` */ 27#pragma D binding "1.0" uthread 28 29inline struct proc * curproc = 30 (uthread && (uthread->uu_flag & UT_VFORK) && uthread->uu_proc) ? (struct proc *)uthread->uu_proc : 31 ((struct proc *)(curthread->task->bsd_info)) != NULL ? ((struct proc *)(curthread->task->bsd_info)) : 32 mach_kernel`kernproc; /* ` */ 33#pragma D binding "1.0" curproc 34 35/* 36 * curthread->thread_tag will have this set if the thread is the main thread 37 */ 38inline uint32_t THREAD_TAG_MAINTHREAD = 0x1; 39inline uint32_t THREAD_TAG_CALLOUT = 0x2; 40inline uint32_t THREAD_TAG_IOWORKLOOP = 0x4; 41 42/* 43 * The following miscellaneous constants are used by the proc(4) translators 44 * defined below. 45 */ 46inline char SIDL = 1; 47#pragma D binding "1.0" SIDL 48inline char SRUN = 2; 49#pragma D binding "1.0" SRUN 50inline char SSLEEP = 3; 51#pragma D binding "1.0" SSLEEP 52inline char SSTOP = 4; 53#pragma D binding "1.0" SSTOP 54inline char SZOMB = 5; 55#pragma D binding "1.0" SZOMB 56/* 57 * SONPROC defined here for compatability with ported scripts 58 */ 59inline char SONPROC = 6; 60#pragma D binding "1.0" SONPROC 61 62inline char SOBJ_NONE = 0; 63#pragma D binding "1.0" SOBJ_NONE 64/* 65 * SOBJ_* defined here for compatability with ported scripts 66 */ 67inline char SOBJ_MUTEX = 1; 68#pragma D binding "1.0" SOBJ_MUTEX 69inline char SOBJ_RWLOCK = 2; 70#pragma D binding "1.0" SOBJ_RWLOCK 71inline char SOBJ_CV = 3; 72#pragma D binding "1.0" SOBJ_CV 73inline char SOBJ_SEMA = 4; 74#pragma D binding "1.0" SOBJ_SEMA 75inline char SOBJ_USER = 5; 76#pragma D binding "1.0" SOBJ_USER 77inline char SOBJ_USER_PI = 6; 78#pragma D binding "1.0" SOBJ_USER_PI 79inline char SOBJ_SHUTTLE = 7; 80#pragma D binding "1.0" SOBJ_SHUTTLE 81 82inline char PR_MODEL_ILP32 = 1; 83#pragma D binding "1.0" PR_MODEL_ILP32 84inline char PR_MODEL_LP64 = 2; 85#pragma D binding "1.0" PR_MODEL_LP64 86 87/* 88 * PR_* defined here for compatability with ported scripts 89 */ 90inline int PR_STOPPED = 0x00000001; 91#pragma D binding "1.0" PR_STOPPED 92inline int PR_ISTOP = 0x00000002; 93#pragma D binding "1.0" PR_ISTOP 94inline int PR_DSTOP = 0x00000004; 95#pragma D binding "1.0" PR_DSTOP 96inline int PR_STEP = 0x00000008; 97#pragma D binding "1.0" PR_STEP 98inline int PR_ASLEEP = 0x00000010; 99#pragma D binding "1.0" PR_ASLEEP 100inline int PR_PCINVAL = 0x00000020; 101#pragma D binding "1.0" PR_PCINVAL 102inline int PR_ASLWP = 0x00000040; 103#pragma D binding "1.0" PR_ASLWP 104inline int PR_AGENT = 0x00000080; 105#pragma D binding "1.0" PR_AGENT 106inline int PR_DETACH = 0x00000100; 107#pragma D binding "1.0" PR_DETACH 108inline int PR_DAEMON = 0x00000200; 109#pragma D binding "1.0" PR_DAEMON 110inline int PR_ISSYS = 0x00001000; 111#pragma D binding "1.0" PR_ISSYS 112inline int PR_VFORKP = 0x00002000; 113#pragma D binding "1.0" PR_VFORKP 114inline int PR_ORPHAN = 0x00004000; 115#pragma D binding "1.0" PR_ORPHAN 116inline int PR_FORK = 0x00100000; 117#pragma D binding "1.0" PR_FORK 118inline int PR_RLC = 0x00200000; 119#pragma D binding "1.0" PR_RLC 120inline int PR_KLC = 0x00400000; 121#pragma D binding "1.0" PR_KLC 122inline int PR_ASYNC = 0x00800000; 123#pragma D binding "1.0" PR_ASYNC 124inline int PR_MSACCT = 0x01000000; 125#pragma D binding "1.0" PR_MSACCT 126inline int PR_BPTADJ = 0x02000000; 127#pragma D binding "1.0" PR_BPTADJ 128inline int PR_PTRACE = 0x04000000; 129#pragma D binding "1.0" PR_PTRACE 130inline int PR_MSFORK = 0x08000000; 131#pragma D binding "1.0" PR_MSFORK 132inline int PR_IDLE = 0x10000000; 133#pragma D binding "1.0" PR_IDLE 134 135/* 136 * Translate from the kernel's proc_t structure to a proc(4) psinfo_t struct. 137 * We do not provide support for pr_size, pr_rssize, pr_pctcpu, and pr_pctmem. 138 * We also do not fill in pr_lwp (the lwpsinfo_t for the representative LWP) 139 * because we do not have the ability to select and stop any representative. 140 * Also, for the moment, pr_wstat, pr_time, and pr_ctime are not supported, 141 * but these could be supported by DTrace in the future using subroutines. 142 * Note that any member added to this translator should also be added to the 143 * kthread_t-to-psinfo_t translator, below. 144 */ 145typedef int taskid_t; 146typedef int projid_t; 147typedef int poolid_t; 148typedef struct timespec timestruc_t; /* (SECONDS, NANOSECONDS) */ 149 150typedef struct psinfo { 151 int pr_nlwp; /* number of active lwps in the process */ 152 pid_t pr_pid; /* unique process id */ 153 pid_t pr_ppid; /* process id of parent */ 154 pid_t pr_pgid; /* pid of process group leader */ 155 pid_t pr_sid; /* session id */ 156 uid_t pr_uid; /* real user id */ 157 uid_t pr_euid; /* effective user id */ 158 gid_t pr_gid; /* real group id */ 159 gid_t pr_egid; /* effective group id */ 160 uintptr_t pr_addr; /* address of process */ 161 dev_t pr_ttydev; /* controlling tty device (or PRNODEV) */ 162 timestruc_t pr_start;/* process start time, DEPRECATED, see pr_start_tv below */ 163 char pr_fname[16]; /* name of execed file */ 164 char pr_psargs[80]; /* initial characters of arg list */ 165 int pr_argc; /* initial argument count */ 166 user_addr_t pr_argv; /* address of initial argument vector */ 167 user_addr_t pr_envp; /* address of initial environment vector */ 168 char pr_dmodel; /* data model of the process */ 169 taskid_t pr_taskid; /* task id */ 170 projid_t pr_projid; /* project id */ 171 poolid_t pr_poolid; /* pool id */ 172 zoneid_t pr_zoneid; /* zone id */ 173 174 struct timeval pr_start_tv; /* process start time, from the epoch (SECONDS, MICROSECONDS) */ 175} psinfo_t; 176 177inline int P_LP64 = 0x00000004; /* Process is LP64 */ 178#pragma D binding "1.0" P_LP64 179 180#pragma D binding "1.0" translator 181translator psinfo_t < struct proc * P > { 182 pr_nlwp = ((struct task *)(P->task))->thread_count; 183 pr_pid = P->p_pid; 184 pr_ppid = P->p_ppid; 185 pr_pgid = P->p_pgrp->pg_id; 186 pr_sid = P->p_pgrp->pg_session->s_sid; 187 pr_uid = P->p_ucred->cr_posix.cr_ruid; 188 pr_euid = P->p_ucred->cr_posix.cr_uid; 189 pr_gid = P->p_ucred->cr_posix.cr_rgid; 190 pr_egid = P->p_ucred->cr_posix.cr_groups[0]; 191 pr_addr = (uintptr_t)P; 192 193 pr_ttydev = (P->p_pgrp->pg_session->s_ttyvp == NULL) ? (dev_t)-1 : 194 P->p_pgrp->pg_session->s_ttyp->t_dev; 195 196 /* 197 * timestruct_t (SECONDS, NANOSECONDS) is not available directly nor can a further translation 198 * be specified here. Zero the structure. Use pr_start_tv instead. 199 */ 200 pr_start = *((timestruc_t *)`dtrace_zero); /* ` */ 201 202 pr_fname = P->p_comm; 203 pr_psargs = P->p_comm; /* XXX omits command line arguments XXX */ 204 pr_argc = P->p_argc; 205 pr_argv = P->p_dtrace_argv; 206 pr_envp = P->p_dtrace_envp; 207 208 pr_dmodel = (P->p_flag & P_LP64) ? PR_MODEL_LP64 : PR_MODEL_ILP32; 209 210 pr_taskid = 0; 211 pr_projid = 0; 212 pr_poolid = 0; 213 pr_zoneid = 0; 214 215 /* 216 * pstats->pstart is a struct timeval: (SECONDS, MICROSECONDS). 217 */ 218 pr_start_tv = P->p_start; 219}; 220 221/* 222 * Translate from the kernel's kthread_t structure to a proc(4) psinfo_t 223 * struct. Lacking a facility to define one translator only in terms of 224 * another, we explicitly define each member by using the proc_t-to-psinfo_t 225 * translator, above; any members added to that translator should also be 226 * added here. (The only exception to this is pr_start, which -- due to it 227 * being a structure -- cannot be defined in terms of a translator at all.) 228 */ 229#pragma D binding "1.0" translator 230translator psinfo_t < thread_t T > { 231 pr_nlwp = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_nlwp; 232 pr_pid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_pid; 233 pr_ppid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_ppid; 234 pr_pgid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_pgid; 235 pr_sid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_sid; 236 pr_uid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_uid; 237 pr_euid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_euid; 238 pr_gid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_gid; 239 pr_egid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_egid; 240 pr_addr = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_addr; 241 pr_ttydev = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_ttydev; 242 pr_start = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_start; 243 pr_fname = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_fname; 244 pr_psargs = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_psargs; /* XXX omits command line arguments XXX */ 245 pr_argc = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_argc; 246 pr_argv = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_argv; 247 pr_envp = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_envp; 248 pr_dmodel = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_dmodel; 249 pr_taskid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_taskid; 250 pr_projid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_projid; 251 pr_poolid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_poolid; 252 pr_zoneid = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_zoneid; 253 254 pr_start_tv = xlate <psinfo_t> ((struct proc *)(T->task->bsd_info)).pr_start_tv; 255}; 256 257/* 258 * Translate from the kernel's kthread_t structure to a proc(4) lwpsinfo_t. 259 * We do not provide support for pr_nice, pr_oldpri, pr_cpu, or pr_pctcpu. 260 * Also, for the moment, pr_start and pr_time are not supported, but these 261 * could be supported by DTrace in the future using subroutines. 262 */ 263 264inline processor_t PROCESSOR_NULL = ((processor_t) 0); 265#pragma D binding "1.0" PROCESSOR_NULL 266 267typedef int psetid_t; 268 269typedef struct lwpsinfo { 270 int pr_flag; /* lwp flags (DEPRECATED; do not use) */ 271 id_t pr_lwpid; /* lwp id */ 272 uintptr_t pr_addr; /* internal address of lwp */ 273 uintptr_t pr_wchan; /* wait addr for sleeping lwp */ 274 char pr_stype; /* synchronization event type */ 275 char pr_state; /* numeric lwp state */ 276 char pr_sname; /* printable character for pr_state */ 277 short pr_syscall; /* system call number (if in syscall) */ 278 int pr_pri; /* priority, high value is high priority */ 279 char pr_clname[8]; /* scheduling class name */ 280 processorid_t pr_onpro; /* processor which last ran this lwp */ 281 processorid_t pr_bindpro; /* processor to which lwp is bound */ 282 psetid_t pr_bindpset; /* processor set to which lwp is bound */ 283} lwpsinfo_t; 284 285#pragma D binding "1.0" translator 286translator lwpsinfo_t < thread_t T > { 287 pr_flag = 0; /* lwp flags (DEPRECATED; do not use) */ 288 pr_lwpid = (id_t)T->thread_id; 289 pr_addr = (uintptr_t)T; 290 pr_wchan = (uintptr_t)(((uthread_t)(T->uthread))->uu_wchan); 291 292 pr_stype = SOBJ_NONE; /* XXX Undefined synch object (or none) XXX */ 293 pr_state = curproc->p_stat; 294 pr_sname = (curproc->p_stat == SIDL) ? 'I' : 295 (curproc->p_stat == SRUN) ? 'R' : 296 (curproc->p_stat == SSLEEP) ? 'S' : 297 (curproc->p_stat == SSTOP) ? 'T' : 298 (curproc->p_stat == SZOMB) ? 'Z' : '?'; 299 300 pr_syscall = ((uthread_t)(T->uthread))->uu_code; 301 pr_pri = T->sched_pri; 302 303 pr_clname = (T->sched_mode & 0x0001) ? "RT" : 304 (T->sched_mode & 0x0002) ? "TS" : "SYS"; 305 306 pr_onpro = (T->last_processor == PROCESSOR_NULL) ? -1 : T->last_processor->cpu_id; 307 pr_bindpro = -1; /* Darwin does not bind threads to processors. */ 308 pr_bindpset = -1; /* Darwin does not partition processors. */ 309}; 310 311inline psinfo_t *curpsinfo = xlate <psinfo_t *> (curproc); 312#pragma D attributes Stable/Stable/Common curpsinfo 313#pragma D binding "1.0" curpsinfo 314 315inline lwpsinfo_t *curlwpsinfo = xlate <lwpsinfo_t *> (curthread); 316#pragma D attributes Stable/Stable/Common curlwpsinfo 317#pragma D binding "1.0" curlwpsinfo 318 319/* XXX Really want vn_getpath(curproc->p_fd->fd_cdir, , ) but that takes namecache_rw_lock XXX */ 320inline string cwd = curproc->p_fd->fd_cdir->v_name == NULL ? 321 "<unknown>" : stringof(curproc->p_fd->fd_cdir->v_name); 322#pragma D attributes Stable/Stable/Common cwd 323#pragma D binding "1.0" cwd 324 325/* XXX Really want vn_getpath(curproc->p_fd->fd_rdir, , ) but that takes namecache_rw_lock XXX */ 326inline string root = curproc->p_fd->fd_rdir == NULL ? "/" : 327 curproc->p_fd->fd_rdir->v_name == NULL ? "<unknown>" : 328 stringof(curproc->p_fd->fd_rdir->v_name); 329#pragma D attributes Stable/Stable/Common root 330#pragma D binding "1.0" root 331