dt_proc.c revision 14ea49401f3c8c61422aefbda43809e275f60c6c
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * CDDL HEADER START
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * The contents of this file are subject to the terms of the
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Common Development and Distribution License (the "License").
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * You may not use this file except in compliance with the License.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * See the License for the specific language governing permissions
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * and limitations under the License.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * When distributing Covered Code, include this CDDL HEADER in each
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * If applicable, add the following below this CDDL HEADER, with the
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * fields enclosed by brackets "[]" replaced with your own identifying
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * information: Portions Copyright [yyyy] [name of copyright owner]
0162ce58ecb597543f776cbc7a05fad399db033fvboxsync * CDDL HEADER END
0162ce58ecb597543f776cbc7a05fad399db033fvboxsync * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
0162ce58ecb597543f776cbc7a05fad399db033fvboxsync * Use is subject to license terms.
0162ce58ecb597543f776cbc7a05fad399db033fvboxsync * DTrace Process Control
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * This file provides a set of routines that permit libdtrace and its clients
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * to create and grab process handles using libproc, and to share these handles
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * between library mechanisms that need libproc access, such as ustack(), and
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * client mechanisms that need libproc access, such as dtrace(1M) -c and -p.
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * The library provides several mechanisms in the libproc control layer:
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * Reference Counting: The library code and client code can independently grab
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * the same process handles without interfering with one another. Only when
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * the reference count drops to zero and the handle is not being cached (see
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * below for more information on caching) will Prelease() be called on it.
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * Handle Caching: If a handle is grabbed PGRAB_RDONLY (e.g. by ustack()) and
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * the reference count drops to zero, the handle is not immediately released.
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * Instead, libproc handles are maintained on dph_lrulist in order from most-
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * recently accessed to least-recently accessed. Idle handles are maintained
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * until a pre-defined LRU cache limit is exceeded, permitting repeated calls
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * to ustack() to avoid the overhead of releasing and re-grabbing processes.
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * Process Control: For processes that are grabbed for control (~PGRAB_RDONLY)
ae5af5aa3e87e134919787abd96b8ebfb1a19d62vboxsync * or created by dt_proc_create(), a control thread is created to provide
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * callbacks on process exit and symbol table caching on dlopen()s.
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * MT-Safety: Libproc is not MT-Safe, so dt_proc_lock() and dt_proc_unlock()
7da1c316d25649f85e7590b66a1713c02e69d814vboxsync * are provided to synchronize access to the libproc handle between libdtrace
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * code and client code and the control thread's use of the ps_prochandle.
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * NOTE: MT-Safety is NOT provided for libdtrace itself, or for use of the
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * dtrace_proc_grab/dtrace_proc_create mechanisms. Like all exported libdtrace
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * calls, these are assumed to be MT-Unsafe. MT-Safety is ONLY provided for
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * synchronization between libdtrace control threads and the client thread.
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * The ps_prochandles themselves are maintained along with a dt_proc_t struct
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * in a hash table indexed by PID. This provides basic locking and reference
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * counting. The dt_proc_t is also maintained in LRU order on dph_lrulist.
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * The dph_lrucnt and dph_lrulim count the number of cacheable processes and
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * the current limit on the number of actively cached entries.
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * The control thread for a process establishes breakpoints at the rtld_db
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * locations of interest, updates mappings and symbol tables at these points,
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * and handles exec and fork (by always following the parent). The control
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * thread automatically exits when the process dies or control is lost.
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * A simple notification mechanism is provided for libdtrace clients using
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * dtrace_handle_proc() for notification of PS_UNDEAD or PS_LOST events. If
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * such an event occurs, the dt_proc_t itself is enqueued on a notification
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * list and the control thread broadcasts to dph_cv. dtrace_sleep() will wake
c3cd0366348bcd10e42bd7be9ea05d194394f389vboxsync * up using this condition and will then call the client handler as necessary.
15617cf4cb5fa181f4d6f55f987a883cf298cce6vboxsync#define IS_SYS_FORK(w) (w == SYS_vfork || w == SYS_forksys)
15617cf4cb5fa181f4d6f55f987a883cf298cce6vboxsyncdt_proc_bpcreate(dt_proc_t *dpr, uintptr_t addr, dt_bkpt_f *func, void *data)
15617cf4cb5fa181f4d6f55f987a883cf298cce6vboxsync if ((dbp = dt_zalloc(dpr->dpr_hdl, sizeof (dt_bkpt_t))) != NULL) {
15617cf4cb5fa181f4d6f55f987a883cf298cce6vboxsync if (Psetbkpt(P, dbp->dbp_addr, &dbp->dbp_instr) == 0)
const char *msg)
case RD_DLACTIVITY:
case RD_PREINIT:
case RD_POSTINIT:
if (exec) {
* PR_REQUESTED stop. Since PCWSTOP/Pstopstatus() can be applied repeatedly
Psync(P);
Psync(P);
typedef struct dt_proc_control_data {
switch (Pstate(P)) {
case PS_STOP:
case PS_LOST:
if (Preopen(P) == 0)
goto pwait_locked;
case PS_UNDEAD:
if (notify)
return (NULL);
static struct ps_prochandle *
return (NULL);
if (remove)
return (dpr);
int rflag;
int err;
(void) pthread_attr_init(&a);
if (err == 0) {
(void) pthread_attr_destroy(&a);
return (err);
struct ps_prochandle *
int err;
struct ps_prochandle *
int err;
struct ps_prochandle *
struct ps_prochandle *