Home | History | Annotate | Line # | Download | only in common
      1  1.1    darran /*
      2  1.1    darran  * CDDL HEADER START
      3  1.1    darran  *
      4  1.1    darran  * The contents of this file are subject to the terms of the
      5  1.1    darran  * Common Development and Distribution License (the "License").
      6  1.1    darran  * You may not use this file except in compliance with the License.
      7  1.1    darran  *
      8  1.1    darran  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  1.1    darran  * or http://www.opensolaris.org/os/licensing.
     10  1.1    darran  * See the License for the specific language governing permissions
     11  1.1    darran  * and limitations under the License.
     12  1.1    darran  *
     13  1.1    darran  * When distributing Covered Code, include this CDDL HEADER in each
     14  1.1    darran  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  1.1    darran  * If applicable, add the following below this CDDL HEADER, with the
     16  1.1    darran  * fields enclosed by brackets "[]" replaced with your own identifying
     17  1.1    darran  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  1.1    darran  *
     19  1.1    darran  * CDDL HEADER END
     20  1.1    darran  */
     21  1.1    darran 
     22  1.1    darran /*
     23  1.1    darran  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     24  1.1    darran  * Use is subject to license terms.
     25  1.1    darran  */
     26  1.1    darran 
     27  1.7  christos /*
     28  1.7  christos  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
     29  1.7  christos  * Copyright (c) 2012 by Delphix. All rights reserved.
     30  1.7  christos  */
     31  1.1    darran 
     32  1.1    darran #include <sys/resource.h>
     33  1.1    darran #include <sys/mman.h>
     34  1.1    darran #include <sys/types.h>
     35  1.1    darran 
     36  1.1    darran #include <strings.h>
     37  1.1    darran #include <signal.h>
     38  1.1    darran #include <stdlib.h>
     39  1.1    darran #include <unistd.h>
     40  1.1    darran #include <limits.h>
     41  1.7  christos #ifdef illumos
     42  1.1    darran #include <alloca.h>
     43  1.2    darran #endif
     44  1.1    darran #include <errno.h>
     45  1.1    darran #include <fcntl.h>
     46  1.1    darran 
     47  1.1    darran #include <dt_impl.h>
     48  1.1    darran #include <dt_string.h>
     49  1.1    darran 
     50  1.1    darran static int
     51  1.1    darran dt_opt_agg(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
     52  1.1    darran {
     53  1.1    darran 	dt_aggregate_t *agp = &dtp->dt_aggregate;
     54  1.1    darran 
     55  1.1    darran 	if (arg != NULL)
     56  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
     57  1.1    darran 
     58  1.1    darran 	agp->dtat_flags |= option;
     59  1.1    darran 	return (0);
     60  1.1    darran }
     61  1.1    darran 
     62  1.1    darran /*ARGSUSED*/
     63  1.1    darran static int
     64  1.1    darran dt_opt_amin(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
     65  1.1    darran {
     66  1.1    darran 	char str[DTRACE_ATTR2STR_MAX];
     67  1.1    darran 	dtrace_attribute_t attr;
     68  1.1    darran 
     69  1.1    darran 	if (arg == NULL || dtrace_str2attr(arg, &attr) == -1)
     70  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
     71  1.1    darran 
     72  1.1    darran 	dt_dprintf("set compiler attribute minimum to %s\n",
     73  1.1    darran 	    dtrace_attr2str(attr, str, sizeof (str)));
     74  1.1    darran 
     75  1.1    darran 	if (dtp->dt_pcb != NULL) {
     76  1.1    darran 		dtp->dt_pcb->pcb_cflags |= DTRACE_C_EATTR;
     77  1.1    darran 		dtp->dt_pcb->pcb_amin = attr;
     78  1.1    darran 	} else {
     79  1.1    darran 		dtp->dt_cflags |= DTRACE_C_EATTR;
     80  1.1    darran 		dtp->dt_amin = attr;
     81  1.1    darran 	}
     82  1.1    darran 
     83  1.1    darran 	return (0);
     84  1.1    darran }
     85  1.1    darran 
     86  1.1    darran static void
     87  1.1    darran dt_coredump(void)
     88  1.1    darran {
     89  1.1    darran 	const char msg[] = "libdtrace DEBUG: [ forcing coredump ]\n";
     90  1.1    darran 
     91  1.1    darran 	struct sigaction act;
     92  1.1    darran 	struct rlimit lim;
     93  1.1    darran 
     94  1.1    darran 	(void) write(STDERR_FILENO, msg, sizeof (msg) - 1);
     95  1.1    darran 
     96  1.1    darran 	act.sa_handler = SIG_DFL;
     97  1.1    darran 	act.sa_flags = 0;
     98  1.1    darran 
     99  1.1    darran 	(void) sigemptyset(&act.sa_mask);
    100  1.1    darran 	(void) sigaction(SIGABRT, &act, NULL);
    101  1.1    darran 
    102  1.1    darran 	lim.rlim_cur = RLIM_INFINITY;
    103  1.1    darran 	lim.rlim_max = RLIM_INFINITY;
    104  1.1    darran 
    105  1.1    darran 	(void) setrlimit(RLIMIT_CORE, &lim);
    106  1.1    darran 	abort();
    107  1.1    darran }
    108  1.1    darran 
    109  1.1    darran /*ARGSUSED*/
    110  1.1    darran static int
    111  1.1    darran dt_opt_core(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    112  1.1    darran {
    113  1.1    darran 	static int enabled = 0;
    114  1.1    darran 
    115  1.1    darran 	if (arg != NULL)
    116  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    117  1.1    darran 
    118  1.1    darran 	if (enabled++ || atexit(dt_coredump) == 0)
    119  1.1    darran 		return (0);
    120  1.1    darran 
    121  1.1    darran 	return (dt_set_errno(dtp, errno));
    122  1.1    darran }
    123  1.1    darran 
    124  1.1    darran /*ARGSUSED*/
    125  1.1    darran static int
    126  1.1    darran dt_opt_cpp_hdrs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    127  1.1    darran {
    128  1.1    darran 	if (arg != NULL)
    129  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    130  1.1    darran 
    131  1.1    darran 	if (dtp->dt_pcb != NULL)
    132  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
    133  1.1    darran 
    134  1.1    darran 	if (dt_cpp_add_arg(dtp, "-H") == NULL)
    135  1.1    darran 		return (dt_set_errno(dtp, EDT_NOMEM));
    136  1.1    darran 
    137  1.1    darran 	return (0);
    138  1.1    darran }
    139  1.1    darran 
    140  1.1    darran /*ARGSUSED*/
    141  1.1    darran static int
    142  1.1    darran dt_opt_cpp_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    143  1.1    darran {
    144  1.1    darran 	char *cpp;
    145  1.1    darran 
    146  1.1    darran 	if (arg == NULL)
    147  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    148  1.1    darran 
    149  1.1    darran 	if (dtp->dt_pcb != NULL)
    150  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
    151  1.1    darran 
    152  1.1    darran 	if ((cpp = strdup(arg)) == NULL)
    153  1.1    darran 		return (dt_set_errno(dtp, EDT_NOMEM));
    154  1.1    darran 
    155  1.1    darran 	dtp->dt_cpp_argv[0] = (char *)strbasename(cpp);
    156  1.1    darran 	free(dtp->dt_cpp_path);
    157  1.1    darran 	dtp->dt_cpp_path = cpp;
    158  1.1    darran 
    159  1.1    darran 	return (0);
    160  1.1    darran }
    161  1.1    darran 
    162  1.1    darran static int
    163  1.1    darran dt_opt_cpp_opts(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    164  1.1    darran {
    165  1.1    darran 	char *buf;
    166  1.1    darran 	size_t len;
    167  1.1    darran 	const char *opt = (const char *)option;
    168  1.1    darran 
    169  1.1    darran 	if (opt == NULL || arg == NULL)
    170  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    171  1.1    darran 
    172  1.1    darran 	if (dtp->dt_pcb != NULL)
    173  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
    174  1.1    darran 
    175  1.1    darran 	len = strlen(opt) + strlen(arg) + 1;
    176  1.1    darran 	buf = alloca(len);
    177  1.1    darran 
    178  1.1    darran 	(void) strcpy(buf, opt);
    179  1.1    darran 	(void) strcat(buf, arg);
    180  1.1    darran 
    181  1.1    darran 	if (dt_cpp_add_arg(dtp, buf) == NULL)
    182  1.1    darran 		return (dt_set_errno(dtp, EDT_NOMEM));
    183  1.1    darran 
    184  1.1    darran 	return (0);
    185  1.1    darran }
    186  1.1    darran 
    187  1.1    darran /*ARGSUSED*/
    188  1.1    darran static int
    189  1.1    darran dt_opt_ctypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    190  1.1    darran {
    191  1.1    darran 	int fd;
    192  1.1    darran 
    193  1.1    darran 	if (arg == NULL)
    194  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    195  1.1    darran 
    196  1.1    darran 	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
    197  1.1    darran 		return (dt_set_errno(dtp, errno));
    198  1.1    darran 
    199  1.1    darran 	(void) close(dtp->dt_cdefs_fd);
    200  1.1    darran 	dtp->dt_cdefs_fd = fd;
    201  1.1    darran 	return (0);
    202  1.1    darran }
    203  1.1    darran 
    204  1.1    darran /*ARGSUSED*/
    205  1.1    darran static int
    206  1.1    darran dt_opt_droptags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    207  1.1    darran {
    208  1.1    darran 	dtp->dt_droptags = 1;
    209  1.1    darran 	return (0);
    210  1.1    darran }
    211  1.1    darran 
    212  1.1    darran /*ARGSUSED*/
    213  1.1    darran static int
    214  1.1    darran dt_opt_dtypes(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    215  1.1    darran {
    216  1.1    darran 	int fd;
    217  1.1    darran 
    218  1.1    darran 	if (arg == NULL)
    219  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    220  1.1    darran 
    221  1.1    darran 	if ((fd = open64(arg, O_CREAT | O_WRONLY, 0666)) == -1)
    222  1.1    darran 		return (dt_set_errno(dtp, errno));
    223  1.1    darran 
    224  1.1    darran 	(void) close(dtp->dt_ddefs_fd);
    225  1.1    darran 	dtp->dt_ddefs_fd = fd;
    226  1.1    darran 	return (0);
    227  1.1    darran }
    228  1.1    darran 
    229  1.1    darran /*ARGSUSED*/
    230  1.1    darran static int
    231  1.1    darran dt_opt_debug(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    232  1.1    darran {
    233  1.1    darran 	if (arg != NULL)
    234  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    235  1.1    darran 
    236  1.1    darran 	_dtrace_debug = 1;
    237  1.1    darran 	return (0);
    238  1.1    darran }
    239  1.1    darran 
    240  1.1    darran /*ARGSUSED*/
    241  1.1    darran static int
    242  1.1    darran dt_opt_iregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    243  1.1    darran {
    244  1.1    darran 	int n;
    245  1.1    darran 
    246  1.1    darran 	if (arg == NULL || (n = atoi(arg)) <= 0)
    247  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    248  1.1    darran 
    249  1.1    darran 	dtp->dt_conf.dtc_difintregs = n;
    250  1.1    darran 	return (0);
    251  1.1    darran }
    252  1.1    darran 
    253  1.1    darran /*ARGSUSED*/
    254  1.1    darran static int
    255  1.1    darran dt_opt_lazyload(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    256  1.1    darran {
    257  1.1    darran 	dtp->dt_lazyload = 1;
    258  1.1    darran 
    259  1.1    darran 	return (0);
    260  1.1    darran }
    261  1.1    darran 
    262  1.1    darran /*ARGSUSED*/
    263  1.1    darran static int
    264  1.1    darran dt_opt_ld_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    265  1.1    darran {
    266  1.1    darran 	char *ld;
    267  1.1    darran 
    268  1.1    darran 	if (arg == NULL)
    269  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    270  1.1    darran 
    271  1.1    darran 	if (dtp->dt_pcb != NULL)
    272  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
    273  1.1    darran 
    274  1.1    darran 	if ((ld = strdup(arg)) == NULL)
    275  1.1    darran 		return (dt_set_errno(dtp, EDT_NOMEM));
    276  1.1    darran 
    277  1.1    darran 	free(dtp->dt_ld_path);
    278  1.1    darran 	dtp->dt_ld_path = ld;
    279  1.1    darran 
    280  1.1    darran 	return (0);
    281  1.1    darran }
    282  1.1    darran 
    283  1.7  christos #if defined(__FreeBSD__) || defined(__NetBSD__)
    284  1.7  christos static int
    285  1.7  christos dt_opt_objcopy_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    286  1.7  christos {
    287  1.7  christos 	char *objcopy;
    288  1.7  christos 
    289  1.7  christos 	if (arg == NULL)
    290  1.7  christos 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    291  1.7  christos 
    292  1.7  christos 	if (dtp->dt_pcb != NULL)
    293  1.7  christos 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
    294  1.7  christos 
    295  1.7  christos 	if ((objcopy = strdup(arg)) == NULL)
    296  1.7  christos 		return (dt_set_errno(dtp, EDT_NOMEM));
    297  1.7  christos 
    298  1.7  christos 	free(dtp->dt_objcopy_path);
    299  1.7  christos 	dtp->dt_objcopy_path = objcopy;
    300  1.7  christos 
    301  1.7  christos 	return (0);
    302  1.7  christos }
    303  1.7  christos #endif
    304  1.7  christos 
    305  1.1    darran /*ARGSUSED*/
    306  1.1    darran static int
    307  1.1    darran dt_opt_libdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    308  1.1    darran {
    309  1.1    darran 	dt_dirpath_t *dp;
    310  1.1    darran 
    311  1.1    darran 	if (arg == NULL)
    312  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    313  1.1    darran 
    314  1.1    darran 	if ((dp = malloc(sizeof (dt_dirpath_t))) == NULL ||
    315  1.1    darran 	    (dp->dir_path = strdup(arg)) == NULL) {
    316  1.1    darran 		free(dp);
    317  1.1    darran 		return (dt_set_errno(dtp, EDT_NOMEM));
    318  1.1    darran 	}
    319  1.1    darran 
    320  1.1    darran 	dt_list_append(&dtp->dt_lib_path, dp);
    321  1.1    darran 	return (0);
    322  1.1    darran }
    323  1.1    darran 
    324  1.1    darran /*ARGSUSED*/
    325  1.1    darran static int
    326  1.1    darran dt_opt_linkmode(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    327  1.1    darran {
    328  1.1    darran 	if (arg == NULL)
    329  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    330  1.1    darran 
    331  1.1    darran 	if (strcmp(arg, "kernel") == 0)
    332  1.1    darran 		dtp->dt_linkmode = DT_LINK_KERNEL;
    333  1.1    darran 	else if (strcmp(arg, "primary") == 0)
    334  1.1    darran 		dtp->dt_linkmode = DT_LINK_PRIMARY;
    335  1.1    darran 	else if (strcmp(arg, "dynamic") == 0)
    336  1.1    darran 		dtp->dt_linkmode = DT_LINK_DYNAMIC;
    337  1.1    darran 	else if (strcmp(arg, "static") == 0)
    338  1.1    darran 		dtp->dt_linkmode = DT_LINK_STATIC;
    339  1.1    darran 	else
    340  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    341  1.1    darran 
    342  1.1    darran 	return (0);
    343  1.1    darran }
    344  1.1    darran 
    345  1.1    darran /*ARGSUSED*/
    346  1.1    darran static int
    347  1.1    darran dt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    348  1.1    darran {
    349  1.1    darran 	if (arg == NULL)
    350  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    351  1.1    darran 
    352  1.1    darran 	if (strcasecmp(arg, "elf") == 0)
    353  1.1    darran 		dtp->dt_linktype = DT_LTYP_ELF;
    354  1.1    darran 	else if (strcasecmp(arg, "dof") == 0)
    355  1.1    darran 		dtp->dt_linktype = DT_LTYP_DOF;
    356  1.1    darran 	else
    357  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    358  1.1    darran 
    359  1.1    darran 	return (0);
    360  1.1    darran }
    361  1.1    darran 
    362  1.1    darran /*ARGSUSED*/
    363  1.1    darran static int
    364  1.7  christos dt_opt_encoding(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    365  1.7  christos {
    366  1.7  christos 	if (arg == NULL)
    367  1.7  christos 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    368  1.7  christos 
    369  1.7  christos 	if (strcmp(arg, "ascii") == 0)
    370  1.7  christos 		dtp->dt_encoding = DT_ENCODING_ASCII;
    371  1.7  christos 	else if (strcmp(arg, "utf8") == 0)
    372  1.7  christos 		dtp->dt_encoding = DT_ENCODING_UTF8;
    373  1.7  christos 	else
    374  1.7  christos 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    375  1.7  christos 
    376  1.7  christos 	return (0);
    377  1.7  christos }
    378  1.7  christos 
    379  1.7  christos /*ARGSUSED*/
    380  1.7  christos static int
    381  1.1    darran dt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    382  1.1    darran {
    383  1.1    darran 	if (arg == NULL)
    384  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    385  1.1    darran 
    386  1.1    darran 	if (strcmp(arg, "exec") == 0)
    387  1.1    darran 		dtp->dt_prcmode = DT_PROC_STOP_CREATE;
    388  1.1    darran 	else if (strcmp(arg, "preinit") == 0)
    389  1.1    darran 		dtp->dt_prcmode = DT_PROC_STOP_PREINIT;
    390  1.1    darran 	else if (strcmp(arg, "postinit") == 0)
    391  1.1    darran 		dtp->dt_prcmode = DT_PROC_STOP_POSTINIT;
    392  1.1    darran 	else if (strcmp(arg, "main") == 0)
    393  1.1    darran 		dtp->dt_prcmode = DT_PROC_STOP_MAIN;
    394  1.1    darran 	else
    395  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    396  1.1    darran 
    397  1.1    darran 	return (0);
    398  1.1    darran }
    399  1.1    darran 
    400  1.1    darran /*ARGSUSED*/
    401  1.1    darran static int
    402  1.1    darran dt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    403  1.1    darran {
    404  1.1    darran 	int n;
    405  1.1    darran 
    406  1.1    darran 	if (arg == NULL || (n = atoi(arg)) < 0)
    407  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    408  1.1    darran 
    409  1.1    darran 	dtp->dt_procs->dph_lrulim = n;
    410  1.1    darran 	return (0);
    411  1.1    darran }
    412  1.1    darran 
    413  1.7  christos static int
    414  1.7  christos dt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    415  1.7  christos {
    416  1.7  christos 	char **p;
    417  1.7  christos 	char *var;
    418  1.7  christos 	int i;
    419  1.7  christos 
    420  1.7  christos 	/*
    421  1.7  christos 	 * We can't effectively set environment variables from #pragma lines
    422  1.7  christos 	 * since the processes have already been spawned.
    423  1.7  christos 	 */
    424  1.7  christos 	if (dtp->dt_pcb != NULL)
    425  1.7  christos 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
    426  1.7  christos 
    427  1.7  christos 	if (arg == NULL)
    428  1.7  christos 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    429  1.7  christos 
    430  1.7  christos 	if (!option && strchr(arg, '=') != NULL)
    431  1.7  christos 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    432  1.7  christos 
    433  1.7  christos 	for (i = 1, p = dtp->dt_proc_env; *p != NULL; i++, p++)
    434  1.7  christos 		continue;
    435  1.7  christos 
    436  1.7  christos 	for (p = dtp->dt_proc_env; *p != NULL; p++) {
    437  1.7  christos 		var = strchr(*p, '=');
    438  1.7  christos 		if (var == NULL)
    439  1.7  christos 			var = *p + strlen(*p);
    440  1.7  christos 		if (strncmp(*p, arg, var - *p) == 0) {
    441  1.7  christos 			dt_free(dtp, *p);
    442  1.7  christos 			*p = dtp->dt_proc_env[i - 1];
    443  1.7  christos 			dtp->dt_proc_env[i - 1] = NULL;
    444  1.7  christos 			i--;
    445  1.7  christos 		}
    446  1.7  christos 	}
    447  1.7  christos 
    448  1.7  christos 	if (option) {
    449  1.7  christos 		if ((var = strdup(arg)) == NULL)
    450  1.7  christos 			return (dt_set_errno(dtp, EDT_NOMEM));
    451  1.7  christos 
    452  1.7  christos 		if ((p = dt_alloc(dtp, sizeof (char *) * (i + 1))) == NULL) {
    453  1.7  christos 			dt_free(dtp, var);
    454  1.7  christos 			return (dt_set_errno(dtp, EDT_NOMEM));
    455  1.7  christos 		}
    456  1.7  christos 
    457  1.7  christos 		bcopy(dtp->dt_proc_env, p, sizeof (char *) * i);
    458  1.7  christos 		dt_free(dtp, dtp->dt_proc_env);
    459  1.7  christos 		dtp->dt_proc_env = p;
    460  1.7  christos 
    461  1.7  christos 		dtp->dt_proc_env[i - 1] = var;
    462  1.7  christos 		dtp->dt_proc_env[i] = NULL;
    463  1.7  christos 	}
    464  1.7  christos 
    465  1.7  christos 	return (0);
    466  1.7  christos }
    467  1.7  christos 
    468  1.1    darran /*ARGSUSED*/
    469  1.1    darran static int
    470  1.1    darran dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    471  1.1    darran {
    472  1.1    darran 	if (arg == NULL)
    473  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    474  1.1    darran 
    475  1.1    darran 	if (dtp->dt_pcb != NULL)
    476  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTCTX));
    477  1.1    darran 
    478  1.1    darran 	if (strcmp(arg, "a") == 0)
    479  1.1    darran 		dtp->dt_stdcmode = DT_STDC_XA;
    480  1.1    darran 	else if (strcmp(arg, "c") == 0)
    481  1.1    darran 		dtp->dt_stdcmode = DT_STDC_XC;
    482  1.1    darran 	else if (strcmp(arg, "s") == 0)
    483  1.1    darran 		dtp->dt_stdcmode = DT_STDC_XS;
    484  1.1    darran 	else if (strcmp(arg, "t") == 0)
    485  1.1    darran 		dtp->dt_stdcmode = DT_STDC_XT;
    486  1.1    darran 	else
    487  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    488  1.1    darran 
    489  1.1    darran 	return (0);
    490  1.1    darran }
    491  1.1    darran 
    492  1.1    darran /*ARGSUSED*/
    493  1.1    darran static int
    494  1.1    darran dt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    495  1.1    darran {
    496  1.1    darran 	dt_dirpath_t *dp = dt_list_next(&dtp->dt_lib_path);
    497  1.1    darran 	char *path;
    498  1.1    darran 
    499  1.1    darran 	if (arg == NULL)
    500  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    501  1.1    darran 
    502  1.1    darran 	if ((path = strdup(arg)) == NULL)
    503  1.1    darran 		return (dt_set_errno(dtp, EDT_NOMEM));
    504  1.1    darran 
    505  1.1    darran 	free(dp->dir_path);
    506  1.1    darran 	dp->dir_path = path;
    507  1.1    darran 
    508  1.1    darran 	return (0);
    509  1.1    darran }
    510  1.1    darran 
    511  1.1    darran /*ARGSUSED*/
    512  1.1    darran static int
    513  1.1    darran dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    514  1.1    darran {
    515  1.1    darran 	int m;
    516  1.1    darran 
    517  1.1    darran 	if (arg == NULL || (m = atoi(arg)) <= 0)
    518  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    519  1.1    darran 
    520  1.1    darran 	dtp->dt_treedump = m;
    521  1.1    darran 	return (0);
    522  1.1    darran }
    523  1.1    darran 
    524  1.1    darran /*ARGSUSED*/
    525  1.1    darran static int
    526  1.1    darran dt_opt_tregs(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    527  1.1    darran {
    528  1.1    darran 	int n;
    529  1.1    darran 
    530  1.1    darran 	if (arg == NULL || (n = atoi(arg)) <= 0)
    531  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    532  1.1    darran 
    533  1.1    darran 	dtp->dt_conf.dtc_diftupregs = n;
    534  1.1    darran 	return (0);
    535  1.1    darran }
    536  1.1    darran 
    537  1.1    darran /*ARGSUSED*/
    538  1.1    darran static int
    539  1.1    darran dt_opt_xlate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    540  1.1    darran {
    541  1.1    darran 	if (arg == NULL)
    542  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    543  1.1    darran 
    544  1.1    darran 	if (strcmp(arg, "dynamic") == 0)
    545  1.1    darran 		dtp->dt_xlatemode = DT_XL_DYNAMIC;
    546  1.1    darran 	else if (strcmp(arg, "static") == 0)
    547  1.1    darran 		dtp->dt_xlatemode = DT_XL_STATIC;
    548  1.1    darran 	else
    549  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    550  1.1    darran 
    551  1.1    darran 	return (0);
    552  1.1    darran }
    553  1.1    darran 
    554  1.1    darran /*ARGSUSED*/
    555  1.1    darran static int
    556  1.1    darran dt_opt_cflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    557  1.1    darran {
    558  1.1    darran 	if (arg != NULL)
    559  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    560  1.1    darran 
    561  1.1    darran 	if (dtp->dt_pcb != NULL)
    562  1.1    darran 		dtp->dt_pcb->pcb_cflags |= option;
    563  1.1    darran 	else
    564  1.1    darran 		dtp->dt_cflags |= option;
    565  1.1    darran 
    566  1.1    darran 	return (0);
    567  1.1    darran }
    568  1.1    darran 
    569  1.1    darran static int
    570  1.1    darran dt_opt_dflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    571  1.1    darran {
    572  1.1    darran 	if (arg != NULL)
    573  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    574  1.1    darran 
    575  1.1    darran 	dtp->dt_dflags |= option;
    576  1.1    darran 	return (0);
    577  1.1    darran }
    578  1.1    darran 
    579  1.1    darran static int
    580  1.1    darran dt_opt_invcflags(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    581  1.1    darran {
    582  1.1    darran 	if (arg != NULL)
    583  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    584  1.1    darran 
    585  1.1    darran 	if (dtp->dt_pcb != NULL)
    586  1.1    darran 		dtp->dt_pcb->pcb_cflags &= ~option;
    587  1.1    darran 	else
    588  1.1    darran 		dtp->dt_cflags &= ~option;
    589  1.1    darran 
    590  1.1    darran 	return (0);
    591  1.1    darran }
    592  1.1    darran 
    593  1.1    darran /*ARGSUSED*/
    594  1.1    darran static int
    595  1.1    darran dt_opt_version(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    596  1.1    darran {
    597  1.1    darran 	dt_version_t v;
    598  1.1    darran 
    599  1.1    darran 	if (arg == NULL)
    600  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    601  1.1    darran 
    602  1.1    darran 	if (dt_version_str2num(arg, &v) == -1)
    603  1.1    darran 		return (dt_set_errno(dtp, EDT_VERSINVAL));
    604  1.1    darran 
    605  1.1    darran 	if (!dt_version_defined(v))
    606  1.1    darran 		return (dt_set_errno(dtp, EDT_VERSUNDEF));
    607  1.1    darran 
    608  1.1    darran 	return (dt_reduce(dtp, v));
    609  1.1    darran }
    610  1.1    darran 
    611  1.1    darran static int
    612  1.1    darran dt_opt_runtime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    613  1.1    darran {
    614  1.1    darran 	char *end;
    615  1.1    darran 	dtrace_optval_t val = 0;
    616  1.1    darran 	int i;
    617  1.1    darran 
    618  1.1    darran 	const struct {
    619  1.1    darran 		char *positive;
    620  1.1    darran 		char *negative;
    621  1.1    darran 	} couples[] = {
    622  1.1    darran 		{ "yes",	"no" },
    623  1.1    darran 		{ "enable",	"disable" },
    624  1.1    darran 		{ "enabled",	"disabled" },
    625  1.1    darran 		{ "true",	"false" },
    626  1.1    darran 		{ "on",		"off" },
    627  1.1    darran 		{ "set",	"unset" },
    628  1.1    darran 		{ NULL }
    629  1.1    darran 	};
    630  1.1    darran 
    631  1.1    darran 	if (arg != NULL) {
    632  1.1    darran 		if (arg[0] == '\0') {
    633  1.1    darran 			val = DTRACEOPT_UNSET;
    634  1.1    darran 			goto out;
    635  1.1    darran 		}
    636  1.1    darran 
    637  1.1    darran 		for (i = 0; couples[i].positive != NULL; i++) {
    638  1.1    darran 			if (strcasecmp(couples[i].positive, arg) == 0) {
    639  1.1    darran 				val = 1;
    640  1.1    darran 				goto out;
    641  1.1    darran 			}
    642  1.1    darran 
    643  1.1    darran 			if (strcasecmp(couples[i].negative, arg) == 0) {
    644  1.1    darran 				val = DTRACEOPT_UNSET;
    645  1.1    darran 				goto out;
    646  1.1    darran 			}
    647  1.1    darran 		}
    648  1.1    darran 
    649  1.1    darran 		errno = 0;
    650  1.1    darran 		val = strtoull(arg, &end, 0);
    651  1.1    darran 
    652  1.1    darran 		if (*end != '\0' || errno != 0 || val < 0)
    653  1.1    darran 			return (dt_set_errno(dtp, EDT_BADOPTVAL));
    654  1.1    darran 	}
    655  1.1    darran 
    656  1.1    darran out:
    657  1.1    darran 	dtp->dt_options[option] = val;
    658  1.1    darran 	return (0);
    659  1.1    darran }
    660  1.1    darran 
    661  1.1    darran static int
    662  1.1    darran dt_optval_parse(const char *arg, dtrace_optval_t *rval)
    663  1.1    darran {
    664  1.1    darran 	dtrace_optval_t mul = 1;
    665  1.1    darran 	size_t len;
    666  1.1    darran 	char *end;
    667  1.1    darran 
    668  1.1    darran 	len = strlen(arg);
    669  1.1    darran 	errno = 0;
    670  1.1    darran 
    671  1.1    darran 	switch (arg[len - 1]) {
    672  1.1    darran 	case 't':
    673  1.1    darran 	case 'T':
    674  1.1    darran 		mul *= 1024;
    675  1.1    darran 		/*FALLTHRU*/
    676  1.1    darran 	case 'g':
    677  1.1    darran 	case 'G':
    678  1.1    darran 		mul *= 1024;
    679  1.1    darran 		/*FALLTHRU*/
    680  1.1    darran 	case 'm':
    681  1.1    darran 	case 'M':
    682  1.1    darran 		mul *= 1024;
    683  1.1    darran 		/*FALLTHRU*/
    684  1.1    darran 	case 'k':
    685  1.1    darran 	case 'K':
    686  1.1    darran 		mul *= 1024;
    687  1.1    darran 		/*FALLTHRU*/
    688  1.1    darran 	default:
    689  1.1    darran 		break;
    690  1.1    darran 	}
    691  1.1    darran 
    692  1.1    darran 	errno = 0;
    693  1.1    darran 	*rval = strtoull(arg, &end, 0) * mul;
    694  1.1    darran 
    695  1.1    darran 	if ((mul > 1 && end != &arg[len - 1]) || (mul == 1 && *end != '\0') ||
    696  1.1    darran 	    *rval < 0 || errno != 0)
    697  1.1    darran 		return (-1);
    698  1.1    darran 
    699  1.1    darran 	return (0);
    700  1.1    darran }
    701  1.1    darran 
    702  1.1    darran static int
    703  1.1    darran dt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    704  1.1    darran {
    705  1.1    darran 	dtrace_optval_t val = 0;
    706  1.1    darran 
    707  1.1    darran 	if (arg != NULL && dt_optval_parse(arg, &val) != 0)
    708  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    709  1.1    darran 
    710  1.1    darran 	dtp->dt_options[option] = val;
    711  1.1    darran 	return (0);
    712  1.1    darran }
    713  1.1    darran 
    714  1.1    darran static int
    715  1.1    darran dt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    716  1.1    darran {
    717  1.1    darran 	char *end;
    718  1.1    darran 	int i;
    719  1.1    darran 	dtrace_optval_t mul = 1, val = 0;
    720  1.1    darran 
    721  1.1    darran 	const struct {
    722  1.1    darran 		char *name;
    723  1.1    darran 		hrtime_t mul;
    724  1.1    darran 	} suffix[] = {
    725  1.1    darran 		{ "ns", 	NANOSEC / NANOSEC },
    726  1.1    darran 		{ "nsec",	NANOSEC / NANOSEC },
    727  1.1    darran 		{ "us",		NANOSEC / MICROSEC },
    728  1.1    darran 		{ "usec",	NANOSEC / MICROSEC },
    729  1.1    darran 		{ "ms",		NANOSEC / MILLISEC },
    730  1.1    darran 		{ "msec",	NANOSEC / MILLISEC },
    731  1.1    darran 		{ "s",		NANOSEC / SEC },
    732  1.1    darran 		{ "sec",	NANOSEC / SEC },
    733  1.1    darran 		{ "m",		NANOSEC * (hrtime_t)60 },
    734  1.1    darran 		{ "min",	NANOSEC * (hrtime_t)60 },
    735  1.1    darran 		{ "h",		NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
    736  1.1    darran 		{ "hour",	NANOSEC * (hrtime_t)60 * (hrtime_t)60 },
    737  1.1    darran 		{ "d",		NANOSEC * (hrtime_t)(24 * 60 * 60) },
    738  1.1    darran 		{ "day",	NANOSEC * (hrtime_t)(24 * 60 * 60) },
    739  1.1    darran 		{ "hz",		0 },
    740  1.1    darran 		{ NULL }
    741  1.1    darran 	};
    742  1.1    darran 
    743  1.1    darran 	if (arg != NULL) {
    744  1.1    darran 		errno = 0;
    745  1.1    darran 		val = strtoull(arg, &end, 0);
    746  1.1    darran 
    747  1.1    darran 		for (i = 0; suffix[i].name != NULL; i++) {
    748  1.1    darran 			if (strcasecmp(suffix[i].name, end) == 0) {
    749  1.1    darran 				mul = suffix[i].mul;
    750  1.1    darran 				break;
    751  1.1    darran 			}
    752  1.1    darran 		}
    753  1.1    darran 
    754  1.8       chs 		if (suffix[i].name == NULL && *end != '\0' || val < 0)
    755  1.1    darran 			return (dt_set_errno(dtp, EDT_BADOPTVAL));
    756  1.1    darran 
    757  1.1    darran 		if (mul == 0) {
    758  1.1    darran 			/*
    759  1.1    darran 			 * The rate has been specified in frequency-per-second.
    760  1.1    darran 			 */
    761  1.1    darran 			if (val != 0)
    762  1.1    darran 				val = NANOSEC / val;
    763  1.1    darran 		} else {
    764  1.1    darran 			val *= mul;
    765  1.1    darran 		}
    766  1.1    darran 	}
    767  1.1    darran 
    768  1.1    darran 	dtp->dt_options[option] = val;
    769  1.1    darran 	return (0);
    770  1.1    darran }
    771  1.1    darran 
    772  1.1    darran /*
    773  1.1    darran  * When setting the strsize option, set the option in the dt_options array
    774  1.1    darran  * using dt_opt_size() as usual, and then update the definition of the CTF
    775  1.1    darran  * type for the D intrinsic "string" to be an array of the corresponding size.
    776  1.1    darran  * If any errors occur, reset dt_options[option] to its previous value.
    777  1.1    darran  */
    778  1.1    darran static int
    779  1.1    darran dt_opt_strsize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    780  1.1    darran {
    781  1.1    darran 	dtrace_optval_t val = dtp->dt_options[option];
    782  1.1    darran 	ctf_file_t *fp = DT_STR_CTFP(dtp);
    783  1.1    darran 	ctf_id_t type = ctf_type_resolve(fp, DT_STR_TYPE(dtp));
    784  1.1    darran 	ctf_arinfo_t r;
    785  1.1    darran 
    786  1.1    darran 	if (dt_opt_size(dtp, arg, option) != 0)
    787  1.1    darran 		return (-1); /* dt_errno is set for us */
    788  1.1    darran 
    789  1.1    darran 	if (dtp->dt_options[option] > UINT_MAX) {
    790  1.1    darran 		dtp->dt_options[option] = val;
    791  1.1    darran 		return (dt_set_errno(dtp, EOVERFLOW));
    792  1.1    darran 	}
    793  1.1    darran 
    794  1.1    darran 	if (ctf_array_info(fp, type, &r) == CTF_ERR) {
    795  1.1    darran 		dtp->dt_options[option] = val;
    796  1.1    darran 		dtp->dt_ctferr = ctf_errno(fp);
    797  1.1    darran 		return (dt_set_errno(dtp, EDT_CTF));
    798  1.1    darran 	}
    799  1.1    darran 
    800  1.1    darran 	r.ctr_nelems = (uint_t)dtp->dt_options[option];
    801  1.1    darran 
    802  1.1    darran 	if (ctf_set_array(fp, type, &r) == CTF_ERR ||
    803  1.1    darran 	    ctf_update(fp) == CTF_ERR) {
    804  1.1    darran 		dtp->dt_options[option] = val;
    805  1.1    darran 		dtp->dt_ctferr = ctf_errno(fp);
    806  1.1    darran 		return (dt_set_errno(dtp, EDT_CTF));
    807  1.1    darran 	}
    808  1.1    darran 
    809  1.1    darran 	return (0);
    810  1.1    darran }
    811  1.1    darran 
    812  1.1    darran static const struct {
    813  1.1    darran 	const char *dtbp_name;
    814  1.1    darran 	int dtbp_policy;
    815  1.1    darran } _dtrace_bufpolicies[] = {
    816  1.1    darran 	{ "ring", DTRACEOPT_BUFPOLICY_RING },
    817  1.1    darran 	{ "fill", DTRACEOPT_BUFPOLICY_FILL },
    818  1.1    darran 	{ "switch", DTRACEOPT_BUFPOLICY_SWITCH },
    819  1.1    darran 	{ NULL, 0 }
    820  1.1    darran };
    821  1.1    darran 
    822  1.1    darran /*ARGSUSED*/
    823  1.1    darran static int
    824  1.1    darran dt_opt_bufpolicy(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    825  1.1    darran {
    826  1.1    darran 	dtrace_optval_t policy = DTRACEOPT_UNSET;
    827  1.1    darran 	int i;
    828  1.1    darran 
    829  1.1    darran 	if (arg == NULL)
    830  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    831  1.1    darran 
    832  1.1    darran 	for (i = 0; _dtrace_bufpolicies[i].dtbp_name != NULL; i++) {
    833  1.1    darran 		if (strcmp(_dtrace_bufpolicies[i].dtbp_name, arg) == 0) {
    834  1.1    darran 			policy = _dtrace_bufpolicies[i].dtbp_policy;
    835  1.1    darran 			break;
    836  1.1    darran 		}
    837  1.1    darran 	}
    838  1.1    darran 
    839  1.1    darran 	if (policy == DTRACEOPT_UNSET)
    840  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    841  1.1    darran 
    842  1.1    darran 	dtp->dt_options[DTRACEOPT_BUFPOLICY] = policy;
    843  1.1    darran 
    844  1.1    darran 	return (0);
    845  1.1    darran }
    846  1.1    darran 
    847  1.1    darran static const struct {
    848  1.1    darran 	const char *dtbr_name;
    849  1.1    darran 	int dtbr_policy;
    850  1.1    darran } _dtrace_bufresize[] = {
    851  1.1    darran 	{ "auto", DTRACEOPT_BUFRESIZE_AUTO },
    852  1.1    darran 	{ "manual", DTRACEOPT_BUFRESIZE_MANUAL },
    853  1.1    darran 	{ NULL, 0 }
    854  1.1    darran };
    855  1.1    darran 
    856  1.1    darran /*ARGSUSED*/
    857  1.1    darran static int
    858  1.1    darran dt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
    859  1.1    darran {
    860  1.1    darran 	dtrace_optval_t policy = DTRACEOPT_UNSET;
    861  1.1    darran 	int i;
    862  1.1    darran 
    863  1.1    darran 	if (arg == NULL)
    864  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    865  1.1    darran 
    866  1.1    darran 	for (i = 0; _dtrace_bufresize[i].dtbr_name != NULL; i++) {
    867  1.1    darran 		if (strcmp(_dtrace_bufresize[i].dtbr_name, arg) == 0) {
    868  1.1    darran 			policy = _dtrace_bufresize[i].dtbr_policy;
    869  1.1    darran 			break;
    870  1.1    darran 		}
    871  1.1    darran 	}
    872  1.1    darran 
    873  1.1    darran 	if (policy == DTRACEOPT_UNSET)
    874  1.1    darran 		return (dt_set_errno(dtp, EDT_BADOPTVAL));
    875  1.1    darran 
    876  1.1    darran 	dtp->dt_options[DTRACEOPT_BUFRESIZE] = policy;
    877  1.1    darran 
    878  1.1    darran 	return (0);
    879  1.1    darran }
    880  1.1    darran 
    881  1.1    darran int
    882  1.1    darran dt_options_load(dtrace_hdl_t *dtp)
    883  1.1    darran {
    884  1.1    darran 	dof_hdr_t hdr, *dof;
    885  1.7  christos 	dof_sec_t *sec = NULL;	// XXX: gcc
    886  1.1    darran 	size_t offs;
    887  1.1    darran 	int i;
    888  1.1    darran 
    889  1.1    darran 	/*
    890  1.1    darran 	 * To load the option values, we need to ask the kernel to provide its
    891  1.1    darran 	 * DOF, which we'll sift through to look for OPTDESC sections.
    892  1.1    darran 	 */
    893  1.1    darran 	bzero(&hdr, sizeof (dof_hdr_t));
    894  1.1    darran 	hdr.dofh_loadsz = sizeof (dof_hdr_t);
    895  1.1    darran 
    896  1.7  christos #ifdef illumos
    897  1.1    darran 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &hdr) == -1)
    898  1.2    darran #else
    899  1.2    darran 	dof = &hdr;
    900  1.2    darran 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &dof) == -1)
    901  1.2    darran #endif
    902  1.1    darran 		return (dt_set_errno(dtp, errno));
    903  1.1    darran 
    904  1.1    darran 	if (hdr.dofh_loadsz < sizeof (dof_hdr_t))
    905  1.1    darran 		return (dt_set_errno(dtp, EINVAL));
    906  1.1    darran 
    907  1.9  christos 	dof = calloc(hdr.dofh_loadsz, 1);
    908  1.9  christos 	if (dof == NULL)
    909  1.9  christos 		return (dt_set_errno(dtp, errno));
    910  1.1    darran 	dof->dofh_loadsz = hdr.dofh_loadsz;
    911  1.1    darran 
    912  1.1    darran 	for (i = 0; i < DTRACEOPT_MAX; i++)
    913  1.1    darran 		dtp->dt_options[i] = DTRACEOPT_UNSET;
    914  1.1    darran 
    915  1.7  christos #ifdef illumos
    916  1.1    darran 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, dof) == -1)
    917  1.2    darran #else
    918  1.2    darran 	if (dt_ioctl(dtp, DTRACEIOC_DOFGET, &dof) == -1)
    919  1.2    darran #endif
    920  1.9  christos 	{
    921  1.9  christos 		free(dof);
    922  1.1    darran 		return (dt_set_errno(dtp, errno));
    923  1.9  christos 	}
    924  1.1    darran 
    925  1.1    darran 	for (i = 0; i < dof->dofh_secnum; i++) {
    926  1.1    darran 		sec = (dof_sec_t *)(uintptr_t)((uintptr_t)dof +
    927  1.1    darran 		    dof->dofh_secoff + i * dof->dofh_secsize);
    928  1.1    darran 
    929  1.1    darran 		if (sec->dofs_type != DOF_SECT_OPTDESC)
    930  1.1    darran 			continue;
    931  1.1    darran 
    932  1.1    darran 		break;
    933  1.1    darran 	}
    934  1.1    darran 
    935  1.1    darran 	for (offs = 0; offs < sec->dofs_size; offs += sec->dofs_entsize) {
    936  1.1    darran 		dof_optdesc_t *opt = (dof_optdesc_t *)(uintptr_t)
    937  1.1    darran 		    ((uintptr_t)dof + sec->dofs_offset + offs);
    938  1.1    darran 
    939  1.1    darran 		if (opt->dofo_strtab != DOF_SECIDX_NONE)
    940  1.1    darran 			continue;
    941  1.1    darran 
    942  1.1    darran 		if (opt->dofo_option >= DTRACEOPT_MAX)
    943  1.1    darran 			continue;
    944  1.1    darran 
    945  1.1    darran 		dtp->dt_options[opt->dofo_option] = opt->dofo_value;
    946  1.1    darran 	}
    947  1.9  christos 	free(dof);
    948  1.1    darran 	return (0);
    949  1.1    darran }
    950  1.1    darran 
    951  1.1    darran typedef struct dt_option {
    952  1.1    darran 	const char *o_name;
    953  1.1    darran 	int (*o_func)(dtrace_hdl_t *, const char *, uintptr_t);
    954  1.1    darran 	uintptr_t o_option;
    955  1.1    darran } dt_option_t;
    956  1.1    darran 
    957  1.1    darran /*
    958  1.1    darran  * Compile-time options.
    959  1.1    darran  */
    960  1.1    darran static const dt_option_t _dtrace_ctoptions[] = {
    961  1.1    darran 	{ "aggpercpu", dt_opt_agg, DTRACE_A_PERCPU },
    962  1.1    darran 	{ "amin", dt_opt_amin },
    963  1.1    darran 	{ "argref", dt_opt_cflags, DTRACE_C_ARGREF },
    964  1.1    darran 	{ "core", dt_opt_core },
    965  1.1    darran 	{ "cpp", dt_opt_cflags, DTRACE_C_CPP },
    966  1.1    darran 	{ "cpphdrs", dt_opt_cpp_hdrs },
    967  1.1    darran 	{ "cpppath", dt_opt_cpp_path },
    968  1.1    darran 	{ "ctypes", dt_opt_ctypes },
    969  1.1    darran 	{ "defaultargs", dt_opt_cflags, DTRACE_C_DEFARG },
    970  1.1    darran 	{ "dtypes", dt_opt_dtypes },
    971  1.1    darran 	{ "debug", dt_opt_debug },
    972  1.1    darran 	{ "define", dt_opt_cpp_opts, (uintptr_t)"-D" },
    973  1.1    darran 	{ "droptags", dt_opt_droptags },
    974  1.1    darran 	{ "empty", dt_opt_cflags, DTRACE_C_EMPTY },
    975  1.7  christos 	{ "encoding", dt_opt_encoding },
    976  1.1    darran 	{ "errtags", dt_opt_cflags, DTRACE_C_ETAGS },
    977  1.1    darran 	{ "evaltime", dt_opt_evaltime },
    978  1.1    darran 	{ "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" },
    979  1.1    darran 	{ "iregs", dt_opt_iregs },
    980  1.1    darran 	{ "kdefs", dt_opt_invcflags, DTRACE_C_KNODEF },
    981  1.1    darran 	{ "knodefs", dt_opt_cflags, DTRACE_C_KNODEF },
    982  1.1    darran 	{ "late", dt_opt_xlate },
    983  1.1    darran 	{ "lazyload", dt_opt_lazyload },
    984  1.1    darran 	{ "ldpath", dt_opt_ld_path },
    985  1.1    darran 	{ "libdir", dt_opt_libdir },
    986  1.1    darran 	{ "linkmode", dt_opt_linkmode },
    987  1.1    darran 	{ "linktype", dt_opt_linktype },
    988  1.1    darran 	{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
    989  1.7  christos #if defined(__FreeBSD__) || defined(__NetBSD__)
    990  1.7  christos 	{ "objcopypath", dt_opt_objcopy_path },
    991  1.7  christos #endif
    992  1.1    darran 	{ "pgmax", dt_opt_pgmax },
    993  1.1    darran 	{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
    994  1.7  christos 	{ "setenv", dt_opt_setenv, 1 },
    995  1.1    darran 	{ "stdc", dt_opt_stdc },
    996  1.1    darran 	{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
    997  1.1    darran 	{ "syslibdir", dt_opt_syslibdir },
    998  1.1    darran 	{ "tree", dt_opt_tree },
    999  1.1    darran 	{ "tregs", dt_opt_tregs },
   1000  1.1    darran 	{ "udefs", dt_opt_invcflags, DTRACE_C_UNODEF },
   1001  1.1    darran 	{ "undef", dt_opt_cpp_opts, (uintptr_t)"-U" },
   1002  1.1    darran 	{ "unodefs", dt_opt_cflags, DTRACE_C_UNODEF },
   1003  1.7  christos 	{ "unsetenv", dt_opt_setenv, 0 },
   1004  1.1    darran 	{ "verbose", dt_opt_cflags, DTRACE_C_DIFV },
   1005  1.1    darran 	{ "version", dt_opt_version },
   1006  1.1    darran 	{ "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS },
   1007  1.2    darran 	{ NULL, NULL, 0 }
   1008  1.1    darran };
   1009  1.1    darran 
   1010  1.1    darran /*
   1011  1.1    darran  * Run-time options.
   1012  1.1    darran  */
   1013  1.1    darran static const dt_option_t _dtrace_rtoptions[] = {
   1014  1.1    darran 	{ "aggsize", dt_opt_size, DTRACEOPT_AGGSIZE },
   1015  1.1    darran 	{ "bufsize", dt_opt_size, DTRACEOPT_BUFSIZE },
   1016  1.1    darran 	{ "bufpolicy", dt_opt_bufpolicy, DTRACEOPT_BUFPOLICY },
   1017  1.1    darran 	{ "bufresize", dt_opt_bufresize, DTRACEOPT_BUFRESIZE },
   1018  1.1    darran 	{ "cleanrate", dt_opt_rate, DTRACEOPT_CLEANRATE },
   1019  1.1    darran 	{ "cpu", dt_opt_runtime, DTRACEOPT_CPU },
   1020  1.1    darran 	{ "destructive", dt_opt_runtime, DTRACEOPT_DESTRUCTIVE },
   1021  1.1    darran 	{ "dynvarsize", dt_opt_size, DTRACEOPT_DYNVARSIZE },
   1022  1.1    darran 	{ "grabanon", dt_opt_runtime, DTRACEOPT_GRABANON },
   1023  1.1    darran 	{ "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES },
   1024  1.1    darran 	{ "jstackstrsize", dt_opt_size, DTRACEOPT_JSTACKSTRSIZE },
   1025  1.1    darran 	{ "nspec", dt_opt_runtime, DTRACEOPT_NSPEC },
   1026  1.1    darran 	{ "specsize", dt_opt_size, DTRACEOPT_SPECSIZE },
   1027  1.1    darran 	{ "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES },
   1028  1.1    darran 	{ "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE },
   1029  1.1    darran 	{ "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE },
   1030  1.1    darran 	{ "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES },
   1031  1.7  christos 	{ "temporal", dt_opt_runtime, DTRACEOPT_TEMPORAL },
   1032  1.2    darran 	{ NULL, NULL, 0 }
   1033  1.1    darran };
   1034  1.1    darran 
   1035  1.1    darran /*
   1036  1.1    darran  * Dynamic run-time options.
   1037  1.1    darran  */
   1038  1.1    darran static const dt_option_t _dtrace_drtoptions[] = {
   1039  1.7  christos 	{ "agghist", dt_opt_runtime, DTRACEOPT_AGGHIST },
   1040  1.7  christos 	{ "aggpack", dt_opt_runtime, DTRACEOPT_AGGPACK },
   1041  1.1    darran 	{ "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE },
   1042  1.1    darran 	{ "aggsortkey", dt_opt_runtime, DTRACEOPT_AGGSORTKEY },
   1043  1.1    darran 	{ "aggsortkeypos", dt_opt_runtime, DTRACEOPT_AGGSORTKEYPOS },
   1044  1.1    darran 	{ "aggsortpos", dt_opt_runtime, DTRACEOPT_AGGSORTPOS },
   1045  1.1    darran 	{ "aggsortrev", dt_opt_runtime, DTRACEOPT_AGGSORTREV },
   1046  1.7  christos 	{ "aggzoom", dt_opt_runtime, DTRACEOPT_AGGZOOM },
   1047  1.1    darran 	{ "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT },
   1048  1.1    darran 	{ "quiet", dt_opt_runtime, DTRACEOPT_QUIET },
   1049  1.1    darran 	{ "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES },
   1050  1.1    darran 	{ "stackindent", dt_opt_runtime, DTRACEOPT_STACKINDENT },
   1051  1.1    darran 	{ "switchrate", dt_opt_rate, DTRACEOPT_SWITCHRATE },
   1052  1.2    darran 	{ NULL, NULL, 0 }
   1053  1.1    darran };
   1054  1.1    darran 
   1055  1.1    darran int
   1056  1.1    darran dtrace_getopt(dtrace_hdl_t *dtp, const char *opt, dtrace_optval_t *val)
   1057  1.1    darran {
   1058  1.1    darran 	const dt_option_t *op;
   1059  1.1    darran 
   1060  1.1    darran 	if (opt == NULL)
   1061  1.1    darran 		return (dt_set_errno(dtp, EINVAL));
   1062  1.1    darran 
   1063  1.1    darran 	/*
   1064  1.1    darran 	 * We only need to search the run-time options -- it's not legal
   1065  1.1    darran 	 * to get the values of compile-time options.
   1066  1.1    darran 	 */
   1067  1.1    darran 	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
   1068  1.1    darran 		if (strcmp(op->o_name, opt) == 0) {
   1069  1.1    darran 			*val = dtp->dt_options[op->o_option];
   1070  1.1    darran 			return (0);
   1071  1.1    darran 		}
   1072  1.1    darran 	}
   1073  1.1    darran 
   1074  1.1    darran 	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
   1075  1.1    darran 		if (strcmp(op->o_name, opt) == 0) {
   1076  1.1    darran 			*val = dtp->dt_options[op->o_option];
   1077  1.1    darran 			return (0);
   1078  1.1    darran 		}
   1079  1.1    darran 	}
   1080  1.1    darran 
   1081  1.1    darran 	return (dt_set_errno(dtp, EDT_BADOPTNAME));
   1082  1.1    darran }
   1083  1.1    darran 
   1084  1.1    darran int
   1085  1.1    darran dtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val)
   1086  1.1    darran {
   1087  1.1    darran 	const dt_option_t *op;
   1088  1.1    darran 
   1089  1.1    darran 	if (opt == NULL)
   1090  1.1    darran 		return (dt_set_errno(dtp, EINVAL));
   1091  1.1    darran 
   1092  1.1    darran 	for (op = _dtrace_ctoptions; op->o_name != NULL; op++) {
   1093  1.1    darran 		if (strcmp(op->o_name, opt) == 0)
   1094  1.1    darran 			return (op->o_func(dtp, val, op->o_option));
   1095  1.1    darran 	}
   1096  1.1    darran 
   1097  1.1    darran 	for (op = _dtrace_drtoptions; op->o_name != NULL; op++) {
   1098  1.1    darran 		if (strcmp(op->o_name, opt) == 0)
   1099  1.1    darran 			return (op->o_func(dtp, val, op->o_option));
   1100  1.1    darran 	}
   1101  1.1    darran 
   1102  1.1    darran 	for (op = _dtrace_rtoptions; op->o_name != NULL; op++) {
   1103  1.1    darran 		if (strcmp(op->o_name, opt) == 0) {
   1104  1.1    darran 			/*
   1105  1.1    darran 			 * Only dynamic run-time options may be set while
   1106  1.1    darran 			 * tracing is active.
   1107  1.1    darran 			 */
   1108  1.1    darran 			if (dtp->dt_active)
   1109  1.1    darran 				return (dt_set_errno(dtp, EDT_ACTIVE));
   1110  1.1    darran 
   1111  1.1    darran 			return (op->o_func(dtp, val, op->o_option));
   1112  1.1    darran 		}
   1113  1.1    darran 	}
   1114  1.1    darran 
   1115  1.1    darran 	return (dt_set_errno(dtp, EDT_BADOPTNAME));
   1116  1.1    darran }
   1117