diff options
Diffstat (limited to 'cddl/contrib')
72 files changed, 4046 insertions, 580 deletions
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1 b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1 index 8724b27f4cbb..ab8c672a95a1 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1 +++ b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1 @@ -20,7 +20,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 7, 2021 +.Dd September 8, 2023 .Dt DTRACE 1 .Os .Sh NAME @@ -29,7 +29,8 @@ .Sh SYNOPSIS .Nm .Op Fl 32 | Fl 64 -.Op Fl aACeFGhHlqSvVwZ +.Op Fl aACdeFGhHlOqSvVwZ +.Op Fl -libxo .Op Fl b Ar bufsz .Op Fl c Ar cmd .Op Fl D Ar name Op Ns = Ns value @@ -195,6 +196,12 @@ option. For a description of the set of tokens defined by the D compiler when invoking the C preprocessor, see .Fl X . +.It Fl d +Dump the D script to standard output, after syntactic transformations have been +applied. +For example, if-statements in D are implemented using such transformations: a +conditional clause in a probe body is replaced at compile-time by a separate +probe predicated on the original condition. .It Fl D Ar name Op Ns = Ns value Define .Ar name @@ -351,6 +358,11 @@ writing D programs. The specified .Ar path is added after the default library search path. +.It Fl -libxo +Generate output via +.Xr libxo 3 . +This option is the same as specifying +.Sy oformat . .It Fl m Oo Ar provider : Oc Ar module Oo Oo Ar predicate Oc Ar action Oc Specify module name to trace or list .Fl ( l @@ -394,6 +406,14 @@ argument can be suffixed with an optional D probe clause. More than one .Fl n option can be specified on the command line at a time. +.It Fl O +This option causes +.Nm +to print all the aggregations upon exiting if +.Sy oformat +or +.Fl -libxo +are specified. .It Fl o Ar output Specify the .Ar output @@ -646,6 +666,32 @@ Number of whitespace characters to use when indenting and .Fn ustack output. +.It Sy oformat Ns = Ns Ar format +Specify the format to use for output. +Setting +.Sy oformat +to +.Ql text +makes +.Nm +use regular human-readable output which is its default behavior. +The options passed to +.Sy oformat +are directly forwarded to +.Xr libxo 3 . +Some of the supported formatters include +.Ql json , +.Ql xml +and +.Ql html . +Note that this option will cause +.Nm +to not produce any output unless printing functions are explicitly called, +or the +.Fl O +flag is specified. +For more information see +.Sx STRUCTURED OUTPUT . .It Sy statusrate Ns = Ns Ar time Rate of status checking. .It Sy switchrate Ns = Ns Ar time @@ -772,6 +818,376 @@ or .Fl i options) contain descriptions that do not match any known probes. .El +.Sh STRUCTURED OUTPUT +.Nm +supports structured output using +.Xr libxo 3 . +The output will always have a top-level object called +.Dq dtrace , +followed by a list of objects +.Dq probes . +Each of the probe objects will to have a timestamp which is generated at +output time rather than probe firing time, an identifier for the CPU on +which the probe was executed, and the probe's full specification: +.Bd -literal +{ + "dtrace": { + "probes": [ + { + "timestamp": ..., + "cpu": ..., + "id": ..., + "provider": ..., + "module": ..., + "function": ..., + "name": ..., + "output": [ + ... (script-specific output) + ] + } + ] + } +} + +<?xml version="1.0"?> +<dtrace> + <probes> + <timestamp>...</timestamp> + <cpu>...</cpu> + <id>...</id> + <provider>...</provider> + <module>...</module> + <function>...</function> + <name>...</name> + <output> + ... (script-specific output) + </output> + </probes> +</dtrace> +.Ed +.Pp +It is also possible for XML output to take the following form if some +of the fields are empty (in this example, module and function values +are absent): +.Bd -literal +<?xml version="1.0"?> +<dtrace> + <probes> + ... + <module/> + <function/> + ... + <output> + ... (script-specific output) + </output> + </probes> +</dtrace> +.Ed +.Pp +Similarly, +.Sy oformat +can be used to generate HTML: +.Bd -literal +<div class="line"> +<div class="data" data-tag="timestamp">...</div> +<div class="text"></div> +<div class="data" data-tag="cpu">...</div> +<div class="text"></div> +<div class="data" data-tag="id">...</div> +<div class="text"></div> +<div class="data" data-tag="provider">...</div> +<div class="text"></div> +<div class="data" data-tag="module">...</div> +<div class="text"></div> +<div class="data" data-tag="function">...</div> +<div class="text"></div> +<div class="data" data-tag="name">...</div> +<div class="data" data-tag="... (script-specific output)">...</div> +</div> +.Ed +.Pp +Unlike JSON and XML, the +.Dq output +array is not present. +Instead, data is simply formatted into a div of class +.Dq data +and a data-tag is associated with each of the keys. +.Pp +The +.Dq output +array's contents depend on the probes' actions and is explained below. +The examples here are presented in JSON form as opposed to XML or HTML, +however the conversion explained above applies for all output formats. +.Pp +Any scalar output, such as output produced by the +.Fn trace +action is of form: +.Bd -literal +{ + "value": ... +} +.Ed +.Pp +The +.Fn printf +action begins with an object containing the formatted output of the +.Fn printf +action. +Subsequent objects contains the value of each of the arguments to +.Fn printf +in its raw form as if the +.Fn trace +action was used instead. +A +.Fn printf +statement which contains no arguments other than the message will only have +one object following the message object and its value will always be 0. +This is an artefact of the implementation and can safely be ignored. +.Bd -literal +# dtrace --libxo json,pretty -n 'BEGIN { printf("... %Y, ..", walltimestamp); }' + +{ + "message": "... 2023 Sep 7 16:49:02, .." +}, +{ + "value": 1694105342633402400 +}, +{ + ... +} +.Ed +.Pp +Scalar aggregations are aggregations which produce a single value for a given +key. +These aggregations include +.Fn count , +.Fn min , +.Fn max , +.Fn stddev +and +.Fn sum . +Each one of them is represented by the key containing their name. +For example, the output of a +.Fn stddev +aggregation will contain a key +.Dq stddev +inside an +.Dq aggregation-data +object: +.Bd -literal +{ + "aggregation-data": [ + { + "keys": [ + ... + ], + "stddev": ... + } + ], + "aggregation-name": ... +} +.Ed +.Pp +The +.Dq keys +field remains consistent across all aggregations, however +.Fn quantize , +.Fn lquantize +and +.Fn llquantize +need to be treated differently. +.Sy oformat +will create a new array of objects called +.Dq buckets . +Each of the objects contains a +.Dq value +and a +.Dq count +field which are +the left-hand side and the right-hand side of human-readable +.Nm +output respectively. +The full object has the following format: +.Bd -literal +{ + "aggregation-data": [ + ... + { + "keys": [ + ... + ], + "buckets": [ + { + "value": 32, + "count": 0 + }, + { + "value": 64, + "count": 17 + }, + ... + ], + }, + ... + ] + "aggregation-name": ... +} +.Ed +.Pp +Similar to scalar aggregations, named scalar actions such as +.Fn mod , +.Fn umod , +.Fn usym , +.Fn tracemem +and +.Fn printm +will output an object with the key being equal to the +name of the action. +For example, +.Fn printm +output would produce the following object: +.Bd -literal +{ + "printm": "0x4054171100" +} +.Ed +.Pp +.Fn sym +is slightly different. +While it will create a +.Dq sym +field which contains its value, in some cases it will also create additional +fields +.Dq object , +.Dq name +and +.Dq offset : +.Bd -literal +# dtrace -x oformat=json,pretty -On 'BEGIN { sym((uintptr_t)&`prison0); }' + +{ + "sym": "kernel`prison0", + "object": "kernel", + "name": "prison0" +} + +# dtrace --libxo json,pretty -On 'BEGIN { sym((uintptr_t)curthread); }' + +{ + "sym": "0xfffffe00c18d2000", + "offset": "0xfffffe00c18d2000" +} +.Ed +.Pp +.Fn stack +and +.Fn ustack +actions unroll each of the stack frames into its own object in an array. +The only real difference between them is that the +.Fn stack +action will produce a list called +.Dq stack-frames +while +.Fn ustack +will produce one called +.Dq ustack-frames . +The following is an example of their +.Sy oformat +output: +.Bd -literal +{ + "stack-frames": [ + { + "symbol": "dtrace.ko`dtrace_dof_create+0x35", + "module": "dtrace.ko", + "name": "dtrace_dof_create", + "offset": "0x35" + }, + { + "symbol": "dtrace.ko`dtrace_ioctl+0x81c", + "module": "dtrace.ko", + "name": "dtrace_ioctl", + "offset": "0x81c" + }, + ... + ] +} + +{ + "ustack-frames": [ + { + "symbol": "libc.so.7`ioctl+0xa", + "module": "libc.so.7", + "name": "ioctl", + "offset": "0xa" + }, + { + "symbol": "libdtrace.so.2`dtrace_go+0xf3", + "module": "libdtrace.so.2", + "name": "dtrace_go", + "offset": "0xf3" + }, + ... + ] +} +.Ed +.Pp +The +.Fn print +action produces a +.Dq type +list in the following form: +.Bd -literal +{ + "type": [ + { + "object-name": "kernel", + "name": "struct thread", + "ctfid": 2372 + }, + { + "member-name": "td_lock", + "name": "struct mtx *volatile", + "ctfid": 2035, + "value": "0xffffffff82158440" + }, + ... +} +.Ed +.Pp +If the type is invalid, a +.Dq warning +object will be produced containing the diagnostic message as well as two +possible optional fields: +.Dq type-identifier +which contains the CTF identifier of the type and +.Dq size containing the size of an integer, enum or float. +The fields generated will depend on the kind of error that was encountered +while processing the trace data. +.Pp +Finally, +.Sy oformat +provides a special pseudo-probe to represent drops. +As +.Nm +polls for various kinds of drops +.Sy oformat +will produce output similar to the following in order to represent drops: +.Bd -literal +{ + "cpu": -1, + "id": -1, + "provider": "dtrace", + "module": "INTERNAL", + "function": "INTERNAL", + "name": "DROP", + "timestamp": ..., + "count": ..., + "total": ..., + "kind": 2, + "msg": "... dynamic variable drops\n" +} +.Ed .Sh OPERANDS You can specify zero or more additional arguments on the .Nm @@ -803,11 +1219,6 @@ failed or that the specified request could not be satisfied. .It 2 Invalid command line options or arguments were specified. .El -.Sh HISTORY -The -.Nm -utility first appeared in -.Fx 7.1 . .Sh SEE ALSO .Xr cpp 1 , .Xr elf 5 , @@ -815,3 +1226,8 @@ utility first appeared in .Rs .%T Solaris Dynamic Tracing Guide .Re +.Sh HISTORY +The +.Nm +utility first appeared in +.Fx 7.1 . diff --git a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c index 06eff2055c17..dc68c6ef5f72 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c +++ b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.c @@ -26,6 +26,7 @@ /* * Copyright (c) 2012 by Delphix. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright (c) 2023, Domagoj Stolfa. All rights reserved. */ #include <sys/types.h> @@ -55,6 +56,9 @@ #include <spawn.h> #endif +#undef NORETURN /* needed because libxo redefines it */ +#include <libxo/xo.h> + typedef struct dtrace_cmd { void (*dc_func)(struct dtrace_cmd *); /* function to compile arg */ dtrace_probespec_t dc_spec; /* probe specifier context */ @@ -77,7 +81,7 @@ typedef struct dtrace_cmd { #define E_USAGE 2 static const char DTRACE_OPTSTR[] = - "3:6:aAb:Bc:CD:ef:FGhHi:I:lL:m:n:o:p:P:qs:SU:vVwx:X:Z"; + "3:6:aAb:Bc:CdD:ef:FGhHi:I:lL:m:n:o:Op:P:qs:SU:vVwx:X:Z"; static char **g_argv; static int g_argc; @@ -130,7 +134,7 @@ usage(FILE *fp) { static const char predact[] = "[[ predicate ] action ]"; - (void) fprintf(fp, "Usage: %s [-32|-64] [-aACeFGhHlqSvVwZ] " + (void) fprintf(fp, "Usage: %s [-32|-64] [-aACdeFGhHlqSvVwZ] " "[-b bufsz] [-c cmd] [-D name[=def]]\n\t[-I path] [-L path] " "[-o output] [-p pid] [-s script] [-U name]\n\t" "[-x opt[=val]] [-X a|c|s|t]\n\n" @@ -152,6 +156,7 @@ usage(FILE *fp) "\t-b set trace buffer size\n" "\t-c run specified command and exit upon its completion\n" "\t-C run cpp(1) preprocessor on script files\n" + "\t-d dump script after syntactic transformations\n" "\t-D define symbol when invoking preprocessor\n" "\t-e exit after compiling request but prior to enabling probes\n" "\t-f enable or list probes matching the specified function name\n" @@ -166,6 +171,7 @@ usage(FILE *fp) "\t-m enable or list probes matching the specified module name\n" "\t-n enable or list probes matching the specified probe name\n" "\t-o set output file\n" + "\t-O print output upon exiting (specific to oformat)\n" "\t-p grab specified process-ID and cache its symbol tables\n" "\t-P enable or list probes matching the specified provider name\n" "\t-q set quiet mode (only output explicitly traced data)\n" @@ -906,7 +912,10 @@ errhandler(const dtrace_errdata_t *data, void *arg) static int drophandler(const dtrace_dropdata_t *data, void *arg) { - error(data->dtdda_msg); + if (!dtrace_oformat(g_dtp)) { + error(data->dtdda_msg); + } + return (DTRACE_HANDLE_OK); } @@ -1125,7 +1134,9 @@ chew(const dtrace_probedata_t *data, void *arg) } if (!g_flowindent) { - if (!g_quiet) { + if (dtrace_oformat(g_dtp)) { + dtrace_oformat_probe(g_dtp, data, cpu, pd); + } else if (!g_quiet) { char name[DTRACE_FUNCNAMELEN + DTRACE_NAMELEN + 2]; (void) snprintf(name, sizeof (name), "%s:%s", @@ -1312,7 +1323,8 @@ main(int argc, char *argv[]) g_ofp = stdout; int done = 0, mode = 0; - int err, i, c; + int err, i, c, new_argc, libxo_specified; + int print_upon_exit = 0; char *p, **v; struct ps_prochandle *P; pid_t pid; @@ -1335,6 +1347,15 @@ main(int argc, char *argv[]) (g_psv = malloc(sizeof (struct ps_prochandle *) * argc)) == NULL) fatal("failed to allocate memory for arguments"); + new_argc = xo_parse_args(argc, argv); + if (new_argc < 0) + return (usage(stderr)); + + if (new_argc != argc) + libxo_specified = 1; + + argc = new_argc; + g_argv[g_argc++] = argv[0]; /* propagate argv[0] to D as $0/$$0 */ argv[0] = g_pname; /* rewrite argv[0] for getopt errors */ @@ -1531,6 +1552,10 @@ main(int argc, char *argv[]) } else if (g_mode == DMODE_ANON) (void) dtrace_setopt(g_dtp, "linkmode", "primary"); + + if (libxo_specified) + dtrace_oformat_configure(g_dtp); + /* * Now that we have libdtrace open, make a second pass through argv[] * to perform any dtrace_setopt() calls and change any compiler flags. @@ -1559,6 +1584,10 @@ main(int argc, char *argv[]) g_cflags |= DTRACE_C_CPP; break; + case 'd': + g_cflags |= DTRACE_C_SUGAR; + break; + case 'D': if (dtrace_setopt(g_dtp, "define", optarg) != 0) dfatal("failed to set -D %s", optarg); @@ -1619,6 +1648,10 @@ main(int argc, char *argv[]) dcp->dc_arg = optarg; break; + case 'O': + print_upon_exit = 1; + break; + case 'q': if (dtrace_setopt(g_dtp, "quiet", 0) != 0) dfatal("failed to set -q"); @@ -1760,6 +1793,11 @@ main(int argc, char *argv[]) (void) dtrace_getopt(g_dtp, "quiet", &opt); g_quiet = opt != DTRACEOPT_UNSET; + if (dtrace_oformat(g_dtp)) { + if (dtrace_setopt(g_dtp, "quiet", 0) != 0) + dfatal("failed to set quiet (caused by oformat)"); + } + /* * Now make a fifth and final pass over the options that have been * turned into programs and saved in g_cmdv[], performing any mode- @@ -1772,6 +1810,9 @@ main(int argc, char *argv[]) if (g_ofile != NULL && (g_ofp = fopen(g_ofile, "a")) == NULL) fatal("failed to open output file '%s'", g_ofile); + if (dtrace_oformat(g_dtp)) + dtrace_set_outfp(g_ofp); + for (i = 0; i < g_cmdc; i++) exec_prog(&g_cmdv[i]); @@ -1806,6 +1847,9 @@ main(int argc, char *argv[]) if ((g_ofp = fopen(g_ofile, "a")) == NULL) fatal("failed to open output file '%s'", g_ofile); + if (dtrace_oformat(g_dtp)) + dtrace_set_outfp(g_ofp); + for (i = 0; i < g_cmdc; i++) { anon_prog(&g_cmdv[i], dtrace_dof_create(g_dtp, g_cmdv[i].dc_prog, 0), i); @@ -1966,12 +2010,21 @@ main(int argc, char *argv[]) g_pslive = g_psc; /* count for prochandler() */ + dtrace_oformat_setup(g_dtp); do { if (!g_intr && !done) dtrace_sleep(g_dtp); #ifdef __FreeBSD__ - if (g_siginfo) { + /* + * XXX: Supporting SIGINFO with oformat makes little sense, as + * it can't really produce sensible DTrace output. + * + * If needed, we could support it by having an imaginary + * "SIGINFO" probe that we can construct in the output but leave + * it out for now. + */ + if (g_siginfo && !dtrace_oformat(g_dtp)) { (void)dtrace_aggregate_print(g_dtp, g_ofp, NULL); g_siginfo = 0; } @@ -2008,14 +2061,24 @@ main(int argc, char *argv[]) clearerr(g_ofp); } while (!done); - oprintf("\n"); + if (!dtrace_oformat(g_dtp)) + oprintf("\n"); - if (!g_impatient) { + /* + * Since there is no way to format a probe here and machine-readable + * output makes little sense without explicitly asking for it, we print + * nothing upon Ctrl-C if oformat is specified. If the user wishes to + * get output upon exit, they must write an explicit dtrace:::END probe + * to do so. + */ + if ((!g_impatient && !dtrace_oformat(g_dtp)) || + (!g_impatient && print_upon_exit)) { if (dtrace_aggregate_print(g_dtp, g_ofp, NULL) == -1 && dtrace_errno(g_dtp) != EINTR) dfatal("failed to print aggregations"); } + dtrace_oformat_teardown(g_dtp); dtrace_close(g_dtp); return (g_status); } diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv6localicmp.ksh.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv6localicmp.ksh.out index 2e94ff35de88..7f7368f13900 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv6localicmp.ksh.out +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv6localicmp.ksh.out @@ -1,6 +1,6 @@ -PING6(56=40+8+8 bytes) ::1 --> ::1 +PING(56=40+8+8 bytes) ::1 --> ::1 1 packets transmitted, 1 packets received, 0.0% packet loss 2 ip:::send (args[2]: 6 16, args[5]: 6 0 16) 2 ip:::send (args[2]: 6 16, args[5]: 6 0 16) diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/kinst/tst.basic.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/kinst/tst.basic.ksh new file mode 100644 index 000000000000..3005da74c895 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/kinst/tst.basic.ksh @@ -0,0 +1,48 @@ +#!/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) 2022 Mark Johnston <markj@FreeBSD.org> +# + +script() +{ + $dtrace -q -s /dev/stdin <<__EOF__ +kinst::vm_fault: {} +kinst::amd64_syscall: {} +kinst::exit1: {} +kinst::spinlock_enter: {} +kinst::memcpy: {} + +tick-10s {exit(0);} +__EOF__ +} + +spin() +{ + while true; do + ls -la / >/dev/null 2>&1 + done +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +spin & +child=$! + +script +exit $? diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/mib/tst.icmp.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/mib/tst.icmp.ksh index b1cac20fc8db..6def4da1062b 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/mib/tst.icmp.ksh +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/mib/tst.icmp.ksh @@ -59,7 +59,7 @@ pinger() { while true; do ping -A inet localhost - /usr/bin/sleep 1 + sleep 1 done } diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/mib/tst.udp.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/mib/tst.udp.ksh index a492124c9c17..10a83cbd06fd 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/mib/tst.udp.ksh +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/mib/tst.udp.ksh @@ -54,7 +54,7 @@ rupper() { while true; do rup localhost - /usr/bin/sleep 1 + sleep 1 done } diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.avg.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.avg.ksh new file mode 100644 index 000000000000..daf5c7f4e9bb --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.avg.ksh @@ -0,0 +1,66 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + @[probefunc] = avg(tid); +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.count.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.count.ksh new file mode 100644 index 000000000000..ab7c5fa28471 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.count.ksh @@ -0,0 +1,66 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + @[execname] = count(); +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.llquantize.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.llquantize.ksh new file mode 100644 index 000000000000..380335de000a --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.llquantize.ksh @@ -0,0 +1,73 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + self->ts = timestamp; +} + +syscall:::return +/self->ts/ +{ + @[probefunc] = llquantize(timestamp - self->ts, 2, 1, 32, 32); + self->ts = 0; +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.lquantize.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.lquantize.ksh new file mode 100644 index 000000000000..5ec6c725a7f0 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.lquantize.ksh @@ -0,0 +1,73 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + self->ts = timestamp; +} + +syscall:::return +/self->ts/ +{ + @[probefunc] = lquantize(timestamp - self->ts, 0, 1000000, 100); + self->ts = 0; +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.max.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.max.ksh new file mode 100644 index 000000000000..45f790aae030 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.max.ksh @@ -0,0 +1,66 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + @[probefunc] = max(tid); +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.min.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.min.ksh new file mode 100644 index 000000000000..6f40acdfff40 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.min.ksh @@ -0,0 +1,66 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + @[probefunc] = min(tid); +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.quantize.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.quantize.ksh new file mode 100644 index 000000000000..c0ba0f4a6c0f --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.quantize.ksh @@ -0,0 +1,73 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + self->ts = timestamp; +} + +syscall:::return +/self->ts/ +{ + @[probefunc] = quantize(timestamp - self->ts); + self->ts = 0; +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.stddev.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.stddev.ksh new file mode 100644 index 000000000000..7b06a67b9a8a --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.stddev.ksh @@ -0,0 +1,66 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + @[probefunc] = stddev(tid); +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.sum.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.sum.ksh new file mode 100644 index 000000000000..f7c323c6baac --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.sum.ksh @@ -0,0 +1,66 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + @[probefunc] = sum(1); +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggmod.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggmod.ksh new file mode 100644 index 000000000000..335819cbcfc9 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggmod.ksh @@ -0,0 +1,66 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + @[mod((uintptr_t)rand())] = count(); +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggstack.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggstack.ksh new file mode 100644 index 000000000000..30af498c2498 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggstack.ksh @@ -0,0 +1,66 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +fbt:::entry +{ + @[stack()] = count(); +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggsym.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggsym.ksh new file mode 100644 index 000000000000..d0da3e5086ed --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggsym.ksh @@ -0,0 +1,66 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + @[sym((uintptr_t)rand())] = count(); +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggustack.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggustack.ksh new file mode 100644 index 000000000000..98cf2a0562a4 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggustack.ksh @@ -0,0 +1,66 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + @[ustack()] = count(); +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggusym.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggusym.ksh new file mode 100644 index 000000000000..7945b83250c3 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggusym.ksh @@ -0,0 +1,66 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + @[usym((uintptr_t)rand())] = count(); +} + +tick-5s +{ + exit(0); +} + +END +{ + printa(@); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.drop.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.drop.ksh new file mode 100644 index 000000000000..7f17c321ff74 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.drop.ksh @@ -0,0 +1,61 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +fbt:::entry +{ + x[timestamp] = 1; +} + +tick-5s +{ + exit(0); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.mod.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.mod.ksh new file mode 100644 index 000000000000..b0e6ce3cc380 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.mod.ksh @@ -0,0 +1,57 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +BEGIN +{ + mod(0); + exit(0); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.print.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.print.ksh new file mode 100644 index 000000000000..68d675f20329 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.print.ksh @@ -0,0 +1,60 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +BEGIN +{ + print(*curthread); + print(*curthread->td_proc); + print(*curthread->td_ucred); + print(*curthread->td_ucred->cr_prison); + exit(0); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.printf.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.printf.ksh new file mode 100644 index 000000000000..a25352c4a1ca --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.printf.ksh @@ -0,0 +1,57 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +BEGIN +{ + printf("Hello World!"); + exit(0); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.printm.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.printm.ksh new file mode 100644 index 000000000000..634606fa574e --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.printm.ksh @@ -0,0 +1,57 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +BEGIN +{ + printm(100, memref(curthread, 10)); + exit(0); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.stack.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.stack.ksh new file mode 100644 index 000000000000..33d1ee6dc1d7 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.stack.ksh @@ -0,0 +1,61 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + stack(); +} + +tick-1s +{ + exit(0); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.sym.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.sym.ksh new file mode 100644 index 000000000000..5e9bb3fea58e --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.sym.ksh @@ -0,0 +1,57 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +BEGIN +{ + sym(0); + exit(0); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.trace.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.trace.ksh new file mode 100644 index 000000000000..42f714a1a500 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.trace.ksh @@ -0,0 +1,66 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +BEGIN +{ + trace(0); + trace(1); + trace(2); + trace(3); + trace(4); + trace(5); + trace(6); + trace(7); + trace(8); + trace(9); + exit(0); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.tracemem.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.tracemem.ksh new file mode 100644 index 000000000000..dd9dbff3c191 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.tracemem.ksh @@ -0,0 +1,57 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +BEGIN +{ + tracemem(curthread, 10); + exit(0); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.umod.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.umod.ksh new file mode 100644 index 000000000000..0d50e34dfff1 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.umod.ksh @@ -0,0 +1,57 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +BEGIN +{ + umod(0); + exit(0); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.ustack.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.ustack.ksh new file mode 100644 index 000000000000..1b1cc0a247d3 --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.ustack.ksh @@ -0,0 +1,61 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +syscall:::entry +{ + ustack(); +} + +tick-1s +{ + exit(0); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.usym.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.usym.ksh new file mode 100644 index 000000000000..36372d05aa2f --- /dev/null +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.usym.ksh @@ -0,0 +1,57 @@ +#!/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) 2023 Domagoj Stolfa +# + +bname=`basename $0` +dtraceout=/tmp/dtrace.$bname + +script() +{ + $dtrace -o $dtraceout.$1 -x oformat=$1 -s /dev/stdin <<__EOF__ +BEGIN +{ + usym(0); + exit(0); +} +__EOF__ +} + +if [ $# != 1 ]; then + echo expected one argument: '<'dtrace-path'>' + exit 2 +fi + +dtrace=$1 + +script json +jq . $dtraceout.json + +if [ $? != 0 ]; then + echo $bname: failed to produce valid JSON. see $dtraceout.json + exit 1 +fi + +script xml +xmllint $dtraceout.xml + +if [ $? != 0 ]; then + echo $bname: failed to produce valid XML. see $dtraceout.xml + exit 1 +fi + +rm $dtraceout.json +rm $dtraceout.xml + +exit 0 diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PDESC_ZERO.badlib.exe b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PDESC_ZERO.badlib.exe index e360d25b465b..4985133fb2a6 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PDESC_ZERO.badlib.exe +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PDESC_ZERO.badlib.exe @@ -1,4 +1,4 @@ -#!/usr/bin/env ksh +#!/usr/local/bin/ksh -p # # CDDL HEADER START # diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_FUNC.badfunc.exe b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_FUNC.badfunc.exe index e360d25b465b..4985133fb2a6 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_FUNC.badfunc.exe +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_FUNC.badfunc.exe @@ -1,4 +1,4 @@ -#!/usr/bin/env ksh +#!/usr/local/bin/ksh -p # # CDDL HEADER START # diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_LIB.libdash.exe b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_LIB.libdash.exe index e360d25b465b..4985133fb2a6 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_LIB.libdash.exe +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_LIB.libdash.exe @@ -1,4 +1,4 @@ -#!/usr/bin/env ksh +#!/usr/local/bin/ksh -p # # CDDL HEADER START # diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.alldash.exe b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.alldash.exe index e360d25b465b..4985133fb2a6 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.alldash.exe +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.alldash.exe @@ -1,4 +1,4 @@ -#!/usr/bin/env ksh +#!/usr/local/bin/ksh -p # # CDDL HEADER START # diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.badname.exe b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.badname.exe index e360d25b465b..4985133fb2a6 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.badname.exe +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.badname.exe @@ -1,4 +1,4 @@ -#!/usr/bin/env ksh +#!/usr/local/bin/ksh -p # # CDDL HEADER START # diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.globdash.exe b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.globdash.exe index e360d25b465b..4985133fb2a6 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.globdash.exe +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.globdash.exe @@ -1,4 +1,4 @@ -#!/usr/bin/env ksh +#!/usr/local/bin/ksh -p # # CDDL HEADER START # diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_OFF.toobig.exe b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_OFF.toobig.exe index e360d25b465b..4985133fb2a6 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_OFF.toobig.exe +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_OFF.toobig.exe @@ -1,4 +1,4 @@ -#!/usr/bin/env ksh +#!/usr/local/bin/ksh -p # # CDDL HEADER START # diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/tst.coverage.exe b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/tst.coverage.exe index ddd0f60f63ce..b9365eaafe3d 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/tst.coverage.exe +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/tst.coverage.exe @@ -1,4 +1,4 @@ -#!/usr/bin/env ksh +#!/usr/local/bin/ksh -p # # CDDL HEADER START # diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/tst.emptystack.exe b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/tst.emptystack.exe index 6369bc561412..9b9e2659786d 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/tst.emptystack.exe +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/tst.emptystack.exe @@ -1,4 +1,4 @@ -#!/usr/bin/env ksh +#!/usr/local/bin/ksh -p # # CDDL HEADER START # diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/proc/tst.startexit.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/proc/tst.startexit.ksh index 429173806f35..76996bfcb413 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/proc/tst.startexit.ksh +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/proc/tst.startexit.ksh @@ -68,7 +68,7 @@ EOF sleeper() { while true; do - /usr/bin/sleep 1 + sleep 1 done } diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/speculation/tst.NoSpecBuffer.exe b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/speculation/tst.NoSpecBuffer.exe index 5acce76efc6c..d15d0668cfc1 100644 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/speculation/tst.NoSpecBuffer.exe +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/speculation/tst.NoSpecBuffer.exe @@ -1,4 +1,4 @@ -#!/usr/bin/env ksh +#!/usr/local/bin/ksh -p # # CDDL HEADER START # diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/i86xpv/xdt/tst.schedargs.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/i86xpv/xdt/tst.schedargs.ksh index 5b14fc989138..c74a278c1347 100755 --- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/i86xpv/xdt/tst.schedargs.ksh +++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/i86xpv/xdt/tst.schedargs.ksh @@ -45,7 +45,7 @@ outf=/tmp/sched.args.$$ script() { - $dtrace -c '/usr/bin/sleep 10' -o $outf -qs /dev/stdin <<EOF + $dtrace -c 'sleep 10' -o $outf -qs /dev/stdin <<EOF xdt:sched::off-cpu, xdt:sched::on-cpu, xdt:sched::block, diff --git a/cddl/contrib/opensolaris/cmd/lockstat/lockstat.1 b/cddl/contrib/opensolaris/cmd/lockstat/lockstat.1 index c649e21bb67e..6c9657fa5406 100644 --- a/cddl/contrib/opensolaris/cmd/lockstat/lockstat.1 +++ b/cddl/contrib/opensolaris/cmd/lockstat/lockstat.1 @@ -19,8 +19,6 @@ .\" CDDL HEADER END .\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved. .\" -.\" $FreeBSD$ -.\" .Dd February 25, 2020 .Dt LOCKSTAT 1 .Os diff --git a/cddl/contrib/opensolaris/cmd/lockstat/lockstat.c b/cddl/contrib/opensolaris/cmd/lockstat/lockstat.c index 2fd29843b8ce..2cbad3442efb 100644 --- a/cddl/contrib/opensolaris/cmd/lockstat/lockstat.c +++ b/cddl/contrib/opensolaris/cmd/lockstat/lockstat.c @@ -632,7 +632,7 @@ predicate_destroy(char **pred) } static void -filter_add(char **filt, char *what, uintptr_t base, uintptr_t size) +filter_add(char **filt, char *what, uintptr_t base, size_t size) { char buf[256], *c = buf, *new; int len, newlen; diff --git a/cddl/contrib/opensolaris/cmd/lockstat/sym.c b/cddl/contrib/opensolaris/cmd/lockstat/sym.c index b5366c566857..7516e7d435f4 100644 --- a/cddl/contrib/opensolaris/cmd/lockstat/sym.c +++ b/cddl/contrib/opensolaris/cmd/lockstat/sym.c @@ -42,6 +42,7 @@ #include <libelf.h> #include <link.h> #include <elf.h> +#include <gelf.h> #ifdef illumos #include <sys/machelf.h> @@ -54,7 +55,6 @@ #endif #include <sys/cpuvar.h> - typedef struct syment { uintptr_t addr; char *name; @@ -73,11 +73,6 @@ static char maxsymname[64]; #endif #endif -#define __sElfN(x) typedef __CONCAT(__CONCAT(__CONCAT(Elf,__ELF_WORD_SIZE),_),x) x -__sElfN(Sym); -__sElfN(Shdr); -#define elf_getshdr __elfN(getshdr) - static void add_symbol(char *name, uintptr_t addr, size_t size) { @@ -174,7 +169,7 @@ symtab_init(void) { Elf *elf; Elf_Scn *scn = NULL; - Sym *symtab, *symp, *lastsym; + GElf_Sym *symtab, *symp, *lastsym; char *strtab; uint_t cnt; int fd; @@ -198,13 +193,13 @@ symtab_init(void) (void) elf_version(EV_CURRENT); elf = elf_begin(fd, ELF_C_READ, NULL); - for (cnt = 1; (scn = elf_nextscn(elf, scn)) != NULL; cnt++) { - Shdr *shdr = elf_getshdr(scn); - if (shdr->sh_type == SHT_SYMTAB) { - symtab = (Sym *)elf_getdata(scn, NULL)->d_buf; - nsyms = shdr->sh_size / shdr->sh_entsize; - strindex = shdr->sh_link; + GElf_Shdr shdr; + (void) gelf_getshdr(scn, &shdr); + if (shdr.sh_type == SHT_SYMTAB) { + symtab = (GElf_Sym *)elf_getdata(scn, NULL)->d_buf; + nsyms = shdr.sh_size / shdr.sh_entsize; + strindex = shdr.sh_link; } } diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c index 5ea55a05faf0..643e7fae8ace 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c @@ -35,6 +35,7 @@ #include <unistd.h> #include <dt_impl.h> #include <assert.h> +#include <dt_oformat.h> #ifdef illumos #include <alloca.h> #else @@ -471,9 +472,14 @@ dt_aggregate_snap_cpu(dtrace_hdl_t *dtp, processorid_t cpu) } if (buf->dtbd_drops != 0) { + xo_open_instance("probes"); + dt_oformat_drop(dtp, cpu); if (dt_handle_cpudrop(dtp, cpu, - DTRACEDROP_AGGREGATION, buf->dtbd_drops) == -1) + DTRACEDROP_AGGREGATION, buf->dtbd_drops) == -1) { + xo_close_instance("probes"); return (-1); + } + xo_close_instance("probes"); } if (buf->dtbd_size == 0) @@ -2127,8 +2133,13 @@ dtrace_aggregate_print(dtrace_hdl_t *dtp, FILE *fp, if (func == NULL) func = dtrace_aggregate_walk_sorted; - if ((*func)(dtp, dt_print_agg, &pd) == -1) - return (dt_set_errno(dtp, dtp->dt_errno)); + if (dtp->dt_oformat) { + if ((*func)(dtp, dt_format_agg, &pd) == -1) + return (dt_set_errno(dtp, dtp->dt_errno)); + } else { + if ((*func)(dtp, dt_print_agg, &pd) == -1) + return (dt_set_errno(dtp, dtp->dt_errno)); + } return (0); } diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c index e63771c91e08..f3fda4af834e 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c @@ -2478,10 +2478,7 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg, "not referenced)\n", yypcb->pcb_sargv[argc - 1], argc - 1); } - /* - * Perform sugar transformations (for "if" / "else") and replace the - * existing clause chain with the new one. - */ + /* Perform sugar transformations. */ if (context == DT_CTX_DPROG) { dt_node_t *dnp, *next_dnp; dt_node_t *new_list = NULL; @@ -2492,8 +2489,17 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg, next_dnp = dnp->dn_list; dnp->dn_list = NULL; - if (dnp->dn_kind == DT_NODE_CLAUSE) + if (dnp->dn_kind == DT_NODE_CLAUSE) { dnp = dt_compile_sugar(dtp, dnp); + if (cflags & DTRACE_C_SUGAR) { + dt_node_t *p; + + dt_printd(dnp, stdout, 0); + for (p = dnp->dn_list; p != NULL; + p = p->dn_list) + dt_printd(p, stdout, 0); + } + } /* append node to the new list */ new_list = dt_node_link(new_list, dnp); } diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c index 862d4b9222d7..6a32235f7e39 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c @@ -24,6 +24,7 @@ */ /* + * Copyright (c) 2023, Domagoj Stolfa. All rights reserved. * Copyright (c) 2017, Joyent, Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. */ @@ -40,12 +41,50 @@ #endif #include <dt_impl.h> #include <dt_pq.h> +#include <dt_oformat.h> #ifndef illumos #include <libproc_compat.h> #endif #define DT_MASK_LO 0x00000000FFFFFFFFULL +#define dt_format_sym(dtp, addr) dt_print_sym((dtp), NULL, NULL, addr) + +typedef struct dt_prepare_args { + int first_bin; + int last_bin; + union { + struct lquantize_args { +#define lquantize_step u.lquantize.step +#define lquantize_levels u.lquantize.levels +#define lquantize_base u.lquantize.base + int base; + uint16_t step; + uint16_t levels; + } lquantize; + struct llquantize_args { +#define llquantize_next u.llquantize.next +#define llquantize_step u.llquantize.step +#define llquantize_value u.llquantize.value +#define llquantize_levels u.llquantize.levels +#define llquantize_order u.llquantize.order +#define llquantize_factor u.llquantize.factor +#define llquantize_low u.llquantize.low +#define llquantize_high u.llquantize.high +#define llquantize_nsteps u.llquantize.nsteps + int64_t next; + int64_t step; + int64_t value; + int levels; + int order; + uint16_t factor; + uint16_t low; + uint16_t high; + uint16_t nsteps; + } llquantize; + } u; +} dt_prepare_args_t; + /* * We declare this here because (1) we need it and (2) we want to avoid a * dependency on libm in libdtrace. @@ -761,17 +800,17 @@ dt_print_packed(dtrace_hdl_t *dtp, FILE *fp, 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) +static const int64_t * +dt_format_quantize_prepare(dtrace_hdl_t *dtp, const void *addr, size_t size, + dt_prepare_args_t *args) { const int64_t *data = addr; - int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1; - long double total = 0; - char positives = 0, negatives = 0; + int first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1; - if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t)) - return (dt_set_errno(dtp, EDT_DMISMATCH)); + if (size != DTRACE_QUANTIZE_NBUCKETS * sizeof (uint64_t)) { + (void) dt_set_errno(dtp, EDT_DMISMATCH); + return (NULL); + } while (first_bin < DTRACE_QUANTIZE_NBUCKETS - 1 && data[first_bin] == 0) first_bin++; @@ -795,6 +834,58 @@ dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, last_bin++; } + args->first_bin = first_bin; + args->last_bin = last_bin; + return (data); +} + +int +dt_format_quantize(dtrace_hdl_t *dtp, const void *addr, size_t size, + uint64_t normal) +{ + const int64_t *data; + dt_prepare_args_t args = { 0 }; + int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1; + + data = dt_format_quantize_prepare(dtp, addr, size, &args); + /* dt_errno is set for us */ + if (data == NULL) + return (-1); + + first_bin = args.first_bin; + last_bin = args.last_bin; + + xo_open_list("buckets"); + for (i = first_bin; i <= last_bin; i++) { + long long value = (long long)DTRACE_QUANTIZE_BUCKETVAL(i); + xo_open_instance("buckets"); + xo_emit("{:value/%lld} {:count/%lld}", value, + (long long)data[i] / normal); + xo_close_instance("buckets"); + } + xo_close_list("buckets"); + + return (0); +} + +int +dt_print_quantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, + size_t size, uint64_t normal) +{ + const int64_t *data; + dt_prepare_args_t args = { 0 }; + int i, first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1; + long double total = 0; + char positives = 0, negatives = 0; + + data = dt_format_quantize_prepare(dtp, addr, size, &args); + /* dt_errno is set for us */ + if (data == NULL) + return (-1); + + first_bin = args.first_bin; + last_bin = args.last_bin; + for (i = first_bin; i <= last_bin; i++) { positives |= (data[i] > 0); negatives |= (data[i] < 0); @@ -859,19 +950,19 @@ dt_print_quantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr, return (0); } -int -dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, - size_t size, uint64_t normal) +static const int64_t * +dt_format_lquantize_prepare(dtrace_hdl_t *dtp, const void *addr, size_t size, + dt_prepare_args_t *args) { const int64_t *data = addr; - int i, first_bin, last_bin, base; + int first_bin = 0, last_bin = DTRACE_QUANTIZE_NBUCKETS - 1, base; uint64_t arg; - long double total = 0; uint16_t step, levels; - char positives = 0, negatives = 0; - if (size < sizeof (uint64_t)) - return (dt_set_errno(dtp, EDT_DMISMATCH)); + if (size < sizeof (uint64_t)) { + (void) dt_set_errno(dtp, EDT_DMISMATCH); + return (NULL); + } arg = *data++; size -= sizeof (uint64_t); @@ -883,8 +974,10 @@ dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, first_bin = 0; last_bin = levels + 1; - if (size != sizeof (uint64_t) * (levels + 2)) - return (dt_set_errno(dtp, EDT_DMISMATCH)); + if (size != sizeof (uint64_t) * (levels + 2)) { + (void) dt_set_errno(dtp, EDT_DMISMATCH); + return (NULL); + } while (first_bin <= levels + 1 && data[first_bin] == 0) first_bin++; @@ -903,6 +996,80 @@ dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, last_bin++; } + args->first_bin = first_bin; + args->last_bin = last_bin; + args->lquantize_base = base; + args->lquantize_step = step; + args->lquantize_levels = levels; + return (data); +} + +int +dt_format_lquantize(dtrace_hdl_t *dtp, const void *addr, size_t size, + uint64_t normal) +{ + const int64_t *data; + dt_prepare_args_t args = { 0 }; + int i, first_bin, last_bin, base; + uint16_t step, levels; + + data = dt_format_lquantize_prepare(dtp, addr, size, &args); + /* dt_errno is set for us */ + if (data == NULL) + return (-1); + + first_bin = args.first_bin; + last_bin = args.last_bin; + step = args.lquantize_step; + levels = args.lquantize_levels; + base = args.lquantize_base; + + xo_open_list("buckets"); + for (i = first_bin; i <= last_bin; i++) { + char c[32]; + int err; + + xo_open_instance("buckets"); + if (i == 0) { + xo_emit("{:value/%d} {:operator/%s}", base, "<"); + } else if (i == levels + 1) { + xo_emit("{:value/%d} {:operator/%s}", + base + (levels * step), ">="); + } else { + xo_emit("{:value/%d}", base + (i - 1) * step); + } + + xo_emit("{:count/%lld}", (long long)data[i] / normal); + xo_close_instance("buckets"); + } + xo_close_list("buckets"); + + return (0); +} + +int +dt_print_lquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, + size_t size, uint64_t normal) +{ + const int64_t *data; + dt_prepare_args_t args = { 0 }; + int i, first_bin, last_bin, base; + uint64_t arg; + long double total = 0; + uint16_t step, levels; + char positives = 0, negatives = 0; + + data = dt_format_lquantize_prepare(dtp, addr, size, &args); + /* dt_errno is set for us */ + if (data == NULL) + return (-1); + + first_bin = args.first_bin; + last_bin = args.last_bin; + step = args.lquantize_step; + levels = args.lquantize_levels; + base = args.lquantize_base; + for (i = first_bin; i <= last_bin; i++) { positives |= (data[i] > 0); negatives |= (data[i] < 0); @@ -990,21 +1157,20 @@ dt_print_lquantize_packed(dtrace_hdl_t *dtp, FILE *fp, const void *addr, 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) +static const int64_t * +dt_format_llquantize_prepare(dtrace_hdl_t *dtp, const void *addr, size_t size, + dt_prepare_args_t *args) { int i, first_bin, last_bin, bin = 1, order, levels; uint16_t factor, low, high, nsteps; const int64_t *data = addr; int64_t value = 1, next, step; - char positives = 0, negatives = 0; - long double total = 0; uint64_t arg; - char c[32]; - if (size < sizeof (uint64_t)) - return (dt_set_errno(dtp, EDT_DMISMATCH)); + if (size < sizeof(uint64_t)) { + (void) dt_set_errno(dtp, EDT_DMISMATCH); + return (NULL); + } arg = *data++; size -= sizeof (uint64_t); @@ -1019,8 +1185,10 @@ dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, * but sanity check them (to a degree) nonetheless. */ if (size > INT32_MAX || factor < 2 || low >= high || - nsteps == 0 || factor > nsteps) - return (dt_set_errno(dtp, EDT_DMISMATCH)); + nsteps == 0 || factor > nsteps) { + (void) dt_set_errno(dtp, EDT_DMISMATCH); + return (NULL); + } levels = (int)size / sizeof (uint64_t); @@ -1044,6 +1212,133 @@ dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, last_bin++; } + for (order = 0; order < low; order++) + value *= factor; + + next = value * factor; + step = next > nsteps ? next / nsteps : 1; + + args->first_bin = first_bin; + args->last_bin = last_bin; + args->llquantize_factor = factor; + args->llquantize_low = low; + args->llquantize_high = high; + args->llquantize_nsteps = nsteps; + args->llquantize_levels = levels; + args->llquantize_order = order; + args->llquantize_next = next; + args->llquantize_step = step; + args->llquantize_value = value; + + return (data); +} + +int +dt_format_llquantize(dtrace_hdl_t *dtp, const void *addr, size_t size, + uint64_t normal) +{ + int first_bin, last_bin, bin = 1, order, levels; + uint16_t factor, low, high, nsteps; + const int64_t *data; + dt_prepare_args_t args = { 0 }; + int64_t value = 1, next, step; + uint64_t arg; + char c[32]; + + data = dt_format_llquantize_prepare(dtp, addr, size, &args); + /* dt_errno is set for us */ + if (data == NULL) + return (-1); + + first_bin = args.first_bin; + last_bin = args.last_bin; + factor = args.llquantize_factor; + low = args.llquantize_low; + high = args.llquantize_high; + nsteps = args.llquantize_nsteps; + levels = args.llquantize_levels; + order = args.llquantize_order; + next = args.llquantize_next; + step = args.llquantize_step; + value = args.llquantize_value; + + xo_open_list("buckets"); + if (first_bin == 0) { + /* + * We have to represent < value somehow in JSON, so we bundle an + * optional "operator" in llquantize buckets. + */ + xo_open_instance("buckets"); + xo_emit("{:value/%lld} {:count/%lld} {:operator/%s}", + (long long)value, (long long)data[0] / normal, "<"); + xo_close_instance("buckets"); + } + + while (order <= high) { + if (bin >= first_bin && bin <= last_bin) { + xo_open_instance("buckets"); + xo_emit("{:value/%lld} {:count/%lld}", (long long)value, + (long long)data[bin] / normal); + xo_close_instance("buckets"); + } + + assert(value < next); + bin++; + + if ((value += step) != next) + continue; + + next = value * factor; + step = next > nsteps ? next / nsteps : 1; + order++; + } + + if (last_bin < bin) { + xo_close_list("buckets"); + return (0); + } + + assert(last_bin == bin); + xo_open_instance("buckets"); + xo_emit("{:value/%lld} {:count/%lld} {:operator/%s}", (long long)value, + (long long)data[bin] / normal, ">="); + xo_close_instance("buckets"); + + xo_close_list("buckets"); + return (0); +} + +int +dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, + size_t size, uint64_t normal) +{ + int i, first_bin, last_bin, bin = 1, order, levels; + uint16_t factor, low, high, nsteps; + const int64_t *data; + dt_prepare_args_t args = { 0 }; + int64_t value = 1, next, step; + char positives = 0, negatives = 0; + long double total = 0; + uint64_t arg; + char c[32]; + + data = dt_format_llquantize_prepare(dtp, addr, size, &args); + /* dt_errno is set for us */ + if (data == NULL) + return (-1); + + first_bin = args.first_bin; + last_bin = args.last_bin; + factor = args.llquantize_factor; + low = args.llquantize_low; + high = args.llquantize_high; + nsteps = args.llquantize_nsteps; + levels = args.llquantize_levels; + order = args.llquantize_order; + next = args.llquantize_next; + step = args.llquantize_step; + value = args.llquantize_value; + for (i = first_bin; i <= last_bin; i++) { positives |= (data[i] > 0); negatives |= (data[i] < 0); @@ -1054,12 +1349,6 @@ dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, "------------- Distribution -------------", "count") < 0) return (-1); - for (order = 0; order < low; order++) - value *= factor; - - next = value * factor; - step = next > nsteps ? next / nsteps : 1; - if (first_bin == 0) { (void) snprintf(c, sizeof (c), "< %lld", (long long)value); @@ -1105,6 +1394,16 @@ dt_print_llquantize(dtrace_hdl_t *dtp, FILE *fp, const void *addr, total, positives, negatives)); } +static int +dt_format_average(dtrace_hdl_t *dtp, caddr_t addr, size_t size, uint64_t normal) +{ + int64_t *data = (int64_t *)addr; + + xo_emit("{:average/%lld}", + data[0] ? (long long)(data[1] / (int64_t)normal / data[0]) : 0); + return (0); +} + /*ARGSUSED*/ static int dt_print_average(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, @@ -1117,6 +1416,16 @@ dt_print_average(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, (long long)(data[1] / (int64_t)normal / data[0]) : 0)); } +static int +dt_format_stddev(dtrace_hdl_t *dtp, caddr_t addr, size_t size, uint64_t normal) +{ + uint64_t *data = (uint64_t *)addr; + + xo_emit("{:stddev/%llu}", + data[0] ? (unsigned long long)dt_stddev(data, normal) : 0); + return (0); +} + /*ARGSUSED*/ static int dt_print_stddev(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, @@ -1249,6 +1558,185 @@ raw: } int +dt_format_stack(dtrace_hdl_t *dtp, caddr_t addr, int depth, int size) +{ + dtrace_syminfo_t dts; + GElf_Sym sym; + int i; + uint64_t pc; + + xo_open_list("stack-frames"); + for (i = 0; i < depth; i++) { + switch (size) { + case sizeof (uint32_t): + pc = *((uint32_t *)addr); + break; + + case sizeof (uint64_t): + pc = *((uint64_t *)addr); + break; + + default: + return (dt_set_errno(dtp, EDT_BADSTACKPC)); + } + + if (pc == 0) + break; + + addr += size; + + xo_open_instance("stack-frames"); + if (dtrace_lookup_by_addr(dtp, pc, &sym, &dts) == 0) { + if (pc > sym.st_value) { + xo_emit("{:symbol/%s`%s+0x%llx} {:module/%s} " + "{:name/%s} {:offset/0x%llx}", + dts.dts_object, dts.dts_name, + (u_longlong_t)(pc - sym.st_value), + dts.dts_object, dts.dts_name, + (u_longlong_t)(pc - sym.st_value)); + } else { + xo_emit("{:symbol/%s`%s} {:module/%s} " + "{:name/%s}", + dts.dts_object, dts.dts_name, + dts.dts_object, dts.dts_name); + } + } else { + /* + * We'll repeat the lookup, but this time we'll specify + * a NULL GElf_Sym -- indicating that we're only + * interested in the containing module. + */ + if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0) { + xo_emit("{:symbol/%s`0x%llx} {:module/%s} " + "{:offset/0x%llx}", + dts.dts_object, (u_longlong_t)pc, + dts.dts_object, (u_longlong_t)pc); + } else { + xo_emit("{:symbol/0x%llx} {:offset/0x%llx}", + (u_longlong_t)pc, (u_longlong_t)pc); + } + } + xo_close_instance("stack-frames"); + } + xo_close_list("stack-frames"); + + return (0); +} + +int +dt_format_ustack(dtrace_hdl_t *dtp, caddr_t addr, uint64_t arg) +{ + uint64_t *pc = (uint64_t *)addr; + uint32_t depth = DTRACE_USTACK_NFRAMES(arg); + uint32_t strsize = DTRACE_USTACK_STRSIZE(arg); + const char *strbase = addr + (depth + 1) * sizeof (uint64_t); + const char *str = strsize ? strbase : NULL; + int err = 0; + + char name[PATH_MAX], objname[PATH_MAX], c[PATH_MAX * 2]; + struct ps_prochandle *P; + GElf_Sym sym; + int i, indent; + pid_t pid; + + if (depth == 0) + return (0); + + pid = (pid_t)*pc++; + + /* + * Ultimately, we need to add an entry point in the library vector for + * determining <symbol, offset> from <pid, address>. For now, if + * this is a vector open, we just print the raw address or string. + */ + if (dtp->dt_vector == NULL) + P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0); + else + P = NULL; + + if (P != NULL) + dt_proc_lock(dtp, P); /* lock handle while we perform lookups */ + + xo_open_list("ustack-frames"); + for (i = 0; i < depth && pc[i] != 0; i++) { + const prmap_t *map; + + xo_open_instance("ustack-frames"); + if (P != NULL && Plookup_by_addr(P, pc[i], + name, sizeof (name), &sym) == 0) { + (void) Pobjname(P, pc[i], objname, sizeof (objname)); + + if (pc[i] > sym.st_value) { + xo_emit("{:symbol/%s`%s+0x%llx} {:module/%s} " + "{:name/%s} {:offset/0x%llx}", + dt_basename(objname), name, + (u_longlong_t)(pc[i] - sym.st_value), + dt_basename(objname), name, + (u_longlong_t)(pc[i] - sym.st_value)); + } else { + xo_emit("{:symbol/%s`%s} {:module/%s} " + "{:name/%s}", + dt_basename(objname), name, + dt_basename(objname), name); + } + } else if (str != NULL && str[0] != '\0' && str[0] != '@' && + (P != NULL && ((map = Paddr_to_map(P, pc[i])) == NULL || + (map->pr_mflags & MA_WRITE)))) { + /* + * If the current string pointer in the string table + * does not point to an empty string _and_ the program + * counter falls in a writable region, we'll use the + * string from the string table instead of the raw + * address. This last condition is necessary because + * some (broken) ustack helpers will return a string + * even for a program counter that they can't + * identify. If we have a string for a program + * counter that falls in a segment that isn't + * writable, we assume that we have fallen into this + * case and we refuse to use the string. + */ + xo_emit("{:symbol/%s}", str); + } else { + if (P != NULL && Pobjname(P, pc[i], objname, + sizeof (objname)) != 0) { + xo_emit("{:symbol/%s`0x%llx} {:module/%s} " + "{:offset/0x%llx}", + dt_basename(objname), (u_longlong_t)pc[i], + dt_basename(objname), (u_longlong_t)pc[i]); + } else { + xo_emit("{:symbol/0x%llx} {:offset/0x%llx}", + (u_longlong_t)pc[i], (u_longlong_t)pc[i]); + } + } + + if (str != NULL && str[0] == '@') { + /* + * If the first character of the string is an "at" sign, + * then the string is inferred to be an annotation -- + * and it is printed out beneath the frame and offset + * with brackets. + */ + xo_emit("{:annotation/%s}", &str[1]); + } + + if (str != NULL) { + str += strlen(str) + 1; + if (str - strbase >= strsize) + str = NULL; + } + xo_close_instance("ustack-frames"); + } + xo_close_list("ustack-frames"); + + if (P != NULL) { + dt_proc_unlock(dtp, P); + dt_proc_release(dtp, P); + } + + return (err); +} + +int dt_print_stack(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr, int depth, int size) { @@ -1461,6 +1949,41 @@ dt_print_ustack(dtrace_hdl_t *dtp, FILE *fp, const char *format, } static int +dt_format_usym(dtrace_hdl_t *dtp, caddr_t addr, dtrace_actkind_t act) +{ + uint64_t pid = ((uint64_t *)addr)[0]; + uint64_t pc = ((uint64_t *)addr)[1]; + char *s; + int n, len = 256; + + if (act == DTRACEACT_USYM && dtp->dt_vector == NULL) { + struct ps_prochandle *P; + + if ((P = dt_proc_grab(dtp, pid, + PGRAB_RDONLY | PGRAB_FORCE, 0)) != NULL) { + GElf_Sym sym; + + dt_proc_lock(dtp, P); + + if (Plookup_by_addr(P, pc, NULL, 0, &sym) == 0) + pc = sym.st_value; + + dt_proc_unlock(dtp, P); + dt_proc_release(dtp, P); + } + } + + do { + n = len; + s = alloca(n); + } while ((len = dtrace_uaddr2str(dtp, pid, pc, s, n)) > n); + + xo_emit("{:usym/%s}", s); + return (0); +} + + +static int dt_print_usym(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, dtrace_actkind_t act) { /* LINTED - alignment */ @@ -1497,6 +2020,42 @@ dt_print_usym(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr, dtrace_actkind_t act) } int +dt_format_umod(dtrace_hdl_t *dtp, caddr_t addr) +{ + uint64_t pid = ((uint64_t *)addr)[0]; + uint64_t pc = ((uint64_t *)addr)[1]; + int err = 0; + + char objname[PATH_MAX]; + struct ps_prochandle *P; + + /* + * See the comment in dt_print_ustack() for the rationale for + * printing raw addresses in the vectored case. + */ + if (dtp->dt_vector == NULL) + P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0); + else + P = NULL; + + if (P != NULL) + dt_proc_lock(dtp, P); /* lock handle while we perform lookups */ + + if (P != NULL && Pobjname(P, pc, objname, sizeof (objname)) != 0) { + xo_emit("{:umod/%s}", dt_basename(objname)); + } else { + xo_emit("{:umod/0x%llx}", (u_longlong_t)pc); + } + + if (P != NULL) { + dt_proc_unlock(dtp, P); + dt_proc_release(dtp, P); + } + + return (0); +} + +int dt_print_umod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr) { /* LINTED - alignment */ @@ -1552,8 +2111,13 @@ dt_print_sym(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr) format = " %-50s"; if (dtrace_lookup_by_addr(dtp, pc, &sym, &dts) == 0) { - (void) snprintf(c, sizeof (c), "%s`%s", - dts.dts_object, dts.dts_name); + if (dtp->dt_oformat) + xo_emit("{:sym/%s`%s} {:object/%s} {:name/%s}", + dts.dts_object, dts.dts_name, dts.dts_object, + dts.dts_name); + else + (void) snprintf(c, sizeof (c), "%s`%s", + dts.dts_object, dts.dts_name); } else { /* * We'll repeat the lookup, but this time we'll specify a @@ -1561,21 +2125,47 @@ dt_print_sym(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr) * the containing module. */ if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0) { - (void) snprintf(c, sizeof (c), "%s`0x%llx", - dts.dts_object, (u_longlong_t)pc); + if (dtp->dt_oformat) + xo_emit("{:sym/%s`0x%llx} {:object/%s} " + "{:offset/0x%llx}", + dts.dts_object, (u_longlong_t)pc, + dts.dts_object, (u_longlong_t)pc); + else + (void) snprintf(c, sizeof (c), "%s`0x%llx", + dts.dts_object, (u_longlong_t)pc); } else { - (void) snprintf(c, sizeof (c), "0x%llx", - (u_longlong_t)pc); + if (dtp->dt_oformat) + xo_emit("{:sym/0x%llx} {:offset/0x%llx}", + (u_longlong_t)pc, (u_longlong_t)pc); + else + (void) snprintf(c, sizeof (c), "0x%llx", + (u_longlong_t)pc); } } - if (dt_printf(dtp, fp, format, c) < 0) + if (dtp->dt_oformat != 0 && dt_printf(dtp, fp, format, c) < 0) return (-1); return (0); } int +dt_format_mod(dtrace_hdl_t *dtp, caddr_t addr) +{ + /* LINTED - alignment */ + uint64_t pc = *((uint64_t *)addr); + dtrace_syminfo_t dts; + + if (dtrace_lookup_by_addr(dtp, pc, NULL, &dts) == 0) { + xo_emit("{:mod/%s}", dts.dts_object); + } else { + xo_emit("{:mod/0x%llx}", (u_longlong_t)pc); + } + + return (0); +} + +int dt_print_mod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr) { /* LINTED - alignment */ @@ -1598,6 +2188,74 @@ dt_print_mod(dtrace_hdl_t *dtp, FILE *fp, const char *format, caddr_t addr) return (0); } +static char * +dt_format_bytes_get(dtrace_hdl_t *dtp, caddr_t addr, size_t nbytes) +{ + char *s = dt_alloc(dtp, nbytes * 2 + 2 + 1); /* 2 bytes per byte + 0x + '\0' */ + char t[6]; + char *c = (char *)addr; + size_t i, j; + + if (s == NULL) + return (NULL); + + /* + * XXX: Some duplication with dt_print_bytes(). + */ + for (i = 0; i < nbytes; i++) { + if (isprint(c[i]) || isspace(c[i]) || c[i] == '\b' || c[i] == '\a') + continue; + + if (c[i] == '\0' && i > 0) { + for (j = i + 1; j < nbytes; j++) { + if (c[j] != '\0') + break; + } + + if (j != nbytes) + break; + + memcpy(s, c, nbytes); + return (s); + } + + break; + } + + if (i == nbytes) { + memcpy(s, c, nbytes); + s[nbytes] = '\0'; + return (s); + } + + s[0] = '0'; + s[1] = 'x'; + for (i = 0; i < nbytes; i++) { + snprintf(t, sizeof(t), "%02x", (uchar_t)c[i]); + memcpy(s + (i * 2) + 2, t, 2); + } + + s[nbytes * 2 + 2] = 0; + return (s); +} + +static int +dt_format_memory(dtrace_hdl_t *dtp, caddr_t addr) +{ + + size_t nbytes = *((uintptr_t *) addr); + char *s; + + s = dt_format_bytes_get(dtp, addr + sizeof(uintptr_t), nbytes); + if (s == NULL) + return (-1); + + xo_emit("{:printm/%s}", s); + dt_free(dtp, s); + + return (0); +} + static int dt_print_memory(dtrace_hdl_t *dtp, FILE *fp, caddr_t addr) { @@ -1803,6 +2461,90 @@ dt_trunc(dtrace_hdl_t *dtp, caddr_t base, dtrace_recdesc_t *rec) } static int +dt_format_datum(dtrace_hdl_t *dtp, dtrace_recdesc_t *rec, caddr_t addr, + size_t size, const dtrace_aggdata_t *aggdata, uint64_t normal, + dt_print_aggdata_t *pd) +{ + dtrace_actkind_t act = rec->dtrd_action; + boolean_t packed = pd->dtpa_agghist || pd->dtpa_aggpack; + dtrace_aggdesc_t *agg = aggdata->dtada_desc; + char fmt[512]; + char *s; + + if (packed && pd->dtpa_agghisthdr != agg->dtagd_varid) + pd->dtpa_agghisthdr = agg->dtagd_varid; + + switch (act) { + case DTRACEACT_STACK: + return (dt_format_stack(dtp, addr, rec->dtrd_arg, + rec->dtrd_size / rec->dtrd_arg)); + + case DTRACEACT_USTACK: + case DTRACEACT_JSTACK: + return (dt_format_ustack(dtp, addr, rec->dtrd_arg)); + + case DTRACEACT_USYM: + case DTRACEACT_UADDR: + return (dt_format_usym(dtp, addr, act)); + + case DTRACEACT_UMOD: + return (dt_format_umod(dtp, addr)); + + case DTRACEACT_SYM: + return (dt_format_sym(dtp, addr)); + case DTRACEACT_MOD: + return (dt_format_mod(dtp, addr)); + + case DTRACEAGG_QUANTIZE: + return (dt_format_quantize(dtp, addr, size, normal)); + + case DTRACEAGG_LQUANTIZE: + return (dt_format_lquantize(dtp, addr, size, normal)); + + case DTRACEAGG_LLQUANTIZE: + return (dt_format_llquantize(dtp, addr, size, normal)); + + case DTRACEAGG_AVG: + return (dt_format_average(dtp, addr, size, normal)); + + case DTRACEAGG_STDDEV: + return (dt_format_stddev(dtp, addr, size, normal)); + + default: + break; + } + + switch (size) { + case sizeof (uint64_t): + snprintf(fmt, sizeof(fmt), "{:%s/%%lld}", pd->dtpa_keyname); + xo_emit(fmt, (long long)*((uint64_t *)addr) / normal); + break; + case sizeof (uint32_t): + snprintf(fmt, sizeof(fmt), "{:%s/%%d}", pd->dtpa_keyname); + xo_emit(fmt, *((uint32_t *)addr) / (uint32_t)normal); + break; + case sizeof (uint16_t): + snprintf(fmt, sizeof(fmt), "{:%s/%%d}", pd->dtpa_keyname); + xo_emit(fmt, *((uint16_t *)addr) / (uint32_t)normal); + break; + case sizeof (uint8_t): + snprintf(fmt, sizeof(fmt), "{:%s/%%d}", pd->dtpa_keyname); + xo_emit(fmt, *((uint8_t *)addr) / (uint32_t)normal); + break; + default: + s = dt_format_bytes_get(dtp, addr, size); + if (s == NULL) + return (-1); + + xo_emit("{:value/%s}", s); + dt_free(dtp, s); + break; + } + + return (0); +} + +static int dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec, caddr_t addr, size_t size, const dtrace_aggdata_t *aggdata, uint64_t normal, dt_print_aggdata_t *pd) @@ -1957,6 +2699,119 @@ dt_print_datum(dtrace_hdl_t *dtp, FILE *fp, dtrace_recdesc_t *rec, } int +dt_format_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg) +{ + int i, aggact = 0; + dt_print_aggdata_t *pd = arg; + const dtrace_aggdata_t *aggdata = aggsdata[0]; + dtrace_aggdesc_t *agg = aggdata->dtada_desc; + dtrace_hdl_t *dtp = pd->dtpa_dtp; + dtrace_recdesc_t *rec; + dtrace_actkind_t act; + caddr_t addr; + size_t size; + + if (pd->dtpa_aggname == NULL) + pd->dtpa_aggname = agg->dtagd_name; + + xo_open_instance("aggregation-data"); + strcpy(pd->dtpa_keyname, "value"); + xo_open_list("keys"); + + /* + * Iterate over each record description in the key, printing the traced + * data, skipping the first datum (the tuple member created by the + * compiler). + */ + for (i = 1; i < agg->dtagd_nrecs; i++) { + rec = &agg->dtagd_rec[i]; + act = rec->dtrd_action; + addr = aggdata->dtada_data + rec->dtrd_offset; + size = rec->dtrd_size; + + if (DTRACEACT_ISAGG(act)) { + aggact = i; + break; + } + + xo_open_instance("keys"); + if (dt_format_datum(dtp, rec, addr, + size, aggdata, 1, pd) < 0) { + xo_close_instance("keys"); + xo_close_instance("aggregation-data"); + return (-1); + } + xo_close_instance("keys"); + + if (dt_buffered_flush(dtp, NULL, rec, aggdata, + DTRACE_BUFDATA_AGGKEY) < 0) { + xo_close_instance("aggregation-data"); + return (-1); + } + } + xo_close_list("keys"); + + assert(aggact != 0); + + for (i = (naggvars == 1 ? 0 : 1); i < naggvars; i++) { + uint64_t normal; + + aggdata = aggsdata[i]; + agg = aggdata->dtada_desc; + rec = &agg->dtagd_rec[aggact]; + act = rec->dtrd_action; + addr = aggdata->dtada_data + rec->dtrd_offset; + size = rec->dtrd_size; + + assert(DTRACEACT_ISAGG(act)); + + switch (act) { + case DTRACEAGG_MIN: + strcpy(pd->dtpa_keyname, "min"); + break; + case DTRACEAGG_MAX: + strcpy(pd->dtpa_keyname, "max"); + break; + case DTRACEAGG_COUNT: + strcpy(pd->dtpa_keyname, "count"); + break; + case DTRACEAGG_SUM: + strcpy(pd->dtpa_keyname, "sum"); + break; + default: + strcpy(pd->dtpa_keyname, "UNKNOWN"); + break; + } + + normal = aggdata->dtada_normal; + + if (dt_format_datum(dtp, rec, addr, size, + aggdata, normal, pd) < 0) { + xo_close_instance("aggregation-data"); + return (-1); + } + + if (dt_buffered_flush(dtp, NULL, rec, aggdata, + DTRACE_BUFDATA_AGGVAL) < 0) { + xo_close_instance("aggregation-data"); + return (-1); + } + + if (!pd->dtpa_allunprint) + agg->dtagd_flags |= DTRACE_AGD_PRINTED; + } + + if (dt_buffered_flush(dtp, NULL, NULL, aggdata, + DTRACE_BUFDATA_AGGFORMAT | DTRACE_BUFDATA_AGGLAST) < 0) { + xo_close_instance("aggregation-data"); + return (-1); + } + + xo_close_instance("aggregation-data"); + return (0); +} + +int dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg) { int i, aggact = 0; @@ -2038,6 +2893,33 @@ dt_print_aggs(const dtrace_aggdata_t **aggsdata, int naggvars, void *arg) } int +dt_format_agg(const dtrace_aggdata_t *aggdata, void *arg) +{ + dt_print_aggdata_t *pd = arg; + dtrace_aggdesc_t *agg = aggdata->dtada_desc; + dtrace_aggvarid_t aggvarid = pd->dtpa_id; + + if (pd->dtpa_allunprint) { + if (agg->dtagd_flags & DTRACE_AGD_PRINTED) + return (0); + } else { + /* + * If we're not printing all unprinted aggregations, then the + * aggregation variable ID denotes a specific aggregation + * variable that we should print -- skip any other aggregations + * that we encounter. + */ + if (agg->dtagd_nrecs == 0) + return (0); + + if (aggvarid != agg->dtagd_varid) + return (0); + } + + return (dt_format_aggs(&aggdata, 1, arg)); +} + +int dt_print_agg(const dtrace_aggdata_t *aggdata, void *arg) { dt_print_aggdata_t *pd = arg; @@ -2101,6 +2983,33 @@ dt_setopt(dtrace_hdl_t *dtp, const dtrace_probedata_t *data, return (rval); } +/* + * Helper functions to help maintain style(9) in dt_consume_cpu(). + */ +static int +dt_oformat_agg_sorted(dtrace_hdl_t *dtp, dtrace_aggregate_f *func, + dt_print_aggdata_t *pd) +{ + int r; + + r = dtrace_aggregate_walk_sorted(dtp, dt_format_agg, pd); + if (r < 0) { + xo_close_list("aggregation-data"); + xo_emit("{:aggregation-name/%s}", pd->dtpa_aggname); + xo_close_instance("output"); + } + + return (r); +} + +static void +dt_oformat_agg_name(dt_print_aggdata_t *pd) +{ + + xo_close_list("aggregation-data"); + xo_emit("{:aggregation-name/%s}", pd->dtpa_aggname); +} + static int dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, dtrace_bufdesc_t *buf, boolean_t just_one, @@ -2114,6 +3023,7 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, uint64_t tracememsize = 0; dtrace_probedata_t data; uint64_t drops; + size_t skip_format; bzero(&data, sizeof (data)); data.dtpda_handle = dtp; @@ -2145,6 +3055,8 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, epd = data.dtpda_edesc; data.dtpda_data = buf->dtbd_data + offs; + data.dtpda_timestamp = DTRACE_RECORD_LOAD_TIMESTAMP( + (struct dtrace_rechdr *)data.dtpda_data); if (data.dtpda_edesc->dtepd_uarg != DT_ECB_DEFAULT) { rval = dt_handle(dtp, &data); @@ -2160,6 +3072,8 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, (void) dt_flowindent(dtp, &data, dtp->dt_last_epid, buf, offs); + if (dtp->dt_oformat) + xo_open_instance("probes"); rval = (*efunc)(&data, arg); if (flow) { @@ -2176,11 +3090,17 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, if (rval != DTRACE_CONSUME_THIS) return (dt_set_errno(dtp, EDT_BADRVAL)); + skip_format = 0; + if (dtp->dt_oformat) + xo_open_list("output"); for (i = 0; i < epd->dtepd_nrecs; i++) { caddr_t addr; dtrace_recdesc_t *rec = &epd->dtepd_rec[i]; dtrace_actkind_t act = rec->dtrd_action; + if (skip_format > 0) + skip_format--; + data.dtpda_data = buf->dtbd_data + offs + rec->dtrd_offset; addr = data.dtpda_data; @@ -2301,54 +3221,109 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, if (rval != DTRACE_CONSUME_THIS) return (dt_set_errno(dtp, EDT_BADRVAL)); + if (dtp->dt_oformat && rec->dtrd_size > 0) + xo_open_instance("output"); if (act == DTRACEACT_STACK) { int depth = rec->dtrd_arg; - if (dt_print_stack(dtp, fp, NULL, addr, depth, - rec->dtrd_size / depth) < 0) + if (dtp->dt_oformat) { + if (dt_format_stack(dtp, addr, depth, + rec->dtrd_size / depth) < 0) { + xo_close_instance("output"); + return (-1); + } + } else { + if (dt_print_stack(dtp, + fp, NULL, addr, depth, + rec->dtrd_size / depth) < 0) return (-1); + } goto nextrec; } if (act == DTRACEACT_USTACK || act == DTRACEACT_JSTACK) { - if (dt_print_ustack(dtp, fp, NULL, - addr, rec->dtrd_arg) < 0) - return (-1); + if (dtp->dt_oformat) { + if (dt_format_ustack(dtp, addr, + rec->dtrd_arg) < 0) { + xo_close_instance("output"); + return (-1); + } + } else { + if (dt_print_ustack(dtp, fp, NULL, + addr, rec->dtrd_arg) < 0) + return (-1); + } goto nextrec; } if (act == DTRACEACT_SYM) { - if (dt_print_sym(dtp, fp, NULL, addr) < 0) - return (-1); + if (dtp->dt_oformat) { + if (dt_format_sym(dtp, addr) < 0) { + xo_close_instance("output"); + return (-1); + } + } else { + if (dt_print_sym(dtp, fp, NULL, addr) < 0) + return (-1); + } goto nextrec; } if (act == DTRACEACT_MOD) { - if (dt_print_mod(dtp, fp, NULL, addr) < 0) - return (-1); + if (dtp->dt_oformat) { + if (dt_format_mod(dtp, addr) < 0) { + xo_close_instance("output"); + return (-1); + } + } else { + if (dt_print_mod(dtp, fp, NULL, addr) < 0) + return (-1); + } goto nextrec; } if (act == DTRACEACT_USYM || act == DTRACEACT_UADDR) { - if (dt_print_usym(dtp, fp, addr, act) < 0) - return (-1); + if (dtp->dt_oformat) { + if (dt_format_usym(dtp, addr, act) < 0) { + xo_close_instance("output"); + return (-1); + } + } else { + if (dt_print_usym(dtp, fp, addr, act) < 0) + return (-1); + } goto nextrec; } if (act == DTRACEACT_UMOD) { - if (dt_print_umod(dtp, fp, NULL, addr) < 0) - return (-1); + if (dtp->dt_oformat) { + if (dt_format_umod(dtp, addr) < 0) { + xo_close_instance("output"); + return (-1); + } + } else { + if (dt_print_umod(dtp, fp, NULL, addr) < 0) + return (-1); + } goto nextrec; } if (act == DTRACEACT_PRINTM) { - if (dt_print_memory(dtp, fp, addr) < 0) - return (-1); + if (dtp->dt_oformat) { + if (dt_format_memory(dtp, addr) < 0) { + xo_close_instance("output"); + return (-1); + } + } else { + if (dt_print_memory(dtp, fp, addr) < 0) + return (-1); + } goto nextrec; } - if (DTRACEACT_ISPRINTFLIKE(act)) { + if (dtp->dt_oformat == DTRACE_OFORMAT_TEXT && + DTRACEACT_ISPRINTFLIKE(act)) { void *fmtdata; int (*func)(dtrace_hdl_t *, FILE *, void *, const dtrace_probedata_t *, @@ -2388,6 +3363,54 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, } /* + * We don't care about a formatted printa, system or + * freopen for oformat. + */ + if (dtp->dt_oformat && act == DTRACEACT_PRINTF && + skip_format == 0) { + void *fmtdata; + if ((fmtdata = dt_format_lookup(dtp, + rec->dtrd_format)) == NULL) + goto nofmt; + + n = dtrace_sprintf(dtp, fp, fmtdata, rec, + epd->dtepd_nrecs - i, + (uchar_t *)buf->dtbd_data + offs, + buf->dtbd_size - offs); + + if (n < 0) { + xo_close_instance("output"); + return (-1); /* errno is set for us */ + } + + xo_emit("{:message/%s}", dtp->dt_sprintf_buf); + skip_format += n; + + /* + * We want the "message" object to be its own + * thing, but we still want to process the + * current DIFEXPR in case there is a value + * attached to it. If there is, we need to + * re-open a new output instance, as otherwise + * the message ends up bundled with the first + * value. + * + * XXX: There is an edge case where a + * printf("hello"); will produce a DIFO that + * returns 0 attached to it and we have no good + * way to determine if this 0 value is because + * there's no real data attached to the printf + * as an argument, or it's because the argument + * actually returns 0. + */ + if (skip_format == 0) + goto nextrec; + + xo_close_instance("output"); + xo_open_instance("output"); + } + + /* * If this is a DIF expression, and the record has a * format set, this indicates we have a CTF type name * associated with the data and we should try to print @@ -2397,8 +3420,14 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, const char *strdata = dt_strdata_lookup(dtp, rec->dtrd_format); if (strdata != NULL) { - n = dtrace_print(dtp, fp, strdata, - addr, rec->dtrd_size); + if (dtp->dt_oformat) + n = dtrace_format_print(dtp, fp, + strdata, addr, + rec->dtrd_size); + else + n = dtrace_print(dtp, fp, + strdata, addr, + rec->dtrd_size); /* * dtrace_print() will return -1 on @@ -2408,8 +3437,12 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, * should fall through to the normal * trace method. */ - if (n < 0) + if (n < 0) { + if (dtp->dt_oformat) + xo_close_instance( + "output"); return (-1); + } if (n > 0) goto nextrec; @@ -2424,8 +3457,11 @@ nofmt: size_t size = ((epd->dtepd_nrecs - i) * sizeof (dtrace_aggvarid_t)); - if ((aggvars = dt_alloc(dtp, size)) == NULL) + if ((aggvars = dt_alloc(dtp, size)) == NULL) { + if (dtp->dt_oformat) + xo_close_instance("output"); return (-1); + } /* * This might be a printa() with multiple @@ -2443,6 +3479,9 @@ nofmt: break; if (nrec->dtrd_action != act) { + if (dtp->dt_oformat) + xo_close_instance( + "output"); return (dt_set_errno(dtp, EDT_BADAGG)); } @@ -2462,24 +3501,50 @@ nofmt: assert(naggvars >= 1); + if (dtp->dt_oformat) + xo_open_list("aggregation-data"); if (naggvars == 1) { pd.dtpa_id = aggvars[0]; dt_free(dtp, aggvars); - if (dt_printf(dtp, fp, "\n") < 0 || - dtrace_aggregate_walk_sorted(dtp, - dt_print_agg, &pd) < 0) - return (-1); + if (dtp->dt_oformat) { + n = dt_oformat_agg_sorted(dtp, + dt_format_agg, &pd); + if (n < 0) + return (-1); + } else { + if (dt_printf(dtp, fp, "\n") < 0 || + dtrace_aggregate_walk_sorted(dtp, + dt_print_agg, &pd) < 0) + return (-1); + } + + if (dtp->dt_oformat) + dt_oformat_agg_name(&pd); goto nextrec; } - if (dt_printf(dtp, fp, "\n") < 0 || - dtrace_aggregate_walk_joined(dtp, aggvars, - naggvars, dt_print_aggs, &pd) < 0) { - dt_free(dtp, aggvars); - return (-1); + if (dtp->dt_oformat) { + if (dtrace_aggregate_walk_joined(dtp, + aggvars, naggvars, + dt_format_aggs, &pd) < 0) { + dt_oformat_agg_name(&pd); + xo_close_instance("output"); + dt_free(dtp, aggvars); + return (-1); + } + } else { + if (dt_printf(dtp, fp, "\n") < 0 || + dtrace_aggregate_walk_joined(dtp, + aggvars, naggvars, + dt_print_aggs, &pd) < 0) { + dt_free(dtp, aggvars); + return (-1); + } } + if (dtp->dt_oformat) + dt_oformat_agg_name(&pd); dt_free(dtp, aggvars); goto nextrec; } @@ -2490,8 +3555,17 @@ nofmt: tracememsize = rec->dtrd_size; } - n = dt_print_bytes(dtp, fp, addr, - tracememsize, -33, quiet, 1); + if (dtp->dt_oformat) { + char *s; + + s = dt_format_bytes_get(dtp, addr, + tracememsize); + n = xo_emit("{:tracemem/%s}", s); + dt_free(dtp, s); + } else { + n = dt_print_bytes(dtp, fp, addr, + tracememsize, -33, quiet, 1); + } tracememsize = 0; @@ -2503,31 +3577,67 @@ nofmt: switch (rec->dtrd_size) { case sizeof (uint64_t): - n = dt_printf(dtp, fp, - quiet ? "%lld" : " %16lld", - /* LINTED - alignment */ - *((unsigned long long *)addr)); + if (dtp->dt_oformat) { + xo_emit("{:value/%lld}", + *((unsigned long long *)addr)); + n = 0; + } else + n = dt_printf(dtp, fp, + quiet ? "%lld" : " %16lld", + /* LINTED - alignment */ + *((unsigned long long *)addr)); break; case sizeof (uint32_t): - n = dt_printf(dtp, fp, quiet ? "%d" : " %8d", - /* LINTED - alignment */ - *((uint32_t *)addr)); + if (dtp->dt_oformat) { + xo_emit("{:value/%d}", + *((uint32_t *)addr)); + n = 0; + } else + n = dt_printf(dtp, fp, + quiet ? "%d" : " %8d", + /* LINTED - alignment */ + *((uint32_t *)addr)); break; case sizeof (uint16_t): - n = dt_printf(dtp, fp, quiet ? "%d" : " %5d", - /* LINTED - alignment */ - *((uint16_t *)addr)); + if (dtp->dt_oformat) { + xo_emit("{:value/%d}", + *((uint16_t *)addr)); + n = 0; + } else + n = dt_printf(dtp, fp, + quiet ? "%d" : " %5d", + /* LINTED - alignment */ + *((uint16_t *)addr)); break; case sizeof (uint8_t): - n = dt_printf(dtp, fp, quiet ? "%d" : " %3d", - *((uint8_t *)addr)); + if (dtp->dt_oformat) { + xo_emit("{:value/%d}", + *((uint8_t *)addr)); + n = 0; + } else + n = dt_printf(dtp, fp, + quiet ? "%d" : " %3d", + *((uint8_t *)addr)); break; default: - n = dt_print_bytes(dtp, fp, addr, - rec->dtrd_size, -33, quiet, 0); + if (dtp->dt_oformat && rec->dtrd_size > 0) { + char *s; + + s = dt_format_bytes_get(dtp, addr, + rec->dtrd_size); + xo_emit("{:value/%s}", s); + dt_free(dtp, s); + n = 0; + } else { + n = dt_print_bytes(dtp, fp, addr, + rec->dtrd_size, -33, quiet, 0); + } break; } + if (dtp->dt_oformat && rec->dtrd_size > 0) + xo_close_instance("output"); + if (n < 0) return (-1); /* errno is set for us */ @@ -2544,6 +3654,12 @@ nextrec: nextepid: offs += epd->dtepd_size; dtp->dt_last_epid = id; + + if (dtp->dt_oformat) { + xo_close_list("output"); + xo_close_instance("probes"); + xo_flush(); + } if (just_one) { buf->dtbd_oldest = offs; break; @@ -2562,7 +3678,12 @@ nextepid: */ buf->dtbd_drops = 0; - return (dt_handle_cpudrop(dtp, cpu, DTRACEDROP_PRINCIPAL, drops)); + xo_open_instance("probes"); + dt_oformat_drop(dtp, cpu); + rval = dt_handle_cpudrop(dtp, cpu, DTRACEDROP_PRINCIPAL, drops); + xo_close_instance("probes"); + + return (rval); } /* @@ -3065,8 +4186,12 @@ dtrace_consume(dtrace_hdl_t *dtp, FILE *fp, /* Consume drops. */ for (i = 0; i < max_ncpus; i++) { if (drops[i] != 0) { - int error = dt_handle_cpudrop(dtp, i, + int error; + xo_open_instance("probes"); + dt_oformat_drop(dtp, i); + error = dt_handle_cpudrop(dtp, i, DTRACEDROP_PRINCIPAL, drops[i]); + xo_close_instance("probes"); if (error != 0) return (error); } @@ -3082,3 +4207,22 @@ dtrace_consume(dtrace_hdl_t *dtp, FILE *fp, return (0); } + +void +dtrace_oformat_probe(dtrace_hdl_t *dtp __unused, const dtrace_probedata_t *data, + processorid_t cpu, dtrace_probedesc_t *pd) +{ + + xo_emit("{:timestamp/%llu} {:cpu/%d} {:id/%d} {:provider/%s} " + "{:module/%s} {:function/%s} {:name/%s}", + (unsigned long long)data->dtpda_timestamp, cpu, pd->dtpd_id, + pd->dtpd_provider, pd->dtpd_mod, pd->dtpd_func, pd->dtpd_name); +} + +void +dt_oformat_drop(dtrace_hdl_t *dtp, processorid_t cpu) +{ + xo_emit("{:cpu/%d} {:id/%d} {:provider/%s} " + "{:module/%s} {:function/%s} {:name/%s}", + cpu, -1, "dtrace", "INTERNAL", "INTERNAL", "DROP"); +} diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_handle.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_handle.c index f26126bba517..91a4871f56b5 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_handle.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_handle.c @@ -36,6 +36,7 @@ #endif #include <dt_impl.h> +#include <dt_oformat.h> #include <dt_program.h> static const char _dt_errprog[] = @@ -315,6 +316,7 @@ dt_handle_cpudrop(dtrace_hdl_t *dtp, processorid_t cpu, dtrace_dropdata_t drop; char str[80], *s; int size; + struct timeval tv; assert(what == DTRACEDROP_PRINCIPAL || what == DTRACEDROP_AGGREGATION); @@ -339,6 +341,15 @@ dt_handle_cpudrop(dtrace_hdl_t *dtp, processorid_t cpu, what == DTRACEDROP_PRINCIPAL ? "" : "aggregation ", howmany > 1 ? "s" : "", cpu); + if (dtp->dt_oformat) { + (void) gettimeofday(&tv, NULL); + xo_emit("{:timestamp/%ld.%06ld} {:count/%ju} " + "{:total/%ju} {:kind/%d} {:msg/%s}", + tv.tv_sec, tv.tv_usec, (uintmax_t)drop.dtdda_drops, + (uintmax_t)drop.dtdda_total, drop.dtdda_kind, + drop.dtdda_msg); + } + if (dtp->dt_drophdlr == NULL) return (dt_set_errno(dtp, EDT_DROPABORT)); @@ -396,6 +407,7 @@ dt_handle_status(dtrace_hdl_t *dtp, dtrace_status_t *old, dtrace_status_t *new) char str[80], *s; uintptr_t base = (uintptr_t)new, obase = (uintptr_t)old; int i, size; + struct timeval tv; bzero(&drop, sizeof (drop)); drop.dtdda_handle = dtp; @@ -408,6 +420,8 @@ dt_handle_status(dtrace_hdl_t *dtp, dtrace_status_t *old, dtrace_status_t *new) if (new->dtst_killed && !old->dtst_killed) return (dt_set_errno(dtp, EDT_BRICKED)); + (void) gettimeofday(&tv, NULL); + for (i = 0; _dt_droptab[i].dtdrt_str != NULL; i++) { uintptr_t naddr = base + _dt_droptab[i].dtdrt_offset; uintptr_t oaddr = obase + _dt_droptab[i].dtdrt_offset; @@ -438,12 +452,31 @@ dt_handle_status(dtrace_hdl_t *dtp, dtrace_status_t *old, dtrace_status_t *new) drop.dtdda_total = nval; drop.dtdda_drops = nval - oval; - if (dtp->dt_drophdlr == NULL) + if (dtp->dt_oformat) { + xo_open_instance("probes"); + dt_oformat_drop(dtp, DTRACE_CPUALL); + xo_emit("{:timestamp/%ld.%06ld} {:count/%ju} " + "{:total/%ju} {:kind/%d} {:msg/%s}", + tv.tv_sec, tv.tv_usec, (uintmax_t)drop.dtdda_drops, + (uintmax_t)drop.dtdda_total, drop.dtdda_kind, + drop.dtdda_msg); + } + + if (dtp->dt_drophdlr == NULL) { + if (dtp->dt_oformat) + xo_close_instance("probes"); return (dt_set_errno(dtp, EDT_DROPABORT)); + } if ((*dtp->dt_drophdlr)(&drop, - dtp->dt_droparg) == DTRACE_HANDLE_ABORT) + dtp->dt_droparg) == DTRACE_HANDLE_ABORT) { + if (dtp->dt_oformat) + xo_close_instance("probes"); return (dt_set_errno(dtp, EDT_DROPABORT)); + } + + if (dtp->dt_oformat) + xo_close_instance("probes"); } return (0); diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h index b3f69bb6329d..1be984f28001 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h @@ -211,6 +211,8 @@ typedef struct dt_print_aggdata { int dtpa_agghist; /* print aggregation as histogram */ int dtpa_agghisthdr; /* aggregation histogram hdr printed */ int dtpa_aggpack; /* pack quantized aggregations */ + char dtpa_keyname[256]; /* key name for oformat */ + char *dtpa_aggname; /* aggregate name for oformat */ } dt_print_aggdata_t; typedef struct dt_dirpath { @@ -323,6 +325,7 @@ struct dtrace_hdl { #endif int dt_fd; /* file descriptor for dtrace pseudo-device */ int dt_ftfd; /* file descriptor for fasttrap pseudo-device */ + int dt_kinstfd; /* file descriptor for kinst pseudo-device */ int dt_fterr; /* saved errno from failed open of dt_ftfd */ int dt_cdefs_fd; /* file descriptor for C CTF debugging cache */ int dt_ddefs_fd; /* file descriptor for D CTF debugging cache */ @@ -363,6 +366,7 @@ struct dtrace_hdl { dtrace_epid_t dt_last_epid; /* most recently consumed EPID */ uint64_t dt_last_timestamp; /* most recently consumed timestamp */ boolean_t dt_has_sugar; /* syntactic sugar used? */ + int dt_oformat; /* output format (none, json, xml, html) */ }; /* @@ -701,6 +705,8 @@ extern int dt_print_llquantize(dtrace_hdl_t *, FILE *, const void *, size_t, uint64_t); extern int dt_print_agg(const dtrace_aggdata_t *, void *); +extern int dt_format_agg(const dtrace_aggdata_t *, void *); + extern int dt_handle(dtrace_hdl_t *, dtrace_probedata_t *); extern int dt_handle_liberr(dtrace_hdl_t *, const dtrace_probedata_t *, const char *); @@ -710,6 +716,8 @@ extern int dt_handle_status(dtrace_hdl_t *, dtrace_status_t *, dtrace_status_t *); extern int dt_handle_setopt(dtrace_hdl_t *, dtrace_setoptdata_t *); +extern void dt_oformat_drop(dtrace_hdl_t *, processorid_t); + extern int dt_lib_depend_add(dtrace_hdl_t *, dt_list_t *, const char *); extern dt_lib_depend_t *dt_lib_depend_lookup(dt_list_t *, const char *); diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l index 7dcf21652586..d50369bb57c9 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l @@ -97,6 +97,8 @@ static void unput(int); */ %} +%option yylineno + %e 1500 /* maximum nodes */ %p 4900 /* maximum positions */ %n 600 /* maximum states */ diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c index 0b3dac0224f9..442c6f940733 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c @@ -215,10 +215,6 @@ prepare_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf32_t *dep) dofr[j].dofr_offset; rel->r_info = ELF32_R_INFO(count + dep->de_global, R_386_PC32); -#elif defined(__mips__) -/* XXX */ - printf("%s:%s(%d): MIPS not implemented\n", - __FUNCTION__, __FILE__, __LINE__); #elif defined(__powerpc__) /* * Add 4 bytes to hit the low half of this 64-bit @@ -229,9 +225,9 @@ prepare_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf32_t *dep) rel->r_info = ELF32_R_INFO(count + dep->de_global, R_PPC_REL32); #elif defined(__riscv) -/* XXX */ - printf("%s:%s(%d): RISC-V not implemented\n", - __FUNCTION__, __FILE__, __LINE__); + rel->r_offset = s->dofs_offset + dofr[j].dofr_offset; + rel->r_info = ELF32_R_INFO(count + dep->de_global, + R_RISCV_32_PCREL); #else #error unknown ISA #endif @@ -401,15 +397,15 @@ prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep) R_AARCH64_PREL64); #elif defined(__arm__) /* XXX */ -#elif defined(__mips__) -/* XXX */ #elif defined(__powerpc__) rel->r_offset = s->dofs_offset + dofr[j].dofr_offset; rel->r_info = ELF64_R_INFO(count + dep->de_global, R_PPC64_REL64); #elif defined(__riscv) -/* XXX */ + rel->r_offset = s->dofs_offset + dofr[j].dofr_offset; + rel->r_info = ELF64_R_INFO(count + dep->de_global, + R_RISCV_32_PCREL); #elif defined(__i386) || defined(__amd64) rel->r_offset = s->dofs_offset + dofr[j].dofr_offset; @@ -504,14 +500,28 @@ dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd) elf_file.ehdr.e_type = ET_REL; #if defined(__arm__) elf_file.ehdr.e_machine = EM_ARM; -#elif defined(__mips__) - elf_file.ehdr.e_machine = EM_MIPS; #elif defined(__powerpc__) elf_file.ehdr.e_machine = EM_PPC; #elif defined(__i386) || defined(__amd64) elf_file.ehdr.e_machine = EM_386; #elif defined(__aarch64__) elf_file.ehdr.e_machine = EM_AARCH64; +#elif defined(__riscv) + elf_file.ehdr.e_machine = EM_RISCV; + + /* Set the ELF flags according to our current ABI */ +#if defined(__riscv_compressed) + elf_file.ehdr.e_flags |= EF_RISCV_RVC; +#endif +#if defined(__riscv_float_abi_soft) + elf_file.ehdr.e_flags |= EF_RISCV_FLOAT_ABI_SOFT; +#endif +#if defined(__riscv_float_abi_single) + elf_file.ehdr.e_flags |= EF_RISCV_FLOAT_ABI_SINGLE; +#endif +#if defined(__riscv_float_abi_double) + elf_file.ehdr.e_flags |= EF_RISCV_FLOAT_ABI_DOUBLE; +#endif #endif elf_file.ehdr.e_version = EV_CURRENT; elf_file.ehdr.e_shoff = sizeof (Elf32_Ehdr); @@ -572,7 +582,7 @@ dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd) } else { shp = &elf_file.shdr[ESHDR_REL]; shp->sh_name = 37; /* DTRACE_SHSTRTAB32[37] = ".rel.SUNW_dof" */ - shp->sh_flags = SHF_ALLOC; + shp->sh_flags = 0; shp->sh_type = SHT_REL; shp->sh_entsize = sizeof (de.de_rel[0]); shp->sh_link = ESHDR_SYMTAB; @@ -644,8 +654,6 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd) elf_file.ehdr.e_type = ET_REL; #if defined(__arm__) elf_file.ehdr.e_machine = EM_ARM; -#elif defined(__mips__) - elf_file.ehdr.e_machine = EM_MIPS; #elif defined(__powerpc64__) #if defined(_CALL_ELF) && _CALL_ELF == 2 elf_file.ehdr.e_flags = 2; @@ -655,6 +663,22 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd) elf_file.ehdr.e_machine = EM_AMD64; #elif defined(__aarch64__) elf_file.ehdr.e_machine = EM_AARCH64; +#elif defined(__riscv) + elf_file.ehdr.e_machine = EM_RISCV; + + /* Set the ELF flags according to our current ABI */ +#if defined(__riscv_compressed) + elf_file.ehdr.e_flags |= EF_RISCV_RVC; +#endif +#if defined(__riscv_float_abi_soft) + elf_file.ehdr.e_flags |= EF_RISCV_FLOAT_ABI_SOFT; +#endif +#if defined(__riscv_float_abi_single) + elf_file.ehdr.e_flags |= EF_RISCV_FLOAT_ABI_SINGLE; +#endif +#if defined(__riscv_float_abi_double) + elf_file.ehdr.e_flags |= EF_RISCV_FLOAT_ABI_DOUBLE; +#endif #endif elf_file.ehdr.e_version = EV_CURRENT; elf_file.ehdr.e_shoff = sizeof (Elf64_Ehdr); @@ -715,7 +739,7 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, int fd) } else { shp = &elf_file.shdr[ESHDR_REL]; shp->sh_name = 37; /* DTRACE_SHSTRTAB64[37] = ".rel.SUNW_dof" */ - shp->sh_flags = SHF_ALLOC; + shp->sh_flags = 0; shp->sh_type = SHT_RELA; shp->sh_entsize = sizeof (de.de_rel[0]); shp->sh_link = ESHDR_SYMTAB; @@ -843,17 +867,6 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, __LINE__); return (-1); } -#elif defined(__mips__) -#define DT_REL_NONE R_MIPS_NONE - -static int -dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, - uint32_t *off) -{ - printf("%s:%s(%d): MIPS not implemented\n", __FUNCTION__, __FILE__, - __LINE__); - return (-1); -} #elif defined(__powerpc__) /* The sentinel is 'xor r3,r3,r3'. */ #define DT_OP_XOR_R3 0x7c631a78 @@ -938,14 +951,74 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, return (0); } #elif defined(__riscv) +#define DT_OP_NOP 0x00000013 /* addi x0, x0, 0 */ +#define DT_OP_RET 0x00008067 /* jalr x0, x1, 0 */ +#define DT_OP_IS_AUIPC(op) (((op) & 0x7f) == 0x17) +#define DT_OP_IS_JALR(op) (((op) & 0x707f) == 0x67) +#define DT_OP_JALR_CALL 0x000080e7 /* jalr x1, x1, 0 */ +#define DT_OP_JALR_TAIL 0x00030067 /* jalr x0, x6, 0 */ #define DT_REL_NONE R_RISCV_NONE + static int dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, uint32_t *off) { - printf("%s:%s(%d): RISC-V implementation required\n", __FUNCTION__, - __FILE__, __LINE__); - return (-1); + uint32_t *ip; + + /* + * XXX: this implementation is untested, but should serve as a decent + * starting point. + */ + + /* + * Ensure that the offset is aligned on a compressed-instruction + * boundary. + */ + if ((rela->r_offset & (sizeof (uint16_t) - 1)) != 0) + return (-1); + + /* + * We only know about some specific relocation types. + * We also recognize relocation type NONE, since that gets used for + * relocations of USDT probes, and we might be re-processing a file. + */ + if (GELF_R_TYPE(rela->r_info) != R_RISCV_CALL && + GELF_R_TYPE(rela->r_info) != R_RISCV_CALL_PLT && + GELF_R_TYPE(rela->r_info) != R_RISCV_NONE) + return (-1); + + ip = (uint32_t *)(p + rela->r_offset); + + /* + * We may have already processed this object file in an earlier linker + * invocation. Check to see if the present instruction sequence matches + * the one we would install below. + */ + if (ip[0] == DT_OP_NOP && (ip[1] == DT_OP_NOP || ip[1] == DT_OP_RET)) + return (0); + + /* + * We expect a auipc+jalr pair, either from a call or a tail. + * - call: auipc x1 0; jalr x1, x1, 0 + * - tail: auipc x6 0; jalr x0, x6, 0 + */ + if (!DT_OP_IS_AUIPC(ip[0]) || !DT_OP_IS_JALR(ip[1])) + return (-1); + + /* + * On riscv, we do not have to differentiate between regular probes and + * is-enabled probes. Calls are to be converted into a no-op whereas + * tail calls should become a return. + */ + if (ip[1] == DT_OP_JALR_CALL) { + ip[0] = DT_OP_NOP; + ip[1] = DT_OP_NOP; + } else { + ip[0] = DT_OP_NOP; + ip[1] = DT_OP_RET; + } + + return (0); } #elif defined(__i386) || defined(__amd64) @@ -1167,9 +1240,7 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) if (dtp->dt_oflags & DTRACE_O_LP64) { eclass = ELFCLASS64; -#if defined(__mips__) - emachine1 = emachine2 = EM_MIPS; -#elif defined(__powerpc__) +#if defined(__powerpc__) emachine1 = emachine2 = EM_PPC64; #if !defined(_CALL_ELF) || _CALL_ELF == 1 uses_funcdesc = 1; @@ -1178,14 +1249,14 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) emachine1 = emachine2 = EM_AMD64; #elif defined(__aarch64__) emachine1 = emachine2 = EM_AARCH64; +#elif defined(__riscv) + emachine1 = emachine2 = EM_RISCV; #endif symsize = sizeof (Elf64_Sym); } else { eclass = ELFCLASS32; #if defined(__arm__) emachine1 = emachine2 = EM_ARM; -#elif defined(__mips__) - emachine1 = emachine2 = EM_MIPS; #elif defined(__powerpc__) emachine1 = emachine2 = EM_PPC; #elif defined(__i386) || defined(__amd64) @@ -1612,6 +1683,7 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) * invocation. */ if (rsym.st_shndx != SHN_ABS) { + rsym.st_info = GELF_ST_INFO(STB_WEAK, STT_FUNC); rsym.st_shndx = SHN_ABS; (void) gelf_update_sym(data_sym, ndx, &rsym); } diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c index b9408944f8c5..281c787de533 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c @@ -1129,33 +1129,21 @@ dt_module_getctflib(dtrace_hdl_t *dtp, dt_module_t *dmp, const char *name) * including the path. */ static void -#ifdef illumos -dt_module_update(dtrace_hdl_t *dtp, const char *name) -#else dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat) -#endif { char fname[MAXPATHLEN]; struct stat64 st; int fd, err, bits; -#ifdef __FreeBSD__ struct module_stat ms; dt_kmodule_t *dkmp; uint_t h; int modid; -#endif - dt_module_t *dmp; const char *s; size_t shstrs; GElf_Shdr sh; Elf_Data *dp; Elf_Scn *sp; - -#ifdef illumos - (void) snprintf(fname, sizeof (fname), - "%s/%s/object", OBJFS_ROOT, name); -#else GElf_Ehdr ehdr; GElf_Phdr ph; char name[MAXPATHLEN]; @@ -1165,7 +1153,6 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat) (void) strlcpy(name, k_stat->name, sizeof(name)); (void) strlcpy(fname, k_stat->pathname, sizeof(fname)); -#endif if ((fd = open(fname, O_RDONLY)) == -1 || fstat64(fd, &st) == -1 || (dmp = dt_module_create(dtp, name)) == NULL) { @@ -1174,6 +1161,9 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat) return; } + (void) strlcpy(dmp->dm_file, fname, sizeof(dmp->dm_file)); + dmp->dm_modid = k_stat->id; + /* * Since the module can unload out from under us (and /system/object * will return ENOENT), tell libelf to cook the entire file now and @@ -1206,7 +1196,6 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat) dt_module_destroy(dtp, dmp); return; } -#if defined(__FreeBSD__) mapbase = (uintptr_t)k_stat->address; gelf_getehdr(dmp->dm_elf, &ehdr); is_elf_obj = (ehdr.e_type == ET_REL); @@ -1219,7 +1208,6 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat) return; } } -#endif /* * Iterate over the section headers locating various sections of * interest and use their attributes to flesh out the dt_module_t. @@ -1228,7 +1216,6 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat) if (gelf_getshdr(sp, &sh) == NULL || sh.sh_type == SHT_NULL || (s = elf_strptr(dmp->dm_elf, shstrs, sh.sh_name)) == NULL) continue; /* skip any malformed sections */ -#if defined(__FreeBSD__) if (sh.sh_size == 0) continue; if (sh.sh_type == SHT_PROGBITS || sh.sh_type == SHT_NOBITS) { @@ -1240,7 +1227,6 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat) dmp->dm_sec_offsets[elf_ndxscn(sp)] = sh.sh_addr; mapbase += sh.sh_size; } -#endif if (strcmp(s, ".text") == 0) { dmp->dm_text_size = sh.sh_size; dmp->dm_text_va = sh.sh_addr; @@ -1254,17 +1240,10 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat) (dp = elf_getdata(sp, NULL)) != NULL) { bcopy(dp->d_buf, &dmp->dm_info, MIN(sh.sh_size, sizeof (dmp->dm_info))); - } else if (strcmp(s, ".filename") == 0 && - (dp = elf_getdata(sp, NULL)) != NULL) { - (void) strlcpy(dmp->dm_file, - dp->d_buf, sizeof (dmp->dm_file)); } } dmp->dm_flags |= DT_DM_KERNEL; -#ifdef illumos - dmp->dm_modid = (int)OBJFS_MODID(st.st_ino); -#else /* * Include .rodata and special sections into .text. * This depends on default section layout produced by GNU ld @@ -1285,12 +1264,10 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat) } } #endif -#endif /* illumos */ if (dmp->dm_info.objfs_info_primary) dmp->dm_flags |= DT_DM_PRIMARY; -#ifdef __FreeBSD__ ms.version = sizeof(ms); for (modid = kldfirstmod(k_stat->id); modid > 0; modid = modnext(modid)) { @@ -1315,7 +1292,6 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat) dkmp->dkm_module = dmp; dtp->dt_kmods[h] = dkmp; } -#endif dt_dprintf("opened %d-bit module %s (%s) [%d]\n", bits, dmp->dm_name, dmp->dm_file, dmp->dm_modid); diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_oformat.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_oformat.h new file mode 100644 index 000000000000..bea7dbd19b4d --- /dev/null +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_oformat.h @@ -0,0 +1,34 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Domagoj Stolfa + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _DT_OFORMAT_H_ +#define _DT_OFORMAT_H_ + +#undef NORETURN /* needed because libxo redefines it */ +#include <libxo/xo.h> + +#endif /* _DT_OFORMAT_H_ */ diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c index f55d488f4d91..8f8d20298e4c 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c @@ -59,6 +59,7 @@ #include <dt_printf.h> #include <dt_string.h> #include <dt_provider.h> +#include <dt_oformat.h> #ifndef illumos #include <sys/sysctl.h> #include <string.h> @@ -416,6 +417,8 @@ static const dt_ident_t _dtrace_globals[] = { &dt_idops_func, "void(int)" }, { "rand", DT_IDENT_FUNC, 0, DIF_SUBR_RAND, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_func, "int()" }, +{ "regs", DT_IDENT_ARRAY, 0, DIF_VAR_REGS, DT_ATTR_STABCMN, DT_VERS_1_13, + &dt_idops_regs, NULL }, { "rindex", DT_IDENT_FUNC, 0, DIF_SUBR_RINDEX, DT_ATTR_STABCMN, DT_VERS_1_1, &dt_idops_func, "int(const char *, const char *, [int])" }, #ifdef illumos @@ -1113,6 +1116,15 @@ dt_vopen(int version, int flags, int *errp, */ if (err == ENOENT && modfind("dtraceall") < 0) { kldload("dtraceall"); /* ignore the error */ +#if __SIZEOF_LONG__ == 8 + if (modfind("linux64elf") >= 0) + kldload("systrace_linux"); + if (modfind("linuxelf") >= 0) + kldload("systrace_linux32"); +#else + if (modfind("linuxelf") >= 0) + kldload("systrace_linux"); +#endif dtfd = open("/dev/dtrace/dtrace", O_RDWR | O_CLOEXEC); err = errno; } @@ -1171,6 +1183,7 @@ alloc: dtp->dt_version = version; dtp->dt_fd = dtfd; dtp->dt_ftfd = ftfd; + dtp->dt_kinstfd = -1; dtp->dt_fterr = fterr; dtp->dt_cdefs_fd = -1; dtp->dt_ddefs_fd = -1; @@ -1679,6 +1692,8 @@ dtrace_close(dtrace_hdl_t *dtp) (void) close(dtp->dt_fd); if (dtp->dt_ftfd != -1) (void) close(dtp->dt_ftfd); + if (dtp->dt_kinstfd != -1) + (void) close(dtp->dt_kinstfd); if (dtp->dt_cdefs_fd != -1) (void) close(dtp->dt_cdefs_fd); if (dtp->dt_ddefs_fd != -1) @@ -1722,6 +1737,8 @@ dtrace_close(dtrace_hdl_t *dtp) free(dtp->dt_kmods); #endif free(dtp->dt_provs); + + xo_finish(); free(dtp); } diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c index ce13659f1685..1e7a8115c960 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c @@ -43,6 +43,7 @@ #include <dt_impl.h> #include <dt_string.h> +#include <dt_oformat.h> static int dt_opt_agg(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) @@ -724,6 +725,18 @@ dt_opt_size(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) } static int +dt_opt_oformat(dtrace_hdl_t *dtp, const char *arg, uintptr_t option __unused) +{ + if (arg == NULL) + return (dt_set_errno(dtp, EDT_BADOPTVAL)); + + if (xo_set_options(NULL, arg) < 0) + return (dt_set_errno(dtp, EDT_BADOPTVAL)); + + return (dtrace_oformat_configure(dtp)); +} + +static int dt_opt_rate(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) { char *end; @@ -1046,6 +1059,7 @@ static const dt_option_t _dtrace_rtoptions[] = { { "jstackframes", dt_opt_runtime, DTRACEOPT_JSTACKFRAMES }, { "jstackstrsize", dt_opt_size, DTRACEOPT_JSTACKSTRSIZE }, { "nspec", dt_opt_runtime, DTRACEOPT_NSPEC }, + { "oformat", dt_opt_oformat, 0 }, { "specsize", dt_opt_size, DTRACEOPT_SPECSIZE }, { "stackframes", dt_opt_runtime, DTRACEOPT_STACKFRAMES }, { "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE }, diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c index f028f99ccf64..2b85dd2b26b6 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c @@ -4767,8 +4767,8 @@ dt_printd(dt_node_t *dnp, FILE *fp, int depth) dt_printd(dnp->dn_pred, fp, 0); (void) fprintf(fp, "/\n"); } - (void) fprintf(fp, "{\n"); + (void) fprintf(fp, "{\n"); for (arg = dnp->dn_acts; arg != NULL; arg = arg->dn_list) dt_printd(arg, fp, depth + 1); (void) fprintf(fp, "}\n"); diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c index 97da0c3a5ac2..9bbd12e5544f 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c @@ -27,6 +27,7 @@ */ /* * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright (c) 2023, Domagoj Stolfa. All rights reserved. */ /* @@ -82,6 +83,7 @@ #include <dt_printf.h> #include <dt_string.h> #include <dt_impl.h> +#include <dt_oformat.h> /* determines whether the given integer CTF encoding is a character */ #define CTF_IS_CHAR(e) \ @@ -101,8 +103,10 @@ typedef struct dt_printarg { int pa_depth; /* member depth */ int pa_nest; /* nested array depth */ FILE *pa_file; /* output file */ + const char *pa_object; /* object name */ } dt_printarg_t; +static int dt_format_member(const char *, ctf_id_t, ulong_t, int, void *); static int dt_print_member(const char *, ctf_id_t, ulong_t, int, void *); /* @@ -189,7 +193,10 @@ print_bitfield(dt_printarg_t *pap, ulong_t off, ctf_encoding_t *ep) value >>= shift; value &= mask; - (void) fprintf(fp, "%#llx", (u_longlong_t)value); + xo_emit("{:value/%#llx}", (u_longlong_t)value); + + /* Flush in order to ensure output is aligned properly */ + xo_flush(); } /* @@ -200,24 +207,25 @@ dt_print_hex(FILE *fp, caddr_t addr, size_t size) { switch (size) { case sizeof (uint8_t): - (void) fprintf(fp, "%#x", *(uint8_t *)addr); + xo_emit("{:value/%#x}", *(uint8_t *)addr); break; case sizeof (uint16_t): - /* LINTED - alignment */ - (void) fprintf(fp, "%#x", *(uint16_t *)addr); + xo_emit("{:value/%#x}", *(uint16_t *)addr); break; case sizeof (uint32_t): - /* LINTED - alignment */ - (void) fprintf(fp, "%#x", *(uint32_t *)addr); + xo_emit("{:value/%#x}", *(uint32_t *)addr); break; case sizeof (uint64_t): - (void) fprintf(fp, "%#llx", - /* LINTED - alignment */ + xo_emit("{:value/%#llx}", (unsigned long long)*(uint64_t *)addr); break; default: - (void) fprintf(fp, "<invalid size %u>", (uint_t)size); + xo_emit("<{:warning} {:size/%u}>", "invalid size", + (uint_t)size); } + + /* Flush in order to ensure output is aligned properly */ + xo_flush(); } /* @@ -229,12 +237,16 @@ dt_print_int(ctf_id_t base, ulong_t off, dt_printarg_t *pap) { FILE *fp = pap->pa_file; ctf_file_t *ctfp = pap->pa_ctfp; + dtrace_hdl_t *dtp = pap->pa_dtp; ctf_encoding_t e; size_t size; caddr_t addr = pap->pa_addr + off / NBBY; if (ctf_type_encoding(ctfp, base, &e) == CTF_ERR) { - (void) fprintf(fp, "<unknown encoding>"); + xo_emit("<{:warning}>", "unknown encoding"); + + /* Flush in order to ensure output is aligned properly */ + xo_flush(); return; } @@ -243,7 +255,8 @@ dt_print_int(ctf_id_t base, ulong_t off, dt_printarg_t *pap) * would be found. */ if (e.cte_format & CTF_INT_VARARGS) { - (void) fprintf(fp, "..."); + if (!dtp->dt_oformat) + (void)fprintf(fp, "..."); return; } @@ -263,11 +276,14 @@ dt_print_int(ctf_id_t base, ulong_t off, dt_printarg_t *pap) if (CTF_IS_CHAR(e)) { char c = *(char *)addr; if (isprint(c)) - (void) fprintf(fp, "'%c'", c); + xo_emit("'{:value/%c}'", c); else if (c == 0) - (void) fprintf(fp, "'\\0'"); + xo_emit("'\\{:value/0}'"); else - (void) fprintf(fp, "'\\%03o'", c); + xo_emit("'\\{:value/%03o}'", c); + + /* Flush in order to ensure output is aligned properly */ + xo_flush(); return; } @@ -285,22 +301,20 @@ dt_print_float(ctf_id_t base, ulong_t off, dt_printarg_t *pap) ctf_file_t *ctfp = pap->pa_ctfp; ctf_encoding_t e; caddr_t addr = pap->pa_addr + off / NBBY; + dtrace_hdl_t *dtp = pap->pa_dtp; if (ctf_type_encoding(ctfp, base, &e) == 0) { if (e.cte_format == CTF_FP_SINGLE && e.cte_bits == sizeof (float) * NBBY) { - /* LINTED - alignment */ - (void) fprintf(fp, "%+.7e", *((float *)addr)); + xo_emit("{:value/%+.7e}", *((float *)addr)); } else if (e.cte_format == CTF_FP_DOUBLE && e.cte_bits == sizeof (double) * NBBY) { - /* LINTED - alignment */ - (void) fprintf(fp, "%+.7e", *((double *)addr)); + xo_emit("{:value/%+.7e}", *((double *)addr)); } else if (e.cte_format == CTF_FP_LDOUBLE && e.cte_bits == sizeof (long double) * NBBY) { - /* LINTED - alignment */ - (void) fprintf(fp, "%+.16LE", *((long double *)addr)); + xo_emit("{:value/%+.16LE}", *((long double *)addr)); } else { - (void) fprintf(fp, "<unknown encoding>"); + xo_emit("<{:warning}>", "unknown encoding"); } } } @@ -329,8 +343,7 @@ dt_print_ptr(ctf_id_t base, ulong_t off, dt_printarg_t *pap) if (dtrace_lookup_by_addr(pap->pa_dtp, pc, &sym, &dts) != 0) { dt_print_hex(fp, addr, size); } else { - (void) fprintf(fp, "%s`%s", dts.dts_object, - dts.dts_name); + xo_emit("{:value/%s`%s}", dts.dts_object, dts.dts_name); } } } @@ -367,6 +380,7 @@ dt_print_array(ctf_id_t base, ulong_t off, dt_printarg_t *pap) FILE *fp = pap->pa_file; ctf_file_t *ctfp = pap->pa_ctfp; caddr_t addr = pap->pa_addr + off / NBBY; + char *str; ctf_arinfo_t car; ssize_t eltsize; ctf_encoding_t e; @@ -374,16 +388,18 @@ dt_print_array(ctf_id_t base, ulong_t off, dt_printarg_t *pap) boolean_t isstring; int kind; ctf_id_t rtype; + dtrace_hdl_t *dtp = pap->pa_dtp; if (ctf_array_info(ctfp, base, &car) == CTF_ERR) { - (void) fprintf(fp, "%p", (void *)addr); + xo_emit("{:value/%p}", (void *)addr); return; } if ((eltsize = ctf_type_size(ctfp, car.ctr_contents)) < 0 || (rtype = ctf_type_resolve(ctfp, car.ctr_contents)) == CTF_ERR || (kind = ctf_type_kind(ctfp, rtype)) == CTF_ERR) { - (void) fprintf(fp, "<invalid type %lu>", car.ctr_contents); + xo_emit("<{:warning} {:type-identifier/%lu}>", "invalid type", + car.ctr_contents); return; } @@ -411,18 +427,44 @@ dt_print_array(ctf_id_t base, ulong_t off, dt_printarg_t *pap) * * As D will internally represent this as a char[256] array. */ - if (!isstring || pap->pa_depth != 0) - (void) fprintf(fp, "[ "); + if (dtp->dt_oformat) { + if (!isstring) + xo_open_list("value"); + else { + str = malloc(car.ctr_nelems); + if (str == NULL) + return; + *str = 0; + } + } else { + if (!isstring || pap->pa_depth != 0) + (void)fprintf(fp, "[ "); - if (isstring) - (void) fprintf(fp, "\""); + if (isstring) + (void)fprintf(fp, "\""); + } for (i = 0; i < car.ctr_nelems; i++) { if (isstring) { char c = *((char *)addr + eltsize * i); - if (c == '\0') + if (c == '\0') { + if (dtp->dt_oformat) + str[i] = 0; break; - (void) fprintf(fp, "%c", c); + } + + if (dtp->dt_oformat) + str[i] = c; + else + (void)fprintf(fp, "%c", c); + } else if (dtp->dt_oformat) { + dt_printarg_t pa = *pap; + pa.pa_nest += pap->pa_depth + 1; + pa.pa_depth = 0; + pa.pa_addr = addr + eltsize * i; + + (void) ctf_type_visit(ctfp, car.ctr_contents, + dt_format_member, &pa); } else { /* * Recursively invoke ctf_type_visit() on each member. @@ -444,15 +486,24 @@ dt_print_array(ctf_id_t base, ulong_t off, dt_printarg_t *pap) } } - if (isstring) - (void) fprintf(fp, "\""); - - if (!isstring || pap->pa_depth != 0) { - if (CTF_IS_STRUCTLIKE(kind)) - dt_print_indent(pap); - else - (void) fprintf(fp, " "); - (void) fprintf(fp, "]"); + if (dtp->dt_oformat) { + if (!isstring) + xo_close_list("value"); + else { + xo_emit("{:value/%s}", str); + free(str); + } + } else { + if (isstring) + (void)fprintf(fp, "\""); + + if (!isstring || pap->pa_depth != 0) { + if (CTF_IS_STRUCTLIKE(kind)) + dt_print_indent(pap); + else + (void)fprintf(fp, " "); + (void)fprintf(fp, "]"); + } } } @@ -463,7 +514,8 @@ dt_print_array(ctf_id_t base, ulong_t off, dt_printarg_t *pap) static void dt_print_structlike(ctf_id_t id, ulong_t off, dt_printarg_t *pap) { - (void) fprintf(pap->pa_file, "{"); + if (pap->pa_dtp->dt_oformat == DTRACE_OFORMAT_TEXT) + (void)fprintf(pap->pa_file, "{"); } /* @@ -480,6 +532,7 @@ dt_print_enum(ctf_id_t base, ulong_t off, dt_printarg_t *pap) ssize_t size; caddr_t addr = pap->pa_addr + off / NBBY; int value = 0; + dtrace_hdl_t *dtp = pap->pa_dtp; /* * The C standard says that an enum will be at most the sizeof (int). @@ -498,14 +551,19 @@ dt_print_enum(ctf_id_t base, ulong_t off, dt_printarg_t *pap) value = *(int32_t *)addr; break; default: - (void) fprintf(fp, "<invalid enum size %u>", (uint_t)size); + xo_emit("<{:warning} {:size/%u}>", "invalid enum size", + (uint_t)size); return; } - if ((ename = ctf_enum_name(ctfp, base, value)) != NULL) - (void) fprintf(fp, "%s", ename); - else - (void) fprintf(fp, "%d", value); + if ((ename = ctf_enum_name(ctfp, base, value)) != NULL) { + xo_emit("{:value/%s}", ename); + } else { + xo_emit("{:value/%d}", value); + } + + /* Flush in order to ensure output is aligned properly */ + xo_flush(); } /* @@ -516,7 +574,8 @@ dt_print_enum(ctf_id_t base, ulong_t off, dt_printarg_t *pap) static void dt_print_tag(ctf_id_t base, ulong_t off, dt_printarg_t *pap) { - (void) fprintf(pap->pa_file, "<forward decl>"); + if (pap->pa_dtp->dt_oformat == DTRACE_OFORMAT_TEXT) + (void)fprintf(pap->pa_file, "<forward decl>"); } typedef void dt_printarg_f(ctf_id_t, ulong_t, dt_printarg_t *); @@ -533,6 +592,46 @@ static dt_printarg_f *const dt_printfuncs[] = { dt_print_tag /* CTF_K_FORWARD */ }; +static int +dt_format_member(const char *name, ctf_id_t id, ulong_t off, int depth, + void *data) +{ + char type[DT_TYPE_NAMELEN]; + int kind; + dt_printarg_t *pap = data; + FILE *fp = pap->pa_file; + ctf_file_t *ctfp = pap->pa_ctfp; + boolean_t arraymember; + boolean_t brief; + ctf_encoding_t e; + ctf_id_t rtype; + + if ((rtype = ctf_type_resolve(ctfp, id)) == CTF_ERR || + (kind = ctf_type_kind(ctfp, rtype)) == CTF_ERR || + kind < CTF_K_INTEGER || kind > CTF_K_FORWARD) { + xo_emit("{:name/%s} <{:warning} {:type-identifier/%lu}>" + " {:value/0x%llx}", + name, "invalid type", id, pap->pa_addr); + return (0); + } + + dt_print_type_name(ctfp, id, type, sizeof (type)); + xo_open_instance("type"); + if (pap->pa_object) { + xo_emit("{:object-name/%s}", pap->pa_object); + /* Clear the object to avoid duplication */ + pap->pa_object = NULL; + } + + if (*name != 0) + xo_emit("{:member-name/%s}", name); + xo_emit("{:name/%s} {:ctfid/%ld}", type, id); + dt_printfuncs[kind - 1](rtype, off, pap); + + xo_close_instance("type"); + return (0); +} + /* * Print one member of a structure. This callback is invoked from * ctf_type_visit() recursively. @@ -634,16 +733,12 @@ dt_print_member(const char *name, ctf_id_t id, ulong_t off, int depth, return (0); } -/* - * Main print function invoked by dt_consume_cpu(). - */ -int -dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename, - caddr_t addr, size_t len) +static ctf_id_t +dt_print_prepare(dtrace_hdl_t *dtp, const char *typename, caddr_t addr, + size_t len, dt_printarg_t *pa) { const char *s; char *object; - dt_printarg_t pa; ctf_id_t id; dt_module_t *dmp; ctf_file_t *ctfp; @@ -661,20 +756,20 @@ dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename, ; if (*s != '`') - return (0); + return (CTF_ERR); 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); + return (CTF_ERR); if (dmp->dm_pid != 0) { libid = atoi(s + 1); s = strchr(s + 1, '`'); if (s == NULL || libid > dmp->dm_nctflibs) - return (0); + return (CTF_ERR); ctfp = dmp->dm_libctfp[libid]; } else { ctfp = dt_module_getctf(dtp, dmp); @@ -688,18 +783,63 @@ dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename, * work. */ if (ctfp == NULL || ctf_type_kind(ctfp, id) == CTF_ERR) + return (CTF_ERR); + + pa->pa_dtp = dtp; + pa->pa_addr = addr; + pa->pa_ctfp = ctfp; + pa->pa_nest = 0; + pa->pa_depth = 0; + pa->pa_object = strdup(object); + return (id); +} + +/* + * Main print function invoked by dt_consume_cpu(). + */ +int +dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename, + caddr_t addr, size_t len) +{ + dt_printarg_t pa; + ctf_id_t id; + + id = dt_print_prepare(dtp, typename, addr, len, &pa); + if (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 = ctfp; - pa.pa_nest = 0; - pa.pa_depth = 0; pa.pa_file = fp; (void) ctf_type_visit(pa.pa_ctfp, id, dt_print_member, &pa); dt_print_trailing_braces(&pa, 0); + dt_free(dtp, (void *)pa.pa_object); + + return (len); +} + +/* + * Main format function invoked by dt_consume_cpu(). + */ +int +dtrace_format_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename, + caddr_t addr, size_t len) +{ + dt_printarg_t pa; + ctf_id_t id; + char toplevel[1024]; + + id = dt_print_prepare(dtp, typename, addr, len, &pa); + if (id == CTF_ERR) + return (0); + + if (ctf_type_name(pa.pa_ctfp, id, toplevel, sizeof(toplevel)) < 0) + return (0); + + xo_open_list("type"); + (void) ctf_type_visit(pa.pa_ctfp, id, dt_format_member, &pa); + xo_close_list("type"); + dt_free(dtp, (void *)pa.pa_object); return (len); } + diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c index 57a7db4ad0fd..c33ae955ba61 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c @@ -317,8 +317,7 @@ pfprint_fp(dtrace_hdl_t *dtp, FILE *fp, const char *format, case sizeof (double): return (dt_printf(dtp, fp, format, *((double *)addr) / n)); -#if !defined(__arm__) && !defined(__powerpc__) && \ - !defined(__mips__) && !defined(__riscv) +#if !defined(__arm__) && !defined(__powerpc__) && !defined(__riscv) case sizeof (long double): return (dt_printf(dtp, fp, format, *((long double *)addr) / ldn)); diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.h index b3b5b8b94bf6..58e345b204ac 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.h +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.h @@ -21,6 +21,7 @@ */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2023 Domagoj Stolfa. All rights reserved. * Use is subject to license terms. */ @@ -128,6 +129,11 @@ extern int dt_print_ustack(dtrace_hdl_t *, FILE *, extern int dt_print_mod(dtrace_hdl_t *, FILE *, const char *, caddr_t); extern int dt_print_umod(dtrace_hdl_t *, FILE *, const char *, caddr_t); +extern int dt_format_stack(dtrace_hdl_t *, caddr_t, int, int); +extern int dt_format_ustack(dtrace_hdl_t *, caddr_t, uint64_t); +extern int dt_format_mod(dtrace_hdl_t *, caddr_t); +extern int dt_format_umod(dtrace_hdl_t *, caddr_t); + #ifdef __cplusplus } #endif diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.c index 34bcc15b9ac7..b32dcea1f8ba 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.c @@ -80,10 +80,8 @@ * up using this condition and will then call the client handler as necessary. */ +#include <sys/syscall.h> #include <sys/wait.h> -#ifdef illumos -#include <sys/lwp.h> -#endif #include <strings.h> #include <signal.h> #include <assert.h> @@ -93,14 +91,10 @@ #include <dt_pid.h> #include <dt_impl.h> -#ifndef illumos -#include <sys/syscall.h> #include <libproc_compat.h> -#define SYS_forksys SYS_fork -#endif #define IS_SYS_EXEC(w) (w == SYS_execve) -#define IS_SYS_FORK(w) (w == SYS_vfork || w == SYS_forksys) +#define IS_SYS_FORK(w) (w == SYS_vfork || w == SYS_fork) static dt_bkpt_t * dt_proc_bpcreate(dt_proc_t *dpr, uintptr_t addr, dt_bkpt_f *func, void *data) @@ -147,38 +141,23 @@ dt_proc_bpdestroy(dt_proc_t *dpr, int delbkpts) static void dt_proc_bpmatch(dtrace_hdl_t *dtp, dt_proc_t *dpr) { -#ifdef illumos - const lwpstatus_t *psp = &Pstatus(dpr->dpr_proc)->pr_lwp; -#else unsigned long pc; -#endif dt_bkpt_t *dbp; assert(DT_MUTEX_HELD(&dpr->dpr_lock)); -#ifndef illumos proc_regget(dpr->dpr_proc, REG_PC, &pc); proc_bkptregadj(&pc); -#endif for (dbp = dt_list_next(&dpr->dpr_bps); dbp != NULL; dbp = dt_list_next(dbp)) { -#ifdef illumos - if (psp->pr_reg[R_PC] == dbp->dbp_addr) - break; -#else if (pc == dbp->dbp_addr) break; -#endif } if (dbp == NULL) { dt_dprintf("pid %d: spurious breakpoint wakeup for %lx\n", -#ifdef illumos - (int)dpr->dpr_pid, (ulong_t)psp->pr_reg[R_PC]); -#else (int)dpr->dpr_pid, pc); -#endif return; } @@ -346,12 +325,8 @@ dt_proc_rdwatch(dt_proc_t *dpr, rd_event_e event, const char *evname) } (void) dt_proc_bpcreate(dpr, rdn.u.bptaddr, -#ifdef illumos - (dt_bkpt_f *)dt_proc_rdevent, (void *)evname); -#else /* XXX ugly */ (dt_bkpt_f *)dt_proc_rdevent, __DECONST(void *, evname)); -#endif } /* @@ -361,34 +336,18 @@ dt_proc_rdwatch(dt_proc_t *dpr, rd_event_e event, const char *evname) static void dt_proc_attach(dt_proc_t *dpr, int exec) { -#ifdef illumos - const pstatus_t *psp = Pstatus(dpr->dpr_proc); -#endif rd_err_e err; GElf_Sym sym; assert(DT_MUTEX_HELD(&dpr->dpr_lock)); if (exec) { -#ifdef illumos - if (psp->pr_lwp.pr_errno != 0) - return; /* exec failed: nothing needs to be done */ -#endif dt_proc_bpdestroy(dpr, B_FALSE); -#ifdef illumos - Preset_maps(dpr->dpr_proc); -#endif } if ((dpr->dpr_rtld = Prd_agent(dpr->dpr_proc)) != NULL && (err = rd_event_enable(dpr->dpr_rtld, B_TRUE)) == RD_OK) { -#ifdef illumos - dt_proc_rdwatch(dpr, RD_PREINIT, "RD_PREINIT"); -#endif dt_proc_rdwatch(dpr, RD_POSTINIT, "RD_POSTINIT"); -#ifdef illumos - dt_proc_rdwatch(dpr, RD_DLACTIVITY, "RD_DLACTIVITY"); -#endif } else { dt_dprintf("pid %d: failed to enable rtld events: %s\n", (int)dpr->dpr_pid, dpr->dpr_rtld ? rd_errstr(err) : @@ -407,84 +366,6 @@ dt_proc_attach(dt_proc_t *dpr, int exec) } } -/* - * Wait for a stopped process to be set running again by some other debugger. - * This is typically not required by /proc-based debuggers, since the usual - * model is that one debugger controls one victim. But DTrace, as usual, has - * its own needs: the stop() action assumes that prun(1) or some other tool - * will be applied to resume the victim process. This could be solved by - * adding a PCWRUN directive to /proc, but that seems like overkill unless - * other debuggers end up needing this functionality, so we implement a cheap - * equivalent to PCWRUN using the set of existing kernel mechanisms. - * - * Our intent is really not just to wait for the victim to run, but rather to - * wait for it to run and then stop again for a reason other than the current - * PR_REQUESTED stop. Since PCWSTOP/Pstopstatus() can be applied repeatedly - * to a stopped process and will return the same result without affecting the - * victim, we can just perform these operations repeatedly until Pstate() - * changes, the representative LWP ID changes, or the stop timestamp advances. - * dt_proc_control() will then rediscover the new state and continue as usual. - * When the process is still stopped in the same exact state, we sleep for a - * brief interval before waiting again so as not to spin consuming CPU cycles. - */ -static void -dt_proc_waitrun(dt_proc_t *dpr) -{ - printf("%s:%s(%d): not implemented\n", __FUNCTION__, __FILE__, - __LINE__); -#ifdef DOODAD - struct ps_prochandle *P = dpr->dpr_proc; - const lwpstatus_t *psp = &Pstatus(P)->pr_lwp; - - int krflag = psp->pr_flags & (PR_KLC | PR_RLC); - timestruc_t tstamp = psp->pr_tstamp; - lwpid_t lwpid = psp->pr_lwpid; - - const long wstop = PCWSTOP; - int pfd = Pctlfd(P); - - assert(DT_MUTEX_HELD(&dpr->dpr_lock)); - assert(psp->pr_flags & PR_STOPPED); - assert(Pstate(P) == PS_STOP); - - /* - * While we are waiting for the victim to run, clear PR_KLC and PR_RLC - * so that if the libdtrace client is killed, the victim stays stopped. - * dt_proc_destroy() will also observe this and perform PRELEASE_HANG. - */ - (void) Punsetflags(P, krflag); - Psync(P); - - (void) pthread_mutex_unlock(&dpr->dpr_lock); - - while (!dpr->dpr_quit) { - if (write(pfd, &wstop, sizeof (wstop)) == -1 && errno == EINTR) - continue; /* check dpr_quit and continue waiting */ - - (void) pthread_mutex_lock(&dpr->dpr_lock); - (void) Pstopstatus(P, PCNULL, 0); - psp = &Pstatus(P)->pr_lwp; - - /* - * If we've reached a new state, found a new representative, or - * the stop timestamp has changed, restore PR_KLC/PR_RLC to its - * original setting and then return with dpr_lock held. - */ - if (Pstate(P) != PS_STOP || psp->pr_lwpid != lwpid || - bcmp(&psp->pr_tstamp, &tstamp, sizeof (tstamp)) != 0) { - (void) Psetflags(P, krflag); - Psync(P); - return; - } - - (void) pthread_mutex_unlock(&dpr->dpr_lock); - (void) poll(NULL, 0, MILLISEC / 2); - } - - (void) pthread_mutex_lock(&dpr->dpr_lock); -#endif -} - typedef struct dt_proc_control_data { dtrace_hdl_t *dpcd_hdl; /* DTrace handle */ dt_proc_t *dpcd_proc; /* proccess to control */ @@ -511,12 +392,6 @@ dt_proc_control(void *arg) dt_proc_hash_t *dph = dtp->dt_procs; struct ps_prochandle *P = dpr->dpr_proc; int pid = dpr->dpr_pid; - -#ifdef illumos - int pfd = Pctlfd(P); - - const long wstop = PCWSTOP; -#endif int notify = B_FALSE; /* @@ -534,44 +409,14 @@ dt_proc_control(void *arg) */ (void) pthread_mutex_lock(&dpr->dpr_lock); -#ifdef illumos - (void) Punsetflags(P, PR_ASYNC); /* require synchronous mode */ - (void) Psetflags(P, PR_BPTADJ); /* always adjust eip on x86 */ - (void) Punsetflags(P, PR_FORK); /* do not inherit on fork */ - - (void) Pfault(P, FLTBPT, B_TRUE); /* always trace breakpoints */ - (void) Pfault(P, FLTTRACE, B_TRUE); /* always trace single-step */ - - /* - * We must trace exit from exec() system calls so that if the exec is - * successful, we can reset our breakpoints and re-initialize libproc. - */ - (void) Psysexit(P, SYS_execve, B_TRUE); - - /* - * We must trace entry and exit for fork() system calls in order to - * disable our breakpoints temporarily during the fork. We do not set - * the PR_FORK flag, so if fork succeeds the child begins executing and - * does not inherit any other tracing behaviors or a control thread. - */ - (void) Psysentry(P, SYS_vfork, B_TRUE); - (void) Psysexit(P, SYS_vfork, B_TRUE); - (void) Psysentry(P, SYS_forksys, B_TRUE); - (void) Psysexit(P, SYS_forksys, B_TRUE); - - Psync(P); /* enable all /proc changes */ -#endif dt_proc_attach(dpr, B_FALSE); /* enable rtld breakpoints */ /* - * If PR_KLC is set, we created the process; otherwise we grabbed it. - * Check for an appropriate stop request and wait for dt_proc_continue. + * If DT_CLOSE_KILL is set, we created the process; otherwise we + * grabbed it. Check for an appropriate stop request and wait for + * dt_proc_continue. */ -#ifdef illumos - if (Pstatus(P)->pr_flags & PR_KLC) -#else - if (proc_getflags(P) & PR_KLC) -#endif + if (dpr->dpr_close == DT_CLOSE_KILL) dt_proc_stop(dpr, DT_PROC_STOP_CREATE); else dt_proc_stop(dpr, DT_PROC_STOP_GRAB); @@ -595,55 +440,21 @@ dt_proc_control(void *arg) while (!dpr->dpr_quit) { const lwpstatus_t *psp; -#ifdef illumos - if (write(pfd, &wstop, sizeof (wstop)) == -1 && errno == EINTR) - continue; /* check dpr_quit and continue waiting */ -#else /* Wait for the process to report status. */ proc_wstatus(P); if (errno == EINTR) continue; /* check dpr_quit and continue waiting */ -#endif (void) pthread_mutex_lock(&dpr->dpr_lock); -#ifdef illumos -pwait_locked: - if (Pstopstatus(P, PCNULL, 0) == -1 && errno == EINTR) { - (void) pthread_mutex_unlock(&dpr->dpr_lock); - continue; /* check dpr_quit and continue waiting */ - } -#endif - switch (Pstate(P)) { case PS_STOP: -#ifdef illumos - psp = &Pstatus(P)->pr_lwp; -#else psp = proc_getlwpstatus(P); -#endif dt_dprintf("pid %d: proc stopped showing %d/%d\n", pid, psp->pr_why, psp->pr_what); /* - * If the process stops showing PR_REQUESTED, then the - * DTrace stop() action was applied to it or another - * debugging utility (e.g. pstop(1)) asked it to stop. - * In either case, the user's intention is for the - * process to remain stopped until another external - * mechanism (e.g. prun(1)) is applied. So instead of - * setting the process running ourself, we wait for - * someone else to do so. Once that happens, we return - * to our normal loop waiting for an event of interest. - */ - if (psp->pr_why == PR_REQUESTED) { - dt_proc_waitrun(dpr); - (void) pthread_mutex_unlock(&dpr->dpr_lock); - continue; - } - - /* * If the process stops showing one of the events that * we are tracing, perform the appropriate response. * Note that we ignore PR_SUSPENDED, PR_CHECKPOINT, and @@ -666,11 +477,6 @@ pwait_locked: break; case PS_LOST: -#ifdef illumos - if (Preopen(P) == 0) - goto pwait_locked; -#endif - dt_dprintf("pid %d: proc lost: %s\n", pid, strerror(errno)); @@ -685,9 +491,19 @@ pwait_locked: break; } - if (Pstate(P) != PS_UNDEAD && Psetrun(P, 0, 0) == -1) { - dt_dprintf("pid %d: failed to set running: %s\n", - (int)dpr->dpr_pid, strerror(errno)); + if (Pstate(P) != PS_UNDEAD) { + if (dpr->dpr_quit && dpr->dpr_close == DT_CLOSE_KILL) { + /* + * We're about to kill the child, so don't + * bother resuming it. In some cases, such as + * an initialization error, we shouldn't have + * started it in the first place, so letting it + * run could be harmful. + */ + } else if (Psetrun(P, 0, 0) == -1) { + dt_dprintf("pid %d: failed to set running: " + "%s\n", (int)dpr->dpr_pid, strerror(errno)); + } } (void) pthread_mutex_unlock(&dpr->dpr_lock); @@ -739,11 +555,7 @@ dt_proc_t * dt_proc_lookup(dtrace_hdl_t *dtp, struct ps_prochandle *P, int remove) { dt_proc_hash_t *dph = dtp->dt_procs; -#ifdef illumos - pid_t pid = Pstatus(P)->pr_pid; -#else pid_t pid = proc_getpid(P); -#endif dt_proc_t *dpr, **dpp = &dph->dph_hash[pid & (dph->dph_hashlen - 1)]; for (dpr = *dpp; dpr != NULL; dpr = dpr->dpr_hash) { @@ -772,28 +584,15 @@ dt_proc_destroy(dtrace_hdl_t *dtp, struct ps_prochandle *P) assert(dpr != NULL); - /* - * If neither PR_KLC nor PR_RLC is set, then the process is stopped by - * an external debugger and we were waiting in dt_proc_waitrun(). - * Leave the process in this condition using PRELEASE_HANG. - */ -#ifdef illumos - if (!(Pstatus(dpr->dpr_proc)->pr_flags & (PR_KLC | PR_RLC))) { -#else - if (!(proc_getflags(dpr->dpr_proc) & (PR_KLC | PR_RLC))) { -#endif - dt_dprintf("abandoning pid %d\n", (int)dpr->dpr_pid); - rflag = PRELEASE_HANG; -#ifdef illumos - } else if (Pstatus(dpr->dpr_proc)->pr_flags & PR_KLC) { -#else - } else if (proc_getflags(dpr->dpr_proc) & PR_KLC) { -#endif + switch (dpr->dpr_close) { + case DT_CLOSE_KILL: dt_dprintf("killing pid %d\n", (int)dpr->dpr_pid); - rflag = PRELEASE_KILL; /* apply kill-on-last-close */ - } else { + rflag = PRELEASE_KILL; + break; + case DT_CLOSE_RUN: dt_dprintf("releasing pid %d\n", (int)dpr->dpr_pid); - rflag = 0; /* apply run-on-last-close */ + rflag = 0; + break; } if (dpr->dpr_tid) { @@ -813,11 +612,7 @@ dt_proc_destroy(dtrace_hdl_t *dtp, struct ps_prochandle *P) */ (void) pthread_mutex_lock(&dpr->dpr_lock); dpr->dpr_quit = B_TRUE; -#ifdef illumos - (void) _lwp_kill(dpr->dpr_tid, SIGCANCEL); -#else pthread_kill(dpr->dpr_tid, SIGTHR); -#endif /* * If the process is currently idling in dt_proc_stop(), re- @@ -885,11 +680,7 @@ dt_proc_create_thread(dtrace_hdl_t *dtp, dt_proc_t *dpr, uint_t stop) (void) sigfillset(&nset); (void) sigdelset(&nset, SIGABRT); /* unblocked for assert() */ -#ifdef illumos - (void) sigdelset(&nset, SIGCANCEL); /* see dt_proc_destroy() */ -#else (void) sigdelset(&nset, SIGUSR1); /* see dt_proc_destroy() */ -#endif data.dpcd_hdl = dtp; data.dpcd_proc = dpr; @@ -917,14 +708,8 @@ dt_proc_create_thread(dtrace_hdl_t *dtp, dt_proc_t *dpr, uint_t stop) * small amount of useful information to help figure it out. */ if (dpr->dpr_done) { -#ifdef illumos - const psinfo_t *prp = Ppsinfo(dpr->dpr_proc); - int stat = prp ? prp->pr_wstat : 0; - int pid = dpr->dpr_pid; -#else int stat = proc_getwstat(dpr->dpr_proc); int pid = proc_getpid(dpr->dpr_proc); -#endif if (proc_state(dpr->dpr_proc) == PS_LOST) { (void) dt_proc_error(dpr->dpr_hdl, dpr, "failed to control pid %d: process exec'd " @@ -968,29 +753,15 @@ dt_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv, (void) pthread_mutex_init(&dpr->dpr_lock, NULL); (void) pthread_cond_init(&dpr->dpr_cv, NULL); -#ifdef illumos - dpr->dpr_proc = Pxcreate(file, argv, dtp->dt_proc_env, &err, NULL, 0); - if (dpr->dpr_proc == NULL) { - return (dt_proc_error(dtp, dpr, - "failed to execute %s: %s\n", file, Pcreate_error(err))); - } -#else if ((err = proc_create(file, argv, dtp->dt_proc_env, pcf, child_arg, &dpr->dpr_proc)) != 0) { return (dt_proc_error(dtp, dpr, "failed to execute %s: %s\n", file, Pcreate_error(err))); } -#endif dpr->dpr_hdl = dtp; -#ifdef illumos - dpr->dpr_pid = Pstatus(dpr->dpr_proc)->pr_pid; -#else dpr->dpr_pid = proc_getpid(dpr->dpr_proc); -#endif - - (void) Punsetflags(dpr->dpr_proc, PR_RLC); - (void) Psetflags(dpr->dpr_proc, PR_KLC); + dpr->dpr_close = DT_CLOSE_KILL; if (dt_proc_create_thread(dtp, dpr, dtp->dt_prcmode) != 0) return (NULL); /* dt_proc_error() has been called for us */ @@ -1048,20 +819,14 @@ dt_proc_grab(dtrace_hdl_t *dtp, pid_t pid, int flags, int nomonitor) (void) pthread_mutex_init(&dpr->dpr_lock, NULL); (void) pthread_cond_init(&dpr->dpr_cv, NULL); -#ifdef illumos - if ((dpr->dpr_proc = Pgrab(pid, flags, &err)) == NULL) { -#else if ((err = proc_attach(pid, flags, &dpr->dpr_proc)) != 0) { -#endif return (dt_proc_error(dtp, dpr, "failed to grab pid %d: %s\n", (int)pid, Pgrab_error(err))); } dpr->dpr_hdl = dtp; dpr->dpr_pid = pid; - - (void) Punsetflags(dpr->dpr_proc, PR_KLC); - (void) Psetflags(dpr->dpr_proc, PR_RLC); + dpr->dpr_close = DT_CLOSE_RUN; /* * If we are attempting to grab the process without a monitor @@ -1227,11 +992,7 @@ dtrace_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv, struct ps_prochandle *P = dt_proc_create(dtp, file, argv, pcf, child_arg); if (P != NULL && idp != NULL && idp->di_id == 0) { -#ifdef illumos - idp->di_id = Pstatus(P)->pr_pid; /* $target = created pid */ -#else idp->di_id = proc_getpid(P); /* $target = created pid */ -#endif } return (P); diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.h index beae6f6d5cda..458e9902881f 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.h +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.h @@ -40,6 +40,11 @@ extern "C" { #endif +enum dt_close_action { + DT_CLOSE_RUN, + DT_CLOSE_KILL, +}; + typedef struct dt_proc { dt_list_t dpr_list; /* prev/next pointers for lru chain */ struct dt_proc *dpr_hash; /* next pointer for pid hash chain */ @@ -60,6 +65,7 @@ typedef struct dt_proc { uint8_t dpr_rdonly; /* proc flag: opened read-only */ pthread_t dpr_tid; /* control thread (or zero if none) */ dt_list_t dpr_bps; /* list of dt_bkpt_t structures */ + enum dt_close_action dpr_close; /* do this to child when exiting */ } dt_proc_t; typedef struct dt_proc_notify { diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c index 7cf352d4d505..2391690afc0b 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c @@ -48,6 +48,7 @@ #include <dt_list.h> #include <dt_pid.h> #include <dtrace.h> +#include <kinst.h> static dt_provider_t * dt_provider_insert(dtrace_hdl_t *dtp, dt_provider_t *pvp, uint_t h) @@ -699,6 +700,34 @@ dt_probe_info(dtrace_hdl_t *dtp, prp = idp->di_data; else if (pdp->dtpd_id != DTRACE_IDNONE) prp = dt_probe_discover(pvp, pdp); + + if (strcmp(pvp->pv_desc.dtvd_name, "kinst") == 0) { + dtrace_kinst_probedesc_t pd; + + if (dtp->dt_kinstfd == -1) { + int fd; + + fd = open("/dev/dtrace/kinst", O_WRONLY); + if (fd < 0) { + (void) dt_set_errno(dtp, errno); + return (NULL); + } + dtp->dt_kinstfd = fd; + } + memset(&pd, 0, sizeof(pd)); + strlcpy(pd.kpd_func, pdp->dtpd_func, + sizeof (pd.kpd_func)); + + if (n_is_glob) + pd.kpd_off = -1; + else + pd.kpd_off = strtol(pdp->dtpd_name, NULL, 10); + if (ioctl(dtp->dt_kinstfd, KINSTIOC_MAKEPROBE, &pd) != + 0) { + (void) dt_set_errno(dtp, errno); + return (NULL); + } + } } /* diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c index 1729eaf2e7be..5976333e1b16 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c @@ -50,6 +50,7 @@ #include <stdint.h> #include <dt_impl.h> +#include <dt_oformat.h> static const struct { size_t dtps_offset; @@ -992,3 +993,44 @@ dtrace_uaddr2str(dtrace_hdl_t *dtp, pid_t pid, return (dt_string2str(c, str, nbytes)); } + +int +dtrace_oformat_configure(dtrace_hdl_t *dtp) +{ + + dtp->dt_oformat = xo_get_style(NULL) == XO_STYLE_TEXT ? + DTRACE_OFORMAT_TEXT : + DTRACE_OFORMAT_STRUCTURED; + xo_set_flags(NULL, XOF_DTRT); + return (0); +} + +int +dtrace_oformat(dtrace_hdl_t *dtp) +{ + + return (dtp->dt_oformat != DTRACE_OFORMAT_TEXT); +} + +void +dtrace_set_outfp(const FILE *ofp) +{ + + xo_set_file((FILE *)ofp); +} + +void +dtrace_oformat_setup(dtrace_hdl_t *dtp) +{ + + xo_open_container("dtrace"); + xo_open_list("probes"); +} + +void +dtrace_oformat_teardown(dtrace_hdl_t *dtp) +{ + + xo_close_list("probes"); + xo_close_container("dtrace"); +} diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h b/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h index f0bc83a7fc7b..b380f5eb3313 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h @@ -25,6 +25,7 @@ */ /* + * Copyright (c) 2023 by Domagoj Stolfa. All rights reserved. * Copyright (c) 2014, 2016 by Delphix. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ @@ -119,10 +120,11 @@ typedef struct dtrace_proginfo { #define DTRACE_C_PSPEC 0x0080 /* Interpret ambiguous specifiers as probes */ #define DTRACE_C_ETAGS 0x0100 /* Prefix error messages with error tags */ #define DTRACE_C_ARGREF 0x0200 /* Do not require all macro args to be used */ +#define DTRACE_C_SUGAR 0x0400 /* Dump D script post-dt_sugar */ #define DTRACE_C_DEFARG 0x0800 /* Use 0/"" as value for unspecified args */ #define DTRACE_C_NOLIBS 0x1000 /* Do not process D system libraries */ #define DTRACE_C_CTL 0x2000 /* Only process control directives */ -#define DTRACE_C_MASK 0x3bff /* mask of all valid flags to dtrace_*compile */ +#define DTRACE_C_MASK 0x3fff /* mask of all valid flags to dtrace_*compile */ extern dtrace_prog_t *dtrace_program_strcompile(dtrace_hdl_t *, const char *, dtrace_probespec_t, uint_t, int, char *const []); @@ -199,6 +201,7 @@ typedef struct dtrace_probedata { dtrace_flowkind_t dtpda_flow; /* flow kind */ const char *dtpda_prefix; /* recommended flow prefix */ int dtpda_indent; /* recommended flow indent */ + uint64_t dtpda_timestamp; /* hrtime of snapshot */ } dtrace_probedata_t; typedef int dtrace_consume_probe_f(const dtrace_probedata_t *, void *); @@ -232,6 +235,10 @@ extern void *dtrace_printf_create(dtrace_hdl_t *, const char *); extern void *dtrace_printa_create(dtrace_hdl_t *, const char *); extern size_t dtrace_printf_format(dtrace_hdl_t *, void *, char *, size_t); +extern int dtrace_sprintf(dtrace_hdl_t *, FILE *, void *, + const dtrace_recdesc_t *, uint_t, + const void *, size_t); + extern int dtrace_fprintf(dtrace_hdl_t *, FILE *, void *, const dtrace_probedata_t *, const dtrace_recdesc_t *, uint_t, const void *, size_t); @@ -259,6 +266,8 @@ extern int dtrace_freopen(dtrace_hdl_t *, FILE *, void *, */ extern int dtrace_print(dtrace_hdl_t *, FILE *, const char *, caddr_t, size_t); +extern int dtrace_format_print(dtrace_hdl_t *, FILE *, const char *, + caddr_t, size_t); /* * DTrace Work Interface @@ -615,4 +624,18 @@ extern int _dtrace_debug; #define _SC_NPROCESSORS_MAX _SC_NPROCESSORS_CONF #endif +/* + * Values for the dt_oformat property. + */ +#define DTRACE_OFORMAT_TEXT 0 +#define DTRACE_OFORMAT_STRUCTURED 1 + +extern int dtrace_oformat_configure(dtrace_hdl_t *); +extern int dtrace_oformat(dtrace_hdl_t *); +extern void dtrace_set_outfp(const FILE *); +extern void dtrace_oformat_setup(dtrace_hdl_t *); +extern void dtrace_oformat_teardown(dtrace_hdl_t *); +extern void dtrace_oformat_probe(dtrace_hdl_t *, const dtrace_probedata_t *, + processorid_t, dtrace_probedesc_t *); + #endif /* _DTRACE_H */ diff --git a/cddl/contrib/opensolaris/tools/ctf/common/utils.c b/cddl/contrib/opensolaris/tools/ctf/common/utils.c index f74eb8de40fa..fda29486d94b 100644 --- a/cddl/contrib/opensolaris/tools/ctf/common/utils.c +++ b/cddl/contrib/opensolaris/tools/ctf/common/utils.c @@ -35,30 +35,6 @@ /*LINTLIBRARY*/ -static const char *pname; - -#pragma init(getpname) -const char * -getpname(void) -{ - const char *p, *q; - - if (pname != NULL) - return (pname); - - if ((p = getexecname()) != NULL) - q = strrchr(p, '/'); - else - q = NULL; - - if (q == NULL) - pname = p; - else - pname = q + 1; - - return (pname); -} - void vdie(const char *format, va_list alist) { diff --git a/cddl/contrib/opensolaris/tools/ctf/common/utils.h b/cddl/contrib/opensolaris/tools/ctf/common/utils.h index 99378bb4f251..6918bdab89aa 100644 --- a/cddl/contrib/opensolaris/tools/ctf/common/utils.h +++ b/cddl/contrib/opensolaris/tools/ctf/common/utils.h @@ -42,8 +42,6 @@ extern "C" { extern void vdie(const char *, va_list); extern void die(const char *, ...); -extern const char *getpname(void); - #ifdef __cplusplus } #endif diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.c b/cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.c index 161927cf0663..c5be22ecfa1b 100644 --- a/cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.c +++ b/cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.c @@ -886,7 +886,7 @@ main(int argc, char **argv) for (i = 0; i < nifiles; i++) tifiles[i] = argv[optind + i]; - qsort(tifiles, nifiles, sizeof (char *), (int (*)())strcompare); + qsort(tifiles, nifiles, sizeof (char *), strcompare); ifiles[0] = tifiles[0]; for (idx = 0, tidx = 1; tidx < nifiles; tidx++) { @@ -912,14 +912,8 @@ main(int argc, char **argv) */ if (read_ctf(ifiles, nifiles, NULL, merge_ctf_cb, &wq, require_ctf) == 0) { - /* - * If we're verifying that C files have CTF, it's safe to - * assume that in this case, we're building only from assembly - * inputs. - */ - if (require_ctf) - exit(0); - terminate("No ctf sections found to merge\n"); + warning("No ctf sections found to merge\n"); + exit(0); } pthread_mutex_lock(&wq.wq_queue_lock); diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c b/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c index 67866555ae5d..42faaad65db5 100644 --- a/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c +++ b/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c @@ -1004,7 +1004,9 @@ die_sou_create(dwarf_t *dw, Dwarf_Die str, Dwarf_Off off, tdesc_t *tdp, else ml->ml_size = tdesc_bitsize(ml->ml_type); - if (die_unsigned(dw, mem, DW_AT_bit_offset, &bitoff, 0)) { + if (die_unsigned(dw, mem, DW_AT_data_bit_offset, &bitoff, 0)) { + ml->ml_offset += bitoff; + } else if (die_unsigned(dw, mem, DW_AT_bit_offset, &bitoff, 0)) { #if BYTE_ORDER == _BIG_ENDIAN ml->ml_offset += bitoff; #else @@ -1367,7 +1369,7 @@ static const fp_size_map_t fp_encodings[] = { }; static uint_t -die_base_type2enc(dwarf_t *dw, Dwarf_Off off, Dwarf_Signed enc, size_t sz) +die_base_type2enc(dwarf_t *dw, Dwarf_Off off, Dwarf_Unsigned enc, size_t sz) { const fp_size_map_t *map = fp_encodings; uint_t szidx = dw->dw_ptrsz == sizeof (uint64_t); @@ -1398,9 +1400,9 @@ static intr_t * die_base_from_dwarf(dwarf_t *dw, Dwarf_Die base, Dwarf_Off off, size_t sz) { intr_t *intr = xcalloc(sizeof (intr_t)); - Dwarf_Signed enc; + Dwarf_Unsigned enc; - (void) die_signed(dw, base, DW_AT_encoding, &enc, DW_ATTR_REQ); + (void) die_unsigned(dw, base, DW_AT_encoding, &enc, DW_ATTR_REQ); switch (enc) { case DW_ATE_unsigned: diff --git a/cddl/contrib/opensolaris/tools/ctf/dump/dump.c b/cddl/contrib/opensolaris/tools/ctf/dump/dump.c index 06c00a7b0e7f..5cbf46af1b73 100644 --- a/cddl/contrib/opensolaris/tools/ctf/dump/dump.c +++ b/cddl/contrib/opensolaris/tools/ctf/dump/dump.c @@ -856,7 +856,7 @@ print_stats(void) static int print_usage(FILE *fp, int verbose) { - (void) fprintf(fp, "Usage: %s [-dfhlsSt] [-u file] file\n", getpname()); + (void) fprintf(fp, "Usage: %s [-dfhlsSt] [-u file] file\n", getprogname()); if (verbose) { (void) fprintf(fp, |