aboutsummaryrefslogtreecommitdiff
path: root/cddl/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'cddl/contrib')
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/dtrace.1430
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/dtrace.c79
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.system.d.out12
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv6localicmp.ksh.out2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/kinst/tst.basic.ksh48
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/mib/tst.icmp.ksh2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/mib/tst.udp.ksh2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.avg.ksh66
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.count.ksh66
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.llquantize.ksh73
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.lquantize.ksh73
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.max.ksh66
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.min.ksh66
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.quantize.ksh73
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.stddev.ksh66
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.agg.sum.ksh66
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggmod.ksh66
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggstack.ksh66
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggsym.ksh66
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggustack.ksh66
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.aggusym.ksh66
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.drop.ksh61
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.mod.ksh57
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.print.ksh60
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.printf.ksh57
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.printm.ksh57
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.stack.ksh61
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.sym.ksh57
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.trace.ksh66
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.tracemem.ksh57
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.umod.ksh57
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.ustack.ksh61
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/oformat/tst.usym.ksh57
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PDESC_ZERO.badlib.exe2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_FUNC.badfunc.exe2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_LIB.libdash.exe2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.alldash.exe2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.badname.exe2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_NAME.globdash.exe2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/err.D_PROC_OFF.toobig.exe2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/tst.coverage.exe2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/pid/tst.emptystack.exe2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/proc/tst.exitcore.ksh2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/proc/tst.startexit.ksh2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/speculation/tst.NoSpecBuffer.exe2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/translators/tst.OutputAliasTrans.d12
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/i86xpv/xdt/tst.schedargs.ksh2
-rw-r--r--cddl/contrib/opensolaris/cmd/lockstat/lockstat.12
-rw-r--r--cddl/contrib/opensolaris/cmd/lockstat/lockstat.c6
-rw-r--r--cddl/contrib/opensolaris/cmd/lockstat/sym.c21
-rw-r--r--cddl/contrib/opensolaris/common/ctf/ctf_create.c371
-rw-r--r--cddl/contrib/opensolaris/common/ctf/ctf_decl.c19
-rw-r--r--cddl/contrib/opensolaris/common/ctf/ctf_hash.c16
-rw-r--r--cddl/contrib/opensolaris/common/ctf/ctf_impl.h69
-rw-r--r--cddl/contrib/opensolaris/common/ctf/ctf_lookup.c38
-rw-r--r--cddl/contrib/opensolaris/common/ctf/ctf_open.c388
-rw-r--r--cddl/contrib/opensolaris/common/ctf/ctf_types.c439
-rw-r--r--cddl/contrib/opensolaris/common/ctf/ctf_util.c6
-rw-r--r--cddl/contrib/opensolaris/lib/libctf/common/ctf.5208
-rw-r--r--cddl/contrib/opensolaris/lib/libctf/common/ctf_lib.c3
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_aggregate.c17
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_cc.c16
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_consume.c1322
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_handle.c37
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h8
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_lex.l2
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c142
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c30
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_oformat.h34
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c19
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_options.c14
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_parser.c2
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_print.c266
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c3
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.h6
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.c295
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_proc.h6
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_provider.c29
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_subr.c43
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h25
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/mips/dt_isadep.c75
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/common/ctf_headers.h2
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/common/memory.c14
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/common/memory.h1
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/common/utils.c52
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/common/utils.h4
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/compare.c92
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c453
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c3
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.c16
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h20
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c29
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/fixup_tdescs.c119
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/output.c2
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c1214
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/stabs.c381
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/dump/dump.c291
98 files changed, 5576 insertions, 3362 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/aggs/tst.subr.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d
index 9b02e982fe0d..6668f80d81a0 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/aggs/tst.subr.d
@@ -98,7 +98,7 @@ INTFUNC(ntohll(0x1234567890abcdefL))
STRFUNC(inet_ntoa((ipaddr_t *)alloca(sizeof (ipaddr_t))))
STRFUNC(inet_ntoa6((in6_addr_t *)alloca(sizeof (in6_addr_t))))
STRFUNC(inet_ntop(AF_INET, (void *)alloca(sizeof (ipaddr_t))))
-INTFUNC(getf(0))
+/* INTFUNC(getf(0)) */
INTFUNC(strtoll("0x12EE5D5", 16))
STRFUNC(json("{\"systemtap\": false}", "systemtap"))
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.system.d.out b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.system.d.out
index fa61a5110615..16da36e1e3be 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.system.d.out
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.system.d.out
@@ -1,17 +1,17 @@
foo 9 -2
-PING localhost (127.0.0.1): 56 data bytes
+PING 127.0.0.1 (127.0.0.1): 56 data bytes
---- localhost ping statistics ---
+--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
10
-PING localhost (127.0.0.1): 56 data bytes
+PING 127.0.0.1 (127.0.0.1): 56 data bytes
---- localhost ping statistics ---
+--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
11
-PING localhost (127.0.0.1): 56 data bytes
+PING 127.0.0.1 (127.0.0.1): 56 data bytes
---- localhost ping statistics ---
+--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
12
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.exitcore.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/proc/tst.exitcore.ksh
index 59094e3da37f..1c23b2a0b9e0 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/proc/tst.exitcore.ksh
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/proc/tst.exitcore.ksh
@@ -61,7 +61,7 @@ EOF
sleeper()
{
while true; do
- $longsleep &
+ limits -c unlimited $longsleep &
/bin/sleep 1
kill -SEGV $!
done
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/common/translators/tst.OutputAliasTrans.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/translators/tst.OutputAliasTrans.d
index cd4715319913..c6bfff2181e6 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/translators/tst.OutputAliasTrans.d
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/translators/tst.OutputAliasTrans.d
@@ -37,23 +37,23 @@
#pragma D option quiet
-struct input_struct {
+struct dtrace_input_struct {
int ii;
char ic;
};
-struct output_struct {
+struct dtrace_output_struct {
int oi;
char oc;
};
-typedef struct output_struct output_t;
+typedef struct dtrace_output_struct dtrace_output_t;
-translator output_t < struct input_struct *ivar >
+translator dtrace_output_t < struct dtrace_input_struct *ivar >
{
- oi = ((struct input_struct *) ivar)->ii;
- oc = ((struct input_struct *) ivar)->ic;
+ oi = ((struct dtrace_input_struct *) ivar)->ii;
+ oc = ((struct dtrace_input_struct *) ivar)->ic;
};
BEGIN
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 a7378980bc56..2cbad3442efb 100644
--- a/cddl/contrib/opensolaris/cmd/lockstat/lockstat.c
+++ b/cddl/contrib/opensolaris/cmd/lockstat/lockstat.c
@@ -606,14 +606,14 @@ predicate_add(char **pred, char *what, char *cmp, uintptr_t value)
if (*pred[0] != '\0') {
if (cmp != NULL) {
- (void) sprintf(new, "(%s) && (%s %s 0x%p)",
+ (void) sprintf(new, "(%s) && (%s %s %p)",
*pred, what, cmp, (void *)value);
} else {
(void) sprintf(new, "(%s) && (%s)", *pred, what);
}
} else {
if (cmp != NULL) {
- (void) sprintf(new, "%s %s 0x%p",
+ (void) sprintf(new, "%s %s %p",
what, cmp, (void *)value);
} else {
(void) sprintf(new, "%s", what);
@@ -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/common/ctf/ctf_create.c b/cddl/contrib/opensolaris/common/ctf/ctf_create.c
index 3a080e71baa0..154cefb775ba 100644
--- a/cddl/contrib/opensolaris/common/ctf/ctf_create.c
+++ b/cddl/contrib/opensolaris/common/ctf/ctf_create.c
@@ -87,48 +87,85 @@ ctf_create(int *errp)
}
static uchar_t *
-ctf_copy_smembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t)
+ctf_copy_smembers(const ctf_file_t *fp, ctf_dtdef_t *dtd, uint_t soff,
+ uchar_t *t)
{
ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
- ctf_member_t ctm;
+ size_t sz;
+ uint_t name;
for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
if (dmd->dmd_name) {
- ctm.ctm_name = soff;
+ name = soff;
soff += strlen(dmd->dmd_name) + 1;
} else
- ctm.ctm_name = 0;
+ name = 0;
- ctm.ctm_type = (ushort_t)dmd->dmd_type;
- ctm.ctm_offset = (ushort_t)dmd->dmd_offset;
+ if (fp->ctf_version == CTF_VERSION_2) {
+ struct ctf_member_v2 ctm;
- bcopy(&ctm, t, sizeof (ctm));
- t += sizeof (ctm);
+ ctm.ctm_name = name;
+ ctm.ctm_type = (ushort_t)dmd->dmd_type;
+ ctm.ctm_offset = (ushort_t)dmd->dmd_offset;
+
+ sz = sizeof (ctm);
+ bcopy(&ctm, t, sz);
+ t += sz;
+ } else {
+ struct ctf_member_v3 ctm;
+
+ ctm.ctm_name = name;
+ ctm.ctm_type = dmd->dmd_type;
+ ctm.ctm_offset = dmd->dmd_offset;
+
+ sz = sizeof (ctm);
+ bcopy(&ctm, t, sz);
+ t += sz;
+ }
}
return (t);
}
static uchar_t *
-ctf_copy_lmembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t)
+ctf_copy_lmembers(const ctf_file_t *fp, ctf_dtdef_t *dtd, uint_t soff,
+ uchar_t *t)
{
ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
- ctf_lmember_t ctlm;
+ size_t sz;
+ uint_t name;
for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
if (dmd->dmd_name) {
- ctlm.ctlm_name = soff;
+ name = soff;
soff += strlen(dmd->dmd_name) + 1;
} else
- ctlm.ctlm_name = 0;
+ name = 0;
+
+ if (fp->ctf_version == CTF_VERSION_2) {
+ struct ctf_lmember_v2 ctlm;
- ctlm.ctlm_type = (ushort_t)dmd->dmd_type;
- ctlm.ctlm_pad = 0;
- ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI(dmd->dmd_offset);
- ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO(dmd->dmd_offset);
+ ctlm.ctlm_name = name;
+ ctlm.ctlm_type = (ushort_t)dmd->dmd_type;
+ ctlm.ctlm_pad = 0;
+ ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI(dmd->dmd_offset);
+ ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO(dmd->dmd_offset);
- bcopy(&ctlm, t, sizeof (ctlm));
- t += sizeof (ctlm);
+ sz = sizeof (ctlm);
+ bcopy(&ctlm, t, sz);
+ t += sz;
+ } else {
+ struct ctf_lmember_v3 ctlm;
+
+ ctlm.ctlm_name = name;
+ ctlm.ctlm_type = dmd->dmd_type;
+ ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI(dmd->dmd_offset);
+ ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO(dmd->dmd_offset);
+
+ sz = sizeof (ctlm);
+ bcopy(&ctlm, t, sz);
+ t += sz;
+ }
}
return (t);
@@ -259,7 +296,7 @@ ctf_update(ctf_file_t *fp)
*/
bzero(&hdr, sizeof (hdr));
hdr.cth_magic = CTF_MAGIC;
- hdr.cth_version = CTF_VERSION;
+ hdr.cth_version = fp->ctf_version;
if (fp->ctf_flags & LCTF_CHILD)
hdr.cth_parname = 1; /* i.e. _CTF_STRTAB_TEMPLATE[1] */
@@ -271,13 +308,20 @@ ctf_update(ctf_file_t *fp)
for (size = 0, dtd = ctf_list_next(&fp->ctf_dtdefs);
dtd != NULL; dtd = ctf_list_next(dtd)) {
- uint_t kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
- uint_t vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
+ uint_t kind = LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info);
+ uint_t vlen = LCTF_INFO_VLEN(fp, dtd->dtd_data.ctt_info);
- if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
- size += sizeof (ctf_stype_t);
- else
- size += sizeof (ctf_type_t);
+ if (fp->ctf_version == CTF_VERSION_2) {
+ if (dtd->dtd_data.ctt_size != CTF_V2_LSIZE_SENT)
+ size += sizeof (struct ctf_stype_v2);
+ else
+ size += sizeof (struct ctf_type_v2);
+ } else {
+ if (dtd->dtd_data.ctt_size != LCTF_LSIZE_SENT(fp))
+ size += sizeof (struct ctf_stype_v3);
+ else
+ size += sizeof (struct ctf_type_v3);
+ }
switch (kind) {
case CTF_K_INTEGER:
@@ -285,17 +329,32 @@ ctf_update(ctf_file_t *fp)
size += sizeof (uint_t);
break;
case CTF_K_ARRAY:
- size += sizeof (ctf_array_t);
+ size += fp->ctf_version == CTF_VERSION_2 ?
+ sizeof (struct ctf_array_v2) :
+ sizeof (struct ctf_array_v3);
break;
case CTF_K_FUNCTION:
- size += sizeof (ushort_t) * (vlen + (vlen & 1));
+ size += roundup2(fp->ctf_idwidth * vlen, 4);
break;
case CTF_K_STRUCT:
case CTF_K_UNION:
- if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
- size += sizeof (ctf_member_t) * vlen;
- else
- size += sizeof (ctf_lmember_t) * vlen;
+ if (fp->ctf_version == CTF_VERSION_2) {
+ if (dtd->dtd_data.ctt_size <
+ LCTF_LSTRUCT_THRESH(fp))
+ size += sizeof (struct ctf_member_v2) *
+ vlen;
+ else
+ size += sizeof (struct ctf_lmember_v2) *
+ vlen;
+ } else {
+ if (dtd->dtd_data.ctt_size <
+ LCTF_LSTRUCT_THRESH(fp))
+ size += sizeof (struct ctf_member_v3) *
+ vlen;
+ else
+ size += sizeof (struct ctf_lmember_v3) *
+ vlen;
+ }
break;
case CTF_K_ENUM:
size += sizeof (ctf_enum_t) * vlen;
@@ -328,11 +387,11 @@ ctf_update(ctf_file_t *fp)
*/
for (dtd = ctf_list_next(&fp->ctf_dtdefs);
dtd != NULL; dtd = ctf_list_next(dtd)) {
+ void *tp;
+ uint_t kind = LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info);
+ uint_t vlen = LCTF_INFO_VLEN(fp, dtd->dtd_data.ctt_info);
+ struct ctf_type_v2 ctt;
- uint_t kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
- uint_t vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
-
- ctf_array_t cta;
uint_t encoding;
size_t len;
@@ -344,12 +403,27 @@ ctf_update(ctf_file_t *fp)
} else
dtd->dtd_data.ctt_name = 0;
- if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
- len = sizeof (ctf_stype_t);
- else
- len = sizeof (ctf_type_t);
+ if (fp->ctf_version == CTF_VERSION_2) {
+ ctt.ctt_name = dtd->dtd_data.ctt_name;
+ ctt.ctt_info = (ushort_t)dtd->dtd_data.ctt_info;
+ ctt.ctt_size = (ushort_t)dtd->dtd_data.ctt_size;
+ if (dtd->dtd_data.ctt_size != CTF_V2_LSIZE_SENT)
+ len = sizeof (struct ctf_stype_v2);
+ else {
+ len = sizeof (struct ctf_type_v2);
+ ctt.ctt_lsizehi = dtd->dtd_data.ctt_lsizehi;
+ ctt.ctt_lsizelo = dtd->dtd_data.ctt_lsizelo;
+ }
+ tp = &ctt;
+ } else {
+ if (dtd->dtd_data.ctt_size != LCTF_LSIZE_SENT(fp))
+ len = sizeof (struct ctf_stype_v3);
+ else
+ len = sizeof (struct ctf_type_v3);
+ tp = &dtd->dtd_data;
+ }
- bcopy(&dtd->dtd_data, t, len);
+ bcopy(tp, t, len);
t += len;
switch (kind) {
@@ -371,24 +445,52 @@ ctf_update(ctf_file_t *fp)
break;
case CTF_K_ARRAY:
- cta.cta_contents = (ushort_t)
- dtd->dtd_u.dtu_arr.ctr_contents;
- cta.cta_index = (ushort_t)
- dtd->dtd_u.dtu_arr.ctr_index;
- cta.cta_nelems = dtd->dtd_u.dtu_arr.ctr_nelems;
- bcopy(&cta, t, sizeof (cta));
- t += sizeof (cta);
+ if (fp->ctf_version == CTF_VERSION_2) {
+ struct ctf_array_v2 cta;
+
+ cta.cta_contents =
+ (uint16_t)dtd->dtd_u.dtu_arr.ctr_contents;
+ cta.cta_index =
+ (uint16_t)dtd->dtd_u.dtu_arr.ctr_index;
+ cta.cta_nelems = dtd->dtd_u.dtu_arr.ctr_nelems;
+
+ bcopy(&cta, t, sizeof (cta));
+ t += sizeof (cta);
+ } else {
+ struct ctf_array_v3 cta;
+
+ cta.cta_contents =
+ dtd->dtd_u.dtu_arr.ctr_contents;
+ cta.cta_index = dtd->dtd_u.dtu_arr.ctr_index;
+ cta.cta_nelems = dtd->dtd_u.dtu_arr.ctr_nelems;
+
+ bcopy(&cta, t, sizeof (cta));
+ t += sizeof (cta);
+ }
break;
case CTF_K_FUNCTION: {
- ushort_t *argv = (ushort_t *)(uintptr_t)t;
+ char *argv = (char *)(uintptr_t)t;
uint_t argc;
- for (argc = 0; argc < vlen; argc++)
- *argv++ = (ushort_t)dtd->dtd_u.dtu_argv[argc];
+ if (fp->ctf_version == CTF_VERSION_2) {
+ ushort_t arg;
- if (vlen & 1)
- *argv++ = 0; /* pad to 4-byte boundary */
+ for (argc = 0; argc < vlen;
+ argc++, argv += sizeof(arg)) {
+ arg =
+ (ushort_t)dtd->dtd_u.dtu_argv[argc];
+ memcpy(argv, &arg, sizeof(arg));
+ }
+ } else {
+ uint_t arg;
+
+ for (argc = 0; argc < vlen;
+ argc++, argv += sizeof(arg)) {
+ arg = (uint_t)dtd->dtd_u.dtu_argv[argc];
+ memcpy(argv, &arg, sizeof(arg));
+ }
+ }
t = (uchar_t *)argv;
break;
@@ -396,10 +498,12 @@ ctf_update(ctf_file_t *fp)
case CTF_K_STRUCT:
case CTF_K_UNION:
- if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
- t = ctf_copy_smembers(dtd, (uint_t)(s - s0), t);
+ if (dtd->dtd_data.ctt_size < LCTF_LSTRUCT_THRESH(fp))
+ t = ctf_copy_smembers(fp, dtd, (uint_t)(s - s0),
+ t);
else
- t = ctf_copy_lmembers(dtd, (uint_t)(s - s0), t);
+ t = ctf_copy_lmembers(fp, dtd, (uint_t)(s - s0),
+ t);
s = ctf_copy_membnames(dtd, s);
break;
@@ -495,7 +599,7 @@ ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef_t *dtd)
if (p != NULL)
*q = p->dtd_hash;
- kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
+ kind = LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info);
switch (kind) {
case CTF_K_STRUCT:
case CTF_K_UNION:
@@ -515,11 +619,11 @@ ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef_t *dtd)
break;
case CTF_K_FUNCTION:
ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
- for (i = 0; i < CTF_INFO_VLEN(dtd->dtd_data.ctt_info); i++)
+ for (i = 0; i < LCTF_INFO_VLEN(fp, dtd->dtd_data.ctt_info); i++)
if (dtd->dtd_u.dtu_argv[i] != 0)
ctf_ref_dec(fp, dtd->dtd_u.dtu_argv[i]);
ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) *
- CTF_INFO_VLEN(dtd->dtd_data.ctt_info));
+ LCTF_INFO_VLEN(fp, dtd->dtd_data.ctt_info));
break;
case CTF_K_ARRAY:
ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_contents);
@@ -584,7 +688,7 @@ ctf_discard(ctf_file_t *fp)
for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
ntd = ctf_list_prev(dtd);
- if (CTF_TYPE_TO_INDEX(dtd->dtd_type) <= fp->ctf_dtoldid)
+ if (LCTF_TYPE_TO_INDEX(fp, dtd->dtd_type) <= fp->ctf_dtoldid)
continue; /* skip types that have been committed */
ctf_dtd_delete(fp, dtd);
@@ -609,7 +713,7 @@ ctf_add_generic(ctf_file_t *fp, uint_t flag, const char *name, ctf_dtdef_t **rp)
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno(fp, ECTF_RDONLY));
- if (CTF_INDEX_TO_TYPE(fp->ctf_dtnextid, 1) > CTF_MAX_TYPE)
+ if (LCTF_INDEX_TO_TYPE(fp, fp->ctf_dtnextid, 1) > LCTF_MAX_TYPE(fp))
return (ctf_set_errno(fp, ECTF_FULL));
if ((dtd = ctf_alloc(sizeof (ctf_dtdef_t))) == NULL)
@@ -621,7 +725,7 @@ ctf_add_generic(ctf_file_t *fp, uint_t flag, const char *name, ctf_dtdef_t **rp)
}
type = fp->ctf_dtnextid++;
- type = CTF_INDEX_TO_TYPE(type, (fp->ctf_flags & LCTF_CHILD));
+ type = LCTF_INDEX_TO_TYPE(fp, type, (fp->ctf_flags & LCTF_CHILD));
bzero(dtd, sizeof (ctf_dtdef_t));
dtd->dtd_name = s;
@@ -669,7 +773,7 @@ ctf_add_encoded(ctf_file_t *fp, uint_t flag,
if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
return (CTF_ERR); /* errno is set for us */
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0);
+ dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, kind, flag, 0);
dtd->dtd_data.ctt_size = clp2(P2ROUNDUP(ep->cte_bits, NBBY) / NBBY);
dtd->dtd_u.dtu_enc = *ep;
@@ -682,7 +786,7 @@ ctf_add_reftype(ctf_file_t *fp, uint_t flag, ctf_id_t ref, uint_t kind)
ctf_dtdef_t *dtd;
ctf_id_t type;
- if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
+ if (ref == CTF_ERR || ref > LCTF_MAX_TYPE(fp))
return (ctf_set_errno(fp, EINVAL));
if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
@@ -690,8 +794,8 @@ ctf_add_reftype(ctf_file_t *fp, uint_t flag, ctf_id_t ref, uint_t kind)
ctf_ref_inc(fp, ref);
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0);
- dtd->dtd_data.ctt_type = (ushort_t)ref;
+ dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, kind, flag, 0);
+ dtd->dtd_data.ctt_type = (uint_t)ref;
return (type);
}
@@ -739,7 +843,7 @@ ctf_add_array(ctf_file_t *fp, uint_t flag, const ctf_arinfo_t *arp)
if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
return (CTF_ERR); /* errno is set for us */
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, flag, 0);
+ dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_ARRAY, flag, 0);
dtd->dtd_data.ctt_size = 0;
dtd->dtd_u.dtu_arr = *arp;
ctf_ref_inc(fp, arp->ctr_contents);
@@ -757,7 +861,8 @@ ctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
if (!(fp->ctf_flags & LCTF_RDWR))
return (ctf_set_errno(fp, ECTF_RDONLY));
- if (dtd == NULL || CTF_INFO_KIND(dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
+ if (dtd == NULL ||
+ LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
return (ctf_set_errno(fp, ECTF_BADID));
fpd = fp;
@@ -799,7 +904,7 @@ ctf_add_function(ctf_file_t *fp, uint_t flag,
if (ctc->ctc_flags & CTF_FUNC_VARARG)
vlen++; /* add trailing zero to indicate varargs (see below) */
- if (vlen > CTF_MAX_VLEN)
+ if (vlen > LCTF_MAX_VLEN(fp))
return (ctf_set_errno(fp, EOVERFLOW));
fpd = fp;
@@ -822,8 +927,8 @@ ctf_add_function(ctf_file_t *fp, uint_t flag,
return (CTF_ERR); /* errno is set for us */
}
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, flag, vlen);
- dtd->dtd_data.ctt_type = (ushort_t)ctc->ctc_return;
+ dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_FUNCTION, flag, vlen);
+ dtd->dtd_data.ctt_type = ctc->ctc_return;
ctf_ref_inc(fp, ctc->ctc_return);
for (i = 0; i < ctc->ctc_argc; i++)
@@ -853,7 +958,7 @@ ctf_add_struct(ctf_file_t *fp, uint_t flag, const char *name)
else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
return (CTF_ERR); /* errno is set for us */
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, flag, 0);
+ dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_STRUCT, flag, 0);
dtd->dtd_data.ctt_size = 0;
return (type);
@@ -875,7 +980,7 @@ ctf_add_union(ctf_file_t *fp, uint_t flag, const char *name)
else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
return (CTF_ERR); /* errno is set for us */
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, flag, 0);
+ dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_UNION, flag, 0);
dtd->dtd_data.ctt_size = 0;
return (type);
@@ -897,7 +1002,7 @@ ctf_add_enum(ctf_file_t *fp, uint_t flag, const char *name)
else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
return (CTF_ERR); /* errno is set for us */
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, flag, 0);
+ dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_ENUM, flag, 0);
dtd->dtd_data.ctt_size = fp->ctf_dmodel->ctd_int;
return (type);
@@ -936,7 +1041,7 @@ ctf_add_forward(ctf_file_t *fp, uint_t flag, const char *name, uint_t kind)
if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
return (CTF_ERR); /* errno is set for us */
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FORWARD, flag, 0);
+ dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_FORWARD, flag, 0);
dtd->dtd_data.ctt_type = kind;
return (type);
@@ -957,8 +1062,8 @@ ctf_add_typedef(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref)
if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
return (CTF_ERR); /* errno is set for us */
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, flag, 0);
- dtd->dtd_data.ctt_type = (ushort_t)ref;
+ dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_TYPEDEF, flag, 0);
+ dtd->dtd_data.ctt_type = ref;
ctf_ref_inc(fp, ref);
return (type);
@@ -1000,14 +1105,14 @@ ctf_add_enumerator(ctf_file_t *fp, ctf_id_t enid, const char *name, int value)
if (dtd == NULL)
return (ctf_set_errno(fp, ECTF_BADID));
- kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
- root = CTF_INFO_ISROOT(dtd->dtd_data.ctt_info);
- vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
+ kind = LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info);
+ root = LCTF_INFO_ROOT(fp, dtd->dtd_data.ctt_info);
+ vlen = LCTF_INFO_VLEN(fp, dtd->dtd_data.ctt_info);
if (kind != CTF_K_ENUM)
return (ctf_set_errno(fp, ECTF_NOTENUM));
- if (vlen == CTF_MAX_VLEN)
+ if (vlen > LCTF_MAX_VLEN(fp))
return (ctf_set_errno(fp, ECTF_DTFULL));
for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
@@ -1029,7 +1134,7 @@ ctf_add_enumerator(ctf_file_t *fp, ctf_id_t enid, const char *name, int value)
dmd->dmd_offset = 0;
dmd->dmd_value = value;
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1);
+ dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, kind, root, vlen + 1);
ctf_list_append(&dtd->dtd_u.dtu_members, dmd);
fp->ctf_dtstrlen += strlen(s) + 1;
@@ -1054,14 +1159,14 @@ ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type)
if (dtd == NULL)
return (ctf_set_errno(fp, ECTF_BADID));
- kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
- root = CTF_INFO_ISROOT(dtd->dtd_data.ctt_info);
- vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
+ kind = LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info);
+ root = LCTF_INFO_ROOT(fp, dtd->dtd_data.ctt_info);
+ vlen = LCTF_INFO_VLEN(fp, dtd->dtd_data.ctt_info);
if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
return (ctf_set_errno(fp, ECTF_NOTSOU));
- if (vlen == CTF_MAX_VLEN)
+ if (vlen > LCTF_MAX_VLEN(fp))
return (ctf_set_errno(fp, ECTF_DTFULL));
if (name != NULL) {
@@ -1121,14 +1226,14 @@ ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type)
ssize = MAX(ssize, msize);
}
- if (ssize > CTF_MAX_SIZE) {
- dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
+ if (ssize > LCTF_MAX_SIZE(fp)) {
+ dtd->dtd_data.ctt_size = LCTF_LSIZE_SENT(fp);
dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(ssize);
dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(ssize);
} else
- dtd->dtd_data.ctt_size = (ushort_t)ssize;
+ dtd->dtd_data.ctt_size = ssize;
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1);
+ dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, kind, root, vlen + 1);
ctf_list_append(&dtd->dtd_u.dtu_members, dmd);
if (s != NULL)
@@ -1233,10 +1338,10 @@ static long
soucmp(ctf_file_t *src_fp, ctf_id_t src_type, ctf_file_t *dst_fp,
ctf_id_t dst_type)
{
- const struct ctf_type *src_tp, *dst_tp;
+ const void *src_tp, *dst_tp;
const char *src_name, *dst_name;
ssize_t src_sz, dst_sz, src_inc, dst_inc;
- uint_t kind, n;
+ uint_t dst_kind, dst_vlen, src_kind, src_vlen, n;
if ((src_type = ctf_type_resolve(src_fp, src_type)) == CTF_ERR)
return (CTF_ERR);
@@ -1248,47 +1353,37 @@ soucmp(ctf_file_t *src_fp, ctf_id_t src_type, ctf_file_t *dst_fp,
if ((dst_tp = ctf_lookup_by_id(&dst_fp, dst_type)) == NULL)
return (CTF_ERR);
- if ((kind = LCTF_INFO_KIND(src_fp, src_tp->ctt_info)) !=
- LCTF_INFO_KIND(dst_fp, dst_tp->ctt_info))
+ ctf_get_ctt_info(src_fp, src_tp, &src_kind, &src_vlen, NULL);
+ ctf_get_ctt_info(dst_fp, dst_tp, &dst_kind, &dst_vlen, NULL);
+
+ if (src_kind != dst_kind)
return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
- if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
+ if (src_kind != CTF_K_STRUCT && src_kind != CTF_K_UNION)
return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
- if ((n = LCTF_INFO_VLEN(src_fp, src_tp->ctt_info)) !=
- LCTF_INFO_VLEN(dst_fp, dst_tp->ctt_info))
+ if (src_vlen != dst_vlen)
return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
(void) ctf_get_ctt_size(src_fp, src_tp, &src_sz, &src_inc);
(void) ctf_get_ctt_size(dst_fp, dst_tp, &dst_sz, &dst_inc);
- if (src_sz != dst_sz || src_inc != dst_inc)
+ if (src_sz != dst_sz)
return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
- if (src_sz < CTF_LSTRUCT_THRESH) {
- const ctf_member_t *src_mp, *dst_mp;
+ const char *src_mp, *dst_mp;
+ ulong_t src_offset, dst_offset;
- src_mp = (const ctf_member_t *)((uintptr_t)src_tp + src_inc);
- dst_mp = (const ctf_member_t *)((uintptr_t)dst_tp + dst_inc);
- for (; n != 0; n--, src_mp++, dst_mp++) {
- if (src_mp->ctm_offset != dst_mp->ctm_offset)
- return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
- src_name = ctf_strptr(src_fp, src_mp->ctm_name);
- dst_name = ctf_strptr(dst_fp, dst_mp->ctm_name);
- if (strcmp(src_name, dst_name) != 0)
- return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
- }
- } else {
- const ctf_lmember_t *src_mp, *dst_mp;
+ src_mp = (const char *)src_tp + src_inc;
+ dst_mp = (const char *)dst_tp + dst_inc;
+ for (n = src_vlen; n != 0;
+ n--, src_mp += src_inc, dst_mp += dst_inc) {
+ ctf_get_ctm_info(src_fp, src_mp, src_sz, &src_inc, NULL,
+ &src_offset, &src_name);
+ ctf_get_ctm_info(dst_fp, dst_mp, dst_sz, &dst_inc, NULL,
+ &dst_offset, &dst_name);
- src_mp = (const ctf_lmember_t *)((uintptr_t)src_tp + src_inc);
- dst_mp = (const ctf_lmember_t *)((uintptr_t)dst_tp + dst_inc);
- for (; n != 0; n--, src_mp++, dst_mp++) {
- if (src_mp->ctlm_offsethi != dst_mp->ctlm_offsethi ||
- src_mp->ctlm_offsetlo != dst_mp->ctlm_offsetlo)
- return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
- src_name = ctf_strptr(src_fp, src_mp->ctlm_name);
- dst_name = ctf_strptr(dst_fp, dst_mp->ctlm_name);
- if (strcmp(src_name, dst_name) != 0)
- return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
- }
+ if (src_offset != dst_offset)
+ return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
+ if (strcmp(src_name, dst_name) != 0)
+ return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
}
return (0);
@@ -1307,9 +1402,9 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
ctf_id_t dst_type = CTF_ERR;
uint_t dst_kind = CTF_K_UNKNOWN;
- const ctf_type_t *tp;
+ const void *tp;
const char *name;
- uint_t kind, flag, vlen;
+ uint_t type, kind, flag, vlen;
ctf_bundle_t src, dst;
ctf_encoding_t src_en, main_en, dst_en;
@@ -1331,10 +1426,9 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
if ((tp = ctf_lookup_by_id(&src_fp, src_type)) == NULL)
return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));
- name = ctf_strptr(src_fp, tp->ctt_name);
- kind = LCTF_INFO_KIND(src_fp, tp->ctt_info);
- flag = LCTF_INFO_ROOT(src_fp, tp->ctt_info);
- vlen = LCTF_INFO_VLEN(src_fp, tp->ctt_info);
+ name = ctf_type_rname(src_fp, tp);
+
+ ctf_get_ctt_info(src_fp, tp, &kind, &vlen, &flag);
switch (kind) {
case CTF_K_STRUCT:
@@ -1389,10 +1483,10 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
*/
if (dst_type == CTF_ERR && name[0] != '\0') {
for (dtd = ctf_list_prev(&dst_fp->ctf_dtdefs); dtd != NULL &&
- CTF_TYPE_TO_INDEX(dtd->dtd_type) > dst_fp->ctf_dtoldid;
- dtd = ctf_list_prev(dtd)) {
- if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) != kind ||
- dtd->dtd_name == NULL ||
+ LCTF_TYPE_TO_INDEX(dst_fp, dtd->dtd_type) >
+ dst_fp->ctf_dtoldid; dtd = ctf_list_prev(dtd)) {
+ if (LCTF_INFO_KIND(dst_fp, dtd->dtd_data.ctt_info) !=
+ kind || dtd->dtd_name == NULL ||
strcmp(dtd->dtd_name, name) != 0)
continue;
if (kind == CTF_K_INTEGER || kind == CTF_K_FLOAT) {
@@ -1499,7 +1593,8 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
break;
case CTF_K_FUNCTION:
- ctc.ctc_return = ctf_add_type(dst_fp, src_fp, tp->ctt_type);
+ ctf_get_ctt_index(src_fp, tp, NULL, &type, NULL);
+ ctc.ctc_return = ctf_add_type(dst_fp, src_fp, type);
ctc.ctc_argc = 0;
ctc.ctc_flags = 0;
@@ -1541,14 +1636,16 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
if (ctf_member_iter(src_fp, src_type, membadd, &dst) != 0)
errs++; /* increment errs and fail at bottom of case */
- if ((size = ctf_type_size(src_fp, src_type)) > CTF_MAX_SIZE) {
- dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
+ if ((size = ctf_type_size(src_fp, src_type)) >
+ LCTF_MAX_SIZE(src_fp)) {
+ dtd->dtd_data.ctt_size = LCTF_LSIZE_SENT(dst_fp);
dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);
dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);
} else
- dtd->dtd_data.ctt_size = (ushort_t)size;
+ dtd->dtd_data.ctt_size = size;
- dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, vlen);
+ dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(dst_fp, kind, flag,
+ vlen);
/*
* Make a final pass through the members changing each dmd_type
diff --git a/cddl/contrib/opensolaris/common/ctf/ctf_decl.c b/cddl/contrib/opensolaris/common/ctf/ctf_decl.c
index 6bf57001570f..63d173c15f5f 100644
--- a/cddl/contrib/opensolaris/common/ctf/ctf_decl.c
+++ b/cddl/contrib/opensolaris/common/ctf/ctf_decl.c
@@ -88,10 +88,10 @@ ctf_decl_push(ctf_decl_t *cd, ctf_file_t *fp, ctf_id_t type)
{
ctf_decl_node_t *cdp;
ctf_decl_prec_t prec;
- uint_t kind, n = 1;
+ uint_t ctype, kind, n = 1;
int is_qual = 0;
- const ctf_type_t *tp;
+ const void *tp;
ctf_arinfo_t ar;
if ((tp = ctf_lookup_by_id(&fp, type)) == NULL) {
@@ -99,7 +99,10 @@ ctf_decl_push(ctf_decl_t *cd, ctf_file_t *fp, ctf_id_t type)
return;
}
- switch (kind = LCTF_INFO_KIND(fp, tp->ctt_info)) {
+ ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
+ ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
+
+ switch (kind) {
case CTF_K_ARRAY:
(void) ctf_array_info(fp, type, &ar);
ctf_decl_push(cd, fp, ar.ctr_contents);
@@ -108,27 +111,27 @@ ctf_decl_push(ctf_decl_t *cd, ctf_file_t *fp, ctf_id_t type)
break;
case CTF_K_TYPEDEF:
- if (ctf_strptr(fp, tp->ctt_name)[0] == '\0') {
- ctf_decl_push(cd, fp, tp->ctt_type);
+ if (ctf_type_rname(fp, tp)[0] == '\0') {
+ ctf_decl_push(cd, fp, ctype);
return;
}
prec = CTF_PREC_BASE;
break;
case CTF_K_FUNCTION:
- ctf_decl_push(cd, fp, tp->ctt_type);
+ ctf_decl_push(cd, fp, ctype);
prec = CTF_PREC_FUNCTION;
break;
case CTF_K_POINTER:
- ctf_decl_push(cd, fp, tp->ctt_type);
+ ctf_decl_push(cd, fp, ctype);
prec = CTF_PREC_POINTER;
break;
case CTF_K_VOLATILE:
case CTF_K_CONST:
case CTF_K_RESTRICT:
- ctf_decl_push(cd, fp, tp->ctt_type);
+ ctf_decl_push(cd, fp, ctype);
prec = cd->cd_qualp;
is_qual++;
break;
diff --git a/cddl/contrib/opensolaris/common/ctf/ctf_hash.c b/cddl/contrib/opensolaris/common/ctf/ctf_hash.c
index b10a7618f66e..5a36fbbd88cf 100644
--- a/cddl/contrib/opensolaris/common/ctf/ctf_hash.c
+++ b/cddl/contrib/opensolaris/common/ctf/ctf_hash.c
@@ -29,7 +29,7 @@
#include <ctf_impl.h>
-static const ushort_t _CTF_EMPTY[1] = { 0 };
+static const uint_t _CTF_EMPTY[1] = { 0 };
int
ctf_hash_create(ctf_hash_t *hp, ulong_t nelems)
@@ -43,7 +43,7 @@ ctf_hash_create(ctf_hash_t *hp, ulong_t nelems)
*/
if (nelems == 0) {
bzero(hp, sizeof (ctf_hash_t));
- hp->h_buckets = (ushort_t *)_CTF_EMPTY;
+ hp->h_buckets = (uint_t *)_CTF_EMPTY;
hp->h_nbuckets = 1;
return (0);
}
@@ -52,7 +52,7 @@ ctf_hash_create(ctf_hash_t *hp, ulong_t nelems)
hp->h_nelems = nelems + 1; /* we use index zero as a sentinel */
hp->h_free = 1; /* first free element is index 1 */
- hp->h_buckets = ctf_alloc(sizeof (ushort_t) * hp->h_nbuckets);
+ hp->h_buckets = ctf_alloc(sizeof (uint_t) * hp->h_nbuckets);
hp->h_chains = ctf_alloc(sizeof (ctf_helem_t) * hp->h_nelems);
if (hp->h_buckets == NULL || hp->h_chains == NULL) {
@@ -60,7 +60,7 @@ ctf_hash_create(ctf_hash_t *hp, ulong_t nelems)
return (EAGAIN);
}
- bzero(hp->h_buckets, sizeof (ushort_t) * hp->h_nbuckets);
+ bzero(hp->h_buckets, sizeof (uint_t) * hp->h_nbuckets);
bzero(hp->h_chains, sizeof (ctf_helem_t) * hp->h_nelems);
return (0);
@@ -92,7 +92,7 @@ ctf_hash_compute(const char *key, size_t len)
}
int
-ctf_hash_insert(ctf_hash_t *hp, ctf_file_t *fp, ushort_t type, uint_t name)
+ctf_hash_insert(ctf_hash_t *hp, ctf_file_t *fp, uint_t type, uint_t name)
{
ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID(name)];
const char *str = ctsp->cts_strs + CTF_NAME_OFFSET(name);
@@ -129,7 +129,7 @@ ctf_hash_insert(ctf_hash_t *hp, ctf_file_t *fp, ushort_t type, uint_t name)
* If the key is not present, then call ctf_hash_insert() and hash it in.
*/
int
-ctf_hash_define(ctf_hash_t *hp, ctf_file_t *fp, ushort_t type, uint_t name)
+ctf_hash_define(ctf_hash_t *hp, ctf_file_t *fp, uint_t type, uint_t name)
{
const char *str = ctf_strptr(fp, name);
ctf_helem_t *hep = ctf_hash_lookup(hp, fp, str, strlen(str));
@@ -147,7 +147,7 @@ ctf_hash_lookup(ctf_hash_t *hp, ctf_file_t *fp, const char *key, size_t len)
ctf_helem_t *hep;
ctf_strs_t *ctsp;
const char *str;
- ushort_t i;
+ uint_t i;
ulong_t h = ctf_hash_compute(key, len) % hp->h_nbuckets;
@@ -167,7 +167,7 @@ void
ctf_hash_destroy(ctf_hash_t *hp)
{
if (hp->h_buckets != NULL && hp->h_nbuckets != 1) {
- ctf_free(hp->h_buckets, sizeof (ushort_t) * hp->h_nbuckets);
+ ctf_free(hp->h_buckets, sizeof (uint_t) * hp->h_nbuckets);
hp->h_buckets = NULL;
}
diff --git a/cddl/contrib/opensolaris/common/ctf/ctf_impl.h b/cddl/contrib/opensolaris/common/ctf/ctf_impl.h
index f56fa6a00548..774eff1380fa 100644
--- a/cddl/contrib/opensolaris/common/ctf/ctf_impl.h
+++ b/cddl/contrib/opensolaris/common/ctf/ctf_impl.h
@@ -65,15 +65,15 @@ extern "C" {
typedef struct ctf_helem {
uint_t h_name; /* reference to name in string table */
- ushort_t h_type; /* corresponding type ID number */
- ushort_t h_next; /* index of next element in hash chain */
+ uint_t h_type; /* corresponding type ID number */
+ uint_t h_next; /* index of next element in hash chain */
} ctf_helem_t;
typedef struct ctf_hash {
- ushort_t *h_buckets; /* hash bucket array (chain indices) */
+ uint_t *h_buckets; /* hash bucket array (chain indices) */
ctf_helem_t *h_chains; /* hash chains buffer */
- ushort_t h_nbuckets; /* number of elements in bucket array */
- ushort_t h_nelems; /* number of elements in hash table */
+ uint_t h_nbuckets; /* number of elements in bucket array */
+ uint_t h_nelems; /* number of elements in hash table */
uint_t h_free; /* index of next free hash element */
} ctf_hash_t;
@@ -99,9 +99,20 @@ typedef struct ctf_lookup {
} ctf_lookup_t;
typedef struct ctf_fileops {
- ushort_t (*ctfo_get_kind)(ushort_t);
- ushort_t (*ctfo_get_root)(ushort_t);
- ushort_t (*ctfo_get_vlen)(ushort_t);
+ uint_t (*ctfo_get_kind)(uint_t);
+ uint_t (*ctfo_get_root)(uint_t);
+ uint_t (*ctfo_get_vlen)(uint_t);
+ uint_t (*ctfo_get_max_vlen)(void);
+ uint_t (*ctfo_get_max_size)(void);
+ uint_t (*ctfo_get_max_type)(void);
+ uint_t (*ctfo_get_lsize_sent)(void);
+ uint_t (*ctfo_get_lstruct_thresh)(void);
+
+ uint_t (*ctfo_type_info)(uint_t, uint_t, uint_t);
+ int (*ctfo_type_isparent)(uint_t);
+ int (*ctfo_type_ischild)(uint_t);
+ uint_t (*ctfo_type_to_index)(uint_t);
+ uint_t (*ctfo_index_to_type)(uint_t, uint_t);
} ctf_fileops_t;
typedef struct ctf_list {
@@ -149,7 +160,7 @@ typedef struct ctf_dtdef {
struct ctf_dtdef *dtd_hash; /* hash chain pointer for ctf_dthash */
char *dtd_name; /* name associated with definition (if any) */
ctf_id_t dtd_type; /* type identifier for this definition */
- ctf_type_t dtd_data; /* type node (see <sys/ctf.h>) */
+ struct ctf_type_v3 dtd_data; /* type node (see <sys/ctf.h>) */
int dtd_ref; /* recfount for dyanmic types */
union {
ctf_list_t dtu_members; /* struct, union, or enum */
@@ -194,7 +205,7 @@ struct ctf_file {
uint_t *ctf_sxlate; /* translation table for symtab entries */
ulong_t ctf_nsyms; /* number of entries in symtab xlate table */
uint_t *ctf_txlate; /* translation table for type IDs */
- ushort_t *ctf_ptrtab; /* translation table for pointer-to lookups */
+ uint_t *ctf_ptrtab; /* translation table for pointer-to lookups */
ulong_t ctf_typemax; /* maximum valid type ID number */
const ctf_dmodel_t *ctf_dmodel; /* data model pointer (see above) */
struct ctf_file *ctf_parent; /* parent CTF container (if any) */
@@ -204,6 +215,7 @@ struct ctf_file {
uint_t ctf_flags; /* libctf flags (see below) */
int ctf_errno; /* error code for most recent error */
int ctf_version; /* CTF data version */
+ size_t ctf_idwidth; /* Size, in bytes, of a type ID */
ctf_dtdef_t **ctf_dthash; /* hash of dynamic type definitions */
ulong_t ctf_dthashlen; /* size of dynamic type hash bucket array */
ctf_list_t ctf_dtdefs; /* list of dynamic type definitions */
@@ -214,11 +226,24 @@ struct ctf_file {
};
#define LCTF_INDEX_TO_TYPEPTR(fp, i) \
- ((ctf_type_t *)((uintptr_t)(fp)->ctf_buf + (fp)->ctf_txlate[(i)]))
+ ((void *)((uintptr_t)(fp)->ctf_buf + (fp)->ctf_txlate[(i)]))
#define LCTF_INFO_KIND(fp, info) ((fp)->ctf_fileops->ctfo_get_kind(info))
#define LCTF_INFO_ROOT(fp, info) ((fp)->ctf_fileops->ctfo_get_root(info))
#define LCTF_INFO_VLEN(fp, info) ((fp)->ctf_fileops->ctfo_get_vlen(info))
+#define LCTF_MAX_VLEN(fp) ((fp)->ctf_fileops->ctfo_get_max_vlen())
+#define LCTF_MAX_SIZE(fp) ((fp)->ctf_fileops->ctfo_get_max_size())
+#define LCTF_MAX_TYPE(fp) ((fp)->ctf_fileops->ctfo_get_max_type())
+#define LCTF_LSIZE_SENT(fp) \
+ ((fp)->ctf_fileops->ctfo_get_lsize_sent())
+#define LCTF_LSTRUCT_THRESH(fp) \
+ ((fp)->ctf_fileops->ctfo_get_lstruct_thresh())
+
+#define LCTF_TYPE_INFO(fp, k, r, l) ((fp)->ctf_fileops->ctfo_type_info(k, r, l))
+#define LCTF_TYPE_ISPARENT(fp, id) ((fp)->ctf_fileops->ctfo_type_isparent(id))
+#define LCTF_TYPE_ISCHILD(fp, id) ((fp)->ctf_fileops->ctfo_type_ischild(id))
+#define LCTF_TYPE_TO_INDEX(fp, t) ((fp)->ctf_fileops->ctfo_type_to_index(t))
+#define LCTF_INDEX_TO_TYPE(fp, id, c) ((fp)->ctf_fileops->ctfo_index_to_type(id, c))
#define LCTF_MMAP 0x0001 /* libctf should munmap buffers on close */
#define LCTF_CHILD 0x0002 /* CTF container is a child */
@@ -276,14 +301,22 @@ enum {
ECTF_NOTDYN /* type is not a dynamic type */
};
-extern ssize_t ctf_get_ctt_size(const ctf_file_t *, const ctf_type_t *,
- ssize_t *, ssize_t *);
+extern void ctf_get_ctt_index(const ctf_file_t *fp, const void *v,
+ uint_t *indexp, uint_t *typep, int *ischildp);
+extern ssize_t ctf_get_ctt_size(const ctf_file_t *, const void *v, ssize_t *,
+ ssize_t *);
+extern void ctf_get_ctt_info(const ctf_file_t *, const void *v, uint_t *kind,
+ uint_t *vlen, int *isroot);
-extern const ctf_type_t *ctf_lookup_by_id(ctf_file_t **, ctf_id_t);
+extern void ctf_get_ctm_info(const ctf_file_t *fp, const void *v, size_t sz,
+ size_t *incrementp, uint_t *typep, ulong_t *offsetp, const char **namep);
+
+extern const void *ctf_lookup_by_id(ctf_file_t **, ctf_id_t);
+extern const char *ctf_type_rname(ctf_file_t *, const void *);
extern int ctf_hash_create(ctf_hash_t *, ulong_t);
-extern int ctf_hash_insert(ctf_hash_t *, ctf_file_t *, ushort_t, uint_t);
-extern int ctf_hash_define(ctf_hash_t *, ctf_file_t *, ushort_t, uint_t);
+extern int ctf_hash_insert(ctf_hash_t *, ctf_file_t *, uint_t, uint_t);
+extern int ctf_hash_define(ctf_hash_t *, ctf_file_t *, uint_t, uint_t);
extern ctf_helem_t *ctf_hash_lookup(ctf_hash_t *, ctf_file_t *,
const char *, size_t);
extern uint_t ctf_hash_size(const ctf_hash_t *);
@@ -305,8 +338,8 @@ extern void ctf_decl_fini(ctf_decl_t *);
extern void ctf_decl_push(ctf_decl_t *, ctf_file_t *, ctf_id_t);
extern void ctf_decl_sprintf(ctf_decl_t *, const char *, ...);
-extern const char *ctf_strraw(ctf_file_t *, uint_t);
-extern const char *ctf_strptr(ctf_file_t *, uint_t);
+extern const char *ctf_strraw(const ctf_file_t *, uint_t);
+extern const char *ctf_strptr(const ctf_file_t *, uint_t);
extern ctf_file_t *ctf_set_open_errno(int *, int);
extern long ctf_set_errno(ctf_file_t *, int);
diff --git a/cddl/contrib/opensolaris/common/ctf/ctf_lookup.c b/cddl/contrib/opensolaris/common/ctf/ctf_lookup.c
index cd9c71436938..e822e22f634c 100644
--- a/cddl/contrib/opensolaris/common/ctf/ctf_lookup.c
+++ b/cddl/contrib/opensolaris/common/ctf/ctf_lookup.c
@@ -111,17 +111,17 @@ ctf_lookup_by_name(ctf_file_t *fp, const char *name)
* data includes "struct foo *" but not "foo_t *" and
* the user tries to access "foo_t *" in the debugger.
*/
- ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)];
+ ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX(fp, type)];
if (ntype == 0) {
ntype = ctf_type_resolve(fp, type);
if (ntype == CTF_ERR || (ntype = fp->ctf_ptrtab[
- CTF_TYPE_TO_INDEX(ntype)]) == 0) {
+ LCTF_TYPE_TO_INDEX(fp, ntype)]) == 0) {
(void) ctf_set_errno(fp, ECTF_NOTYPE);
goto err;
}
}
- type = CTF_INDEX_TO_TYPE(ntype,
+ type = LCTF_INDEX_TO_TYPE(fp, ntype,
(fp->ctf_flags & LCTF_CHILD));
q = p + 1;
@@ -203,7 +203,7 @@ ctf_lookup_by_symbol(ctf_file_t *fp, ulong_t symidx)
if (fp->ctf_sxlate[symidx] == -1u)
return (ctf_set_errno(fp, ECTF_NOTYPEDAT));
- type = *(ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[symidx]);
+ type = *(uint_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[symidx]);
if (type == 0)
return (ctf_set_errno(fp, ECTF_NOTYPEDAT));
@@ -215,18 +215,24 @@ ctf_lookup_by_symbol(ctf_file_t *fp, ulong_t symidx)
* given type ID. If the ID is invalid, the function returns NULL.
* This function is not exported outside of the library.
*/
-const ctf_type_t *
+const void *
ctf_lookup_by_id(ctf_file_t **fpp, ctf_id_t type)
{
ctf_file_t *fp = *fpp; /* caller passes in starting CTF container */
- if ((fp->ctf_flags & LCTF_CHILD) && CTF_TYPE_ISPARENT(type) &&
- (fp = fp->ctf_parent) == NULL) {
- (void) ctf_set_errno(*fpp, ECTF_NOPARENT);
- return (NULL);
+ if ((fp->ctf_flags & LCTF_CHILD) && LCTF_TYPE_ISPARENT(fp, type)) {
+ if (fp->ctf_parent == NULL) {
+ (void) ctf_set_errno(*fpp, ECTF_NOPARENT);
+ return (NULL);
+ }
+
+ /* The parent may be using a different CTF version. */
+ type = LCTF_TYPE_TO_INDEX(fp, type);
+ fp = fp->ctf_parent;
+ } else {
+ type = LCTF_TYPE_TO_INDEX(fp, type);
}
- type = CTF_TYPE_TO_INDEX(type);
if (type > 0 && type <= fp->ctf_typemax) {
*fpp = fp; /* function returns ending CTF container */
return (LCTF_INDEX_TO_TYPEPTR(fp, type));
@@ -244,8 +250,8 @@ int
ctf_func_info(ctf_file_t *fp, ulong_t symidx, ctf_funcinfo_t *fip)
{
const ctf_sect_t *sp = &fp->ctf_symtab;
- const ushort_t *dp;
- ushort_t info, kind, n;
+ const uint_t *dp;
+ uint_t info, kind, n;
if (sp->cts_data == NULL)
return (ctf_set_errno(fp, ECTF_NOSYMTAB));
@@ -266,7 +272,7 @@ ctf_func_info(ctf_file_t *fp, ulong_t symidx, ctf_funcinfo_t *fip)
if (fp->ctf_sxlate[symidx] == -1u)
return (ctf_set_errno(fp, ECTF_NOFUNCDAT));
- dp = (ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[symidx]);
+ dp = (uint_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[symidx]);
info = *dp++;
kind = LCTF_INFO_KIND(fp, info);
@@ -297,17 +303,17 @@ ctf_func_info(ctf_file_t *fp, ulong_t symidx, ctf_funcinfo_t *fip)
int
ctf_func_args(ctf_file_t *fp, ulong_t symidx, uint_t argc, ctf_id_t *argv)
{
- const ushort_t *dp;
+ const uint_t *dp;
ctf_funcinfo_t f;
if (ctf_func_info(fp, symidx, &f) == CTF_ERR)
return (CTF_ERR); /* errno is set for us */
/*
- * The argument data is two ushort_t's past the translation table
+ * The argument data is two uint_t's past the translation table
* offset: one for the function info, and one for the return type.
*/
- dp = (ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[symidx]) + 2;
+ dp = (uint_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[symidx]) + 2;
for (argc = MIN(argc, f.ctc_argc); argc != 0; argc--)
*argv++ = *dp++;
diff --git a/cddl/contrib/opensolaris/common/ctf/ctf_open.c b/cddl/contrib/opensolaris/common/ctf/ctf_open.c
index 001cf5c59104..cdc3e2f028fe 100644
--- a/cddl/contrib/opensolaris/common/ctf/ctf_open.c
+++ b/cddl/contrib/opensolaris/common/ctf/ctf_open.c
@@ -44,46 +44,184 @@ const char _CTF_NULLSTR[] = "";
int _libctf_version = CTF_VERSION; /* library client version */
int _libctf_debug = 0; /* debugging messages enabled */
-static ushort_t
-get_kind_v1(ushort_t info)
+static uint_t
+get_kind_v2(uint_t info)
{
- return (CTF_INFO_KIND_V1(info));
+ return (CTF_V2_INFO_KIND((ushort_t)info));
}
-static ushort_t
-get_kind_v2(ushort_t info)
+static uint_t
+get_root_v2(uint_t info)
{
- return (CTF_INFO_KIND(info));
+ return (CTF_V2_INFO_ISROOT((ushort_t)info));
}
-static ushort_t
-get_root_v1(ushort_t info)
+static uint_t
+get_vlen_v2(uint_t info)
{
- return (CTF_INFO_ISROOT_V1(info));
+ return (CTF_V2_INFO_VLEN((ushort_t)info));
}
-static ushort_t
-get_root_v2(ushort_t info)
+static uint_t
+get_max_vlen_v2(void)
{
- return (CTF_INFO_ISROOT(info));
+ return (CTF_V2_MAX_VLEN);
}
-static ushort_t
-get_vlen_v1(ushort_t info)
+static uint_t
+get_max_size_v2(void)
{
- return (CTF_INFO_VLEN_V1(info));
+ return (CTF_V2_MAX_SIZE);
}
-static ushort_t
-get_vlen_v2(ushort_t info)
+static uint_t
+get_max_type_v2(void)
{
- return (CTF_INFO_VLEN(info));
+ return (CTF_V2_MAX_TYPE);
}
+static uint_t
+get_lsize_sent_v2(void)
+{
+ return (CTF_V2_LSIZE_SENT);
+}
+
+static uint_t
+get_lstruct_thresh_v2(void)
+{
+ return (CTF_V2_LSTRUCT_THRESH);
+}
+
+static uint_t
+type_info_v2(uint_t kind, uint_t isroot, uint_t len)
+{
+ return (CTF_V2_TYPE_INFO(kind, isroot, len));
+}
+
+static int
+type_isparent_v2(uint_t id)
+{
+ return (CTF_V2_TYPE_ISPARENT(id));
+}
+
+static int
+type_ischild_v2(uint_t id)
+{
+ return (CTF_V2_TYPE_ISCHILD(id));
+}
+
+static uint_t
+type_to_index_v2(uint_t t)
+{
+ return (CTF_V2_TYPE_TO_INDEX(t));
+}
+
+static uint_t
+index_to_type_v2(uint_t id, uint_t child)
+{
+ return (CTF_V2_INDEX_TO_TYPE(id, child));
+}
+
+static uint_t
+get_kind_v3(uint_t info)
+{
+ return (CTF_V3_INFO_KIND(info));
+}
+
+static uint_t
+get_root_v3(uint_t info)
+{
+ return (CTF_V3_INFO_ISROOT(info));
+}
+
+static uint_t
+get_vlen_v3(uint_t info)
+{
+ return (CTF_V3_INFO_VLEN(info));
+}
+
+static uint_t
+get_max_vlen_v3(void)
+{
+ return (CTF_V3_MAX_VLEN);
+}
+
+static uint_t
+get_max_size_v3(void)
+{
+ return (CTF_V3_MAX_SIZE);
+}
+
+static uint_t
+get_max_type_v3(void)
+{
+ return (CTF_V3_MAX_TYPE);
+}
+
+static uint_t
+get_lsize_sent_v3(void)
+{
+ return (CTF_V3_LSIZE_SENT);
+}
+
+static uint_t
+get_lstruct_thresh_v3(void)
+{
+ return (CTF_V3_LSTRUCT_THRESH);
+}
+
+static uint_t
+type_info_v3(uint_t kind, uint_t isroot, uint_t len)
+{
+ return (CTF_V3_TYPE_INFO(kind, isroot, len));
+}
+
+static int
+type_isparent_v3(uint_t id)
+{
+ return (CTF_V3_TYPE_ISPARENT(id));
+}
+
+static int
+type_ischild_v3(uint_t id)
+{
+ return (CTF_V3_TYPE_ISCHILD(id));
+}
+
+static uint_t
+type_to_index_v3(uint_t t)
+{
+ return (CTF_V3_TYPE_TO_INDEX(t));
+}
+
+static uint_t
+index_to_type_v3(uint_t id, uint_t child)
+{
+ return (CTF_V3_INDEX_TO_TYPE(id, child));
+}
+
+#define CTF_FILEOPS_ENTRY(v) \
+ { \
+ .ctfo_get_kind = get_kind_v ## v, \
+ .ctfo_get_root = get_root_v ## v, \
+ .ctfo_get_vlen = get_vlen_v ## v, \
+ .ctfo_get_max_vlen = get_max_vlen_v ## v, \
+ .ctfo_get_max_size = get_max_size_v ## v, \
+ .ctfo_get_max_type = get_max_type_v ## v, \
+ .ctfo_get_lsize_sent = get_lsize_sent_v ## v, \
+ .ctfo_get_lstruct_thresh = get_lstruct_thresh_v ## v, \
+ .ctfo_type_info = type_info_v ## v, \
+ .ctfo_type_isparent = type_isparent_v ## v, \
+ .ctfo_type_ischild = type_ischild_v ## v, \
+ .ctfo_type_to_index = type_to_index_v ## v, \
+ .ctfo_index_to_type = index_to_type_v ## v \
+ }
+
static const ctf_fileops_t ctf_fileops[] = {
{ NULL, NULL },
- { get_kind_v1, get_root_v1, get_vlen_v1 },
- { get_kind_v2, get_root_v2, get_vlen_v2 },
+ { NULL, NULL },
+ CTF_FILEOPS_ENTRY(2),
+ CTF_FILEOPS_ENTRY(3),
};
/*
@@ -118,7 +256,8 @@ init_symtab(ctf_file_t *fp, const ctf_header_t *hp,
uint_t objtoff = hp->cth_objtoff;
uint_t funcoff = hp->cth_funcoff;
- ushort_t info, vlen;
+ uint_t info, vlen;
+
Elf64_Sym sym, *gsp;
const char *name;
@@ -156,7 +295,7 @@ init_symtab(ctf_file_t *fp, const ctf_header_t *hp,
}
*xp = objtoff;
- objtoff += sizeof (ushort_t);
+ objtoff += fp->ctf_idwidth;
break;
case STT_FUNC:
@@ -167,7 +306,7 @@ init_symtab(ctf_file_t *fp, const ctf_header_t *hp,
*xp = funcoff;
- info = *(ushort_t *)((uintptr_t)fp->ctf_buf + funcoff);
+ info = *(uint_t *)((uintptr_t)fp->ctf_buf + funcoff);
vlen = LCTF_INFO_VLEN(fp, info);
/*
@@ -177,9 +316,10 @@ init_symtab(ctf_file_t *fp, const ctf_header_t *hp,
*/
if (LCTF_INFO_KIND(fp, info) == CTF_K_UNKNOWN &&
vlen == 0)
- funcoff += sizeof (ushort_t); /* skip pad */
+ funcoff += fp->ctf_idwidth;
else
- funcoff += sizeof (ushort_t) * (vlen + 2);
+ funcoff +=
+ roundup2(fp->ctf_idwidth * (vlen + 2), 4);
break;
default:
@@ -199,15 +339,13 @@ init_symtab(ctf_file_t *fp, const ctf_header_t *hp,
static int
init_types(ctf_file_t *fp, const ctf_header_t *cth)
{
- /* LINTED - pointer alignment */
- const ctf_type_t *tbuf = (ctf_type_t *)(fp->ctf_buf + cth->cth_typeoff);
- /* LINTED - pointer alignment */
- const ctf_type_t *tend = (ctf_type_t *)(fp->ctf_buf + cth->cth_stroff);
+ const void *tbuf = (const void *)(fp->ctf_buf + cth->cth_typeoff);
+ const void *tend = (const void *)(fp->ctf_buf + cth->cth_stroff);
ulong_t pop[CTF_K_MAX + 1] = { 0 };
- const ctf_type_t *tp;
+ const void *tp;
ctf_hash_t *hp;
- ushort_t id, dst;
+ uint_t id, dst;
uint_t *xp;
/*
@@ -225,14 +363,14 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
* pass, we count the number of each type and the total number of types.
*/
for (tp = tbuf; tp < tend; fp->ctf_typemax++) {
- ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info);
- ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info);
ssize_t size, increment;
size_t vbytes;
- uint_t n;
+ uint_t kind, n, type, vlen;
(void) ctf_get_ctt_size(fp, tp, &size, &increment);
+ ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
+ ctf_get_ctt_index(fp, tp, NULL, &type, NULL);
switch (kind) {
case CTF_K_INTEGER:
@@ -240,31 +378,30 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
vbytes = sizeof (uint_t);
break;
case CTF_K_ARRAY:
- vbytes = sizeof (ctf_array_t);
+ if (fp->ctf_version == CTF_VERSION_2)
+ vbytes = sizeof (struct ctf_array_v2);
+ else
+ vbytes = sizeof (struct ctf_array_v3);
break;
case CTF_K_FUNCTION:
- vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
+ vbytes = roundup2(fp->ctf_idwidth * vlen, 4);
break;
case CTF_K_STRUCT:
- case CTF_K_UNION:
- if (fp->ctf_version == CTF_VERSION_1 ||
- size < CTF_LSTRUCT_THRESH) {
- ctf_member_t *mp = (ctf_member_t *)
- ((uintptr_t)tp + increment);
-
- vbytes = sizeof (ctf_member_t) * vlen;
- for (n = vlen; n != 0; n--, mp++)
- child |= CTF_TYPE_ISCHILD(mp->ctm_type);
- } else {
- ctf_lmember_t *lmp = (ctf_lmember_t *)
- ((uintptr_t)tp + increment);
+ case CTF_K_UNION: {
+ size_t increment1;
+ uint_t type;
+ const void *mp =
+ (const void *)((uintptr_t)tp + increment);
- vbytes = sizeof (ctf_lmember_t) * vlen;
- for (n = vlen; n != 0; n--, lmp++)
- child |=
- CTF_TYPE_ISCHILD(lmp->ctlm_type);
+ vbytes = 0;
+ for (n = vlen; n != 0; n--, mp += increment1) {
+ ctf_get_ctm_info(fp, mp, size, &increment1, &type,
+ NULL, NULL);
+ child |= LCTF_TYPE_ISCHILD(fp, type);
+ vbytes += increment1;
}
break;
+ }
case CTF_K_ENUM:
vbytes = sizeof (ctf_enum_t) * vlen;
break;
@@ -274,11 +411,10 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
* kind for the tag, so bump that population count too.
* If ctt_type is unknown, treat the tag as a struct.
*/
- if (tp->ctt_type == CTF_K_UNKNOWN ||
- tp->ctt_type >= CTF_K_MAX)
+ if (type == CTF_K_UNKNOWN || type >= CTF_K_MAX)
pop[CTF_K_STRUCT]++;
else
- pop[tp->ctt_type]++;
+ pop[type]++;
/*FALLTHRU*/
case CTF_K_UNKNOWN:
vbytes = 0;
@@ -288,14 +424,14 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
case CTF_K_VOLATILE:
case CTF_K_CONST:
case CTF_K_RESTRICT:
- child |= CTF_TYPE_ISCHILD(tp->ctt_type);
+ child |= LCTF_TYPE_ISCHILD(fp, type);
vbytes = 0;
break;
default:
ctf_dprintf("detected invalid CTF kind -- %u\n", kind);
return (ECTF_CORRUPT);
}
- tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
+ tp = (const void *)((uintptr_t)tp + increment + vbytes);
pop[kind]++;
}
@@ -329,7 +465,7 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
return (err);
fp->ctf_txlate = ctf_alloc(sizeof (uint_t) * (fp->ctf_typemax + 1));
- fp->ctf_ptrtab = ctf_alloc(sizeof (ushort_t) * (fp->ctf_typemax + 1));
+ fp->ctf_ptrtab = ctf_alloc(sizeof (uint_t) * (fp->ctf_typemax + 1));
if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL)
return (EAGAIN); /* memory allocation failed */
@@ -338,15 +474,15 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
*xp++ = 0; /* type id 0 is used as a sentinel value */
bzero(fp->ctf_txlate, sizeof (uint_t) * (fp->ctf_typemax + 1));
- bzero(fp->ctf_ptrtab, sizeof (ushort_t) * (fp->ctf_typemax + 1));
+ bzero(fp->ctf_ptrtab, sizeof (uint_t) * (fp->ctf_typemax + 1));
/*
* In the second pass through the types, we fill in each entry of the
* type and pointer tables and add names to the appropriate hashes.
*/
for (id = 1, tp = tbuf; tp < tend; xp++, id++) {
- ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info);
- ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info);
+ const struct ctf_type_v3 *ctt = tp;
+ uint_t kind, type, vlen;
ssize_t size, increment;
const char *name;
@@ -355,7 +491,9 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
ctf_encoding_t cte;
(void) ctf_get_ctt_size(fp, tp, &size, &increment);
- name = ctf_strptr(fp, tp->ctt_name);
+ ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
+ ctf_get_ctt_index(fp, tp, NULL, &type, NULL);
+ name = ctf_type_rname(fp, tp);
switch (kind) {
case CTF_K_INTEGER:
@@ -368,7 +506,8 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
if ((hep = ctf_hash_lookup(&fp->ctf_names, fp,
name, strlen(name))) == NULL) {
err = ctf_hash_insert(&fp->ctf_names, fp,
- CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
+ LCTF_INDEX_TO_TYPE(fp, id, child),
+ ctt->ctt_name);
if (err != 0 && err != ECTF_STRTAB)
return (err);
} else if (ctf_type_encoding(fp, hep->h_type,
@@ -377,58 +516,89 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
* Work-around SOS8 stabs bug: replace existing
* intrinsic w/ same name if it was zero bits.
*/
- hep->h_type = CTF_INDEX_TO_TYPE(id, child);
+ hep->h_type = LCTF_INDEX_TO_TYPE(fp, id, child);
}
vbytes = sizeof (uint_t);
break;
case CTF_K_ARRAY:
- vbytes = sizeof (ctf_array_t);
+ if (fp->ctf_version == CTF_VERSION_2)
+ vbytes = sizeof (struct ctf_array_v2);
+ else
+ vbytes = sizeof (struct ctf_array_v3);
break;
case CTF_K_FUNCTION:
err = ctf_hash_insert(&fp->ctf_names, fp,
- CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
+ LCTF_INDEX_TO_TYPE(fp, id, child), ctt->ctt_name);
if (err != 0 && err != ECTF_STRTAB)
return (err);
- vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
+ vbytes = roundup2(fp->ctf_idwidth * vlen, 4);
break;
case CTF_K_STRUCT:
err = ctf_hash_define(&fp->ctf_structs, fp,
- CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
+ LCTF_INDEX_TO_TYPE(fp, id, child), ctt->ctt_name);
if (err != 0 && err != ECTF_STRTAB)
return (err);
- if (fp->ctf_version == CTF_VERSION_1 ||
- size < CTF_LSTRUCT_THRESH)
- vbytes = sizeof (ctf_member_t) * vlen;
- else {
- vbytes = sizeof (ctf_lmember_t) * vlen;
- nlstructs++;
+ if (fp->ctf_version == CTF_VERSION_2) {
+ if (size < LCTF_LSTRUCT_THRESH(fp))
+ vbytes = sizeof (struct ctf_member_v2) *
+ vlen;
+ else {
+ vbytes =
+ sizeof (struct ctf_lmember_v2) *
+ vlen;
+ nlstructs++;
+ }
+ } else {
+ if (size < LCTF_LSTRUCT_THRESH(fp))
+ vbytes = sizeof (struct ctf_member_v3) *
+ vlen;
+ else {
+ vbytes =
+ sizeof (struct ctf_lmember_v3) *
+ vlen;
+ nlstructs++;
+ }
}
break;
case CTF_K_UNION:
err = ctf_hash_define(&fp->ctf_unions, fp,
- CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
+ LCTF_INDEX_TO_TYPE(fp, id, child), ctt->ctt_name);
if (err != 0 && err != ECTF_STRTAB)
return (err);
- if (fp->ctf_version == CTF_VERSION_1 ||
- size < CTF_LSTRUCT_THRESH)
- vbytes = sizeof (ctf_member_t) * vlen;
- else {
- vbytes = sizeof (ctf_lmember_t) * vlen;
- nlunions++;
+ if (fp->ctf_version == CTF_VERSION_2) {
+ if (size < LCTF_LSTRUCT_THRESH(fp))
+ vbytes = sizeof (struct ctf_member_v2) *
+ vlen;
+ else {
+ vbytes =
+ sizeof (struct ctf_lmember_v2) *
+ vlen;
+ nlunions++;
+ }
+ } else {
+ if (size < LCTF_LSTRUCT_THRESH(fp))
+ vbytes = sizeof (struct ctf_member_v3) *
+ vlen;
+ else {
+ vbytes =
+ sizeof (struct ctf_lmember_v3) *
+ vlen;
+ nlunions++;
+ }
}
break;
case CTF_K_ENUM:
err = ctf_hash_define(&fp->ctf_enums, fp,
- CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
+ LCTF_INDEX_TO_TYPE(fp, id, child), ctt->ctt_name);
if (err != 0 && err != ECTF_STRTAB)
return (err);
@@ -438,7 +608,7 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
case CTF_K_TYPEDEF:
err = ctf_hash_insert(&fp->ctf_names, fp,
- CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
+ LCTF_INDEX_TO_TYPE(fp, id, child), ctt->ctt_name);
if (err != 0 && err != ECTF_STRTAB)
return (err);
vbytes = 0;
@@ -449,7 +619,7 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
* Only insert forward tags into the given hash if the
* type or tag name is not already present.
*/
- switch (tp->ctt_type) {
+ switch (type) {
case CTF_K_STRUCT:
hp = &fp->ctf_structs;
break;
@@ -466,7 +636,8 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
if (ctf_hash_lookup(hp, fp,
name, strlen(name)) == NULL) {
err = ctf_hash_insert(hp, fp,
- CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
+ LCTF_INDEX_TO_TYPE(fp, id, child),
+ ctt->ctt_name);
if (err != 0 && err != ECTF_STRTAB)
return (err);
}
@@ -479,17 +650,17 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
* container, then store the index of the pointer type
* in fp->ctf_ptrtab[ index of referenced type ].
*/
- if (CTF_TYPE_ISCHILD(tp->ctt_type) == child &&
- CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax)
+ if (LCTF_TYPE_ISCHILD(fp, type) == child &&
+ LCTF_TYPE_TO_INDEX(fp, type) <= fp->ctf_typemax)
fp->ctf_ptrtab[
- CTF_TYPE_TO_INDEX(tp->ctt_type)] = id;
+ LCTF_TYPE_TO_INDEX(fp, type)] = id;
/*FALLTHRU*/
case CTF_K_VOLATILE:
case CTF_K_CONST:
case CTF_K_RESTRICT:
err = ctf_hash_insert(&fp->ctf_names, fp,
- CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
+ LCTF_INDEX_TO_TYPE(fp, id, child), ctt->ctt_name);
if (err != 0 && err != ECTF_STRTAB)
return (err);
/*FALLTHRU*/
@@ -500,7 +671,7 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
}
*xp = (uint_t)((uintptr_t)tp - (uintptr_t)fp->ctf_buf);
- tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
+ tp = (const void *)((uintptr_t)tp + increment + vbytes);
}
ctf_dprintf("%lu total types processed\n", fp->ctf_typemax);
@@ -520,14 +691,17 @@ init_types(ctf_file_t *fp, const ctf_header_t *cth)
*/
for (id = 1; id <= fp->ctf_typemax; id++) {
if ((dst = fp->ctf_ptrtab[id]) != 0) {
+ uint_t index, kind;
+ int ischild;
+
tp = LCTF_INDEX_TO_TYPEPTR(fp, id);
+ ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
+ ctf_get_ctt_index(fp, tp, &index, NULL, &ischild);
- if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_TYPEDEF &&
- strcmp(ctf_strptr(fp, tp->ctt_name), "") == 0 &&
- CTF_TYPE_ISCHILD(tp->ctt_type) == child &&
- CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax)
- fp->ctf_ptrtab[
- CTF_TYPE_TO_INDEX(tp->ctt_type)] = dst;
+ if (kind == CTF_K_TYPEDEF &&
+ strcmp(ctf_type_rname(fp, tp), "") == 0 &&
+ ischild == child && index <= fp->ctf_typemax)
+ fp->ctf_ptrtab[index] = dst;
}
}
@@ -581,29 +755,14 @@ ctf_bufopen(const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
if (pp->ctp_magic != CTF_MAGIC)
return (ctf_set_open_errno(errp, ECTF_NOCTFBUF));
- if (pp->ctp_version == CTF_VERSION_2) {
+ if (pp->ctp_version == CTF_VERSION_2 ||
+ pp->ctp_version == CTF_VERSION_3) {
if (ctfsect->cts_size < sizeof (ctf_header_t))
return (ctf_set_open_errno(errp, ECTF_NOCTFBUF));
bcopy(ctfsect->cts_data, &hp, sizeof (hp));
hdrsz = sizeof (ctf_header_t);
- } else if (pp->ctp_version == CTF_VERSION_1) {
- const ctf_header_v1_t *h1p =
- (const ctf_header_v1_t *)ctfsect->cts_data;
-
- if (ctfsect->cts_size < sizeof (ctf_header_v1_t))
- return (ctf_set_open_errno(errp, ECTF_NOCTFBUF));
-
- bzero(&hp, sizeof (hp));
- hp.cth_preamble = h1p->cth_preamble;
- hp.cth_objtoff = h1p->cth_objtoff;
- hp.cth_funcoff = h1p->cth_funcoff;
- hp.cth_typeoff = h1p->cth_typeoff;
- hp.cth_stroff = h1p->cth_stroff;
- hp.cth_strlen = h1p->cth_strlen;
-
- hdrsz = sizeof (ctf_header_v1_t);
} else
return (ctf_set_open_errno(errp, ECTF_CTFVERS));
@@ -679,6 +838,7 @@ ctf_bufopen(const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
bzero(fp, sizeof (ctf_file_t));
fp->ctf_version = hp.cth_version;
+ fp->ctf_idwidth = fp->ctf_version == CTF_VERSION_2 ? 2 : 4;
fp->ctf_fileops = &ctf_fileops[hp.cth_version];
bcopy(ctfsect, &fp->ctf_data, sizeof (ctf_sect_t));
@@ -948,7 +1108,7 @@ ctf_close(ctf_file_t *fp)
if (fp->ctf_ptrtab != NULL) {
ctf_free(fp->ctf_ptrtab,
- sizeof (ushort_t) * (fp->ctf_typemax + 1));
+ sizeof (uint_t) * (fp->ctf_typemax + 1));
}
ctf_hash_destroy(&fp->ctf_structs);
diff --git a/cddl/contrib/opensolaris/common/ctf/ctf_types.c b/cddl/contrib/opensolaris/common/ctf/ctf_types.c
index 21b061cd9356..a3fe0bba4a9d 100644
--- a/cddl/contrib/opensolaris/common/ctf/ctf_types.c
+++ b/cddl/contrib/opensolaris/common/ctf/ctf_types.c
@@ -27,19 +27,90 @@
#include <ctf_impl.h>
+void
+ctf_get_ctt_index(const ctf_file_t *fp, const void *v, uint_t *indexp,
+ uint_t *typep, int *ischildp)
+{
+ uint_t index, type;
+ int ischild;
+
+ if (fp->ctf_version == CTF_VERSION_2) {
+ const struct ctf_type_v2 *ctt = v;
+
+ type = ctt->ctt_type;
+ index = CTF_V2_TYPE_TO_INDEX(ctt->ctt_type);
+ ischild = CTF_V2_TYPE_ISCHILD(ctt->ctt_type);
+ } else {
+ const struct ctf_type_v3 *ctt = v;
+
+ type = ctt->ctt_type;
+ index = CTF_V3_TYPE_TO_INDEX(ctt->ctt_type);
+ ischild = CTF_V3_TYPE_ISCHILD(ctt->ctt_type);
+ }
+
+ if (indexp != NULL)
+ *indexp = index;
+ if (typep != NULL)
+ *typep = type;
+ if (ischildp != NULL)
+ *ischildp = ischild;
+}
+
+void
+ctf_get_ctt_info(const ctf_file_t *fp, const void *v, uint_t *kindp,
+ uint_t *vlenp, int *isrootp)
+{
+ uint_t kind, vlen;
+ int isroot;
+
+ if (fp->ctf_version == CTF_VERSION_2) {
+ const struct ctf_type_v2 *ctt = v;
+
+ kind = CTF_V2_INFO_KIND(ctt->ctt_info);
+ vlen = CTF_V2_INFO_VLEN(ctt->ctt_info);
+ isroot = CTF_V2_INFO_ISROOT(ctt->ctt_info);
+ } else {
+ const struct ctf_type_v3 *ctt = v;
+
+ kind = CTF_V3_INFO_KIND(ctt->ctt_info);
+ vlen = CTF_V3_INFO_VLEN(ctt->ctt_info);
+ isroot = CTF_V3_INFO_ISROOT(ctt->ctt_info);
+ }
+
+ if (kindp != NULL)
+ *kindp = kind;
+ if (vlenp != NULL)
+ *vlenp = vlen;
+ if (isrootp != NULL)
+ *isrootp = isroot;
+}
+
ssize_t
-ctf_get_ctt_size(const ctf_file_t *fp, const ctf_type_t *tp, ssize_t *sizep,
+ctf_get_ctt_size(const ctf_file_t *fp, const void *v, ssize_t *sizep,
ssize_t *incrementp)
{
ssize_t size, increment;
- if (fp->ctf_version > CTF_VERSION_1 &&
- tp->ctt_size == CTF_LSIZE_SENT) {
- size = CTF_TYPE_LSIZE(tp);
- increment = sizeof (ctf_type_t);
+ if (fp->ctf_version == CTF_VERSION_2) {
+ const struct ctf_type_v2 *ctt = v;
+
+ if (ctt->ctt_size == CTF_V2_LSIZE_SENT) {
+ size = (size_t)CTF_TYPE_LSIZE(ctt);
+ increment = sizeof (struct ctf_type_v2);
+ } else {
+ size = ctt->ctt_size;
+ increment = sizeof (struct ctf_stype_v2);
+ }
} else {
- size = tp->ctt_size;
- increment = sizeof (ctf_stype_t);
+ const struct ctf_type_v3 *ctt = v;
+
+ if (ctt->ctt_size == CTF_V3_LSIZE_SENT) {
+ size = (size_t)CTF_TYPE_LSIZE(ctt);
+ increment = sizeof (struct ctf_type_v3);
+ } else {
+ size = ctt->ctt_size;
+ increment = sizeof (struct ctf_stype_v3);
+ }
}
if (sizep)
@@ -51,6 +122,61 @@ ctf_get_ctt_size(const ctf_file_t *fp, const ctf_type_t *tp, ssize_t *sizep,
}
/*
+ * Fetch info for a struct or union member.
+ */
+void
+ctf_get_ctm_info(const ctf_file_t *fp, const void *v, size_t size,
+ size_t *incrementp, uint_t *typep, ulong_t *offsetp, const char **namep)
+{
+ size_t increment;
+ ulong_t offset;
+ uint_t name, type;
+
+ if (fp->ctf_version == CTF_VERSION_2) {
+ if (size < CTF_V2_LSTRUCT_THRESH) {
+ const struct ctf_member_v2 *ctm = v;
+
+ name = ctm->ctm_name;
+ type = ctm->ctm_type;
+ offset = ctm->ctm_offset;
+ increment = sizeof(*ctm);
+ } else {
+ const struct ctf_lmember_v2 *ctlm = v;
+
+ name = ctlm->ctlm_name;
+ type = ctlm->ctlm_type;
+ offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
+ increment = sizeof(*ctlm);
+ }
+ } else {
+ if (size < CTF_V3_LSTRUCT_THRESH) {
+ const struct ctf_member_v3 *ctm = v;
+
+ name = ctm->ctm_name;
+ type = ctm->ctm_type;
+ offset = ctm->ctm_offset;
+ increment = sizeof(*ctm);
+ } else {
+ const struct ctf_lmember_v3 *ctlm = v;
+
+ name = ctlm->ctlm_name;
+ type = ctlm->ctlm_type;
+ offset = (ulong_t)CTF_LMEM_OFFSET(ctlm);
+ increment = sizeof(*ctlm);
+ }
+ }
+
+ if (incrementp != NULL)
+ *incrementp = increment;
+ if (typep != NULL)
+ *typep = type;
+ if (offsetp != NULL)
+ *offsetp = offset;
+ if (namep != NULL)
+ *namep = ctf_strraw(fp, name);
+}
+
+/*
* Iterate over the members of a STRUCT or UNION. We pass the name, member
* type, and offset of each member to the specified callback function.
*/
@@ -58,9 +184,9 @@ int
ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
{
ctf_file_t *ofp = fp;
- const ctf_type_t *tp;
+ const void *tp;
ssize_t size, increment;
- uint_t kind, n;
+ uint_t kind, n, vlen;
int rc;
if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
@@ -70,32 +196,22 @@ ctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg)
return (CTF_ERR); /* errno is set for us */
(void) ctf_get_ctt_size(fp, tp, &size, &increment);
- kind = LCTF_INFO_KIND(fp, tp->ctt_info);
+ ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
return (ctf_set_errno(ofp, ECTF_NOTSOU));
- if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) {
- const ctf_member_t *mp = (const ctf_member_t *)
- ((uintptr_t)tp + increment);
+ const char *mp = (const char *)((uintptr_t)tp + increment);
- for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) {
- const char *name = ctf_strptr(fp, mp->ctm_name);
- if ((rc = func(name, mp->ctm_type, mp->ctm_offset,
- arg)) != 0)
- return (rc);
- }
+ for (n = vlen; n != 0; n--, mp += increment) {
+ const char *name;
+ ulong_t offset;
+ uint_t type;
- } else {
- const ctf_lmember_t *lmp = (const ctf_lmember_t *)
- ((uintptr_t)tp + increment);
-
- for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) {
- const char *name = ctf_strptr(fp, lmp->ctlm_name);
- if ((rc = func(name, lmp->ctlm_type,
- (ulong_t)CTF_LMEM_OFFSET(lmp), arg)) != 0)
- return (rc);
- }
+ ctf_get_ctm_info(fp, mp, size, &increment, &type, &offset,
+ &name);
+ if ((rc = func(name, type, offset, arg)) != 0)
+ return (rc);
}
return (0);
@@ -109,10 +225,10 @@ int
ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
{
ctf_file_t *ofp = fp;
- const ctf_type_t *tp;
+ const void *tp;
const ctf_enum_t *ep;
ssize_t increment;
- uint_t n;
+ uint_t kind, n, vlen;
int rc;
if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
@@ -121,14 +237,15 @@ ctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg)
if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
return (CTF_ERR); /* errno is set for us */
- if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM)
+ ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
+ if (kind != CTF_K_ENUM)
return (ctf_set_errno(ofp, ECTF_NOTENUM));
(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
- for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) {
+ for (n = vlen; n != 0; n--, ep++) {
const char *name = ctf_strptr(fp, ep->cte_name);
if ((rc = func(name, ep->cte_value, arg)) != 0)
return (rc);
@@ -146,11 +263,13 @@ ctf_type_iter(ctf_file_t *fp, ctf_type_f *func, void *arg)
{
ctf_id_t id, max = fp->ctf_typemax;
int rc, child = (fp->ctf_flags & LCTF_CHILD);
+ int isroot;
for (id = 1; id <= max; id++) {
- const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR(fp, id);
- if (CTF_INFO_ISROOT(tp->ctt_info) &&
- (rc = func(CTF_INDEX_TO_TYPE(id, child), arg)) != 0)
+ const void *tp = LCTF_INDEX_TO_TYPEPTR(fp, id);
+ ctf_get_ctt_info(fp, tp, NULL, NULL, &isroot);
+ if (isroot &&
+ (rc = func(LCTF_INDEX_TO_TYPE(fp, id, child), arg)) != 0)
return (rc);
}
@@ -169,21 +288,23 @@ ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
{
ctf_id_t prev = type, otype = type;
ctf_file_t *ofp = fp;
- const ctf_type_t *tp;
+ const void *tp;
+ uint_t kind, ctype;
while ((tp = ctf_lookup_by_id(&fp, type)) != NULL) {
- switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
+ ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
+ switch (kind) {
case CTF_K_TYPEDEF:
case CTF_K_VOLATILE:
case CTF_K_CONST:
case CTF_K_RESTRICT:
- if (tp->ctt_type == type || tp->ctt_type == otype ||
- tp->ctt_type == prev) {
+ ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
+ if (ctype == type || ctype == otype || ctype == prev) {
ctf_dprintf("type %ld cycle detected\n", otype);
return (ctf_set_errno(ofp, ECTF_CORRUPT));
}
prev = type;
- type = tp->ctt_type;
+ type = ctype;
break;
default:
return (type);
@@ -238,9 +359,8 @@ ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
cdp != NULL; cdp = ctf_list_next(cdp)) {
ctf_file_t *rfp = fp;
- const ctf_type_t *tp =
- ctf_lookup_by_id(&rfp, cdp->cd_type);
- const char *name = ctf_strptr(rfp, tp->ctt_name);
+ const void *tp = ctf_lookup_by_id(&rfp, cdp->cd_type);
+ const char *name = ctf_type_rname(rfp, tp);
if (k != CTF_K_POINTER && k != CTF_K_ARRAY)
ctf_decl_sprintf(&cd, " ");
@@ -336,6 +456,23 @@ ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
return (rv >= 0 && rv < len ? buf : NULL);
}
+const char *
+ctf_type_rname(ctf_file_t *fp, const void *v)
+{
+ uint_t name;
+
+ if (fp->ctf_version == CTF_VERSION_2) {
+ const struct ctf_type_v2 *ctt = v;
+
+ name = ctt->ctt_name;
+ } else {
+ const struct ctf_type_v3 *ctt = v;
+
+ name = ctt->ctt_name;
+ }
+
+ return (ctf_strptr(fp, name));
+}
/*
* Resolve the type down to a base type node, and then return the size
@@ -344,9 +481,10 @@ ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
ssize_t
ctf_type_size(ctf_file_t *fp, ctf_id_t type)
{
- const ctf_type_t *tp;
+ const void *tp;
ssize_t size;
ctf_arinfo_t ar;
+ uint_t kind;
if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
return (-1); /* errno is set for us */
@@ -354,7 +492,9 @@ ctf_type_size(ctf_file_t *fp, ctf_id_t type)
if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
return (-1); /* errno is set for us */
- switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
+ ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
+
+ switch (kind) {
case CTF_K_POINTER:
return (fp->ctf_dmodel->ctd_pointer);
@@ -393,8 +533,9 @@ ctf_type_size(ctf_file_t *fp, ctf_id_t type)
ssize_t
ctf_type_align(ctf_file_t *fp, ctf_id_t type)
{
- const ctf_type_t *tp;
+ const void *tp;
ctf_arinfo_t r;
+ uint_t kind, vlen;
if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
return (-1); /* errno is set for us */
@@ -402,7 +543,9 @@ ctf_type_align(ctf_file_t *fp, ctf_id_t type)
if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
return (-1); /* errno is set for us */
- switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
+ ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
+
+ switch (kind) {
case CTF_K_POINTER:
case CTF_K_FUNCTION:
return (fp->ctf_dmodel->ctd_pointer);
@@ -414,7 +557,7 @@ ctf_type_align(ctf_file_t *fp, ctf_id_t type)
case CTF_K_STRUCT:
case CTF_K_UNION: {
- uint_t n = LCTF_INFO_VLEN(fp, tp->ctt_info);
+ uint_t n = vlen;
ssize_t size, increment;
size_t align = 0;
const void *vmp;
@@ -422,22 +565,16 @@ ctf_type_align(ctf_file_t *fp, ctf_id_t type)
(void) ctf_get_ctt_size(fp, tp, &size, &increment);
vmp = (uchar_t *)tp + increment;
- if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_STRUCT)
+ if (kind == CTF_K_STRUCT)
n = MIN(n, 1); /* only use first member for structs */
- if (fp->ctf_version == CTF_VERSION_1 ||
- size < CTF_LSTRUCT_THRESH) {
- const ctf_member_t *mp = vmp;
- for (; n != 0; n--, mp++) {
- ssize_t am = ctf_type_align(fp, mp->ctm_type);
- align = MAX(align, am);
- }
- } else {
- const ctf_lmember_t *lmp = vmp;
- for (; n != 0; n--, lmp++) {
- ssize_t am = ctf_type_align(fp, lmp->ctlm_type);
- align = MAX(align, am);
- }
+ for (const char *mp = vmp; n != 0; n--, mp += increment) {
+ uint_t type;
+
+ ctf_get_ctm_info(fp, mp, size, &increment, &type,
+ NULL, NULL);
+ ssize_t am = ctf_type_align(fp, type);
+ align = MAX(align, am);
}
return (align);
@@ -457,12 +594,15 @@ ctf_type_align(ctf_file_t *fp, ctf_id_t type)
int
ctf_type_kind(ctf_file_t *fp, ctf_id_t type)
{
- const ctf_type_t *tp;
+ const void *tp;
+ uint_t kind;
if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
return (CTF_ERR); /* errno is set for us */
- return (LCTF_INFO_KIND(fp, tp->ctt_info));
+ ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
+
+ return (kind);
}
/*
@@ -473,18 +613,22 @@ ctf_id_t
ctf_type_reference(ctf_file_t *fp, ctf_id_t type)
{
ctf_file_t *ofp = fp;
- const ctf_type_t *tp;
+ const void *tp;
+ uint_t ctype, kind;
if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
return (CTF_ERR); /* errno is set for us */
- switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
+ ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
+
+ switch (kind) {
case CTF_K_POINTER:
case CTF_K_TYPEDEF:
case CTF_K_VOLATILE:
case CTF_K_CONST:
case CTF_K_RESTRICT:
- return (tp->ctt_type);
+ ctf_get_ctt_index(fp, tp, NULL, &ctype, NULL);
+ return (ctype);
default:
return (ctf_set_errno(ofp, ECTF_NOTREF));
}
@@ -506,8 +650,8 @@ ctf_type_pointer(ctf_file_t *fp, ctf_id_t type)
if (ctf_lookup_by_id(&fp, type) == NULL)
return (CTF_ERR); /* errno is set for us */
- if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0)
- return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD)));
+ if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX(fp, type)]) != 0)
+ return (LCTF_INDEX_TO_TYPE(fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
return (ctf_set_errno(ofp, ECTF_NOTYPE));
@@ -515,8 +659,8 @@ ctf_type_pointer(ctf_file_t *fp, ctf_id_t type)
if (ctf_lookup_by_id(&fp, type) == NULL)
return (ctf_set_errno(ofp, ECTF_NOTYPE));
- if ((ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)]) != 0)
- return (CTF_INDEX_TO_TYPE(ntype, (fp->ctf_flags & LCTF_CHILD)));
+ if ((ntype = fp->ctf_ptrtab[LCTF_TYPE_TO_INDEX(fp, type)]) != 0)
+ return (LCTF_INDEX_TO_TYPE(fp, ntype, (fp->ctf_flags & LCTF_CHILD)));
return (ctf_set_errno(ofp, ECTF_NOTYPE));
}
@@ -528,16 +672,17 @@ int
ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
{
ctf_file_t *ofp = fp;
- const ctf_type_t *tp;
+ const void *tp;
ssize_t increment;
- uint_t data;
+ uint_t data, kind;
if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
return (CTF_ERR); /* errno is set for us */
(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
+ ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
- switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
+ switch (kind) {
case CTF_K_INTEGER:
data = *(const uint_t *)((uintptr_t)tp + increment);
ep->cte_format = CTF_INT_ENCODING(data);
@@ -572,10 +717,10 @@ ctf_type_cmp(ctf_file_t *lfp, ctf_id_t ltype, ctf_file_t *rfp, ctf_id_t rtype)
if (lfp == rfp)
return (rval);
- if (CTF_TYPE_ISPARENT(ltype) && lfp->ctf_parent != NULL)
+ if (LCTF_TYPE_ISPARENT(lfp, ltype) && lfp->ctf_parent != NULL)
lfp = lfp->ctf_parent;
- if (CTF_TYPE_ISPARENT(rtype) && rfp->ctf_parent != NULL)
+ if (LCTF_TYPE_ISPARENT(rfp, rtype) && rfp->ctf_parent != NULL)
rfp = rfp->ctf_parent;
if (lfp < rfp)
@@ -597,7 +742,7 @@ int
ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype,
ctf_file_t *rfp, ctf_id_t rtype)
{
- const ctf_type_t *ltp, *rtp;
+ const void *ltp, *rtp;
ctf_encoding_t le, re;
ctf_arinfo_t la, ra;
uint_t lkind, rkind;
@@ -614,8 +759,7 @@ ctf_type_compat(ctf_file_t *lfp, ctf_id_t ltype,
if (lkind != rkind ||
(ltp = ctf_lookup_by_id(&lfp, ltype)) == NULL ||
(rtp = ctf_lookup_by_id(&rfp, rtype)) == NULL ||
- strcmp(ctf_strptr(lfp, ltp->ctt_name),
- ctf_strptr(rfp, rtp->ctt_name)) != 0)
+ strcmp(ctf_type_rname(lfp, ltp), ctf_type_rname(rfp, rtp)) != 0)
return (0);
switch (lkind) {
@@ -649,9 +793,9 @@ _ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name, ulong_t off,
ctf_membinfo_t *mip)
{
ctf_file_t *ofp = fp;
- const ctf_type_t *tp;
+ const void *tp;
ssize_t size, increment;
- uint_t kind, n;
+ uint_t kind, n, vlen;
if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
return (CTF_ERR); /* errno is set for us */
@@ -660,41 +804,27 @@ _ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name, ulong_t off,
return (CTF_ERR); /* errno is set for us */
(void) ctf_get_ctt_size(fp, tp, &size, &increment);
- kind = LCTF_INFO_KIND(fp, tp->ctt_info);
+ ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
return (ctf_set_errno(ofp, ECTF_NOTSOU));
- if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) {
- const ctf_member_t *mp = (const ctf_member_t *)
- ((uintptr_t)tp + increment);
-
- for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) {
- if (mp->ctm_name == 0 &&
- _ctf_member_info(fp, mp->ctm_type, name,
- mp->ctm_offset + off, mip) == 0)
- return (0);
- if (strcmp(ctf_strptr(fp, mp->ctm_name), name) == 0) {
- mip->ctm_type = mp->ctm_type;
- mip->ctm_offset = mp->ctm_offset + off;
- return (0);
- }
- }
- } else {
- const ctf_lmember_t *lmp = (const ctf_lmember_t *)
- ((uintptr_t)tp + increment);
-
- for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) {
- if (lmp->ctlm_name == 0 &&
- _ctf_member_info(fp, lmp->ctlm_name, name,
- (ulong_t)CTF_LMEM_OFFSET(lmp) + off, mip) == 0)
- return (0);
- if (strcmp(ctf_strptr(fp, lmp->ctlm_name), name) == 0) {
- mip->ctm_type = lmp->ctlm_type;
- mip->ctm_offset =
- (ulong_t)CTF_LMEM_OFFSET(lmp) + off;
- return (0);
- }
+ const char *mp = (const char *)((uintptr_t)tp + increment);
+
+ for (n = vlen; n != 0; n--, mp += increment) {
+ const char *name1;
+ ulong_t offset;
+ uint_t type;
+
+ ctf_get_ctm_info(fp, mp, size, &increment, &type, &offset,
+ &name1);
+ if (name1[0] == '\0' &&
+ _ctf_member_info(fp, type, name, offset + off, mip) == 0)
+ return (0);
+ if (strcmp(name1, name) == 0) {
+ mip->ctm_type = type;
+ mip->ctm_offset = offset + off;
+ return (0);
}
}
@@ -719,22 +849,34 @@ int
ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
{
ctf_file_t *ofp = fp;
- const ctf_type_t *tp;
- const ctf_array_t *ap;
+ const void *ap, *tp;
ssize_t increment;
+ uint_t kind;
if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
return (CTF_ERR); /* errno is set for us */
- if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ARRAY)
+ ctf_get_ctt_info(fp, tp, &kind, NULL, NULL);
+
+ if (kind != CTF_K_ARRAY)
return (ctf_set_errno(ofp, ECTF_NOTARRAY));
(void) ctf_get_ctt_size(fp, tp, NULL, &increment);
- ap = (const ctf_array_t *)((uintptr_t)tp + increment);
- arp->ctr_contents = ap->cta_contents;
- arp->ctr_index = ap->cta_index;
- arp->ctr_nelems = ap->cta_nelems;
+ ap = (const void *)((uintptr_t)tp + increment);
+ if (fp->ctf_version == CTF_VERSION_2) {
+ const struct ctf_array_v2 *ap2 = ap;
+
+ arp->ctr_contents = ap2->cta_contents;
+ arp->ctr_index = ap2->cta_index;
+ arp->ctr_nelems = ap2->cta_nelems;
+ } else {
+ const struct ctf_array_v3 *ap3 = ap;
+
+ arp->ctr_contents = ap3->cta_contents;
+ arp->ctr_index = ap3->cta_index;
+ arp->ctr_nelems = ap3->cta_nelems;
+ }
return (0);
}
@@ -747,10 +889,10 @@ const char *
ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value)
{
ctf_file_t *ofp = fp;
- const ctf_type_t *tp;
+ const void *tp;
const ctf_enum_t *ep;
ssize_t increment;
- uint_t n;
+ uint_t kind, n, vlen;
if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
return (NULL); /* errno is set for us */
@@ -758,7 +900,9 @@ ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value)
if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
return (NULL); /* errno is set for us */
- if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) {
+ ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
+
+ if (kind != CTF_K_ENUM) {
(void) ctf_set_errno(ofp, ECTF_NOTENUM);
return (NULL);
}
@@ -767,7 +911,7 @@ ctf_enum_name(ctf_file_t *fp, ctf_id_t type, int value)
ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
- for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) {
+ for (n = vlen; n != 0; n--, ep++) {
if (ep->cte_value == value)
return (ctf_strptr(fp, ep->cte_name));
}
@@ -784,10 +928,10 @@ int
ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
{
ctf_file_t *ofp = fp;
- const ctf_type_t *tp;
+ const void *tp;
const ctf_enum_t *ep;
ssize_t size, increment;
- uint_t n;
+ uint_t kind, n, vlen;
if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
return (CTF_ERR); /* errno is set for us */
@@ -795,7 +939,9 @@ ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
return (CTF_ERR); /* errno is set for us */
- if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM) {
+ ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
+
+ if (kind != CTF_K_ENUM) {
(void) ctf_set_errno(ofp, ECTF_NOTENUM);
return (CTF_ERR);
}
@@ -804,7 +950,7 @@ ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
ep = (const ctf_enum_t *)((uintptr_t)tp + increment);
- for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) {
+ for (n = vlen; n != 0; n--, ep++) {
if (strcmp(ctf_strptr(fp, ep->cte_name), name) == 0) {
if (valp != NULL)
*valp = ep->cte_value;
@@ -828,9 +974,9 @@ ctf_type_rvisit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg,
const char *name, ulong_t offset, int depth)
{
ctf_id_t otype = type;
- const ctf_type_t *tp;
+ const void *tp;
ssize_t size, increment;
- uint_t kind, n;
+ uint_t kind, n, vlen;
int rc;
if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)
@@ -842,35 +988,24 @@ ctf_type_rvisit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg,
if ((rc = func(name, otype, offset, depth, arg)) != 0)
return (rc);
- kind = LCTF_INFO_KIND(fp, tp->ctt_info);
+ ctf_get_ctt_info(fp, tp, &kind, &vlen, NULL);
if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
return (0);
(void) ctf_get_ctt_size(fp, tp, &size, &increment);
- if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) {
- const ctf_member_t *mp = (const ctf_member_t *)
- ((uintptr_t)tp + increment);
+ const char *mp = (const char *)((uintptr_t)tp + increment);
+ for (n = vlen; n != 0; n--, mp += increment) {
+ const char *name;
+ ulong_t offset1;
+ uint_t type;
- for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) {
- if ((rc = ctf_type_rvisit(fp, mp->ctm_type,
- func, arg, ctf_strptr(fp, mp->ctm_name),
- offset + mp->ctm_offset, depth + 1)) != 0)
- return (rc);
- }
-
- } else {
- const ctf_lmember_t *lmp = (const ctf_lmember_t *)
- ((uintptr_t)tp + increment);
-
- for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) {
- if ((rc = ctf_type_rvisit(fp, lmp->ctlm_type,
- func, arg, ctf_strptr(fp, lmp->ctlm_name),
- offset + (ulong_t)CTF_LMEM_OFFSET(lmp),
- depth + 1)) != 0)
- return (rc);
- }
+ ctf_get_ctm_info(fp, mp, size, &increment, &type, &offset1,
+ &name);
+ if ((rc = ctf_type_rvisit(fp, type, func, arg, name,
+ offset + offset1, depth + 1)) != 0)
+ return (rc);
}
return (0);
diff --git a/cddl/contrib/opensolaris/common/ctf/ctf_util.c b/cddl/contrib/opensolaris/common/ctf/ctf_util.c
index 740d403e8c52..d3d9a65211bb 100644
--- a/cddl/contrib/opensolaris/common/ctf/ctf_util.c
+++ b/cddl/contrib/opensolaris/common/ctf/ctf_util.c
@@ -96,9 +96,9 @@ ctf_list_delete(ctf_list_t *lp, void *existing)
* up the appropriate string table buffer and then adding the offset.
*/
const char *
-ctf_strraw(ctf_file_t *fp, uint_t name)
+ctf_strraw(const ctf_file_t *fp, uint_t name)
{
- ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID(name)];
+ const ctf_strs_t *ctsp = &fp->ctf_str[CTF_NAME_STID(name)];
if (ctsp->cts_strs != NULL && CTF_NAME_OFFSET(name) < ctsp->cts_len)
return (ctsp->cts_strs + CTF_NAME_OFFSET(name));
@@ -108,7 +108,7 @@ ctf_strraw(ctf_file_t *fp, uint_t name)
}
const char *
-ctf_strptr(ctf_file_t *fp, uint_t name)
+ctf_strptr(const ctf_file_t *fp, uint_t name)
{
const char *s = ctf_strraw(fp, name);
return (s != NULL ? s : "(?)");
diff --git a/cddl/contrib/opensolaris/lib/libctf/common/ctf.5 b/cddl/contrib/opensolaris/lib/libctf/common/ctf.5
index d9f41de6a9ca..1d747bbbea13 100644
--- a/cddl/contrib/opensolaris/lib/libctf/common/ctf.5
+++ b/cddl/contrib/opensolaris/lib/libctf/common/ctf.5
@@ -11,7 +11,7 @@
.\"
.\" Copyright (c) 2014 Joyent, Inc.
.\"
-.Dd Sep 26, 2014
+.Dd February 28, 2022
.Dt CTF 5
.Os
.Sh NAME
@@ -65,11 +65,11 @@ data can be obtained through libctf.
The
.Nm
file format is broken down into seven different sections.
-The first section is the
+The first two sections are the
.Sy preamble
and
.Sy header ,
-which describes the version of the
+which describe the version of the
.Nm
file, the links it has to other
.Nm
@@ -129,15 +129,22 @@ and the type information that comes from the
module.
This means that a module only has types that are unique to itself and the most
common types in the kernel are not duplicated.
+Uniquification is not used when building kernel modules on
+.Fx .
.Sh FILE FORMAT
This documents version
-.Em two
+.Em three
of the
.Nm
file format.
-All applications and tools on
-.Fx
-currently produce and operate on this version.
+The
+.Xr ctfconvert 1
+and
+.Xr ctfmerge 1
+utilities emit
+.Nm
+version 3, and all other applications and libraries can operate on
+versions 2 and 3.
.Lp
The file format can be summarized with the following image, the
following sections will cover this in more detail.
@@ -164,7 +171,7 @@ following sections will cover this in more detail.
||||||| +-- magic - vers flags
||||||| | | | |
||||||| +------+------+------+------+
-+---------| 0xcf | 0xf1 | 0x02 | 0x00 |
++---------| 0xcf | 0xf1 | 0x03 | 0x00 |
|||||| +------+------+------+------+
|||||| 0 1 2 3 4
||||||
@@ -191,7 +198,7 @@ following sections will cover this in more detail.
|||| +------+------+------+-----+
+----------| 0x00 | 0x42 | 0x36 | ... |
||| +------+------+------+-----+
- ||| cth_objtoff +0x2 +0x4 +0x6 cth_funcoff
+ ||| cth_objtoff +0x4 +0x8 +0xc cth_funcoff
|||
||| + CTF_TYPE_INFO + CTF_TYPE_INFO
||| | + Return type |
@@ -199,7 +206,7 @@ following sections will cover this in more detail.
||| +--------+------+------+-----+
+---------| 0x2c10 | 0x08 | 0x0c | ... |
|| +--------+------+------+-----+
- || cth_funcff +0x2 +0x4 +0x6 cth_typeoff
+ || cth_funcff +0x4 +0x8 +0xc cth_typeoff
||
|| + ctf_stype_t for type 1
|| | integer + integer encoding
@@ -208,7 +215,7 @@ following sections will cover this in more detail.
|| +--------------------+-----------+-----+
+--------| 0x19 * 0xc01 * 0x0 | 0x1000000 | ... |
| +--------------------+-----------+-----+
- | cth_typeoff +0x08 +0x0c cth_stroff
+ | cth_typeoff +0x0c +0x10 cth_stroff
|
| +--- str 0
| | +--- str 1 + str 2
@@ -265,7 +272,7 @@ member defines the version of the
.Nm
file.
The current version is
-.Li 2 .
+.Li 3 .
It is possible to encounter an unsupported version.
In that case, software should not try to parse the format, as it may have
changed.
@@ -296,7 +303,7 @@ always refer to the
.Sy uncompressed
data.
.Lp
-In version two of the
+In versions two and three of the
.Nm
file format, the
.Sy header
@@ -327,7 +334,7 @@ typedef struct ctf_header {
After the
.Sy preamble ,
the next two members
-.Em cth_parlablel
+.Em cth_parlabel
and
.Em cth_parname ,
are used to identify the parent.
@@ -364,7 +371,7 @@ file.
The difference between members indicates the size of the section itself.
Different offsets have different alignment requirements.
The start of the
-.Em cth_objotoff
+.Em cth_objtoff
and
.Em cth_funcoff
must be two byte aligned, while the sections
@@ -381,9 +388,9 @@ section, one should subtract the offset of the section from the following one.
For example, the size of the
.Sy types
section can be calculated by subtracting
-.Em cth_stroff
+.Em cth_typeoff
from
-.Em cth_typeoff .
+.Em cth_stroff .
.Lp
Finally, the member
.Em cth_strlen
@@ -402,16 +409,20 @@ Through the
data, types are referred to by identifiers.
A given
.Nm
-file supports up to 32767 (0x7fff) types.
+file supports up to 2147483646 (0x7ffffffe) types.
+.Nm
+version 2 had a much smaller limit of 32767 types.
The first valid type identifier is 0x1.
When a given
.Nm
file is a child, indicated by a non-zero entry for the
.Sy header Ns 's
.Em cth_parname ,
-then the first valid type identifier is 0x8000 and the last is 0xffff.
-In this case, type identifiers 0x1 through 0x7fff are references to the
+then the first valid type identifier is 0x80000000 and the last is 0xfffffffe.
+In this case, type identifiers 0x1 through 0x7ffffffe are references to the
parent.
+0x7fffffff and 0xffffffff are not treated as valid type identifiers so as to
+enable the use of -1 as an error value.
.Lp
The type identifier zero is a sentinel value used to indicate that there
is no type information available or it is an unknown type.
@@ -444,7 +455,7 @@ container.
Every
.Nm
type begins with metadata encoded into a
-.Sy uint16_t .
+.Sy uint32_t .
This encoded information tells us three different pieces of information:
.Bl -bullet -offset indent -compact
.It
@@ -455,16 +466,9 @@ Whether this type is a root type or not
The length of the variable data
.El
.Lp
-The 16 bits that make up the encoding are broken down such that you have
-five bits for the kind, one bit for indicating whether or not it is a
-root type, and 10 bits for the variable length.
-This is laid out as follows:
-.Bd -literal -offset indent
-+--------------------+
-| kind | root | vlen |
-+--------------------+
-15 11 10 9 0
-.Ed
+The 32 bits that make up the encoding are broken down into six bits
+for the kind (bits 26 to 31), one bit for the root type flag (bit 25),
+and 25 bits for the length of the variable data.
.Lp
The current version of the file format defines 14 different kinds.
The interpretation of these different kinds will be discussed in the section
@@ -502,7 +506,7 @@ That type is not considered a
type.
If a type is a
.Sy root
-type, then it will have bit 10 set.
+type, then it will have bit 25 set.
.Lp
The variable length section is specific to each kind and is discussed in the
section
@@ -512,13 +516,13 @@ The following macros are useful for constructing and deconstructing the encoded
type information:
.Bd -literal -offset indent
-#define CTF_MAX_VLEN 0x3ff
-#define CTF_INFO_KIND(info) (((info) & 0xf800) >> 11)
-#define CTF_INFO_ISROOT(info) (((info) & 0x0400) >> 10)
-#define CTF_INFO_VLEN(info) (((info) & CTF_MAX_VLEN))
+#define CTF_V3_MAX_VLEN 0x00ffffff
+#define CTF_V3_INFO_KIND(info) (((info) & 0xfc000000) >> 26)
+#define CTF_V3_INFO_ISROOT(info) (((info) & 0x02000000) >> 25)
+#define CTF_V3_INFO_VLEN(info) (((info) & CTF_V3_MAX_VLEN))
-#define CTF_TYPE_INFO(kind, isroot, vlen) \\
- (((kind) << 11) | (((isroot) ? 1 : 0) << 10) | ((vlen) & CTF_MAX_VLEN))
+#define CTF_V3_TYPE_INFO(kind, isroot, vlen) \\
+ (((kind) << 26) | (((isroot) ? 1 : 0) << 25) | ((vlen) & CTF_V3_MAX_VLEN))
.Ed
.Ss The Label Section
When consuming
@@ -536,6 +540,11 @@ releases, that they are not used together by tools, particularly when a child
needs to refer to a type in the parent.
Because they are linked using the type identifiers, if the wrong parent is used
then the wrong type will be encountered.
+Note that this mechanism is not currently used on
+.Fx .
+In particular, kernel modules built on
+.Fx
+each contain a complete type graph.
.Lp
Each label is encoded in the file format using the following eight byte
structure:
@@ -573,7 +582,7 @@ The object section provides a mapping from ELF symbols of type
.Sy STT_OBJECT
in the symbol table to a type identifier.
Every entry in this section is a
-.Sy uint16_t
+.Sy uint32_t
which contains a type identifier as described in the section
.Sx Type Identifiers .
If there is no information for an object, then the type identifier 0x0
@@ -617,14 +626,17 @@ section and skipping the correct symbols:
#include <stdio.h>
/*
- * Given the start of the object section in the CTF file, the number of symbols,
+ * Given the start of the object section in a CTFv3 file, the number of symbols,
* and the ELF Data sections for the symbol table and the string table, this
* prints the type identifiers that correspond to objects. Note, a more robust
* implementation should ensure that they don't walk beyond the end of the CTF
* object section.
+ *
+ * An implementation that handles CTFv2 must take into account the fact that
+ * type identifiers are 16 bits wide rather than 32 bits wide.
*/
static int
-walk_symbols(uint16_t *objtoff, Elf_Data *symdata, Elf_Data *strdata,
+walk_symbols(uint32_t *objtoff, Elf_Data *symdata, Elf_Data *strdata,
long nsyms)
{
long i;
@@ -667,9 +679,9 @@ Unlike with objects, because functions have a variable number of arguments, they
start with a type encoding as defined in
.Sx Type Encoding ,
which is the size of a
-.Sy uint16_t .
+.Sy uint32_t .
For functions which have no type information available, they are encoded as
-.Li CTF_TYPE_INFO(CTF_K_UNKNOWN, 0, 0) .
+.Li CTF_V3_TYPE_INFO(CTF_K_UNKNOWN, 0, 0) .
Functions with arguments are encoded differently.
Here, the variable length is turned into the number of arguments in the
function.
@@ -677,12 +689,12 @@ If a function is a
.Sy varargs
type function, then the number of arguments is increased by one.
Functions with type information are encoded as:
-.Li CTF_TYPE_INFO(CTF_K_FUNCTION, 0, nargs) .
+.Li CTF_V3_TYPE_INFO(CTF_K_FUNCTION, 0, nargs) .
.Lp
For functions that have no type information, nothing else is encoded, and the
next function is encoded.
For functions with type information, the next
-.Sy uint16_t
+.Sy uint32_t
is encoded with the type identifier of the return type of the function.
It is followed by each of the type identifiers of the arguments, if any exist,
in the order that they appear in the function.
@@ -723,29 +735,29 @@ The base of the type information comes in two forms, a short form and a long
form, each of which may be followed by a variable number of arguments.
The following definitions describe the short and long forms:
.Bd -literal
-#define CTF_MAX_SIZE 0xfffe /* max size of a type in bytes */
-#define CTF_LSIZE_SENT 0xffff /* sentinel for ctt_size */
-#define CTF_MAX_LSIZE UINT64_MAX
+#define CTF_V3_MAX_SIZE 0xfffffffe /* max size of a type in bytes */
+#define CTF_V3_LSIZE_SENT 0xffffffff /* sentinel for ctt_size */
+#define CTF_V3_MAX_LSIZE UINT64_MAX
-typedef struct ctf_stype {
+struct ctf_stype_v3 {
uint32_t ctt_name; /* reference to name in string table */
- uint16_t ctt_info; /* encoded kind, variant length */
+ uint32_t ctt_info; /* encoded kind, variant length */
union {
- uint16_t _size; /* size of entire type in bytes */
- uint16_t _type; /* reference to another type */
+ uint32_t _size; /* size of entire type in bytes */
+ uint32_t _type; /* reference to another type */
} _u;
-} ctf_stype_t;
+};
-typedef struct ctf_type {
+struct ctf_type_v3 {
uint32_t ctt_name; /* reference to name in string table */
- uint16_t ctt_info; /* encoded kind, variant length */
+ uint32_t ctt_info; /* encoded kind, variant length */
union {
- uint16_t _size; /* always CTF_LSIZE_SENT */
- uint16_t _type; /* do not use */
+ uint32_t _size; /* always CTF_LSIZE_SENT */
+ uint32_t _type; /* do not use */
} _u;
uint32_t ctt_lsizehi; /* high 32 bits of type size in bytes */
uint32_t ctt_lsizelo; /* low 32 bits of type size in bytes */
-} ctf_type_t;
+};
#define ctt_size _u._size /* for fundamental types that have a size */
#define ctt_type _u._type /* for types that reference another type */
@@ -754,29 +766,29 @@ typedef struct ctf_type {
Type sizes are stored in
.Sy bytes .
The basic small form uses a
-.Sy uint16_t
+.Sy uint32_t
to store the number of bytes.
-If the number of bytes in a structure would exceed 0xfffe, then the alternate
-form, the
-.Sy ctf_type_t ,
+If the number of bytes in a structure would exceed 0xfffffffe, then the
+alternate form, the
+.Sy struct ctf_type_v3 ,
is used instead.
To indicate that the larger form is being used, the member
.Em ctt_size
is set to value of
-.Sy CTF_LSIZE_SENT
-(0xffff).
+.Sy CTF_V3_LSIZE_SENT
+(0xffffffff).
In general, when going through the type section, consumers use the
-.Sy ctf_type_t
+.Sy struct ctf_type_v3
structure, but pay attention to the value of the member
.Em ctt_size
-to determine whether they should increment their scan by the size of the
-.Sy ctf_stype_t
+to determine whether they should increment their scan by the size of
+.Sy struct ctf_stype_v3
or
-.Sy ctf_type_t .
+.Sy struct ctf_type_v3 .
Not all kinds of types use
.Sy ctt_size .
Those which do not, will always use the
-.Sy ctf_stype_t
+.Sy struct ctf_stype_v3
structure.
The individual sections for each kind have more information.
.Lp
@@ -798,7 +810,7 @@ The next member, the
is encoded as described in the section
.Sx Type Encoding .
The type's kind tells us how to interpret the remaining data in the
-.Sy ctf_type_t
+.Sy struct ctf_type_v3
and any variable length data that may exist.
The rest of this section will be broken down into the interpretation of the
various kinds.
@@ -936,11 +948,11 @@ With arrays, the
member is set to zero.
The structure that follows an array is defined as:
.Bd -literal
-typedef struct ctf_array {
- uint16_t cta_contents; /* reference to type of array contents */
- uint16_t cta_index; /* reference to type of array index */
+struct ctf_array_v3 {
+ uint32_t cta_contents; /* reference to type of array contents */
+ uint32_t cta_index; /* reference to type of array index */
uint32_t cta_nelems; /* number of elements */
-} ctf_array_t;
+};
.Ed
.Lp
The
@@ -948,7 +960,7 @@ The
and
.Em cta_index
members of the
-.Sy ctf_array_t
+.Sy struct ctf_array_v3
are type identifiers which are encoded as per the section
.Sx Type Identifiers .
The member
@@ -971,17 +983,23 @@ member is not used here.
The variable argument list contains the type identifiers for the arguments of
the function, if any.
Each one is represented by a
-.Sy uint16_t
+.Sy uint32_t
and encoded according to the
.Sx Type Identifiers
section.
If the function's last argument is of type varargs, then it is also written out,
but the type identifier is zero.
This is included in the count of the function's arguments.
-An extra type identifier may follow the argument and return type identifiers
-in order to maintain four-byte alignment for the following type definition.
+In
+.Nm
+version 2, an extra type identifier may follow the argument and return type
+identifiers in order to maintain four-byte alignment for the following type
+definition.
Such a type identifier is not included in the argument count and has a value
of zero.
+In
+.Nm
+version 3, four-byte alignment occurs naturally and no padding is used.
.Ss Encoding of Structures and Unions
Structures and Unions, which are encoded with
.Sy CTF_K_STRUCT
@@ -1000,23 +1018,22 @@ is the size of the structure and union.
There are two different structures which are used to encode members in the
variable list.
When the size of a structure or union is greater than or equal to the large
-member threshold, 8192, then a different structure is used to encode the member,
-all members are encoded using the same structure.
+member threshold, 536870912, then a different structure is used to encode the
+member; all members are encoded using the same structure.
The structure for members is as follows:
.Bd -literal
-typedef struct ctf_member {
+struct ctf_member_v3 {
uint32_t ctm_name; /* reference to name in string table */
- uint16_t ctm_type; /* reference to type of member */
- uint16_t ctm_offset; /* offset of this member in bits */
-} ctf_member_t;
+ uint32_t ctm_type; /* reference to type of member */
+ uint32_t ctm_offset; /* offset of this member in bits */
+};
-typedef struct ctf_lmember {
+struct ctf_lmember_v3 {
uint32_t ctlm_name; /* reference to name in string table */
- uint16_t ctlm_type; /* reference to type of member */
- uint16_t ctlm_pad; /* padding */
+ uint32_t ctlm_type; /* reference to type of member */
uint32_t ctlm_offsethi; /* high 32 bits of member offset in bits */
uint32_t ctlm_offsetlo; /* low 32 bits of member offset in bits */
-} ctf_lmember_t;
+};
.Ed
.Lp
Both the
@@ -1045,13 +1062,13 @@ at which the member begins.
Note that a compiler may lay out a type with padding.
This means that the difference in offset between two consecutive members may be
larger than the size of the member.
-When the size of the overall structure is strictly less than 8192 bytes, the
-normal structure,
-.Sy ctf_member_t ,
+When the size of the overall structure is strictly less than 536870912 bytes,
+the normal structure,
+.Sy struct ctf_member_v3 ,
is used and the offset in bits is stored in the member
.Em ctm_offset .
-However, when the size of the structure is greater than or equal to 8192 bytes,
-then the number of bits is split into two 32-bit quantities.
+However, when the size of the structure is greater than or equal to 536870912
+bytes, then the number of bits is split into two 32-bit quantities.
One member,
.Em ctlm_offsethi ,
represents the upper 32 bits of the offset, while the other member,
@@ -1114,7 +1131,7 @@ actual type in the parent, otherwise the definition may be in another
.Nm
container or may not be known at all.
The only member of the
-.Sy ctf_type_t
+.Sy struct ctf_type_v3
that matters for a forward declaration is the
.Em ctt_name
which points to the name of the forward reference in the string table as
@@ -1216,6 +1233,9 @@ The type of the section must be
The section should have a link set to the symbol table and its address
alignment must be 4.
.Sh SEE ALSO
+.Xr ctfconvert 1 ,
+.Xr ctfdump 1 ,
+.Xr ctfmerge 1 ,
.Xr dtrace 1 ,
.Xr elf 3 ,
.Xr gelf 3 ,
diff --git a/cddl/contrib/opensolaris/lib/libctf/common/ctf_lib.c b/cddl/contrib/opensolaris/lib/libctf/common/ctf_lib.c
index f48c09cce0e2..e1ba993a09a9 100644
--- a/cddl/contrib/opensolaris/lib/libctf/common/ctf_lib.c
+++ b/cddl/contrib/opensolaris/lib/libctf/common/ctf_lib.c
@@ -245,7 +245,8 @@ ctf_fdopen(int fd, int *errp)
*/
if (nbytes >= (ssize_t) sizeof (ctf_preamble_t) &&
hdr.ctf.ctp_magic == CTF_MAGIC) {
- if (hdr.ctf.ctp_version > CTF_VERSION)
+ if (hdr.ctf.ctp_version != CTF_VERSION_2 &&
+ hdr.ctf.ctp_version != CTF_VERSION_3)
return (ctf_set_open_errno(errp, ECTF_CTFVERS));
ctfsect.cts_data = mmap64(NULL, st.st_size, PROT_READ,
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 811c88bbf0ad..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);
}
/*
@@ -2621,7 +3742,7 @@ dt_unring_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf)
bcopy(buf->dtbd_data, ndp, buf->dtbd_oldest);
dt_free(dtp, buf->dtbd_data);
- buf->dtbd_oldest = 0;
+ buf->dtbd_oldest = misalign;
buf->dtbd_data = newdata;
buf->dtbd_size += misalign;
@@ -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 482da920b754..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;
@@ -1470,7 +1483,7 @@ alloc:
dtyp->dty_dst, ctf_lookup_by_name(dmp->dm_ctfp,
dtyp->dty_src)) == CTF_ERR) {
dt_dprintf("failed to add typedef %s %s to D "
- "container: %s", dtyp->dty_src, dtyp->dty_dst,
+ "container: %s\n", dtyp->dty_src, dtyp->dty_dst,
ctf_errmsg(ctf_errno(dmp->dm_ctfp)));
return (set_open_errno(dtp, errp, EDT_CTF));
}
@@ -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 2d8c24a0a596..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;
@@ -694,7 +695,6 @@ dt_printf(dtrace_hdl_t *dtp, FILE *fp, const char *format, ...)
va_copy(ap2, ap);
n = vfprintf(fp, format, ap2);
- fflush(fp);
va_end(ap2);
va_end(ap);
@@ -993,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/lib/libdtrace/mips/dt_isadep.c b/cddl/contrib/opensolaris/lib/libdtrace/mips/dt_isadep.c
deleted file mode 100644
index 1aeb95f3dfd7..000000000000
--- a/cddl/contrib/opensolaris/lib/libdtrace/mips/dt_isadep.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <string.h>
-#include <libgen.h>
-
-#include <dt_impl.h>
-#include <dt_pid.h>
-
-/*ARGSUSED*/
-int
-dt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
- fasttrap_probe_spec_t *ftp, const GElf_Sym *symp)
-{
-
- dt_dprintf("%s: unimplemented\n", __func__);
- return (DT_PROC_ERR);
-}
-
-int
-dt_pid_create_return_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
- fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, uint64_t *stret)
-{
-
- dt_dprintf("%s: unimplemented\n", __func__);
- return (DT_PROC_ERR);
-}
-
-/*ARGSUSED*/
-int
-dt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
- fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, ulong_t off)
-{
-
- dt_dprintf("%s: unimplemented\n", __func__);
- return (DT_PROC_ERR);
-}
-
-/*ARGSUSED*/
-int
-dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
- fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern)
-{
-
- dt_dprintf("%s: unimplemented\n", __func__);
- return (DT_PROC_ERR);
-}
diff --git a/cddl/contrib/opensolaris/tools/ctf/common/ctf_headers.h b/cddl/contrib/opensolaris/tools/ctf/common/ctf_headers.h
index b00b8fd9a650..ca66b9bf5486 100644
--- a/cddl/contrib/opensolaris/tools/ctf/common/ctf_headers.h
+++ b/cddl/contrib/opensolaris/tools/ctf/common/ctf_headers.h
@@ -65,7 +65,7 @@
* an explicit path #include.
*/
-#include <uts/common/sys/ctf.h>
+#include <sys/ctf.h>
#include <uts/common/sys/ctf_api.h>
#include <lib/libctf/common/libctf.h>
diff --git a/cddl/contrib/opensolaris/tools/ctf/common/memory.c b/cddl/contrib/opensolaris/tools/ctf/common/memory.c
index e16044a8b672..66296c5b114d 100644
--- a/cddl/contrib/opensolaris/tools/ctf/common/memory.c
+++ b/cddl/contrib/opensolaris/tools/ctf/common/memory.c
@@ -44,6 +44,20 @@ memory_bailout(void)
exit(1);
}
+int
+xasprintf(char **s, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vasprintf(s, fmt, ap);
+ va_end(ap);
+ if (ret == -1)
+ memory_bailout();
+ return (ret);
+}
+
void *
xmalloc(size_t size)
{
diff --git a/cddl/contrib/opensolaris/tools/ctf/common/memory.h b/cddl/contrib/opensolaris/tools/ctf/common/memory.h
index 88ca31bec65a..72706b5f7fdb 100644
--- a/cddl/contrib/opensolaris/tools/ctf/common/memory.h
+++ b/cddl/contrib/opensolaris/tools/ctf/common/memory.h
@@ -39,6 +39,7 @@
extern "C" {
#endif
+int xasprintf(char **, const char *, ...);
void *xmalloc(size_t);
void *xcalloc(size_t);
char *xstrdup(const char *);
diff --git a/cddl/contrib/opensolaris/tools/ctf/common/utils.c b/cddl/contrib/opensolaris/tools/ctf/common/utils.c
index b9db1a870165..fda29486d94b 100644
--- a/cddl/contrib/opensolaris/tools/ctf/common/utils.c
+++ b/cddl/contrib/opensolaris/tools/ctf/common/utils.c
@@ -24,8 +24,7 @@
* All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
+#include <err.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -36,55 +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
-vwarn(const char *format, va_list alist)
-{
- int err = errno;
-
- if (pname != NULL)
- (void) fprintf(stderr, "%s: ", pname);
-
- (void) vfprintf(stderr, format, alist);
-
- if (strchr(format, '\n') == NULL)
- (void) fprintf(stderr, ": %s\n", strerror(err));
-}
-
-/*PRINTFLIKE1*/
-void
-warn(const char *format, ...)
-{
- va_list alist;
-
- va_start(alist, format);
- vwarn(format, alist);
- va_end(alist);
-}
-
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 9b07361a53ab..6918bdab89aa 100644
--- a/cddl/contrib/opensolaris/tools/ctf/common/utils.h
+++ b/cddl/contrib/opensolaris/tools/ctf/common/utils.h
@@ -39,13 +39,9 @@ extern "C" {
#define E_ERROR 1 /* Exit status for error */
#define E_USAGE 2 /* Exit status for usage error */
-extern void vwarn(const char *, va_list);
-extern void warn(const char *, ...);
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/compare.c b/cddl/contrib/opensolaris/tools/ctf/cvt/compare.c
deleted file mode 100644
index 26037f8a537a..000000000000
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/compare.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * This is a test program designed to catch mismerges and mistranslations from
- * stabs to CTF.
- *
- * Given a file with stabs data and a file with CTF data, determine whether
- * or not all of the data structures and objects described by the stabs data
- * are present in the CTF data.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "ctftools.h"
-
-char *progname;
-int debug_level = DEBUG_LEVEL;
-
-static void
-usage(void)
-{
- fprintf(stderr, "Usage: %s ctf_file stab_file\n", progname);
-}
-
-int
-main(int argc, char **argv)
-{
- tdata_t *ctftd, *stabrtd, *stabtd, *difftd;
- char *ctfname, *stabname;
- int new;
-
- progname = argv[0];
-
- if (argc != 3) {
- usage();
- exit(2);
- }
-
- ctfname = argv[1];
- stabname = argv[2];
-
- stabrtd = tdata_new();
- stabtd = tdata_new();
- difftd = tdata_new();
-
- if (read_stabs(stabrtd, stabname, 0) != 0)
- merge_into_master(stabrtd, stabtd, NULL, 1);
- else if (read_ctf(&stabname, 1, NULL, read_ctf_save_cb, &stabtd, 0)
- == 0)
- terminate("%s doesn't have stabs or CTF\n", stabname);
-
- if (read_ctf(&ctfname, 1, NULL, read_ctf_save_cb, &ctftd, 0) == 0)
- terminate("%s doesn't contain CTF data\n", ctfname);
-
- merge_into_master(stabtd, ctftd, difftd, 0);
-
- if ((new = hash_count(difftd->td_iihash)) != 0) {
- (void) hash_iter(difftd->td_iihash, (int (*)())iidesc_dump,
- NULL);
- terminate("%s grew by %d\n", stabname, new);
- }
-
- return (0);
-}
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c b/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
index 5cd2de9f43ea..01b18093443b 100644
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
+++ b/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
@@ -58,8 +58,7 @@ struct ctf_buf {
caddr_t ctb_end; /* pointer to end of buffer */
caddr_t ctb_ptr; /* pointer to empty buffer space */
size_t ctb_size; /* size of buffer */
- int nptent; /* number of processed types */
- int ntholes; /* number of type holes */
+ uint_t nptent; /* number of processed types */
};
/*
@@ -165,10 +164,10 @@ write_label(void *arg1, void *arg2)
static void
write_objects(iidesc_t *idp, ctf_buf_t *b)
{
- ushort_t id = (idp ? idp->ii_dtype->t_id : 0);
+ uint_t id = (idp ? idp->ii_dtype->t_id : 0);
if (target_requires_swap) {
- SWAP_16(id);
+ SWAP_32(id);
}
ctf_buf_write(b, &id, sizeof (id));
@@ -179,8 +178,8 @@ write_objects(iidesc_t *idp, ctf_buf_t *b)
static void
write_functions(iidesc_t *idp, ctf_buf_t *b)
{
- ushort_t fdata[2];
- ushort_t id;
+ uint_t fdata[2];
+ uint_t id;
int nargs;
int i;
@@ -194,17 +193,17 @@ write_functions(iidesc_t *idp, ctf_buf_t *b)
nargs = idp->ii_nargs + (idp->ii_vargs != 0);
- if (nargs > CTF_MAX_VLEN) {
+ if (nargs > CTF_V3_MAX_VLEN) {
terminate("function %s has too many args: %d > %d\n",
- idp->ii_name, nargs, CTF_MAX_VLEN);
+ idp->ii_name, nargs, CTF_V3_MAX_VLEN);
}
- fdata[0] = CTF_TYPE_INFO(CTF_K_FUNCTION, 1, nargs);
+ fdata[0] = CTF_V3_TYPE_INFO(CTF_K_FUNCTION, 1, nargs);
fdata[1] = idp->ii_dtype->t_id;
if (target_requires_swap) {
- SWAP_16(fdata[0]);
- SWAP_16(fdata[1]);
+ SWAP_32(fdata[0]);
+ SWAP_32(fdata[1]);
}
ctf_buf_write(b, fdata, sizeof (fdata));
@@ -213,7 +212,7 @@ write_functions(iidesc_t *idp, ctf_buf_t *b)
id = idp->ii_args[i]->t_id;
if (target_requires_swap) {
- SWAP_16(id);
+ SWAP_32(id);
}
ctf_buf_write(b, &id, sizeof (id));
@@ -234,29 +233,29 @@ write_functions(iidesc_t *idp, ctf_buf_t *b)
* doesn't need to care.
*/
static void
-write_sized_type_rec(ctf_buf_t *b, ctf_type_t *ctt, size_t size)
+write_sized_type_rec(ctf_buf_t *b, struct ctf_type_v3 *ctt, size_t size)
{
- if (size > CTF_MAX_SIZE) {
- ctt->ctt_size = CTF_LSIZE_SENT;
+ if (size > CTF_V3_MAX_SIZE) {
+ ctt->ctt_size = CTF_V3_LSIZE_SENT;
ctt->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);
ctt->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);
if (target_requires_swap) {
SWAP_32(ctt->ctt_name);
- SWAP_16(ctt->ctt_info);
- SWAP_16(ctt->ctt_size);
+ SWAP_32(ctt->ctt_info);
+ SWAP_32(ctt->ctt_size);
SWAP_32(ctt->ctt_lsizehi);
SWAP_32(ctt->ctt_lsizelo);
}
ctf_buf_write(b, ctt, sizeof (*ctt));
} else {
- ctf_stype_t *cts = (ctf_stype_t *)ctt;
+ struct ctf_stype_v3 *cts = (struct ctf_stype_v3 *)ctt;
- cts->ctt_size = (ushort_t)size;
+ cts->ctt_size = size;
if (target_requires_swap) {
SWAP_32(cts->ctt_name);
- SWAP_16(cts->ctt_info);
- SWAP_16(cts->ctt_size);
+ SWAP_32(cts->ctt_info);
+ SWAP_32(cts->ctt_size);
}
ctf_buf_write(b, cts, sizeof (*cts));
@@ -264,14 +263,14 @@ write_sized_type_rec(ctf_buf_t *b, ctf_type_t *ctt, size_t size)
}
static void
-write_unsized_type_rec(ctf_buf_t *b, ctf_type_t *ctt)
+write_unsized_type_rec(ctf_buf_t *b, struct ctf_type_v3 *ctt)
{
- ctf_stype_t *cts = (ctf_stype_t *)ctt;
+ struct ctf_stype_v3 *cts = (struct ctf_stype_v3 *)ctt;
if (target_requires_swap) {
SWAP_32(cts->ctt_name);
- SWAP_16(cts->ctt_info);
- SWAP_16(cts->ctt_size);
+ SWAP_32(cts->ctt_info);
+ SWAP_32(cts->ctt_size);
}
ctf_buf_write(b, cts, sizeof (*cts));
@@ -292,14 +291,12 @@ write_type(void *arg1, void *arg2)
int isroot = tp->t_flags & TDESC_F_ISROOT;
int i;
- ctf_type_t ctt;
- ctf_array_t cta;
- ctf_member_t ctm;
- ctf_lmember_t ctlm;
- ctf_enum_t cte;
- ushort_t id;
-
- ctlm.ctlm_pad = 0;
+ struct ctf_type_v3 ctt;
+ struct ctf_array_v3 cta;
+ struct ctf_member_v3 ctm;
+ struct ctf_lmember_v3 ctlm;
+ struct ctf_enum cte;
+ uint_t id;
/*
* There shouldn't be any holes in the type list (where a hole is
@@ -308,13 +305,13 @@ write_type(void *arg1, void *arg2)
* fake entries to fill the holes, or we won't be able to reconstruct
* the tree from the written data.
*/
- if (++b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) {
+ if (++b->nptent < CTF_V3_TYPE_TO_INDEX(tp->t_id)) {
debug(2, "genctf: type hole from %d < x < %d\n",
- b->nptent - 1, CTF_TYPE_TO_INDEX(tp->t_id));
+ b->nptent - 1, CTF_V3_TYPE_TO_INDEX(tp->t_id));
ctt.ctt_name = CTF_TYPE_NAME(CTF_STRTAB_0, 0);
- ctt.ctt_info = CTF_TYPE_INFO(0, 0, 0);
- while (b->nptent < CTF_TYPE_TO_INDEX(tp->t_id)) {
+ ctt.ctt_info = CTF_V3_TYPE_INFO(0, 0, 0);
+ while (b->nptent < CTF_V3_TYPE_TO_INDEX(tp->t_id)) {
write_sized_type_rec(b, &ctt, 0);
b->nptent++;
}
@@ -327,10 +324,10 @@ write_type(void *arg1, void *arg2)
case INTRINSIC:
ip = tp->t_intr;
if (ip->intr_type == INTR_INT)
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_INTEGER,
+ ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_INTEGER,
isroot, 1);
else
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FLOAT, isroot, 1);
+ ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_FLOAT, isroot, 1);
write_sized_type_rec(b, &ctt, tp->t_size);
encoding = 0;
@@ -355,21 +352,21 @@ write_type(void *arg1, void *arg2)
break;
case POINTER:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_POINTER, isroot, 0);
+ ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_POINTER, isroot, 0);
ctt.ctt_type = tp->t_tdesc->t_id;
write_unsized_type_rec(b, &ctt);
break;
case ARRAY:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, isroot, 1);
+ ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_ARRAY, isroot, 1);
write_sized_type_rec(b, &ctt, tp->t_size);
cta.cta_contents = tp->t_ardef->ad_contents->t_id;
cta.cta_index = tp->t_ardef->ad_idxtype->t_id;
cta.cta_nelems = tp->t_ardef->ad_nelems;
if (target_requires_swap) {
- SWAP_16(cta.cta_contents);
- SWAP_16(cta.cta_index);
+ SWAP_32(cta.cta_contents);
+ SWAP_32(cta.cta_index);
SWAP_32(cta.cta_nelems);
}
ctf_buf_write(b, &cta, sizeof (cta));
@@ -380,19 +377,19 @@ write_type(void *arg1, void *arg2)
for (i = 0, mp = tp->t_members; mp != NULL; mp = mp->ml_next)
i++; /* count up struct or union members */
- if (i > CTF_MAX_VLEN) {
+ if (i > CTF_V3_MAX_VLEN) {
terminate("sou %s has too many members: %d > %d\n",
- tdesc_name(tp), i, CTF_MAX_VLEN);
+ tdesc_name(tp), i, CTF_V3_MAX_VLEN);
}
if (tp->t_type == STRUCT)
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, isroot, i);
+ ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_STRUCT, isroot, i);
else
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, isroot, i);
+ ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_UNION, isroot, i);
write_sized_type_rec(b, &ctt, tp->t_size);
- if (tp->t_size < CTF_LSTRUCT_THRESH) {
+ if (tp->t_size < CTF_V3_LSTRUCT_THRESH) {
for (mp = tp->t_members; mp != NULL; mp = mp->ml_next) {
offset = strtab_insert(&b->ctb_strtab,
mp->ml_name);
@@ -403,8 +400,8 @@ write_type(void *arg1, void *arg2)
ctm.ctm_offset = mp->ml_offset;
if (target_requires_swap) {
SWAP_32(ctm.ctm_name);
- SWAP_16(ctm.ctm_type);
- SWAP_16(ctm.ctm_offset);
+ SWAP_32(ctm.ctm_type);
+ SWAP_32(ctm.ctm_offset);
}
ctf_buf_write(b, &ctm, sizeof (ctm));
}
@@ -423,7 +420,7 @@ write_type(void *arg1, void *arg2)
if (target_requires_swap) {
SWAP_32(ctlm.ctlm_name);
- SWAP_16(ctlm.ctlm_type);
+ SWAP_32(ctlm.ctlm_type);
SWAP_32(ctlm.ctlm_offsethi);
SWAP_32(ctlm.ctlm_offsetlo);
}
@@ -437,11 +434,11 @@ write_type(void *arg1, void *arg2)
for (i = 0, ep = tp->t_emem; ep != NULL; ep = ep->el_next)
i++; /* count up enum members */
- if (i > CTF_MAX_VLEN) {
- i = CTF_MAX_VLEN;
+ if (i > CTF_V3_MAX_VLEN) {
+ i = CTF_V3_MAX_VLEN;
}
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, isroot, i);
+ ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_ENUM, isroot, i);
write_sized_type_rec(b, &ctt, tp->t_size);
for (ep = tp->t_emem; ep != NULL && i > 0; ep = ep->el_next) {
@@ -460,25 +457,25 @@ write_type(void *arg1, void *arg2)
break;
case FORWARD:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FORWARD, isroot, 0);
+ ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_FORWARD, isroot, 0);
ctt.ctt_type = 0;
write_unsized_type_rec(b, &ctt);
break;
case TYPEDEF:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, isroot, 0);
+ ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_TYPEDEF, isroot, 0);
ctt.ctt_type = tp->t_tdesc->t_id;
write_unsized_type_rec(b, &ctt);
break;
case VOLATILE:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_VOLATILE, isroot, 0);
+ ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_VOLATILE, isroot, 0);
ctt.ctt_type = tp->t_tdesc->t_id;
write_unsized_type_rec(b, &ctt);
break;
case CONST:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_CONST, isroot, 0);
+ ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_CONST, isroot, 0);
ctt.ctt_type = tp->t_tdesc->t_id;
write_unsized_type_rec(b, &ctt);
break;
@@ -486,12 +483,12 @@ write_type(void *arg1, void *arg2)
case FUNCTION:
i = tp->t_fndef->fn_nargs + tp->t_fndef->fn_vargs;
- if (i > CTF_MAX_VLEN) {
+ if (i > CTF_V3_MAX_VLEN) {
terminate("function %s has too many args: %d > %d\n",
- tdesc_name(tp), i, CTF_MAX_VLEN);
+ tdesc_name(tp), i, CTF_V3_MAX_VLEN);
}
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, isroot, i);
+ ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_FUNCTION, isroot, i);
ctt.ctt_type = tp->t_fndef->fn_ret->t_id;
write_unsized_type_rec(b, &ctt);
@@ -499,7 +496,7 @@ write_type(void *arg1, void *arg2)
id = tp->t_fndef->fn_args[i]->t_id;
if (target_requires_swap) {
- SWAP_16(id);
+ SWAP_32(id);
}
ctf_buf_write(b, &id, sizeof (id));
@@ -511,14 +508,10 @@ write_type(void *arg1, void *arg2)
i++;
}
- if (i & 1) {
- id = 0;
- ctf_buf_write(b, &id, sizeof (id));
- }
break;
case RESTRICT:
- ctt.ctt_info = CTF_TYPE_INFO(CTF_K_RESTRICT, isroot, 0);
+ ctt.ctt_info = CTF_V3_TYPE_INFO(CTF_K_RESTRICT, isroot, 0);
ctt.ctt_type = tp->t_tdesc->t_id;
write_unsized_type_rec(b, &ctt);
break;
@@ -704,7 +697,7 @@ ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress)
* integers; we pad these out to the next 4-byte boundary if needed.
*/
h.cth_magic = CTF_MAGIC;
- h.cth_version = CTF_VERSION;
+ h.cth_version = CTF_VERSION_3;
h.cth_flags = do_compress ? CTF_F_COMPRESS : 0;
h.cth_parlabel = strtab_insert(&buf->ctb_strtab,
iiburst->iib_td->td_parlabel);
@@ -761,14 +754,46 @@ ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress)
}
static void
-get_ctt_size(ctf_type_t *ctt, size_t *sizep, size_t *incrementp)
+get_ctt_info(ctf_header_t *h, void *v, uint_t *kind, uint_t *vlen, int *isroot)
+{
+ if (h->cth_version == CTF_VERSION_2) {
+ struct ctf_type_v2 *ctt = v;
+
+ *kind = CTF_V2_INFO_KIND(ctt->ctt_info);
+ *vlen = CTF_V2_INFO_VLEN(ctt->ctt_info);
+ *isroot = CTF_V2_INFO_ISROOT(ctt->ctt_info);
+ } else {
+ struct ctf_type_v3 *ctt = v;
+
+ *kind = CTF_V3_INFO_KIND(ctt->ctt_info);
+ *vlen = CTF_V3_INFO_VLEN(ctt->ctt_info);
+ *isroot = CTF_V3_INFO_ISROOT(ctt->ctt_info);
+ }
+}
+
+static void
+get_ctt_size(ctf_header_t *h, void *v, size_t *sizep, size_t *incrementp)
{
- if (ctt->ctt_size == CTF_LSIZE_SENT) {
- *sizep = (size_t)CTF_TYPE_LSIZE(ctt);
- *incrementp = sizeof (ctf_type_t);
+ if (h->cth_version == CTF_VERSION_2) {
+ struct ctf_type_v2 *ctt = v;
+
+ if (ctt->ctt_size == CTF_V2_LSIZE_SENT) {
+ *sizep = (size_t)CTF_TYPE_LSIZE(ctt);
+ *incrementp = sizeof (struct ctf_type_v2);
+ } else {
+ *sizep = ctt->ctt_size;
+ *incrementp = sizeof (struct ctf_stype_v2);
+ }
} else {
- *sizep = ctt->ctt_size;
- *incrementp = sizeof (ctf_stype_t);
+ struct ctf_type_v3 *ctt = v;
+
+ if (ctt->ctt_size == CTF_V3_LSIZE_SENT) {
+ *sizep = (size_t)CTF_TYPE_LSIZE(ctt);
+ *incrementp = sizeof (struct ctf_type_v3);
+ } else {
+ *sizep = ctt->ctt_size;
+ *incrementp = sizeof (struct ctf_stype_v3);
+ }
}
}
@@ -776,18 +801,22 @@ static int
count_types(ctf_header_t *h, caddr_t data)
{
caddr_t dptr = data + h->cth_typeoff;
+ uint_t version = h->cth_version;
+ size_t idwidth;
int count = 0;
+ idwidth = version == CTF_VERSION_2 ? 2 : 4;
dptr = data + h->cth_typeoff;
while (dptr < data + h->cth_stroff) {
void *v = (void *) dptr;
- ctf_type_t *ctt = v;
- size_t vlen = CTF_INFO_VLEN(ctt->ctt_info);
size_t size, increment;
+ uint_t vlen, kind;
+ int isroot;
- get_ctt_size(ctt, &size, &increment);
+ get_ctt_info(h, v, &kind, &vlen, &isroot);
+ get_ctt_size(h, v, &size, &increment);
- switch (CTF_INFO_KIND(ctt->ctt_info)) {
+ switch (kind) {
case CTF_K_INTEGER:
case CTF_K_FLOAT:
dptr += 4;
@@ -799,17 +828,31 @@ count_types(ctf_header_t *h, caddr_t data)
case CTF_K_CONST:
case CTF_K_RESTRICT:
case CTF_K_FUNCTION:
- dptr += sizeof (ushort_t) * (vlen + (vlen & 1));
+ dptr += idwidth * vlen;
break;
case CTF_K_ARRAY:
- dptr += sizeof (ctf_array_t);
+ if (version == CTF_VERSION_2)
+ dptr += sizeof (struct ctf_array_v2);
+ else
+ dptr += sizeof (struct ctf_array_v3);
break;
case CTF_K_STRUCT:
case CTF_K_UNION:
- if (size < CTF_LSTRUCT_THRESH)
- dptr += sizeof (ctf_member_t) * vlen;
- else
- dptr += sizeof (ctf_lmember_t) * vlen;
+ if (version == CTF_VERSION_2) {
+ if (size < CTF_V2_LSTRUCT_THRESH)
+ dptr += sizeof (struct ctf_member_v2) *
+ vlen;
+ else
+ dptr += sizeof (struct ctf_lmember_v2) *
+ vlen;
+ } else {
+ if (size < CTF_V3_LSTRUCT_THRESH)
+ dptr += sizeof (struct ctf_member_v3) *
+ vlen;
+ else
+ dptr += sizeof (struct ctf_lmember_v3) *
+ vlen;
+ }
break;
case CTF_K_ENUM:
dptr += sizeof (ctf_enum_t) * vlen;
@@ -818,7 +861,7 @@ count_types(ctf_header_t *h, caddr_t data)
break;
default:
parseterminate("Unknown CTF type %d (#%d) at %#x",
- CTF_INFO_KIND(ctt->ctt_info), count, dptr - data);
+ kind, count, dptr - data);
}
dptr += increment;
@@ -895,11 +938,15 @@ resurrect_objects(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
caddr_t buf = ctfdata + h->cth_objtoff;
size_t bufsz = h->cth_funcoff - h->cth_objtoff;
caddr_t dptr;
+ size_t idwidth;
+
+ idwidth = h->cth_version == CTF_VERSION_2 ? 2 : 4;
symit_reset(si);
- for (dptr = buf; dptr < buf + bufsz; dptr += 2) {
- void *v = (void *) dptr;
- ushort_t id = *((ushort_t *)v);
+ for (dptr = buf; dptr < buf + bufsz; dptr += idwidth) {
+ uint32_t id = 0;
+
+ memcpy(&id, (void *) dptr, idwidth);
iidesc_t *ii;
GElf_Sym *sym;
@@ -912,7 +959,7 @@ resurrect_objects(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
if (id == 0) {
debug(3, "Skipping null object\n");
continue;
- } else if (id >= tdsize) {
+ } else if (id >= (uint_t)tdsize) {
parseterminate("Reference to invalid type %d", id);
}
@@ -937,18 +984,21 @@ resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
{
caddr_t buf = ctfdata + h->cth_funcoff;
size_t bufsz = h->cth_typeoff - h->cth_funcoff;
+ size_t idwidth;
caddr_t dptr = buf;
iidesc_t *ii;
- ushort_t info;
- ushort_t retid;
GElf_Sym *sym;
int i;
+ idwidth = h->cth_version == CTF_VERSION_2 ? 2 : 4;
+
symit_reset(si);
while (dptr < buf + bufsz) {
- void *v = (void *) dptr;
- info = *((ushort_t *)v);
- dptr += 2;
+ uint32_t id, info, retid;
+
+ info = 0;
+ memcpy(&info, (void *) dptr, idwidth);
+ dptr += idwidth;
if (!(sym = symit_next(si, STT_FUNC)) && info != 0)
parseterminate("Unexpected end of function symbols");
@@ -959,11 +1009,11 @@ resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
continue;
}
- v = (void *) dptr;
- retid = *((ushort_t *)v);
- dptr += 2;
+ retid = 0;
+ memcpy(&retid, (void *) dptr, idwidth);
+ dptr += idwidth;
- if (retid >= tdsize)
+ if (retid >= (uint_t)tdsize)
parseterminate("Reference to invalid type %d", retid);
ii = iidesc_new(symit_name(si));
@@ -973,15 +1023,18 @@ resurrect_functions(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
ii->ii_owner = xstrdup(symit_curfile(si));
} else
ii->ii_type = II_GFUN;
- ii->ii_nargs = CTF_INFO_VLEN(info);
+ if (h->cth_version == CTF_VERSION_2)
+ ii->ii_nargs = CTF_V2_INFO_VLEN(info);
+ else
+ ii->ii_nargs = CTF_V3_INFO_VLEN(info);
if (ii->ii_nargs)
ii->ii_args =
xmalloc(sizeof (tdesc_t *) * ii->ii_nargs);
- for (i = 0; i < ii->ii_nargs; i++, dptr += 2) {
- v = (void *) dptr;
- ushort_t id = *((ushort_t *)v);
- if (id >= tdsize)
+ for (i = 0; i < ii->ii_nargs; i++, dptr += idwidth) {
+ id = 0;
+ memcpy(&id, (void *) dptr, idwidth);
+ if (id >= (uint_t)tdsize)
parseterminate("Reference to invalid type %d",
id);
ii->ii_args[i] = tdarr[id];
@@ -1011,55 +1064,65 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
tdesc_t *tdp;
uint_t data;
uint_t encoding;
- size_t size, increment;
+ size_t idwidth, size, increment;
int tcnt;
int iicnt = 0;
tid_t tid, argid;
- int kind, vlen;
- int i;
+ int isroot, kind, vlen;
+ int i, version;
elist_t **epp;
mlist_t **mpp;
intr_t *ip;
- ctf_type_t *ctt;
- ctf_array_t *cta;
- ctf_enum_t *cte;
+ version = h->cth_version;
+ idwidth = version == CTF_VERSION_2 ? 2 : 4;
/*
* A maxid of zero indicates a request to resurrect all types, so reset
* maxid to the maximum type id.
*/
- if (maxid == 0)
- maxid = CTF_MAX_TYPE;
+ if (maxid == 0) {
+ maxid = version == CTF_VERSION_2 ?
+ CTF_V2_MAX_TYPE : CTF_V3_MAX_TYPE;
+ }
for (dptr = buf, tcnt = 0, tid = 1; dptr < buf + bufsz; tcnt++, tid++) {
+ ctf_enum_t *cte;
+ uint_t name, type;
+ void *v;
+
if (tid > maxid)
break;
if (tid >= tdsize)
parseterminate("Reference to invalid type %d", tid);
- void *v = (void *) dptr;
- ctt = v;
+ get_ctt_info(h, dptr, &kind, &vlen, &isroot);
+ get_ctt_size(h, dptr, &size, &increment);
+ if (version == CTF_VERSION_2) {
+ struct ctf_type_v2 *ctt = (void *) dptr;
- get_ctt_size(ctt, &size, &increment);
+ name = ctt->ctt_name;
+ type = ctt->ctt_type;
+ } else {
+ struct ctf_type_v3 *ctt = (void *) dptr;
+
+ name = ctt->ctt_name;
+ type = ctt->ctt_type;
+ }
dptr += increment;
tdp = tdarr[tid];
- if (CTF_NAME_STID(ctt->ctt_name) != CTF_STRTAB_0)
+ if (CTF_NAME_STID(name) != CTF_STRTAB_0)
parseterminate(
"Unable to cope with non-zero strtab id");
- if (CTF_NAME_OFFSET(ctt->ctt_name) != 0) {
- tdp->t_name =
- xstrdup(sbuf + CTF_NAME_OFFSET(ctt->ctt_name));
+ if (CTF_NAME_OFFSET(name) != 0) {
+ tdp->t_name = xstrdup(sbuf + CTF_NAME_OFFSET(name));
} else
tdp->t_name = NULL;
- kind = CTF_INFO_KIND(ctt->ctt_info);
- vlen = CTF_INFO_VLEN(ctt->ctt_info);
-
switch (kind) {
case CTF_K_INTEGER:
tdp->t_type = INTRINSIC;
@@ -1106,62 +1169,110 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
case CTF_K_POINTER:
tdp->t_type = POINTER;
- tdp->t_tdesc = tdarr[ctt->ctt_type];
+ tdp->t_tdesc = tdarr[type];
break;
- case CTF_K_ARRAY:
+ case CTF_K_ARRAY: {
+ uint_t contents, index, nelems;
+
tdp->t_type = ARRAY;
tdp->t_size = size;
- v = (void *) dptr;
- cta = v;
- dptr += sizeof (ctf_array_t);
+ if (version == CTF_VERSION_2) {
+ struct ctf_array_v2 *cta = (void *) dptr;
+ contents = cta->cta_contents;
+ index = cta->cta_index;
+ nelems = cta->cta_nelems;
+ dptr += sizeof (*cta);
+ } else {
+ struct ctf_array_v3 *cta = (void *) dptr;
+ contents = cta->cta_contents;
+ index = cta->cta_index;
+ nelems = cta->cta_nelems;
+ dptr += sizeof (*cta);
+ }
tdp->t_ardef = xmalloc(sizeof (ardef_t));
- tdp->t_ardef->ad_contents = tdarr[cta->cta_contents];
- tdp->t_ardef->ad_idxtype = tdarr[cta->cta_index];
- tdp->t_ardef->ad_nelems = cta->cta_nelems;
+ tdp->t_ardef->ad_contents = tdarr[contents];
+ tdp->t_ardef->ad_idxtype = tdarr[index];
+ tdp->t_ardef->ad_nelems = nelems;
break;
+ }
case CTF_K_STRUCT:
- case CTF_K_UNION:
+ case CTF_K_UNION: {
tdp->t_type = (kind == CTF_K_STRUCT ? STRUCT : UNION);
tdp->t_size = size;
- if (size < CTF_LSTRUCT_THRESH) {
- for (i = 0, mpp = &tdp->t_members; i < vlen;
- i++, mpp = &((*mpp)->ml_next)) {
- v = (void *) dptr;
- ctf_member_t *ctm = v;
- dptr += sizeof (ctf_member_t);
-
- *mpp = xmalloc(sizeof (mlist_t));
- (*mpp)->ml_name = xstrdup(sbuf +
- ctm->ctm_name);
- (*mpp)->ml_type = tdarr[ctm->ctm_type];
- (*mpp)->ml_offset = ctm->ctm_offset;
- (*mpp)->ml_size = 0;
+ if (version == CTF_VERSION_2) {
+ if (size < CTF_V2_LSTRUCT_THRESH) {
+ for (i = 0, mpp = &tdp->t_members; i < vlen;
+ i++, mpp = &((*mpp)->ml_next)) {
+ v = (void *) dptr;
+ struct ctf_member_v2 *ctm = v;
+ dptr += sizeof (struct ctf_member_v2);
+
+ *mpp = xmalloc(sizeof (mlist_t));
+ (*mpp)->ml_name = xstrdup(sbuf +
+ ctm->ctm_name);
+ (*mpp)->ml_type = tdarr[ctm->ctm_type];
+ (*mpp)->ml_offset = ctm->ctm_offset;
+ (*mpp)->ml_size = 0;
+ }
+ } else {
+ for (i = 0, mpp = &tdp->t_members; i < vlen;
+ i++, mpp = &((*mpp)->ml_next)) {
+ v = (void *) dptr;
+ struct ctf_lmember_v2 *ctlm = v;
+ dptr += sizeof (struct ctf_lmember_v2);
+
+ *mpp = xmalloc(sizeof (mlist_t));
+ (*mpp)->ml_name = xstrdup(sbuf +
+ ctlm->ctlm_name);
+ (*mpp)->ml_type =
+ tdarr[ctlm->ctlm_type];
+ (*mpp)->ml_offset =
+ (int)CTF_LMEM_OFFSET(ctlm);
+ (*mpp)->ml_size = 0;
+ }
}
} else {
- for (i = 0, mpp = &tdp->t_members; i < vlen;
- i++, mpp = &((*mpp)->ml_next)) {
- v = (void *) dptr;
- ctf_lmember_t *ctlm = v;
- dptr += sizeof (ctf_lmember_t);
-
- *mpp = xmalloc(sizeof (mlist_t));
- (*mpp)->ml_name = xstrdup(sbuf +
- ctlm->ctlm_name);
- (*mpp)->ml_type =
- tdarr[ctlm->ctlm_type];
- (*mpp)->ml_offset =
- (int)CTF_LMEM_OFFSET(ctlm);
- (*mpp)->ml_size = 0;
+ if (size < CTF_V3_LSTRUCT_THRESH) {
+ for (i = 0, mpp = &tdp->t_members; i < vlen;
+ i++, mpp = &((*mpp)->ml_next)) {
+ v = (void *) dptr;
+ struct ctf_member_v3 *ctm = v;
+ dptr += sizeof (struct ctf_member_v3);
+
+ *mpp = xmalloc(sizeof (mlist_t));
+ (*mpp)->ml_name = xstrdup(sbuf +
+ ctm->ctm_name);
+ (*mpp)->ml_type = tdarr[ctm->ctm_type];
+ (*mpp)->ml_offset = ctm->ctm_offset;
+ (*mpp)->ml_size = 0;
+ }
+ } else {
+ for (i = 0, mpp = &tdp->t_members; i < vlen;
+ i++, mpp = &((*mpp)->ml_next)) {
+ v = (void *) dptr;
+ struct ctf_lmember_v3 *ctlm = v;
+ dptr += sizeof (struct ctf_lmember_v3);
+
+ *mpp = xmalloc(sizeof (mlist_t));
+ (*mpp)->ml_name = xstrdup(sbuf +
+ ctlm->ctlm_name);
+ (*mpp)->ml_type =
+ tdarr[ctlm->ctlm_type];
+ (*mpp)->ml_offset =
+ (int)CTF_LMEM_OFFSET(ctlm);
+ (*mpp)->ml_size = 0;
+ }
}
}
*mpp = NULL;
break;
+ }
case CTF_K_ENUM:
tdp->t_type = ENUM;
@@ -1187,26 +1298,26 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
case CTF_K_TYPEDEF:
tdp->t_type = TYPEDEF;
- tdp->t_tdesc = tdarr[ctt->ctt_type];
+ tdp->t_tdesc = tdarr[type];
break;
case CTF_K_VOLATILE:
tdp->t_type = VOLATILE;
- tdp->t_tdesc = tdarr[ctt->ctt_type];
+ tdp->t_tdesc = tdarr[type];
break;
case CTF_K_CONST:
tdp->t_type = CONST;
- tdp->t_tdesc = tdarr[ctt->ctt_type];
+ tdp->t_tdesc = tdarr[type];
break;
case CTF_K_FUNCTION:
tdp->t_type = FUNCTION;
tdp->t_fndef = xcalloc(sizeof (fndef_t));
- tdp->t_fndef->fn_ret = tdarr[ctt->ctt_type];
+ tdp->t_fndef->fn_ret = tdarr[type];
- v = (void *) (dptr + (sizeof (ushort_t) * (vlen - 1)));
- if (vlen > 0 && *(ushort_t *)v == 0)
+ v = (void *) (dptr + (idwidth * (vlen - 1)));
+ if (vlen > 0 && *(uint_t *)v == 0)
tdp->t_fndef->fn_vargs = 1;
tdp->t_fndef->fn_nargs = vlen - tdp->t_fndef->fn_vargs;
@@ -1215,20 +1326,19 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
for (i = 0; i < vlen; i++) {
v = (void *) dptr;
- argid = *(ushort_t *)v;
- dptr += sizeof (ushort_t);
+ memcpy(&argid, v, idwidth);
+ dptr += idwidth;
if (argid != 0)
tdp->t_fndef->fn_args[i] = tdarr[argid];
}
- if (vlen & 1)
- dptr += sizeof (ushort_t);
+ dptr = (caddr_t) roundup2((uintptr_t) dptr, 4);
break;
case CTF_K_RESTRICT:
tdp->t_type = RESTRICT;
- tdp->t_tdesc = tdarr[ctt->ctt_type];
+ tdp->t_tdesc = tdarr[type];
break;
case CTF_K_UNKNOWN:
@@ -1238,7 +1348,7 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
warning("Can't parse unknown CTF type %d\n", kind);
}
- if (CTF_INFO_ISROOT(ctt->ctt_info)) {
+ if (isroot) {
iidesc_t *ii = iidesc_new(tdp->t_name);
if (tdp->t_type == STRUCT || tdp->t_type == UNION ||
tdp->t_type == ENUM)
@@ -1252,8 +1362,7 @@ resurrect_types(ctf_header_t *h, tdata_t *td, tdesc_t **tdarr, int tdsize,
}
debug(3, "Resurrected %d %stype %s (%d)\n", tdp->t_type,
- (CTF_INFO_ISROOT(ctt->ctt_info) ? "root " : ""),
- tdesc_name(tdp), tdp->t_id);
+ (isroot ? "root " : ""), tdesc_name(tdp), tdp->t_id);
}
debug(3, "Resurrected %d types (%d were roots)\n", tcnt, iicnt);
@@ -1353,7 +1462,7 @@ ctf_load(char *file, caddr_t buf, size_t bufsz, symit_data_t *si, char *label)
if (h->cth_magic != CTF_MAGIC)
parseterminate("Corrupt CTF - bad magic 0x%x", h->cth_magic);
- if (h->cth_version != CTF_VERSION)
+ if (h->cth_version != CTF_VERSION_2 && h->cth_version != CTF_VERSION_3)
parseterminate("Unknown CTF version %d", h->cth_version);
ctfdatasz = h->cth_stroff + h->cth_strlen;
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c b/cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c
index d40be25da27f..68969356e75e 100644
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c
+++ b/cddl/contrib/opensolaris/tools/ctf/cvt/ctfconvert.c
@@ -83,7 +83,6 @@ file_read(tdata_t *td, char *filename, int ignore_non_c)
{
typedef int (*reader_f)(tdata_t *, Elf *, char *);
static reader_f readers[] = {
- stabs_read,
dw_read,
NULL
};
@@ -165,8 +164,6 @@ main(int argc, char **argv)
if (getenv("CTFCONVERT_DEBUG_LEVEL"))
debug_level = atoi(getenv("CTFCONVERT_DEBUG_LEVEL"));
- if (getenv("CTFCONVERT_DEBUG_PARSE"))
- debug_parse = atoi(getenv("CTFCONVERT_DEBUG_PARSE"));
while ((c = getopt(argc, argv, ":l:L:o:givs")) != EOF) {
switch (c) {
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.c b/cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.c
index ddb5f388ca98..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);
@@ -972,11 +966,11 @@ main(int argc, char **argv)
savetd = tdata_new();
- if (CTF_TYPE_ISCHILD(reftd->td_nextid))
+ if (CTF_V3_TYPE_ISCHILD(reftd->td_nextid))
terminate("No room for additional types in master\n");
savetd->td_nextid = withfile ? reftd->td_nextid :
- CTF_INDEX_TO_TYPE(1, TRUE);
+ CTF_V3_INDEX_TO_TYPE(1, TRUE);
merge_into_master(mstrtd, reftd, savetd, 0);
tdata_label_add(savetd, label, CTF_LABEL_LASTIDX);
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h b/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h
index b7da16ac3ddd..612c9f25a5a0 100644
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h
+++ b/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h
@@ -50,9 +50,6 @@ extern "C" {
#ifndef DEBUG_LEVEL
#define DEBUG_LEVEL 0
#endif
-#ifndef DEBUG_PARSE
-#define DEBUG_PARSE 0
-#endif
#ifndef DEBUG_STREAM
#define DEBUG_STREAM stderr
@@ -100,7 +97,6 @@ extern "C" {
extern const char *progname;
extern int debug_level;
-extern int debug_parse;
extern char *curhdr;
/*
@@ -405,18 +401,6 @@ void merge_into_master(tdata_t *, tdata_t *, tdata_t *, int);
void write_ctf(tdata_t *, const char *, const char *, int);
-/* parse.c */
-void parse_init(tdata_t *);
-void parse_finish(tdata_t *);
-int parse_stab(stab_t *, char *, iidesc_t **);
-tdesc_t *lookup(int);
-tdesc_t *lookupname(const char *);
-void check_hash(void);
-void resolve_typed_bitfields(void);
-
-/* stabs.c */
-int stabs_read(tdata_t *, Elf *, char *);
-
/* dwarf.c */
int dw_read(tdata_t *, Elf *, char *);
const char *dw_tag2str(uint_t);
@@ -445,8 +429,8 @@ int streq(const char *, const char *);
int findelfsecidx(Elf *, const char *, const char *);
size_t elf_ptrsz(Elf *);
char *mktmpname(const char *, const char *);
-void terminate(const char *, ...) __NORETURN;
-void aborterr(const char *, ...) __NORETURN;
+void terminate(const char *, ...) __attribute__((noreturn));
+void aborterr(const char *, ...) __attribute__((noreturn));
void set_terminate_cleanup(void (*)(void));
void elfterminate(const char *, const char *, ...);
void warning(const char *, ...);
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c b/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
index 32c993e1e524..42faaad65db5 100644
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
+++ b/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
@@ -618,7 +618,7 @@ tdesc_intr_long(dwarf_t *dw)
* caller can then use the copy as the type for a bitfield structure member.
*/
static tdesc_t *
-tdesc_intr_clone(dwarf_t *dw, tdesc_t *old, size_t bitsz)
+tdesc_intr_clone(dwarf_t *dw, tdesc_t *old, size_t bitsz, const char *suffix)
{
tdesc_t *new = xcalloc(sizeof (tdesc_t));
@@ -627,7 +627,7 @@ tdesc_intr_clone(dwarf_t *dw, tdesc_t *old, size_t bitsz)
"unresolved type\n", old->t_id);
}
- new->t_name = xstrdup(old->t_name);
+ xasprintf(&new->t_name, "%s %s", old->t_name, suffix);
new->t_size = old->t_size;
new->t_id = mfgtid_next(dw);
new->t_type = INTRINSIC;
@@ -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
@@ -1123,8 +1125,16 @@ die_sou_resolve(tdesc_t *tdp, tdesc_t **tdpp __unused, void *private)
*/
if (mt->t_members == NULL)
continue;
- if (mt->t_type == ARRAY && mt->t_ardef->ad_nelems == 0)
- continue;
+ if (mt->t_type == ARRAY) {
+ if (mt->t_ardef->ad_nelems == 0)
+ continue;
+ mt = tdesc_basetype(mt->t_ardef->ad_contents);
+ if ((mt->t_flags & TDESC_F_RESOLVED) != 0 &&
+ (mt->t_type == STRUCT ||
+ mt->t_type == UNION) &&
+ mt->t_members == NULL)
+ continue;
+ }
if ((mt->t_flags & TDESC_F_RESOLVED) != 0 &&
(mt->t_type == STRUCT || mt->t_type == UNION))
continue;
@@ -1150,7 +1160,8 @@ die_sou_resolve(tdesc_t *tdp, tdesc_t **tdpp __unused, void *private)
debug(3, "tdp %u: creating bitfield for %d bits\n",
tdp->t_id, ml->ml_size);
- ml->ml_type = tdesc_intr_clone(dw, mt, ml->ml_size);
+ ml->ml_type = tdesc_intr_clone(dw, mt, ml->ml_size,
+ "bitfield");
}
}
@@ -1358,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);
@@ -1389,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/cvt/fixup_tdescs.c b/cddl/contrib/opensolaris/tools/ctf/cvt/fixup_tdescs.c
index b239a62dc53b..ea4f4ee64625 100644
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/fixup_tdescs.c
+++ b/cddl/contrib/opensolaris/tools/ctf/cvt/fixup_tdescs.c
@@ -38,125 +38,6 @@
#include "hash.h"
#include "memory.h"
-/*
- * Due to 4432619, the 6.1 compiler will sometimes incorrectly generate pointer
- * stabs. Given a struct foo, and a corresponding typedef struct foo foo_t.
- * In some cases, when faced with a pointer to a foo_t, the compiler will
- * sometimes generate a stab that describes a pointer to a struct foo.
- * Regardless of correctness, this breaks merges, as it occurs inconsistently
- * by file. The following two routines know how to recognize and repair foo_t *
- * and foo_t ** bugs in a specific set of cases. There is no general way to
- * solve this problem without a fix to the compiler. In general, cases should
- * only be added to these routines to fix merging problems in genunix.
- */
-static void
-fix_ptrptr_to_struct(tdata_t *td)
-{
- const char *strs[2] = { "as", "fdbuffer" };
- const char *mems[2] = { "a_objectdir", "fd_shadow" };
- const char *acts[2] = { "vnode", "page" };
- const char *tgts[2] = { "vnode_t", "page_t" };
- tdesc_t *str;
- tdesc_t *act, *tgt;
- tdesc_t *p1, *p2;
- mlist_t *ml;
- int i;
-
- for (i = 0; i < (int) (sizeof (strs) / sizeof (strs[0])); i++) {
- if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
- continue;
-
- for (ml = str->t_members; ml; ml = ml->ml_next) {
- if (streq(ml->ml_name, mems[i]))
- break;
- }
- if (!ml)
- continue;
-
- if (ml->ml_type->t_type != POINTER || ml->ml_type->t_name ||
- ml->ml_type->t_tdesc->t_type != POINTER ||
- ml->ml_type->t_tdesc->t_name)
- continue;
-
- act = ml->ml_type->t_tdesc->t_tdesc;
- if (act->t_type != STRUCT || !streq(act->t_name, acts[i]))
- continue;
-
- if (!(tgt = lookupname(tgts[i])) || tgt->t_type != TYPEDEF)
- continue;
-
- /* We have an instance of the bug */
- p2 = xcalloc(sizeof (*p2));
- p2->t_type = POINTER;
- p2->t_id = td->td_nextid++;
- p2->t_tdesc = tgt;
-
- p1 = xcalloc(sizeof (*p1));
- p1->t_type = POINTER;
- p1->t_id = td->td_nextid++;
- p1->t_tdesc = p2;
-
- ml->ml_type = p1;
-
- debug(3, "Fixed %s->%s => ptrptr struct %s bug\n",
- strs[i], mems[i], acts[i]);
- }
-}
-
-static void
-fix_ptr_to_struct(tdata_t *td)
-{
- const char *strs[2] = { "vmem", "id_space" };
- const char *mems[2] = { NULL, "is_vmem" };
- tdesc_t *ptr = NULL;
- tdesc_t *str, *vmt;
- mlist_t *ml;
- int i;
-
- if ((vmt = lookupname("vmem_t")) == NULL || vmt->t_type != TYPEDEF)
- return;
-
- for (i = 0; i < (int) (sizeof (strs) / sizeof (strs[0])); i++) {
- if (!(str = lookupname(strs[i])) || str->t_type != STRUCT)
- continue;
-
- for (ml = str->t_members; ml; ml = ml->ml_next) {
- if (mems[i] && !streq(ml->ml_name, mems[i]))
- continue;
-
- if (ml->ml_type->t_type != POINTER ||
- ml->ml_type->t_name ||
- (ml->ml_type->t_tdesc->t_type != STRUCT &&
- ml->ml_type->t_tdesc->t_type != FORWARD) ||
- !streq(ml->ml_type->t_tdesc->t_name, "vmem"))
- continue;
-
- debug(3, "Fixed %s->%s => ptr struct vmem bug\n",
- strs[i], ml->ml_name);
-
- if (!ptr) {
- ptr = xcalloc(sizeof (*ptr));
- ptr->t_type = POINTER;
- ptr->t_id = td->td_nextid++;
- ptr->t_tdesc = vmt;
- }
-
- ml->ml_type = ptr;
- }
- }
-}
-
-/*
- * Fix stabs generation bugs. These routines must be run before the
- * post-conversion merge
- */
-void
-cvt_fixstabs(tdata_t *td)
-{
- fix_ptrptr_to_struct(td);
- fix_ptr_to_struct(td);
-}
-
struct match {
tdesc_t *m_ret;
const char *m_name;
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/output.c b/cddl/contrib/opensolaris/tools/ctf/cvt/output.c
index 3385e4b2d09f..05f71231ac68 100644
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/output.c
+++ b/cddl/contrib/opensolaris/tools/ctf/cvt/output.c
@@ -467,7 +467,6 @@ write_file(Elf *src, const char *srcname, Elf *dst, const char *dstname,
int keep_stabs = (flags & CTF_KEEP_STABS);
int *secxlate;
int srcidx, dstidx;
- int curnmoff = 0;
int changing = 0;
int pad;
int i;
@@ -529,7 +528,6 @@ write_file(Elf *src, const char *srcname, Elf *dst, const char *dstname,
secxlate[srcidx] = -1;
} else {
secxlate[srcidx] = dstidx++;
- curnmoff += strlen(sname) + 1;
}
new_offset = (off_t)dehdr.e_phoff;
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c b/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c
deleted file mode 100644
index a452ca5960a7..000000000000
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/st_parse.c
+++ /dev/null
@@ -1,1214 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-/*
- * This file is a sewer.
- */
-
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <assert.h>
-#include <strings.h>
-#include <setjmp.h>
-#include <ctype.h>
-#include <uts/common/sys/ctf.h>
-
-#include "ctftools.h"
-#include "memory.h"
-#include "list.h"
-
-#define HASH(NUM) ((int)(NUM & (BUCKETS - 1)))
-#define BUCKETS 128
-
-#define TYPEPAIRMULT 10000
-#define MAKETYPEID(file, num) ((file) * TYPEPAIRMULT + num)
-#define TYPEFILE(tid) ((tid) / TYPEPAIRMULT)
-#define TYPENUM(tid) ((tid) % TYPEPAIRMULT)
-
-#define expected(a, b, c) _expected(a, b, c, __LINE__)
-
-static int faketypenumber = 100000000;
-
-static tdesc_t *hash_table[BUCKETS];
-static tdesc_t *name_table[BUCKETS];
-
-static list_t *typedbitfldmems;
-
-static void reset(void);
-static jmp_buf resetbuf;
-
-static char *soudef(char *cp, stabtype_t type, tdesc_t **rtdp);
-static void enumdef(char *cp, tdesc_t **rtdp);
-static int compute_sum(const char *w);
-
-static char *number(char *cp, int *n);
-static char *name(char *cp, char **w);
-static char *id(char *cp, int *h);
-static char *whitesp(char *cp);
-static void addhash(tdesc_t *tdp, int num);
-static int tagadd(char *w, int h, tdesc_t *tdp);
-static char *tdefdecl(char *cp, int h, tdesc_t **rtdp);
-static char *intrinsic(char *cp, tdesc_t **rtdp);
-static char *arraydef(char *cp, tdesc_t **rtdp);
-
-int debug_parse = DEBUG_PARSE;
-
-/*PRINTFLIKE3*/
-static void
-parse_debug(int level, char *cp, const char *fmt, ...)
-{
- va_list ap;
- char buf[1024];
- char tmp[32];
- int i;
-
- if (level > debug_level || !debug_parse)
- return;
-
- if (cp != NULL) {
- for (i = 0; i < 30; i++) {
- if (cp[i] == '\0')
- break;
- if (!iscntrl(cp[i]))
- tmp[i] = cp[i];
- }
- tmp[i] = '\0';
- (void) snprintf(buf, sizeof (buf), "%s [cp='%s']\n", fmt, tmp);
- } else {
- strcpy(buf, fmt);
- strcat(buf, "\n");
- }
-
- va_start(ap, fmt);
- vadebug(level, buf, ap);
- va_end(ap);
-}
-
-/* Report unexpected syntax in stabs. */
-static void
-_expected(
- const char *who, /* what function, or part thereof, is reporting */
- const char *what, /* what was expected */
- const char *where, /* where we were in the line of input */
- int line)
-{
- fprintf(stderr, "%s, expecting \"%s\" at \"%s\"\n", who, what, where);
- fprintf(stderr, "code line: %d, file %s\n", line,
- (curhdr ? curhdr : "NO FILE"));
- reset();
-}
-
-/*ARGSUSED*/
-void
-parse_init(tdata_t *td __unused)
-{
- int i;
-
- for (i = 0; i < BUCKETS; i++) {
- hash_table[i] = NULL;
- name_table[i] = NULL;
- }
-
- if (typedbitfldmems != NULL) {
- list_free(typedbitfldmems, NULL, NULL);
- typedbitfldmems = NULL;
- }
-}
-
-void
-parse_finish(tdata_t *td)
-{
- td->td_nextid = ++faketypenumber;
-}
-
-static tdesc_t *
-unres_new(int tid)
-{
- tdesc_t *tdp;
-
- tdp = xcalloc(sizeof (*tdp));
- tdp->t_type = TYPEDEF_UNRES;
- tdp->t_id = tid;
-
- return (tdp);
-}
-
-static char *
-read_tid(char *cp, tdesc_t **tdpp)
-{
- tdesc_t *tdp;
- int tid;
-
- cp = id(cp, &tid);
-
- assert(tid != 0);
-
- if (*cp == '=') {
- if (!(cp = tdefdecl(cp + 1, tid, &tdp)))
- return (NULL);
- if (tdp->t_id && tdp->t_id != tid) {
- tdesc_t *ntdp = xcalloc(sizeof (*ntdp));
-
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp = ntdp;
- }
- addhash(tdp, tid);
- } else if ((tdp = lookup(tid)) == NULL)
- tdp = unres_new(tid);
-
- *tdpp = tdp;
- return (cp);
-}
-
-static iitype_t
-parse_fun(char *cp, iidesc_t *ii)
-{
- iitype_t iitype = 0;
- tdesc_t *tdp;
- tdesc_t **args = NULL;
- int nargs = 0;
- int va = 0;
-
- /*
- * name:P prototype
- * name:F global function
- * name:f static function
- */
- switch (*cp++) {
- case 'P':
- iitype = II_NOT; /* not interesting */
- break;
-
- case 'F':
- iitype = II_GFUN;
- break;
-
- case 'f':
- iitype = II_SFUN;
- break;
-
- default:
- expected("parse_nfun", "[PfF]", cp - 1);
- }
-
- if (!(cp = read_tid(cp, &tdp)))
- return (-1);
-
- if (*cp)
- args = xmalloc(sizeof (tdesc_t *) * FUNCARG_DEF);
-
- while (*cp && *++cp) {
- if (*cp == '0') {
- va = 1;
- continue;
- }
-
- nargs++;
- if (nargs > FUNCARG_DEF)
- args = xrealloc(args, sizeof (tdesc_t *) * nargs);
- if (!(cp = read_tid(cp, &args[nargs - 1]))) {
- if (tdp->t_type == TYPEDEF_UNRES)
- free(tdp);
- free(args);
- return (-1);
- }
- }
-
- ii->ii_type = iitype;
- ii->ii_dtype = tdp;
- ii->ii_nargs = nargs;
- ii->ii_args = args;
- ii->ii_vargs = va;
-
- return (iitype);
-}
-
-static iitype_t
-parse_sym(char *cp, iidesc_t *ii)
-{
- tdesc_t *tdp;
- iitype_t iitype = 0;
-
- /*
- * name:G global variable
- * name:S static variable
- */
- switch (*cp++) {
- case 'G':
- iitype = II_GVAR;
- break;
- case 'S':
- iitype = II_SVAR;
- break;
- case 'p':
- iitype = II_PSYM;
- break;
- case '(':
- cp--;
- /*FALLTHROUGH*/
- case 'r':
- case 'V':
- iitype = II_NOT; /* not interesting */
- break;
- default:
- expected("parse_sym", "[GprSV(]", cp - 1);
- }
-
- if (!(cp = read_tid(cp, &tdp)))
- return (-1);
-
- ii->ii_type = iitype;
- ii->ii_dtype = tdp;
-
- return (iitype);
-}
-
-static iitype_t
-parse_type(char *cp, iidesc_t *ii)
-{
- tdesc_t *tdp, *ntdp;
- int tid;
-
- if (*cp++ != 't')
- expected("parse_type", "t (type)", cp - 1);
-
- cp = id(cp, &tid);
- if ((tdp = lookup(tid)) == NULL) {
- if (*cp++ != '=')
- expected("parse_type", "= (definition)", cp - 1);
-
- (void) tdefdecl(cp, tid, &tdp);
-
- if (tdp->t_id == tid) {
- assert(tdp->t_type != TYPEDEF);
- assert(!lookup(tdp->t_id));
-
- if (!streq(tdp->t_name, ii->ii_name)) {
- ntdp = xcalloc(sizeof (*ntdp));
- ntdp->t_name = xstrdup(ii->ii_name);
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp->t_id = faketypenumber++;
- tdp = ntdp;
- }
- } else if (tdp->t_id == 0) {
- assert(tdp->t_type == FORWARD ||
- tdp->t_type == INTRINSIC);
-
- if (tdp->t_name && !streq(tdp->t_name, ii->ii_name)) {
- ntdp = xcalloc(sizeof (*ntdp));
- ntdp->t_name = xstrdup(ii->ii_name);
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp->t_id = faketypenumber++;
- tdp = ntdp;
- }
- } else if (tdp->t_id != tid) {
- ntdp = xcalloc(sizeof (*ntdp));
- ntdp->t_name = xstrdup(ii->ii_name);
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp = ntdp;
- }
-
- if (tagadd(ii->ii_name, tid, tdp) < 0)
- return (-1);
- }
-
- ii->ii_type = II_TYPE;
- ii->ii_dtype = tdp;
- return (II_TYPE);
-}
-
-static iitype_t
-parse_sou(char *cp, iidesc_t *idp)
-{
- tdesc_t *rtdp;
- int tid;
-
- if (*cp++ != 'T')
- expected("parse_sou", "T (sou)", cp - 1);
-
- cp = id(cp, &tid);
- if (*cp++ != '=')
- expected("parse_sou", "= (definition)", cp - 1);
-
- parse_debug(1, NULL, "parse_sou: declaring '%s'", idp->ii_name ?
- idp->ii_name : "(anon)");
- if ((rtdp = lookup(tid)) != NULL) {
- if (idp->ii_name != NULL) {
- if (rtdp->t_name != NULL &&
- strcmp(rtdp->t_name, idp->ii_name) != 0) {
- tdesc_t *tdp;
-
- tdp = xcalloc(sizeof (*tdp));
- tdp->t_name = xstrdup(idp->ii_name);
- tdp->t_type = TYPEDEF;
- tdp->t_tdesc = rtdp;
- addhash(tdp, tid); /* for *(x,y) types */
- parse_debug(3, NULL, " %s defined as %s(%d)",
- idp->ii_name, tdesc_name(rtdp), tid);
- } else if (rtdp->t_name == NULL) {
- rtdp->t_name = xstrdup(idp->ii_name);
- addhash(rtdp, tid);
- }
- }
- } else {
- rtdp = xcalloc(sizeof (*rtdp));
- rtdp->t_name = idp->ii_name ? xstrdup(idp->ii_name) : NULL;
- addhash(rtdp, tid);
- }
-
- switch (*cp++) {
- case 's':
- (void) soudef(cp, STRUCT, &rtdp);
- break;
- case 'u':
- (void) soudef(cp, UNION, &rtdp);
- break;
- case 'e':
- enumdef(cp, &rtdp);
- break;
- default:
- expected("parse_sou", "<tag type s/u/e>", cp - 1);
- break;
- }
-
- idp->ii_type = II_SOU;
- idp->ii_dtype = rtdp;
- return (II_SOU);
-}
-
-int
-parse_stab(stab_t *stab, char *cp, iidesc_t **iidescp)
-{
- iidesc_t *ii = NULL;
- iitype_t (*parse)(char *, iidesc_t *);
- int rc;
-
- /*
- * set up for reset()
- */
- if (setjmp(resetbuf))
- return (-1);
-
- cp = whitesp(cp);
- ii = iidesc_new(NULL);
- cp = name(cp, &ii->ii_name);
-
- switch (stab->n_type) {
- case N_FUN:
- parse = parse_fun;
- break;
-
- case N_LSYM:
- if (*cp == 't')
- parse = parse_type;
- else if (*cp == 'T')
- parse = parse_sou;
- else
- parse = parse_sym;
- break;
-
- case N_GSYM:
- case N_LCSYM:
- case N_PSYM:
- case N_ROSYM:
- case N_RSYM:
- case N_STSYM:
- parse = parse_sym;
- break;
- default:
- parse_debug(1, cp, "Unknown stab type %#x", stab->n_type);
- bzero(&resetbuf, sizeof (resetbuf));
- return (-1);
- }
-
- rc = parse(cp, ii);
- bzero(&resetbuf, sizeof (resetbuf));
-
- if (rc < 0 || ii->ii_type == II_NOT) {
- iidesc_free(ii, NULL);
- return (rc);
- }
-
- *iidescp = ii;
-
- return (1);
-}
-
-/*
- * Check if we have this node in the hash table already
- */
-tdesc_t *
-lookup(int h)
-{
- int bucket = HASH(h);
- tdesc_t *tdp = hash_table[bucket];
-
- while (tdp != NULL) {
- if (tdp->t_id == h)
- return (tdp);
- tdp = tdp->t_hash;
- }
- return (NULL);
-}
-
-static char *
-whitesp(char *cp)
-{
- char c;
-
- for (c = *cp++; isspace(c); c = *cp++)
- ;
- --cp;
- return (cp);
-}
-
-static char *
-name(char *cp, char **w)
-{
- char *new, *orig, c;
- int len;
-
- orig = cp;
- c = *cp++;
- if (c == ':')
- *w = NULL;
- else if (isalpha(c) || strchr("_.$#", c)) {
- for (c = *cp++; isalnum(c) || strchr(" _.$#", c); c = *cp++)
- ;
- if (c != ':')
- reset();
- len = cp - orig;
- new = xmalloc(len);
- while (orig < cp - 1)
- *new++ = *orig++;
- *new = '\0';
- *w = new - (len - 1);
- } else
- reset();
-
- return (cp);
-}
-
-static char *
-number(char *cp, int *n)
-{
- char *next;
-
- *n = (int)strtol(cp, &next, 10);
- if (next == cp)
- expected("number", "<number>", cp);
- return (next);
-}
-
-static char *
-id(char *cp, int *h)
-{
- int n1, n2;
-
- if (*cp == '(') { /* SunPro style */
- cp++;
- cp = number(cp, &n1);
- if (*cp++ != ',')
- expected("id", ",", cp - 1);
- cp = number(cp, &n2);
- if (*cp++ != ')')
- expected("id", ")", cp - 1);
- *h = MAKETYPEID(n1, n2);
- } else if (isdigit(*cp)) { /* gcc style */
- cp = number(cp, &n1);
- *h = n1;
- } else {
- expected("id", "(/0-9", cp);
- }
- return (cp);
-}
-
-static int
-tagadd(char *w, int h, tdesc_t *tdp)
-{
- tdesc_t *otdp;
-
- tdp->t_name = w;
- if (!(otdp = lookup(h)))
- addhash(tdp, h);
- else if (otdp != tdp) {
- warning("duplicate entry\n");
- warning(" old: %s %d (%d,%d)\n", tdesc_name(otdp),
- otdp->t_type, TYPEFILE(otdp->t_id), TYPENUM(otdp->t_id));
- warning(" new: %s %d (%d,%d)\n", tdesc_name(tdp),
- tdp->t_type, TYPEFILE(tdp->t_id), TYPENUM(tdp->t_id));
- return (-1);
- }
-
- return (0);
-}
-
-static char *
-tdefdecl(char *cp, int h, tdesc_t **rtdp)
-{
- tdesc_t *ntdp;
- char *w;
- int c, h2;
- char type;
-
- parse_debug(3, cp, "tdefdecl h=%d", h);
-
- /* Type codes */
- switch (type = *cp) {
- case 'b': /* integer */
- case 'R': /* fp */
- cp = intrinsic(cp, rtdp);
- break;
- case '(': /* equiv to another type */
- cp = id(cp, &h2);
- ntdp = lookup(h2);
-
- if (ntdp != NULL && *cp == '=') {
- if (ntdp->t_type == FORWARD && *(cp + 1) == 'x') {
- /*
- * The 6.2 compiler, and possibly others, will
- * sometimes emit the same stab for a forward
- * declaration twice. That is, "(1,2)=xsfoo:"
- * will sometimes show up in two different
- * places. This is, of course, quite fun. We
- * want CTF to work in spite of the compiler,
- * so we'll let this one through.
- */
- char *c2 = cp + 2;
- char *nm;
-
- if (!strchr("sue", *c2++)) {
- expected("tdefdecl/x-redefine", "[sue]",
- c2 - 1);
- }
-
- c2 = name(c2, &nm);
- if (strcmp(nm, ntdp->t_name) != 0) {
- terminate("Stabs error: Attempt to "
- "redefine type (%d,%d) as "
- "something else: %s\n",
- TYPEFILE(h2), TYPENUM(h2),
- c2 - 1);
- }
- free(nm);
-
- h2 = faketypenumber++;
- ntdp = NULL;
- } else {
- terminate("Stabs error: Attempting to "
- "redefine type (%d,%d)\n", TYPEFILE(h2),
- TYPENUM(h2));
- }
- }
-
- if (ntdp == NULL) { /* if that type isn't defined yet */
- if (*cp != '=') {
- /* record it as unresolved */
- parse_debug(3, NULL, "tdefdecl unres type %d",
- h2);
- *rtdp = calloc(sizeof (**rtdp), 1);
- (*rtdp)->t_type = TYPEDEF_UNRES;
- (*rtdp)->t_id = h2;
- break;
- } else
- cp++;
-
- /* define a new type */
- cp = tdefdecl(cp, h2, rtdp);
- if ((*rtdp)->t_id && (*rtdp)->t_id != h2) {
- ntdp = calloc(sizeof (*ntdp), 1);
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = *rtdp;
- *rtdp = ntdp;
- }
-
- addhash(*rtdp, h2);
-
- } else { /* that type is already defined */
- if (ntdp->t_type != TYPEDEF || ntdp->t_name != NULL) {
- *rtdp = ntdp;
- } else {
- parse_debug(3, NULL,
- "No duplicate typedef anon for ref");
- *rtdp = ntdp;
- }
- }
- break;
- case '*':
- ntdp = NULL;
- cp = tdefdecl(cp + 1, h, &ntdp);
- if (ntdp == NULL)
- expected("tdefdecl/*", "id", cp);
-
- if (!ntdp->t_id)
- ntdp->t_id = faketypenumber++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = POINTER;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_id = h;
- (*rtdp)->t_tdesc = ntdp;
- break;
- case 'f':
- cp = tdefdecl(cp + 1, h, &ntdp);
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = FUNCTION;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_id = h;
- (*rtdp)->t_fndef = xcalloc(sizeof (fndef_t));
- /*
- * The 6.1 compiler will sometimes generate incorrect stabs for
- * function pointers (it'll get the return type wrong). This
- * causes merges to fail. We therefore treat function pointers
- * as if they all point to functions that return int. When
- * 4432549 is fixed, the lookupname() call below should be
- * replaced with `ntdp'.
- */
- (*rtdp)->t_fndef->fn_ret = lookupname("int");
- break;
- case 'a':
- case 'z':
- cp++;
- if (*cp++ != 'r')
- expected("tdefdecl/[az]", "r", cp - 1);
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = ARRAY;
- (*rtdp)->t_id = h;
- cp = arraydef(cp, rtdp);
- break;
- case 'x':
- c = *++cp;
- if (c != 's' && c != 'u' && c != 'e')
- expected("tdefdecl/x", "[sue]", cp - 1);
- cp = name(cp + 1, &w);
-
- ntdp = xcalloc(sizeof (*ntdp));
- ntdp->t_type = FORWARD;
- ntdp->t_name = w;
- /*
- * We explicitly don't set t_id here - the caller will do it.
- * The caller may want to use a real type ID, or they may
- * choose to make one up.
- */
-
- *rtdp = ntdp;
- break;
-
- case 'B': /* volatile */
- cp = tdefdecl(cp + 1, h, &ntdp);
-
- if (!ntdp->t_id)
- ntdp->t_id = faketypenumber++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = VOLATILE;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_tdesc = ntdp;
- (*rtdp)->t_id = h;
- break;
-
- case 'k': /* const */
- cp = tdefdecl(cp + 1, h, &ntdp);
-
- if (!ntdp->t_id)
- ntdp->t_id = faketypenumber++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = CONST;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_tdesc = ntdp;
- (*rtdp)->t_id = h;
- break;
-
- case 'K': /* restricted */
- cp = tdefdecl(cp + 1, h, &ntdp);
-
- if (!ntdp->t_id)
- ntdp->t_id = faketypenumber++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_type = RESTRICT;
- (*rtdp)->t_size = 0;
- (*rtdp)->t_tdesc = ntdp;
- (*rtdp)->t_id = h;
- break;
-
- case 'u':
- case 's':
- cp++;
-
- *rtdp = xcalloc(sizeof (**rtdp));
- (*rtdp)->t_name = NULL;
- cp = soudef(cp, (type == 'u') ? UNION : STRUCT, rtdp);
- break;
- default:
- expected("tdefdecl", "<type code>", cp);
- }
- return (cp);
-}
-
-static char *
-intrinsic(char *cp, tdesc_t **rtdp)
-{
- intr_t *intr = xcalloc(sizeof (intr_t));
- tdesc_t *tdp;
- int width, fmt, i;
-
- switch (*cp++) {
- case 'b':
- intr->intr_type = INTR_INT;
- if (*cp == 's')
- intr->intr_signed = 1;
- else if (*cp != 'u')
- expected("intrinsic/b", "[su]", cp);
- cp++;
-
- if (strchr("cbv", *cp))
- intr->intr_iformat = *cp++;
-
- cp = number(cp, &width);
- if (*cp++ != ';')
- expected("intrinsic/b", "; (post-width)", cp - 1);
-
- cp = number(cp, &intr->intr_offset);
- if (*cp++ != ';')
- expected("intrinsic/b", "; (post-offset)", cp - 1);
-
- cp = number(cp, &intr->intr_nbits);
- break;
-
- case 'R':
- intr->intr_type = INTR_REAL;
- for (fmt = 0, i = 0; isdigit(*(cp + i)); i++)
- fmt = fmt * 10 + (*(cp + i) - '0');
-
- if (fmt < 1 || fmt > CTF_FP_MAX)
- expected("intrinsic/R", "number <= CTF_FP_MAX", cp);
-
- intr->intr_fformat = fmt;
- cp += i;
-
- if (*cp++ != ';')
- expected("intrinsic/R", ";", cp - 1);
- cp = number(cp, &width);
-
- intr->intr_nbits = width * 8;
- break;
- }
-
- tdp = xcalloc(sizeof (*tdp));
- tdp->t_type = INTRINSIC;
- tdp->t_size = width;
- tdp->t_name = NULL;
- tdp->t_intr = intr;
- parse_debug(3, NULL, "intrinsic: size=%d", width);
- *rtdp = tdp;
-
- return (cp);
-}
-
-static tdesc_t *
-bitintrinsic(tdesc_t *template, int nbits)
-{
- tdesc_t *newtdp = xcalloc(sizeof (tdesc_t));
-
- newtdp->t_name = xstrdup(template->t_name);
- newtdp->t_id = faketypenumber++;
- newtdp->t_type = INTRINSIC;
- newtdp->t_size = template->t_size;
- newtdp->t_intr = xmalloc(sizeof (intr_t));
- bcopy(template->t_intr, newtdp->t_intr, sizeof (intr_t));
- newtdp->t_intr->intr_nbits = nbits;
-
- return (newtdp);
-}
-
-static char *
-offsize(char *cp, mlist_t *mlp)
-{
- int offset, size;
-
- if (*cp == ',')
- cp++;
- cp = number(cp, &offset);
- if (*cp++ != ',')
- expected("offsize/2", ",", cp - 1);
- cp = number(cp, &size);
- if (*cp++ != ';')
- expected("offsize/3", ";", cp - 1);
- mlp->ml_offset = offset;
- mlp->ml_size = size;
- return (cp);
-}
-
-static tdesc_t *
-find_intrinsic(tdesc_t *tdp)
-{
- for (;;) {
- switch (tdp->t_type) {
- case TYPEDEF:
- case VOLATILE:
- case CONST:
- case RESTRICT:
- tdp = tdp->t_tdesc;
- break;
-
- default:
- return (tdp);
- }
- }
-}
-
-static char *
-soudef(char *cp, stabtype_t type, tdesc_t **rtdp)
-{
- mlist_t *mlp, **prev;
- char *w;
- int h;
- int size;
- tdesc_t *tdp, *itdp;
-
- cp = number(cp, &size);
- (*rtdp)->t_size = size;
- (*rtdp)->t_type = type; /* s or u */
-
- /*
- * An '@' here indicates a bitmask follows. This is so the
- * compiler can pass information to debuggers about how structures
- * are passed in the v9 world. We don't need this information
- * so we skip over it.
- */
- if (cp[0] == '@') {
- cp += 3;
- }
-
- parse_debug(3, cp, "soudef: %s size=%d", tdesc_name(*rtdp),
- (*rtdp)->t_size);
-
- prev = &((*rtdp)->t_members);
- /* now fill up the fields */
- while ((*cp != '\0') && (*cp != ';')) { /* signifies end of fields */
- mlp = xcalloc(sizeof (*mlp));
- *prev = mlp;
- cp = name(cp, &w);
- mlp->ml_name = w;
- cp = id(cp, &h);
- /*
- * find the tdesc struct in the hash table for this type
- * and stick a ptr in here
- */
- tdp = lookup(h);
- if (tdp == NULL) { /* not in hash list */
- parse_debug(3, NULL, " defines %s (%d)", w, h);
- if (*cp++ != '=') {
- tdp = unres_new(h);
- parse_debug(3, NULL,
- " refers to %s (unresolved %d)",
- (w ? w : "anon"), h);
- } else {
- cp = tdefdecl(cp, h, &tdp);
-
- if (tdp->t_id && tdp->t_id != h) {
- tdesc_t *ntdp = xcalloc(sizeof (*ntdp));
-
- ntdp->t_type = TYPEDEF;
- ntdp->t_tdesc = tdp;
- tdp = ntdp;
- }
-
- addhash(tdp, h);
- parse_debug(4, cp,
- " soudef now looking at ");
- cp++;
- }
- } else {
- parse_debug(3, NULL, " refers to %s (%d, %s)",
- w ? w : "anon", h, tdesc_name(tdp));
- }
-
- cp = offsize(cp, mlp);
-
- itdp = find_intrinsic(tdp);
- if (itdp->t_type == INTRINSIC) {
- if (mlp->ml_size != itdp->t_intr->intr_nbits) {
- parse_debug(4, cp, "making %d bit intrinsic "
- "from %s", mlp->ml_size, tdesc_name(itdp));
- mlp->ml_type = bitintrinsic(itdp, mlp->ml_size);
- } else
- mlp->ml_type = tdp;
- } else if (itdp->t_type == TYPEDEF_UNRES) {
- list_add(&typedbitfldmems, mlp);
- mlp->ml_type = tdp;
- } else {
- mlp->ml_type = tdp;
- }
-
- /* cp is now pointing to next field */
- prev = &mlp->ml_next;
- }
- return (cp);
-}
-
-static char *
-arraydef(char *cp, tdesc_t **rtdp)
-{
- int start, end, h;
-
- cp = id(cp, &h);
- if (*cp++ != ';')
- expected("arraydef/1", ";", cp - 1);
-
- (*rtdp)->t_ardef = xcalloc(sizeof (ardef_t));
- (*rtdp)->t_ardef->ad_idxtype = lookup(h);
-
- cp = number(cp, &start); /* lower */
- if (*cp++ != ';')
- expected("arraydef/2", ";", cp - 1);
-
- if (*cp == 'S') {
- /*
- * variable length array - treat as null dimensioned
- *
- * For VLA variables on sparc, SS12 generated stab entry
- * looks as follows:
- * .stabs "buf:(0,28)=zr(0,4);0;S-12;(0,1)", 0x80, 0, 0, -16
- * Whereas SS12u1 generated stab entry looks like this:
- * .stabs "buf:(0,28)=zr(0,4);0;S0;(0,1)", 0x80, 0, 0, 0
- * On x86, both versions generate the first type of entry.
- * We should be able to parse both.
- */
- cp++;
- if (*cp == '-')
- cp++;
- cp = number(cp, &end);
- end = start;
- } else {
- /*
- * normal fixed-dimension array
- * Stab entry for this looks as follows :
- * .stabs "x:(0,28)=ar(0,4);0;9;(0,3)", 0x80, 0, 40, 0
- */
- cp = number(cp, &end); /* upper */
- }
-
- if (*cp++ != ';')
- expected("arraydef/3", ";", cp - 1);
- (*rtdp)->t_ardef->ad_nelems = end - start + 1;
- cp = tdefdecl(cp, h, &((*rtdp)->t_ardef->ad_contents));
-
- parse_debug(3, cp, "defined array idx type %d %d-%d next ",
- h, start, end);
-
- return (cp);
-}
-
-static void
-enumdef(char *cp, tdesc_t **rtdp)
-{
- elist_t *elp, **prev;
- char *w;
-
- (*rtdp)->t_type = ENUM;
- (*rtdp)->t_emem = NULL;
-
- prev = &((*rtdp)->t_emem);
- while (*cp != ';') {
- elp = xcalloc(sizeof (*elp));
- elp->el_next = NULL;
- *prev = elp;
- cp = name(cp, &w);
- elp->el_name = w;
- cp = number(cp, &elp->el_number);
- parse_debug(3, NULL, "enum %s: %s=%d", tdesc_name(*rtdp),
- elp->el_name, elp->el_number);
- prev = &elp->el_next;
- if (*cp++ != ',')
- expected("enumdef", ",", cp - 1);
- }
-}
-
-static tdesc_t *
-lookup_name(tdesc_t **hash, const char *name1)
-{
- int bucket = compute_sum(name1);
- tdesc_t *tdp, *ttdp = NULL;
-
- for (tdp = hash[bucket]; tdp != NULL; tdp = tdp->t_next) {
- if (tdp->t_name != NULL && strcmp(tdp->t_name, name1) == 0) {
- if (tdp->t_type == STRUCT || tdp->t_type == UNION ||
- tdp->t_type == ENUM || tdp->t_type == INTRINSIC)
- return (tdp);
- if (tdp->t_type == TYPEDEF)
- ttdp = tdp;
- }
- }
- return (ttdp);
-}
-
-tdesc_t *
-lookupname(const char *name1)
-{
- return (lookup_name(name_table, name1));
-}
-
-/*
- * Add a node to the hash queues.
- */
-static void
-addhash(tdesc_t *tdp, int num)
-{
- int hash = HASH(num);
- tdesc_t *ttdp;
- char added_num = 0, added_name = 0;
-
- /*
- * If it already exists in the hash table don't add it again
- * (but still check to see if the name should be hashed).
- */
- ttdp = lookup(num);
-
- if (ttdp == NULL) {
- tdp->t_id = num;
- tdp->t_hash = hash_table[hash];
- hash_table[hash] = tdp;
- added_num = 1;
- }
-
- if (tdp->t_name != NULL) {
- ttdp = lookupname(tdp->t_name);
- if (ttdp == NULL) {
- hash = compute_sum(tdp->t_name);
- tdp->t_next = name_table[hash];
- name_table[hash] = tdp;
- added_name = 1;
- }
- }
- if (!added_num && !added_name) {
- terminate("stabs: broken hash\n");
- }
-}
-
-static int
-compute_sum(const char *w)
-{
- char c;
- int sum;
-
- for (sum = 0; (c = *w) != '\0'; sum += c, w++)
- ;
- return (HASH(sum));
-}
-
-static void
-reset(void)
-{
- longjmp(resetbuf, 1);
-}
-
-void
-check_hash(void)
-{
- tdesc_t *tdp;
- int i;
-
- printf("checking hash\n");
- for (i = 0; i < BUCKETS; i++) {
- if (hash_table[i]) {
- for (tdp = hash_table[i]->t_hash;
- tdp && tdp != hash_table[i];
- tdp = tdp->t_hash)
- continue;
- if (tdp) {
- terminate("cycle in hash bucket %d\n", i);
- return;
- }
- }
-
- if (name_table[i]) {
- for (tdp = name_table[i]->t_next;
- tdp && tdp != name_table[i];
- tdp = tdp->t_next)
- continue;
- if (tdp) {
- terminate("cycle in name bucket %d\n", i);
- return;
- }
- }
- }
- printf("done\n");
-}
-
-/*ARGSUSED1*/
-static int
-resolve_typed_bitfields_cb(void *arg, void *private __unused)
-{
- mlist_t *ml = arg;
- tdesc_t *tdp = ml->ml_type;
-
- debug(3, "Resolving typed bitfields (member %s)\n",
- (ml->ml_name ? ml->ml_name : "(anon)"));
-
- while (tdp) {
- switch (tdp->t_type) {
- case INTRINSIC:
- if (ml->ml_size != tdp->t_intr->intr_nbits) {
- debug(3, "making %d bit intrinsic from %s",
- ml->ml_size, tdesc_name(tdp));
- ml->ml_type = bitintrinsic(tdp, ml->ml_size);
- } else {
- debug(3, "using existing %d bit %s intrinsic",
- ml->ml_size, tdesc_name(tdp));
- ml->ml_type = tdp;
- }
- return (1);
-
- case POINTER:
- case TYPEDEF:
- case VOLATILE:
- case CONST:
- case RESTRICT:
- tdp = tdp->t_tdesc;
- break;
-
- default:
- return (1);
- }
- }
-
- terminate("type chain for bitfield member %s has a NULL", ml->ml_name);
- /*NOTREACHED*/
- return (0);
-}
-
-void
-resolve_typed_bitfields(void)
-{
- (void) list_iter(typedbitfldmems,
- resolve_typed_bitfields_cb, NULL);
-}
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/stabs.c b/cddl/contrib/opensolaris/tools/ctf/cvt/stabs.c
deleted file mode 100644
index c0c68b53e030..000000000000
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/stabs.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Routines used to read stabs data from a file, and to build a tdata structure
- * based on the interesting parts of that data.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <assert.h>
-#include <string.h>
-#include <libgen.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/param.h>
-
-#include "ctftools.h"
-#include "list.h"
-#include "stack.h"
-#include "memory.h"
-#include "traverse.h"
-
-char *curhdr;
-
-/*
- * The stabs generator will sometimes reference types before they've been
- * defined. If this is the case, a TYPEDEF_UNRES tdesc will be generated.
- * Note that this is different from a forward declaration, in which the
- * stab is defined, but is defined as something that doesn't exist yet.
- * When we have read all of the stabs from the file, we can go back and
- * fix up all of the unresolved types. We should be able to fix all of them.
- */
-/*ARGSUSED2*/
-static int
-resolve_tou_node(tdesc_t *node, tdesc_t **nodep, void *private __unused)
-{
- tdesc_t *new;
-
- debug(3, "Trying to resolve %s (%d)\n", tdesc_name(node), node->t_id);
- new = lookup(node->t_id);
-
- if (new == NULL) {
- terminate("Couldn't resolve type %d\n", node->t_id);
- }
-
- debug(3, " Resolving to %d\n", new->t_id);
-
- *nodep = new;
-
- return (1);
-}
-
-/*ARGSUSED*/
-static int
-resolve_fwd_node(tdesc_t *node, tdesc_t **nodep, void *private __unused)
-{
- tdesc_t *new = lookupname(node->t_name);
-
- debug(3, "Trying to unforward %s (%d)\n", tdesc_name(node), node->t_id);
-
- if (!new || (new->t_type != STRUCT && new->t_type != UNION))
- return (0);
-
- debug(3, " Unforwarded to %d\n", new->t_id);
-
- *nodep = new;
-
- return (1);
-}
-
-static tdtrav_cb_f resolve_cbs[] = {
- NULL,
- NULL, /* intrinsic */
- NULL, /* pointer */
- NULL, /* array */
- NULL, /* function */
- NULL, /* struct */
- NULL, /* union */
- NULL, /* enum */
- resolve_fwd_node, /* forward */
- NULL, /* typedef */
- resolve_tou_node, /* typedef unres */
- NULL, /* volatile */
- NULL, /* const */
- NULL, /* restrict */
-};
-
-static void
-resolve_nodes(tdata_t *td)
-{
- debug(2, "Resolving unresolved stabs\n");
-
- (void) iitraverse_hash(td->td_iihash, &td->td_curvgen, resolve_cbs,
- NULL, NULL, td);
-}
-
-static char *
-concat(char *s1, char *s2, int s2strip)
-{
- int savelen = strlen(s2) - s2strip;
- int newlen = (s1 ? strlen(s1) : 0) + savelen + 1;
- char *out;
-
- out = xrealloc(s1, newlen);
- if (s1)
- strncpy(out + strlen(out), s2, savelen);
- else
- strncpy(out, s2, savelen);
-
- out[newlen - 1] = '\0';
-
- return (out);
-}
-
-/*
- * N_FUN stabs come with their arguments in promoted form. In order to get the
- * actual arguments, we need to wait for the N_PSYM stabs that will come towards
- * the end of the function. These routines free the arguments (fnarg_free) we
- * got from the N_FUN stab and add (fnarg_add) the ones from the N_PSYM stabs.
- */
-static void
-fnarg_add(iidesc_t *curfun, iidesc_t *arg)
-{
- curfun->ii_nargs++;
-
- if (curfun->ii_nargs == 1)
- curfun->ii_args = xmalloc(sizeof (tdesc_t *) * FUNCARG_DEF);
- else if (curfun->ii_nargs > FUNCARG_DEF) {
- curfun->ii_args = xrealloc(curfun->ii_args,
- sizeof (tdesc_t *) * curfun->ii_nargs);
- }
-
- curfun->ii_args[curfun->ii_nargs - 1] = arg->ii_dtype;
- arg->ii_dtype = NULL;
-}
-
-static void
-fnarg_free(iidesc_t *ii)
-{
- ii->ii_nargs = 0;
- free(ii->ii_args);
- ii->ii_args = NULL;
-}
-
-/*
- * Read the stabs from the stab ELF section, and turn them into a tdesc tree,
- * assembled under an iidesc list.
- */
-int
-stabs_read(tdata_t *td, Elf *elf, char *file)
-{
- Elf_Scn *scn;
- Elf_Data *data;
- stab_t *stab;
- stk_t *file_stack;
- iidesc_t *iidescp;
- iidesc_t *curfun = NULL;
- char curpath[MAXPATHLEN];
- char *curfile = NULL;
- char *str;
- char *fstr = NULL, *ofstr = NULL;
- int stabidx, stabstridx;
- int nstabs, rc, i;
- int scope = 0;
-
- if (!((stabidx = findelfsecidx(elf, file, ".stab.excl")) >= 0 &&
- (stabstridx = findelfsecidx(elf, file, ".stab.exclstr")) >= 0) &&
- !((stabidx = findelfsecidx(elf, file, ".stab")) >= 0 &&
- (stabstridx = findelfsecidx(elf, file, ".stabstr")) >= 0)) {
- errno = ENOENT;
- return (-1);
- }
-
- file_stack = stack_new(free);
-
- stack_push(file_stack, file);
- curhdr = file;
-
- debug(3, "Found stabs in %d, strings in %d\n", stabidx, stabstridx);
-
- scn = elf_getscn(elf, stabidx);
- data = elf_rawdata(scn, NULL);
- nstabs = data->d_size / sizeof (stab_t);
-
- parse_init(td);
- for (i = 0; i < nstabs; i++) {
- stab = &((stab_t *)data->d_buf)[i];
-
- /* We don't want any local definitions */
- if (stab->n_type == N_LBRAC) {
- scope++;
- debug(3, "stab %d: opening scope (%d)\n", i + 1, scope);
- continue;
- } else if (stab->n_type == N_RBRAC) {
- scope--;
- debug(3, "stab %d: closing scope (%d)\n", i + 1, scope);
- continue;
- } else if (stab->n_type == N_EINCL) {
- /*
- * There's a bug in the 5.2 (Taz) compilers that causes
- * them to emit an extra N_EINCL if there's no actual
- * text in the file being compiled. To work around this
- * bug, we explicitly check to make sure we're not
- * trying to pop a stack that only has the outer scope
- * on it.
- */
- if (stack_level(file_stack) != 1) {
- str = (char *)stack_pop(file_stack);
- free(str);
- curhdr = (char *)stack_peek(file_stack);
- }
- }
-
- /* We only care about a subset of the stabs */
- if (!(stab->n_type == N_FUN || stab->n_type == N_GSYM ||
- stab->n_type == N_LCSYM || stab->n_type == N_LSYM ||
- stab->n_type == N_PSYM || stab->n_type == N_ROSYM ||
- stab->n_type == N_RSYM ||
- stab->n_type == N_STSYM || stab->n_type == N_BINCL ||
- stab->n_type == N_SO || stab->n_type == N_OPT))
- continue;
-
- if ((str = elf_strptr(elf, stabstridx,
- (size_t)stab->n_strx)) == NULL) {
- terminate("%s: Can't find string at %u for stab %d\n",
- file, stab->n_strx, i);
- }
-
- if (stab->n_type == N_BINCL) {
- curhdr = xstrdup(str);
- stack_push(file_stack, curhdr);
- continue;
- } else if (stab->n_type == N_SO) {
- if (str[strlen(str) - 1] != '/') {
- strcpy(curpath, str);
- curfile = basename(curpath);
- }
- continue;
- } else if (stab->n_type == N_OPT) {
- if (strcmp(str, "gcc2_compiled.") == 0) {
- terminate("%s: GCC-generated stabs are "
- "unsupported. Use DWARF instead.\n", file);
- }
- continue;
- }
-
- if (str[strlen(str) - 1] == '\\') {
- int offset = 1;
- /*
- * There's a bug in the compilers that causes them to
- * generate \ for continuations with just -g (this is
- * ok), and \\ for continuations with -g -O (this is
- * broken). This bug is "fixed" in the 6.2 compilers
- * via the elimination of continuation stabs.
- */
- if (str[strlen(str) - 2] == '\\')
- offset = 2;
- fstr = concat(fstr, str, offset);
- continue;
- } else
- fstr = concat(fstr, str, 0);
-
- debug(3, "%4d: .stabs \"%s\", %#x, %d, %hd, %d (from %s)\n", i,
- fstr, stab->n_type, 0, stab->n_desc,
- stab->n_value, curhdr);
-
- if (debug_level >= 3)
- check_hash();
-
- /*
- * Sometimes the compiler stutters, and emits the same stab
- * twice. This is bad for the parser, which will attempt to
- * redefine the type IDs indicated in the stabs. This is
- * compiler bug 4433511.
- */
- if (ofstr && strcmp(fstr, ofstr) == 0) {
- debug(3, "Stutter stab\n");
- free(fstr);
- fstr = NULL;
- continue;
- }
-
- if (ofstr)
- free(ofstr);
- ofstr = fstr;
-
- iidescp = NULL;
-
- if ((rc = parse_stab(stab, fstr, &iidescp)) < 0) {
- terminate("%s: Couldn't parse stab \"%s\" "
- "(source file %s)\n", file, str, curhdr);
- }
-
- if (rc == 0)
- goto parse_loop_end;
-
- /* Make sure the scope tracking is working correctly */
- assert(stab->n_type != N_FUN || (iidescp->ii_type != II_GFUN &&
- iidescp->ii_type != II_SFUN) || scope == 0);
-
- /*
- * The only things we care about that are in local scope are
- * the N_PSYM stabs.
- */
- if (scope && stab->n_type != N_PSYM) {
- if (iidescp)
- iidesc_free(iidescp, NULL);
- goto parse_loop_end;
- }
-
- switch (iidescp->ii_type) {
- case II_SFUN:
- iidescp->ii_owner = xstrdup(curfile);
- /*FALLTHROUGH*/
- case II_GFUN:
- curfun = iidescp;
- fnarg_free(iidescp);
- iidesc_add(td->td_iihash, iidescp);
- break;
-
- case II_SVAR:
- iidescp->ii_owner = xstrdup(curfile);
- /*FALLTHROUGH*/
- case II_GVAR:
- case II_TYPE:
- case II_SOU:
- iidesc_add(td->td_iihash, iidescp);
- break;
-
- case II_PSYM:
- fnarg_add(curfun, iidescp);
- iidesc_free(iidescp, NULL);
- break;
- default:
- aborterr("invalid ii_type %d for stab type %d",
- iidescp->ii_type, stab->n_type);
- }
-
-parse_loop_end:
- fstr = NULL;
- }
-
- if (ofstr)
- free(ofstr);
-
- resolve_nodes(td);
- resolve_typed_bitfields();
- parse_finish(td);
-
- cvt_fixstabs(td);
- cvt_fixups(td, elf_ptrsz(elf));
-
- return (0);
-}
diff --git a/cddl/contrib/opensolaris/tools/ctf/dump/dump.c b/cddl/contrib/opensolaris/tools/ctf/dump/dump.c
index 740485ddff03..5cbf46af1b73 100644
--- a/cddl/contrib/opensolaris/tools/ctf/dump/dump.c
+++ b/cddl/contrib/opensolaris/tools/ctf/dump/dump.c
@@ -24,13 +24,12 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <sys/stat.h>
#include <sys/mman.h>
+#include <err.h>
#include <strings.h>
#include <unistd.h>
#include <stdlib.h>
@@ -97,6 +96,8 @@ typedef struct ctf_data {
caddr_t cd_ctfdata; /* Pointer to the CTF data */
size_t cd_ctflen; /* Length of CTF data */
+ size_t cd_idwidth; /* Size of a type ID, in bytes */
+
/*
* cd_symdata will be non-NULL if the CTF data is being retrieved from
* an ELF file with a symbol table. cd_strdata and cd_nsyms should be
@@ -266,9 +267,8 @@ next_sym(const ctf_data_t *cd, const int symidx, const uchar_t matchtype,
static int
read_data(const ctf_header_t *hp, const ctf_data_t *cd)
{
- void *v = (void *) (cd->cd_ctfdata + hp->cth_objtoff);
- const ushort_t *idp = v;
- ulong_t n = (hp->cth_funcoff - hp->cth_objtoff) / sizeof (ushort_t);
+ const char *v = (void *) (cd->cd_ctfdata + hp->cth_objtoff);
+ ulong_t n = (hp->cth_funcoff - hp->cth_objtoff) / cd->cd_idwidth;
if (flags != F_STATS)
print_line("- Data Objects ");
@@ -287,6 +287,7 @@ read_data(const ctf_header_t *hp, const ctf_data_t *cd)
char *name = NULL;
for (symidx = -1, i = 0; i < (int) n; i++) {
+ uint32_t id = 0;
int nextsym;
if (cd->cd_symdata == NULL || (nextsym = next_sym(cd,
@@ -295,7 +296,9 @@ read_data(const ctf_header_t *hp, const ctf_data_t *cd)
else
symidx = nextsym;
- len = printf(" [%u] %u", i, *idp++);
+ memcpy(&id, v, cd->cd_idwidth);
+ v += cd->cd_idwidth;
+ len = printf(" [%u] %u", i, id);
if (name != NULL)
(void) printf("%*s%s (%u)", (15 - len), "",
name, symidx);
@@ -310,11 +313,10 @@ read_data(const ctf_header_t *hp, const ctf_data_t *cd)
static int
read_funcs(const ctf_header_t *hp, const ctf_data_t *cd)
{
- void *v = (void *) (cd->cd_ctfdata + hp->cth_funcoff);
- const ushort_t *fp = v;
+ const char *v = (void *) (cd->cd_ctfdata + hp->cth_funcoff);
+ uint_t f = 0, info;
- v = (void *) (cd->cd_ctfdata + hp->cth_typeoff);
- const ushort_t *end = v;
+ const char *end = (void *) (cd->cd_ctfdata + hp->cth_typeoff);
ulong_t id;
int symidx;
@@ -331,10 +333,14 @@ read_funcs(const ctf_header_t *hp, const ctf_data_t *cd)
if (hp->cth_funcoff > hp->cth_typeoff)
WARN("file is corrupt -- cth_funcoff > cth_typeoff\n");
- for (symidx = -1, id = 0; fp < end; id++) {
- ushort_t info = *fp++;
- ushort_t kind = CTF_INFO_KIND(info);
- ushort_t n = CTF_INFO_VLEN(info);
+ for (symidx = -1, id = 0; v < end; id++) {
+ info = 0;
+ memcpy(&info, v, cd->cd_idwidth);
+ v += cd->cd_idwidth;
+ ushort_t kind = hp->cth_version == CTF_VERSION_2 ?
+ CTF_V2_INFO_KIND(info) : CTF_V3_INFO_KIND(info);
+ ushort_t n = hp->cth_version == CTF_VERSION_2 ?
+ CTF_V2_INFO_VLEN(info) : CTF_V3_INFO_VLEN(info);
ushort_t i;
int nextsym;
char *name;
@@ -354,7 +360,7 @@ read_funcs(const ctf_header_t *hp, const ctf_data_t *cd)
return (E_ERROR);
}
- if (fp + n > end) {
+ if (v + n * cd->cd_idwidth > end) {
(void) printf(" [%lu] vlen %u extends past section "
"boundary\n", id, n);
return (E_ERROR);
@@ -364,17 +370,24 @@ read_funcs(const ctf_header_t *hp, const ctf_data_t *cd)
(void) printf(" [%lu] FUNC ", id);
if (name != NULL)
(void) printf("(%s) ", name);
- (void) printf("returns: %u args: (", *fp++);
+ memcpy(&f, v, cd->cd_idwidth);
+ v += cd->cd_idwidth;
+ (void) printf("returns: %u args: (", f);
if (n != 0) {
- (void) printf("%u", *fp++);
- for (i = 1; i < n; i++)
- (void) printf(", %u", *fp++);
+ memcpy(&f, v, cd->cd_idwidth);
+ v += cd->cd_idwidth;
+ (void) printf("%u", f);
+ for (i = 1; i < n; i++) {
+ memcpy(&f, v, cd->cd_idwidth);
+ v += cd->cd_idwidth;
+ (void) printf(", %u", f);
+ }
}
(void) printf(")\n");
} else
- fp += n + 1; /* skip to next function definition */
+ v += n * cd->cd_idwidth + 1; /* skip to next function definition */
stats.s_nfunc++;
stats.s_nargs += n;
@@ -387,13 +400,10 @@ read_funcs(const ctf_header_t *hp, const ctf_data_t *cd)
static int
read_types(const ctf_header_t *hp, const ctf_data_t *cd)
{
- void *v = (void *) (cd->cd_ctfdata + hp->cth_typeoff);
- const ctf_type_t *tp = v;
-
- v = (void *) (cd->cd_ctfdata + hp->cth_stroff);
- const ctf_type_t *end = v;
-
+ const char *v = (void *) (cd->cd_ctfdata + hp->cth_typeoff);
+ const char *end = (void *) (cd->cd_ctfdata + hp->cth_stroff);
ulong_t id;
+ uint_t version;
if (flags != F_STATS)
print_line("- Types ");
@@ -407,103 +417,158 @@ read_types(const ctf_header_t *hp, const ctf_data_t *cd)
if (hp->cth_typeoff > hp->cth_stroff)
WARN("file is corrupt -- cth_typeoff > cth_stroff\n");
+ version = hp->cth_version;
+
id = 1;
if (hp->cth_parlabel || hp->cth_parname)
- id += 1 << CTF_PARENT_SHIFT;
+ id += 1ul << (hp->cth_version == CTF_VERSION_2 ?
+ CTF_V2_PARENT_SHIFT : CTF_V3_PARENT_SHIFT);
- for (/* */; tp < end; id++) {
- ulong_t i, n = CTF_INFO_VLEN(tp->ctt_info);
+ for (/* */; v < end; id++) {
+ struct ctf_type_v2 t2;
+ struct ctf_type_v3 t3;
+ ulong_t i, n;
size_t size, increment, vlen = 0;
- int kind = CTF_INFO_KIND(tp->ctt_info);
+ uint_t isroot, name, type;
+ int kind;
+
+ if (version == CTF_VERSION_2) {
+ memcpy(&t2, v, sizeof(t2));
+ name = t2.ctt_name;
+ n = CTF_V2_INFO_VLEN(t2.ctt_info);
+ isroot = CTF_V2_INFO_ISROOT(t2.ctt_info);
+ kind = CTF_V2_INFO_KIND(t2.ctt_info);
+ type = t2.ctt_type;
+
+ if (t2.ctt_size == CTF_V2_LSIZE_SENT) {
+ increment = sizeof (struct ctf_type_v2);
+ size = (size_t)CTF_TYPE_LSIZE(&t2);
+ } else {
+ increment = sizeof (struct ctf_stype_v2);
+ size = t2.ctt_size;
+ }
+ } else {
+ memcpy(&t3, v, sizeof(t3));
+ name = t3.ctt_name;
+ n = CTF_V3_INFO_VLEN(t3.ctt_info);
+ isroot = CTF_V3_INFO_ISROOT(t3.ctt_info);
+ kind = CTF_V3_INFO_KIND(t3.ctt_info);
+ type = t3.ctt_type;
+
+ if (t3.ctt_size == CTF_V3_LSIZE_SENT) {
+ increment = sizeof (struct ctf_type_v3);
+ size = (size_t)CTF_TYPE_LSIZE(&t3);
+ } else {
+ increment = sizeof (struct ctf_stype_v3);
+ size = t3.ctt_size;
+ }
+ }
union {
- const void *ptr;
- ctf_array_t *ap;
- const ctf_member_t *mp;
- const ctf_lmember_t *lmp;
+ const char *ptr;
+ struct ctf_array_v2 *ap2;
+ struct ctf_array_v3 *ap3;
+ const struct ctf_member_v2 *mp2;
+ const struct ctf_member_v3 *mp3;
+ const struct ctf_lmember_v2 *lmp2;
+ const struct ctf_lmember_v3 *lmp3;
const ctf_enum_t *ep;
- const ushort_t *argp;
} u;
+ u.ptr = v + increment;
+
if (flags != F_STATS) {
(void) printf(" %c%lu%c ",
- "[<"[CTF_INFO_ISROOT(tp->ctt_info)], id,
- "]>"[CTF_INFO_ISROOT(tp->ctt_info)]);
+ "[<"[isroot], id, "]>"[isroot]);
}
- if (tp->ctt_size == CTF_LSIZE_SENT) {
- increment = sizeof (ctf_type_t);
- size = (size_t)CTF_TYPE_LSIZE(tp);
- } else {
- increment = sizeof (ctf_stype_t);
- size = tp->ctt_size;
- }
- u.ptr = (const char *)tp + increment;
-
switch (kind) {
case CTF_K_INTEGER:
if (flags != F_STATS) {
- uint_t encoding = *((const uint_t *)u.ptr);
+ uint_t encoding =
+ *((const uint_t *)(const void *)u.ptr);
(void) printf("INTEGER %s encoding=%s offset=%u"
- " bits=%u", ref_to_str(tp->ctt_name, hp,
- cd), int_encoding_to_str(
+ " bits=%u", ref_to_str(name, hp, cd),
+ int_encoding_to_str(
CTF_INT_ENCODING(encoding)),
CTF_INT_OFFSET(encoding),
CTF_INT_BITS(encoding));
}
- vlen = sizeof (uint_t);
+ vlen = sizeof (uint32_t);
break;
case CTF_K_FLOAT:
if (flags != F_STATS) {
- uint_t encoding = *((const uint_t *)u.ptr);
+ uint_t encoding =
+ *((const uint_t *)(const void *)u.ptr);
(void) printf("FLOAT %s encoding=%s offset=%u "
- "bits=%u", ref_to_str(tp->ctt_name, hp,
- cd), fp_encoding_to_str(
+ "bits=%u", ref_to_str(name, hp, cd),
+ fp_encoding_to_str(
CTF_FP_ENCODING(encoding)),
CTF_FP_OFFSET(encoding),
CTF_FP_BITS(encoding));
}
- vlen = sizeof (uint_t);
+ vlen = sizeof (uint32_t);
break;
case CTF_K_POINTER:
if (flags != F_STATS) {
(void) printf("POINTER %s refers to %u",
- ref_to_str(tp->ctt_name, hp, cd),
- tp->ctt_type);
+ ref_to_str(name, hp, cd), type);
}
break;
- case CTF_K_ARRAY:
+ case CTF_K_ARRAY: {
+ uint_t contents, index, nelems;
+
+ if (version == CTF_VERSION_2) {
+ contents = u.ap2->cta_contents;
+ index = u.ap2->cta_index;
+ nelems = u.ap2->cta_nelems;
+ } else {
+ contents = u.ap3->cta_contents;
+ index = u.ap3->cta_index;
+ nelems = u.ap3->cta_nelems;
+ }
if (flags != F_STATS) {
(void) printf("ARRAY %s content: %u index: %u "
- "nelems: %u\n", ref_to_str(tp->ctt_name,
- hp, cd), u.ap->cta_contents,
- u.ap->cta_index, u.ap->cta_nelems);
+ "nelems: %u\n", ref_to_str(name, hp, cd),
+ contents, index, nelems);
}
- vlen = sizeof (ctf_array_t);
+ if (version == 2)
+ vlen = sizeof (struct ctf_array_v2);
+ else
+ vlen = sizeof (struct ctf_array_v3);
break;
+ }
+
+ case CTF_K_FUNCTION: {
+ uint_t arg = 0;
- case CTF_K_FUNCTION:
if (flags != F_STATS) {
(void) printf("FUNCTION %s returns: %u args: (",
- ref_to_str(tp->ctt_name, hp, cd),
- tp->ctt_type);
+ ref_to_str(name, hp, cd), type);
if (n != 0) {
- (void) printf("%u", *u.argp++);
- for (i = 1; i < n; i++, u.argp++)
- (void) printf(", %u", *u.argp);
+ memcpy(&arg, u.ptr, cd->cd_idwidth);
+ u.ptr += cd->cd_idwidth;
+ (void) printf("%u", arg);
+ for (i = 1; i < n;
+ i++, u.ptr += cd->cd_idwidth) {
+ memcpy(&arg, u.ptr,
+ cd->cd_idwidth);
+ (void) printf(", %u", arg);
+ }
}
(void) printf(")");
}
- vlen = sizeof (ushort_t) * (n + (n & 1));
+ vlen = roundup2(cd->cd_idwidth * n, 4);
break;
+ }
case CTF_K_STRUCT:
case CTF_K_UNION:
@@ -527,36 +592,64 @@ read_types(const ctf_header_t *hp, const ctf_data_t *cd)
if (flags != F_STATS) {
(void) printf(" %s (%zd bytes)\n",
- ref_to_str(tp->ctt_name, hp, cd), size);
-
- if (size >= CTF_LSTRUCT_THRESH) {
- for (i = 0; i < n; i++, u.lmp++) {
- (void) printf(
- "\t%s type=%u off=%llu\n",
- ref_to_str(u.lmp->ctlm_name,
- hp, cd), u.lmp->ctlm_type,
- (unsigned long long)
- CTF_LMEM_OFFSET(u.lmp));
+ ref_to_str(name, hp, cd), size);
+
+ if (version == CTF_VERSION_2) {
+ if (size >= CTF_V2_LSTRUCT_THRESH) {
+ for (i = 0; i < n; i++, u.lmp2++) {
+ (void) printf(
+ "\t%s type=%u off=%llu\n",
+ ref_to_str(u.lmp2->ctlm_name,
+ hp, cd), u.lmp2->ctlm_type,
+ (unsigned long long)
+ CTF_LMEM_OFFSET(u.lmp2));
+ }
+ } else {
+ for (i = 0; i < n; i++, u.mp2++) {
+ (void) printf(
+ "\t%s type=%u off=%u\n",
+ ref_to_str(u.mp2->ctm_name,
+ hp, cd), u.mp2->ctm_type,
+ u.mp2->ctm_offset);
+ }
}
} else {
- for (i = 0; i < n; i++, u.mp++) {
- (void) printf(
- "\t%s type=%u off=%u\n",
- ref_to_str(u.mp->ctm_name,
- hp, cd), u.mp->ctm_type,
- u.mp->ctm_offset);
+ if (size >= CTF_V3_LSTRUCT_THRESH) {
+ for (i = 0; i < n; i++, u.lmp3++) {
+ (void) printf(
+ "\t%s type=%u off=%llu\n",
+ ref_to_str(u.lmp3->ctlm_name,
+ hp, cd), u.lmp3->ctlm_type,
+ (unsigned long long)
+ CTF_LMEM_OFFSET(u.lmp3));
+ }
+ } else {
+ for (i = 0; i < n; i++, u.mp3++) {
+ (void) printf(
+ "\t%s type=%u off=%u\n",
+ ref_to_str(u.mp3->ctm_name,
+ hp, cd), u.mp3->ctm_type,
+ u.mp3->ctm_offset);
+ }
}
}
}
- vlen = n * (size >= CTF_LSTRUCT_THRESH ?
- sizeof (ctf_lmember_t) : sizeof (ctf_member_t));
+ if (version == CTF_VERSION_2) {
+ vlen = n * (size >= CTF_V2_LSTRUCT_THRESH ?
+ sizeof (struct ctf_lmember_v2) :
+ sizeof (struct ctf_member_v2));
+ } else {
+ vlen = n * (size >= CTF_V3_LSTRUCT_THRESH ?
+ sizeof (struct ctf_lmember_v3) :
+ sizeof (struct ctf_member_v3));
+ }
break;
case CTF_K_ENUM:
if (flags != F_STATS) {
(void) printf("ENUM %s\n",
- ref_to_str(tp->ctt_name, hp, cd));
+ ref_to_str(name, hp, cd));
for (i = 0; i < n; i++, u.ep++) {
(void) printf("\t%s = %d\n",
@@ -574,39 +667,35 @@ read_types(const ctf_header_t *hp, const ctf_data_t *cd)
case CTF_K_FORWARD:
if (flags != F_STATS) {
(void) printf("FORWARD %s",
- ref_to_str(tp->ctt_name, hp, cd));
+ ref_to_str(name, hp, cd));
}
break;
case CTF_K_TYPEDEF:
if (flags != F_STATS) {
(void) printf("TYPEDEF %s refers to %u",
- ref_to_str(tp->ctt_name, hp, cd),
- tp->ctt_type);
+ ref_to_str(name, hp, cd), type);
}
break;
case CTF_K_VOLATILE:
if (flags != F_STATS) {
(void) printf("VOLATILE %s refers to %u",
- ref_to_str(tp->ctt_name, hp, cd),
- tp->ctt_type);
+ ref_to_str(name, hp, cd), type);
}
break;
case CTF_K_CONST:
if (flags != F_STATS) {
(void) printf("CONST %s refers to %u",
- ref_to_str(tp->ctt_name, hp, cd),
- tp->ctt_type);
+ ref_to_str(name, hp, cd), type);
}
break;
case CTF_K_RESTRICT:
if (flags != F_STATS) {
(void) printf("RESTRICT %s refers to %u",
- ref_to_str(tp->ctt_name, hp, cd),
- tp->ctt_type);
+ ref_to_str(name, hp, cd), type);
}
break;
@@ -624,7 +713,7 @@ read_types(const ctf_header_t *hp, const ctf_data_t *cd)
stats.s_ntypes++;
stats.s_types[kind]++;
- tp = (ctf_type_t *)((uintptr_t)tp + increment + vlen);
+ v += increment + vlen;
}
return (E_SUCCESS);
@@ -767,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,
@@ -935,14 +1024,16 @@ main(int argc, char *argv[])
if (pp->ctp_magic != CTF_MAGIC)
die("%s does not appear to contain CTF data\n", filename);
- if (pp->ctp_version == CTF_VERSION) {
+ if (pp->ctp_version >= CTF_VERSION_2) {
v = (void *) cd.cd_ctfdata;
hp = v;
cd.cd_ctfdata = (caddr_t)cd.cd_ctfdata + sizeof (ctf_header_t);
+ cd.cd_idwidth = pp->ctp_version == CTF_VERSION_2 ? 2 : 4;
+
if (cd.cd_ctflen < sizeof (ctf_header_t)) {
die("%s does not contain a v%d CTF header\n", filename,
- CTF_VERSION);
+ pp->ctp_version);
}
} else {