summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/dtrace.c8
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggencoding.d32
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggencoding.d.out646
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.agghist.d46
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.agghist.d.out38
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpack.d53
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpack.d.out124
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackbanner.ksh75
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackbanner.ksh.out102
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackzoom.d43
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackzoom.d.out149
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggzoom.d35
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggzoom.d.out211
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d4
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d179
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d.out218
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d51
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d.out13
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.c61
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d65
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d.out11
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/usdt.d27
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.fds.ksh91
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.func_access.ksh9
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.getf.ksh98
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.procpriv.ksh138
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.providers.ksh126
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooLarge.d35
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooSmall.d34
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d66
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d.out20
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidpid.d21
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidpid2.d21
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidpid3.d21
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidtype.ksh34
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidtype2.ksh35
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.user64mode.ksh90
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.aouttype.c46
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.aouttype.ksh44
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.c79
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.ksh76
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.ksh.out4
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.libtype.c29
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.libtype.ksh45
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.linkmap.ksh44
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.pidprint.ksh69
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.pidprinttarg.ksh70
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtype.c72
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtype.ksh69
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtype.ksh.out16
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtypetarg.ksh70
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh83
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh.out4
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userstrings.ksh72
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userstrings.ksh.out4
-rw-r--r--cddl/contrib/opensolaris/common/ctf/ctf_open.c88
-rw-r--r--cddl/contrib/opensolaris/common/ctf/ctf_types.c41
-rw-r--r--cddl/contrib/opensolaris/common/util/strtolctype.h79
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c264
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_as.c8
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c25
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c447
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.c10
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.h7
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_dis.c10
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_error.c3
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y8
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_ident.c21
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h19
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l15
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c284
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.h10
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c21
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c22
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c155
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h8
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c172
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.h8
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c27
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c6
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c29
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.c13
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h16
-rw-r--r--cddl/lib/libdtrace/libproc_compat.h2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c1079
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/dtrace/sdt_subr.c23
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/sys/ctf_api.h5
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h41
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h2
-rw-r--r--sys/cddl/dev/dtrace/dtrace_cddl.h1
-rw-r--r--sys/modules/dtrace/dtrace/Makefile1
91 files changed, 6652 insertions, 244 deletions
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c
index a745ceb..4cbb866 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c
+++ b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c
@@ -25,6 +25,7 @@
*/
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#include <sys/types.h>
@@ -513,6 +514,7 @@ static void
print_probe_info(const dtrace_probeinfo_t *p)
{
char buf[BUFSIZ];
+ char *user;
int i;
oprintf("\n\tProbe Description Attributes\n");
@@ -536,10 +538,14 @@ print_probe_info(const dtrace_probeinfo_t *p)
oprintf("\n\tArgument Types\n");
for (i = 0; i < p->dtp_argc; i++) {
+ if (p->dtp_argv[i].dtt_flags & DTT_FL_USER)
+ user = "userland ";
+ else
+ user = "";
if (ctf_type_name(p->dtp_argv[i].dtt_ctfp,
p->dtp_argv[i].dtt_type, buf, sizeof (buf)) == NULL)
(void) strlcpy(buf, "(unknown)", sizeof (buf));
- oprintf("\t\targs[%d]: %s\n", i, buf);
+ oprintf("\t\targs[%d]: %s%s\n", i, user, buf);
}
if (p->dtp_argc == 0)
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggencoding.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggencoding.d
new file mode 100644
index 0000000..a594afc
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggencoding.d
@@ -0,0 +1,32 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
+
+#pragma D option quiet
+#pragma D option encoding=utf8
+#pragma D option aggzoom
+
+tick-1ms
+/i++ < 320/
+{
+ @ = lquantize(i, 0, 640, 1, i);
+ @ = lquantize(641 - i, 0, 640, 1, i);
+}
+
+tick-1ms
+/i == 320/
+{
+ printa(@);
+ exit(0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggencoding.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggencoding.d.out
new file mode 100644
index 0000000..68482ff
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggencoding.d.out
@@ -0,0 +1,646 @@
+
+
+ value ------------- Distribution ------------- count
+ 0 | 0
+ 1 | 1
+ 2 |▏ 2
+ 3 |▎ 3
+ 4 |▍ 4
+ 5 |▌ 5
+ 6 |▋ 6
+ 7 |▊ 7
+ 8 |▉ 8
+ 9 |█ 9
+ 10 |█▏ 10
+ 11 |█▎ 11
+ 12 |█▍ 12
+ 13 |█▌ 13
+ 14 |█▋ 14
+ 15 |█▊ 15
+ 16 |█▉ 16
+ 17 |██ 17
+ 18 |██▏ 18
+ 19 |██▎ 19
+ 20 |██▍ 20
+ 21 |██▍ 21
+ 22 |██▌ 22
+ 23 |██▋ 23
+ 24 |██▊ 24
+ 25 |██▉ 25
+ 26 |███ 26
+ 27 |███▏ 27
+ 28 |███▎ 28
+ 29 |███▍ 29
+ 30 |███▌ 30
+ 31 |███▋ 31
+ 32 |███▊ 32
+ 33 |███▉ 33
+ 34 |████ 34
+ 35 |████▏ 35
+ 36 |████▎ 36
+ 37 |████▍ 37
+ 38 |████▌ 38
+ 39 |████▋ 39
+ 40 |████▊ 40
+ 41 |████▊ 41
+ 42 |████▉ 42
+ 43 |█████ 43
+ 44 |█████▏ 44
+ 45 |█████▎ 45
+ 46 |█████▍ 46
+ 47 |█████▌ 47
+ 48 |█████▋ 48
+ 49 |█████▊ 49
+ 50 |█████▉ 50
+ 51 |██████ 51
+ 52 |██████▏ 52
+ 53 |██████▎ 53
+ 54 |██████▍ 54
+ 55 |██████▌ 55
+ 56 |██████▋ 56
+ 57 |██████▊ 57
+ 58 |██████▉ 58
+ 59 |███████ 59
+ 60 |███████▏ 60
+ 61 |███████▏ 61
+ 62 |███████▎ 62
+ 63 |███████▍ 63
+ 64 |███████▌ 64
+ 65 |███████▋ 65
+ 66 |███████▊ 66
+ 67 |███████▉ 67
+ 68 |████████ 68
+ 69 |████████▏ 69
+ 70 |████████▎ 70
+ 71 |████████▍ 71
+ 72 |████████▌ 72
+ 73 |████████▋ 73
+ 74 |████████▊ 74
+ 75 |████████▉ 75
+ 76 |█████████ 76
+ 77 |█████████▏ 77
+ 78 |█████████▎ 78
+ 79 |█████████▍ 79
+ 80 |█████████▌ 80
+ 81 |█████████▌ 81
+ 82 |█████████▋ 82
+ 83 |█████████▊ 83
+ 84 |█████████▉ 84
+ 85 |██████████ 85
+ 86 |██████████▏ 86
+ 87 |██████████▎ 87
+ 88 |██████████▍ 88
+ 89 |██████████▌ 89
+ 90 |██████████▋ 90
+ 91 |██████████▊ 91
+ 92 |██████████▉ 92
+ 93 |███████████ 93
+ 94 |███████████▏ 94
+ 95 |███████████▎ 95
+ 96 |███████████▍ 96
+ 97 |███████████▌ 97
+ 98 |███████████▋ 98
+ 99 |███████████▊ 99
+ 100 |███████████▉ 100
+ 101 |███████████▉ 101
+ 102 |████████████ 102
+ 103 |████████████▏ 103
+ 104 |████████████▎ 104
+ 105 |████████████▍ 105
+ 106 |████████████▌ 106
+ 107 |████████████▋ 107
+ 108 |████████████▊ 108
+ 109 |████████████▉ 109
+ 110 |█████████████ 110
+ 111 |█████████████▏ 111
+ 112 |█████████████▎ 112
+ 113 |█████████████▍ 113
+ 114 |█████████████▌ 114
+ 115 |█████████████▋ 115
+ 116 |█████████████▊ 116
+ 117 |█████████████▉ 117
+ 118 |██████████████ 118
+ 119 |██████████████▏ 119
+ 120 |██████████████▎ 120
+ 121 |██████████████▎ 121
+ 122 |██████████████▍ 122
+ 123 |██████████████▌ 123
+ 124 |██████████████▋ 124
+ 125 |██████████████▊ 125
+ 126 |██████████████▉ 126
+ 127 |███████████████ 127
+ 128 |███████████████▏ 128
+ 129 |███████████████▎ 129
+ 130 |███████████████▍ 130
+ 131 |███████████████▌ 131
+ 132 |███████████████▋ 132
+ 133 |███████████████▊ 133
+ 134 |███████████████▉ 134
+ 135 |████████████████ 135
+ 136 |████████████████▏ 136
+ 137 |████████████████▎ 137
+ 138 |████████████████▍ 138
+ 139 |████████████████▌ 139
+ 140 |████████████████▋ 140
+ 141 |████████████████▋ 141
+ 142 |████████████████▊ 142
+ 143 |████████████████▉ 143
+ 144 |█████████████████ 144
+ 145 |█████████████████▏ 145
+ 146 |█████████████████▎ 146
+ 147 |█████████████████▍ 147
+ 148 |█████████████████▌ 148
+ 149 |█████████████████▋ 149
+ 150 |█████████████████▊ 150
+ 151 |█████████████████▉ 151
+ 152 |██████████████████ 152
+ 153 |██████████████████▏ 153
+ 154 |██████████████████▎ 154
+ 155 |██████████████████▍ 155
+ 156 |██████████████████▌ 156
+ 157 |██████████████████▋ 157
+ 158 |██████████████████▊ 158
+ 159 |██████████████████▉ 159
+ 160 |███████████████████ 160
+ 161 |███████████████████ 161
+ 162 |███████████████████▏ 162
+ 163 |███████████████████▎ 163
+ 164 |███████████████████▍ 164
+ 165 |███████████████████▌ 165
+ 166 |███████████████████▋ 166
+ 167 |███████████████████▊ 167
+ 168 |███████████████████▉ 168
+ 169 |████████████████████ 169
+ 170 |████████████████████▏ 170
+ 171 |████████████████████▎ 171
+ 172 |████████████████████▍ 172
+ 173 |████████████████████▌ 173
+ 174 |████████████████████▋ 174
+ 175 |████████████████████▊ 175
+ 176 |████████████████████▉ 176
+ 177 |█████████████████████ 177
+ 178 |█████████████████████▏ 178
+ 179 |█████████████████████▎ 179
+ 180 |█████████████████████▍ 180
+ 181 |█████████████████████▍ 181
+ 182 |█████████████████████▌ 182
+ 183 |█████████████████████▋ 183
+ 184 |█████████████████████▊ 184
+ 185 |█████████████████████▉ 185
+ 186 |██████████████████████ 186
+ 187 |██████████████████████▏ 187
+ 188 |██████████████████████▎ 188
+ 189 |██████████████████████▍ 189
+ 190 |██████████████████████▌ 190
+ 191 |██████████████████████▋ 191
+ 192 |██████████████████████▊ 192
+ 193 |██████████████████████▉ 193
+ 194 |███████████████████████ 194
+ 195 |███████████████████████▏ 195
+ 196 |███████████████████████▎ 196
+ 197 |███████████████████████▍ 197
+ 198 |███████████████████████▌ 198
+ 199 |███████████████████████▋ 199
+ 200 |███████████████████████▊ 200
+ 201 |███████████████████████▊ 201
+ 202 |███████████████████████▉ 202
+ 203 |████████████████████████ 203
+ 204 |████████████████████████▏ 204
+ 205 |████████████████████████▎ 205
+ 206 |████████████████████████▍ 206
+ 207 |████████████████████████▌ 207
+ 208 |████████████████████████▋ 208
+ 209 |████████████████████████▊ 209
+ 210 |████████████████████████▉ 210
+ 211 |█████████████████████████ 211
+ 212 |█████████████████████████▏ 212
+ 213 |█████████████████████████▎ 213
+ 214 |█████████████████████████▍ 214
+ 215 |█████████████████████████▌ 215
+ 216 |█████████████████████████▋ 216
+ 217 |█████████████████████████▊ 217
+ 218 |█████████████████████████▉ 218
+ 219 |██████████████████████████ 219
+ 220 |██████████████████████████▏ 220
+ 221 |██████████████████████████▏ 221
+ 222 |██████████████████████████▎ 222
+ 223 |██████████████████████████▍ 223
+ 224 |██████████████████████████▌ 224
+ 225 |██████████████████████████▋ 225
+ 226 |██████████████████████████▊ 226
+ 227 |██████████████████████████▉ 227
+ 228 |███████████████████████████ 228
+ 229 |███████████████████████████▏ 229
+ 230 |███████████████████████████▎ 230
+ 231 |███████████████████████████▍ 231
+ 232 |███████████████████████████▌ 232
+ 233 |███████████████████████████▋ 233
+ 234 |███████████████████████████▊ 234
+ 235 |███████████████████████████▉ 235
+ 236 |████████████████████████████ 236
+ 237 |████████████████████████████▏ 237
+ 238 |████████████████████████████▎ 238
+ 239 |████████████████████████████▍ 239
+ 240 |████████████████████████████▌ 240
+ 241 |████████████████████████████▌ 241
+ 242 |████████████████████████████▋ 242
+ 243 |████████████████████████████▊ 243
+ 244 |████████████████████████████▉ 244
+ 245 |█████████████████████████████ 245
+ 246 |█████████████████████████████▏ 246
+ 247 |█████████████████████████████▎ 247
+ 248 |█████████████████████████████▍ 248
+ 249 |█████████████████████████████▌ 249
+ 250 |█████████████████████████████▋ 250
+ 251 |█████████████████████████████▊ 251
+ 252 |█████████████████████████████▉ 252
+ 253 |██████████████████████████████ 253
+ 254 |██████████████████████████████▏ 254
+ 255 |██████████████████████████████▎ 255
+ 256 |██████████████████████████████▍ 256
+ 257 |██████████████████████████████▌ 257
+ 258 |██████████████████████████████▋ 258
+ 259 |██████████████████████████████▊ 259
+ 260 |██████████████████████████████▉ 260
+ 261 |██████████████████████████████▉ 261
+ 262 |███████████████████████████████ 262
+ 263 |███████████████████████████████▏ 263
+ 264 |███████████████████████████████▎ 264
+ 265 |███████████████████████████████▍ 265
+ 266 |███████████████████████████████▌ 266
+ 267 |███████████████████████████████▋ 267
+ 268 |███████████████████████████████▊ 268
+ 269 |███████████████████████████████▉ 269
+ 270 |████████████████████████████████ 270
+ 271 |████████████████████████████████▏ 271
+ 272 |████████████████████████████████▎ 272
+ 273 |████████████████████████████████▍ 273
+ 274 |████████████████████████████████▌ 274
+ 275 |████████████████████████████████▋ 275
+ 276 |████████████████████████████████▊ 276
+ 277 |████████████████████████████████▉ 277
+ 278 |█████████████████████████████████ 278
+ 279 |█████████████████████████████████▏ 279
+ 280 |█████████████████████████████████▎ 280
+ 281 |█████████████████████████████████▎ 281
+ 282 |█████████████████████████████████▍ 282
+ 283 |█████████████████████████████████▌ 283
+ 284 |█████████████████████████████████▋ 284
+ 285 |█████████████████████████████████▊ 285
+ 286 |█████████████████████████████████▉ 286
+ 287 |██████████████████████████████████ 287
+ 288 |██████████████████████████████████▏ 288
+ 289 |██████████████████████████████████▎ 289
+ 290 |██████████████████████████████████▍ 290
+ 291 |██████████████████████████████████▌ 291
+ 292 |██████████████████████████████████▋ 292
+ 293 |██████████████████████████████████▊ 293
+ 294 |██████████████████████████████████▉ 294
+ 295 |███████████████████████████████████ 295
+ 296 |███████████████████████████████████▏ 296
+ 297 |███████████████████████████████████▎ 297
+ 298 |███████████████████████████████████▍ 298
+ 299 |███████████████████████████████████▌ 299
+ 300 |███████████████████████████████████▋ 300
+ 301 |███████████████████████████████████▋ 301
+ 302 |███████████████████████████████████▊ 302
+ 303 |███████████████████████████████████▉ 303
+ 304 |████████████████████████████████████ 304
+ 305 |████████████████████████████████████▏ 305
+ 306 |████████████████████████████████████▎ 306
+ 307 |████████████████████████████████████▍ 307
+ 308 |████████████████████████████████████▌ 308
+ 309 |████████████████████████████████████▋ 309
+ 310 |████████████████████████████████████▊ 310
+ 311 |████████████████████████████████████▉ 311
+ 312 |█████████████████████████████████████ 312
+ 313 |█████████████████████████████████████▏ 313
+ 314 |█████████████████████████████████████▎ 314
+ 315 |█████████████████████████████████████▍ 315
+ 316 |█████████████████████████████████████▌ 316
+ 317 |█████████████████████████████████████▋ 317
+ 318 |█████████████████████████████████████▊ 318
+ 319 |█████████████████████████████████████▉ 319
+ 320 |██████████████████████████████████████ 320
+ 321 |██████████████████████████████████████ 320
+ 322 |█████████████████████████████████████▉ 319
+ 323 |█████████████████████████████████████▊ 318
+ 324 |█████████████████████████████████████▋ 317
+ 325 |█████████████████████████████████████▌ 316
+ 326 |█████████████████████████████████████▍ 315
+ 327 |█████████████████████████████████████▎ 314
+ 328 |█████████████████████████████████████▏ 313
+ 329 |█████████████████████████████████████ 312
+ 330 |████████████████████████████████████▉ 311
+ 331 |████████████████████████████████████▊ 310
+ 332 |████████████████████████████████████▋ 309
+ 333 |████████████████████████████████████▌ 308
+ 334 |████████████████████████████████████▍ 307
+ 335 |████████████████████████████████████▎ 306
+ 336 |████████████████████████████████████▏ 305
+ 337 |████████████████████████████████████ 304
+ 338 |███████████████████████████████████▉ 303
+ 339 |███████████████████████████████████▊ 302
+ 340 |███████████████████████████████████▋ 301
+ 341 |███████████████████████████████████▋ 300
+ 342 |███████████████████████████████████▌ 299
+ 343 |███████████████████████████████████▍ 298
+ 344 |███████████████████████████████████▎ 297
+ 345 |███████████████████████████████████▏ 296
+ 346 |███████████████████████████████████ 295
+ 347 |██████████████████████████████████▉ 294
+ 348 |██████████████████████████████████▊ 293
+ 349 |██████████████████████████████████▋ 292
+ 350 |██████████████████████████████████▌ 291
+ 351 |██████████████████████████████████▍ 290
+ 352 |██████████████████████████████████▎ 289
+ 353 |██████████████████████████████████▏ 288
+ 354 |██████████████████████████████████ 287
+ 355 |█████████████████████████████████▉ 286
+ 356 |█████████████████████████████████▊ 285
+ 357 |█████████████████████████████████▋ 284
+ 358 |█████████████████████████████████▌ 283
+ 359 |█████████████████████████████████▍ 282
+ 360 |█████████████████████████████████▎ 281
+ 361 |█████████████████████████████████▎ 280
+ 362 |█████████████████████████████████▏ 279
+ 363 |█████████████████████████████████ 278
+ 364 |████████████████████████████████▉ 277
+ 365 |████████████████████████████████▊ 276
+ 366 |████████████████████████████████▋ 275
+ 367 |████████████████████████████████▌ 274
+ 368 |████████████████████████████████▍ 273
+ 369 |████████████████████████████████▎ 272
+ 370 |████████████████████████████████▏ 271
+ 371 |████████████████████████████████ 270
+ 372 |███████████████████████████████▉ 269
+ 373 |███████████████████████████████▊ 268
+ 374 |███████████████████████████████▋ 267
+ 375 |███████████████████████████████▌ 266
+ 376 |███████████████████████████████▍ 265
+ 377 |███████████████████████████████▎ 264
+ 378 |███████████████████████████████▏ 263
+ 379 |███████████████████████████████ 262
+ 380 |██████████████████████████████▉ 261
+ 381 |██████████████████████████████▉ 260
+ 382 |██████████████████████████████▊ 259
+ 383 |██████████████████████████████▋ 258
+ 384 |██████████████████████████████▌ 257
+ 385 |██████████████████████████████▍ 256
+ 386 |██████████████████████████████▎ 255
+ 387 |██████████████████████████████▏ 254
+ 388 |██████████████████████████████ 253
+ 389 |█████████████████████████████▉ 252
+ 390 |█████████████████████████████▊ 251
+ 391 |█████████████████████████████▋ 250
+ 392 |█████████████████████████████▌ 249
+ 393 |█████████████████████████████▍ 248
+ 394 |█████████████████████████████▎ 247
+ 395 |█████████████████████████████▏ 246
+ 396 |█████████████████████████████ 245
+ 397 |████████████████████████████▉ 244
+ 398 |████████████████████████████▊ 243
+ 399 |████████████████████████████▋ 242
+ 400 |████████████████████████████▌ 241
+ 401 |████████████████████████████▌ 240
+ 402 |████████████████████████████▍ 239
+ 403 |████████████████████████████▎ 238
+ 404 |████████████████████████████▏ 237
+ 405 |████████████████████████████ 236
+ 406 |███████████████████████████▉ 235
+ 407 |███████████████████████████▊ 234
+ 408 |███████████████████████████▋ 233
+ 409 |███████████████████████████▌ 232
+ 410 |███████████████████████████▍ 231
+ 411 |███████████████████████████▎ 230
+ 412 |███████████████████████████▏ 229
+ 413 |███████████████████████████ 228
+ 414 |██████████████████████████▉ 227
+ 415 |██████████████████████████▊ 226
+ 416 |██████████████████████████▋ 225
+ 417 |██████████████████████████▌ 224
+ 418 |██████████████████████████▍ 223
+ 419 |██████████████████████████▎ 222
+ 420 |██████████████████████████▏ 221
+ 421 |██████████████████████████▏ 220
+ 422 |██████████████████████████ 219
+ 423 |█████████████████████████▉ 218
+ 424 |█████████████████████████▊ 217
+ 425 |█████████████████████████▋ 216
+ 426 |█████████████████████████▌ 215
+ 427 |█████████████████████████▍ 214
+ 428 |█████████████████████████▎ 213
+ 429 |█████████████████████████▏ 212
+ 430 |█████████████████████████ 211
+ 431 |████████████████████████▉ 210
+ 432 |████████████████████████▊ 209
+ 433 |████████████████████████▋ 208
+ 434 |████████████████████████▌ 207
+ 435 |████████████████████████▍ 206
+ 436 |████████████████████████▎ 205
+ 437 |████████████████████████▏ 204
+ 438 |████████████████████████ 203
+ 439 |███████████████████████▉ 202
+ 440 |███████████████████████▊ 201
+ 441 |███████████████████████▊ 200
+ 442 |███████████████████████▋ 199
+ 443 |███████████████████████▌ 198
+ 444 |███████████████████████▍ 197
+ 445 |███████████████████████▎ 196
+ 446 |███████████████████████▏ 195
+ 447 |███████████████████████ 194
+ 448 |██████████████████████▉ 193
+ 449 |██████████████████████▊ 192
+ 450 |██████████████████████▋ 191
+ 451 |██████████████████████▌ 190
+ 452 |██████████████████████▍ 189
+ 453 |██████████████████████▎ 188
+ 454 |██████████████████████▏ 187
+ 455 |██████████████████████ 186
+ 456 |█████████████████████▉ 185
+ 457 |█████████████████████▊ 184
+ 458 |█████████████████████▋ 183
+ 459 |█████████████████████▌ 182
+ 460 |█████████████████████▍ 181
+ 461 |█████████████████████▍ 180
+ 462 |█████████████████████▎ 179
+ 463 |█████████████████████▏ 178
+ 464 |█████████████████████ 177
+ 465 |████████████████████▉ 176
+ 466 |████████████████████▊ 175
+ 467 |████████████████████▋ 174
+ 468 |████████████████████▌ 173
+ 469 |████████████████████▍ 172
+ 470 |████████████████████▎ 171
+ 471 |████████████████████▏ 170
+ 472 |████████████████████ 169
+ 473 |███████████████████▉ 168
+ 474 |███████████████████▊ 167
+ 475 |███████████████████▋ 166
+ 476 |███████████████████▌ 165
+ 477 |███████████████████▍ 164
+ 478 |███████████████████▎ 163
+ 479 |███████████████████▏ 162
+ 480 |███████████████████ 161
+ 481 |███████████████████ 160
+ 482 |██████████████████▉ 159
+ 483 |██████████████████▊ 158
+ 484 |██████████████████▋ 157
+ 485 |██████████████████▌ 156
+ 486 |██████████████████▍ 155
+ 487 |██████████████████▎ 154
+ 488 |██████████████████▏ 153
+ 489 |██████████████████ 152
+ 490 |█████████████████▉ 151
+ 491 |█████████████████▊ 150
+ 492 |█████████████████▋ 149
+ 493 |█████████████████▌ 148
+ 494 |█████████████████▍ 147
+ 495 |█████████████████▎ 146
+ 496 |█████████████████▏ 145
+ 497 |█████████████████ 144
+ 498 |████████████████▉ 143
+ 499 |████████████████▊ 142
+ 500 |████████████████▋ 141
+ 501 |████████████████▋ 140
+ 502 |████████████████▌ 139
+ 503 |████████████████▍ 138
+ 504 |████████████████▎ 137
+ 505 |████████████████▏ 136
+ 506 |████████████████ 135
+ 507 |███████████████▉ 134
+ 508 |███████████████▊ 133
+ 509 |███████████████▋ 132
+ 510 |███████████████▌ 131
+ 511 |███████████████▍ 130
+ 512 |███████████████▎ 129
+ 513 |███████████████▏ 128
+ 514 |███████████████ 127
+ 515 |██████████████▉ 126
+ 516 |██████████████▊ 125
+ 517 |██████████████▋ 124
+ 518 |██████████████▌ 123
+ 519 |██████████████▍ 122
+ 520 |██████████████▎ 121
+ 521 |██████████████▎ 120
+ 522 |██████████████▏ 119
+ 523 |██████████████ 118
+ 524 |█████████████▉ 117
+ 525 |█████████████▊ 116
+ 526 |█████████████▋ 115
+ 527 |█████████████▌ 114
+ 528 |█████████████▍ 113
+ 529 |█████████████▎ 112
+ 530 |█████████████▏ 111
+ 531 |█████████████ 110
+ 532 |████████████▉ 109
+ 533 |████████████▊ 108
+ 534 |████████████▋ 107
+ 535 |████████████▌ 106
+ 536 |████████████▍ 105
+ 537 |████████████▎ 104
+ 538 |████████████▏ 103
+ 539 |████████████ 102
+ 540 |███████████▉ 101
+ 541 |███████████▉ 100
+ 542 |███████████▊ 99
+ 543 |███████████▋ 98
+ 544 |███████████▌ 97
+ 545 |███████████▍ 96
+ 546 |███████████▎ 95
+ 547 |███████████▏ 94
+ 548 |███████████ 93
+ 549 |██████████▉ 92
+ 550 |██████████▊ 91
+ 551 |██████████▋ 90
+ 552 |██████████▌ 89
+ 553 |██████████▍ 88
+ 554 |██████████▎ 87
+ 555 |██████████▏ 86
+ 556 |██████████ 85
+ 557 |█████████▉ 84
+ 558 |█████████▊ 83
+ 559 |█████████▋ 82
+ 560 |█████████▌ 81
+ 561 |█████████▌ 80
+ 562 |█████████▍ 79
+ 563 |█████████▎ 78
+ 564 |█████████▏ 77
+ 565 |█████████ 76
+ 566 |████████▉ 75
+ 567 |████████▊ 74
+ 568 |████████▋ 73
+ 569 |████████▌ 72
+ 570 |████████▍ 71
+ 571 |████████▎ 70
+ 572 |████████▏ 69
+ 573 |████████ 68
+ 574 |███████▉ 67
+ 575 |███████▊ 66
+ 576 |███████▋ 65
+ 577 |███████▌ 64
+ 578 |███████▍ 63
+ 579 |███████▎ 62
+ 580 |███████▏ 61
+ 581 |███████▏ 60
+ 582 |███████ 59
+ 583 |██████▉ 58
+ 584 |██████▊ 57
+ 585 |██████▋ 56
+ 586 |██████▌ 55
+ 587 |██████▍ 54
+ 588 |██████▎ 53
+ 589 |██████▏ 52
+ 590 |██████ 51
+ 591 |█████▉ 50
+ 592 |█████▊ 49
+ 593 |█████▋ 48
+ 594 |█████▌ 47
+ 595 |█████▍ 46
+ 596 |█████▎ 45
+ 597 |█████▏ 44
+ 598 |█████ 43
+ 599 |████▉ 42
+ 600 |████▊ 41
+ 601 |████▊ 40
+ 602 |████▋ 39
+ 603 |████▌ 38
+ 604 |████▍ 37
+ 605 |████▎ 36
+ 606 |████▏ 35
+ 607 |████ 34
+ 608 |███▉ 33
+ 609 |███▊ 32
+ 610 |███▋ 31
+ 611 |███▌ 30
+ 612 |███▍ 29
+ 613 |███▎ 28
+ 614 |███▏ 27
+ 615 |███ 26
+ 616 |██▉ 25
+ 617 |██▊ 24
+ 618 |██▋ 23
+ 619 |██▌ 22
+ 620 |██▍ 21
+ 621 |██▍ 20
+ 622 |██▎ 19
+ 623 |██▏ 18
+ 624 |██ 17
+ 625 |█▉ 16
+ 626 |█▊ 15
+ 627 |█▋ 14
+ 628 |█▌ 13
+ 629 |█▍ 12
+ 630 |█▎ 11
+ 631 |█▏ 10
+ 632 |█ 9
+ 633 |▉ 8
+ 634 |▊ 7
+ 635 |▋ 6
+ 636 |▌ 5
+ 637 |▍ 4
+ 638 |▎ 3
+ 639 |▏ 2
+ >= 640 | 1
+
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.agghist.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.agghist.d
new file mode 100644
index 0000000..317aece
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.agghist.d
@@ -0,0 +1,46 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
+
+#pragma D option agghist
+#pragma D option quiet
+
+BEGIN
+{
+ @["demerit"] = sum(-10);
+ @["wtf"] = sum(10);
+ @["bot"] = sum(20);
+
+ @bagnoogle["SOAP/XML"] = sum(1);
+ @bagnoogle["XACML store"] = sum(5);
+ @bagnoogle["SAML token"] = sum(6);
+
+ @stalloogle["breakfast"] = sum(-5);
+ @stalloogle["non-diet pepsi"] = sum(-20);
+ @stalloogle["parrot"] = sum(-100);
+
+ printa(@);
+ printa(@bagnoogle);
+ printa(@stalloogle);
+
+ printf("\nzoomed:");
+
+ setopt("aggzoom");
+ printa(@);
+ printa(@bagnoogle);
+ printa(@stalloogle);
+
+ exit(0);
+}
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.agghist.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.agghist.d.out
new file mode 100644
index 0000000..d76e4da
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.agghist.d.out
@@ -0,0 +1,38 @@
+
+
+ key ------------- Distribution ------------- count
+ demerit @@@@@| -10
+ wtf |@@@@@ 10
+ bot |@@@@@@@@@@ 20
+
+
+ key ------------- Distribution ------------- count
+ SOAP/XML |@@@ 1
+ XACML store |@@@@@@@@@@@@@@@@@ 5
+ SAML token |@@@@@@@@@@@@@@@@@@@@ 6
+
+
+ key ------------- Distribution ------------- count
+ parrot @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| -100
+ non-diet pepsi @@@@@@| -20
+ breakfast @@| -5
+
+zoomed:
+
+ key ------------- Distribution ------------- count
+ demerit @@@@@@@@@@| -10
+ wtf |@@@@@@@@@@ 10
+ bot |@@@@@@@@@@@@@@@@@@@ 20
+
+
+ key ------------- Distribution ------------- count
+ SOAP/XML |@@@@@@@ 1
+ XACML store |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 5
+ SAML token |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 6
+
+
+ key ------------- Distribution ------------- count
+ parrot @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| -100
+ non-diet pepsi @@@@@@@@| -20
+ breakfast @@| -5
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpack.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpack.d
new file mode 100644
index 0000000..c9fdba7
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpack.d
@@ -0,0 +1,53 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
+
+#pragma D option aggpack
+#pragma D option encoding=ascii
+#pragma D option quiet
+
+BEGIN
+{
+ @x = quantize(1 << 32);
+ @y[1] = quantize(1);
+ @z["mumble"] = quantize(1);
+ @xx["foo", (char)1, (short)2, (long)3] = quantize(1);
+
+ @neg = lquantize(-10, -10, 20, 1, -1);
+ @neg = lquantize(-5, -10, 20, 1, 1);
+ @neg = lquantize(0, -10, 20, 1, 1);
+
+ i = 0;
+}
+
+tick-1ms
+{
+ @a[i] = quantize(0, i);
+ @a[i] = quantize(1, 100 - i);
+ i++;
+}
+
+tick-1ms
+/i > 100/
+{
+ exit(0);
+}
+
+END
+{
+ setopt("aggzoom", "true");
+ printa(@neg);
+ setopt("aggzoom", "false");
+ printa(@neg);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpack.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpack.d.out
new file mode 100644
index 0000000..5300ebd
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpack.d.out
@@ -0,0 +1,124 @@
+
+
+ min .--------------------------------. max | count
+ < -10 : V X X : >= 20 | 1
+
+
+ min .--------------------------------. max | count
+ < -10 : v x x : >= 20 | 1
+
+
+ min .---. max | count
+ 2147483648 : X : 8589934592 | 1
+
+ key min .---. max | count
+ 1 0 : X : 2 | 1
+
+ key min .---. max | count
+ mumble 0 : X : 2 | 1
+
+ key min .---. max | count
+ foo 1 2 3 0 : X : 2 | 1
+
+ key min .---. max | count
+ 100 0 :X : 2 | 100
+ 99 0 :X_ : 2 | 100
+ 98 0 :X_ : 2 | 100
+ 97 0 :X_ : 2 | 100
+ 96 0 :X_ : 2 | 100
+ 95 0 :X_ : 2 | 100
+ 94 0 :X_ : 2 | 100
+ 93 0 :X_ : 2 | 100
+ 92 0 :X_ : 2 | 100
+ 91 0 :X_ : 2 | 100
+ 90 0 :X_ : 2 | 100
+ 89 0 :X_ : 2 | 100
+ 88 0 :X_ : 2 | 100
+ 87 0 :X_ : 2 | 100
+ 86 0 :X_ : 2 | 100
+ 85 0 :X_ : 2 | 100
+ 84 0 :X_ : 2 | 100
+ 83 0 :X_ : 2 | 100
+ 82 0 :X_ : 2 | 100
+ 81 0 :X_ : 2 | 100
+ 80 0 :X_ : 2 | 100
+ 79 0 :X_ : 2 | 100
+ 78 0 :xx : 2 | 100
+ 77 0 :xx : 2 | 100
+ 76 0 :xx : 2 | 100
+ 75 0 :xx : 2 | 100
+ 74 0 :xx : 2 | 100
+ 73 0 :xx : 2 | 100
+ 72 0 :xx : 2 | 100
+ 71 0 :xx : 2 | 100
+ 70 0 :xx : 2 | 100
+ 69 0 :xx : 2 | 100
+ 68 0 :xx : 2 | 100
+ 67 0 :xx : 2 | 100
+ 66 0 :xx : 2 | 100
+ 65 0 :xx : 2 | 100
+ 64 0 :xx : 2 | 100
+ 63 0 :xx : 2 | 100
+ 62 0 :xx : 2 | 100
+ 61 0 :xx : 2 | 100
+ 60 0 :xx : 2 | 100
+ 59 0 :xx : 2 | 100
+ 58 0 :xx : 2 | 100
+ 57 0 :xx : 2 | 100
+ 56 0 :xx : 2 | 100
+ 55 0 :xx : 2 | 100
+ 54 0 :xx : 2 | 100
+ 53 0 :xx : 2 | 100
+ 52 0 :xx : 2 | 100
+ 51 0 :xx : 2 | 100
+ 50 0 :xx : 2 | 100
+ 49 0 :xx : 2 | 100
+ 48 0 :xx : 2 | 100
+ 47 0 :xx : 2 | 100
+ 46 0 :xx : 2 | 100
+ 45 0 :xx : 2 | 100
+ 44 0 :xx : 2 | 100
+ 43 0 :xx : 2 | 100
+ 42 0 :xx : 2 | 100
+ 41 0 :xx : 2 | 100
+ 40 0 :xx : 2 | 100
+ 39 0 :xx : 2 | 100
+ 38 0 :xx : 2 | 100
+ 37 0 :xx : 2 | 100
+ 36 0 :xx : 2 | 100
+ 35 0 :xx : 2 | 100
+ 34 0 :xx : 2 | 100
+ 33 0 :xx : 2 | 100
+ 32 0 :xx : 2 | 100
+ 31 0 :xx : 2 | 100
+ 30 0 :xx : 2 | 100
+ 29 0 :xx : 2 | 100
+ 28 0 :xx : 2 | 100
+ 27 0 :xx : 2 | 100
+ 26 0 :xx : 2 | 100
+ 25 0 :xx : 2 | 100
+ 24 0 :xx : 2 | 100
+ 23 0 :xx : 2 | 100
+ 22 0 :xx : 2 | 100
+ 21 0 :_X : 2 | 100
+ 20 0 :_X : 2 | 100
+ 19 0 :_X : 2 | 100
+ 18 0 :_X : 2 | 100
+ 17 0 :_X : 2 | 100
+ 16 0 :_X : 2 | 100
+ 15 0 :_X : 2 | 100
+ 14 0 :_X : 2 | 100
+ 13 0 :_X : 2 | 100
+ 12 0 :_X : 2 | 100
+ 11 0 :_X : 2 | 100
+ 10 0 :_X : 2 | 100
+ 9 0 :_X : 2 | 100
+ 8 0 :_X : 2 | 100
+ 7 0 :_X : 2 | 100
+ 6 0 :_X : 2 | 100
+ 5 0 :_X : 2 | 100
+ 4 0 :_X : 2 | 100
+ 3 0 :_X : 2 | 100
+ 2 0 :_X : 2 | 100
+ 1 0 :_X : 2 | 100
+ 0 0 : X : 2 | 100
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackbanner.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackbanner.ksh
new file mode 100644
index 0000000..f055a08
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackbanner.ksh
@@ -0,0 +1,75 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+let width=8
+
+function outputchar
+{
+ banner $3 | /bin/nawk -v line=$1 -v pos=$2 -v width=$width '{ \
+ for (i = 1; i <= length($0); i++) { \
+ if (substr($0, i, 1) == " ") \
+ continue; \
+ printf("\t@letter%d[%d] = lquantize(%d, 0, 40, 1);\n", \
+ line, NR, i + (pos * width));
+ } \
+ }'
+}
+
+function outputstr
+{
+ let pos=0;
+ let line=0
+
+ printf "#pragma D option aggpack\n#pragma D option aggsortkey\n"
+
+ printf "BEGIN\n{\n"
+ for c in `echo "$1" | /bin/nawk '{ \
+ for (i = 1; i <= length($0); i++) { \
+ c = substr($0, i, 1); \
+ printf("%s\n", c == " " ? "space" : \
+ c == "\n" ? "newline" : c); \
+ } \
+ }'`; do
+ if [[ "$c" == "space" ]]; then
+ let line=line+1
+ let pos=0
+ continue
+ fi
+
+ outputchar $line $pos $c
+ let pos=pos+1
+ done
+
+ let i=0
+
+ while [[ $i -le $line ]]; do
+ printf "\tprinta(@letter%d);\n" $i
+ let i=i+1
+ done
+ printf "\texit(0);\n}\n"
+}
+
+dtrace -qs /dev/stdin -x encoding=utf8 <<EOF
+`outputstr "why must i do this"`
+EOF
+
+dtrace -qs /dev/stdin -x encoding=ascii -x aggzoom <<EOF
+`outputstr "i am not well"`
+EOF
+
+dtrace -qs /dev/stdin -x encoding=utf8 -x aggzoom <<EOF
+`outputstr "send help"`
+EOF
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackbanner.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackbanner.ksh.out
new file mode 100644
index 0000000..a7eba38
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackbanner.ksh.out
@@ -0,0 +1,102 @@
+
+
+ key min .------------------------------------------. max | count
+ 2 < 0 : ▂ ▂ ▂ ▂ ▂ ▂ : >= 40 | 6
+ 3 < 0 : ▂ ▂ ▂ ▂ ▂ ▂ : >= 40 | 6
+ 4 < 0 : ▂ ▂ ▂▂▂▂▂▂ ▂ : >= 40 | 9
+ 5 < 0 : ▂ ▂▂ ▂ ▂ ▂ ▂ : >= 40 | 7
+ 6 < 0 : ▂▂ ▂▂ ▂ ▂ ▂ : >= 40 | 7
+ 7 < 0 : ▂ ▂ ▂ ▂ ▂ : >= 40 | 5
+
+
+ key min .------------------------------------------. max | count
+ 2 < 0 : ▂ ▂ ▂ ▂ ▂▂▂▂ ▂▂▂▂▂ : >= 40 | 13
+ 3 < 0 : ▂▂ ▂▂ ▂ ▂ ▂ ▂ : >= 40 | 8
+ 4 < 0 : ▂ ▂▂ ▂ ▂ ▂ ▂▂▂▂ ▂ : >= 40 | 11
+ 5 < 0 : ▂ ▂ ▂ ▂ ▂ ▂ : >= 40 | 6
+ 6 < 0 : ▂ ▂ ▂ ▂ ▂ ▂ ▂ : >= 40 | 7
+ 7 < 0 : ▂ ▂ ▂▂▂▂ ▂▂▂▂ ▂ : >= 40 | 11
+
+
+ key min .------------------------------------------. max | count
+ 2 < 0 : █ : >= 40 | 1
+ 3 < 0 : █ : >= 40 | 1
+ 4 < 0 : █ : >= 40 | 1
+ 5 < 0 : █ : >= 40 | 1
+ 6 < 0 : █ : >= 40 | 1
+ 7 < 0 : █ : >= 40 | 1
+
+
+ key min .------------------------------------------. max | count
+ 2 < 0 : ▂▂▂▂▂ ▂▂▂▂ : >= 40 | 9
+ 3 < 0 : ▃ ▃ ▃ ▃ : >= 40 | 4
+ 4 < 0 : ▃ ▃ ▃ ▃ : >= 40 | 4
+ 5 < 0 : ▃ ▃ ▃ ▃ : >= 40 | 4
+ 6 < 0 : ▃ ▃ ▃ ▃ : >= 40 | 4
+ 7 < 0 : ▂▂▂▂▂ ▂▂▂▂ : >= 40 | 9
+
+
+ key min .------------------------------------------. max | count
+ 2 < 0 : ▂▂▂▂▂ ▂ ▂ ▂ ▂▂▂▂ : >= 40 | 12
+ 3 < 0 : ▂ ▂ ▂ ▂ ▂ : >= 40 | 5
+ 4 < 0 : ▂ ▂▂▂▂▂▂ ▂ ▂▂▂▂ : >= 40 | 12
+ 5 < 0 : ▂ ▂ ▂ ▂ ▂ : >= 40 | 5
+ 6 < 0 : ▂ ▂ ▂ ▂ ▂ ▂ : >= 40 | 6
+ 7 < 0 : ▂ ▂ ▂ ▂ ▂▂▂▂ : >= 40 | 8
+
+
+
+ key min .------------------------------------------. max | count
+ 2 < 0 : X : >= 40 | 1
+ 3 < 0 : X : >= 40 | 1
+ 4 < 0 : X : >= 40 | 1
+ 5 < 0 : X : >= 40 | 1
+ 6 < 0 : X : >= 40 | 1
+ 7 < 0 : X : >= 40 | 1
+
+
+ key min .------------------------------------------. max | count
+ 2 < 0 : XX X X : >= 40 | 4
+ 3 < 0 : X X XX XX : >= 40 | 6
+ 4 < 0 : X X X XX X : >= 40 | 6
+ 5 < 0 : XXXXXX X X : >= 40 | 8
+ 6 < 0 : X X X X : >= 40 | 4
+ 7 < 0 : X X X X : >= 40 | 4
+
+
+ key min .------------------------------------------. max | count
+ 2 < 0 : X X XXXX XXXXX : >= 40 | 11
+ 3 < 0 : XX X X X X : >= 40 | 6
+ 4 < 0 : X X X X X X : >= 40 | 6
+ 5 < 0 : X X X X X X : >= 40 | 6
+ 6 < 0 : X XX X X X : >= 40 | 6
+ 7 < 0 : X X XXXX X : >= 40 | 7
+
+
+ key min .------------------------------------------. max | count
+ 2 < 0 : X X XXXXXX X X : >= 40 | 10
+ 3 < 0 : X X X X X : >= 40 | 5
+ 4 < 0 : X X XXXXX X X : >= 40 | 9
+ 5 < 0 : X XX X X X X : >= 40 | 7
+ 6 < 0 : XX XX X X X : >= 40 | 7
+ 7 < 0 : X X XXXXXX XXXXXX XXXXXX : >= 40 | 20
+
+
+
+ key min .------------------------------------------. max | count
+ 2 < 0 : ████ ██████ █ █ █████ : >= 40 | 17
+ 3 < 0 : █ █ ██ █ █ █ : >= 40 | 7
+ 4 < 0 : ████ █████ █ █ █ █ █ : >= 40 | 14
+ 5 < 0 : █ █ █ █ █ █ █ : >= 40 | 7
+ 6 < 0 : █ █ █ █ ██ █ █ : >= 40 | 8
+ 7 < 0 : ████ ██████ █ █ █████ : >= 40 | 17
+
+
+ key min .------------------------------------------. max | count
+ 2 < 0 : █ █ ██████ █ █████ : >= 40 | 14
+ 3 < 0 : █ █ █ █ █ █ : >= 40 | 6
+ 4 < 0 : ██████ █████ █ █ █ : >= 40 | 14
+ 5 < 0 : █ █ █ █ █████ : >= 40 | 9
+ 6 < 0 : █ █ █ █ █ : >= 40 | 5
+ 7 < 0 : █ █ ██████ ██████ █ : >= 40 | 15
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackzoom.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackzoom.d
new file mode 100644
index 0000000..2f297e2
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackzoom.d
@@ -0,0 +1,43 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
+
+#pragma D option encoding=ascii
+#pragma D option quiet
+
+tick-1ms
+/i++ < 30/
+{
+ @[1] = lquantize(i, 0, 40, 1, 1000);
+ @[2] = lquantize(i, 0, 40, 1, 1000);
+ @[3] = lquantize(i, 0, 40, 1, 1000);
+}
+
+tick-1ms
+/i == 40/
+{
+ @[1] = lquantize(0, 0, 40, 1, 1);
+ @[1] = lquantize(i, 0, 40, 1, 2000);
+ @[2] = lquantize(0, 0, 40, 1, 1);
+ @[2] = lquantize(i, 0, 40, 1, 2000);
+ @[3] = lquantize(0, 0, 40, 1, 1);
+ @[3] = lquantize(i, 0, 40, 1, 2000);
+
+ printa(@);
+ setopt("aggpack");
+ printa(@);
+ setopt("aggzoom");
+ printa(@);
+ exit(0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackzoom.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackzoom.d.out
new file mode 100644
index 0000000..a22a2a4
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggpackzoom.d.out
@@ -0,0 +1,149 @@
+
+ 1
+ value ------------- Distribution ------------- count
+ < 0 | 0
+ 0 | 1
+ 1 |@ 1000
+ 2 |@ 1000
+ 3 |@ 1000
+ 4 |@ 1000
+ 5 |@ 1000
+ 6 |@ 1000
+ 7 |@ 1000
+ 8 |@ 1000
+ 9 |@ 1000
+ 10 |@ 1000
+ 11 |@ 1000
+ 12 |@ 1000
+ 13 |@ 1000
+ 14 |@ 1000
+ 15 |@ 1000
+ 16 |@ 1000
+ 17 |@ 1000
+ 18 |@ 1000
+ 19 |@ 1000
+ 20 |@ 1000
+ 21 |@ 1000
+ 22 |@ 1000
+ 23 |@ 1000
+ 24 |@ 1000
+ 25 |@ 1000
+ 26 |@ 1000
+ 27 |@ 1000
+ 28 |@ 1000
+ 29 |@ 1000
+ 30 |@ 1000
+ 31 | 0
+ 32 | 0
+ 33 | 0
+ 34 | 0
+ 35 | 0
+ 36 | 0
+ 37 | 0
+ 38 | 0
+ 39 | 0
+ >= 40 |@@ 2000
+
+ 2
+ value ------------- Distribution ------------- count
+ < 0 | 0
+ 0 | 1
+ 1 |@ 1000
+ 2 |@ 1000
+ 3 |@ 1000
+ 4 |@ 1000
+ 5 |@ 1000
+ 6 |@ 1000
+ 7 |@ 1000
+ 8 |@ 1000
+ 9 |@ 1000
+ 10 |@ 1000
+ 11 |@ 1000
+ 12 |@ 1000
+ 13 |@ 1000
+ 14 |@ 1000
+ 15 |@ 1000
+ 16 |@ 1000
+ 17 |@ 1000
+ 18 |@ 1000
+ 19 |@ 1000
+ 20 |@ 1000
+ 21 |@ 1000
+ 22 |@ 1000
+ 23 |@ 1000
+ 24 |@ 1000
+ 25 |@ 1000
+ 26 |@ 1000
+ 27 |@ 1000
+ 28 |@ 1000
+ 29 |@ 1000
+ 30 |@ 1000
+ 31 | 0
+ 32 | 0
+ 33 | 0
+ 34 | 0
+ 35 | 0
+ 36 | 0
+ 37 | 0
+ 38 | 0
+ 39 | 0
+ >= 40 |@@ 2000
+
+ 3
+ value ------------- Distribution ------------- count
+ < 0 | 0
+ 0 | 1
+ 1 |@ 1000
+ 2 |@ 1000
+ 3 |@ 1000
+ 4 |@ 1000
+ 5 |@ 1000
+ 6 |@ 1000
+ 7 |@ 1000
+ 8 |@ 1000
+ 9 |@ 1000
+ 10 |@ 1000
+ 11 |@ 1000
+ 12 |@ 1000
+ 13 |@ 1000
+ 14 |@ 1000
+ 15 |@ 1000
+ 16 |@ 1000
+ 17 |@ 1000
+ 18 |@ 1000
+ 19 |@ 1000
+ 20 |@ 1000
+ 21 |@ 1000
+ 22 |@ 1000
+ 23 |@ 1000
+ 24 |@ 1000
+ 25 |@ 1000
+ 26 |@ 1000
+ 27 |@ 1000
+ 28 |@ 1000
+ 29 |@ 1000
+ 30 |@ 1000
+ 31 | 0
+ 32 | 0
+ 33 | 0
+ 34 | 0
+ 35 | 0
+ 36 | 0
+ 37 | 0
+ 38 | 0
+ 39 | 0
+ >= 40 |@@ 2000
+
+
+
+ key min .------------------------------------------. max | count
+ 1 < 0 : _______________________________ _: >= 40 | 32001
+ 2 < 0 : _______________________________ _: >= 40 | 32001
+ 3 < 0 : _______________________________ _: >= 40 | 32001
+
+
+ key min .------------------------------------------. max | count
+ 1 < 0 : _xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx X: >= 40 | 32001
+ 2 < 0 : _xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx X: >= 40 | 32001
+ 3 < 0 : _xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx X: >= 40 | 32001
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggzoom.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggzoom.d
new file mode 100644
index 0000000..f237d26
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggzoom.d
@@ -0,0 +1,35 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
+
+#pragma D option encoding=ascii
+#pragma D option quiet
+
+tick-1ms
+/i++ < 90/
+{
+ @ = lquantize(i, 0, 100, 1, 1000);
+}
+
+tick-1ms
+/i == 100/
+{
+ @ = lquantize(i++, 0, 100, 1, 2000);
+ @ = lquantize(i++, 0, 100, 1, 3000);
+
+ printa(@);
+ setopt("aggzoom");
+ printa(@);
+ exit(0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggzoom.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggzoom.d.out
new file mode 100644
index 0000000..acddf7f
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.aggzoom.d.out
@@ -0,0 +1,211 @@
+
+
+ value ------------- Distribution ------------- count
+ 0 | 0
+ 1 | 1000
+ 2 | 1000
+ 3 | 1000
+ 4 | 1000
+ 5 | 1000
+ 6 | 1000
+ 7 | 1000
+ 8 | 1000
+ 9 | 1000
+ 10 | 1000
+ 11 | 1000
+ 12 | 1000
+ 13 | 1000
+ 14 | 1000
+ 15 | 1000
+ 16 | 1000
+ 17 | 1000
+ 18 | 1000
+ 19 | 1000
+ 20 | 1000
+ 21 | 1000
+ 22 | 1000
+ 23 | 1000
+ 24 | 1000
+ 25 | 1000
+ 26 | 1000
+ 27 | 1000
+ 28 | 1000
+ 29 | 1000
+ 30 | 1000
+ 31 | 1000
+ 32 | 1000
+ 33 | 1000
+ 34 | 1000
+ 35 | 1000
+ 36 | 1000
+ 37 | 1000
+ 38 | 1000
+ 39 | 1000
+ 40 | 1000
+ 41 | 1000
+ 42 | 1000
+ 43 | 1000
+ 44 | 1000
+ 45 | 1000
+ 46 | 1000
+ 47 | 1000
+ 48 | 1000
+ 49 | 1000
+ 50 | 1000
+ 51 | 1000
+ 52 | 1000
+ 53 | 1000
+ 54 | 1000
+ 55 | 1000
+ 56 | 1000
+ 57 | 1000
+ 58 | 1000
+ 59 | 1000
+ 60 | 1000
+ 61 | 1000
+ 62 | 1000
+ 63 | 1000
+ 64 | 1000
+ 65 | 1000
+ 66 | 1000
+ 67 | 1000
+ 68 | 1000
+ 69 | 1000
+ 70 | 1000
+ 71 | 1000
+ 72 | 1000
+ 73 | 1000
+ 74 | 1000
+ 75 | 1000
+ 76 | 1000
+ 77 | 1000
+ 78 | 1000
+ 79 | 1000
+ 80 | 1000
+ 81 | 1000
+ 82 | 1000
+ 83 | 1000
+ 84 | 1000
+ 85 | 1000
+ 86 | 1000
+ 87 | 1000
+ 88 | 1000
+ 89 | 1000
+ 90 | 1000
+ 91 | 0
+ 92 | 0
+ 93 | 0
+ 94 | 0
+ 95 | 0
+ 96 | 0
+ 97 | 0
+ 98 | 0
+ 99 | 0
+ >= 100 |@@ 5000
+
+
+
+ value ------------- Distribution ------------- count
+ 0 | 0
+ 1 |@@@@@@@@ 1000
+ 2 |@@@@@@@@ 1000
+ 3 |@@@@@@@@ 1000
+ 4 |@@@@@@@@ 1000
+ 5 |@@@@@@@@ 1000
+ 6 |@@@@@@@@ 1000
+ 7 |@@@@@@@@ 1000
+ 8 |@@@@@@@@ 1000
+ 9 |@@@@@@@@ 1000
+ 10 |@@@@@@@@ 1000
+ 11 |@@@@@@@@ 1000
+ 12 |@@@@@@@@ 1000
+ 13 |@@@@@@@@ 1000
+ 14 |@@@@@@@@ 1000
+ 15 |@@@@@@@@ 1000
+ 16 |@@@@@@@@ 1000
+ 17 |@@@@@@@@ 1000
+ 18 |@@@@@@@@ 1000
+ 19 |@@@@@@@@ 1000
+ 20 |@@@@@@@@ 1000
+ 21 |@@@@@@@@ 1000
+ 22 |@@@@@@@@ 1000
+ 23 |@@@@@@@@ 1000
+ 24 |@@@@@@@@ 1000
+ 25 |@@@@@@@@ 1000
+ 26 |@@@@@@@@ 1000
+ 27 |@@@@@@@@ 1000
+ 28 |@@@@@@@@ 1000
+ 29 |@@@@@@@@ 1000
+ 30 |@@@@@@@@ 1000
+ 31 |@@@@@@@@ 1000
+ 32 |@@@@@@@@ 1000
+ 33 |@@@@@@@@ 1000
+ 34 |@@@@@@@@ 1000
+ 35 |@@@@@@@@ 1000
+ 36 |@@@@@@@@ 1000
+ 37 |@@@@@@@@ 1000
+ 38 |@@@@@@@@ 1000
+ 39 |@@@@@@@@ 1000
+ 40 |@@@@@@@@ 1000
+ 41 |@@@@@@@@ 1000
+ 42 |@@@@@@@@ 1000
+ 43 |@@@@@@@@ 1000
+ 44 |@@@@@@@@ 1000
+ 45 |@@@@@@@@ 1000
+ 46 |@@@@@@@@ 1000
+ 47 |@@@@@@@@ 1000
+ 48 |@@@@@@@@ 1000
+ 49 |@@@@@@@@ 1000
+ 50 |@@@@@@@@ 1000
+ 51 |@@@@@@@@ 1000
+ 52 |@@@@@@@@ 1000
+ 53 |@@@@@@@@ 1000
+ 54 |@@@@@@@@ 1000
+ 55 |@@@@@@@@ 1000
+ 56 |@@@@@@@@ 1000
+ 57 |@@@@@@@@ 1000
+ 58 |@@@@@@@@ 1000
+ 59 |@@@@@@@@ 1000
+ 60 |@@@@@@@@ 1000
+ 61 |@@@@@@@@ 1000
+ 62 |@@@@@@@@ 1000
+ 63 |@@@@@@@@ 1000
+ 64 |@@@@@@@@ 1000
+ 65 |@@@@@@@@ 1000
+ 66 |@@@@@@@@ 1000
+ 67 |@@@@@@@@ 1000
+ 68 |@@@@@@@@ 1000
+ 69 |@@@@@@@@ 1000
+ 70 |@@@@@@@@ 1000
+ 71 |@@@@@@@@ 1000
+ 72 |@@@@@@@@ 1000
+ 73 |@@@@@@@@ 1000
+ 74 |@@@@@@@@ 1000
+ 75 |@@@@@@@@ 1000
+ 76 |@@@@@@@@ 1000
+ 77 |@@@@@@@@ 1000
+ 78 |@@@@@@@@ 1000
+ 79 |@@@@@@@@ 1000
+ 80 |@@@@@@@@ 1000
+ 81 |@@@@@@@@ 1000
+ 82 |@@@@@@@@ 1000
+ 83 |@@@@@@@@ 1000
+ 84 |@@@@@@@@ 1000
+ 85 |@@@@@@@@ 1000
+ 86 |@@@@@@@@ 1000
+ 87 |@@@@@@@@ 1000
+ 88 |@@@@@@@@ 1000
+ 89 |@@@@@@@@ 1000
+ 90 |@@@@@@@@ 1000
+ 91 | 0
+ 92 | 0
+ 93 | 0
+ 94 | 0
+ 95 | 0
+ 96 | 0
+ 97 | 0
+ 98 | 0
+ 99 | 0
+ >= 100 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 5000
+
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d
index d508596..9b02e98 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d
@@ -22,6 +22,7 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -97,6 +98,9 @@ INTFUNC(ntohll(0x1234567890abcdefL))
STRFUNC(inet_ntoa((ipaddr_t *)alloca(sizeof (ipaddr_t))))
STRFUNC(inet_ntoa6((in6_addr_t *)alloca(sizeof (in6_addr_t))))
STRFUNC(inet_ntop(AF_INET, (void *)alloca(sizeof (ipaddr_t))))
+INTFUNC(getf(0))
+INTFUNC(strtoll("0x12EE5D5", 16))
+STRFUNC(json("{\"systemtap\": false}", "systemtap"))
BEGIN
/subr == DIF_SUBR_MAX + 1/
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d
new file mode 100644
index 0000000..4600811
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d
@@ -0,0 +1,179 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * General functional tests of JSON parser for json().
+ */
+
+#pragma D option quiet
+#pragma D option strsize=1k
+
+#define TST(name) \
+ printf("\ntst |%s|\n", name)
+#define IN2(vala, valb) \
+ in = strjoin(vala, valb); \
+ printf("in |%s|\n", in)
+#define IN(val) \
+ in = val; \
+ printf("in |%s|\n", in)
+#define SEL(ss) \
+ out = json(in, ss); \
+ printf("sel |%s|\nout |%s|\n", ss, \
+ out != NULL ? out : "<NULL>")
+
+BEGIN
+{
+ TST("empty array");
+ IN("[]");
+ SEL("0");
+
+ TST("one-element array: integer");
+ IN("[1]");
+ SEL("0");
+ SEL("1");
+ SEL("100");
+ SEL("-1");
+
+ TST("one-element array: hex integer (not in spec, not supported)");
+ IN("[0x1000]");
+ SEL("0");
+
+ TST("one-element array: float");
+ IN("[1.5001]");
+ SEL("0");
+
+ TST("one-element array: float + exponent");
+ IN("[16.3e10]");
+ SEL("0");
+
+ TST("one-element array: integer + whitespace");
+ IN("[ \t 5\t]");
+ SEL("0");
+
+ TST("one-element array: integer + exponent + whitespace");
+ IN("[ \t \t 16E10 \t ]");
+ SEL("0");
+
+ TST("one-element array: string");
+ IN("[\"alpha\"]");
+ SEL("0");
+
+ TST("alternative first-element indexing");
+ IN("[1,5,10,15,20]");
+ SEL("[0]");
+ SEL("[3]");
+ SEL("[4]");
+ SEL("[5]");
+
+ TST("one-element array: object");
+ IN("[ { \"first\": true, \"second\": false }]");
+ SEL("0.first");
+ SEL("0.second");
+ SEL("0.third");
+
+ TST("many-element array: integers");
+ IN("[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377]");
+ SEL("10"); /* F(10) = 55 */
+ SEL("14"); /* F(14) = 377 */
+ SEL("19");
+
+ TST("many-element array: multiple types");
+ IN2("[\"string\",32,true,{\"a\":9,\"b\":false},100.3e10,false,200.5,",
+ "{\"key\":\"val\"},null]");
+ SEL("0");
+ SEL("0.notobject");
+ SEL("1");
+ SEL("2");
+ SEL("3");
+ SEL("3.a");
+ SEL("3.b");
+ SEL("3.c");
+ SEL("4");
+ SEL("5");
+ SEL("6");
+ SEL("7");
+ SEL("7.key");
+ SEL("7.key.notobject");
+ SEL("7.nonexist");
+ SEL("8");
+ SEL("9");
+
+ TST("many-element array: multiple types + whitespace");
+ IN2("\n[\t\"string\" ,\t32 , true\t,\t {\"a\": 9,\t\"b\": false},\t\t",
+ "100.3e10, false, 200.5,{\"key\" \t:\n \"val\"},\t\t null ]\t\t");
+ SEL("0");
+ SEL("0.notobject");
+ SEL("1");
+ SEL("2");
+ SEL("3");
+ SEL("3.a");
+ SEL("3.b");
+ SEL("3.c");
+ SEL("4");
+ SEL("5");
+ SEL("6");
+ SEL("7");
+ SEL("7.key");
+ SEL("7.key.notobject");
+ SEL("7.nonexist");
+ SEL("8");
+ SEL("9");
+
+ TST("two-element array: various string escape codes");
+ IN2("[\"abcd \\\" \\\\ \\/ \\b \\f \\n \\r \\t \\u0000 \\uf00F \", ",
+ "\"final\"]");
+ SEL("0");
+ SEL("1");
+
+ TST("three-element array: broken escape code");
+ IN("[\"fine here\", \"dodgey \\u00AZ\", \"wont get here\"]");
+ SEL("0");
+ SEL("1");
+ SEL("2");
+
+ TST("nested objects");
+ IN2("{ \"top\": { \"mid\" : { \"legs\": \"feet\" }, \"number\": 9, ",
+ "\"array\":[0,1,{\"a\":true,\"bb\":[1,2,false,{\"x\":\"yz\"}]}]}}");
+ SEL("top");
+ SEL("fargo");
+ SEL("top.mid");
+ SEL("top.centre");
+ SEL("top.mid.legs");
+ SEL("top.mid.number");
+ SEL("top.mid.array");
+ SEL("top.number");
+ SEL("top.array");
+ SEL("top.array[0]");
+ SEL("top.array[1]");
+ SEL("top.array[2]");
+ SEL("top.array[2].a");
+ SEL("top.array[2].b");
+ SEL("top.array[2].bb");
+ SEL("top.array[2].bb[0]");
+ SEL("top.array[2].bb[1]");
+ SEL("top.array[2].bb[2]");
+ SEL("top.array[2].bb[3]");
+ SEL("top.array[2].bb[3].x");
+ SEL("top.array[2].bb[3].x.nofurther");
+ SEL("top.array[2].bb[4]");
+ SEL("top.array[3]");
+
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d.out
new file mode 100644
index 0000000..a857ab9
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.general.d.out
@@ -0,0 +1,218 @@
+
+tst |empty array|
+in |[]|
+sel |0|
+out |<NULL>|
+
+tst |one-element array: integer|
+in |[1]|
+sel |0|
+out |1|
+sel |1|
+out |<NULL>|
+sel |100|
+out |<NULL>|
+sel |-1|
+out |<NULL>|
+
+tst |one-element array: hex integer (not in spec, not supported)|
+in |[0x1000]|
+sel |0|
+out |<NULL>|
+
+tst |one-element array: float|
+in |[1.5001]|
+sel |0|
+out |1.5001|
+
+tst |one-element array: float + exponent|
+in |[16.3e10]|
+sel |0|
+out |16.3e10|
+
+tst |one-element array: integer + whitespace|
+in |[ 5 ]|
+sel |0|
+out |5|
+
+tst |one-element array: integer + exponent + whitespace|
+in |[ 16E10 ]|
+sel |0|
+out |16E10|
+
+tst |one-element array: string|
+in |["alpha"]|
+sel |0|
+out |alpha|
+
+tst |alternative first-element indexing|
+in |[1,5,10,15,20]|
+sel |[0]|
+out |1|
+sel |[3]|
+out |15|
+sel |[4]|
+out |20|
+sel |[5]|
+out |<NULL>|
+
+tst |one-element array: object|
+in |[ { "first": true, "second": false }]|
+sel |0.first|
+out |true|
+sel |0.second|
+out |false|
+sel |0.third|
+out |<NULL>|
+
+tst |many-element array: integers|
+in |[0,1,1,2,3,5,8,13,21,34,55,89,144,233,377]|
+sel |10|
+out |55|
+sel |14|
+out |377|
+sel |19|
+out |<NULL>|
+
+tst |many-element array: multiple types|
+in |["string",32,true,{"a":9,"b":false},100.3e10,false,200.5,{"key":"val"},null]|
+sel |0|
+out |string|
+sel |0.notobject|
+out |<NULL>|
+sel |1|
+out |32|
+sel |2|
+out |true|
+sel |3|
+out |{"a":9,"b":false}|
+sel |3.a|
+out |9|
+sel |3.b|
+out |false|
+sel |3.c|
+out |<NULL>|
+sel |4|
+out |100.3e10|
+sel |5|
+out |false|
+sel |6|
+out |200.5|
+sel |7|
+out |{"key":"val"}|
+sel |7.key|
+out |val|
+sel |7.key.notobject|
+out |<NULL>|
+sel |7.nonexist|
+out |<NULL>|
+sel |8|
+out |null|
+sel |9|
+out |<NULL>|
+
+tst |many-element array: multiple types + whitespace|
+in |
+[ "string" , 32 , true , {"a": 9, "b": false}, 100.3e10, false, 200.5,{"key" :
+ "val"}, null ] |
+sel |0|
+out |string|
+sel |0.notobject|
+out |<NULL>|
+sel |1|
+out |32|
+sel |2|
+out |true|
+sel |3|
+out |{"a": 9, "b": false}|
+sel |3.a|
+out |9|
+sel |3.b|
+out |false|
+sel |3.c|
+out |<NULL>|
+sel |4|
+out |100.3e10|
+sel |5|
+out |false|
+sel |6|
+out |200.5|
+sel |7|
+out |{"key" :
+ "val"}|
+sel |7.key|
+out |val|
+sel |7.key.notobject|
+out |<NULL>|
+sel |7.nonexist|
+out |<NULL>|
+sel |8|
+out |null|
+sel |9|
+out |<NULL>|
+
+tst |two-element array: various string escape codes|
+in |["abcd \" \\ \/ \b \f \n \r \t \u0000 \uf00F ", "final"]|
+sel |0|
+out |abcd \" \\ \/ \b \f \n \r \t \u0000 \uf00F |
+sel |1|
+out |final|
+
+tst |three-element array: broken escape code|
+in |["fine here", "dodgey \u00AZ", "wont get here"]|
+sel |0|
+out |fine here|
+sel |1|
+out |<NULL>|
+sel |2|
+out |<NULL>|
+
+tst |nested objects|
+in |{ "top": { "mid" : { "legs": "feet" }, "number": 9, "array":[0,1,{"a":true,"bb":[1,2,false,{"x":"yz"}]}]}}|
+sel |top|
+out |{ "mid" : { "legs": "feet" }, "number": 9, "array":[0,1,{"a":true,"bb":[1,2,false,{"x":"yz"}]}]}|
+sel |fargo|
+out |<NULL>|
+sel |top.mid|
+out |{ "legs": "feet" }|
+sel |top.centre|
+out |<NULL>|
+sel |top.mid.legs|
+out |feet|
+sel |top.mid.number|
+out |<NULL>|
+sel |top.mid.array|
+out |<NULL>|
+sel |top.number|
+out |9|
+sel |top.array|
+out |[0,1,{"a":true,"bb":[1,2,false,{"x":"yz"}]}]|
+sel |top.array[0]|
+out |0|
+sel |top.array[1]|
+out |1|
+sel |top.array[2]|
+out |{"a":true,"bb":[1,2,false,{"x":"yz"}]}|
+sel |top.array[2].a|
+out |true|
+sel |top.array[2].b|
+out |<NULL>|
+sel |top.array[2].bb|
+out |[1,2,false,{"x":"yz"}]|
+sel |top.array[2].bb[0]|
+out |1|
+sel |top.array[2].bb[1]|
+out |2|
+sel |top.array[2].bb[2]|
+out |false|
+sel |top.array[2].bb[3]|
+out |{"x":"yz"}|
+sel |top.array[2].bb[3].x|
+out |yz|
+sel |top.array[2].bb[3].x.nofurther|
+out |<NULL>|
+sel |top.array[2].bb[4]|
+out |<NULL>|
+sel |top.array[3]|
+out |<NULL>|
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d
new file mode 100644
index 0000000..6aa50b9
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d
@@ -0,0 +1,51 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * ASSERTION:
+ * json() run time must be bounded above by strsize. This test makes strsize
+ * small and deliberately overflows it to prove we bail and return NULL in
+ * the event that we run off the end of the string.
+ *
+ */
+
+#pragma D option quiet
+#pragma D option strsize=18
+
+BEGIN
+{
+ in = "{\"a\": 1024}"; /* length == 19 */
+ out = json(in, "a");
+ printf("|%s|\n%s\n\n", in, out != NULL ? out : "<NULL>");
+
+ in = "{\"a\": 1024}"; /* length == 11 */
+ out = json(in, "a");
+ printf("|%s|\n%s\n\n", in, out != NULL ? out : "<NULL>");
+
+ in = "{\"a\":false,\"b\":true}"; /* length == 20 */
+ out = json(in, "b");
+ printf("|%s|\n%s\n\n", in, out != NULL ? out : "<NULL>");
+
+ in = "{\"a\":false,\"b\":20}"; /* length == 18 */
+ out = json(in, "b");
+ printf("|%s|\n%s\n\n", in, out != NULL ? out : "<NULL>");
+
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d.out
new file mode 100644
index 0000000..7f1d79b
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.strsize.d.out
@@ -0,0 +1,13 @@
+|{"a": 1024|
+<NULL>
+
+|{"a": 1024}|
+1024
+
+|{"a":false,"b":tru|
+<NULL>
+
+|{"a":false,"b":20}|
+20
+
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.c b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.c
new file mode 100644
index 0000000..307106d
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.c
@@ -0,0 +1,61 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012 (c), Joyent, Inc. All rights reserved.
+ */
+
+#include <sys/sdt.h>
+#include "usdt.h"
+
+#define FMT "{" \
+ " \"sizes\": [ \"first\", 2, %f ]," \
+ " \"index\": %d," \
+ " \"facts\": {" \
+ " \"odd\": \"%s\"," \
+ " \"even\": \"%s\"" \
+ " }," \
+ " \"action\": \"%s\"" \
+ "}\n"
+
+int
+waiting(volatile int *a)
+{
+ return (*a);
+}
+
+int
+main(int argc, char **argv)
+{
+ volatile int a = 0;
+ int idx;
+ double size = 250.5;
+
+ while (waiting(&a) == 0)
+ continue;
+
+ for (idx = 0; idx < 10; idx++) {
+ char *odd, *even, *json, *action;
+
+ size *= 1.78;
+ odd = idx % 2 == 1 ? "true" : "false";
+ even = idx % 2 == 0 ? "true" : "false";
+ action = idx == 7 ? "ignore" : "print";
+
+ asprintf(&json, FMT, size, idx, odd, even, action);
+ BUNYAN_FAKE_LOG_DEBUG(json);
+ free(json);
+ }
+
+ BUNYAN_FAKE_LOG_DEBUG("{\"finished\": true}");
+
+ return (0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d
new file mode 100644
index 0000000..f0fbdd5
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d
@@ -0,0 +1,65 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ */
+
+#pragma D option strsize=4k
+#pragma D option quiet
+#pragma D option destructive
+
+/*
+ * This test reads a JSON string from a USDT probe, roughly simulating the
+ * primary motivating use case for the json() subroutine: filtering
+ * JSON-formatted log messages from a logging subsystem like node-bunyan.
+ */
+
+pid$1:a.out:waiting:entry
+{
+ this->value = (int *)alloca(sizeof (int));
+ *this->value = 1;
+ copyout(this->value, arg0, sizeof (int));
+}
+
+bunyan*$1:::log-*
+{
+ this->j = copyinstr(arg0);
+}
+
+bunyan*$1:::log-*
+/json(this->j, "finished") == NULL && json(this->j, "action") != "ignore"/
+{
+ this->index = strtoll(json(this->j, "index"));
+ this->size = json(this->j, "sizes[2]");
+ this->odd = json(this->j, "facts.odd");
+ this->even = json(this->j, "facts.even");
+ printf("[%d] sz %s odd %s even %s\n", this->index, this->size,
+ this->odd, this->even);
+}
+
+bunyan*$1:::log-*
+/json(this->j, "finished") != NULL/
+{
+ printf("FINISHED!\n");
+ exit(0);
+}
+
+tick-10s
+{
+ printf("ERROR: Timed out before finish message!\n");
+ exit(1);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d.out
new file mode 100644
index 0000000..c7f58bb
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/tst.usdt.d.out
@@ -0,0 +1,11 @@
+[0] sz 445.890000 odd false even true
+[1] sz 793.684200 odd true even false
+[2] sz 1412.757876 odd false even true
+[3] sz 2514.709019 odd true even false
+[4] sz 4476.182054 odd false even true
+[5] sz 7967.604057 odd true even false
+[6] sz 14182.335221 odd false even true
+[8] sz 44935.310914 odd false even true
+[9] sz 79984.853427 odd true even false
+FINISHED!
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/usdt.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/usdt.d
new file mode 100644
index 0000000..1a4fc87
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/json/usdt.d
@@ -0,0 +1,27 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2012, Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * Sets up a fake node-bunyan-like USDT provider for use from C.
+ */
+
+provider bunyan_fake {
+ probe log__trace(char *msg);
+ probe log__debug(char *msg);
+ probe log__info(char *msg);
+ probe log__warn(char *msg);
+ probe log__error(char *msg);
+ probe log__fatal(char *msg);
+};
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.fds.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.fds.ksh
new file mode 100644
index 0000000..a5aa271
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.fds.ksh
@@ -0,0 +1,91 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012, Joyent, Inc. All rights reserved.
+#
+
+tmpin=/tmp/tst.fds.$$.d
+tmpout1=/tmp/tst.fds.$$.out1
+tmpout2=/tmp/tst.fds.$$.out2
+
+cat > $tmpin <<EOF
+#define DUMPFIELD(fd, fmt, field) \
+ errmsg = "could not dump field"; \
+ printf("%d: field =fmt\n", fd, fds[fd].field);
+
+/*
+ * Note that we are explicitly not looking at fi_mount -- it (by design) does
+ * not work if not running with kernel permissions.
+ */
+#define DUMP(fd) \
+ DUMPFIELD(fd, %s, fi_name); \
+ DUMPFIELD(fd, %s, fi_dirname); \
+ DUMPFIELD(fd, %s, fi_pathname); \
+ DUMPFIELD(fd, %d, fi_offset); \
+ DUMPFIELD(fd, %s, fi_fs); \
+ DUMPFIELD(fd, %o, fi_oflags);
+
+BEGIN
+{
+ DUMP(0);
+ DUMP(1);
+ DUMP(2);
+ DUMP(3);
+ DUMP(4);
+ exit(0);
+}
+
+ERROR
+{
+ printf("error: %s\n", errmsg);
+ exit(1);
+}
+EOF
+
+#
+# First, with all privs
+#
+/usr/sbin/dtrace -q -Cs /dev/stdin < $tmpin > $tmpout2
+mv $tmpout2 $tmpout1
+
+#
+# And now with only dtrace_proc and dtrace_user -- the output should be
+# identical.
+#
+ppriv -s A=basic,dtrace_proc,dtrace_user $$
+
+/usr/sbin/dtrace -q -Cs /dev/stdin < $tmpin > $tmpout2
+
+echo ">>> $tmpout1"
+cat $tmpout1
+
+echo ">>> $tmpout2"
+cat $tmpout2
+
+rval=0
+
+if ! cmp $tmpout1 $tmpout2 ; then
+ rval=1
+fi
+
+rm $tmpout1 $tmpout2 $tmpin
+exit $rval
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.func_access.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.func_access.ksh
index ae4934c..da9bb4c 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.func_access.ksh
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.func_access.ksh
@@ -22,8 +22,8 @@
#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
+# Copyright (c) 2012, Joyent, Inc. All rights reserved.
#
-#ident "%Z%%M% %I% %E% SMI"
ppriv -s A=basic,dtrace_proc,dtrace_user $$
@@ -31,7 +31,7 @@ ppriv -s A=basic,dtrace_proc,dtrace_user $$
BEGIN {
errorcount = 0;
- expected_errorcount = 23;
+ expected_errorcount = 27;
}
BEGIN { trace(mutex_owned(&`pidlock)); }
@@ -55,6 +55,8 @@ BEGIN { trace(strtok(`initname, "/")); }
BEGIN { trace(strtok(NULL, "/")); }
BEGIN { trace(strtok("foo/bar", `initname)); }
BEGIN { trace(strtok(NULL, `initname)); }
+BEGIN { trace(strtoll(`initname)); }
+BEGIN { trace(strtoll(`initname, 10)); }
BEGIN { trace(substr(`initname, 2, 3)); }
BEGIN { trace(ddi_pathname(`top_devinfo, 1)); }
@@ -63,6 +65,9 @@ BEGIN { trace(strjoin("foo", `initname)); }
BEGIN { trace(dirname(`initname)); }
BEGIN { trace(cleanpath(`initname)); }
+BEGIN { j = "{\"/sbin/init\":\"uh oh\"}"; trace(json(j, `initname)); }
+BEGIN { trace(json(`initname, "x")); }
+
ERROR {
errorcount++;
}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.getf.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.getf.ksh
new file mode 100644
index 0000000..7dbb83f
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.getf.ksh
@@ -0,0 +1,98 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012, Joyent, Inc. All rights reserved.
+#
+
+ppriv -s A=basic,dtrace_proc,dtrace_user $$
+
+/usr/sbin/dtrace -q -Cs /dev/stdin <<EOF
+
+#define CANREAD(field) \
+ BEGIN { this->fp = getf(0); errmsg = "can't read field"; \
+ printf("field: "); trace(this->fp->field); printf("\n"); }
+
+#define CANTREAD(field) \
+ BEGIN { errmsg = ""; this->fp = getf(0); trace(this->fp->field); \
+ printf("\nable to successfully read field!"); exit(1); }
+
+CANREAD(f_flag)
+CANREAD(f_flag2)
+CANREAD(f_vnode)
+CANREAD(f_offset)
+CANREAD(f_cred)
+CANREAD(f_audit_data)
+CANREAD(f_count)
+
+/*
+ * We can potentially read parts of our cred, but we can't dereference
+ * through cr_zone.
+ */
+CANTREAD(f_cred->cr_zone->zone_id)
+
+CANREAD(f_vnode->v_path)
+CANREAD(f_vnode->v_op)
+CANREAD(f_vnode->v_op->vnop_name)
+
+CANTREAD(f_vnode->v_flag)
+CANTREAD(f_vnode->v_count)
+CANTREAD(f_vnode->v_pages)
+CANTREAD(f_vnode->v_type)
+CANTREAD(f_vnode->v_vfsmountedhere)
+CANTREAD(f_vnode->v_op->vop_open)
+
+BEGIN
+{
+ errmsg = "";
+ this->fp = getf(0);
+ this->fp2 = getf(1);
+
+ trace(this->fp->f_vnode);
+ printf("\nable to successfully read this->fp!");
+ exit(1);
+}
+
+BEGIN
+{
+ errmsg = "";
+ this->fp = getf(0);
+}
+
+BEGIN
+{
+ trace(this->fp->f_vnode);
+ printf("\nable to successfully read this->fp from prior clause!");
+}
+
+BEGIN
+{
+ exit(0);
+}
+
+ERROR
+/errmsg != ""/
+{
+ printf("fatal error: %s", errmsg);
+ exit(1);
+}
+
+EOF
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.procpriv.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.procpriv.ksh
new file mode 100644
index 0000000..7022566
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.procpriv.ksh
@@ -0,0 +1,138 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012, Joyent, Inc. All rights reserved.
+#
+
+ppriv -s A=basic,dtrace_proc,dtrace_user $$
+
+#
+# When we have dtrace_proc (but lack dtrace_kernel), we expect to be able to
+# read certain curpsinfo/curlwpsinfo/curcpu fields even though they require
+# reading in-kernel state. However, there are other fields in these translated
+# structures that we know we shouldn't be able to read, as they require reading
+# in-kernel state that we cannot read with only dtrace_proc. Finally, there
+# are a few fields that we may or may not be able to read depending on the
+# specifics of context. This test therefore asserts that we can read what we
+# think we should be able to, that we can't read what we think we shouldn't be
+# able to, and (for purposes of completeness) that we are indifferent about
+# what we cannot assert one way or the other.
+#
+/usr/sbin/dtrace -q -Cs /dev/stdin <<EOF
+
+#define CANREAD(what, field) \
+ BEGIN { errmsg = "can't read field from what"; printf("field: "); \
+ trace(what->field); printf("\n"); }
+
+#define CANTREAD(what, field) \
+ BEGIN { errmsg = ""; trace(what->field); \
+ printf("\nable to successfully read field from what!"); exit(1); }
+
+#define MIGHTREAD(what, field) \
+ BEGIN { errmsg = ""; printf("field: "); trace(what->field); printf("\n"); }
+
+#define CANREADVAR(vname) \
+ BEGIN { errmsg = "can't read vname"; printf("vname: "); \
+ trace(vname); printf("\n"); }
+
+#define CANTREADVAR(vname) \
+ BEGIN { errmsg = ""; trace(vname); \
+ printf("\nable to successfully read vname!"); exit(1); }
+
+#define MIGHTREADVAR(vname) \
+ BEGIN { errmsg = ""; printf("vname: "); trace(vname); printf("\n"); }
+
+CANREAD(curpsinfo, pr_pid)
+CANREAD(curpsinfo, pr_nlwp)
+CANREAD(curpsinfo, pr_ppid)
+CANREAD(curpsinfo, pr_uid)
+CANREAD(curpsinfo, pr_euid)
+CANREAD(curpsinfo, pr_gid)
+CANREAD(curpsinfo, pr_egid)
+CANREAD(curpsinfo, pr_addr)
+CANREAD(curpsinfo, pr_start)
+CANREAD(curpsinfo, pr_fname)
+CANREAD(curpsinfo, pr_psargs)
+CANREAD(curpsinfo, pr_argc)
+CANREAD(curpsinfo, pr_argv)
+CANREAD(curpsinfo, pr_envp)
+CANREAD(curpsinfo, pr_dmodel)
+
+/*
+ * If our p_pgidp points to the same pid structure as our p_pidp, we will
+ * be able to read pr_pgid -- but we won't if not.
+ */
+MIGHTREAD(curpsinfo, pr_pgid)
+
+CANTREAD(curpsinfo, pr_sid)
+CANTREAD(curpsinfo, pr_ttydev)
+CANTREAD(curpsinfo, pr_projid)
+CANTREAD(curpsinfo, pr_zoneid)
+CANTREAD(curpsinfo, pr_contract)
+
+CANREAD(curlwpsinfo, pr_flag)
+CANREAD(curlwpsinfo, pr_lwpid)
+CANREAD(curlwpsinfo, pr_addr)
+CANREAD(curlwpsinfo, pr_wchan)
+CANREAD(curlwpsinfo, pr_stype)
+CANREAD(curlwpsinfo, pr_state)
+CANREAD(curlwpsinfo, pr_sname)
+CANREAD(curlwpsinfo, pr_syscall)
+CANREAD(curlwpsinfo, pr_pri)
+CANREAD(curlwpsinfo, pr_onpro)
+CANREAD(curlwpsinfo, pr_bindpro)
+CANREAD(curlwpsinfo, pr_bindpset)
+
+CANTREAD(curlwpsinfo, pr_clname)
+CANTREAD(curlwpsinfo, pr_lgrp)
+
+CANREAD(curcpu, cpu_id)
+
+CANTREAD(curcpu, cpu_pset)
+CANTREAD(curcpu, cpu_chip)
+CANTREAD(curcpu, cpu_lgrp)
+CANTREAD(curcpu, cpu_info)
+
+/*
+ * We cannot assert one thing or another about the variable "root": for those
+ * with only dtrace_proc, it will be readable in the global but not readable in
+ * the non-global.
+ */
+MIGHTREADVAR(root)
+
+CANREADVAR(cpu)
+CANTREADVAR(pset)
+CANTREADVAR(cwd)
+CANTREADVAR(chip)
+CANTREADVAR(lgrp)
+
+BEGIN
+{
+ exit(0);
+}
+
+ERROR
+/errmsg != ""/
+{
+ printf("fatal error: %s", errmsg);
+ exit(1);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.providers.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.providers.ksh
new file mode 100644
index 0000000..94c3722
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/privs/tst.providers.ksh
@@ -0,0 +1,126 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012, Joyent, Inc. All rights reserved.
+#
+
+#
+# First, make sure that we can successfully enable the io provider
+#
+if ! dtrace -P io -n BEGIN'{exit(0)}' > /dev/null 2>&1 ; then
+ echo failed to enable io provider with full privs
+ exit 1
+fi
+
+ppriv -s A=basic,dtrace_proc,dtrace_user $$
+
+#
+# Now make sure that we cannot enable the io provider with reduced privs
+#
+if ! dtrace -x errtags -P io -n BEGIN'{exit(1)}' 2>&1 | \
+ grep D_PDESC_ZERO > /dev/null 2>&1 ; then
+ echo successfully enabled the io provider with reduced privs
+ exit 1
+fi
+
+#
+# Keeping our reduced privs, we want to assure that we can see every provider
+# that we think we should be able to see -- and that we can see curpsinfo
+# state but can't otherwise see arguments.
+#
+/usr/sbin/dtrace -wq -Cs /dev/stdin <<EOF
+
+int seen[string];
+int err;
+
+#define CANENABLE(provider) \
+provider::: \
+/err == 0 && progenyof(\$pid) && !seen["provider"]/ \
+{ \
+ trace(arg0); \
+ printf("\nsuccessful trace of arg0 in %s:%s:%s:%s\n", \
+ probeprov, probemod, probefunc, probename); \
+ exit(++err); \
+} \
+ \
+provider::: \
+/progenyof(\$pid)/ \
+{ \
+ seen["provider"]++; \
+} \
+ \
+provider::: \
+/progenyof(\$pid)/ \
+{ \
+ errstr = "provider"; \
+ this->ignore = stringof(curpsinfo->pr_psargs); \
+ errstr = ""; \
+} \
+ \
+END \
+/err == 0 && !seen["provider"]/ \
+{ \
+ printf("no probes from provider\n"); \
+ exit(++err); \
+} \
+ \
+END \
+/err == 0/ \
+{ \
+ printf("saw %d probes from provider\n", seen["provider"]); \
+}
+
+CANENABLE(proc)
+CANENABLE(sched)
+CANENABLE(vminfo)
+CANENABLE(sysinfo)
+
+BEGIN
+{
+ /*
+ * We'll kick off a system of a do-nothing command -- which should be
+ * enough to kick proc, sched, vminfo and sysinfo probes.
+ */
+ system("echo > /dev/null");
+}
+
+ERROR
+/err == 0 && errstr != ""/
+{
+ printf("fatal error: couldn't read curpsinfo->pr_psargs in ");
+ printf("%s-provided probe\n", errstr);
+ exit(++err);
+}
+
+proc:::exit
+/progenyof(\$pid)/
+{
+ exit(0);
+}
+
+tick-10ms
+/i++ > 500/
+{
+ printf("exit probe did not seem to fire\n");
+ exit(++err);
+}
+EOF
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooLarge.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooLarge.d
new file mode 100644
index 0000000..4d6b5af
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooLarge.d
@@ -0,0 +1,35 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * ASSERTION:
+ * The largest base we will accept is Base 36 -- i.e. using all of 0-9 and
+ * A-Z as numerals.
+ *
+ * SECTION: Actions and Subroutines/strtoll()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ printf("%d\n", strtoll("0", 37));
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooSmall.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooSmall.d
new file mode 100644
index 0000000..de56b50
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/err.BaseTooSmall.d
@@ -0,0 +1,34 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * ASSERTION:
+ * The smallest base we will accept is Base 2.
+ *
+ * SECTION: Actions and Subroutines/strtoll()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ printf("%d\n", strtoll("0", 1));
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d
new file mode 100644
index 0000000..0b1812a
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d
@@ -0,0 +1,66 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * ASSERTION:
+ * Test the strtoll() subroutine.
+ *
+ * SECTION: Actions and Subroutines/strtoll()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+
+ /* minimum base (2) and maximum base (36): */
+ printf("%d\n", strtoll("0", 2));
+ printf("%d\n", strtoll("1", 36));
+
+ /* simple tests: */
+ printf("%d\n", strtoll("0x20", 16));
+ printf("%d\n", strtoll("-32", 10));
+ printf("%d\n", strtoll("010", 8));
+ printf("%d\n", strtoll("101010", 2));
+
+ /* INT64_MIN and INT64_MAX: */
+ printf("%d\n", strtoll("9223372036854775807"));
+ printf("%d\n", strtoll("-9223372036854775808"));
+ printf("%d\n", strtoll("0777777777777777777777", 8));
+ printf("%d\n", strtoll("-01000000000000000000000", 8));
+
+ /* wrapping: */
+ printf("%d\n", strtoll("1000000000000000000000", 8));
+ printf("%d\n", strtoll("-1000000000000000000001", 8));
+
+ /* hex without prefix: */
+ printf("%d\n", strtoll("baddcafe", 16));
+
+ /* stopping at first out-of-base character: */
+ printf("%d\n", strtoll("12j", 10));
+ printf("%d\n", strtoll("102", 2));
+
+ /* base 36: */
+ printf("%d\n", strtoll("-0DTrace4EverZ", 36));
+
+ /* base 10 is assumed: */
+ printf("%d\n", strtoll("1985"));
+ printf("%d\n", strtoll("-2012"));
+
+ /* empty string: */
+ printf("%d\n", strtoll(""));
+
+ exit(0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d.out
new file mode 100644
index 0000000..d12eb9c
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/strtoll/tst.strtoll.d.out
@@ -0,0 +1,20 @@
+0
+1
+32
+-32
+8
+42
+9223372036854775807
+-9223372036854775808
+9223372036854775807
+-9223372036854775808
+-9223372036854775808
+9223372036854775807
+3135097598
+12
+2
+-1819882045752187535
+1985
+-2012
+0
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidpid.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidpid.d
new file mode 100644
index 0000000..4865d81
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidpid.d
@@ -0,0 +1,21 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace((pidfoo`int)0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidpid2.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidpid2.d
new file mode 100644
index 0000000..bafed12
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidpid2.d
@@ -0,0 +1,21 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace((pid8foo`int)0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidpid3.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidpid3.d
new file mode 100644
index 0000000..fb9443a
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidpid3.d
@@ -0,0 +1,21 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ trace((pid0`int)0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidtype.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidtype.ksh
new file mode 100644
index 0000000..978cde3
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidtype.ksh
@@ -0,0 +1,34 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# While it's hard to be completely certain that a type of the name we want
+# doesn't exist, we're going to try to pick a name which is rather unique.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+t="season_8_mountain_of_madness_t"
+pid=$$
+
+rc=`$dtrace -n "BEGIN{ trace(pid$pid`$t)0); }"`
+
+exit $rc
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidtype2.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidtype2.ksh
new file mode 100644
index 0000000..e64ed52
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.invalidtype2.ksh
@@ -0,0 +1,35 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# While it's hard to be completely certain that a type of the name we want
+# doesn't exist, we're going to try to pick a name which is rather
+# unique. This time we're also going to use the pid$target alias.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+t="season_8_mountain_of_madness_t"
+pid=$$
+
+rc=`$dtrace -n "BEGIN{ trace(pid`$t)0); }"` -p $pid
+
+exit $rc
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.user64mode.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.user64mode.ksh
new file mode 100644
index 0000000..d987c8d
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/err.user64mode.ksh
@@ -0,0 +1,90 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# This test is purposefully using a 64-bit DTrace and thus 64-bit types
+# when compared with a 32-bit process. This test uses the userland
+# keyword and so the implicit copyin should access illegal memory and
+# thus exit.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+t="zelda_info_t"
+exe="tst.chasestrings.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf'
+if [[ $? -ne 0 ]]; then
+ echo "CTF does not exist in $exe, that's a bug" >&2
+ exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -64 -qs /dev/stdin <<EOF
+typedef struct info {
+ char *zi_gamename;
+ int zi_ndungeons;
+ char *zi_villain;
+ int zi_haszelda;
+} info_t;
+
+pid$pid::has_princess:entry
+/next == 0/
+{
+ this->t = (userland info_t *)arg0;
+ printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+ stringof(this->t->zi_gamename), this->t->zi_ndungeons,
+ stringof(this->t->zi_villain), this->t->zi_haszelda);
+ next = 1;
+}
+
+pid$pid::has_dungeons:entry
+/next == 1/
+{
+ this->t = (userland info_t *)arg0;
+ printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+ stringof(this->t->zi_gamename), this->t->zi_ndungeons,
+ stringof(this->t->zi_villain), this->t->zi_haszelda);
+ next = 2;
+}
+
+pid$pid::has_villain:entry
+/next == 2/
+{
+ this->t = (userland info_t *)arg0;
+ printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+ stringof(this->t->zi_gamename), this->t->zi_ndungeons,
+ stringof(this->t->zi_villain), this->t->zi_haszelda);
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.aouttype.c b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.aouttype.c
new file mode 100644
index 0000000..a4d25f8
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.aouttype.c
@@ -0,0 +1,46 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 (c) Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * This test tries to make sure that we have CTF data for a type that only this
+ * binary would reasonably have. In this case, the
+ * season_7_lisa_the_vegetarian_t.
+ */
+#include <unistd.h>
+
+typedef struct season_7_lisa_the_vegetarian {
+ int fr_salad;
+} season_7_lisa_the_vegetarian_t;
+
+int
+sleeper(season_7_lisa_the_vegetarian_t *lp)
+{
+ for (;;) {
+ sleep(lp->fr_salad);
+ }
+ /*NOTREACHED*/
+ return (0);
+}
+
+int
+main(void)
+{
+ season_7_lisa_the_vegetarian_t l;
+ l.fr_salad = 100;
+
+ sleeper(&l);
+
+ return (0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.aouttype.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.aouttype.ksh
new file mode 100644
index 0000000..151a936
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.aouttype.ksh
@@ -0,0 +1,44 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Lookup a type that is inside a.out.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+t="season_7_lisa_the_vegetrian_t *"
+exe="tst.aouttype.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf'
+if [[ $? -ne 0 ]]; then
+ echo "CTF does not exist in $exe, that's a bug" >&2
+ exit 1
+fi
+
+./$exe &
+pid=$!
+
+rc=`$dtrace -n "BEGIN{ trace((pid$pid\`$t)0); exit(0); }"`
+
+kill -9 $pid
+
+exit $rc
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.c b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.c
new file mode 100644
index 0000000..595a7cb
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.c
@@ -0,0 +1,79 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 (c) Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * This test takes data from the current binary which is basically running in a
+ * loop between two functions and our goal is to have two unique types that they
+ * contain which we can print.
+ */
+
+#include <unistd.h>
+
+typedef struct zelda_info {
+ char *zi_gamename;
+ int zi_ndungeons;
+ char *zi_villain;
+ int zi_haszelda;
+} zelda_info_t;
+
+static int
+has_princess(zelda_info_t *z)
+{
+ return (z->zi_haszelda);
+}
+
+static int
+has_dungeons(zelda_info_t *z)
+{
+ return (z->zi_ndungeons != 0);
+}
+
+static const char *
+has_villain(zelda_info_t *z)
+{
+ return (z->zi_villain);
+}
+
+int
+main(void)
+{
+ zelda_info_t oot;
+ zelda_info_t la;
+ zelda_info_t lttp;
+
+ oot.zi_gamename = "Ocarina of Time";
+ oot.zi_ndungeons = 10;
+ oot.zi_villain = "Ganondorf";
+ oot.zi_haszelda = 1;
+
+ la.zi_gamename = "Link's Awakening";
+ la.zi_ndungeons = 9;
+ la.zi_villain = "Nightmare";
+ la.zi_haszelda = 0;
+
+ lttp.zi_gamename = "A Link to the Past";
+ lttp.zi_ndungeons = 12;
+ lttp.zi_villain = "Ganon";
+ lttp.zi_haszelda = 1;
+
+ for (;;) {
+ (void) has_princess(&oot);
+ (void) has_dungeons(&la);
+ (void) has_villain(&lttp);
+ sleep(1);
+ }
+
+ return (0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.ksh
new file mode 100644
index 0000000..2502846
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.ksh
@@ -0,0 +1,76 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# This test is checking that we can read members and that pointers inside
+# members point to valid data that is intelligible, eg. strings.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+t="zelda_info_t"
+exe="tst.chasestrings.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf'
+if [[ $? -ne 0 ]]; then
+ echo "CTF does not exist in $exe, that's a bug" >&2
+ exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -qs /dev/stdin <<EOF
+pid$pid::has_princess:entry
+/next == 0/
+{
+ this->t = (pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t)));
+ printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+ copyinstr((uintptr_t)this->t->zi_gamename), this->t->zi_ndungeons,
+ copyinstr((uintptr_t)this->t->zi_villain), this->t->zi_haszelda);
+ next = 1;
+}
+
+pid$pid::has_dungeons:entry
+/next == 1/
+{
+ this->t = (pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t)));
+ printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+ copyinstr((uintptr_t)this->t->zi_gamename), this->t->zi_ndungeons,
+ copyinstr((uintptr_t)this->t->zi_villain), this->t->zi_haszelda);
+ next = 2;
+}
+
+pid$pid::has_villain:entry
+/next == 2/
+{
+ this->t = (pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t)));
+ printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+ copyinstr((uintptr_t)this->t->zi_gamename), this->t->zi_ndungeons,
+ copyinstr((uintptr_t)this->t->zi_villain), this->t->zi_haszelda);
+ exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.ksh.out
new file mode 100644
index 0000000..219e406
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.ksh.out
@@ -0,0 +1,4 @@
+game: Ocarina of Time, dungeon: 10, villain: Ganondorf, zelda: 1
+game: Link's Awakening, dungeon: 9, villain: Nightmare, zelda: 0
+game: A Link to the Past, dungeon: 12, villain: Ganon, zelda: 1
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.libtype.c b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.libtype.c
new file mode 100644
index 0000000..916a5b5
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.libtype.c
@@ -0,0 +1,29 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 (c) Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * We're linked against libc which has types, though we do not.
+ */
+#include <unistd.h>
+
+int
+main(void)
+{
+ for (;;) {
+ sleep(1000);
+ }
+ /*NOTREACHED*/
+ return (0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.libtype.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.libtype.ksh
new file mode 100644
index 0000000..af7c6c8
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.libtype.ksh
@@ -0,0 +1,45 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Here we want to make sure that the program in question does not have ctf data
+# in its a.out; however, we can get types out of a linked libc.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+t="int"
+exe="tst.libtype.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf'
+if [[ $? -eq 0 ]]; then
+ echo "CTF exists in $exe, that's a bug" >&2
+ exit 1
+fi
+
+./$exe &
+pid=$!
+
+rc=`$dtrace -n "BEGIN{ trace((pid$pid\`$t)0); exit(0); }"`
+
+kill -9 $pid
+
+exit $rc
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.linkmap.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.linkmap.ksh
new file mode 100644
index 0000000..f767def
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.linkmap.ksh
@@ -0,0 +1,44 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# We should be able to see both strstr from libc and from ld on an
+# alternate linkmap.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+
+$dtrace -q -p $$ -s /dev/stdin <<EOF
+pid\$target:LM1\`ld.so.1:strstr:entry,
+pid\$target:libc.so.1:strstr:entry
+{
+ exit (0);
+}
+
+BEGIN
+{
+ exit (0);
+}
+EOF
+rc=$?
+
+exit $rc
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.pidprint.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.pidprint.ksh
new file mode 100644
index 0000000..febb015
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.pidprint.ksh
@@ -0,0 +1,69 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Use print() on userland CTF types and verify we get the data we expect.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+t="final_fantasy_info_t"
+exe="tst.printtype.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf'
+if [[ $? -ne 0 ]]; then
+ echo "CTF does not exist in $exe, that's a bug" >&2
+ exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -qs /dev/stdin <<EOF
+pid$pid::ff_getgameid:entry
+/next == 0/
+{
+ print(*args[0]);
+ printf("\n");
+ next = 1;
+}
+
+pid$pid::ff_getpartysize:entry
+/next == 1/
+{
+ print(*args[0]);
+ printf("\n");
+ next = 2;
+}
+
+pid$pid::ff_getsummons:entry
+/next == 2/
+{
+ print(*args[0]);
+ printf("\n");
+ exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.pidprinttarg.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.pidprinttarg.ksh
new file mode 100644
index 0000000..7398dc4
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.pidprinttarg.ksh
@@ -0,0 +1,70 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Use print() on userland CTF types and verify we get the data we
+# expect. This time, use $target to make sure that path works correctly.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+t="final_fantasy_info_t"
+exe="tst.printtype.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf'
+if [[ $? -ne 0 ]]; then
+ echo "CTF does not exist in $exe, that's a bug" >&2
+ exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -p $pid -qs /dev/stdin <<EOF
+pid\$target::ff_getgameid:entry
+/next == 0/
+{
+ print(*args[0]);
+ printf("\n");
+ next = 1;
+}
+
+pid\$target::ff_getpartysize:entry
+/next == 1/
+{
+ print(*args[0]);
+ printf("\n");
+ next = 2;
+}
+
+pid\$target::ff_getsummons:entry
+/next == 2/
+{
+ print(*args[0]);
+ printf("\n");
+ exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtype.c b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtype.c
new file mode 100644
index 0000000..6c27593
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtype.c
@@ -0,0 +1,72 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 (c) Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * The point of this is to use print() on various functions to make sure that we
+ * can print basic structures. Note that we purposefully are making sure that
+ * there are no pointers here.
+ */
+#include <unistd.h>
+
+typedef struct final_fantasy_info {
+ int ff_gameid;
+ int ff_partysize;
+ int ff_hassummons;
+} final_fantasy_info_t;
+
+static int
+ff_getgameid(final_fantasy_info_t *f)
+{
+ return (0);
+}
+
+static int
+ff_getpartysize(final_fantasy_info_t *f)
+{
+ return (0);
+}
+
+static int
+ff_getsummons(final_fantasy_info_t *f)
+{
+ return (0);
+}
+
+int
+main(void)
+{
+ final_fantasy_info_t ffiii, ffx, ffi;
+
+ ffi.ff_gameid = 1;
+ ffi.ff_partysize = 4;
+ ffi.ff_hassummons = 0;
+
+ ffiii.ff_gameid = 6;
+ ffiii.ff_partysize = 4;
+ ffiii.ff_hassummons = 1;
+
+ ffx.ff_gameid = 10;
+ ffx.ff_partysize = 3;
+ ffx.ff_hassummons = 1;
+
+ for (;;) {
+ ff_getgameid(&ffi);
+ ff_getpartysize(&ffx);
+ ff_getsummons(&ffiii);
+ sleep(1);
+ }
+ /*NOTREACHED*/
+ return (0);
+}
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtype.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtype.ksh
new file mode 100644
index 0000000..dfc1535
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtype.ksh
@@ -0,0 +1,69 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Use print() on userland CTF types and verify we get the data we expect.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+t="final_fantasy_info_t"
+exe="tst.printtype.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf'
+if [[ $? -ne 0 ]]; then
+ echo "CTF does not exist in $exe, that's a bug" >&2
+ exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -qs /dev/stdin <<EOF
+pid$pid::ff_getgameid:entry
+/next == 0/
+{
+ print(*(pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t))));
+ printf("\n");
+ next = 1;
+}
+
+pid$pid::ff_getpartysize:entry
+/next == 1/
+{
+ print(*(pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t))));
+ printf("\n");
+ next = 2;
+}
+
+pid$pid::ff_getsummons:entry
+/next == 2/
+{
+ print(*(pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t))));
+ printf("\n");
+ exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtype.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtype.ksh.out
new file mode 100644
index 0000000..1770ba2
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtype.ksh.out
@@ -0,0 +1,16 @@
+final_fantasy_info_t {
+ int ff_gameid = 0x1
+ int ff_partysize = 0x4
+ int ff_hassummons = 0
+}
+final_fantasy_info_t {
+ int ff_gameid = 0xa
+ int ff_partysize = 0x3
+ int ff_hassummons = 0x1
+}
+final_fantasy_info_t {
+ int ff_gameid = 0x6
+ int ff_partysize = 0x4
+ int ff_hassummons = 0x1
+}
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtypetarg.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtypetarg.ksh
new file mode 100644
index 0000000..025d4a8
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.printtypetarg.ksh
@@ -0,0 +1,70 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Use print() on userland CTF types and verify we get the data we
+# expect. Use the pid` alias for $target.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+t="final_fantasy_info_t"
+exe="tst.printtype.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf'
+if [[ $? -ne 0 ]]; then
+ echo "CTF does not exist in $exe, that's a bug" >&2
+ exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -p $pid -qs /dev/stdin <<EOF
+pid\$target::ff_getgameid:entry
+/next == 0/
+{
+ print(*(pid\`$t *)(copyin(arg0, sizeof (pid\`$t))));
+ printf("\n");
+ next = 1;
+}
+
+pid\$target::ff_getpartysize:entry
+/next == 1/
+{
+ print(*(pid\`$t *)(copyin(arg0, sizeof (pid\`$t))));
+ printf("\n");
+ next = 2;
+}
+
+pid\$target::ff_getsummons:entry
+/next == 2/
+{
+ print(*(pid\`$t *)(copyin(arg0, sizeof (pid\`$t))));
+ printf("\n");
+ exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh
new file mode 100644
index 0000000..58811ff
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh
@@ -0,0 +1,83 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Simple test that if we manually use the userland keyword that it
+# works.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+t="zelda_info_t"
+exe="tst.chasestrings.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf'
+if [[ $? -ne 0 ]]; then
+ echo "CTF does not exist in $exe, that's a bug" >&2
+ exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -32 -qs /dev/stdin <<EOF
+typedef struct info {
+ char *zi_gamename;
+ int zi_ndungeons;
+ char *zi_villain;
+ int zi_haszelda;
+} info_t;
+
+pid$pid::has_princess:entry
+/next == 0/
+{
+ this->t = (userland info_t *)arg0;
+ printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+ stringof(this->t->zi_gamename), this->t->zi_ndungeons,
+ stringof(this->t->zi_villain), this->t->zi_haszelda);
+ next = 1;
+}
+
+pid$pid::has_dungeons:entry
+/next == 1/
+{
+ this->t = (userland info_t *)arg0;
+ printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+ stringof(this->t->zi_gamename), this->t->zi_ndungeons,
+ stringof(this->t->zi_villain), this->t->zi_haszelda);
+ next = 2;
+}
+
+pid$pid::has_villain:entry
+/next == 2/
+{
+ this->t = (userland info_t *)arg0;
+ printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+ stringof(this->t->zi_gamename), this->t->zi_ndungeons,
+ stringof(this->t->zi_villain), this->t->zi_haszelda);
+ exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh.out
new file mode 100644
index 0000000..219e406
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh.out
@@ -0,0 +1,4 @@
+game: Ocarina of Time, dungeon: 10, villain: Ganondorf, zelda: 1
+game: Link's Awakening, dungeon: 9, villain: Nightmare, zelda: 0
+game: A Link to the Past, dungeon: 12, villain: Ganon, zelda: 1
+
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userstrings.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userstrings.ksh
new file mode 100644
index 0000000..79d79de
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userstrings.ksh
@@ -0,0 +1,72 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# This test is checking that we can read members and that pointers inside
+# members point to valid data that is intelligible, eg. strings.
+#
+
+if [ $# != 1 ]; then
+ echo expected one argument: '<'dtrace-path'>'
+ exit 2
+fi
+
+dtrace=$1
+exe="tst.chasestrings.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf'
+if [[ $? -ne 0 ]]; then
+ echo "CTF does not exist in $exe, that's a bug" >&2
+ exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -qs /dev/stdin <<EOF
+pid$pid::has_princess:entry
+/next == 0/
+{
+ printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+ stringof(args[0]->zi_gamename), args[0]->zi_ndungeons,
+ stringof(args[0]->zi_villain), args[0]->zi_haszelda);
+ next = 1;
+}
+
+pid$pid::has_dungeons:entry
+/next == 1/
+{
+ printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+ stringof(args[0]->zi_gamename), args[0]->zi_ndungeons,
+ stringof(args[0]->zi_villain), args[0]->zi_haszelda);
+ next = 2;
+}
+
+pid$pid::has_villain:entry
+/next == 2/
+{
+ printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+ stringof(args[0]->zi_gamename), args[0]->zi_ndungeons,
+ stringof(args[0]->zi_villain), args[0]->zi_haszelda);
+ exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userstrings.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userstrings.ksh.out
new file mode 100644
index 0000000..219e406
--- /dev/null
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/uctf/tst.userstrings.ksh.out
@@ -0,0 +1,4 @@
+game: Ocarina of Time, dungeon: 10, villain: Ganondorf, zelda: 1
+game: Link's Awakening, dungeon: 9, villain: Nightmare, zelda: 0
+game: A Link to the Past, dungeon: 12, villain: Ganon, zelda: 1
+
diff --git a/cddl/contrib/opensolaris/common/ctf/ctf_open.c b/cddl/contrib/opensolaris/common/ctf/ctf_open.c
index 2148389..001cf5c 100644
--- a/cddl/contrib/opensolaris/common/ctf/ctf_open.c
+++ b/cddl/contrib/opensolaris/common/ctf/ctf_open.c
@@ -25,7 +25,7 @@
* Use is subject to license terms.
*/
/*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#include <ctf_impl.h>
@@ -788,6 +788,92 @@ bad:
}
/*
+ * Dupliate a ctf_file_t and its underlying section information into a new
+ * container. This works by copying the three ctf_sect_t's of the original
+ * container if they exist and passing those into ctf_bufopen. To copy those, we
+ * mmap anonymous memory with ctf_data_alloc and bcopy the data across. It's not
+ * the cheapest thing, but it's what we've got.
+ */
+ctf_file_t *
+ctf_dup(ctf_file_t *ofp)
+{
+ ctf_file_t *fp;
+ ctf_sect_t ctfsect, symsect, strsect;
+ ctf_sect_t *ctp, *symp, *strp;
+ void *cbuf, *symbuf, *strbuf;
+ int err;
+
+ cbuf = symbuf = strbuf = NULL;
+ /*
+ * The ctfsect isn't allowed to not exist, but the symbol and string
+ * section might not. We only need to copy the data of the section, not
+ * the name, as ctf_bufopen will take care of that.
+ */
+ bcopy(&ofp->ctf_data, &ctfsect, sizeof (ctf_sect_t));
+ cbuf = ctf_data_alloc(ctfsect.cts_size);
+ if (cbuf == NULL) {
+ (void) ctf_set_errno(ofp, ECTF_MMAP);
+ return (NULL);
+ }
+
+ bcopy(ctfsect.cts_data, cbuf, ctfsect.cts_size);
+ ctf_data_protect(cbuf, ctfsect.cts_size);
+ ctfsect.cts_data = cbuf;
+ ctfsect.cts_offset = 0;
+ ctp = &ctfsect;
+
+ if (ofp->ctf_symtab.cts_data != NULL) {
+ bcopy(&ofp->ctf_symtab, &symsect, sizeof (ctf_sect_t));
+ symbuf = ctf_data_alloc(symsect.cts_size);
+ if (symbuf == NULL) {
+ (void) ctf_set_errno(ofp, ECTF_MMAP);
+ goto err;
+ }
+ bcopy(symsect.cts_data, symbuf, symsect.cts_size);
+ ctf_data_protect(symbuf, symsect.cts_size);
+ symsect.cts_data = symbuf;
+ symsect.cts_offset = 0;
+ symp = &symsect;
+ } else {
+ symp = NULL;
+ }
+
+ if (ofp->ctf_strtab.cts_data != NULL) {
+ bcopy(&ofp->ctf_strtab, &strsect, sizeof (ctf_sect_t));
+ strbuf = ctf_data_alloc(strsect.cts_size);
+ if (strbuf == NULL) {
+ (void) ctf_set_errno(ofp, ECTF_MMAP);
+ goto err;
+ }
+ bcopy(strsect.cts_data, strbuf, strsect.cts_size);
+ ctf_data_protect(strbuf, strsect.cts_size);
+ strsect.cts_data = strbuf;
+ strsect.cts_offset = 0;
+ strp = &strsect;
+ } else {
+ strp = NULL;
+ }
+
+ fp = ctf_bufopen(ctp, symp, strp, &err);
+ if (fp == NULL) {
+ (void) ctf_set_errno(ofp, err);
+ goto err;
+ }
+
+ fp->ctf_flags |= LCTF_MMAP;
+
+ return (fp);
+
+err:
+ ctf_data_free(cbuf, ctfsect.cts_size);
+ if (symbuf != NULL)
+ ctf_data_free(symbuf, symsect.cts_size);
+ if (strbuf != NULL)
+ ctf_data_free(strbuf, strsect.cts_size);
+ return (NULL);
+}
+
+/*
* Close the specified CTF container and free associated data structures. Note
* that ctf_close() is a reference counted operation: if the specified file is
* the parent of other active containers, its reference count will be greater
diff --git a/cddl/contrib/opensolaris/common/ctf/ctf_types.c b/cddl/contrib/opensolaris/common/ctf/ctf_types.c
index 290c518..ab1b9ff 100644
--- a/cddl/contrib/opensolaris/common/ctf/ctf_types.c
+++ b/cddl/contrib/opensolaris/common/ctf/ctf_types.c
@@ -25,8 +25,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <ctf_impl.h>
ssize_t
@@ -199,8 +197,9 @@ ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
* Lookup the given type ID and print a string name for it into buf. Return
* the actual number of bytes (not including \0) needed to format the name.
*/
-ssize_t
-ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
+static ssize_t
+ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
+ const char *qname)
{
ctf_decl_t cd;
ctf_decl_node_t *cdp;
@@ -255,6 +254,8 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
case CTF_K_INTEGER:
case CTF_K_FLOAT:
case CTF_K_TYPEDEF:
+ if (qname != NULL)
+ ctf_decl_sprintf(&cd, "%s`", qname);
ctf_decl_sprintf(&cd, "%s", name);
break;
case CTF_K_POINTER:
@@ -268,13 +269,22 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
break;
case CTF_K_STRUCT:
case CTF_K_FORWARD:
- ctf_decl_sprintf(&cd, "struct %s", name);
+ ctf_decl_sprintf(&cd, "struct ");
+ if (qname != NULL)
+ ctf_decl_sprintf(&cd, "%s`", qname);
+ ctf_decl_sprintf(&cd, "%s", name);
break;
case CTF_K_UNION:
- ctf_decl_sprintf(&cd, "union %s", name);
+ ctf_decl_sprintf(&cd, "union ");
+ if (qname != NULL)
+ ctf_decl_sprintf(&cd, "%s`", qname);
+ ctf_decl_sprintf(&cd, "%s", name);
break;
case CTF_K_ENUM:
- ctf_decl_sprintf(&cd, "enum %s", name);
+ ctf_decl_sprintf(&cd, "enum ");
+ if (qname != NULL)
+ ctf_decl_sprintf(&cd, "%s`", qname);
+ ctf_decl_sprintf(&cd, "%s", name);
break;
case CTF_K_VOLATILE:
ctf_decl_sprintf(&cd, "volatile");
@@ -301,6 +311,12 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
return (cd.cd_len);
}
+ssize_t
+ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
+{
+ return (ctf_type_qlname(fp, type, buf, len, NULL));
+}
+
/*
* Lookup the given type ID and print a string name for it into buf. If buf
* is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us.
@@ -308,10 +324,19 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
char *
ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
{
- ssize_t rv = ctf_type_lname(fp, type, buf, len);
+ ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL);
+ return (rv >= 0 && rv < len ? buf : NULL);
+}
+
+char *
+ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
+ const char *qname)
+{
+ ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname);
return (rv >= 0 && rv < len ? buf : NULL);
}
+
/*
* Resolve the type down to a base type node, and then return the size
* of the type storage in bytes.
diff --git a/cddl/contrib/opensolaris/common/util/strtolctype.h b/cddl/contrib/opensolaris/common/util/strtolctype.h
new file mode 100644
index 0000000..a1d1836
--- /dev/null
+++ b/cddl/contrib/opensolaris/common/util/strtolctype.h
@@ -0,0 +1,79 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+#ifndef _COMMON_UTIL_CTYPE_H
+#define _COMMON_UTIL_CTYPE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This header file contains a collection of macros that the strtou?ll?
+ * functions in common/util use to test characters. What we need is a kernel
+ * version of ctype.h.
+ *
+ * NOTE: These macros are used within several DTrace probe context functions.
+ * They must not be altered to make function calls or perform actions not
+ * safe in probe context.
+ */
+
+#if defined(sun) && (defined(_KERNEL) || defined(_BOOT))
+
+#define isalnum(ch) (isalpha(ch) || isdigit(ch))
+#define isalpha(ch) (isupper(ch) || islower(ch))
+#define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
+#define islower(ch) ((ch) >= 'a' && (ch) <= 'z')
+#define isspace(ch) (((ch) == ' ') || ((ch) == '\r') || ((ch) == '\n') || \
+ ((ch) == '\t') || ((ch) == '\f'))
+#define isupper(ch) ((ch) >= 'A' && (ch) <= 'Z')
+#define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \
+ ((ch) >= 'A' && (ch) <= 'F'))
+
+#endif /* _KERNEL || _BOOT */
+
+#define DIGIT(x) \
+ (isdigit(x) ? (x) - '0' : islower(x) ? (x) + 10 - 'a' : (x) + 10 - 'A')
+
+#define MBASE ('z' - 'a' + 1 + 10)
+
+/*
+ * The following macro is a version of isalnum() that limits alphabetic
+ * characters to the ranges a-z and A-Z; locale dependent characters will not
+ * return 1. The members of a-z and A-Z are assumed to be in ascending order
+ * and contiguous.
+ */
+#define lisalnum(x) \
+ (isdigit(x) || ((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z'))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _COMMON_UTIL_CTYPE_H */
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c
index b0f2b4a..6b571fa 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c
@@ -25,7 +25,7 @@
*/
/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@@ -1301,6 +1301,231 @@ dtrace_aggregate_walk(dtrace_hdl_t *dtp, dtrace_aggregate_f *func, void *arg)
}
static int
+dt_aggregate_total(dtrace_hdl_t *dtp, boolean_t clear)
+{
+ dt_ahashent_t *h;
+ dtrace_aggdata_t **total;
+ dtrace_aggid_t max = DTRACE_AGGVARIDNONE, id;
+ dt_aggregate_t *agp = &dtp->dt_aggregate;
+ dt_ahash_t *hash = &agp->dtat_hash;
+ uint32_t tflags;
+
+ tflags = DTRACE_A_TOTAL | DTRACE_A_HASNEGATIVES | DTRACE_A_HASPOSITIVES;
+
+ /*
+ * If we need to deliver per-aggregation totals, we're going to take
+ * three passes over the aggregate: one to clear everything out and
+ * determine our maximum aggregation ID, one to actually total
+ * everything up, and a final pass to assign the totals to the
+ * individual elements.
+ */
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data;
+
+ if ((id = dt_aggregate_aggvarid(h)) > max)
+ max = id;
+
+ aggdata->dtada_total = 0;
+ aggdata->dtada_flags &= ~tflags;
+ }
+
+ if (clear || max == DTRACE_AGGVARIDNONE)
+ return (0);
+
+ total = dt_zalloc(dtp, (max + 1) * sizeof (dtrace_aggdata_t *));
+
+ if (total == NULL)
+ return (-1);
+
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+ dtrace_recdesc_t *rec;
+ caddr_t data;
+ int64_t val, *addr;
+
+ rec = &agg->dtagd_rec[agg->dtagd_nrecs - 1];
+ data = aggdata->dtada_data;
+ addr = (int64_t *)(uintptr_t)(data + rec->dtrd_offset);
+
+ switch (rec->dtrd_action) {
+ case DTRACEAGG_STDDEV:
+ val = dt_stddev((uint64_t *)addr, 1);
+ break;
+
+ case DTRACEAGG_SUM:
+ case DTRACEAGG_COUNT:
+ val = *addr;
+ break;
+
+ case DTRACEAGG_AVG:
+ val = addr[0] ? (addr[1] / addr[0]) : 0;
+ break;
+
+ default:
+ continue;
+ }
+
+ if (total[agg->dtagd_varid] == NULL) {
+ total[agg->dtagd_varid] = aggdata;
+ aggdata->dtada_flags |= DTRACE_A_TOTAL;
+ } else {
+ aggdata = total[agg->dtagd_varid];
+ }
+
+ if (val > 0)
+ aggdata->dtada_flags |= DTRACE_A_HASPOSITIVES;
+
+ if (val < 0) {
+ aggdata->dtada_flags |= DTRACE_A_HASNEGATIVES;
+ val = -val;
+ }
+
+ if (dtp->dt_options[DTRACEOPT_AGGZOOM] != DTRACEOPT_UNSET) {
+ val = (int64_t)((long double)val *
+ (1 / DTRACE_AGGZOOM_MAX));
+
+ if (val > aggdata->dtada_total)
+ aggdata->dtada_total = val;
+ } else {
+ aggdata->dtada_total += val;
+ }
+ }
+
+ /*
+ * And now one final pass to set everyone's total.
+ */
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data, *t;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+
+ if ((t = total[agg->dtagd_varid]) == NULL || aggdata == t)
+ continue;
+
+ aggdata->dtada_total = t->dtada_total;
+ aggdata->dtada_flags |= (t->dtada_flags & tflags);
+ }
+
+ dt_free(dtp, total);
+
+ return (0);
+}
+
+static int
+dt_aggregate_minmaxbin(dtrace_hdl_t *dtp, boolean_t clear)
+{
+ dt_ahashent_t *h;
+ dtrace_aggdata_t **minmax;
+ dtrace_aggid_t max = DTRACE_AGGVARIDNONE, id;
+ dt_aggregate_t *agp = &dtp->dt_aggregate;
+ dt_ahash_t *hash = &agp->dtat_hash;
+
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data;
+
+ if ((id = dt_aggregate_aggvarid(h)) > max)
+ max = id;
+
+ aggdata->dtada_minbin = 0;
+ aggdata->dtada_maxbin = 0;
+ aggdata->dtada_flags &= ~DTRACE_A_MINMAXBIN;
+ }
+
+ if (clear || max == DTRACE_AGGVARIDNONE)
+ return (0);
+
+ minmax = dt_zalloc(dtp, (max + 1) * sizeof (dtrace_aggdata_t *));
+
+ if (minmax == NULL)
+ return (-1);
+
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+ dtrace_recdesc_t *rec;
+ caddr_t data;
+ int64_t *addr;
+ int minbin = -1, maxbin = -1, i;
+ int start = 0, size;
+
+ rec = &agg->dtagd_rec[agg->dtagd_nrecs - 1];
+ size = rec->dtrd_size / sizeof (int64_t);
+ data = aggdata->dtada_data;
+ addr = (int64_t *)(uintptr_t)(data + rec->dtrd_offset);
+
+ switch (rec->dtrd_action) {
+ case DTRACEAGG_LQUANTIZE:
+ /*
+ * For lquantize(), we always display the entire range
+ * of the aggregation when aggpack is set.
+ */
+ start = 1;
+ minbin = start;
+ maxbin = size - 1 - start;
+ break;
+
+ case DTRACEAGG_QUANTIZE:
+ for (i = start; i < size; i++) {
+ if (!addr[i])
+ continue;
+
+ if (minbin == -1)
+ minbin = i - start;
+
+ maxbin = i - start;
+ }
+
+ if (minbin == -1) {
+ /*
+ * If we have no data (e.g., due to a clear()
+ * or negative increments), we'll use the
+ * zero bucket as both our min and max.
+ */
+ minbin = maxbin = DTRACE_QUANTIZE_ZEROBUCKET;
+ }
+
+ break;
+
+ default:
+ continue;
+ }
+
+ if (minmax[agg->dtagd_varid] == NULL) {
+ minmax[agg->dtagd_varid] = aggdata;
+ aggdata->dtada_flags |= DTRACE_A_MINMAXBIN;
+ aggdata->dtada_minbin = minbin;
+ aggdata->dtada_maxbin = maxbin;
+ continue;
+ }
+
+ if (minbin < minmax[agg->dtagd_varid]->dtada_minbin)
+ minmax[agg->dtagd_varid]->dtada_minbin = minbin;
+
+ if (maxbin > minmax[agg->dtagd_varid]->dtada_maxbin)
+ minmax[agg->dtagd_varid]->dtada_maxbin = maxbin;
+ }
+
+ /*
+ * And now one final pass to set everyone's minbin and maxbin.
+ */
+ for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall) {
+ dtrace_aggdata_t *aggdata = &h->dtahe_data, *mm;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+
+ if ((mm = minmax[agg->dtagd_varid]) == NULL || aggdata == mm)
+ continue;
+
+ aggdata->dtada_minbin = mm->dtada_minbin;
+ aggdata->dtada_maxbin = mm->dtada_maxbin;
+ aggdata->dtada_flags |= DTRACE_A_MINMAXBIN;
+ }
+
+ dt_free(dtp, minmax);
+
+ return (0);
+}
+
+static int
dt_aggregate_walk_sorted(dtrace_hdl_t *dtp,
dtrace_aggregate_f *func, void *arg,
int (*sfunc)(const void *, const void *))
@@ -1309,6 +1534,23 @@ dt_aggregate_walk_sorted(dtrace_hdl_t *dtp,
dt_ahashent_t *h, **sorted;
dt_ahash_t *hash = &agp->dtat_hash;
size_t i, nentries = 0;
+ int rval = -1;
+
+ agp->dtat_flags &= ~(DTRACE_A_TOTAL | DTRACE_A_MINMAXBIN);
+
+ if (dtp->dt_options[DTRACEOPT_AGGHIST] != DTRACEOPT_UNSET) {
+ agp->dtat_flags |= DTRACE_A_TOTAL;
+
+ if (dt_aggregate_total(dtp, B_FALSE) != 0)
+ return (-1);
+ }
+
+ if (dtp->dt_options[DTRACEOPT_AGGPACK] != DTRACEOPT_UNSET) {
+ agp->dtat_flags |= DTRACE_A_MINMAXBIN;
+
+ if (dt_aggregate_minmaxbin(dtp, B_FALSE) != 0)
+ return (-1);
+ }
for (h = hash->dtah_all; h != NULL; h = h->dtahe_nextall)
nentries++;
@@ -1316,7 +1558,7 @@ dt_aggregate_walk_sorted(dtrace_hdl_t *dtp,
sorted = dt_alloc(dtp, nentries * sizeof (dt_ahashent_t *));
if (sorted == NULL)
- return (-1);
+ goto out;
for (h = hash->dtah_all, i = 0; h != NULL; h = h->dtahe_nextall)
sorted[i++] = h;
@@ -1340,14 +1582,20 @@ dt_aggregate_walk_sorted(dtrace_hdl_t *dtp,
for (i = 0; i < nentries; i++) {
h = sorted[i];
- if (dt_aggwalk_rval(dtp, h, func(&h->dtahe_data, arg)) == -1) {
- dt_free(dtp, sorted);
- return (-1);
- }
+ if (dt_aggwalk_rval(dtp, h, func(&h->dtahe_data, arg)) == -1)
+ goto out;
}
+ rval = 0;
+out:
+ if (agp->dtat_flags & DTRACE_A_TOTAL)
+ (void) dt_aggregate_total(dtp, B_TRUE);
+
+ if (agp->dtat_flags & DTRACE_A_MINMAXBIN)
+ (void) dt_aggregate_minmaxbin(dtp, B_TRUE);
+
dt_free(dtp, sorted);
- return (0);
+ return (rval);
}
int
@@ -1870,6 +2118,8 @@ dtrace_aggregate_print(dtrace_hdl_t *dtp, FILE *fp,
{
dt_print_aggdata_t pd;
+ bzero(&pd, sizeof (pd));
+
pd.dtpa_dtp = dtp;
pd.dtpa_fp = fp;
pd.dtpa_allunprint = 1;
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_as.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_as.c
index 457b8fd..f937261 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_as.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_as.c
@@ -23,8 +23,10 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
#include <sys/types.h>
#include <strings.h>
@@ -125,7 +127,7 @@ dt_copyvar(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
dvp->dtdv_flags |= DIFV_F_MOD;
bzero(&dn, sizeof (dn));
- dt_node_type_assign(&dn, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(&dn, idp->di_ctfp, idp->di_type, B_FALSE);
dt_node_diftype(pcb->pcb_hdl, &dn, &dvp->dtdv_type);
idp->di_flags &= ~(DT_IDFLG_DIFR | DT_IDFLG_DIFW);
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c
index 64b98c4..a19152e 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@@ -663,6 +663,8 @@ dt_action_printflike(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp,
static void
dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
{
+ int ctflib;
+
dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
boolean_t istrace = (dnp->dn_ident->di_id == DT_ACT_TRACE);
const char *act = istrace ? "trace" : "print";
@@ -694,7 +696,10 @@ dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
* like arrays and function pointers that can't be resolved by
* ctf_type_lookup(). This is later processed by dtrace_dof_create()
* and turned into a reference into the string table so that we can
- * get the type information when we process the data after the fact.
+ * get the type information when we process the data after the fact. In
+ * the case where we are referring to userland CTF data, we also need to
+ * to identify which ctf container in question we care about and encode
+ * that within the name.
*/
if (dnp->dn_ident->di_id == DT_ACT_PRINT) {
dt_node_t *dret;
@@ -705,11 +710,27 @@ dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
n = snprintf(NULL, 0, "%s`%ld", dmp->dm_name, dret->dn_type) + 1;
+ if (dmp->dm_pid != 0) {
+ ctflib = dt_module_getlibid(dtp, dmp, dret->dn_ctfp);
+ assert(ctflib >= 0);
+ n = snprintf(NULL, 0, "%s`%d`%ld", dmp->dm_name,
+ ctflib, dret->dn_type) + 1;
+ } else {
+ n = snprintf(NULL, 0, "%s`%ld", dmp->dm_name,
+ dret->dn_type) + 1;
+ }
sdp->dtsd_strdata = dt_alloc(dtp, n);
if (sdp->dtsd_strdata == NULL)
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
(void) snprintf(sdp->dtsd_strdata, n, "%s`%ld", dmp->dm_name,
dret->dn_type);
+ if (dmp->dm_pid != 0) {
+ (void) snprintf(sdp->dtsd_strdata, n, "%s`%d`%ld",
+ dmp->dm_name, ctflib, dret->dn_type);
+ } else {
+ (void) snprintf(sdp->dtsd_strdata, n, "%s`%ld",
+ dmp->dm_name, dret->dn_type);
+ }
}
ap->dtad_difo = dt_as(yypcb);
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c
index 8d9e494..ae1ed00 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c
@@ -24,7 +24,7 @@
*/
/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@@ -59,6 +59,25 @@ dt_fabsl(long double x)
return (x);
}
+static int
+dt_ndigits(long long val)
+{
+ int rval = 1;
+ long long cmp = 10;
+
+ if (val < 0) {
+ val = val == INT64_MIN ? INT64_MAX : -val;
+ rval++;
+ }
+
+ while (val > cmp && cmp > 0) {
+ rval++;
+ cmp *= 10;
+ }
+
+ return (rval < 4 ? 4 : rval);
+}
+
/*
* 128-bit arithmetic functions needed to support the stddev() aggregating
* action.
@@ -487,7 +506,125 @@ dt_nullrec()
return (DTRACE_CONSUME_NEXT);
}
-int
+static void
+dt_quantize_total(dtrace_hdl_t *dtp, int64_t datum, long double *total)
+{
+ long double val = dt_fabsl((long double)datum);
+
+ if (dtp->dt_options[DTRACEOPT_AGGZOOM] == DTRACEOPT_UNSET) {
+ *total += val;
+ return;
+ }
+
+ /*
+ * If we're zooming in on an aggregation, we want the height of the
+ * highest value to be approximately 95% of total bar height -- so we
+ * adjust up by the reciprocal of DTRACE_AGGZOOM_MAX when comparing to
+ * our highest value.
+ */
+ val *= 1 / DTRACE_AGGZOOM_MAX;
+
+ if (*total < val)
+ *total = val;
+}
+
+static int
+dt_print_quanthdr(dtrace_hdl_t *dtp, FILE *fp, int width)
+{
+ return (dt_printf(dtp, fp, "\n%*s %41s %-9s\n",
+ width ? width : 16, width ? "key" : "value",
+ "------------- Distribution -------------", "count"));
+}
+
+static int
+dt_print_quanthdr_packed(dtrace_hdl_t *dtp, FILE *fp, int width,
+ const dtrace_aggdata_t *aggdata, dtrace_actkind_t action)
+{
+ int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin;
+ int minwidth, maxwidth, i;
+
+ assert(action == DTRACEAGG_QUANTIZE || action == DTRACEAGG_LQUANTIZE);
+
+ if (action == DTRACEAGG_QUANTIZE) {
+ if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
+ min--;
+
+ if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
+ max++;
+
+ minwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(min));
+ maxwidth = dt_ndigits(DTRACE_QUANTIZE_BUCKETVAL(max));
+ } else {
+ maxwidth = 8;
+ minwidth = maxwidth - 1;
+ max++;
+ }
+
+ if (dt_printf(dtp, fp, "\n%*s %*s .",
+ width, width > 0 ? "key" : "", minwidth, "min") < 0)
+ return (-1);
+
+ for (i = min; i <= max; i++) {
+ if (dt_printf(dtp, fp, "-") < 0)
+ return (-1);
+ }
+
+ return (dt_printf(dtp, fp, ". %*s | count\n", -maxwidth, "max"));
+}
+
+/*
+ * We use a subset of the Unicode Block Elements (U+2588 through U+258F,
+ * inclusive) to represent aggregations via UTF-8 -- which are expressed via
+ * 3-byte UTF-8 sequences.
+ */
+#define DTRACE_AGGUTF8_FULL 0x2588
+#define DTRACE_AGGUTF8_BASE 0x258f
+#define DTRACE_AGGUTF8_LEVELS 8
+
+#define DTRACE_AGGUTF8_BYTE0(val) (0xe0 | ((val) >> 12))
+#define DTRACE_AGGUTF8_BYTE1(val) (0x80 | (((val) >> 6) & 0x3f))
+#define DTRACE_AGGUTF8_BYTE2(val) (0x80 | ((val) & 0x3f))
+
+static int
+dt_print_quantline_utf8(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
+ uint64_t normal, long double total)
+{
+ uint_t len = 40, i, whole, partial;
+ long double f = (dt_fabsl((long double)val) * len) / total;
+ const char *spaces = " ";
+
+ whole = (uint_t)f;
+ partial = (uint_t)((f - (long double)(uint_t)f) *
+ (long double)DTRACE_AGGUTF8_LEVELS);
+
+ if (dt_printf(dtp, fp, "|") < 0)
+ return (-1);
+
+ for (i = 0; i < whole; i++) {
+ if (dt_printf(dtp, fp, "%c%c%c",
+ DTRACE_AGGUTF8_BYTE0(DTRACE_AGGUTF8_FULL),
+ DTRACE_AGGUTF8_BYTE1(DTRACE_AGGUTF8_FULL),
+ DTRACE_AGGUTF8_BYTE2(DTRACE_AGGUTF8_FULL)) < 0)
+ return (-1);
+ }
+
+ if (partial != 0) {
+ partial = DTRACE_AGGUTF8_BASE - (partial - 1);
+
+ if (dt_printf(dtp, fp, "%c%c%c",
+ DTRACE_AGGUTF8_BYTE0(partial),
+ DTRACE_AGGUTF8_BYTE1(partial),
+ DTRACE_AGGUTF8_BYTE2(partial)) < 0)
+ return (-1);
+
+ i++;
+ }
+
+ return (dt_printf(dtp, fp, "%s %-9lld\n", spaces + i,
+ (long long)val / normal));
+}
+
+static int
dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
uint64_t normal, long double total, char positives, char negatives)
{
@@ -505,6 +642,11 @@ dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
if (!negatives) {
if (positives) {
+ if (dtp->dt_encoding == DT_ENCODING_UTF8) {
+ return (dt_print_quantline_utf8(dtp, fp, val,
+ normal, total));
+ }
+
f = (dt_fabsl((long double)val) * len) / total;
depth = (uint_t)(f + 0.5);
} else {
@@ -547,6 +689,73 @@ dt_print_quantline(dtrace_hdl_t *dtp, FILE *fp, int64_t val,
}
}
+/*
+ * As with UTF-8 printing of aggregations, we use a subset of the Unicode
+ * Block Elements (U+2581 through U+2588, inclusive) to represent our packed
+ * aggregation.
+ */
+#define DTRACE_AGGPACK_BASE 0x2581
+#define DTRACE_AGGPACK_LEVELS 8
+
+static int
+dt_print_packed(dtrace_hdl_t *dtp, FILE *fp,
+ long double datum, long double total)
+{
+ static boolean_t utf8_checked = B_FALSE;
+ static boolean_t utf8;
+ char *ascii = "__xxxxXX";
+ char *neg = "vvvvVV";
+ unsigned int len;
+ long double val;
+
+ if (!utf8_checked) {
+ char *term;
+
+ /*
+ * We want to determine if we can reasonably emit UTF-8 for our
+ * packed aggregation. To do this, we will check for terminals
+ * that are known to be primitive to emit UTF-8 on these.
+ */
+ utf8_checked = B_TRUE;
+
+ if (dtp->dt_encoding == DT_ENCODING_ASCII) {
+ utf8 = B_FALSE;
+ } else if (dtp->dt_encoding == DT_ENCODING_UTF8) {
+ utf8 = B_TRUE;
+ } else if ((term = getenv("TERM")) != NULL &&
+ (strcmp(term, "sun") == 0 ||
+ strcmp(term, "sun-color") == 0) ||
+ strcmp(term, "dumb") == 0) {
+ utf8 = B_FALSE;
+ } else {
+ utf8 = B_TRUE;
+ }
+ }
+
+ if (datum == 0)
+ return (dt_printf(dtp, fp, " "));
+
+ if (datum < 0) {
+ len = strlen(neg);
+ val = dt_fabsl(datum * (len - 1)) / total;
+ return (dt_printf(dtp, fp, "%c", neg[(uint_t)(val + 0.5)]));
+ }
+
+ if (utf8) {
+ int block = DTRACE_AGGPACK_BASE + (unsigned int)(((datum *
+ (DTRACE_AGGPACK_LEVELS - 1)) / total) + 0.5);
+
+ return (dt_printf(dtp, fp, "%c%c%c",
+ DTRACE_AGGUTF8_BYTE0(block),
+ DTRACE_AGGUTF8_BYTE1(block),
+ DTRACE_AGGUTF8_BYTE2(block)));
+ }
+
+ len = strlen(ascii);
+ val = (datum * (len - 1)) / total;
+ return (dt_printf(dtp, fp, "%c", ascii[(uint_t)(val + 0.5)]));
+}
+
int
dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
size_t size, uint64_t normal)
@@ -564,9 +773,9 @@ dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
if (first_bin == DTRACE_QUANTIZE_NBUCKETS - 1) {
/*
- * There isn't any data. This is possible if (and only if)
- * negative increment values have been used. In this case,
- * we'll print the buckets around 0.
+ * There isn't any data. This is possible if the aggregation
+ * has been clear()'d or if negative increment values have been
+ * used. Regardless, we'll print the buckets around 0.
*/
first_bin = DTRACE_QUANTIZE_ZEROBUCKET - 1;
last_bin = DTRACE_QUANTIZE_ZEROBUCKET + 1;
@@ -584,11 +793,10 @@ dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
for (i = first_bin; i <= last_bin; i++) {
positives |= (data[i] > 0);
negatives |= (data[i] < 0);
- total += dt_fabsl((long double)data[i]);
+ dt_quantize_total(dtp, data[i], &total);
}
- if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
- "------------- Distribution -------------", "count") < 0)
+ if (dt_print_quanthdr(dtp, fp, 0) < 0)
return (-1);
for (i = first_bin; i <= last_bin; i++) {
@@ -605,6 +813,48 @@ dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
}
int
+dt_print_quantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
+ size_t size, const dtrace_aggdata_t *aggdata)
+{
+ const int64_t *data = addr;
+ long double total = 0, count = 0;
+ int min = aggdata->dtada_minbin, max = aggdata->dtada_maxbin, i;
+ int64_t minval, maxval;
+
+ if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t))
+ return (dt_set_errno(dtp, EDT_DMISMATCH));
+
+ if (min != 0 && min != DTRACE_QUANTIZE_ZEROBUCKET)
+ min--;
+
+ if (max < DTRACE_QUANTIZE_NBUCKETS - 1)
+ max++;
+
+ minval = DTRACE_QUANTIZE_BUCKETVAL(min);
+ maxval = DTRACE_QUANTIZE_BUCKETVAL(max);
+
+ if (dt_printf(dtp, fp, " %*lld :", dt_ndigits(minval),
+ (long long)minval) < 0)
+ return (-1);
+
+ for (i = min; i <= max; i++) {
+ dt_quantize_total(dtp, data[i], &total);
+ count += data[i];
+ }
+
+ for (i = min; i <= max; i++) {
+ if (dt_print_packed(dtp, fp, data[i], total) < 0)
+ return (-1);
+ }
+
+ if (dt_printf(dtp, fp, ": %*lld | %lld\n",
+ -dt_ndigits(maxval), (long long)maxval, (long long)count) < 0)
+ return (-1);
+
+ return (0);
+}
+
+int
dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
size_t size, uint64_t normal)
{
@@ -651,7 +901,7 @@ dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
for (i = first_bin; i <= last_bin; i++) {
positives |= (data[i] > 0);
negatives |= (data[i] < 0);
- total += dt_fabsl((long double)data[i]);
+ dt_quantize_total(dtp, data[i], &total);
}
if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
@@ -663,8 +913,7 @@ dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
int err;
if (i == 0) {
- (void) snprintf(c, sizeof (c), "< %d",
- base / (uint32_t)normal);
+ (void) snprintf(c, sizeof (c), "< %d", base);
err = dt_printf(dtp, fp, "%16s ", c);
} else if (i == levels + 1) {
(void) snprintf(c, sizeof (c), ">= %d",
@@ -683,6 +932,59 @@ dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
return (0);
}
+/*ARGSUSED*/
+int
+dt_print_lquantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
+ size_t size, const dtrace_aggdata_t *aggdata)
+{
+ const int64_t *data = addr;
+ long double total = 0, count = 0;
+ int min, max, base, err;
+ uint64_t arg;
+ uint16_t step, levels;
+ char c[32];
+ unsigned int i;
+
+ if (size < sizeof (uint64_t))
+ return (dt_set_errno(dtp, EDT_DMISMATCH));
+
+ arg = *data++;
+ size -= sizeof (uint64_t);
+
+ base = DTRACE_LQUANTIZE_BASE(arg);
+ step = DTRACE_LQUANTIZE_STEP(arg);
+ levels = DTRACE_LQUANTIZE_LEVELS(arg);
+
+ if (size != sizeof (uint64_t) * (levels + 2))
+ return (dt_set_errno(dtp, EDT_DMISMATCH));
+
+ min = 0;
+ max = levels + 1;
+
+ if (min == 0) {
+ (void) snprintf(c, sizeof (c), "< %d", base);
+ err = dt_printf(dtp, fp, "%8s :", c);
+ } else {
+ err = dt_printf(dtp, fp, "%8d :", base + (min - 1) * step);
+ }
+
+ if (err < 0)
+ return (-1);
+
+ for (i = min; i <= max; i++) {
+ dt_quantize_total(dtp, data[i], &total);
+ count += data[i];
+ }
+
+ for (i = min; i <= max; i++) {
+ if (dt_print_packed(dtp, fp, data[i], total) < 0)
+ return (-1);
+ }
+
+ (void) snprintf(c, sizeof (c), ">= %d", base + (levels * step));
+ return (dt_printf(dtp, fp, ": %-8s | %lld\n", c, (long long)count));
+}
+
int
dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
size_t size, uint64_t normal)
@@ -740,7 +1042,7 @@ dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr,
for (i = first_bin; i <= last_bin; i++) {
positives |= (data[i] > 0);
negatives |= (data[i] < 0);
- total += dt_fabsl((long double)data[i]);
+ dt_quantize_total(dtp, data[i], &total);
}
if (dt_printf(dtp, fp, "\n%16s %41s %-9s\n", "value",
@@ -823,7 +1125,7 @@ dt_print_stddev(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
}
/*ARGSUSED*/
-int
+static int
dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
size_t nbytes, int width, int quiet, int forceraw)
{
@@ -876,10 +1178,12 @@ dt_print_bytes(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr,
if (j != nbytes)
break;
- if (quiet)
+ if (quiet) {
return (dt_printf(dtp, fp, "%s", c));
- else
- return (dt_printf(dtp, fp, " %-*s", width, c));
+ } else {
+ return (dt_printf(dtp, fp, " %s%*s",
+ width < 0 ? " " : "", width, c));
+ }
}
break;
@@ -1793,10 +2097,83 @@ dt_trunc(dtrace_hdl_t *dtp, caddr_t base, dtrace_recdesc_t *rec)
static int
dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
- caddr_t addr, size_t size, uint64_t normal)
+ caddr_t addr, size_t size, const dtrace_aggdata_t *aggdata,
+ uint64_t normal, dt_print_aggdata_t *pd)
{
- int err;
+ int err, width;
dtrace_actkind_t act = rec->dtrd_action;
+ boolean_t packed = pd->dtpa_agghist || pd->dtpa_aggpack;
+ dtrace_aggdesc_t *agg = aggdata->dtada_desc;
+
+ static struct {
+ size_t size;
+ int width;
+ int packedwidth;
+ } *fmt, fmttab[] = {
+ { sizeof (uint8_t), 3, 3 },
+ { sizeof (uint16_t), 5, 5 },
+ { sizeof (uint32_t), 8, 8 },
+ { sizeof (uint64_t), 16, 16 },
+ { 0, -50, 16 }
+ };
+
+ if (packed && pd->dtpa_agghisthdr != agg->dtagd_varid) {
+ dtrace_recdesc_t *r;
+
+ width = 0;
+
+ /*
+ * To print our quantization header for either an agghist or
+ * aggpack aggregation, we need to iterate through all of our
+ * of our records to determine their width.
+ */
+ for (r = rec; !DTRACEACT_ISAGG(r->dtrd_action); r++) {
+ for (fmt = fmttab; fmt->size &&
+ fmt->size != r->dtrd_size; fmt++)
+ continue;
+
+ width += fmt->packedwidth + 1;
+ }
+
+ if (pd->dtpa_agghist) {
+ if (dt_print_quanthdr(dtp, fp, width) < 0)
+ return (-1);
+ } else {
+ if (dt_print_quanthdr_packed(dtp, fp,
+ width, aggdata, r->dtrd_action) < 0)
+ return (-1);
+ }
+
+ pd->dtpa_agghisthdr = agg->dtagd_varid;
+ }
+
+ if (pd->dtpa_agghist && DTRACEACT_ISAGG(act)) {
+ char positives = aggdata->dtada_flags & DTRACE_A_HASPOSITIVES;
+ char negatives = aggdata->dtada_flags & DTRACE_A_HASNEGATIVES;
+ int64_t val;
+
+ assert(act == DTRACEAGG_SUM || act == DTRACEAGG_COUNT);
+ val = (long long)*((uint64_t *)addr);
+
+ if (dt_printf(dtp, fp, " ") < 0)
+ return (-1);
+
+ return (dt_print_quantline(dtp, fp, val, normal,
+ aggdata->dtada_total, positives, negatives));
+ }
+
+ if (pd->dtpa_aggpack && DTRACEACT_ISAGG(act)) {
+ switch (act) {
+ case DTRACEAGG_QUANTIZE:
+ return (dt_print_quantize_packed(dtp,
+ fp, addr, size, aggdata));
+ case DTRACEAGG_LQUANTIZE:
+ return (dt_print_lquantize_packed(dtp,
+ fp, addr, size, aggdata));
+ default:
+ break;
+ }
+ }
switch (act) {
case DTRACEACT_STACK:
@@ -1839,28 +2216,33 @@ dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec,
break;
}
+ for (fmt = fmttab; fmt->size && fmt->size != size; fmt++)
+ continue;
+
+ width = packed ? fmt->packedwidth : fmt->width;
+
switch (size) {
case sizeof (uint64_t):
- err = dt_printf(dtp, fp, " %16lld",
+ err = dt_printf(dtp, fp, " %*lld", width,
/* LINTED - alignment */
(long long)*((uint64_t *)addr) / normal);
break;
case sizeof (uint32_t):
/* LINTED - alignment */
- err = dt_printf(dtp, fp, " %8d", *((uint32_t *)addr) /
+ err = dt_printf(dtp, fp, " %*d", width, *((uint32_t *)addr) /
(uint32_t)normal);
break;
case sizeof (uint16_t):
/* LINTED - alignment */
- err = dt_printf(dtp, fp, " %5d", *((uint16_t *)addr) /
+ err = dt_printf(dtp, fp, " %*d", width, *((uint16_t *)addr) /
(uint32_t)normal);
break;
case sizeof (uint8_t):
- err = dt_printf(dtp, fp, " %3d", *((uint8_t *)addr) /
+ err = dt_printf(dtp, fp, " %*d", width, *((uint8_t *)addr) /
(uint32_t)normal);
break;
default:
- err = dt_print_bytes(dtp, fp, addr, size, 50, 0, 0);
+ err = dt_print_bytes(dtp, fp, addr, size, width, 0, 0);
break;
}
@@ -1881,6 +2263,9 @@ dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
caddr_t addr;
size_t size;
+ pd->dtpa_agghist = (aggdata->dtada_flags & DTRACE_A_TOTAL);
+ pd->dtpa_aggpack = (aggdata->dtada_flags & DTRACE_A_MINMAXBIN);
+
/*
* Iterate over each record description in the key, printing the traced
* data, skipping the first datum (the tuple member created by the
@@ -1897,7 +2282,8 @@ dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
break;
}
- if (dt_print_datum(dtp, fp, rec, addr, size, 1) < 0)
+ if (dt_print_datum(dtp, fp, rec, addr,
+ size, aggdata, 1, pd) < 0)
return (-1);
if (dt_buffered_flush(dtp, NULL, rec, aggdata,
@@ -1920,7 +2306,8 @@ dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
assert(DTRACEACT_ISAGG(act));
normal = aggdata->dtada_normal;
- if (dt_print_datum(dtp, fp, rec, addr, size, normal) < 0)
+ if (dt_print_datum(dtp, fp, rec, addr,
+ size, aggdata, normal, pd) < 0)
return (-1);
if (dt_buffered_flush(dtp, NULL, rec, aggdata,
@@ -1931,8 +2318,10 @@ dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg)
agg->dtagd_flags |= DTRACE_AGD_PRINTED;
}
- if (dt_printf(dtp, fp, "\n") < 0)
- return (-1);
+ if (!pd->dtpa_agghist && !pd->dtpa_aggpack) {
+ if (dt_printf(dtp, fp, "\n") < 0)
+ return (-1);
+ }
if (dt_buffered_flush(dtp, NULL, NULL, aggdata,
DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0)
@@ -2401,7 +2790,7 @@ nofmt:
}
n = dt_print_bytes(dtp, fp, addr,
- tracememsize, 33, quiet, 1);
+ tracememsize, -33, quiet, 1);
tracememsize = 0;
@@ -2434,7 +2823,7 @@ nofmt:
break;
default:
n = dt_print_bytes(dtp, fp, addr,
- rec->dtrd_size, 33, quiet, 0);
+ rec->dtrd_size, -33, quiet, 0);
break;
}
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.c
index 871fdd5..d717d56 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.c
@@ -21,7 +21,8 @@
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -779,7 +780,7 @@ dt_decl_enumerator(char *s, dt_node_t *dnp)
yyintdecimal = 0;
dnp = dt_node_int(value);
- dt_node_type_assign(dnp, dsp->ds_ctfp, dsp->ds_type);
+ dt_node_type_assign(dnp, dsp->ds_ctfp, dsp->ds_type, B_FALSE);
if ((inp = malloc(sizeof (dt_idnode_t))) == NULL)
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
@@ -821,6 +822,8 @@ dt_decl_type(dt_decl_t *ddp, dtrace_typeinfo_t *tip)
char *name;
int rv;
+ tip->dtt_flags = 0;
+
/*
* Based on our current #include depth and decl stack depth, determine
* which dynamic CTF module and scope to use when adding any new types.
@@ -828,6 +831,9 @@ dt_decl_type(dt_decl_t *ddp, dtrace_typeinfo_t *tip)
dmp = yypcb->pcb_idepth ? dtp->dt_cdefs : dtp->dt_ddefs;
flag = yypcb->pcb_dstack.ds_next ? CTF_ADD_NONROOT : CTF_ADD_ROOT;
+ if (ddp->dd_attr & DT_DA_USER)
+ tip->dtt_flags = DTT_FL_USER;
+
/*
* If we have already cached a CTF type for this decl, then we just
* return the type information for the cached type.
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.h
index 2933155..d322875 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.h
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_decl.h
@@ -23,12 +23,14 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
#ifndef _DT_DECL_H
#define _DT_DECL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <libctf.h>
#include <dtrace.h>
@@ -59,6 +61,7 @@ typedef struct dt_decl {
#define DT_DA_RESTRICT 0x0040 /* qualify type as restrict */
#define DT_DA_VOLATILE 0x0080 /* qualify type as volatile */
#define DT_DA_PAREN 0x0100 /* parenthesis tag */
+#define DT_DA_USER 0x0200 /* user-land type specifier */
typedef enum dt_dclass {
DT_DC_DEFAULT, /* no storage class specified */
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dis.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dis.c
index fff4235..c0af364 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dis.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_dis.c
@@ -26,7 +26,8 @@
*/
/*
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
*/
#include <strings.h>
@@ -312,9 +313,10 @@ dt_dis_typestr(const dtrace_diftype_t *t, char *buf, size_t len)
(void) snprintf(ckind, sizeof (ckind), "0x%x", t->dtdt_ckind);
}
- if (t->dtdt_flags & DIF_TF_BYREF) {
- (void) snprintf(buf, len, "%s (%s) by ref (size %lu)",
- kind, ckind, (ulong_t)t->dtdt_size);
+ if (t->dtdt_flags & (DIF_TF_BYREF | DIF_TF_BYUREF)) {
+ (void) snprintf(buf, len, "%s (%s) by %sref (size %lu)",
+ kind, ckind, (t->dtdt_flags & DIF_TF_BYUREF) ? "user " : "",
+ (ulong_t)t->dtdt_size);
} else {
(void) snprintf(buf, len, "%s (%s) (size %lu)",
kind, ckind, (ulong_t)t->dtdt_size);
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_error.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_error.c
index d8dbbabb..2327ff7 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_error.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_error.c
@@ -111,7 +111,8 @@ static const struct {
{ EDT_BADAGGVAR, "Invalid aggregation variable identifier" },
{ EDT_OVERSION, "Client requested deprecated version of library" },
{ EDT_ENABLING_ERR, "Failed to enable probe" },
- { EDT_NOPROBES, "No probe sites found for declared provider" }
+ { EDT_NOPROBES, "No probe sites found for declared provider" },
+ { EDT_CANTLOAD, "Failed to load module" },
};
static const int _dt_nerr = sizeof (_dt_errlist) / sizeof (_dt_errlist[0]);
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y
index 0c12623..07790f4 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_grammar.y
@@ -23,8 +23,10 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <dt_impl.h>
@@ -102,6 +104,7 @@
%token DT_KEY_TYPEDEF
%token DT_KEY_UNION
%token DT_KEY_UNSIGNED
+%token DT_KEY_USERLAND
%token DT_KEY_VOID
%token DT_KEY_VOLATILE
%token DT_KEY_WHILE
@@ -633,6 +636,7 @@ type_specifier: DT_KEY_VOID { $$ = dt_decl_spec(CTF_K_INTEGER, DUP("void")); }
| DT_KEY_DOUBLE { $$ = dt_decl_spec(CTF_K_FLOAT, DUP("double")); }
| DT_KEY_SIGNED { $$ = dt_decl_attr(DT_DA_SIGNED); }
| DT_KEY_UNSIGNED { $$ = dt_decl_attr(DT_DA_UNSIGNED); }
+ | DT_KEY_USERLAND { $$ = dt_decl_attr(DT_DA_USER); }
| DT_KEY_STRING {
$$ = dt_decl_spec(CTF_K_TYPEDEF, DUP("string"));
}
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_ident.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_ident.c
index 13adbb4..5a2f0e4 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_ident.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_ident.c
@@ -22,6 +22,8 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -104,7 +106,7 @@ dt_idcook_sign(dt_node_t *dnp, dt_ident_t *idp,
}
}
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
}
/*
@@ -163,7 +165,7 @@ dt_idcook_assc(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
if (argc != 0)
isp->dis_args[argc - 1].dn_list = NULL;
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
} else {
dt_idcook_sign(dnp, idp, argc, args,
@@ -304,7 +306,7 @@ dt_idcook_func(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
}
dt_node_type_assign(&isp->dis_args[i],
- dtt.dtt_ctfp, dtt.dtt_type);
+ dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
}
}
@@ -391,7 +393,9 @@ dt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
dt_node_type_assign(dnp,
prp->pr_argv[ap->dn_value].dtt_ctfp,
- prp->pr_argv[ap->dn_value].dtt_type);
+ prp->pr_argv[ap->dn_value].dtt_type,
+ prp->pr_argv[ap->dn_value].dtt_flags & DTT_FL_USER ?
+ B_TRUE : B_FALSE);
} else if ((dxp = dt_xlator_lookup(dtp,
nnp, xnp, DT_XLATE_FUZZY)) != NULL || (
@@ -419,7 +423,8 @@ dt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
dnp->dn_ident->di_ctfp = xidp->di_ctfp;
dnp->dn_ident->di_type = xidp->di_type;
- dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
+ B_FALSE);
} else {
xyerror(D_ARGS_XLATOR, "translator for %s[%lld] from %s to %s "
@@ -465,7 +470,7 @@ dt_idcook_regs(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
idp->di_ctfp = dtt.dtt_ctfp;
idp->di_type = dtt.dtt_type;
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
}
/*ARGSUSED*/
@@ -487,7 +492,7 @@ dt_idcook_type(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
idp->di_type = dtt.dtt_type;
}
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
}
/*ARGSUSED*/
@@ -495,7 +500,7 @@ static void
dt_idcook_thaw(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
{
if (idp->di_ctfp != NULL && idp->di_type != CTF_ERR)
- dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
}
static void
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
index 2bae220..b7abbc2 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
@@ -146,6 +146,10 @@ typedef struct dt_module {
caddr_t dm_reloc_offset; /* Symbol relocation offset. */
uintptr_t *dm_sec_offsets;
#endif
+ pid_t dm_pid; /* pid for this module */
+ uint_t dm_nctflibs; /* number of ctf children libraries */
+ ctf_file_t **dm_libctfp; /* process library ctf pointers */
+ char **dm_libctfn; /* names of process ctf containers */
} dt_module_t;
#define DT_DM_LOADED 0x1 /* module symbol and type data is loaded */
@@ -189,6 +193,9 @@ typedef struct dt_print_aggdata {
dtrace_aggvarid_t dtpa_id; /* aggregation variable of interest */
FILE *dtpa_fp; /* file pointer */
int dtpa_allunprint; /* print only unprinted aggregations */
+ int dtpa_agghist; /* print aggregation as histogram */
+ int dtpa_agghisthdr; /* aggregation histogram hdr printed */
+ int dtpa_aggpack; /* pack quantized aggregations */
} dt_print_aggdata_t;
typedef struct dt_dirpath {
@@ -283,6 +290,7 @@ struct dtrace_hdl {
uint_t dt_linktype; /* dtrace link output file type (see below) */
uint_t dt_xlatemode; /* dtrace translator linking mode (see below) */
uint_t dt_stdcmode; /* dtrace stdc compatibility mode (see below) */
+ uint_t dt_encoding; /* dtrace output encoding (see below) */
uint_t dt_treedump; /* dtrace tree debug bitmap (see below) */
uint64_t dt_options[DTRACEOPT_MAX]; /* dtrace run-time options */
int dt_version; /* library version requested by client */
@@ -374,6 +382,14 @@ struct dtrace_hdl {
#define DT_STDC_XT 3 /* ISO C + K&R C compat with ISO: __STDC__=0 */
/*
+ * Values for the dt_encoding property, which is used to force a particular
+ * character encoding (overriding default behavior and/or automatic detection).
+ */
+#define DT_ENCODING_UNSET 0
+#define DT_ENCODING_ASCII 1
+#define DT_ENCODING_UTF8 2
+
+/*
* Macro to test whether a given pass bit is set in the dt_treedump bit-vector.
* If the bit for pass 'p' is set, the D compiler displays the parse tree for
* the program by printing it to stderr at the end of compiler pass 'p'.
@@ -536,7 +552,8 @@ enum {
EDT_BADAGGVAR, /* invalid aggregation variable identifier */
EDT_OVERSION, /* client is requesting deprecated version */
EDT_ENABLING_ERR, /* failed to enable probe */
- EDT_NOPROBES /* no probes sites for declared provider */
+ EDT_NOPROBES, /* no probes sites for declared provider */
+ EDT_CANTLOAD /* failed to load a module */
};
/*
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l
index b31933e..032d303 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l
@@ -23,6 +23,10 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <string.h>
#include <stdlib.h>
@@ -93,13 +97,17 @@ static void unput(int);
%}
%e 1500 /* maximum nodes */
-%p 3700 /* maximum positions */
+%p 4900 /* maximum positions */
%n 600 /* maximum states */
+%a 3000 /* maximum transitions */
%s S0 S1 S2 S3 S4
RGX_AGG "@"[a-zA-Z_][0-9a-zA-Z_]*
RGX_PSPEC [-$:a-zA-Z_.?*\\\[\]!][-$:0-9a-zA-Z_.`?*\\\[\]!]*
+RGX_ALTIDENT [a-zA-Z_][0-9a-zA-Z_]*
+RGX_LMID LM[0-9a-fA-F]+`
+RGX_MOD_IDENT [a-zA-Z_`][0-9a-z.A-Z_`]*`
RGX_IDENT [a-zA-Z_`][0-9a-zA-Z_`]*
RGX_INT ([0-9]+|0[xX][0-9A-Fa-f]+)[uU]?[lL]?[lL]?
RGX_FP ([0-9]+("."?)[0-9]*|"."[0-9]+)((e|E)("+"|-)?[0-9]+)?[fFlL]?
@@ -169,6 +177,7 @@ if (yypcb->pcb_token != 0) {
<S0>typedef return (DT_KEY_TYPEDEF);
<S0>union return (DT_KEY_UNION);
<S0>unsigned return (DT_KEY_UNSIGNED);
+<S0>userland return (DT_KEY_USERLAND);
<S0>void return (DT_KEY_VOID);
<S0>volatile return (DT_KEY_VOLATILE);
<S0>while return (DT_KEY_WHILE);
@@ -347,7 +356,9 @@ if (yypcb->pcb_token != 0) {
return (DT_TOK_INT);
}
-<S0>{RGX_IDENT} {
+<S0>{RGX_IDENT} |
+<S0>{RGX_MOD_IDENT}{RGX_IDENT} |
+<S0>{RGX_MOD_IDENT} {
return (id_or_type(yytext));
}
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
index 497faa9..e3905c1 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
@@ -22,6 +22,9 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <sys/types.h>
#if defined(sun)
@@ -50,6 +53,7 @@
#include <dirent.h>
#if !defined(sun)
#include <fcntl.h>
+#include <libproc_compat.h>
#endif
#include <dt_strtab.h>
@@ -462,6 +466,9 @@ static const dt_modops_t dt_modops_64 = {
dt_module_t *
dt_module_create(dtrace_hdl_t *dtp, const char *name)
{
+ long pid;
+ char *eptr;
+ dt_ident_t *idp;
uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_modbuckets;
dt_module_t *dmp;
@@ -485,6 +492,32 @@ dt_module_create(dtrace_hdl_t *dtp, const char *name)
else
dmp->dm_ops = &dt_modops_32;
+ /*
+ * Modules for userland processes are special. They always refer to a
+ * specific process and have a copy of their CTF data from a specific
+ * instant in time. Any dt_module_t that begins with 'pid' is a module
+ * for a specific process, much like how any probe description that
+ * begins with 'pid' is special. pid123 refers to process 123. A module
+ * that is just 'pid' refers specifically to pid$target. This is
+ * generally done as D does not currently allow for macros to be
+ * evaluated when working with types.
+ */
+ if (strncmp(dmp->dm_name, "pid", 3) == 0) {
+ errno = 0;
+ if (dmp->dm_name[3] == '\0') {
+ idp = dt_idhash_lookup(dtp->dt_macros, "target");
+ if (idp != NULL && idp->di_id != 0)
+ dmp->dm_pid = idp->di_id;
+ } else {
+ pid = strtol(dmp->dm_name + 3, &eptr, 10);
+ if (errno == 0 && *eptr == '\0')
+ dmp->dm_pid = (pid_t)pid;
+ else
+ dt_dprintf("encountered malformed pid "
+ "module: %s\n", dmp->dm_name);
+ }
+ }
+
return (dmp);
}
@@ -554,12 +587,169 @@ dt_module_load_sect(dtrace_hdl_t *dtp, dt_module_t *dmp, ctf_sect_t *ctsp)
return (0);
}
+typedef struct dt_module_cb_arg {
+ struct ps_prochandle *dpa_proc;
+ dtrace_hdl_t *dpa_dtp;
+ dt_module_t *dpa_dmp;
+ uint_t dpa_count;
+} dt_module_cb_arg_t;
+
+/* ARGSUSED */
+static int
+dt_module_load_proc_count(void *arg, const prmap_t *prmap, const char *obj)
+{
+ ctf_file_t *fp;
+ dt_module_cb_arg_t *dcp = arg;
+
+ /* Try to grab a ctf container if it exists */
+ fp = Pname_to_ctf(dcp->dpa_proc, obj);
+ if (fp != NULL)
+ dcp->dpa_count++;
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+dt_module_load_proc_build(void *arg, const prmap_t *prmap, const char *obj)
+{
+ ctf_file_t *fp;
+ char buf[MAXPATHLEN], *p;
+ dt_module_cb_arg_t *dcp = arg;
+ int count = dcp->dpa_count;
+ Lmid_t lmid;
+
+ fp = Pname_to_ctf(dcp->dpa_proc, obj);
+ if (fp == NULL)
+ return (0);
+ fp = ctf_dup(fp);
+ if (fp == NULL)
+ return (0);
+ dcp->dpa_dmp->dm_libctfp[count] = fp;
+ /*
+ * While it'd be nice to simply use objname here, because of our prior
+ * actions we'll always get a resolved object name to its on disk file.
+ * Like the pid provider, we need to tell a bit of a lie here. The type
+ * that the user thinks of is in terms of the libraries they requested,
+ * eg. libc.so.1, they don't care about the fact that it's
+ * libc_hwcap.so.1.
+ */
+ (void) Pobjname(dcp->dpa_proc, prmap->pr_vaddr, buf, sizeof (buf));
+ if ((p = strrchr(buf, '/')) == NULL)
+ p = buf;
+ else
+ p++;
+
+ /*
+ * If for some reason we can't find a link map id for this module, which
+ * would be really quite weird. We instead just say the link map id is
+ * zero.
+ */
+ if (Plmid(dcp->dpa_proc, prmap->pr_vaddr, &lmid) != 0)
+ lmid = 0;
+
+ if (lmid == 0)
+ dcp->dpa_dmp->dm_libctfn[count] = strdup(p);
+ else
+ (void) asprintf(&dcp->dpa_dmp->dm_libctfn[count],
+ "LM%x`%s", lmid, p);
+ if (dcp->dpa_dmp->dm_libctfn[count] == NULL)
+ return (1);
+ ctf_setspecific(fp, dcp->dpa_dmp);
+ dcp->dpa_count++;
+ return (0);
+}
+
+/*
+ * We've been asked to load data that belongs to another process. As such we're
+ * going to pgrab it at this instant, load everything that we might ever care
+ * about, and then drive on. The reason for this is that the process that we're
+ * interested in might be changing. As long as we have grabbed it, then this
+ * can't be a problem for us.
+ *
+ * For now, we're actually going to punt on most things and just try to get CTF
+ * data, nothing else. Basically this is only useful as a source of type
+ * information, we can't go and do the stacktrace lookups, etc.
+ */
+static int
+dt_module_load_proc(dtrace_hdl_t *dtp, dt_module_t *dmp)
+{
+ struct ps_prochandle *p;
+ dt_module_cb_arg_t arg;
+
+ /*
+ * Note that on success we do not release this hold. We must hold this
+ * for our life time.
+ */
+ p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE);
+ if (p == NULL) {
+ dt_dprintf("failed to grab pid: %d\n", (int)dmp->dm_pid);
+ return (dt_set_errno(dtp, EDT_CANTLOAD));
+ }
+ dt_proc_lock(dtp, p);
+
+ arg.dpa_proc = p;
+ arg.dpa_dtp = dtp;
+ arg.dpa_dmp = dmp;
+ arg.dpa_count = 0;
+ if (Pobject_iter_resolved(p, dt_module_load_proc_count, &arg) != 0) {
+ dt_dprintf("failed to iterate objects\n");
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_CANTLOAD));
+ }
+
+ if (arg.dpa_count == 0) {
+ dt_dprintf("no ctf data present\n");
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_CANTLOAD));
+ }
+
+ dmp->dm_libctfp = malloc(sizeof (ctf_file_t *) * arg.dpa_count);
+ if (dmp->dm_libctfp == NULL) {
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ }
+ bzero(dmp->dm_libctfp, sizeof (ctf_file_t *) * arg.dpa_count);
+
+ dmp->dm_libctfn = malloc(sizeof (char *) * arg.dpa_count);
+ if (dmp->dm_libctfn == NULL) {
+ free(dmp->dm_libctfp);
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ }
+ bzero(dmp->dm_libctfn, sizeof (char *) * arg.dpa_count);
+
+ dmp->dm_nctflibs = arg.dpa_count;
+
+ arg.dpa_count = 0;
+ if (Pobject_iter_resolved(p, dt_module_load_proc_build, &arg) != 0) {
+ dt_proc_unlock(dtp, p);
+ dt_module_unload(dtp, dmp);
+ dt_proc_release(dtp, p);
+ return (dt_set_errno(dtp, EDT_CANTLOAD));
+ }
+ assert(arg.dpa_count == dmp->dm_nctflibs);
+ dt_dprintf("loaded %d ctf modules for pid %d\n", arg.dpa_count,
+ (int)dmp->dm_pid);
+
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+ dmp->dm_flags |= DT_DM_LOADED;
+
+ return (0);
+}
+
int
dt_module_load(dtrace_hdl_t *dtp, dt_module_t *dmp)
{
if (dmp->dm_flags & DT_DM_LOADED)
return (0); /* module is already loaded */
+ if (dmp->dm_pid != 0)
+ return (dt_module_load_proc(dtp, dmp));
+
dmp->dm_ctdata.cts_name = ".SUNW_ctf";
dmp->dm_ctdata.cts_type = SHT_PROGBITS;
dmp->dm_ctdata.cts_flags = 0;
@@ -645,6 +835,14 @@ dt_module_load(dtrace_hdl_t *dtp, dt_module_t *dmp)
return (0);
}
+int
+dt_module_hasctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
+{
+ if (dmp->dm_pid != 0 && dmp->dm_nctflibs > 0)
+ return (1);
+ return (dt_module_getctf(dtp, dmp) != NULL);
+}
+
ctf_file_t *
dt_module_getctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
{
@@ -718,6 +916,8 @@ err:
void
dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
{
+ int i;
+
ctf_close(dmp->dm_ctfp);
dmp->dm_ctfp = NULL;
@@ -733,6 +933,17 @@ dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
}
#endif
+ if (dmp->dm_libctfp != NULL) {
+ for (i = 0; i < dmp->dm_nctflibs; i++) {
+ ctf_close(dmp->dm_libctfp[i]);
+ free(dmp->dm_libctfn[i]);
+ }
+ free(dmp->dm_libctfp);
+ free(dmp->dm_libctfn);
+ dmp->dm_libctfp = NULL;
+ dmp->dm_nctflibs = 0;
+ }
+
bzero(&dmp->dm_ctdata, sizeof (ctf_sect_t));
bzero(&dmp->dm_symtab, sizeof (ctf_sect_t));
bzero(&dmp->dm_strtab, sizeof (ctf_sect_t));
@@ -778,6 +989,8 @@ dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
(void) elf_end(dmp->dm_elf);
dmp->dm_elf = NULL;
+ dmp->dm_pid = 0;
+
dmp->dm_flags &= ~DT_DM_LOADED;
}
@@ -866,6 +1079,34 @@ dt_module_modelname(dt_module_t *dmp)
return ("32-bit");
}
+/* ARGSUSED */
+int
+dt_module_getlibid(dtrace_hdl_t *dtp, dt_module_t *dmp, const ctf_file_t *fp)
+{
+ int i;
+
+ for (i = 0; i < dmp->dm_nctflibs; i++) {
+ if (dmp->dm_libctfp[i] == fp)
+ return (i);
+ }
+
+ return (-1);
+}
+
+/* ARGSUSED */
+ctf_file_t *
+dt_module_getctflib(dtrace_hdl_t *dtp, dt_module_t *dmp, const char *name)
+{
+ int i;
+
+ for (i = 0; i < dmp->dm_nctflibs; i++) {
+ if (strcmp(dmp->dm_libctfn[i], name) == 0)
+ return (dmp->dm_libctfp[i]);
+ }
+
+ return (NULL);
+}
+
/*
* Update our module cache by adding an entry for the specified module 'name'.
* We create the dt_module_t and populate it using /system/object/<name>/.
@@ -1294,8 +1535,10 @@ dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
dt_module_t *dmp;
int found = 0;
ctf_id_t id;
- uint_t n;
+ uint_t n, i;
int justone;
+ ctf_file_t *fp;
+ char *buf, *p, *q;
uint_t mask = 0; /* mask of dt_module flags to match */
uint_t bits = 0; /* flag bits that must be present */
@@ -1310,7 +1553,6 @@ dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
return (-1); /* dt_errno is set for us */
n = 1;
justone = 1;
-
} else {
if (object == DTRACE_OBJ_KMODS)
mask = bits = DT_DM_KERNEL;
@@ -1334,7 +1576,7 @@ dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
* module. If our search was scoped to only one module then
* return immediately leaving dt_errno unmodified.
*/
- if (dt_module_getctf(dtp, dmp) == NULL) {
+ if (dt_module_hasctf(dtp, dmp) == 0) {
if (justone)
return (-1);
continue;
@@ -1346,13 +1588,38 @@ dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
* 'tip' and keep going in the hope that we will locate the
* underlying structure definition. Otherwise just return.
*/
- if ((id = ctf_lookup_by_name(dmp->dm_ctfp, name)) != CTF_ERR) {
+ if (dmp->dm_pid == 0) {
+ id = ctf_lookup_by_name(dmp->dm_ctfp, name);
+ fp = dmp->dm_ctfp;
+ } else {
+ if ((p = strchr(name, '`')) != NULL) {
+ buf = strdup(name);
+ if (buf == NULL)
+ return (dt_set_errno(dtp, EDT_NOMEM));
+ p = strchr(buf, '`');
+ if ((q = strchr(p + 1, '`')) != NULL)
+ p = q;
+ *p = '\0';
+ fp = dt_module_getctflib(dtp, dmp, buf);
+ if (fp == NULL || (id = ctf_lookup_by_name(fp,
+ p + 1)) == CTF_ERR)
+ id = CTF_ERR;
+ free(buf);
+ } else {
+ for (i = 0; i < dmp->dm_nctflibs; i++) {
+ fp = dmp->dm_libctfp[i];
+ id = ctf_lookup_by_name(fp, name);
+ if (id != CTF_ERR)
+ break;
+ }
+ }
+ }
+ if (id != CTF_ERR) {
tip->dtt_object = dmp->dm_name;
- tip->dtt_ctfp = dmp->dm_ctfp;
+ tip->dtt_ctfp = fp;
tip->dtt_type = id;
-
- if (ctf_type_kind(dmp->dm_ctfp, ctf_type_resolve(
- dmp->dm_ctfp, id)) != CTF_K_FORWARD)
+ if (ctf_type_kind(fp, ctf_type_resolve(fp, id)) !=
+ CTF_K_FORWARD)
return (0);
found++;
@@ -1374,6 +1641,7 @@ dtrace_symbol_type(dtrace_hdl_t *dtp, const GElf_Sym *symp,
tip->dtt_object = NULL;
tip->dtt_ctfp = NULL;
tip->dtt_type = CTF_ERR;
+ tip->dtt_flags = 0;
if ((dmp = dt_module_lookup_by_name(dtp, sip->dts_object)) == NULL)
return (dt_set_errno(dtp, EDT_NOMOD));
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.h
index 8334a2b..d103e02 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.h
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.h
@@ -23,12 +23,13 @@
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#ifndef _DT_MODULE_H
#define _DT_MODULE_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <dt_impl.h>
#ifdef __cplusplus
@@ -43,11 +44,16 @@ extern void dt_module_destroy(dtrace_hdl_t *, dt_module_t *);
extern dt_module_t *dt_module_lookup_by_name(dtrace_hdl_t *, const char *);
extern dt_module_t *dt_module_lookup_by_ctf(dtrace_hdl_t *, ctf_file_t *);
+extern int dt_module_hasctf(dtrace_hdl_t *, dt_module_t *);
extern ctf_file_t *dt_module_getctf(dtrace_hdl_t *, dt_module_t *);
extern dt_ident_t *dt_module_extern(dtrace_hdl_t *, dt_module_t *,
const char *, const dtrace_typeinfo_t *);
extern const char *dt_module_modelname(dt_module_t *);
+extern int dt_module_getlibid(dtrace_hdl_t *, dt_module_t *,
+ const ctf_file_t *);
+extern ctf_file_t *dt_module_getctflib(dtrace_hdl_t *, dt_module_t *,
+ const char *);
#ifdef __cplusplus
}
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
index 9c9b2a6..cf6f2e9 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@@ -122,8 +122,12 @@
#define DT_VERS_1_8_1 DT_VERSION_NUMBER(1, 8, 1)
#define DT_VERS_1_9 DT_VERSION_NUMBER(1, 9, 0)
#define DT_VERS_1_9_1 DT_VERSION_NUMBER(1, 9, 1)
-#define DT_VERS_LATEST DT_VERS_1_9_1
-#define DT_VERS_STRING "Sun D 1.9.1"
+#define DT_VERS_1_10 DT_VERSION_NUMBER(1, 10, 0)
+#define DT_VERS_1_11 DT_VERSION_NUMBER(1, 11, 0)
+#define DT_VERS_1_12 DT_VERSION_NUMBER(1, 12, 0)
+#define DT_VERS_1_12_1 DT_VERSION_NUMBER(1, 12, 1)
+#define DT_VERS_LATEST DT_VERS_1_12_1
+#define DT_VERS_STRING "Sun D 1.12.1"
const dt_version_t _dtrace_versions[] = {
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -145,6 +149,10 @@ const dt_version_t _dtrace_versions[] = {
DT_VERS_1_8_1, /* D API 1.8.1 */
DT_VERS_1_9, /* D API 1.9 */
DT_VERS_1_9_1, /* D API 1.9.1 */
+ DT_VERS_1_10, /* D API 1.10 */
+ DT_VERS_1_11, /* D API 1.11 */
+ DT_VERS_1_12, /* D API 1.12 */
+ DT_VERS_1_12_1, /* D API 1.12.1 */
0
};
@@ -275,6 +283,8 @@ static const dt_ident_t _dtrace_globals[] = {
&dt_idops_func, "uint64_t(uint64_t)" },
{ "htons", DT_IDENT_FUNC, 0, DIF_SUBR_HTONS, DT_ATTR_EVOLCMN, DT_VERS_1_3,
&dt_idops_func, "uint16_t(uint16_t)" },
+{ "getf", DT_IDENT_FUNC, 0, DIF_SUBR_GETF, DT_ATTR_STABCMN, DT_VERS_1_10,
+ &dt_idops_func, "file_t *(int)" },
{ "gid", DT_IDENT_SCALAR, 0, DIF_VAR_GID, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "gid_t" },
{ "id", DT_IDENT_SCALAR, 0, DIF_VAR_ID, DT_ATTR_STABCMN, DT_VERS_1_0,
@@ -297,6 +307,8 @@ static const dt_ident_t _dtrace_globals[] = {
DT_VERS_1_5, &dt_idops_func, "string(int, void *)" },
{ "ipl", DT_IDENT_SCALAR, 0, DIF_VAR_IPL, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "uint_t" },
+{ "json", DT_IDENT_FUNC, 0, DIF_SUBR_JSON, DT_ATTR_STABCMN, DT_VERS_1_11,
+ &dt_idops_func, "string(const char *, const char *)" },
{ "jstack", DT_IDENT_ACTFUNC, 0, DT_ACT_JSTACK, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "stack(...)" },
{ "lltostr", DT_IDENT_FUNC, 0, DIF_SUBR_LLTOSTR, DT_ATTR_STABCMN, DT_VERS_1_0,
@@ -444,6 +456,8 @@ static const dt_ident_t _dtrace_globals[] = {
&dt_idops_func, "string(const char *, const char *)" },
{ "strtok", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOK, DT_ATTR_STABCMN, DT_VERS_1_1,
&dt_idops_func, "string(const char *, const char *)" },
+{ "strtoll", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOLL, DT_ATTR_STABCMN, DT_VERS_1_11,
+ &dt_idops_func, "int64_t(const char *, [int])" },
{ "substr", DT_IDENT_FUNC, 0, DIF_SUBR_SUBSTR, DT_ATTR_STABCMN, DT_VERS_1_1,
&dt_idops_func, "string(const char *, int, [int])" },
{ "sum", DT_IDENT_AGGFUNC, 0, DTRACEAGG_SUM, DT_ATTR_STABCMN, DT_VERS_1_0,
@@ -1148,6 +1162,7 @@ alloc:
dtp->dt_linktype = DT_LTYP_ELF;
dtp->dt_xlatemode = DT_XL_STATIC;
dtp->dt_stdcmode = DT_STDC_XA;
+ dtp->dt_encoding = DT_ENCODING_UNSET;
dtp->dt_version = version;
dtp->dt_fd = dtfd;
dtp->dt_ftfd = ftfd;
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
index c20d250..832af88 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c
@@ -25,6 +25,7 @@
*/
/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
@@ -338,6 +339,23 @@ dt_opt_linktype(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
/*ARGSUSED*/
static int
+dt_opt_encoding(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
+{
+ if (arg == NULL)
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ if (strcmp(arg, "ascii") == 0)
+ dtp->dt_encoding = DT_ENCODING_ASCII;
+ else if (strcmp(arg, "utf8") == 0)
+ dtp->dt_encoding = DT_ENCODING_UTF8;
+ else
+ return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static int
dt_opt_evaltime(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
{
if (arg == NULL)
@@ -928,6 +946,7 @@ static const dt_option_t _dtrace_ctoptions[] = {
{ "define", dt_opt_cpp_opts, (uintptr_t)"-D" },
{ "droptags", dt_opt_droptags },
{ "empty", dt_opt_cflags, DTRACE_C_EMPTY },
+ { "encoding", dt_opt_encoding },
{ "errtags", dt_opt_cflags, DTRACE_C_ETAGS },
{ "evaltime", dt_opt_evaltime },
{ "incdir", dt_opt_cpp_opts, (uintptr_t)"-I" },
@@ -988,11 +1007,14 @@ static const dt_option_t _dtrace_rtoptions[] = {
* Dynamic run-time options.
*/
static const dt_option_t _dtrace_drtoptions[] = {
+ { "agghist", dt_opt_runtime, DTRACEOPT_AGGHIST },
+ { "aggpack", dt_opt_runtime, DTRACEOPT_AGGPACK },
{ "aggrate", dt_opt_rate, DTRACEOPT_AGGRATE },
{ "aggsortkey", dt_opt_runtime, DTRACEOPT_AGGSORTKEY },
{ "aggsortkeypos", dt_opt_runtime, DTRACEOPT_AGGSORTKEYPOS },
{ "aggsortpos", dt_opt_runtime, DTRACEOPT_AGGSORTPOS },
{ "aggsortrev", dt_opt_runtime, DTRACEOPT_AGGSORTREV },
+ { "aggzoom", dt_opt_runtime, DTRACEOPT_AGGZOOM },
{ "flowindent", dt_opt_runtime, DTRACEOPT_FLOWINDENT },
{ "quiet", dt_opt_runtime, DTRACEOPT_QUIET },
{ "rawbytes", dt_opt_runtime, DTRACEOPT_RAWBYTES },
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c
index 5b3be7d..6ce3dad 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c
@@ -22,8 +22,8 @@
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Copyright (c) 2011, Joyent Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -197,7 +197,7 @@ dt_type_lookup(const char *s, dtrace_typeinfo_t *tip)
{
static const char delimiters[] = " \t\n\r\v\f*`";
dtrace_hdl_t *dtp = yypcb->pcb_hdl;
- const char *p, *q, *end, *obj;
+ const char *p, *q, *r, *end, *obj;
for (p = s, end = s + strlen(s); *p != '\0'; p = q) {
while (isspace(*p))
@@ -225,8 +225,23 @@ dt_type_lookup(const char *s, dtrace_typeinfo_t *tip)
bcopy(s, type, (size_t)(p - s));
bcopy(q + 1, type + (size_t)(p - s), strlen(q + 1) + 1);
- if (strchr(q + 1, '`') != NULL)
- return (dt_set_errno(dtp, EDT_BADSCOPE));
+ /*
+ * There may be at most three delimeters. The second
+ * delimeter is usually used to distinguish the type
+ * within a given module, however, there could be a link
+ * map id on the scene in which case that delimeter
+ * would be the third. We determine presence of the lmid
+ * if it rouglhly meets the from LM[0-9]
+ */
+ if ((r = strchr(q + 1, '`')) != NULL &&
+ ((r = strchr(r + 1, '`')) != NULL)) {
+ if (strchr(r + 1, '`') != NULL)
+ return (dt_set_errno(dtp,
+ EDT_BADSCOPE));
+ if (q[1] != 'L' || q[2] != 'M')
+ return (dt_set_errno(dtp,
+ EDT_BADSCOPE));
+ }
return (dtrace_lookup_by_type(dtp, object, type, tip));
}
@@ -256,6 +271,7 @@ dt_type_pointer(dtrace_typeinfo_t *tip)
ctf_file_t *ctfp = tip->dtt_ctfp;
ctf_id_t type = tip->dtt_type;
ctf_id_t base = ctf_type_resolve(ctfp, type);
+ uint_t bflags = tip->dtt_flags;
dt_module_t *dmp;
ctf_id_t ptr;
@@ -287,6 +303,7 @@ dt_type_pointer(dtrace_typeinfo_t *tip)
tip->dtt_object = dmp->dm_name;
tip->dtt_ctfp = dmp->dm_ctfp;
tip->dtt_type = ptr;
+ tip->dtt_flags = bflags;
return (0);
}
@@ -390,7 +407,7 @@ void
dt_node_promote(dt_node_t *lp, dt_node_t *rp, dt_node_t *dnp)
{
dt_type_promote(lp, rp, &dnp->dn_ctfp, &dnp->dn_type);
- dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type);
+ dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type, B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
}
@@ -659,7 +676,8 @@ dt_node_attr_assign(dt_node_t *dnp, dtrace_attribute_t attr)
}
void
-dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type)
+dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type,
+ boolean_t user)
{
ctf_id_t base = ctf_type_resolve(fp, type);
uint_t kind = ctf_type_kind(fp, base);
@@ -691,6 +709,9 @@ dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type)
type == DT_DYN_TYPE(yypcb->pcb_hdl))
dnp->dn_flags |= DT_NF_REF;
+ if (user)
+ dnp->dn_flags |= DT_NF_USERLAND;
+
dnp->dn_flags |= DT_NF_COOKED;
dnp->dn_ctfp = fp;
dnp->dn_type = type;
@@ -728,6 +749,7 @@ size_t
dt_node_type_size(const dt_node_t *dnp)
{
ctf_id_t base;
+ dtrace_hdl_t *dtp = yypcb->pcb_hdl;
if (dnp->dn_kind == DT_NODE_STRING)
return (strlen(dnp->dn_string) + 1);
@@ -740,6 +762,20 @@ dt_node_type_size(const dt_node_t *dnp)
if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_FORWARD)
return (0);
+ /*
+ * Here we have a 32-bit user pointer that is being used with a 64-bit
+ * kernel. When we're using it and its tagged as a userland reference --
+ * then we need to keep it as a 32-bit pointer. However, if we are
+ * referring to it as a kernel address, eg. being used after a copyin()
+ * then we need to make sure that we actually return the kernel's size
+ * of a pointer, 8 bytes.
+ */
+ if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_POINTER &&
+ ctf_getmodel(dnp->dn_ctfp) == CTF_MODEL_ILP32 &&
+ !(dnp->dn_flags & DT_NF_USERLAND) &&
+ dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)
+ return (8);
+
return (ctf_type_size(dnp->dn_ctfp, dnp->dn_type));
}
@@ -1226,7 +1262,7 @@ dt_node_int(uintmax_t value)
if (value <= dtp->dt_ints[i].did_limit) {
dt_node_type_assign(dnp,
dtp->dt_ints[i].did_ctfp,
- dtp->dt_ints[i].did_type);
+ dtp->dt_ints[i].did_type, B_FALSE);
/*
* If a prefix character is present in macro text, add
@@ -1261,7 +1297,7 @@ dt_node_string(char *string)
dnp = dt_node_alloc(DT_NODE_STRING);
dnp->dn_op = DT_TOK_STRING;
dnp->dn_string = string;
- dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp), B_FALSE);
return (dnp);
}
@@ -1337,7 +1373,8 @@ dt_node_type(dt_decl_t *ddp)
dnp = dt_node_alloc(DT_NODE_TYPE);
dnp->dn_op = DT_TOK_IDENT;
dnp->dn_string = name;
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, dtt.dtt_flags);
if (dtt.dtt_ctfp == dtp->dt_cdefs->dm_ctfp ||
dtt.dtt_ctfp == dtp->dt_ddefs->dm_ctfp)
@@ -1581,7 +1618,8 @@ dt_node_decl(void)
bzero(&idn, sizeof (dt_node_t));
if (idp != NULL && idp->di_type != CTF_ERR)
- dt_node_type_assign(&idn, idp->di_ctfp, idp->di_type);
+ dt_node_type_assign(&idn, idp->di_ctfp, idp->di_type,
+ B_FALSE);
else if (idp != NULL)
(void) dt_ident_cook(&idn, idp, NULL);
@@ -1791,7 +1829,7 @@ dt_node_offsetof(dt_decl_t *ddp, char *s)
}
bzero(&dn, sizeof (dn));
- dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type);
+ dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type, B_FALSE);
if (dn.dn_flags & DT_NF_BITFIELD) {
xyerror(D_OFFSETOF_BITFIELD,
@@ -1847,7 +1885,8 @@ dt_node_op1(int op, dt_node_t *cp)
}
dt_node_type_assign(cp, dtp->dt_ddefs->dm_ctfp,
- ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"));
+ ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"),
+ B_FALSE);
cp->dn_kind = DT_NODE_INT;
cp->dn_op = DT_TOK_INT;
@@ -1925,17 +1964,17 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
case DT_TOK_LOR:
dnp->dn_value = l || r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LXOR:
dnp->dn_value = (l != 0) ^ (r != 0);
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LAND:
dnp->dn_value = l && r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_BOR:
dnp->dn_value = l | r;
@@ -1952,12 +1991,12 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
case DT_TOK_EQU:
dnp->dn_value = l == r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_NEQ:
dnp->dn_value = l != r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LT:
dt_node_promote(lp, rp, dnp);
@@ -1966,7 +2005,7 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
else
dnp->dn_value = l < r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LE:
dt_node_promote(lp, rp, dnp);
@@ -1975,7 +2014,7 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
else
dnp->dn_value = l <= r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_GT:
dt_node_promote(lp, rp, dnp);
@@ -1984,7 +2023,7 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
else
dnp->dn_value = l > r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_GE:
dt_node_promote(lp, rp, dnp);
@@ -1993,7 +2032,7 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
else
dnp->dn_value = l >= r;
dt_node_type_assign(dnp,
- DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
break;
case DT_TOK_LSH:
dnp->dn_value = l << r;
@@ -2234,7 +2273,7 @@ dt_node_inline(dt_node_t *expr)
* until we have successfully cooked the right-hand expression, below.
*/
dnp = dt_node_alloc(DT_NODE_INLINE);
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
dt_node_attr_assign(dnp, _dtrace_defattr);
if (dt_node_is_void(dnp)) {
@@ -2389,7 +2428,8 @@ dt_node_member(dt_decl_t *ddp, char *name, dt_node_t *expr)
dnp->dn_membexpr = expr;
if (ddp != NULL)
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
+ dtt.dtt_flags);
return (dnp);
}
@@ -2420,10 +2460,10 @@ dt_node_xlator(dt_decl_t *ddp, dt_decl_t *sdp, char *name, dt_node_t *members)
}
bzero(&sn, sizeof (sn));
- dt_node_type_assign(&sn, src.dtt_ctfp, src.dtt_type);
+ dt_node_type_assign(&sn, src.dtt_ctfp, src.dtt_type, B_FALSE);
bzero(&dn, sizeof (dn));
- dt_node_type_assign(&dn, dst.dtt_ctfp, dst.dtt_type);
+ dt_node_type_assign(&dn, dst.dtt_ctfp, dst.dtt_type, B_FALSE);
if (dt_xlator_lookup(dtp, &sn, &dn, DT_XLATE_EXACT) != NULL) {
xyerror(D_XLATE_REDECL,
@@ -2669,7 +2709,7 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create)
attr = dt_ident_cook(dnp, idp, NULL);
else {
dt_node_type_assign(dnp,
- DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
attr = idp->di_attr;
}
@@ -2745,7 +2785,8 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create)
dnp->dn_ident = idp;
dnp->dn_flags |= DT_NF_LVALUE;
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
+ dtt.dtt_flags);
dt_node_attr_assign(dnp, _dtrace_symattr);
if (uref) {
@@ -2793,7 +2834,7 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create)
attr = dt_ident_cook(dnp, idp, NULL);
else {
dt_node_type_assign(dnp,
- DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
attr = idp->di_attr;
}
@@ -2896,7 +2937,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
xyerror(D_TYPE_ERR, "failed to lookup int64_t\n");
dt_ident_type_assign(cp->dn_ident, dtt.dtt_ctfp, dtt.dtt_type);
- dt_node_type_assign(cp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(cp, dtt.dtt_ctfp, dtt.dtt_type,
+ dtt.dtt_flags);
}
if (cp->dn_kind == DT_NODE_VAR)
@@ -2913,7 +2955,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
dnp->dn_ident = &dxp->dx_souid;
dt_node_type_assign(dnp,
- dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type);
+ dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type,
+ cp->dn_flags & DT_NF_USERLAND);
break;
}
@@ -2933,7 +2976,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
"cannot dereference non-pointer type\n");
}
- dt_node_type_assign(dnp, cp->dn_ctfp, type);
+ dt_node_type_assign(dnp, cp->dn_ctfp, type,
+ cp->dn_flags & DT_NF_USERLAND);
base = ctf_type_resolve(cp->dn_ctfp, type);
kind = ctf_type_kind(cp->dn_ctfp, base);
@@ -2990,7 +3034,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
xyerror(D_OP_SCALAR, "operator %s requires an operand "
"of scalar type\n", opstr(dnp->dn_op));
}
- dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
+ B_FALSE);
break;
case DT_TOK_ADDROF:
@@ -3023,10 +3068,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
dt_node_type_name(cp, n, sizeof (n)));
}
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
-
- if (cp->dn_flags & DT_NF_USERLAND)
- dnp->dn_flags |= DT_NF_USERLAND;
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
+ cp->dn_flags & DT_NF_USERLAND);
break;
case DT_TOK_SIZEOF:
@@ -3041,7 +3084,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
}
dt_node_type_assign(dnp, dtp->dt_ddefs->dm_ctfp,
- ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"));
+ ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"),
+ B_FALSE);
break;
case DT_TOK_STRINGOF:
@@ -3051,7 +3095,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
"cannot apply stringof to a value of type %s\n",
dt_node_type_name(cp, n, sizeof (n)));
}
- dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp),
+ cp->dn_flags & DT_NF_USERLAND);
break;
case DT_TOK_PREINC:
@@ -3244,7 +3289,8 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
"of scalar type\n", opstr(op));
}
- dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
+ B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
break;
@@ -3288,7 +3334,8 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
rp->dn_op = DT_TOK_INT;
rp->dn_value = (intmax_t)val;
- dt_node_type_assign(rp, lp->dn_ctfp, lp->dn_type);
+ dt_node_type_assign(rp, lp->dn_ctfp, lp->dn_type,
+ B_FALSE);
dt_node_attr_assign(rp, _dtrace_symattr);
}
@@ -3320,7 +3367,8 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
dt_node_type_name(rp, n2, sizeof (n2)));
}
- dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
+ B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
break;
@@ -3368,7 +3416,7 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
dt_node_type_name(rp, n2, sizeof (n2)));
}
- dt_node_type_assign(dnp, ctfp, type);
+ dt_node_type_assign(dnp, ctfp, type, B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
if (uref)
@@ -3509,7 +3557,7 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
*/
if (lp->dn_kind == DT_NODE_VAR &&
dt_ident_unref(lp->dn_ident)) {
- dt_node_type_assign(lp, ctfp, type);
+ dt_node_type_assign(lp, ctfp, type, B_FALSE);
dt_ident_type_assign(lp->dn_ident, ctfp, type);
if (uref) {
@@ -3723,7 +3771,7 @@ asgn_common:
type = ctf_type_resolve(ctfp, m.ctm_type);
kind = ctf_type_kind(ctfp, type);
- dt_node_type_assign(dnp, ctfp, m.ctm_type);
+ dt_node_type_assign(dnp, ctfp, m.ctm_type, B_FALSE);
dt_node_attr_assign(dnp, lp->dn_attr);
if (op == DT_TOK_PTR && (kind != CTF_K_ARRAY ||
@@ -3849,7 +3897,8 @@ asgn_common:
}
dnp->dn_ident = dt_xlator_ident(dxp, lp->dn_ctfp, lp->dn_type);
- dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
+ B_FALSE);
dt_node_attr_assign(dnp,
dt_attr_min(rp->dn_attr, dnp->dn_ident->di_attr));
break;
@@ -4014,7 +4063,7 @@ dt_cook_op3(dt_node_t *dnp, uint_t idflags)
"used in a conditional context\n");
}
- dt_node_type_assign(dnp, ctfp, type);
+ dt_node_type_assign(dnp, ctfp, type, B_FALSE);
dt_node_attr_assign(dnp, dt_attr_min(dnp->dn_expr->dn_attr,
dt_attr_min(lp->dn_attr, rp->dn_attr)));
@@ -4047,7 +4096,8 @@ dt_cook_aggregation(dt_node_t *dnp, uint_t idflags)
dt_node_attr_assign(dnp, dt_ident_cook(dnp,
dnp->dn_ident, &dnp->dn_aggtup));
} else {
- dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
+ B_FALSE);
dt_node_attr_assign(dnp, dnp->dn_ident->di_attr);
}
@@ -4249,7 +4299,8 @@ dt_cook_xlator(dt_node_t *dnp, uint_t idflags)
}
(void) dt_node_cook(mnp, DT_IDFLG_REF);
- dt_node_type_assign(mnp, dxp->dx_dst_ctfp, ctm.ctm_type);
+ dt_node_type_assign(mnp, dxp->dx_dst_ctfp, ctm.ctm_type,
+ B_FALSE);
attr = dt_attr_min(attr, mnp->dn_attr);
if (dt_node_is_argcompat(mnp, mnp->dn_membexpr) == 0) {
@@ -4268,7 +4319,7 @@ dt_cook_xlator(dt_node_t *dnp, uint_t idflags)
dxp->dx_souid.di_attr = attr;
dxp->dx_ptrid.di_attr = attr;
- dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+ dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
dt_node_attr_assign(dnp, _dtrace_defattr);
return (dnp);
@@ -4561,7 +4612,9 @@ dt_node_diftype(dtrace_hdl_t *dtp, const dt_node_t *dnp, dtrace_diftype_t *tp)
ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type));
}
- tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ? DIF_TF_BYREF : 0;
+ tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ?
+ (dnp->dn_flags & DT_NF_USERLAND) ? DIF_TF_BYUREF :
+ DIF_TF_BYREF : 0;
tp->dtdt_pad = 0;
tp->dtdt_size = ctf_type_size(dnp->dn_ctfp, dnp->dn_type);
}
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h
index 6064efb..38f21c9 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.h
@@ -22,12 +22,14 @@
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
#ifndef _DT_PARSER_H
#define _DT_PARSER_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/dtrace.h>
@@ -223,7 +225,7 @@ extern void dt_node_list_free(dt_node_t **);
extern void dt_node_link_free(dt_node_t **);
extern void dt_node_attr_assign(dt_node_t *, dtrace_attribute_t);
-extern void dt_node_type_assign(dt_node_t *, ctf_file_t *, ctf_id_t);
+extern void dt_node_type_assign(dt_node_t *, ctf_file_t *, ctf_id_t, boolean_t);
extern void dt_node_type_propagate(const dt_node_t *, dt_node_t *);
extern const char *dt_node_type_name(const dt_node_t *, char *, size_t);
extern size_t dt_node_type_size(const dt_node_t *);
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c
index b145818..c865a2d 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c
@@ -23,6 +23,9 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <assert.h>
#include <strings.h>
@@ -35,6 +38,7 @@
#endif
#include <libgen.h>
#include <stddef.h>
+#include <sys/sysmacros.h>
#include <dt_impl.h>
#include <dt_program.h>
@@ -43,6 +47,7 @@
#if !defined(sun)
#include <libproc_compat.h>
#endif
+#include <dt_module.h>
typedef struct dt_pid_probe {
dtrace_hdl_t *dpp_dtp;
@@ -827,3 +832,170 @@ dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr)
return (ret);
}
+
+/*
+ * libdtrace has a backroom deal with us to ask us for type information on
+ * behalf of pid provider probes when fasttrap doesn't return any type
+ * information. Instead we'll look up the module and see if there is type
+ * information available. However, if there is no type information available due
+ * to a lack of CTF data, then we want to make sure that DTrace still carries on
+ * in face of that. As such we don't have a meaningful exit code about failure.
+ * We emit information about why we failed to the dtrace debug log so someone
+ * can figure it out by asking nicely for DTRACE_DEBUG.
+ */
+void
+dt_pid_get_types(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp,
+ dtrace_argdesc_t *adp, int *nargs)
+{
+ dt_module_t *dmp;
+ ctf_file_t *fp;
+ ctf_funcinfo_t f;
+ ctf_id_t argv[32];
+ GElf_Sym sym;
+#if defined(sun)
+ prsyminfo_t si;
+#else
+ void *si;
+#endif
+ struct ps_prochandle *p;
+ int i, args;
+ char buf[DTRACE_ARGTYPELEN];
+ const char *mptr;
+ char *eptr;
+ int ret = 0;
+ int argc = sizeof (argv) / sizeof (ctf_id_t);
+ Lmid_t lmid;
+
+ /* Set up a potential outcome */
+ args = *nargs;
+ *nargs = 0;
+
+ /*
+ * If we don't have an entry or return probe then we can just stop right
+ * now as we don't have arguments for offset probes.
+ */
+ if (strcmp(pdp->dtpd_name, "entry") != 0 &&
+ strcmp(pdp->dtpd_name, "return") != 0)
+ return;
+
+ dmp = dt_module_create(dtp, pdp->dtpd_provider);
+ if (dmp == NULL) {
+ dt_dprintf("failed to find module for %s\n",
+ pdp->dtpd_provider);
+ return;
+ }
+ if (dt_module_load(dtp, dmp) != 0) {
+ dt_dprintf("failed to load module for %s\n",
+ pdp->dtpd_provider);
+ return;
+ }
+
+ /*
+ * We may be working with a module that doesn't have ctf. If that's the
+ * case then we just return now and move on with life.
+ */
+ fp = dt_module_getctflib(dtp, dmp, pdp->dtpd_mod);
+ if (fp == NULL) {
+ dt_dprintf("no ctf container for %s\n",
+ pdp->dtpd_mod);
+ return;
+ }
+ p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE);
+ if (p == NULL) {
+ dt_dprintf("failed to grab pid\n");
+ return;
+ }
+ dt_proc_lock(dtp, p);
+
+ /*
+ * Check to see if the D module has a link map ID and separate that out
+ * for properly interrogating libproc.
+ */
+ if ((mptr = strchr(pdp->dtpd_mod, '`')) != NULL) {
+ if (strlen(pdp->dtpd_mod) < 3) {
+ dt_dprintf("found weird modname with linkmap, "
+ "aborting: %s\n", pdp->dtpd_mod);
+ goto out;
+ }
+ if (pdp->dtpd_mod[0] != 'L' || pdp->dtpd_mod[1] != 'M') {
+ dt_dprintf("missing leading 'LM', "
+ "aborting: %s\n", pdp->dtpd_mod);
+ goto out;
+ }
+ errno = 0;
+ lmid = strtol(pdp->dtpd_mod + 2, &eptr, 16);
+ if (errno == ERANGE || eptr != mptr) {
+ dt_dprintf("failed to parse out lmid, aborting: %s\n",
+ pdp->dtpd_mod);
+ goto out;
+ }
+ mptr++;
+ } else {
+ mptr = pdp->dtpd_mod;
+ lmid = 0;
+ }
+
+ if (Pxlookup_by_name(p, lmid, mptr, pdp->dtpd_func,
+ &sym, &si) != 0) {
+ dt_dprintf("failed to find function %s in %s`%s\n",
+ pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
+ goto out;
+ }
+#if defined(sun)
+ if (ctf_func_info(fp, si.prs_id, &f) == CTF_ERR) {
+ dt_dprintf("failed to get ctf information for %s in %s`%s\n",
+ pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
+ goto out;
+ }
+#endif
+
+ (void) snprintf(buf, sizeof (buf), "%s`%s", pdp->dtpd_provider,
+ pdp->dtpd_mod);
+
+ if (strcmp(pdp->dtpd_name, "return") == 0) {
+ if (args < 2)
+ goto out;
+
+ bzero(adp, sizeof (dtrace_argdesc_t));
+ adp->dtargd_ndx = 0;
+ adp->dtargd_id = pdp->dtpd_id;
+ adp->dtargd_mapping = adp->dtargd_ndx;
+ /*
+ * We explicitly leave out the library here, we only care that
+ * it is some int. We are assuming that there is no ctf
+ * container in here that is lying about what an int is.
+ */
+ (void) snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
+ "user %s`%s", pdp->dtpd_provider, "int");
+ adp++;
+ bzero(adp, sizeof (dtrace_argdesc_t));
+ adp->dtargd_ndx = 1;
+ adp->dtargd_id = pdp->dtpd_id;
+ adp->dtargd_mapping = adp->dtargd_ndx;
+ ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
+ "userland ");
+ (void) ctf_type_qname(fp, f.ctc_return, adp->dtargd_native +
+ ret, DTRACE_ARGTYPELEN - ret, buf);
+ *nargs = 2;
+#if defined(sun)
+ } else {
+ if (ctf_func_args(fp, si.prs_id, argc, argv) == CTF_ERR)
+ goto out;
+
+ *nargs = MIN(args, f.ctc_argc);
+ for (i = 0; i < *nargs; i++, adp++) {
+ bzero(adp, sizeof (dtrace_argdesc_t));
+ adp->dtargd_ndx = i;
+ adp->dtargd_id = pdp->dtpd_id;
+ adp->dtargd_mapping = adp->dtargd_ndx;
+ ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
+ "userland ");
+ (void) ctf_type_qname(fp, argv[i], adp->dtargd_native +
+ ret, DTRACE_ARGTYPELEN - ret, buf);
+ }
+#endif
+ }
+out:
+ dt_proc_unlock(dtp, p);
+ dt_proc_release(dtp, p);
+}
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.h
index 886e33d..4bf39c8 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.h
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.h
@@ -24,12 +24,13 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#ifndef _DT_PID_H
#define _DT_PID_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <libproc.h>
#include <sys/fasttrap.h>
#include <dt_impl.h>
@@ -57,6 +58,9 @@ extern int dt_pid_create_offset_probe(struct ps_prochandle *, dtrace_hdl_t *,
extern int dt_pid_create_glob_offset_probes(struct ps_prochandle *,
dtrace_hdl_t *, fasttrap_probe_spec_t *, const GElf_Sym *, const char *);
+extern void dt_pid_get_types(dtrace_hdl_t *, const dtrace_probedesc_t *,
+ dtrace_argdesc_t *, int *);
+
#ifdef __cplusplus
}
#endif
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c
index ccfa3da..fb8ea16 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c
@@ -647,12 +647,16 @@ dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename,
dt_printarg_t pa;
ctf_id_t id;
dt_module_t *dmp;
+ ctf_file_t *ctfp;
+ int libid;
/*
* Split the fully-qualified type ID (module`id). This should
* always be the format, but if for some reason we don't find the
* expected value, return 0 to fall back to the generic trace()
- * behavior.
+ * behavior. In the case of userland CTF modules this will actually be
+ * of the format (module`lib`id). This is due to the fact that those
+ * modules have multiple CTF containers which `lib` identifies.
*/
for (s = typename; *s != '\0' && *s != '`'; s++)
;
@@ -663,6 +667,20 @@ dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename,
object = alloca(s - typename + 1);
bcopy(typename, object, s - typename);
object[s - typename] = '\0';
+ dmp = dt_module_lookup_by_name(dtp, object);
+ if (dmp == NULL)
+ return (0);
+
+ if (dmp->dm_pid != 0) {
+ libid = atoi(s + 1);
+ s = strchr(s + 1, '`');
+ if (s == NULL || libid > dmp->dm_nctflibs)
+ return (0);
+ ctfp = dmp->dm_libctfp[libid];
+ } else {
+ ctfp = dt_module_getctf(dtp, dmp);
+ }
+
id = atoi(s + 1);
/*
@@ -670,16 +688,13 @@ dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename,
* wrong and we can't resolve the ID, bail out and let trace() do the
* work.
*/
- dmp = dt_module_lookup_by_name(dtp, object);
- if (dmp == NULL || ctf_type_kind(dt_module_getctf(dtp, dmp),
- id) == CTF_ERR) {
+ if (ctfp == NULL || ctf_type_kind(ctfp, id) == CTF_ERR)
return (0);
- }
/* setup the print structure and kick off the main print routine */
pa.pa_dtp = dtp;
pa.pa_addr = addr;
- pa.pa_ctfp = dt_module_getctf(dtp, dmp);
+ pa.pa_ctfp = ctfp;
pa.pa_nest = 0;
pa.pa_depth = 0;
pa.pa_file = fp;
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c
index 24682b2..9d4403c 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c
@@ -21,8 +21,8 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#if defined(sun)
@@ -1070,7 +1070,7 @@ dt_printf_validate(dt_pfargv_t *pfv, uint_t flags,
xyerror(D_TYPE_ERR, "failed to lookup agg type %s\n", aggtype);
bzero(&aggnode, sizeof (aggnode));
- dt_node_type_assign(&aggnode, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(&aggnode, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
for (i = 0, j = 0; i < pfv->pfv_argc; i++, pfd = pfd->pfd_next) {
const dt_pfconv_t *pfc = pfd->pfd_conv;
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c
index 188ce0e..0f1bfe0 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c
@@ -23,8 +23,9 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <sys/types.h>
#if defined(sun)
@@ -45,6 +46,8 @@
#include <dt_module.h>
#include <dt_string.h>
#include <dt_list.h>
+#include <dt_pid.h>
+#include <dtrace.h>
static dt_provider_t *
dt_provider_insert(dtrace_hdl_t *dtp, dt_provider_t *pvp, uint_t h)
@@ -273,6 +276,21 @@ dt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp)
nc++;
/*
+ * The pid provider believes in giving the kernel a break. No reason to
+ * give the kernel all the ctf containers that we're keeping ourselves
+ * just to get it back from it. So if we're coming from a pid provider
+ * probe and the kernel gave us no argument information we'll get some
+ * here. If for some crazy reason the kernel knows about our userland
+ * types then we just ignore this.
+ */
+ if (xc == 0 && nc == 0 &&
+ strncmp(pvp->pv_desc.dtvd_name, "pid", 3) == 0) {
+ nc = adc;
+ dt_pid_get_types(dtp, pdp, adv, &nc);
+ xc = nc;
+ }
+
+ /*
* Now that we have discovered the number of native and translated
* arguments from the argument descriptions, allocate a new probe ident
* and corresponding dt_probe_t and hash it into the provider.
@@ -318,7 +336,8 @@ dt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp)
dtt.dtt_type = CTF_ERR;
} else {
dt_node_type_assign(prp->pr_nargv[adp->dtargd_mapping],
- dtt.dtt_ctfp, dtt.dtt_type);
+ dtt.dtt_ctfp, dtt.dtt_type,
+ dtt.dtt_flags & DTT_FL_USER ? B_TRUE : B_FALSE);
}
if (dtt.dtt_type != CTF_ERR && (adp->dtargd_xlate[0] == '\0' ||
@@ -337,7 +356,7 @@ dt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp)
dtt.dtt_type = CTF_ERR;
} else {
dt_node_type_assign(prp->pr_xargv[i],
- dtt.dtt_ctfp, dtt.dtt_type);
+ dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
}
prp->pr_mapping[i] = adp->dtargd_mapping;
@@ -638,7 +657,7 @@ dt_probe_tag(dt_probe_t *prp, uint_t argn, dt_node_t *dnp)
bzero(dnp, sizeof (dt_node_t));
dnp->dn_kind = DT_NODE_TYPE;
- dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+ dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
dt_node_attr_assign(dnp, _dtrace_defattr);
return (dnp);
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.c
index 7ac0cc4..74bd487 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_xlator.c
@@ -23,8 +23,10 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
#include <strings.h>
#include <assert.h>
@@ -69,7 +71,7 @@ dt_xlator_create_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
enp->dn_op = DT_TOK_XLATE;
enp->dn_xlator = dxp;
enp->dn_xmember = mnp;
- dt_node_type_assign(enp, dxp->dx_dst_ctfp, type);
+ dt_node_type_assign(enp, dxp->dx_dst_ctfp, type, B_FALSE);
/*
* For the member itself, we use a DT_NODE_MEMBER as usual with the
@@ -83,7 +85,7 @@ dt_xlator_create_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
mnp->dn_membname = strdup(name);
mnp->dn_membexpr = enp;
- dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type);
+ dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type, B_FALSE);
if (mnp->dn_membname == NULL)
return (dt_set_errno(dtp, EDT_NOMEM));
@@ -318,7 +320,8 @@ dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
dxp = dt_list_next(dxp)) {
- dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type);
+ dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type,
+ B_FALSE);
if (ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
dst_ctfp, dst_base) && dt_node_is_argcompat(src, &xn))
goto out;
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h
index b2e3108..6f88e6d 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h
@@ -25,7 +25,8 @@
*/
/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#ifndef _DTRACE_H
@@ -356,6 +357,12 @@ extern int dtrace_handle_setopt(dtrace_hdl_t *,
#define DTRACE_A_PERCPU 0x0001
#define DTRACE_A_KEEPDELTA 0x0002
#define DTRACE_A_ANONYMOUS 0x0004
+#define DTRACE_A_TOTAL 0x0008
+#define DTRACE_A_MINMAXBIN 0x0010
+#define DTRACE_A_HASNEGATIVES 0x0020
+#define DTRACE_A_HASPOSITIVES 0x0040
+
+#define DTRACE_AGGZOOM_MAX 0.95 /* height of max bar */
#define DTRACE_AGGWALK_ERROR -1 /* error while processing */
#define DTRACE_AGGWALK_NEXT 0 /* proceed to next element */
@@ -376,6 +383,10 @@ struct dtrace_aggdata {
caddr_t dtada_delta; /* delta data, if available */
caddr_t *dtada_percpu; /* per CPU data, if avail */
caddr_t *dtada_percpu_delta; /* per CPU delta, if avail */
+ int64_t dtada_total; /* per agg total, if avail */
+ uint16_t dtada_minbin; /* minimum bin, if avail */
+ uint16_t dtada_maxbin; /* maximum bin, if avail */
+ uint32_t dtada_flags; /* flags */
};
typedef int dtrace_aggregate_f(const dtrace_aggdata_t *, void *);
@@ -495,8 +506,11 @@ typedef struct dtrace_typeinfo {
const char *dtt_object; /* object containing type */
ctf_file_t *dtt_ctfp; /* CTF container handle */
ctf_id_t dtt_type; /* CTF type identifier */
+ uint_t dtt_flags; /* Misc. flags */
} dtrace_typeinfo_t;
+#define DTT_FL_USER 0x1 /* user type */
+
extern int dtrace_lookup_by_type(dtrace_hdl_t *, const char *, const char *,
dtrace_typeinfo_t *);
diff --git a/cddl/lib/libdtrace/libproc_compat.h b/cddl/lib/libdtrace/libproc_compat.h
index a561157..2083d8b 100644
--- a/cddl/lib/libdtrace/libproc_compat.h
+++ b/cddl/lib/libdtrace/libproc_compat.h
@@ -45,8 +45,10 @@
#define Pgrab_error strerror
#define Plmid_to_map(p, l, o) proc_obj2map((p), (o))
#define Plookup_by_addr proc_addr2sym
+#define Pname_to_ctf(p, obj) NULL
#define Pname_to_map proc_name2map
#define Pobject_iter proc_iter_objs
+#define Pobject_iter_resolved(p, f, arg) 1
#define Pobjname proc_objname
#define Pread proc_read
#define Prd_agent proc_rdagent
diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
index 0bdabf9..475d8b8 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
@@ -109,6 +109,7 @@
#include <sys/zone.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#include "strtolctype.h"
/* FreeBSD includes: */
#if !defined(sun)
@@ -214,6 +215,7 @@ static dtrace_provider_t *dtrace_provider; /* provider list */
static dtrace_meta_t *dtrace_meta_pid; /* user-land meta provider */
static int dtrace_opens; /* number of opens */
static int dtrace_helpers; /* number of helpers */
+static int dtrace_getf; /* number of unpriv getf()s */
#if defined(sun)
static void *dtrace_softstate; /* softstate pointer */
#endif
@@ -464,8 +466,8 @@ static kmutex_t dtrace_errlock;
* disallow all negative sizes. Ranges of size 0 are allowed.
*/
#define DTRACE_INRANGE(testaddr, testsz, baseaddr, basesz) \
- ((testaddr) - (baseaddr) < (basesz) && \
- (testaddr) + (testsz) - (baseaddr) <= (basesz) && \
+ ((testaddr) - (uintptr_t)(baseaddr) < (basesz) && \
+ (testaddr) + (testsz) - (uintptr_t)(baseaddr) <= (basesz) && \
(testaddr) + (testsz) >= (testaddr))
/*
@@ -574,6 +576,8 @@ void dtrace_dynvar_clean(dtrace_dstate_t *);
dtrace_dynvar_t *dtrace_dynvar(dtrace_dstate_t *, uint_t, dtrace_key_t *,
size_t, dtrace_dynvar_op_t, dtrace_mstate_t *, dtrace_vstate_t *);
uintptr_t dtrace_dif_varstr(uintptr_t, dtrace_state_t *, dtrace_mstate_t *);
+static int dtrace_priv_proc(dtrace_state_t *);
+static void dtrace_getf_barrier(void);
/*
* DTrace Probe Context Functions
@@ -718,7 +722,7 @@ dtrace_canstore(uint64_t addr, size_t sz, dtrace_mstate_t *mstate,
* up both thread-local variables and any global dynamically-allocated
* variables.
*/
- if (DTRACE_INRANGE(addr, sz, (uintptr_t)vstate->dtvs_dynvars.dtds_base,
+ if (DTRACE_INRANGE(addr, sz, vstate->dtvs_dynvars.dtds_base,
vstate->dtvs_dynvars.dtds_size)) {
dtrace_dstate_t *dstate = &vstate->dtvs_dynvars;
uintptr_t base = (uintptr_t)dstate->dtds_base +
@@ -785,6 +789,7 @@ dtrace_canload(uint64_t addr, size_t sz, dtrace_mstate_t *mstate,
dtrace_vstate_t *vstate)
{
volatile uintptr_t *illval = &cpu_core[curcpu].cpuc_dtrace_illval;
+ file_t *fp;
/*
* If we hold the privilege to read from kernel memory, then
@@ -802,10 +807,104 @@ dtrace_canload(uint64_t addr, size_t sz, dtrace_mstate_t *mstate,
/*
* We're allowed to read from our own string table.
*/
- if (DTRACE_INRANGE(addr, sz, (uintptr_t)mstate->dtms_difo->dtdo_strtab,
+ if (DTRACE_INRANGE(addr, sz, mstate->dtms_difo->dtdo_strtab,
mstate->dtms_difo->dtdo_strlen))
return (1);
+ if (vstate->dtvs_state != NULL &&
+ dtrace_priv_proc(vstate->dtvs_state)) {
+ proc_t *p;
+
+ /*
+ * When we have privileges to the current process, there are
+ * several context-related kernel structures that are safe to
+ * read, even absent the privilege to read from kernel memory.
+ * These reads are safe because these structures contain only
+ * state that (1) we're permitted to read, (2) is harmless or
+ * (3) contains pointers to additional kernel state that we're
+ * not permitted to read (and as such, do not present an
+ * opportunity for privilege escalation). Finally (and
+ * critically), because of the nature of their relation with
+ * the current thread context, the memory associated with these
+ * structures cannot change over the duration of probe context,
+ * and it is therefore impossible for this memory to be
+ * deallocated and reallocated as something else while it's
+ * being operated upon.
+ */
+ if (DTRACE_INRANGE(addr, sz, curthread, sizeof (kthread_t)))
+ return (1);
+
+ if ((p = curthread->t_procp) != NULL && DTRACE_INRANGE(addr,
+ sz, curthread->t_procp, sizeof (proc_t))) {
+ return (1);
+ }
+
+ if (curthread->t_cred != NULL && DTRACE_INRANGE(addr, sz,
+ curthread->t_cred, sizeof (cred_t))) {
+ return (1);
+ }
+
+#if defined(sun)
+ if (p != NULL && p->p_pidp != NULL && DTRACE_INRANGE(addr, sz,
+ &(p->p_pidp->pid_id), sizeof (pid_t))) {
+ return (1);
+ }
+
+ if (curthread->t_cpu != NULL && DTRACE_INRANGE(addr, sz,
+ curthread->t_cpu, offsetof(cpu_t, cpu_pause_thread))) {
+ return (1);
+ }
+#endif
+ }
+
+ if ((fp = mstate->dtms_getf) != NULL) {
+ uintptr_t psz = sizeof (void *);
+ vnode_t *vp;
+ vnodeops_t *op;
+
+ /*
+ * When getf() returns a file_t, the enabling is implicitly
+ * granted the (transient) right to read the returned file_t
+ * as well as the v_path and v_op->vnop_name of the underlying
+ * vnode. These accesses are allowed after a successful
+ * getf() because the members that they refer to cannot change
+ * once set -- and the barrier logic in the kernel's closef()
+ * path assures that the file_t and its referenced vode_t
+ * cannot themselves be stale (that is, it impossible for
+ * either dtms_getf itself or its f_vnode member to reference
+ * freed memory).
+ */
+ if (DTRACE_INRANGE(addr, sz, fp, sizeof (file_t)))
+ return (1);
+
+ if ((vp = fp->f_vnode) != NULL) {
+#if defined(sun)
+ if (DTRACE_INRANGE(addr, sz, &vp->v_path, psz))
+ return (1);
+ if (vp->v_path != NULL && DTRACE_INRANGE(addr, sz,
+ vp->v_path, strlen(vp->v_path) + 1)) {
+ return (1);
+ }
+#endif
+
+ if (DTRACE_INRANGE(addr, sz, &vp->v_op, psz))
+ return (1);
+
+#if defined(sun)
+ if ((op = vp->v_op) != NULL &&
+ DTRACE_INRANGE(addr, sz, &op->vnop_name, psz)) {
+ return (1);
+ }
+
+ if (op != NULL && op->vnop_name != NULL &&
+ DTRACE_INRANGE(addr, sz, op->vnop_name,
+ strlen(op->vnop_name) + 1)) {
+ return (1);
+ }
+#endif
+ }
+ }
+
DTRACE_CPUFLAG_SET(CPU_DTRACE_KPRIV);
*illval = addr;
return (0);
@@ -865,6 +964,58 @@ dtrace_vcanload(void *src, dtrace_diftype_t *type, dtrace_mstate_t *mstate,
}
/*
+ * Convert a string to a signed integer using safe loads.
+ *
+ * NOTE: This function uses various macros from strtolctype.h to manipulate
+ * digit values, etc -- these have all been checked to ensure they make
+ * no additional function calls.
+ */
+static int64_t
+dtrace_strtoll(char *input, int base, size_t limit)
+{
+ uintptr_t pos = (uintptr_t)input;
+ int64_t val = 0;
+ int x;
+ boolean_t neg = B_FALSE;
+ char c, cc, ccc;
+ uintptr_t end = pos + limit;
+
+ /*
+ * Consume any whitespace preceding digits.
+ */
+ while ((c = dtrace_load8(pos)) == ' ' || c == '\t')
+ pos++;
+
+ /*
+ * Handle an explicit sign if one is present.
+ */
+ if (c == '-' || c == '+') {
+ if (c == '-')
+ neg = B_TRUE;
+ c = dtrace_load8(++pos);
+ }
+
+ /*
+ * Check for an explicit hexadecimal prefix ("0x" or "0X") and skip it
+ * if present.
+ */
+ if (base == 16 && c == '0' && ((cc = dtrace_load8(pos + 1)) == 'x' ||
+ cc == 'X') && isxdigit(ccc = dtrace_load8(pos + 2))) {
+ pos += 2;
+ c = ccc;
+ }
+
+ /*
+ * Read in contiguous digits until the first non-digit character.
+ */
+ for (; pos < end && c != '\0' && lisalnum(c) && (x = DIGIT(c)) < base;
+ c = dtrace_load8(++pos))
+ val = val * base + x;
+
+ return (neg ? -val : val);
+}
+
+/*
* Compare two strings using safe loads.
*/
static int
@@ -1185,8 +1336,7 @@ dtrace_priv_proc_common_zone(dtrace_state_t *state)
*/
ASSERT(s_cr != NULL);
- if ((cr = CRED()) != NULL &&
- s_cr->cr_zone == cr->cr_zone)
+ if ((cr = CRED()) != NULL && s_cr->cr_zone == cr->cr_zone)
return (1);
return (0);
@@ -1286,6 +1436,115 @@ dtrace_priv_kernel_destructive(dtrace_state_t *state)
}
/*
+ * Determine if the dte_cond of the specified ECB allows for processing of
+ * the current probe to continue. Note that this routine may allow continued
+ * processing, but with access(es) stripped from the mstate's dtms_access
+ * field.
+ */
+static int
+dtrace_priv_probe(dtrace_state_t *state, dtrace_mstate_t *mstate,
+ dtrace_ecb_t *ecb)
+{
+ dtrace_probe_t *probe = ecb->dte_probe;
+ dtrace_provider_t *prov = probe->dtpr_provider;
+ dtrace_pops_t *pops = &prov->dtpv_pops;
+ int mode = DTRACE_MODE_NOPRIV_DROP;
+
+ ASSERT(ecb->dte_cond);
+
+#if defined(sun)
+ if (pops->dtps_mode != NULL) {
+ mode = pops->dtps_mode(prov->dtpv_arg,
+ probe->dtpr_id, probe->dtpr_arg);
+
+ ASSERT((mode & DTRACE_MODE_USER) ||
+ (mode & DTRACE_MODE_KERNEL));
+ ASSERT((mode & DTRACE_MODE_NOPRIV_RESTRICT) ||
+ (mode & DTRACE_MODE_NOPRIV_DROP));
+ }
+
+ /*
+ * If the dte_cond bits indicate that this consumer is only allowed to
+ * see user-mode firings of this probe, call the provider's dtps_mode()
+ * entry point to check that the probe was fired while in a user
+ * context. If that's not the case, use the policy specified by the
+ * provider to determine if we drop the probe or merely restrict
+ * operation.
+ */
+ if (ecb->dte_cond & DTRACE_COND_USERMODE) {
+ ASSERT(mode != DTRACE_MODE_NOPRIV_DROP);
+
+ if (!(mode & DTRACE_MODE_USER)) {
+ if (mode & DTRACE_MODE_NOPRIV_DROP)
+ return (0);
+
+ mstate->dtms_access &= ~DTRACE_ACCESS_ARGS;
+ }
+ }
+#endif
+
+ /*
+ * This is more subtle than it looks. We have to be absolutely certain
+ * that CRED() isn't going to change out from under us so it's only
+ * legit to examine that structure if we're in constrained situations.
+ * Currently, the only times we'll this check is if a non-super-user
+ * has enabled the profile or syscall providers -- providers that
+ * allow visibility of all processes. For the profile case, the check
+ * above will ensure that we're examining a user context.
+ */
+ if (ecb->dte_cond & DTRACE_COND_OWNER) {
+ cred_t *cr;
+ cred_t *s_cr = state->dts_cred.dcr_cred;
+ proc_t *proc;
+
+ ASSERT(s_cr != NULL);
+
+ if ((cr = CRED()) == NULL ||
+ s_cr->cr_uid != cr->cr_uid ||
+ s_cr->cr_uid != cr->cr_ruid ||
+ s_cr->cr_uid != cr->cr_suid ||
+ s_cr->cr_gid != cr->cr_gid ||
+ s_cr->cr_gid != cr->cr_rgid ||
+ s_cr->cr_gid != cr->cr_sgid ||
+ (proc = ttoproc(curthread)) == NULL ||
+ (proc->p_flag & SNOCD)) {
+ if (mode & DTRACE_MODE_NOPRIV_DROP)
+ return (0);
+
+#if defined(sun)
+ mstate->dtms_access &= ~DTRACE_ACCESS_PROC;
+#endif
+ }
+ }
+
+#if defined(sun)
+ /*
+ * If our dte_cond is set to DTRACE_COND_ZONEOWNER and we are not
+ * in our zone, check to see if our mode policy is to restrict rather
+ * than to drop; if to restrict, strip away both DTRACE_ACCESS_PROC
+ * and DTRACE_ACCESS_ARGS
+ */
+ if (ecb->dte_cond & DTRACE_COND_ZONEOWNER) {
+ cred_t *cr;
+ cred_t *s_cr = state->dts_cred.dcr_cred;
+
+ ASSERT(s_cr != NULL);
+
+ if ((cr = CRED()) == NULL ||
+ s_cr->cr_zone->zone_id != cr->cr_zone->zone_id) {
+ if (mode & DTRACE_MODE_NOPRIV_DROP)
+ return (0);
+
+ mstate->dtms_access &=
+ ~(DTRACE_ACCESS_PROC | DTRACE_ACCESS_ARGS);
+ }
+ }
+#endif
+
+ return (1);
+}
+
+/*
* Note: not called from probe context. This function is called
* asynchronously (and at a regular interval) from outside of probe context to
* clean the dirty dynamic variable lists on all CPUs. Dynamic variable
@@ -2903,7 +3162,7 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
#endif
case DIF_VAR_CURTHREAD:
- if (!dtrace_priv_kernel(state))
+ if (!dtrace_priv_proc(state))
return (0);
return ((uint64_t)(uintptr_t)curthread);
@@ -3259,6 +3518,463 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
}
}
+
+typedef enum dtrace_json_state {
+ DTRACE_JSON_REST = 1,
+ DTRACE_JSON_OBJECT,
+ DTRACE_JSON_STRING,
+ DTRACE_JSON_STRING_ESCAPE,
+ DTRACE_JSON_STRING_ESCAPE_UNICODE,
+ DTRACE_JSON_COLON,
+ DTRACE_JSON_COMMA,
+ DTRACE_JSON_VALUE,
+ DTRACE_JSON_IDENTIFIER,
+ DTRACE_JSON_NUMBER,
+ DTRACE_JSON_NUMBER_FRAC,
+ DTRACE_JSON_NUMBER_EXP,
+ DTRACE_JSON_COLLECT_OBJECT
+} dtrace_json_state_t;
+
+/*
+ * This function possesses just enough knowledge about JSON to extract a single
+ * value from a JSON string and store it in the scratch buffer. It is able
+ * to extract nested object values, and members of arrays by index.
+ *
+ * elemlist is a list of JSON keys, stored as packed NUL-terminated strings, to
+ * be looked up as we descend into the object tree. e.g.
+ *
+ * foo[0].bar.baz[32] --> "foo" NUL "0" NUL "bar" NUL "baz" NUL "32" NUL
+ * with nelems = 5.
+ *
+ * The run time of this function must be bounded above by strsize to limit the
+ * amount of work done in probe context. As such, it is implemented as a
+ * simple state machine, reading one character at a time using safe loads
+ * until we find the requested element, hit a parsing error or run off the
+ * end of the object or string.
+ *
+ * As there is no way for a subroutine to return an error without interrupting
+ * clause execution, we simply return NULL in the event of a missing key or any
+ * other error condition. Each NULL return in this function is commented with
+ * the error condition it represents -- parsing or otherwise.
+ *
+ * The set of states for the state machine closely matches the JSON
+ * specification (http://json.org/). Briefly:
+ *
+ * DTRACE_JSON_REST:
+ * Skip whitespace until we find either a top-level Object, moving
+ * to DTRACE_JSON_OBJECT; or an Array, moving to DTRACE_JSON_VALUE.
+ *
+ * DTRACE_JSON_OBJECT:
+ * Locate the next key String in an Object. Sets a flag to denote
+ * the next String as a key string and moves to DTRACE_JSON_STRING.
+ *
+ * DTRACE_JSON_COLON:
+ * Skip whitespace until we find the colon that separates key Strings
+ * from their values. Once found, move to DTRACE_JSON_VALUE.
+ *
+ * DTRACE_JSON_VALUE:
+ * Detects the type of the next value (String, Number, Identifier, Object
+ * or Array) and routes to the states that process that type. Here we also
+ * deal with the element selector list if we are requested to traverse down
+ * into the object tree.
+ *
+ * DTRACE_JSON_COMMA:
+ * Skip whitespace until we find the comma that separates key-value pairs
+ * in Objects (returning to DTRACE_JSON_OBJECT) or values in Arrays
+ * (similarly DTRACE_JSON_VALUE). All following literal value processing
+ * states return to this state at the end of their value, unless otherwise
+ * noted.
+ *
+ * DTRACE_JSON_NUMBER, DTRACE_JSON_NUMBER_FRAC, DTRACE_JSON_NUMBER_EXP:
+ * Processes a Number literal from the JSON, including any exponent
+ * component that may be present. Numbers are returned as strings, which
+ * may be passed to strtoll() if an integer is required.
+ *
+ * DTRACE_JSON_IDENTIFIER:
+ * Processes a "true", "false" or "null" literal in the JSON.
+ *
+ * DTRACE_JSON_STRING, DTRACE_JSON_STRING_ESCAPE,
+ * DTRACE_JSON_STRING_ESCAPE_UNICODE:
+ * Processes a String literal from the JSON, whether the String denotes
+ * a key, a value or part of a larger Object. Handles all escape sequences
+ * present in the specification, including four-digit unicode characters,
+ * but merely includes the escape sequence without converting it to the
+ * actual escaped character. If the String is flagged as a key, we
+ * move to DTRACE_JSON_COLON rather than DTRACE_JSON_COMMA.
+ *
+ * DTRACE_JSON_COLLECT_OBJECT:
+ * This state collects an entire Object (or Array), correctly handling
+ * embedded strings. If the full element selector list matches this nested
+ * object, we return the Object in full as a string. If not, we use this
+ * state to skip to the next value at this level and continue processing.
+ *
+ * NOTE: This function uses various macros from strtolctype.h to manipulate
+ * digit values, etc -- these have all been checked to ensure they make
+ * no additional function calls.
+ */
+static char *
+dtrace_json(uint64_t size, uintptr_t json, char *elemlist, int nelems,
+ char *dest)
+{
+ dtrace_json_state_t state = DTRACE_JSON_REST;
+ int64_t array_elem = INT64_MIN;
+ int64_t array_pos = 0;
+ uint8_t escape_unicount = 0;
+ boolean_t string_is_key = B_FALSE;
+ boolean_t collect_object = B_FALSE;
+ boolean_t found_key = B_FALSE;
+ boolean_t in_array = B_FALSE;
+ uint32_t braces = 0, brackets = 0;
+ char *elem = elemlist;
+ char *dd = dest;
+ uintptr_t cur;
+
+ for (cur = json; cur < json + size; cur++) {
+ char cc = dtrace_load8(cur);
+ if (cc == '\0')
+ return (NULL);
+
+ switch (state) {
+ case DTRACE_JSON_REST:
+ if (isspace(cc))
+ break;
+
+ if (cc == '{') {
+ state = DTRACE_JSON_OBJECT;
+ break;
+ }
+
+ if (cc == '[') {
+ in_array = B_TRUE;
+ array_pos = 0;
+ array_elem = dtrace_strtoll(elem, 10, size);
+ found_key = array_elem == 0 ? B_TRUE : B_FALSE;
+ state = DTRACE_JSON_VALUE;
+ break;
+ }
+
+ /*
+ * ERROR: expected to find a top-level object or array.
+ */
+ return (NULL);
+ case DTRACE_JSON_OBJECT:
+ if (isspace(cc))
+ break;
+
+ if (cc == '"') {
+ state = DTRACE_JSON_STRING;
+ string_is_key = B_TRUE;
+ break;
+ }
+
+ /*
+ * ERROR: either the object did not start with a key
+ * string, or we've run off the end of the object
+ * without finding the requested key.
+ */
+ return (NULL);
+ case DTRACE_JSON_STRING:
+ if (cc == '\\') {
+ *dd++ = '\\';
+ state = DTRACE_JSON_STRING_ESCAPE;
+ break;
+ }
+
+ if (cc == '"') {
+ if (collect_object) {
+ /*
+ * We don't reset the dest here, as
+ * the string is part of a larger
+ * object being collected.
+ */
+ *dd++ = cc;
+ collect_object = B_FALSE;
+ state = DTRACE_JSON_COLLECT_OBJECT;
+ break;
+ }
+ *dd = '\0';
+ dd = dest; /* reset string buffer */
+ if (string_is_key) {
+ if (dtrace_strncmp(dest, elem,
+ size) == 0)
+ found_key = B_TRUE;
+ } else if (found_key) {
+ if (nelems > 1) {
+ /*
+ * We expected an object, not
+ * this string.
+ */
+ return (NULL);
+ }
+ return (dest);
+ }
+ state = string_is_key ? DTRACE_JSON_COLON :
+ DTRACE_JSON_COMMA;
+ string_is_key = B_FALSE;
+ break;
+ }
+
+ *dd++ = cc;
+ break;
+ case DTRACE_JSON_STRING_ESCAPE:
+ *dd++ = cc;
+ if (cc == 'u') {
+ escape_unicount = 0;
+ state = DTRACE_JSON_STRING_ESCAPE_UNICODE;
+ } else {
+ state = DTRACE_JSON_STRING;
+ }
+ break;
+ case DTRACE_JSON_STRING_ESCAPE_UNICODE:
+ if (!isxdigit(cc)) {
+ /*
+ * ERROR: invalid unicode escape, expected
+ * four valid hexidecimal digits.
+ */
+ return (NULL);
+ }
+
+ *dd++ = cc;
+ if (++escape_unicount == 4)
+ state = DTRACE_JSON_STRING;
+ break;
+ case DTRACE_JSON_COLON:
+ if (isspace(cc))
+ break;
+
+ if (cc == ':') {
+ state = DTRACE_JSON_VALUE;
+ break;
+ }
+
+ /*
+ * ERROR: expected a colon.
+ */
+ return (NULL);
+ case DTRACE_JSON_COMMA:
+ if (isspace(cc))
+ break;
+
+ if (cc == ',') {
+ if (in_array) {
+ state = DTRACE_JSON_VALUE;
+ if (++array_pos == array_elem)
+ found_key = B_TRUE;
+ } else {
+ state = DTRACE_JSON_OBJECT;
+ }
+ break;
+ }
+
+ /*
+ * ERROR: either we hit an unexpected character, or
+ * we reached the end of the object or array without
+ * finding the requested key.
+ */
+ return (NULL);
+ case DTRACE_JSON_IDENTIFIER:
+ if (islower(cc)) {
+ *dd++ = cc;
+ break;
+ }
+
+ *dd = '\0';
+ dd = dest; /* reset string buffer */
+
+ if (dtrace_strncmp(dest, "true", 5) == 0 ||
+ dtrace_strncmp(dest, "false", 6) == 0 ||
+ dtrace_strncmp(dest, "null", 5) == 0) {
+ if (found_key) {
+ if (nelems > 1) {
+ /*
+ * ERROR: We expected an object,
+ * not this identifier.
+ */
+ return (NULL);
+ }
+ return (dest);
+ } else {
+ cur--;
+ state = DTRACE_JSON_COMMA;
+ break;
+ }
+ }
+
+ /*
+ * ERROR: we did not recognise the identifier as one
+ * of those in the JSON specification.
+ */
+ return (NULL);
+ case DTRACE_JSON_NUMBER:
+ if (cc == '.') {
+ *dd++ = cc;
+ state = DTRACE_JSON_NUMBER_FRAC;
+ break;
+ }
+
+ if (cc == 'x' || cc == 'X') {
+ /*
+ * ERROR: specification explicitly excludes
+ * hexidecimal or octal numbers.
+ */
+ return (NULL);
+ }
+
+ /* FALLTHRU */
+ case DTRACE_JSON_NUMBER_FRAC:
+ if (cc == 'e' || cc == 'E') {
+ *dd++ = cc;
+ state = DTRACE_JSON_NUMBER_EXP;
+ break;
+ }
+
+ if (cc == '+' || cc == '-') {
+ /*
+ * ERROR: expect sign as part of exponent only.
+ */
+ return (NULL);
+ }
+ /* FALLTHRU */
+ case DTRACE_JSON_NUMBER_EXP:
+ if (isdigit(cc) || cc == '+' || cc == '-') {
+ *dd++ = cc;
+ break;
+ }
+
+ *dd = '\0';
+ dd = dest; /* reset string buffer */
+ if (found_key) {
+ if (nelems > 1) {
+ /*
+ * ERROR: We expected an object, not
+ * this number.
+ */
+ return (NULL);
+ }
+ return (dest);
+ }
+
+ cur--;
+ state = DTRACE_JSON_COMMA;
+ break;
+ case DTRACE_JSON_VALUE:
+ if (isspace(cc))
+ break;
+
+ if (cc == '{' || cc == '[') {
+ if (nelems > 1 && found_key) {
+ in_array = cc == '[' ? B_TRUE : B_FALSE;
+ /*
+ * If our element selector directs us
+ * to descend into this nested object,
+ * then move to the next selector
+ * element in the list and restart the
+ * state machine.
+ */
+ while (*elem != '\0')
+ elem++;
+ elem++; /* skip the inter-element NUL */
+ nelems--;
+ dd = dest;
+ if (in_array) {
+ state = DTRACE_JSON_VALUE;
+ array_pos = 0;
+ array_elem = dtrace_strtoll(
+ elem, 10, size);
+ found_key = array_elem == 0 ?
+ B_TRUE : B_FALSE;
+ } else {
+ found_key = B_FALSE;
+ state = DTRACE_JSON_OBJECT;
+ }
+ break;
+ }
+
+ /*
+ * Otherwise, we wish to either skip this
+ * nested object or return it in full.
+ */
+ if (cc == '[')
+ brackets = 1;
+ else
+ braces = 1;
+ *dd++ = cc;
+ state = DTRACE_JSON_COLLECT_OBJECT;
+ break;
+ }
+
+ if (cc == '"') {
+ state = DTRACE_JSON_STRING;
+ break;
+ }
+
+ if (islower(cc)) {
+ /*
+ * Here we deal with true, false and null.
+ */
+ *dd++ = cc;
+ state = DTRACE_JSON_IDENTIFIER;
+ break;
+ }
+
+ if (cc == '-' || isdigit(cc)) {
+ *dd++ = cc;
+ state = DTRACE_JSON_NUMBER;
+ break;
+ }
+
+ /*
+ * ERROR: unexpected character at start of value.
+ */
+ return (NULL);
+ case DTRACE_JSON_COLLECT_OBJECT:
+ if (cc == '\0')
+ /*
+ * ERROR: unexpected end of input.
+ */
+ return (NULL);
+
+ *dd++ = cc;
+ if (cc == '"') {
+ collect_object = B_TRUE;
+ state = DTRACE_JSON_STRING;
+ break;
+ }
+
+ if (cc == ']') {
+ if (brackets-- == 0) {
+ /*
+ * ERROR: unbalanced brackets.
+ */
+ return (NULL);
+ }
+ } else if (cc == '}') {
+ if (braces-- == 0) {
+ /*
+ * ERROR: unbalanced braces.
+ */
+ return (NULL);
+ }
+ } else if (cc == '{') {
+ braces++;
+ } else if (cc == '[') {
+ brackets++;
+ }
+
+ if (brackets == 0 && braces == 0) {
+ if (found_key) {
+ *dd = '\0';
+ return (dest);
+ }
+ dd = dest; /* reset string buffer */
+ state = DTRACE_JSON_COMMA;
+ }
+ break;
+ }
+ }
+ return (NULL);
+}
+
/*
* Emulate the execution of DTrace ID subroutines invoked by the call opcode.
* Notice that we don't bother validating the proper number of arguments or
@@ -4055,6 +4771,65 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
break;
}
+ case DIF_SUBR_JSON: {
+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
+ uintptr_t json = tupregs[0].dttk_value;
+ size_t jsonlen = dtrace_strlen((char *)json, size);
+ uintptr_t elem = tupregs[1].dttk_value;
+ size_t elemlen = dtrace_strlen((char *)elem, size);
+
+ char *dest = (char *)mstate->dtms_scratch_ptr;
+ char *elemlist = (char *)mstate->dtms_scratch_ptr + jsonlen + 1;
+ char *ee = elemlist;
+ int nelems = 1;
+ uintptr_t cur;
+
+ if (!dtrace_canload(json, jsonlen + 1, mstate, vstate) ||
+ !dtrace_canload(elem, elemlen + 1, mstate, vstate)) {
+ regs[rd] = 0;
+ break;
+ }
+
+ if (!DTRACE_INSCRATCH(mstate, jsonlen + 1 + elemlen + 1)) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
+ regs[rd] = 0;
+ break;
+ }
+
+ /*
+ * Read the element selector and split it up into a packed list
+ * of strings.
+ */
+ for (cur = elem; cur < elem + elemlen; cur++) {
+ char cc = dtrace_load8(cur);
+
+ if (cur == elem && cc == '[') {
+ /*
+ * If the first element selector key is
+ * actually an array index then ignore the
+ * bracket.
+ */
+ continue;
+ }
+
+ if (cc == ']')
+ continue;
+
+ if (cc == '.' || cc == '[') {
+ nelems++;
+ cc = '\0';
+ }
+
+ *ee++ = cc;
+ }
+ *ee++ = '\0';
+
+ if ((regs[rd] = (uintptr_t)dtrace_json(size, json, elemlist,
+ nelems, dest)) != 0)
+ mstate->dtms_scratch_ptr += jsonlen + 1;
+ break;
+ }
+
case DIF_SUBR_TOUPPER:
case DIF_SUBR_TOLOWER: {
uintptr_t s = tupregs[0].dttk_value;
@@ -4364,6 +5139,28 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
break;
}
+ case DIF_SUBR_STRTOLL: {
+ uintptr_t s = tupregs[0].dttk_value;
+ uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
+ int base = 10;
+
+ if (nargs > 1) {
+ if ((base = tupregs[1].dttk_value) <= 1 ||
+ base > ('z' - 'a' + 1) + ('9' - '0' + 1)) {
+ *flags |= CPU_DTRACE_ILLOP;
+ break;
+ }
+ }
+
+ if (!dtrace_strcanload(s, size, mstate, vstate)) {
+ regs[rd] = INT64_MIN;
+ break;
+ }
+
+ regs[rd] = dtrace_strtoll((char *)s, base, size);
+ break;
+ }
+
case DIF_SUBR_LLTOSTR: {
int64_t i = (int64_t)tupregs[0].dttk_value;
uint64_t val, digit;
@@ -4573,11 +5370,32 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
break;
}
+ case DIF_SUBR_GETF: {
+ uintptr_t fd = tupregs[0].dttk_value;
+ struct filedesc *fdp;
+ file_t *fp;
+
+ if (!dtrace_priv_proc(state)) {
+ regs[rd] = 0;
+ break;
+ }
+ fdp = curproc->p_fd;
+ FILEDESC_SLOCK(fdp);
+ fp = fget_locked(fdp, fd);
+ mstate->dtms_getf = fp;
+ regs[rd] = (uintptr_t)fp;
+ FILEDESC_SUNLOCK(fdp);
+ break;
+ }
+
case DIF_SUBR_CLEANPATH: {
char *dest = (char *)mstate->dtms_scratch_ptr, c;
uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
uintptr_t src = tupregs[0].dttk_value;
int i = 0, j = 0;
+#if defined(sun)
+ zone_t *z;
+#endif
if (!dtrace_strcanload(src, size, mstate, vstate)) {
regs[rd] = 0;
@@ -4676,6 +5494,25 @@ next:
} while (c != '\0');
dest[j] = '\0';
+
+#if defined(sun)
+ if (mstate->dtms_getf != NULL &&
+ !(mstate->dtms_access & DTRACE_ACCESS_KERNEL) &&
+ (z = state->dts_cred.dcr_cred->cr_zone) != kcred->cr_zone) {
+ /*
+ * If we've done a getf() as a part of this ECB and we
+ * don't have kernel access (and we're not in the global
+ * zone), check if the path we cleaned up begins with
+ * the zone's root path, and trim it off if so. Note
+ * that this is an output cleanliness issue, not a
+ * security issue: knowing one's zone root path does
+ * not enable privilege escalation.
+ */
+ if (strstr(dest, z->zone_rootpath) == dest)
+ dest += strlen(z->zone_rootpath) - 1;
+ }
+#endif
+
regs[rd] = (uintptr_t)dest;
mstate->dtms_scratch_ptr += size;
break;
@@ -5110,102 +5947,95 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
pc = DIF_INSTR_LABEL(instr);
break;
case DIF_OP_RLDSB:
- if (!dtrace_canstore(regs[r1], 1, mstate, vstate)) {
- *flags |= CPU_DTRACE_KPRIV;
- *illval = regs[r1];
+ if (!dtrace_canload(regs[r1], 1, mstate, vstate))
break;
- }
/*FALLTHROUGH*/
case DIF_OP_LDSB:
regs[rd] = (int8_t)dtrace_load8(regs[r1]);
break;
case DIF_OP_RLDSH:
- if (!dtrace_canstore(regs[r1], 2, mstate, vstate)) {
- *flags |= CPU_DTRACE_KPRIV;
- *illval = regs[r1];
+ if (!dtrace_canload(regs[r1], 2, mstate, vstate))
break;
- }
/*FALLTHROUGH*/
case DIF_OP_LDSH:
regs[rd] = (int16_t)dtrace_load16(regs[r1]);
break;
case DIF_OP_RLDSW:
- if (!dtrace_canstore(regs[r1], 4, mstate, vstate)) {
- *flags |= CPU_DTRACE_KPRIV;
- *illval = regs[r1];
+ if (!dtrace_canload(regs[r1], 4, mstate, vstate))
break;
- }
/*FALLTHROUGH*/
case DIF_OP_LDSW:
regs[rd] = (int32_t)dtrace_load32(regs[r1]);
break;
case DIF_OP_RLDUB:
- if (!dtrace_canstore(regs[r1], 1, mstate, vstate)) {
- *flags |= CPU_DTRACE_KPRIV;
- *illval = regs[r1];
+ if (!dtrace_canload(regs[r1], 1, mstate, vstate))
break;
- }
/*FALLTHROUGH*/
case DIF_OP_LDUB:
regs[rd] = dtrace_load8(regs[r1]);
break;
case DIF_OP_RLDUH:
- if (!dtrace_canstore(regs[r1], 2, mstate, vstate)) {
- *flags |= CPU_DTRACE_KPRIV;
- *illval = regs[r1];
+ if (!dtrace_canload(regs[r1], 2, mstate, vstate))
break;
- }
/*FALLTHROUGH*/
case DIF_OP_LDUH:
regs[rd] = dtrace_load16(regs[r1]);
break;
case DIF_OP_RLDUW:
- if (!dtrace_canstore(regs[r1], 4, mstate, vstate)) {
- *flags |= CPU_DTRACE_KPRIV;
- *illval = regs[r1];
+ if (!dtrace_canload(regs[r1], 4, mstate, vstate))
break;
- }
/*FALLTHROUGH*/
case DIF_OP_LDUW:
regs[rd] = dtrace_load32(regs[r1]);
break;
case DIF_OP_RLDX:
- if (!dtrace_canstore(regs[r1], 8, mstate, vstate)) {
- *flags |= CPU_DTRACE_KPRIV;
- *illval = regs[r1];
+ if (!dtrace_canload(regs[r1], 8, mstate, vstate))
break;
- }
/*FALLTHROUGH*/
case DIF_OP_LDX:
regs[rd] = dtrace_load64(regs[r1]);
break;
case DIF_OP_ULDSB:
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] = (int8_t)
dtrace_fuword8((void *)(uintptr_t)regs[r1]);
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
break;
case DIF_OP_ULDSH:
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] = (int16_t)
dtrace_fuword16((void *)(uintptr_t)regs[r1]);
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
break;
case DIF_OP_ULDSW:
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] = (int32_t)
dtrace_fuword32((void *)(uintptr_t)regs[r1]);
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
break;
case DIF_OP_ULDUB:
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] =
dtrace_fuword8((void *)(uintptr_t)regs[r1]);
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
break;
case DIF_OP_ULDUH:
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] =
dtrace_fuword16((void *)(uintptr_t)regs[r1]);
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
break;
case DIF_OP_ULDUW:
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] =
dtrace_fuword32((void *)(uintptr_t)regs[r1]);
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
break;
case DIF_OP_ULDX:
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] =
dtrace_fuword64((void *)(uintptr_t)regs[r1]);
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
break;
case DIF_OP_RET:
rval = regs[rd];
@@ -5887,7 +6717,7 @@ dtrace_action_chill(dtrace_mstate_t *mstate, hrtime_t val)
if (dtrace_destructive_disallow)
return;
- flags = (volatile uint16_t *)&cpu_core[cpu->cpu_id].cpuc_dtrace_flags;
+ flags = (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
now = dtrace_gethrtime();
@@ -6035,6 +6865,63 @@ out:
mstate->dtms_scratch_ptr = old;
}
+static void
+dtrace_store_by_ref(dtrace_difo_t *dp, caddr_t tomax, size_t size,
+ size_t *valoffsp, uint64_t *valp, uint64_t end, int intuple, int dtkind)
+{
+ volatile uint16_t *flags;
+ uint64_t val = *valp;
+ size_t valoffs = *valoffsp;
+
+ flags = (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
+ ASSERT(dtkind == DIF_TF_BYREF || dtkind == DIF_TF_BYUREF);
+
+ /*
+ * If this is a string, we're going to only load until we find the zero
+ * byte -- after which we'll store zero bytes.
+ */
+ if (dp->dtdo_rtype.dtdt_kind == DIF_TYPE_STRING) {
+ char c = '\0' + 1;
+ size_t s;
+
+ for (s = 0; s < size; s++) {
+ if (c != '\0' && dtkind == DIF_TF_BYREF) {
+ c = dtrace_load8(val++);
+ } else if (c != '\0' && dtkind == DIF_TF_BYUREF) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+ c = dtrace_fuword8((void *)(uintptr_t)val++);
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+ if (*flags & CPU_DTRACE_FAULT)
+ break;
+ }
+
+ DTRACE_STORE(uint8_t, tomax, valoffs++, c);
+
+ if (c == '\0' && intuple)
+ break;
+ }
+ } else {
+ uint8_t c;
+ while (valoffs < end) {
+ if (dtkind == DIF_TF_BYREF) {
+ c = dtrace_load8(val++);
+ } else if (dtkind == DIF_TF_BYUREF) {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+ c = dtrace_fuword8((void *)(uintptr_t)val++);
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+ if (*flags & CPU_DTRACE_FAULT)
+ break;
+ }
+
+ DTRACE_STORE(uint8_t, tomax,
+ valoffs++, c);
+ }
+ }
+
+ *valp = val;
+ *valoffsp = valoffs;
+}
+
/*
* If you're looking for the epicenter of DTrace, you just found it. This
* is the function called by the provider to fire a probe -- from which all
@@ -6137,6 +7024,8 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
uint64_t val = 0;
mstate.dtms_present = DTRACE_MSTATE_ARGS | DTRACE_MSTATE_PROBE;
+ mstate.dtms_getf = NULL;
+
*flags &= ~CPU_DTRACE_ERROR;
if (prov == dtrace_provider) {
@@ -6670,7 +7559,8 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
ASSERT(0);
}
- if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF) {
+ if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF ||
+ dp->dtdo_rtype.dtdt_flags & DIF_TF_BYUREF) {
uintptr_t end = valoffs + size;
if (tracememsize != 0 &&
@@ -6679,40 +7569,15 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
tracememsize = 0;
}
- if (!dtrace_vcanload((void *)(uintptr_t)val,
+ if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF &&
+ !dtrace_vcanload((void *)(uintptr_t)val,
&dp->dtdo_rtype, &mstate, vstate))
continue;
- /*
- * If this is a string, we're going to only
- * load until we find the zero byte -- after
- * which we'll store zero bytes.
- */
- if (dp->dtdo_rtype.dtdt_kind ==
- DIF_TYPE_STRING) {
- char c = '\0' + 1;
- int intuple = act->dta_intuple;
- size_t s;
-
- for (s = 0; s < size; s++) {
- if (c != '\0')
- c = dtrace_load8(val++);
-
- DTRACE_STORE(uint8_t, tomax,
- valoffs++, c);
-
- if (c == '\0' && intuple)
- break;
- }
-
- continue;
- }
-
- while (valoffs < end) {
- DTRACE_STORE(uint8_t, tomax, valoffs++,
- dtrace_load8(val++));
- }
-
+ dtrace_store_by_ref(dp, tomax, size, &valoffs,
+ &val, end, act->dta_intuple,
+ dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF ?
+ DIF_TF_BYREF: DIF_TF_BYUREF);
continue;
}
@@ -8810,6 +9675,20 @@ dtrace_difo_validate(dtrace_difo_t *dp, dtrace_vstate_t *vstate, uint_t nregs,
subr == DIF_SUBR_COPYOUTSTR) {
dp->dtdo_destructive = 1;
}
+
+ if (subr == DIF_SUBR_GETF) {
+ /*
+ * If we have a getf() we need to record that
+ * in our state. Note that our state can be
+ * NULL if this is a helper -- but in that
+ * case, the call to getf() is itself illegal,
+ * and will be caught (slightly later) when
+ * the helper is validated.
+ */
+ if (vstate->dtvs_state != NULL)
+ vstate->dtvs_state->dts_getf++;
+ }
+
break;
case DIF_OP_PUSHTR:
if (type != DIF_TYPE_STRING && type != DIF_TYPE_CTF)
@@ -8839,7 +9718,7 @@ dtrace_difo_validate(dtrace_difo_t *dp, dtrace_vstate_t *vstate, uint_t nregs,
"expected 'ret' as last DIF instruction\n");
}
- if (!(dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF)) {
+ if (!(dp->dtdo_rtype.dtdt_flags & (DIF_TF_BYREF | DIF_TF_BYUREF))) {
/*
* If we're not returning by reference, the size must be either
* 0 or the size of one of the base types.
@@ -9089,7 +9968,9 @@ dtrace_difo_validate_helper(dtrace_difo_t *dp)
subr == DIF_SUBR_INET_NTOA ||
subr == DIF_SUBR_INET_NTOA6 ||
subr == DIF_SUBR_INET_NTOP ||
+ subr == DIF_SUBR_JSON ||
subr == DIF_SUBR_LLTOSTR ||
+ subr == DIF_SUBR_STRTOLL ||
subr == DIF_SUBR_RINDEX ||
subr == DIF_SUBR_STRCHR ||
subr == DIF_SUBR_STRJOIN ||
@@ -13734,6 +14615,24 @@ dtrace_state_go(dtrace_state_t *state, processorid_t *cpu)
state->dts_activity = DTRACE_ACTIVITY_WARMUP;
+#if defined(sun)
+ if (state->dts_getf != 0 &&
+ !(state->dts_cred.dcr_visible & DTRACE_CRV_KERNEL)) {
+ /*
+ * We don't have kernel privs but we have at least one call
+ * to getf(); we need to bump our zone's count, and (if
+ * this is the first enabling to have an unprivileged call
+ * to getf()) we need to hook into closef().
+ */
+ state->dts_cred.dcr_cred->cr_zone->zone_dtrace_getf++;
+
+ if (dtrace_getf++ == 0) {
+ ASSERT(dtrace_closef == NULL);
+ dtrace_closef = dtrace_getf_barrier;
+ }
+ }
+#endif
+
/*
* Now it's time to actually fire the BEGIN probe. We need to disable
* interrupts here both to record the CPU on which we fired the BEGIN
@@ -13850,6 +14749,26 @@ dtrace_state_stop(dtrace_state_t *state, processorid_t *cpu)
state->dts_activity = DTRACE_ACTIVITY_STOPPED;
dtrace_sync();
+#if defined(sun)
+ if (state->dts_getf != 0 &&
+ !(state->dts_cred.dcr_visible & DTRACE_CRV_KERNEL)) {
+ /*
+ * We don't have kernel privs but we have at least one call
+ * to getf(); we need to lower our zone's count, and (if
+ * this is the last enabling to have an unprivileged call
+ * to getf()) we need to clear the closef() hook.
+ */
+ ASSERT(state->dts_cred.dcr_cred->cr_zone->zone_dtrace_getf > 0);
+ ASSERT(dtrace_closef == dtrace_getf_barrier);
+ ASSERT(dtrace_getf > 0);
+
+ state->dts_cred.dcr_cred->cr_zone->zone_dtrace_getf--;
+
+ if (--dtrace_getf == 0)
+ dtrace_closef = NULL;
+ }
+#endif
+
return (0);
}
@@ -15519,6 +16438,25 @@ dtrace_toxrange_add(uintptr_t base, uintptr_t limit)
dtrace_toxranges++;
}
+static void
+dtrace_getf_barrier()
+{
+#if defined(sun)
+ /*
+ * When we have unprivileged (that is, non-DTRACE_CRV_KERNEL) enablings
+ * that contain calls to getf(), this routine will be called on every
+ * closef() before either the underlying vnode is released or the
+ * file_t itself is freed. By the time we are here, it is essential
+ * that the file_t can no longer be accessed from a call to getf()
+ * in probe context -- that assures that a dtrace_sync() can be used
+ * to clear out any enablings referring to the old structures.
+ */
+ if (curthread->t_procp->p_zone->zone_dtrace_getf != 0 ||
+ kcred->cr_zone->zone_dtrace_getf != 0)
+ dtrace_sync();
+#endif
+}
+
/*
* DTrace Driver Cookbook Functions
*/
@@ -16782,6 +17720,9 @@ dtrace_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
dtrace_modload = NULL;
dtrace_modunload = NULL;
+ ASSERT(dtrace_getf == 0);
+ ASSERT(dtrace_closef == NULL);
+
mutex_exit(&cpu_lock);
if (dtrace_helptrace_enabled) {
diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/sdt_subr.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/sdt_subr.c
index 66ff8a9..4d53e01 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/sdt_subr.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/sdt_subr.c
@@ -21,6 +21,7 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -85,11 +86,11 @@ static dtrace_pattr_t xpv_attr = {
sdt_provider_t sdt_providers[] = {
{ "vtrace", "__vtrace_", &vtrace_attr, 0 },
- { "sysinfo", "__cpu_sysinfo_", &info_attr, 0 },
- { "vminfo", "__cpu_vminfo_", &info_attr, 0 },
+ { "sysinfo", "__cpu_sysinfo_", &info_attr, DTRACE_PRIV_USER },
+ { "vminfo", "__cpu_vminfo_", &info_attr, DTRACE_PRIV_USER },
{ "fpuinfo", "__fpuinfo_", &fpu_attr, 0 },
- { "sched", "__sched_", &stab_attr, 0 },
- { "proc", "__proc_", &stab_attr, 0 },
+ { "sched", "__sched_", &stab_attr, DTRACE_PRIV_USER },
+ { "proc", "__proc_", &stab_attr, DTRACE_PRIV_USER },
{ "io", "__io_", &stab_attr, 0 },
{ "mib", "__mib_", &stab_attr, 0 },
{ "fsinfo", "__fsinfo_", &fsinfo_attr, 0 },
@@ -852,6 +853,20 @@ sdt_argdesc_t sdt_args[] = {
};
/*ARGSUSED*/
+int
+sdt_mode(void *arg, dtrace_id_t id, void *parg)
+{
+ /*
+ * We tell DTrace that we're in kernel mode, that the firing needs to
+ * be dropped for anything that doesn't have necessary privileges, and
+ * that it needs to be restricted for anything that has restricted
+ * (i.e., not all-zone) privileges.
+ */
+ return (DTRACE_MODE_KERNEL | DTRACE_MODE_NOPRIV_DROP |
+ DTRACE_MODE_LIMITEDPRIV_RESTRICT);
+}
+
+/*ARGSUSED*/
void
sdt_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc)
{
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/ctf_api.h b/sys/cddl/contrib/opensolaris/uts/common/sys/ctf_api.h
index def14b7..8e3f4ca 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/ctf_api.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/ctf_api.h
@@ -24,7 +24,7 @@
* Use is subject to license terms.
*/
/*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
/*
@@ -155,6 +155,7 @@ extern ctf_file_t *ctf_bufopen(const ctf_sect_t *, const ctf_sect_t *,
extern ctf_file_t *ctf_fdopen(int, int *);
extern ctf_file_t *ctf_open(const char *, int *);
extern ctf_file_t *ctf_create(int *);
+extern ctf_file_t *ctf_dup(ctf_file_t *);
extern void ctf_close(ctf_file_t *);
extern ctf_file_t *ctf_parent_file(ctf_file_t *);
@@ -180,6 +181,8 @@ extern ctf_id_t ctf_lookup_by_symbol(ctf_file_t *, ulong_t);
extern ctf_id_t ctf_type_resolve(ctf_file_t *, ctf_id_t);
extern ssize_t ctf_type_lname(ctf_file_t *, ctf_id_t, char *, size_t);
extern char *ctf_type_name(ctf_file_t *, ctf_id_t, char *, size_t);
+extern char *ctf_type_qname(ctf_file_t *, ctf_id_t, char *, size_t,
+ const char *);
extern ssize_t ctf_type_size(ctf_file_t *, ctf_id_t);
extern ssize_t ctf_type_align(ctf_file_t *, ctf_id_t);
extern int ctf_type_kind(ctf_file_t *, ctf_id_t);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
index eb377f4..831143f 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
@@ -25,8 +25,8 @@
*/
/*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#ifndef _SYS_DTRACE_H
@@ -311,8 +311,10 @@ typedef enum dtrace_probespec {
#define DIF_SUBR_SX_SHARED_HELD 48
#define DIF_SUBR_SX_EXCLUSIVE_HELD 49
#define DIF_SUBR_SX_ISEXCLUSIVE 50
-
-#define DIF_SUBR_MAX 50 /* max subroutine value */
+#define DIF_SUBR_GETF 52
+#define DIF_SUBR_JSON 53
+#define DIF_SUBR_STRTOLL 54
+#define DIF_SUBR_MAX 54 /* max subroutine value */
typedef uint32_t dif_instr_t;
@@ -374,6 +376,7 @@ typedef struct dtrace_diftype {
#define DIF_TYPE_STRING 1 /* type is a D string */
#define DIF_TF_BYREF 0x1 /* type is passed by reference */
+#define DIF_TF_BYUREF 0x2 /* user type is passed by reference */
/*
* A DTrace Intermediate Format variable record is used to describe each of the
@@ -1044,7 +1047,11 @@ typedef struct dtrace_fmtdesc {
#define DTRACEOPT_AGGSORTPOS 25 /* agg. position to sort on */
#define DTRACEOPT_AGGSORTKEYPOS 26 /* agg. key position to sort on */
#define DTRACEOPT_TEMPORAL 27 /* temporally ordered output */
-#define DTRACEOPT_MAX 28 /* number of options */
+#define DTRACEOPT_AGGHIST 28 /* histogram aggregation output */
+#define DTRACEOPT_AGGPACK 29 /* packed aggregation output */
+#define DTRACEOPT_AGGZOOM 30 /* zoomed aggregation scaling */
+#define DTRACEOPT_ZONE 31 /* zone in which to enable probes */
+#define DTRACEOPT_MAX 32 /* number of options */
#define DTRACEOPT_UNSET (dtrace_optval_t)-2 /* unset option */
@@ -1719,7 +1726,22 @@ typedef struct dof_helper {
*
* 1.10.3 Return value
*
- * A boolean value.
+ * A bitwise OR that encapsulates both the mode (either DTRACE_MODE_KERNEL
+ * or DTRACE_MODE_USER) and the policy when the privilege of the enabling
+ * is insufficient for that mode (a combination of DTRACE_MODE_NOPRIV_DROP,
+ * DTRACE_MODE_NOPRIV_RESTRICT, and DTRACE_MODE_LIMITEDPRIV_RESTRICT). If
+ * DTRACE_MODE_NOPRIV_DROP bit is set, insufficient privilege will result
+ * in the probe firing being silently ignored for the enabling; if the
+ * DTRACE_NODE_NOPRIV_RESTRICT bit is set, insufficient privilege will not
+ * prevent probe processing for the enabling, but restrictions will be in
+ * place that induce a UPRIV fault upon attempt to examine probe arguments
+ * or current process state. If the DTRACE_MODE_LIMITEDPRIV_RESTRICT bit
+ * is set, similar restrictions will be placed upon operation if the
+ * privilege is sufficient to process the enabling, but does not otherwise
+ * entitle the enabling to all zones. The DTRACE_MODE_NOPRIV_DROP and
+ * DTRACE_MODE_NOPRIV_RESTRICT are mutually exclusive (and one of these
+ * two policies must be specified), but either may be combined (or not)
+ * with DTRACE_MODE_LIMITEDPRIV_RESTRICT.
*
* 1.10.4 Caller's context
*
@@ -2114,6 +2136,12 @@ typedef struct dtrace_pops {
void (*dtps_destroy)(void *arg, dtrace_id_t id, void *parg);
} dtrace_pops_t;
+#define DTRACE_MODE_KERNEL 0x01
+#define DTRACE_MODE_USER 0x02
+#define DTRACE_MODE_NOPRIV_DROP 0x10
+#define DTRACE_MODE_NOPRIV_RESTRICT 0x20
+#define DTRACE_MODE_LIMITEDPRIV_RESTRICT 0x40
+
typedef uintptr_t dtrace_provider_id_t;
extern int dtrace_register(const char *, const dtrace_pattr_t *, uint32_t,
@@ -2334,6 +2362,7 @@ extern void (*dtrace_helpers_cleanup)(void);
extern void (*dtrace_helpers_fork)(proc_t *parent, proc_t *child);
extern void (*dtrace_cpustart_init)(void);
extern void (*dtrace_cpustart_fini)(void);
+extern void (*dtrace_closef)(void);
extern void (*dtrace_debugger_init)(void);
extern void (*dtrace_debugger_fini)(void);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h
index 7355aa8..1577a80 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h
@@ -934,6 +934,7 @@ typedef struct dtrace_mstate {
uintptr_t dtms_strtok; /* saved strtok() pointer */
uint32_t dtms_access; /* memory access rights */
dtrace_difo_t *dtms_difo; /* current dif object */
+ file_t *dtms_getf; /* cached rval of getf() */
} dtrace_mstate_t;
#define DTRACE_COND_OWNER 0x1
@@ -1166,6 +1167,7 @@ struct dtrace_state {
dtrace_optval_t dts_options[DTRACEOPT_MAX]; /* options */
dtrace_cred_t dts_cred; /* credentials */
size_t dts_nretained; /* number of retained enabs */
+ int dts_getf; /* number of getf() calls */
};
struct dtrace_provider {
diff --git a/sys/cddl/dev/dtrace/dtrace_cddl.h b/sys/cddl/dev/dtrace/dtrace_cddl.h
index d2adfbc..6caf3cf 100644
--- a/sys/cddl/dev/dtrace/dtrace_cddl.h
+++ b/sys/cddl/dev/dtrace/dtrace_cddl.h
@@ -133,6 +133,7 @@ typedef struct kdtrace_thread {
#define t_procp td_proc
#define t_tid td_tid
#define t_did td_tid
+#define t_cred td_ucred
int priv_policy(const cred_t *, int, boolean_t, int, const char *);
diff --git a/sys/modules/dtrace/dtrace/Makefile b/sys/modules/dtrace/dtrace/Makefile
index 52f87d0..c1dade0 100644
--- a/sys/modules/dtrace/dtrace/Makefile
+++ b/sys/modules/dtrace/dtrace/Makefile
@@ -40,6 +40,7 @@ CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris \
-I${.CURDIR}/../../../cddl/dev/dtrace \
-I${.CURDIR}/../../../cddl/dev/dtrace/${ARCHDIR} \
-I${.CURDIR}/../../../cddl/contrib/opensolaris/uts/common \
+ -I${.CURDIR}/../../../../cddl/contrib/opensolaris/common/util \
-I${.CURDIR}/../../.. -DDIS_MEM
CFLAGS+= -DSMP
OpenPOWER on IntegriCloud