summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/lib/libdtrace/common/dt_aggregate.c42
-rw-r--r--usr/src/lib/libdtrace_jni/common/dtj_consume.c192
-rw-r--r--usr/src/lib/libdtrace_jni/common/dtj_jnitab.c41
-rw-r--r--usr/src/lib/libdtrace_jni/common/dtrace_jni.c2
-rw-r--r--usr/src/lib/libdtrace_jni/common/dtrace_jni.h15
-rw-r--r--usr/src/lib/libdtrace_jni/java/Makefile3
-rw-r--r--usr/src/lib/libdtrace_jni/java/docs/html/JavaDTraceAPI.html8
-rw-r--r--usr/src/lib/libdtrace_jni/java/docs/html/fast.html2
-rw-r--r--usr/src/lib/libdtrace_jni/java/docs/images/JavaDTraceAPI.gifbin72848 -> 75631 bytes
-rw-r--r--usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/KernelStackRecord.java25
-rw-r--r--usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/KernelSymbolRecord.java240
-rw-r--r--usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LocalConsumer.java23
-rw-r--r--usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/PrintfRecord.java4
-rw-r--r--usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ProbeData.java197
-rw-r--r--usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ScalarRecord.java86
-rw-r--r--usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/SymbolValueRecord.java52
-rw-r--r--usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Tuple.java101
-rw-r--r--usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/UserStackRecord.java31
-rw-r--r--usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/UserSymbolRecord.java469
-rw-r--r--usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/package.html2
-rw-r--r--usr/src/pkgdefs/SUNWdtrc/prototype_doc8
21 files changed, 1389 insertions, 154 deletions
diff --git a/usr/src/lib/libdtrace/common/dt_aggregate.c b/usr/src/lib/libdtrace/common/dt_aggregate.c
index 922dec49be..1d3b1f0f35 100644
--- a/usr/src/lib/libdtrace/common/dt_aggregate.c
+++ b/usr/src/lib/libdtrace/common/dt_aggregate.c
@@ -2,9 +2,8 @@
* 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.
+ * 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.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -729,16 +729,36 @@ dt_aggregate_keycmp(const void *lhs, const void *rhs)
break;
default:
- for (j = 0; j < lrec->dtrd_size; j++) {
- lval = ((uint8_t *)ldata)[j];
- rval = ((uint8_t *)rdata)[j];
+ switch (lrec->dtrd_action) {
+ case DTRACEACT_UMOD:
+ case DTRACEACT_UADDR:
+ case DTRACEACT_USYM:
+ for (j = 0; j < 2; j++) {
+ /* LINTED - alignment */
+ lval = ((uint64_t *)ldata)[j];
+ /* LINTED - alignment */
+ rval = ((uint64_t *)rdata)[j];
+
+ if (lval < rval)
+ return (DT_LESSTHAN);
+
+ if (lval > rval)
+ return (DT_GREATERTHAN);
+ }
- if (lval < rval)
- return (DT_LESSTHAN);
+ break;
- if (lval > rval)
- return (DT_GREATERTHAN);
+ default:
+ for (j = 0; j < lrec->dtrd_size; j++) {
+ lval = ((uint8_t *)ldata)[j];
+ rval = ((uint8_t *)rdata)[j];
+ if (lval < rval)
+ return (DT_LESSTHAN);
+
+ if (lval > rval)
+ return (DT_GREATERTHAN);
+ }
}
continue;
diff --git a/usr/src/lib/libdtrace_jni/common/dtj_consume.c b/usr/src/lib/libdtrace_jni/common/dtj_consume.c
index 952e7f3225..e656ff5ba5 100644
--- a/usr/src/lib/libdtrace_jni/common/dtj_consume.c
+++ b/usr/src/lib/libdtrace_jni/common/dtj_consume.c
@@ -76,9 +76,15 @@ static jobject dtj_new_stack_record(const caddr_t, const dtrace_recdesc_t *,
dtj_java_consumer_t *);
static jobject dtj_new_probedata_stack_record(const dtrace_probedata_t *,
const dtrace_recdesc_t *, dtj_java_consumer_t *);
+static jobject dtj_new_symbol_record(const caddr_t, const dtrace_recdesc_t *,
+ dtj_java_consumer_t *);
+static jobject dtj_new_probedata_symbol_record(const dtrace_probedata_t *,
+ const dtrace_recdesc_t *, dtj_java_consumer_t *);
/* Aggregation data */
static jobject dtj_new_tuple_stack_record(const dtrace_aggdata_t *,
const dtrace_recdesc_t *, const char *, dtj_java_consumer_t *);
+static jobject dtj_new_tuple_symbol_record(const dtrace_aggdata_t *,
+ const dtrace_recdesc_t *, const char *, dtj_java_consumer_t *);
static jobject dtj_new_distribution(const dtrace_aggdata_t *,
const dtrace_recdesc_t *, dtj_java_consumer_t *);
static jobject dtj_new_aggval(dtj_java_consumer_t *, const dtrace_aggdata_t *,
@@ -92,9 +98,10 @@ static void dtj_aggwalk_init(dtj_java_consumer_t *);
static int dtj_agghandler(const dtrace_bufdata_t *, dtj_java_consumer_t *);
static boolean_t dtj_is_included(const dtrace_aggdata_t *,
dtj_java_consumer_t *);
-static void dtj_attach_frames(dtj_java_consumer_t *, jobject,
- jobjectArray);
+static void dtj_attach_frames(dtj_java_consumer_t *, jobject, jobjectArray);
+static void dtj_attach_name(dtj_java_consumer_t *, jobject, jstring);
static boolean_t dtj_is_stack_action(dtrace_actkind_t);
+static boolean_t dtj_is_symbol_action(dtrace_actkind_t);
static int dtj_clear(const dtrace_aggdata_t *, void *);
/*
@@ -134,12 +141,6 @@ dtj_set_callback_handlers(dtj_java_consumer_t *jc)
dtrace_hdl_t *dtp = jc->dtjj_consumer->dtjc_dtp;
dtrace_optval_t optval;
- /*
- * The user argument to the bufhandler is the lookup key used to obtain
- * the thread-specific java consumer. The java consumer contains JNI
- * state specific to either the consumer loop or the getAggregate()
- * call.
- */
if (dtrace_handle_buffered(dtp, &dtj_bufhandler, NULL) == -1) {
dtj_throw_dtrace_exception(jc,
"failed to establish buffered handler: %s",
@@ -562,16 +563,17 @@ dtj_recdata(dtj_java_consumer_t *jc, uint32_t size, caddr_t addr)
{
JNIEnv *jenv = jc->dtjj_jenv;
jobject jobj;
+ jobject jrec;
switch (size) {
case 1:
- jobj = (*jenv)->NewObject(jenv, g_byte_jc,
- g_byteinit_jm, *((char *)addr));
+ jobj = (*jenv)->NewObject(jenv, g_int_jc,
+ g_intinit_jm, (int)(*((uint8_t *)addr)));
break;
case 2:
- jobj = (*jenv)->NewObject(jenv, g_short_jc,
+ jobj = (*jenv)->NewObject(jenv, g_int_jc,
/* LINTED - alignment */
- g_shortinit_jm, *((int16_t *)addr));
+ g_intinit_jm, (int)(*((uint16_t *)addr)));
break;
case 4:
jobj = (*jenv)->NewObject(jenv, g_int_jc,
@@ -588,7 +590,15 @@ dtj_recdata(dtj_java_consumer_t *jc, uint32_t size, caddr_t addr)
break;
}
- return (jobj);
+ if (!jobj) {
+ return (NULL); /* OutOfMemoryError pending */
+ }
+
+ jrec = (*jenv)->NewObject(jenv, g_scalar_jc,
+ g_scalarinit_jm, jobj, size);
+ (*jenv)->DeleteLocalRef(jenv, jobj);
+
+ return (jrec);
}
/*
@@ -909,6 +919,9 @@ dtj_chew(const dtrace_probedata_t *data, void *arg)
if (dtj_is_stack_action(rec->dtrd_action)) {
jobj = dtj_new_probedata_stack_record(data,
rec, jc);
+ } else if (dtj_is_symbol_action(rec->dtrd_action)) {
+ jobj = dtj_new_probedata_symbol_record(data,
+ rec, jc);
} else {
jobj = dtj_recdata(jc, rec->dtrd_size,
(data->dtpda_data + rec->dtrd_offset));
@@ -1095,6 +1108,26 @@ dtj_bufhandler(const dtrace_bufdata_t *bufdata, void *arg)
return (DTRACE_HANDLE_ABORT);
}
break;
+ case DTRACEACT_USYM:
+ case DTRACEACT_UADDR:
+ case DTRACEACT_UMOD:
+ case DTRACEACT_SYM:
+ case DTRACEACT_MOD:
+ /* stand-alone symbol lookup action */
+ jstr = (*jenv)->NewStringUTF(jenv, s);
+ if (!jstr) {
+ /* OutOfMemoryError pending */
+ return (DTRACE_HANDLE_ABORT);
+ }
+ (*jenv)->CallVoidMethod(jenv, jc->dtjj_probedata,
+ g_pdataadd_symbol_jm,
+ jc->dtjj_consumer->dtjc_probedata_rec_i, jstr);
+ (*jenv)->DeleteLocalRef(jenv, jstr);
+ if ((*jenv)->ExceptionCheck(jenv)) {
+ WRAP_EXCEPTION(jenv);
+ return (DTRACE_HANDLE_ABORT);
+ }
+ break;
default:
/*
* The record handler dtj_chewrec() defers nothing else to this
@@ -1122,6 +1155,24 @@ dtj_is_stack_action(dtrace_actkind_t act)
return (stack_action);
}
+static boolean_t
+dtj_is_symbol_action(dtrace_actkind_t act)
+{
+ boolean_t symbol_action;
+ switch (act) {
+ case DTRACEACT_USYM:
+ case DTRACEACT_UADDR:
+ case DTRACEACT_UMOD:
+ case DTRACEACT_SYM:
+ case DTRACEACT_MOD:
+ symbol_action = B_TRUE;
+ break;
+ default:
+ symbol_action = B_FALSE;
+ }
+ return (symbol_action);
+}
+
/*
* Called by get_aggregate() to clear only those aggregations specified by the
* caller.
@@ -1229,6 +1280,58 @@ dtj_new_tuple_stack_record(const dtrace_aggdata_t *data,
dtj_attach_frames(jc, jobj, frames);
(*jenv)->DeleteLocalRef(jenv, frames);
if ((*jenv)->ExceptionCheck(jenv)) {
+ WRAP_EXCEPTION(jenv);
+ return (NULL);
+ }
+
+ return (jobj);
+}
+
+static jobject
+dtj_new_probedata_symbol_record(const dtrace_probedata_t *data,
+ const dtrace_recdesc_t *rec, dtj_java_consumer_t *jc)
+{
+ caddr_t addr;
+
+ addr = data->dtpda_data + rec->dtrd_offset;
+ return (dtj_new_symbol_record(addr, rec, jc));
+}
+
+static jobject
+dtj_new_tuple_symbol_record(const dtrace_aggdata_t *data,
+ const dtrace_recdesc_t *rec, const char *s, dtj_java_consumer_t *jc)
+{
+ caddr_t addr;
+ JNIEnv *jenv = jc->dtjj_jenv;
+
+ jobject jobj = NULL; /* tuple element */
+ jstring jstr = NULL; /* lookup value */
+ jstring tstr = NULL; /* trimmed lookup value */
+
+ addr = data->dtada_data + rec->dtrd_offset;
+ jobj = dtj_new_symbol_record(addr, rec, jc);
+ if (!jobj) {
+ return (NULL); /* java exception pending */
+ }
+
+ /* Get symbol lookup */
+ jstr = (*jenv)->NewStringUTF(jenv, s);
+ if (!jstr) {
+ /* OutOfMemoryError pending */
+ (*jenv)->DeleteLocalRef(jenv, jobj);
+ return (NULL);
+ }
+ /* Trim leading and trailing whitespace */
+ tstr = (*jenv)->CallObjectMethod(jenv, jstr, g_trim_jm);
+ /* trim() returns a new string; don't leak the old one */
+ (*jenv)->DeleteLocalRef(jenv, jstr);
+ jstr = tstr;
+ tstr = NULL;
+
+ dtj_attach_name(jc, jobj, jstr);
+ (*jenv)->DeleteLocalRef(jenv, jstr);
+ if ((*jenv)->ExceptionCheck(jenv)) {
+ WRAP_EXCEPTION(jenv);
return (NULL);
}
@@ -1249,7 +1352,7 @@ dtj_aggwalk_init(dtj_java_consumer_t *jc)
}
static jobject
-dtj_new_stack_record(caddr_t addr, const dtrace_recdesc_t *rec,
+dtj_new_stack_record(const caddr_t addr, const dtrace_recdesc_t *rec,
dtj_java_consumer_t *jc)
{
JNIEnv *jenv = jc->dtjj_jenv;
@@ -1306,6 +1409,48 @@ dtj_new_stack_record(caddr_t addr, const dtrace_recdesc_t *rec,
return (stack);
}
+static jobject
+dtj_new_symbol_record(const caddr_t addr, const dtrace_recdesc_t *rec,
+ dtj_java_consumer_t *jc)
+{
+ JNIEnv *jenv = jc->dtjj_jenv;
+
+ dtrace_actkind_t act;
+ uint64_t *pc;
+ pid_t pid = -1;
+
+ jobject symbol = NULL; /* return value */
+
+ act = rec->dtrd_action;
+ switch (act) {
+ case DTRACEACT_SYM:
+ case DTRACEACT_MOD:
+ /* LINTED - alignment */
+ pc = (uint64_t *)addr;
+ symbol = (*jenv)->NewObject(jenv, g_symbol_jc,
+ g_symbolinit_jm, *pc);
+ break;
+ case DTRACEACT_USYM:
+ case DTRACEACT_UADDR:
+ case DTRACEACT_UMOD:
+ /* Get pid of user process */
+ pc = (uint64_t *)(uintptr_t)addr;
+ pid = (pid_t)*pc;
+ ++pc;
+ symbol = (*jenv)->NewObject(jenv, g_usymbol_jc,
+ g_usymbolinit_jm, pid, *pc);
+ break;
+ default:
+ dtj_throw_illegal_argument(jenv,
+ "Expected stack action, got %d\n", act);
+ }
+ if ((*jenv)->ExceptionCheck(jenv)) {
+ WRAP_EXCEPTION(jenv);
+ return (NULL);
+ }
+ return (symbol);
+}
+
/*
* Return NULL if java exception pending, otherwise return Distribution value.
*/
@@ -1408,6 +1553,18 @@ dtj_attach_frames(dtj_java_consumer_t *jc, jobject stack,
}
}
+static void
+dtj_attach_name(dtj_java_consumer_t *jc, jobject symbol, jstring s)
+{
+ JNIEnv *jenv = jc->dtjj_jenv;
+
+ if ((*jenv)->IsInstanceOf(jenv, symbol, g_symbol_jc)) {
+ (*jenv)->CallVoidMethod(jenv, symbol, g_symbolset_name_jm, s);
+ } else if ((*jenv)->IsInstanceOf(jenv, symbol, g_usymbol_jc)) {
+ (*jenv)->CallVoidMethod(jenv, symbol, g_usymbolset_name_jm, s);
+ }
+}
+
/*
* Note: It is not valid to look outside the current libdtrace record in the
* given aggdata (except to get the aggregation ID from the first record).
@@ -1541,6 +1698,13 @@ dtj_agghandler(const dtrace_bufdata_t *bufdata, dtj_java_consumer_t *jc)
case DTRACEACT_JSTACK:
jobj = dtj_new_tuple_stack_record(aggdata, rec, s, jc);
break;
+ case DTRACEACT_USYM:
+ case DTRACEACT_UADDR:
+ case DTRACEACT_UMOD:
+ case DTRACEACT_SYM:
+ case DTRACEACT_MOD:
+ jobj = dtj_new_tuple_symbol_record(aggdata, rec, s, jc);
+ break;
default:
jobj = dtj_recdata(jc, rec->dtrd_size,
(aggdata->dtada_data + rec->dtrd_offset));
diff --git a/usr/src/lib/libdtrace_jni/common/dtj_jnitab.c b/usr/src/lib/libdtrace_jni/common/dtj_jnitab.c
index f0f4cc6c8e..906a262a60 100644
--- a/usr/src/lib/libdtrace_jni/common/dtj_jnitab.c
+++ b/usr/src/lib/libdtrace_jni/common/dtj_jnitab.c
@@ -109,6 +109,7 @@ jmethodID g_pdataadd_jm = 0;
jmethodID g_pdataadd_rec_jm = 0;
jmethodID g_pdataadd_trace_jm = 0;
jmethodID g_pdataadd_stack_jm = 0;
+jmethodID g_pdataadd_symbol_jm = 0;
jmethodID g_pdataadd_printf_jm = 0;
jmethodID g_pdataadd_printa_jm = 0;
jmethodID g_pdatainvalidate_printa_jm = 0;
@@ -197,6 +198,20 @@ jmethodID g_distinit_jm = 0;
jclass g_ldist_jc = 0;
jmethodID g_ldistinit_jm = 0;
+/* KernelSymbolRecord */
+jclass g_symbol_jc = 0;
+jmethodID g_symbolinit_jm = 0;
+jmethodID g_symbolset_name_jm = 0;
+
+/* UserSymbolRecord */
+jclass g_usymbol_jc = 0;
+jmethodID g_usymbolinit_jm = 0;
+jmethodID g_usymbolset_name_jm = 0;
+
+/* ScalarRecord */
+jclass g_scalar_jc = 0;
+jmethodID g_scalarinit_jm = 0;
+
static dtj_status_t
dtj_table_load(JNIEnv *jenv)
@@ -292,12 +307,14 @@ dtj_table_load(JNIEnv *jenv)
"(IILorg/opensolaris/os/dtrace/ProbeDescription;"
"Lorg/opensolaris/os/dtrace/Flow;I)V" },
{ JMETHOD, &g_pdataadd_jm, "addDataElement",
- "(Ljava/lang/Object;)V" },
+ "(Lorg/opensolaris/os/dtrace/Record;)V" },
{ JMETHOD, &g_pdataadd_rec_jm, "addRecord",
"(Lorg/opensolaris/os/dtrace/Record;)V" },
{ JMETHOD, &g_pdataadd_trace_jm, "addTraceRecord", "(I)V" },
{ JMETHOD, &g_pdataadd_stack_jm, "addStackRecord",
"(ILjava/lang/String;)V" },
+ { JMETHOD, &g_pdataadd_symbol_jm, "addSymbolRecord",
+ "(ILjava/lang/String;)V" },
{ JMETHOD, &g_pdataadd_printf_jm, "addPrintfRecord", "()V" },
{ JMETHOD, &g_pdataadd_printa_jm, "addPrintaRecord", "(JZ)V" },
{ JMETHOD, &g_pdatainvalidate_printa_jm,
@@ -354,7 +371,7 @@ dtj_table_load(JNIEnv *jenv)
{ JCLASS, &g_tuple_jc, "org/opensolaris/os/dtrace/Tuple" },
{ JMETHOD, &g_tupleinit_jm, CONSTRUCTOR, "()V" },
{ JMETHOD, &g_tupleadd_jm, "addElement",
- "(Ljava/lang/Object;)V" },
+ "(Lorg/opensolaris/os/dtrace/ValueRecord;)V" },
{ JMETHOD, &g_tuplesize_jm, "size", "()I" },
{ JFIELD_STATIC, &g_tuple_EMPTY_jsf, "EMPTY",
"Lorg/opensolaris/os/dtrace/Tuple;" },
@@ -425,6 +442,26 @@ dtj_table_load(JNIEnv *jenv)
"org/opensolaris/os/dtrace/LinearDistribution" },
{ JMETHOD, &g_ldistinit_jm, CONSTRUCTOR, "(JJ[J)V" },
+ /* KernelSymbolRecord */
+ { JCLASS, &g_symbol_jc,
+ "org/opensolaris/os/dtrace/KernelSymbolRecord" },
+ { JMETHOD, &g_symbolinit_jm, CONSTRUCTOR, "(J)V" },
+ { JMETHOD, &g_symbolset_name_jm, "setSymbol",
+ "(Ljava/lang/String;)V" },
+
+ /* UserSymbolRecord */
+ { JCLASS, &g_usymbol_jc,
+ "org/opensolaris/os/dtrace/UserSymbolRecord" },
+ { JMETHOD, &g_usymbolinit_jm, CONSTRUCTOR, "(IJ)V" },
+ { JMETHOD, &g_usymbolset_name_jm, "setSymbol",
+ "(Ljava/lang/String;)V" },
+
+ /* ScalarRecord */
+ { JCLASS, &g_scalar_jc,
+ "org/opensolaris/os/dtrace/ScalarRecord" },
+ { JMETHOD, &g_scalarinit_jm, CONSTRUCTOR,
+ "(Ljava/lang/Object;I)V" },
+
{ DTJ_TYPE_END }
};
diff --git a/usr/src/lib/libdtrace_jni/common/dtrace_jni.c b/usr/src/lib/libdtrace_jni/common/dtrace_jni.c
index 051db0f2af..4f68f6787e 100644
--- a/usr/src/lib/libdtrace_jni/common/dtrace_jni.c
+++ b/usr/src/lib/libdtrace_jni/common/dtrace_jni.c
@@ -84,7 +84,7 @@
* LocalConsumer itself.
*/
-#define DTRACE_JNI_VERSION 1
+#define DTRACE_JNI_VERSION 2
#define FIRST_HANDLE 0 /* sequence-generated consumer ID */
#define NO_HANDLE -1
diff --git a/usr/src/lib/libdtrace_jni/common/dtrace_jni.h b/usr/src/lib/libdtrace_jni/common/dtrace_jni.h
index 7df12ce930..1366ac14b1 100644
--- a/usr/src/lib/libdtrace_jni/common/dtrace_jni.h
+++ b/usr/src/lib/libdtrace_jni/common/dtrace_jni.h
@@ -313,6 +313,7 @@ extern jmethodID g_pdataadd_jm;
extern jmethodID g_pdataadd_rec_jm;
extern jmethodID g_pdataadd_trace_jm;
extern jmethodID g_pdataadd_stack_jm;
+extern jmethodID g_pdataadd_symbol_jm;
extern jmethodID g_pdataadd_printf_jm;
extern jmethodID g_pdataadd_printa_jm;
extern jmethodID g_pdatainvalidate_printa_jm;
@@ -401,6 +402,20 @@ extern jmethodID g_distinit_jm;
extern jclass g_ldist_jc;
extern jmethodID g_ldistinit_jm;
+/* KernelSymbolRecord */
+extern jclass g_symbol_jc;
+extern jmethodID g_symbolinit_jm;
+extern jmethodID g_symbolset_name_jm;
+
+/* UserSymbolRecord */
+extern jclass g_usymbol_jc;
+extern jmethodID g_usymbolinit_jm;
+extern jmethodID g_usymbolset_name_jm;
+
+/* ScalarRecord */
+extern jclass g_scalar_jc;
+extern jmethodID g_scalarinit_jm;
+
/*
* Populates the java class references and associated method and field IDs
* declared in this file (above).
diff --git a/usr/src/lib/libdtrace_jni/java/Makefile b/usr/src/lib/libdtrace_jni/java/Makefile
index 774fa09034..14514ad857 100644
--- a/usr/src/lib/libdtrace_jni/java/Makefile
+++ b/usr/src/lib/libdtrace_jni/java/Makefile
@@ -125,6 +125,7 @@ API_CLASSNAMES=\
Flow \
InterfaceAttributes \
KernelStackRecord \
+ KernelSymbolRecord \
LinearDistribution \
LocalConsumer \
LogDistribution \
@@ -148,8 +149,10 @@ API_CLASSNAMES=\
StackFrame \
StackValueRecord \
SumValue \
+ SymbolValueRecord \
Tuple \
UserStackRecord \
+ UserSymbolRecord \
Utility \
ValueRecord
diff --git a/usr/src/lib/libdtrace_jni/java/docs/html/JavaDTraceAPI.html b/usr/src/lib/libdtrace_jni/java/docs/html/JavaDTraceAPI.html
index 92bb4d641c..7696d167ed 100644
--- a/usr/src/lib/libdtrace_jni/java/docs/html/JavaDTraceAPI.html
+++ b/usr/src/lib/libdtrace_jni/java/docs/html/JavaDTraceAPI.html
@@ -185,11 +185,15 @@
<AREA HREF="../api/org/opensolaris/os/dtrace/ScalarRecord.html"
ALT="ScalarRecord javadoc API"
SHAPE=RECT
- COORDS="364,333,477,375">
+ COORDS="337,333,414,393">
<AREA HREF="../api/org/opensolaris/os/dtrace/StackValueRecord.html"
ALT="StackValueRecord javadoc API"
SHAPE=RECT
- COORDS="487,333,633,375">
+ COORDS="423,333,496,412">
+ <AREA HREF="../api/org/opensolaris/os/dtrace/SymbolValueRecord.html"
+ ALT="SymbolValueRecord javadoc API"
+ SHAPE=RECT
+ COORDS="507,333,579,412">
<AREA HREF="../api/org/opensolaris/os/dtrace/SumValue.html"
ALT="SumValue javadoc API"
SHAPE=RECT
diff --git a/usr/src/lib/libdtrace_jni/java/docs/html/fast.html b/usr/src/lib/libdtrace_jni/java/docs/html/fast.html
index c820d77306..1f5104723c 100644
--- a/usr/src/lib/libdtrace_jni/java/docs/html/fast.html
+++ b/usr/src/lib/libdtrace_jni/java/docs/html/fast.html
@@ -517,7 +517,7 @@ action will not be included in the requested aggregate.
The <a href="http://www.opensolaris.org/os/community/dtrace/">
OpenSolaris DTrace page</a> has links to resources to help you learn
DTrace. In particular, you should read the <a
-href="http://docs.sun.com/db/doc/817-6223"><i>Solaris Dynamic Tracing
+href="http://docs.sun.com/app/docs/doc/817-6223"><i>Solaris Dynamic Tracing
Guide</i></a>.<br>
<br>
Try the example Java programs on this page with other D scripts. You
diff --git a/usr/src/lib/libdtrace_jni/java/docs/images/JavaDTraceAPI.gif b/usr/src/lib/libdtrace_jni/java/docs/images/JavaDTraceAPI.gif
index 5583442ba5..433184fab3 100644
--- a/usr/src/lib/libdtrace_jni/java/docs/images/JavaDTraceAPI.gif
+++ b/usr/src/lib/libdtrace_jni/java/docs/images/JavaDTraceAPI.gif
Binary files differ
diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/KernelStackRecord.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/KernelStackRecord.java
index 95b5fd2bd0..7e97c91ca4 100644
--- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/KernelStackRecord.java
+++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/KernelStackRecord.java
@@ -282,12 +282,13 @@ public final class KernelStackRecord implements StackValueRecord,
}
/**
- * Compares this record with the given stack record. Compares the
- * first unequal pair of bytes at the same index in each record's
- * raw stack data, or if all corresponding bytes are equal, compares
- * the length of each record's array of raw stack data. The {@code
- * compareTo()} method is compatible with {@link #equals(Object o)
- * equals()}.
+ * Compares this record with the given {@code KernelStackRecord}.
+ * Compares the first unequal pair of bytes at the same index in
+ * each record's raw stack data, or if all corresponding bytes are
+ * equal, compares the length of each record's array of raw stack
+ * data. Corresponding bytes are compared as unsigned values. The
+ * {@code compareTo()} method is compatible with {@link
+ * #equals(Object o) equals()}.
* <p>
* This implementation first checks if the specified record is this
* {@code KernelStackRecord}. If so, it returns {@code 0}.
@@ -302,17 +303,7 @@ public final class KernelStackRecord implements StackValueRecord,
return 0;
}
- int len1 = rawStackData.length;
- int len2 = r.rawStackData.length;
- int cmp = 0;
- for (int i = 0; (cmp == 0) && (i < len1) && (i < len2); ++i) {
- cmp = ((rawStackData[i] < r.rawStackData[i]) ? -1 :
- ((rawStackData[i] > r.rawStackData[i]) ? 1 : 0));
- }
- if (cmp == 0) {
- cmp = ((len1 < len2) ? -1 : ((len1 > len2) ? 1 : 0));
- }
- return cmp;
+ return ProbeData.compareByteArrays(rawStackData, r.rawStackData);
}
private void
diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/KernelSymbolRecord.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/KernelSymbolRecord.java
new file mode 100644
index 0000000000..7a32427ba4
--- /dev/null
+++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/KernelSymbolRecord.java
@@ -0,0 +1,240 @@
+/*
+ * 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.
+ *
+ * ident "%Z%%M% %I% %E% SMI"
+ */
+package org.opensolaris.os.dtrace;
+
+import java.io.*;
+import java.beans.*;
+
+/**
+ * A value generated by the DTrace {@code mod()}, {@code func()}, or
+ * {@code sym()} action used to lookup the symbol associated with a
+ * kernel address.
+ * <p>
+ * Immutable. Supports persistence using {@link java.beans.XMLEncoder}.
+ *
+ * @author Tom Erickson
+ */
+public final class KernelSymbolRecord implements SymbolValueRecord,
+ Serializable, Comparable <KernelSymbolRecord>
+{
+ static final long serialVersionUID = -7156627773519296848L;
+
+ static {
+ try {
+ BeanInfo info = Introspector.getBeanInfo(KernelSymbolRecord.class);
+ PersistenceDelegate persistenceDelegate =
+ new DefaultPersistenceDelegate(
+ new String[] {"symbol", "address"})
+ {
+ /*
+ * Need to prevent DefaultPersistenceDelegate from using
+ * overridden equals() method, resulting in a
+ * StackOverFlowError. Revert to PersistenceDelegate
+ * implementation. See
+ * http://forum.java.sun.com/thread.jspa?threadID=
+ * 477019&tstart=135
+ */
+ protected boolean
+ mutatesTo(Object oldInstance, Object newInstance)
+ {
+ return (newInstance != null && oldInstance != null &&
+ oldInstance.getClass() == newInstance.getClass());
+ }
+ };
+ BeanDescriptor d = info.getBeanDescriptor();
+ d.setValue("persistenceDelegate", persistenceDelegate);
+ } catch (IntrospectionException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /** @serial */
+ private String symbol; // set natively after creation; treat as final
+ /** @serial */
+ private final long address;
+
+ /**
+ * Called by native code.
+ */
+ private
+ KernelSymbolRecord(long addressValue)
+ {
+ address = addressValue;
+ }
+
+ /**
+ * Creates a {@code KernelSymbolRecord} with the given symbol lookup
+ * and kernel address converted in probe context as a result of the
+ * DTrace {@code mod()}, {@code func()}, or {@code sym()} action.
+ * <p>
+ * Supports XML persistence.
+ *
+ * @param addressValue symbol address
+ * @param lookupValue the result in the native DTrace library of
+ * looking up the symbol associated with the given kernel address
+ * @throws NullPointerException if the given lookup value is {@code null}
+ */
+ public
+ KernelSymbolRecord(String lookupValue, long addressValue)
+ {
+ symbol = lookupValue;
+ address = addressValue;
+ validate();
+ }
+
+ private void
+ validate()
+ {
+ if (symbol == null) {
+ throw new NullPointerException("symbol is null");
+ }
+ }
+
+ /**
+ * Gets the result of the address lookup in the same form returned
+ * by {@link Consumer#lookupKernelFunction(long address)}.
+ *
+ * @return non-null address lookup in the format defined by the
+ * native DTrace library
+ */
+ public String
+ getSymbol()
+ {
+ return symbol;
+ }
+
+ /**
+ * Called by native code and ProbeData addSymbolRecord()
+ */
+ void
+ setSymbol(String lookupValue)
+ {
+ symbol = lookupValue;
+ validate();
+ }
+
+ /**
+ * Gets the symbol's kernel address.
+ *
+ * @return the symbol's kernel address
+ */
+ public long
+ getAddress()
+ {
+ return address;
+ }
+
+ /**
+ * Gets the symbol's kernel address. The value is used in {@link
+ * #equals(Object o) equals()} and {@link
+ * #compareTo(KernelSymbolRecord r) compareTo()} to test equality
+ * and to determine the natural ordering of {@code
+ * KernelSymbolRecord} instances.
+ *
+ * @return non-null value of the symbol's kernel address
+ */
+ public Long
+ getValue()
+ {
+ return address;
+ }
+
+ /**
+ * Compares the specified object with this {@code KernelSymbolRecord}
+ * for equality. Returns {@code true} if and only if the specified
+ * object is also a {@code KernelSymbolRecord} and both records have
+ * the same address.
+ *
+ * @return {@code true} if and only if the specified object is also
+ * a {@code KernelSymbolRecord} and both records have the same
+ * address
+ */
+ @Override
+ public boolean
+ equals(Object o)
+ {
+ if (o instanceof KernelSymbolRecord) {
+ KernelSymbolRecord r = (KernelSymbolRecord)o;
+ return (address == r.address);
+ }
+ return false;
+ }
+
+ /**
+ * Overridden to ensure that equal instances have equal hash codes.
+ */
+ @Override
+ public int
+ hashCode()
+ {
+ return (int)(address ^ (address >>> 32));
+ }
+
+ /**
+ * Compares this record with the given kernel symbol lookup and
+ * orders by address. The comparison treats addresses as unsigned
+ * values so the ordering is consistent with that defined in the
+ * native DTrace library. The {@code compareTo()} method is
+ * compatible with {@link #equals(Object o) equals()}.
+ *
+ * @return -1, 0, or 1 as this record's address is less than, equal
+ * to, or greater than the given record's address
+ */
+ public int
+ compareTo(KernelSymbolRecord r)
+ {
+ return ProbeData.compareUnsigned(address, r.address);
+ }
+
+ private void
+ readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ // check class invariants
+ try {
+ validate();
+ } catch (Exception e) {
+ throw new InvalidObjectException(e.getMessage());
+ }
+ }
+
+ /**
+ * Gets the result of this symbol lookup. The format is defined in
+ * the native DTrace library and is as stable as that library
+ * definition.
+ *
+ * @return {@link #getSymbol()}
+ */
+ @Override
+ public String
+ toString()
+ {
+ return symbol;
+ }
+}
diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LocalConsumer.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LocalConsumer.java
index c6a1f41dad..dd453601e4 100644
--- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LocalConsumer.java
+++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/LocalConsumer.java
@@ -51,7 +51,7 @@ public class LocalConsumer implements Consumer {
static Logger logger = Logger.getLogger(LocalConsumer.class.getName());
- private static final int DTRACE_JNI_VERSION = 1;
+ private static final int DTRACE_JNI_VERSION = 2;
private static final Option[] DEFAULT_OPTIONS = new Option[] {
new Option(Option.bufsize, Option.kb(256)),
@@ -635,9 +635,22 @@ public class LocalConsumer implements Consumer {
// that listeners finish executing consumerStopped()
// before the stop() method returns.
synchronized (this) {
- state = State.STOPPED;
- fireConsumerStopped(new ConsumerEvent(this,
- System.nanoTime()));
+ if (state == State.STOPPED || state == state.CLOSED) {
+ //
+ // This consumer was stopped just after calling
+ // go() but before starting (the premature return
+ // case at the top of this work() method). It is
+ // possible to call close() on a consumer that has
+ // been stopped before starting. In that case the
+ // premature return above still takes us here in the
+ // finally clause, and we must not revert the CLOSED
+ // state to STOPPED.
+ //
+ } else {
+ state = State.STOPPED;
+ fireConsumerStopped(new ConsumerEvent(this,
+ System.nanoTime()));
+ }
}
// Notify the stop() method to stop waiting
@@ -776,6 +789,8 @@ public class LocalConsumer implements Consumer {
_stop();
}
state = State.STOPPED;
+ fireConsumerStopped(new ConsumerEvent(this,
+ System.nanoTime()));
} catch (DTraceException e) {
if (exceptionHandler != null) {
exceptionHandler.handleException(e);
diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/PrintfRecord.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/PrintfRecord.java
index d7f5f45db6..cb2ee0cc16 100644
--- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/PrintfRecord.java
+++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/PrintfRecord.java
@@ -108,9 +108,9 @@ public final class PrintfRecord implements Record, Serializable {
* @throws NullPointerException if o is null
*/
void
- addUnformattedElement(Object o)
+ addUnformattedElement(ScalarRecord rec)
{
- records.add(new ScalarRecord(o));
+ records.add(rec);
}
/**
diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ProbeData.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ProbeData.java
index a8978be334..a57b314c89 100644
--- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ProbeData.java
+++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ProbeData.java
@@ -111,7 +111,7 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
private Flow flow;
// Scratch data, one element per native probedata->dtpda_edesc->dtepd_nrecs
// element, cleared after records list is fully populated.
- private transient List <Object> nativeElements;
+ private transient List <Record> nativeElements;
/** @serial */
private List <Record> records;
@@ -142,7 +142,7 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
cpu = cpuID;
enabledProbeDescription = p;
flow = f;
- nativeElements = new ArrayList <Object> (nativeElementCount);
+ nativeElements = new ArrayList <Record> (nativeElementCount);
records = new ArrayList <Record> ();
validate();
}
@@ -192,8 +192,11 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
}
private void
- addDataElement(Object o)
+ addDataElement(Record o)
{
+ // Early error detection if native code adds the wrong type
+ Record r = Record.class.cast(o);
+
nativeElements.add(o);
}
@@ -217,9 +220,29 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
// assignment to a variable (results in a native probedata
// record with no data).
int len = nativeElements.size();
- Object o = null;
- for (; ((o = nativeElements.get(i)) == null) && (i < len); ++i);
- records.add(new ScalarRecord(o));
+ Record rec = null;
+ for (; ((rec = nativeElements.get(i)) == null) && (i < len); ++i);
+ records.add(rec);
+ }
+
+ /**
+ * Called by native code.
+ */
+ private void
+ addSymbolRecord(int i, String lookupString)
+ {
+ int len = nativeElements.size();
+ Record rec = null;
+ for (; ((rec = nativeElements.get(i)) == null) && (i < len); ++i);
+ SymbolValueRecord symbol = SymbolValueRecord.class.cast(rec);
+ if (symbol instanceof KernelSymbolRecord) {
+ KernelSymbolRecord.class.cast(symbol).setSymbol(lookupString);
+ } else if (symbol instanceof UserSymbolRecord) {
+ UserSymbolRecord.class.cast(symbol).setSymbol(lookupString);
+ } else {
+ throw new IllegalStateException("no symbol record at index " + i);
+ }
+ records.add(symbol);
}
/**
@@ -229,14 +252,14 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
addStackRecord(int i, String framesString)
{
int len = nativeElements.size();
- Object o = null;
- for (; ((o = nativeElements.get(i)) == null) && (i < len); ++i);
- StackValueRecord stack = (StackValueRecord)o;
+ Record rec = null;
+ for (; ((rec = nativeElements.get(i)) == null) && (i < len); ++i);
+ StackValueRecord stack = StackValueRecord.class.cast(rec);
StackFrame[] frames = KernelStackRecord.parse(framesString);
if (stack instanceof KernelStackRecord) {
- ((KernelStackRecord)stack).setStackFrames(frames);
+ KernelStackRecord.class.cast(stack).setStackFrames(frames);
} else if (stack instanceof UserStackRecord) {
- ((UserStackRecord)stack).setStackFrames(frames);
+ UserStackRecord.class.cast(stack).setStackFrames(frames);
} else {
throw new IllegalStateException("no stack record at index " + i);
}
@@ -270,7 +293,7 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
while (itr.hasPrevious() && (printa == null)) {
record = itr.previous();
if (record instanceof PrintaRecord) {
- printa = (PrintaRecord)record;
+ printa = PrintaRecord.class.cast(record);
}
}
return printa;
@@ -326,9 +349,10 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
addExitRecord(int i)
{
int len = nativeElements.size();
- Object o = null;
- for (; ((o = nativeElements.get(i)) == null) && (i < len); ++i);
- Integer exitStatus = (Integer)o;
+ Record rec = null;
+ for (; ((rec = nativeElements.get(i)) == null) && (i < len); ++i);
+ ScalarRecord scalar = ScalarRecord.class.cast(rec);
+ Integer exitStatus = Integer.class.cast(scalar.getValue());
records.add(new ExitRecord(exitStatus));
}
@@ -342,8 +366,8 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
{
Record record = records.get(records.size() - 1);
if (record instanceof PrintfRecord) {
- PrintfRecord printf = (PrintfRecord)record;
- Object e;
+ PrintfRecord printf = PrintfRecord.class.cast(record);
+ Record e;
for (int i = first; i <= last; ++i) {
e = nativeElements.get(i);
if (e == null) {
@@ -354,7 +378,7 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
// record with no data).
continue;
}
- printf.addUnformattedElement(e);
+ printf.addUnformattedElement(ScalarRecord.class.cast(e));
}
}
}
@@ -376,7 +400,7 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
{
Record record = records.get(records.size() - 1);
if (record instanceof PrintfRecord) {
- PrintfRecord printf = (PrintfRecord)record;
+ PrintfRecord printf = PrintfRecord.class.cast(record);
printf.setFormattedString(s);
}
}
@@ -416,8 +440,107 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
}
}
+ static int
+ compareUnsigned(int i1, int i2)
+ {
+ int cmp;
+
+ if (i1 < 0) {
+ if (i2 < 0) {
+ cmp = (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
+ } else {
+ cmp = 1; // negative > positive
+ }
+ } else if (i2 < 0) {
+ cmp = -1; // positive < negative
+ } else {
+ cmp = (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
+ }
+
+ return cmp;
+ }
+
+ static int
+ compareUnsigned(long i1, long i2)
+ {
+ int cmp;
+
+ if (i1 < 0) {
+ if (i2 < 0) {
+ cmp = (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
+ } else {
+ cmp = 1; // negative > positive
+ }
+ } else if (i2 < 0) {
+ cmp = -1; // positive < negative
+ } else {
+ cmp = (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
+ }
+
+ return cmp;
+ }
+
+ static int
+ compareUnsigned(byte i1, byte i2)
+ {
+ int cmp;
+
+ if (i1 < 0) {
+ if (i2 < 0) {
+ cmp = (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
+ } else {
+ cmp = 1; // negative > positive
+ }
+ } else if (i2 < 0) {
+ cmp = -1; // positive < negative
+ } else {
+ cmp = (i1 < i2 ? -1 : (i1 > i2 ? 1 : 0));
+ }
+
+ return cmp;
+ }
+
+ static int
+ compareByteArrays(byte[] a1, byte[] a2)
+ {
+ int cmp = 0;
+ int len1 = a1.length;
+ int len2 = a2.length;
+
+ for (int i = 0; (cmp == 0) && (i < len1) && (i < len2); ++i) {
+ cmp = compareUnsigned(a1[i], a2[i]);
+ }
+
+ if (cmp == 0) {
+ cmp = (len1 < len2 ? -1 : (len1 > len2 ? 1 : 0));
+ }
+
+ return cmp;
+ }
+
+ @SuppressWarnings("unchecked")
+ static int
+ compareUnsigned(Comparable v1, Comparable v2)
+ {
+ int cmp;
+
+ if (v1 instanceof Integer) {
+ int i1 = Integer.class.cast(v1);
+ int i2 = Integer.class.cast(v2);
+ cmp = compareUnsigned(i1, i2);
+ } else if (v1 instanceof Long) {
+ long i1 = Long.class.cast(v1);
+ long i2 = Long.class.cast(v2);
+ cmp = compareUnsigned(i1, i2);
+ } else {
+ cmp = v1.compareTo(v2);
+ }
+
+ return cmp;
+ }
+
/**
- * @throws ClassCastException if records or their data are are not
+ * @throws ClassCastException if records or their data are not
* mutually comparable
*/
@SuppressWarnings("unchecked")
@@ -428,15 +551,22 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
if (r1 instanceof ScalarRecord) {
ScalarRecord t1 = ScalarRecord.class.cast(r1);
ScalarRecord t2 = ScalarRecord.class.cast(r2);
- Comparable v1 = Comparable.class.cast(t1.getValue());
- Comparable v2 = Comparable.class.cast(t2.getValue());
+ Object o1 = t1.getValue();
+ Object o2 = t2.getValue();
+ if (o1 instanceof byte[]) {
+ byte[] a1 = byte[].class.cast(o1);
+ byte[] a2 = byte[].class.cast(o2);
+ cmp = compareByteArrays(a1, a2);
+ } else {
+ Comparable v1 = Comparable.class.cast(o1);
+ Comparable v2 = Comparable.class.cast(o2);
+ cmp = v1.compareTo(v2); // compare signed values
+ }
+ } else if (r1 instanceof Comparable) {
+ // StackValueRecord, SymbolValueRecord
+ Comparable v1 = Comparable.class.cast(r1);
+ Comparable v2 = Comparable.class.cast(r2);
cmp = v1.compareTo(v2);
- } else if (r1 instanceof PrintfRecord) {
- PrintfRecord t1 = PrintfRecord.class.cast(r1);
- PrintfRecord t2 = PrintfRecord.class.cast(r2);
- String s1 = t1.toString();
- String s2 = t2.toString();
- cmp = s1.compareTo(s2);
} else if (r1 instanceof ExitRecord) {
ExitRecord e1 = ExitRecord.class.cast(r1);
ExitRecord e2 = ExitRecord.class.cast(r2);
@@ -444,8 +574,11 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
int status2 = e2.getStatus();
cmp = (status1 < status2 ? -1 : (status1 > status2 ? 1 : 0));
} else {
- throw new IllegalArgumentException("Unexpected record type: " +
- r1.getClass());
+ // PrintfRecord, PrintaRecord
+ r1.getClass().cast(r2);
+ String s1 = r1.toString();
+ String s2 = r2.toString();
+ cmp = s1.compareTo(s2);
}
return cmp;
@@ -673,10 +806,10 @@ public final class ProbeData implements Serializable, Comparable <ProbeData> {
}
record = records.get(i);
if (record instanceof ValueRecord) {
- value = ((ValueRecord)record).getValue();
+ value = ValueRecord.class.cast(record).getValue();
if (value instanceof String) {
buf.append("\"");
- buf.append((String)value);
+ buf.append(String.class.cast(value));
buf.append("\"");
} else {
buf.append(record);
diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ScalarRecord.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ScalarRecord.java
index 2654a07327..cbeafa34df 100644
--- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ScalarRecord.java
+++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/ScalarRecord.java
@@ -41,7 +41,7 @@ import java.beans.*;
* @author Tom Erickson
*/
public final class ScalarRecord implements ValueRecord, Serializable {
- static final long serialVersionUID = -34046471695050108L;
+ static final long serialVersionUID = -6920826443240176724L;
static final int RAW_BYTES_INDENT = 5;
static {
@@ -49,7 +49,7 @@ public final class ScalarRecord implements ValueRecord, Serializable {
BeanInfo info = Introspector.getBeanInfo(ScalarRecord.class);
PersistenceDelegate persistenceDelegate =
new DefaultPersistenceDelegate(
- new String[] {"value"})
+ new String[] {"value", "numberOfBytes"})
{
/*
* Need to prevent DefaultPersistenceDelegate from using
@@ -75,20 +75,33 @@ public final class ScalarRecord implements ValueRecord, Serializable {
/** @serial */
private final Object value;
+ /** @serial */
+ private int numberOfBytes;
/**
- * Creates a scalar record with the given DTrace primitive.
+ * Creates a scalar record with the given DTrace primitive and the
+ * number of bytes used to store the primitive in the native DTrace
+ * buffer. Since traced 8- and 16-bit integers are promoted (as
+ * unsigned values) to 32-bit integers, it may be important for
+ * output formatting to know the number of bytes used to represent
+ * the primitive before promotion.
*
* @param v DTrace primitive data value
- * @throws NullPointerException if the given value is null
+ * @param nativeByteCount number of bytes used to store the given
+ * primitive in the native DTrace buffer
+ * @throws NullPointerException if the given value is {@code null}
+ * @throws IllegalArgumentException if the given number of bytes is
+ * not consistent with the given primitive type or is not greater
+ * than zero
* @throws ClassCastException if the given value is not a DTrace
* primitive type listed as a possible return value of {@link
* #getValue()}
*/
public
- ScalarRecord(Object v)
+ ScalarRecord(Object v, int nativeByteCount)
{
value = v;
+ numberOfBytes = nativeByteCount;
validate();
}
@@ -98,12 +111,47 @@ public final class ScalarRecord implements ValueRecord, Serializable {
if (value == null) {
throw new NullPointerException();
}
+
// Short-circuit-evaluate common cases first
- if (!((value instanceof Number) ||
- (value instanceof String) ||
- (value instanceof byte[]))) {
- throw new ClassCastException("value is not a D primitive");
- }
+ if (value instanceof Integer) {
+ switch (numberOfBytes) {
+ case 1:
+ case 2:
+ case 4:
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "number of bytes is " + numberOfBytes +
+ ", expected 1, 2, or 4 for Integer primitive");
+ }
+ } else if (value instanceof Long) {
+ if (numberOfBytes != 8) {
+ throw new IllegalArgumentException(
+ "number of bytes is " + numberOfBytes +
+ ", expected 8 for Long primitive");
+ }
+ } else if ((value instanceof String) || (value instanceof byte[])) {
+ switch (numberOfBytes) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ throw new IllegalArgumentException(
+ "number of bytes is " + numberOfBytes +
+ ", expected a number other than " +
+ "1, 2, 4, or 8 for String or byte-array " +
+ "primitive");
+ }
+ } else if (value instanceof Number) {
+ if (numberOfBytes <= 0) {
+ throw new IllegalArgumentException(
+ "number of bytes is " + numberOfBytes +
+ ", must be greater than zero");
+ }
+ } else {
+ throw new ClassCastException(value.getClass().getName() +
+ " value is not a D primitive");
+ }
}
/**
@@ -123,6 +171,24 @@ public final class ScalarRecord implements ValueRecord, Serializable {
}
/**
+ * Gets the number of bytes used to store the primitive value of
+ * this record in the native DTrace buffer. Since traced 8- and
+ * 16-bit integers are promoted (as unsigned values) to 32-bit
+ * integers, it may be important for output formatting to know the
+ * number of bytes used to represent the primitive before promotion.
+ *
+ * @return the number of bytes used to store the primitive value
+ * of this record in the native DTrace buffer, guaranteed to be
+ * greater than zero and consisitent with the type of the primitive
+ * value
+ */
+ public int
+ getNumberOfBytes()
+ {
+ return numberOfBytes;
+ }
+
+ /**
* Compares the specified object with this record for equality.
* Defines equality as having the same value.
*
diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/SymbolValueRecord.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/SymbolValueRecord.java
new file mode 100644
index 0000000000..04ee1842c0
--- /dev/null
+++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/SymbolValueRecord.java
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ *
+ * ident "%Z%%M% %I% %E% SMI"
+ */
+package org.opensolaris.os.dtrace;
+
+/**
+ * A value generated by the DTrace {@code mod()}, {@code func()}, {@code
+ * sym()}, {@code umod()}, {@code ufunc()} or {@code usym()} action used
+ * to lookup the symbol associated with an address in probe context.
+ *
+ * @author Tom Erickson
+ */
+public interface SymbolValueRecord extends ValueRecord {
+ /**
+ * Gets the result of the address lookup.
+ *
+ * @return non-null address lookup in the format defined by the
+ * native DTrace library
+ */
+ public String getSymbol();
+
+ /**
+ * Gets the symbol address.
+ *
+ * @return the symbol address
+ */
+ public long getAddress();
+}
diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Tuple.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Tuple.java
index 65743e657f..6959c1eadb 100644
--- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Tuple.java
+++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/Tuple.java
@@ -154,17 +154,13 @@ public final class Tuple implements Serializable, Comparable <Tuple>,
* {@link ScalarRecord#getValue()}
*/
private void
- addElement(Object element)
+ addElement(ValueRecord element)
{
if (element == null) {
throw new NullPointerException("tuple element is null at " +
"index " + elements.size());
}
- if (element instanceof ValueRecord) {
- elements.add(ValueRecord.class.cast(element));
- } else {
- elements.add(new ScalarRecord(element));
- }
+ elements.add(element);
}
/**
@@ -269,24 +265,34 @@ public final class Tuple implements Serializable, Comparable <Tuple>,
// lenient sort does not throw exceptions
@SuppressWarnings("unchecked")
- private int
+ private static int
compareObjects(Object o1, Object o2)
{
int cmp;
- Class c1 = o1.getClass();
- Class c2 = o2.getClass();
- if (c1.isAssignableFrom(c2) && (o1 instanceof Comparable)) {
- Comparable c = Comparable.class.cast(o1);
- cmp = c.compareTo(c1.cast(o2));
+
+ if (o1 instanceof Comparable) {
+ Class c1 = o1.getClass();
+ Class c2 = o2.getClass();
+ if (c1.equals(c2)) {
+ cmp = ProbeData.compareUnsigned(Comparable.class.cast(o1),
+ Comparable.class.cast(o2));
+ } else {
+ // Compare string values.
+ String s1 = o1.toString();
+ String s2 = o2.toString();
+ cmp = s1.compareTo(s2);
+ }
+ } else if (o1 instanceof byte[] && o2 instanceof byte[]) {
+ byte[] a1 = byte[].class.cast(o1);
+ byte[] a2 = byte[].class.cast(o2);
+ cmp = ProbeData.compareByteArrays(a1, a2);
} else {
- // Compare string values. If matching, compare object class.
+ // Compare string values.
String s1 = o1.toString();
String s2 = o2.toString();
cmp = s1.compareTo(s2);
- if (cmp == 0) {
- cmp = c1.getName().compareTo(c2.getName());
- }
}
+
return cmp;
}
@@ -297,13 +303,13 @@ public final class Tuple implements Serializable, Comparable <Tuple>,
* of corresponding elements and comparing subsequent pairs only
* when all previous pairs are equal (as a tie breaker). If
* corresponding elements are not mutually comparable, it compares
- * the string values of those elements, then if the string values
- * are equal, it compares the class names of those elements' types.
- * If all corresponding elements are equal, then the tuple with more
- * elements sorts higher than the tuple with fewer elements.
+ * the string values of those elements. If all corresponding
+ * elements are equal, then the tuple with more elements sorts
+ * higher than the tuple with fewer elements.
*
* @return a negative integer, zero, or a postive integer as this
* tuple is less than, equal to, or greater than the given tuple
+ * @see Tuple#compare(Tuple t1, Tuple t2, int pos)
*/
public int
compareTo(Tuple t)
@@ -311,24 +317,8 @@ public final class Tuple implements Serializable, Comparable <Tuple>,
int cmp = 0;
int len = size();
int tlen = t.size();
- ValueRecord rec;
- ValueRecord trec;
- Object val;
- Object tval;
for (int i = 0; (cmp == 0) && (i < len) && (i < tlen); ++i) {
- rec = get(i);
- trec = t.get(i);
- if (rec instanceof ScalarRecord) {
- val = rec.getValue();
- } else {
- val = rec;
- }
- if (trec instanceof ScalarRecord) {
- tval = trec.getValue();
- } else {
- tval = trec;
- }
- cmp = compareObjects(val, tval);
+ cmp = Tuple.compare(this, t, i);
}
if (cmp == 0) {
cmp = (len < tlen ? -1 : (len > tlen ? 1 : 0));
@@ -336,6 +326,43 @@ public final class Tuple implements Serializable, Comparable <Tuple>,
return cmp;
}
+ /**
+ * Compares corresponding tuple elements at the given zero-based
+ * index. Elements are ordered as defined in the native DTrace
+ * library, which treats integer values as unsigned when sorting.
+ *
+ * @param t1 first tuple
+ * @param t2 second tuple
+ * @param pos nth tuple element, starting at zero
+ * @return a negative integer, zero, or a postive integer as the
+ * element in the first tuple is less than, equal to, or greater
+ * than the element in the second tuple
+ * @throws IndexOutOfBoundsException if the given tuple index {@code
+ * pos} is out of range {@code (pos < 0 || pos >= size())} for
+ * either of the given tuples
+ */
+ public static int
+ compare(Tuple t1, Tuple t2, int pos)
+ {
+ int cmp = 0;
+ ValueRecord rec1 = t1.get(pos);
+ ValueRecord rec2 = t2.get(pos);
+ Object val1;
+ Object val2;
+ if (rec1 instanceof ScalarRecord) {
+ val1 = rec1.getValue();
+ } else {
+ val1 = rec1;
+ }
+ if (rec2 instanceof ScalarRecord) {
+ val2 = rec2.getValue();
+ } else {
+ val2 = rec2;
+ }
+ cmp = compareObjects(val1, val2);
+ return (cmp);
+ }
+
private void
readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/UserStackRecord.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/UserStackRecord.java
index 7c6e64872b..838beb4b83 100644
--- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/UserStackRecord.java
+++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/UserStackRecord.java
@@ -216,12 +216,7 @@ public final class UserStackRecord implements StackValueRecord,
}
if (o instanceof UserStackRecord) {
UserStackRecord r = (UserStackRecord)o;
- // raw stack data includes the process ID, but the process
- // ID passed to the constructor is not validated against the
- // raw stack data; probably best for this class to test all
- // of its state without making assumptions
- return ((processID == r.processID) &&
- stackRecord.equals(r.stackRecord));
+ return stackRecord.equals(r.stackRecord);
}
return false;
}
@@ -233,21 +228,23 @@ public final class UserStackRecord implements StackValueRecord,
public int
hashCode()
{
- return (stackRecord.hashCode() + processID);
+ return stackRecord.hashCode();
}
/**
* Compares this record with the given {@code UserStackRecord}.
- * Compares process ID first, then if those are equal, compares the
- * views returned by {@link #asKernelStackRecord()}. The {@code
- * compareTo()} method is compatible with {@link #equals(Object o)
- * equals()}.
+ * Compares the first unequal pair of bytes at the same index in
+ * each record's raw stack data, or if all corresponding bytes are
+ * equal, compares the length of each record's array of raw stack
+ * data. Corresponding bytes are compared as unsigned values. The
+ * {@code compareTo()} method is compatible with {@link
+ * #equals(Object o) equals()}.
* <p>
* This implementation first checks if the specified object is this
* {@code UserStackRecord}. If so, it returns {@code 0}.
*
- * @return -1, 0, or 1 as this record is less than, equal to, or
- * greater than the given record
+ * @return -1, 0, or 1 as this record's raw stack data is less than,
+ * equal to, or greater than the given record's raw stack data
*/
public int
compareTo(UserStackRecord r)
@@ -256,13 +253,7 @@ public final class UserStackRecord implements StackValueRecord,
return 0;
}
- int cmp = 0;
- cmp = ((processID < r.processID) ? -1 :
- ((processID > r.processID) ? 1 : 0));
- if (cmp == 0) {
- cmp = stackRecord.compareTo(r.stackRecord);
- }
- return cmp;
+ return stackRecord.compareTo(r.stackRecord);
}
/**
diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/UserSymbolRecord.java b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/UserSymbolRecord.java
new file mode 100644
index 0000000000..b53eddef2f
--- /dev/null
+++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/UserSymbolRecord.java
@@ -0,0 +1,469 @@
+/*
+ * 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.
+ *
+ * ident "%Z%%M% %I% %E% SMI"
+ */
+package org.opensolaris.os.dtrace;
+
+import java.io.*;
+import java.beans.*;
+
+/**
+ * A value generated by the DTrace {@code umod()}, {@code ufunc()}, or
+ * {@code usym()} action used to lookup the symbol associated with a
+ * user address.
+ * <p>
+ * Immutable. Supports persistence using {@link java.beans.XMLEncoder}.
+ *
+ * @author Tom Erickson
+ */
+public final class UserSymbolRecord implements SymbolValueRecord,
+ Serializable, Comparable <UserSymbolRecord>
+{
+ static final long serialVersionUID = -591954442654439794L;
+
+ static {
+ try {
+ BeanInfo info = Introspector.getBeanInfo(UserSymbolRecord.class);
+ PersistenceDelegate persistenceDelegate =
+ new DefaultPersistenceDelegate(
+ new String[] {"processID", "symbol", "address"})
+ {
+ /*
+ * Need to prevent DefaultPersistenceDelegate from using
+ * overridden equals() method, resulting in a
+ * StackOverFlowError. Revert to PersistenceDelegate
+ * implementation. See
+ * http://forum.java.sun.com/thread.jspa?threadID=
+ * 477019&tstart=135
+ */
+ protected boolean
+ mutatesTo(Object oldInstance, Object newInstance)
+ {
+ return (newInstance != null && oldInstance != null &&
+ oldInstance.getClass() == newInstance.getClass());
+ }
+ };
+ BeanDescriptor d = info.getBeanDescriptor();
+ d.setValue("persistenceDelegate", persistenceDelegate);
+ } catch (IntrospectionException e) {
+ e.printStackTrace();
+ }
+ }
+
+ // serialized explicitly to hide implementation; treat as final
+ private transient Value value;
+ // set natively after creation; treat as final
+ private transient String symbol;
+
+ /**
+ * Called by native code.
+ */
+ private
+ UserSymbolRecord(int pid, long addressValue)
+ {
+ value = new Value(pid, addressValue);
+ }
+
+ /**
+ * Creates a {@code UserSymbolRecord} with the given process ID,
+ * symbol lookup, and user address converted in probe context as a
+ * result of the DTrace {@code umod()}, {@code ufunc()}, or {@code
+ * usym()} action.
+ * <p>
+ * Supports XML persistence.
+ *
+ * @param pid non-negative user process ID
+ * @param lookupValue the result in the native DTrace library of
+ * looking up the symbol associated with the given user address
+ * @param addressValue symbol address
+ * @throws NullPointerException if the given lookup value is {@code null}
+ * @throws IllegalArgumentException if the given process ID is
+ * negative
+ */
+ public
+ UserSymbolRecord(int pid, String lookupValue, long addressValue)
+ {
+ value = new Value(pid, addressValue);
+ symbol = lookupValue;
+ validate();
+ }
+
+ private void
+ validate()
+ {
+ if (symbol == null) {
+ throw new NullPointerException("symbol is null");
+ }
+ }
+
+ /**
+ * Gets the process ID associated with this record's symbol.
+ *
+ * @return non-negative pid
+ */
+ public int
+ getProcessID()
+ {
+ return value.getProcessID();
+ }
+
+ /**
+ * Gets the result of the address lookup in the same form returned
+ * by {@link Consumer#lookupUserFunction(int pid, long address)}.
+ *
+ * @return non-null address lookup in the format defined by the
+ * native DTrace library
+ */
+ public String
+ getSymbol()
+ {
+ return symbol;
+ }
+
+ /**
+ * Called by native code and ProbeData addSymbolRecord()
+ */
+ void
+ setSymbol(String lookupValue)
+ {
+ symbol = lookupValue;
+ validate();
+ }
+
+ /**
+ * Gets the symbol's user address.
+ *
+ * @return the symbol's user address
+ */
+ public long
+ getAddress()
+ {
+ return value.getAddress();
+ }
+
+ /**
+ * Gets the composite value of the symbol's process ID and address.
+ * The value is used in {@link #equals(Object o) equals()} and
+ * {@link #compareTo(UserSymbolRecord r) compareTo()} to test
+ * equality and to determine the natural ordering of {@code
+ * UserSymbolRecord} instances.
+ *
+ * @return non-null composite value of the symbols's process ID and
+ * address
+ */
+ public Value
+ getValue()
+ {
+ return value;
+ }
+
+ /**
+ * Compares the specified object with this {@code UserSymbolRecord}
+ * for equality. Returns {@code true} if and only if the specified
+ * object is also a {@code UserSymbolRecord} and both records have
+ * the same process ID and the same address.
+ *
+ * @return {@code true} if and only if the specified object is also
+ * a {@code UserSymbolRecord} and both records have the same
+ * process ID and the same address
+ */
+ @Override
+ public boolean
+ equals(Object o)
+ {
+ if (o instanceof UserSymbolRecord) {
+ UserSymbolRecord r = (UserSymbolRecord)o;
+ return value.equals(r.value);
+ }
+ return false;
+ }
+
+ /**
+ * Overridden to ensure that equal instances have equal hash codes.
+ */
+ @Override
+ public int
+ hashCode()
+ {
+ return value.hashCode();
+ }
+
+ /**
+ * Compares this record with the given user symbol lookup and orders
+ * by the combined value of process ID first and address second.
+ * The comparison treats addresses as unsigned values so the
+ * ordering is consistent with that defined in the native DTrace
+ * library. The {@code compareTo()} method is compatible with {@link
+ * #equals(Object o) equals()}.
+ *
+ * @return -1, 0, or 1 as this record's combined process ID and
+ * address is less than, equal to, or greater than the given
+ * record's combined process ID and address
+ */
+ public int
+ compareTo(UserSymbolRecord r)
+ {
+ return value.compareTo(r.value);
+ }
+
+ /**
+ * Serialize this {@code UserSymbolRecord} instance.
+ *
+ * @serialData processID ({@code int}), followed by symbol ({@code
+ * java.lang.String}), followed by address ({@code long})
+ */
+ private void
+ writeObject(ObjectOutputStream s) throws IOException
+ {
+ s.defaultWriteObject();
+ s.writeInt(getProcessID());
+ s.writeObject(getSymbol());
+ s.writeLong(getAddress());
+ }
+
+ private void
+ readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ int pid = s.readInt();
+ symbol = (String)s.readObject();
+ long addressValue = s.readLong();
+ try {
+ value = new Value(pid, addressValue);
+ validate();
+ } catch (Exception e) {
+ throw new InvalidObjectException(e.getMessage());
+ }
+ }
+
+ /**
+ * Gets the result of this symbol lookup. The format is defined in
+ * the native DTrace library and is as stable as that library
+ * definition.
+ *
+ * @return {@link #getSymbol()}
+ */
+ @Override
+ public String
+ toString()
+ {
+ return symbol;
+ }
+
+ /**
+ * The composite value of a symbol's process ID and user address.
+ * <p>
+ * Immutable. Supports persistence using {@link
+ * java.beans.XMLEncoder}.
+ */
+ public static final class Value implements Serializable,
+ Comparable <Value> {
+ static final long serialVersionUID = -91449037747641135L;
+
+ static {
+ try {
+ BeanInfo info = Introspector.getBeanInfo(
+ UserSymbolRecord.Value.class);
+ PersistenceDelegate persistenceDelegate =
+ new DefaultPersistenceDelegate(
+ new String[] {"processID", "address"})
+ {
+ /*
+ * Need to prevent DefaultPersistenceDelegate from using
+ * overridden equals() method, resulting in a
+ * StackOverFlowError. Revert to PersistenceDelegate
+ * implementation. See
+ * http://forum.java.sun.com/thread.jspa?threadID=
+ * 477019&tstart=135
+ */
+ protected boolean
+ mutatesTo(Object oldInstance, Object newInstance)
+ {
+ return (newInstance != null && oldInstance != null &&
+ oldInstance.getClass() ==
+ newInstance.getClass());
+ }
+ };
+ BeanDescriptor d = info.getBeanDescriptor();
+ d.setValue("persistenceDelegate", persistenceDelegate);
+ } catch (IntrospectionException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /** @serial */
+ private final int processID;
+ /** @serial */
+ private final long address;
+
+ /**
+ * Creates a composite value with the given user process ID and
+ * symbol address.
+ * <p>
+ * Supports XML persistence.
+ *
+ * @param pid non-negative process ID
+ * @param addressValue symbol address
+ * @throws IllegalArgumentException if the given process ID is
+ * negative
+ */
+ public
+ Value(int pid, long addressValue)
+ {
+ processID = pid;
+ address = addressValue;
+ validate();
+ }
+
+ private void
+ validate()
+ {
+ if (processID < 0) {
+ throw new IllegalArgumentException("process ID is negative");
+ }
+ }
+
+ /**
+ * Gets the process ID associated with this value's user
+ * address.
+ *
+ * @return non-negative pid
+ */
+ public int
+ getProcessID()
+ {
+ return processID;
+ }
+
+ /**
+ * Gets the symbol's user address.
+ *
+ * @return the symbol's user address
+ */
+ public long
+ getAddress()
+ {
+ return address;
+ }
+
+ /**
+ * Compares the specified object with this {@code
+ * UserSymbolRecord.Value} for equality. Returns {@code true}
+ * if and only if the specified object is also a {@code
+ * UserSymbolRecord.Value} and both values have the same process
+ * ID and the same address.
+ *
+ * @return {@code true} if and only if the specified object is
+ * also a {@code UserSymbolRecord.Value} and both values have
+ * the same process ID and the same address
+ */
+ @Override
+ public boolean
+ equals(Object o)
+ {
+ if (o instanceof Value) {
+ Value v = (Value)o;
+ return ((processID == v.processID) && (address == v.address));
+ }
+ return false;
+ }
+
+ /**
+ * Overridden to ensure that equal instances have equal hash
+ * codes.
+ */
+ @Override
+ public int
+ hashCode()
+ {
+ int hash = 17;
+ hash = 37 * hash + processID;
+ hash = 37 * hash + (int)(address ^ (address >>> 32));
+ return hash;
+ }
+
+ /**
+ * Compares this value with the given {@code
+ * UserSymbolRecord.Value} and orders by process ID first and
+ * address second. The comparison treats addresses as unsigned
+ * values so the ordering is consistent with that defined in the
+ * native DTrace library. The {@code compareTo()} method is
+ * compatible with {@link #equals(Object o) equals()}.
+ *
+ * @return -1, 0, or 1 as this value's combined process ID and
+ * address is less than, equal to, or greater than the given
+ * value's combined process ID and address
+ */
+ public int
+ compareTo(Value v)
+ {
+ int cmp;
+ cmp = (processID < v.processID ? -1 :
+ (processID > v.processID ? 1 : 0));
+ if (cmp == 0) {
+ cmp = ProbeData.compareUnsigned(address, v.address);
+ }
+ return cmp;
+ }
+
+ private void
+ readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ // check class invariants
+ try {
+ validate();
+ } catch (Exception e) {
+ throw new InvalidObjectException(e.getMessage());
+ }
+ }
+
+ /**
+ * Gets a string representation of this {@code
+ * UserSymbolRecord.Value} instance useful for logging and not
+ * intended for display. The exact details of the
+ * representation are unspecified and subject to change, but the
+ * following format may be regarded as typical:
+ * <pre><code>
+ * class-name[property1 = value1, property2 = value2]
+ * </code></pre>
+ */
+ public String
+ toString()
+ {
+ StringBuilder buf = new StringBuilder();
+ buf.append(Value.class.getName());
+ buf.append("[processID = ");
+ buf.append(processID);
+ buf.append(", address = ");
+ buf.append(address);
+ buf.append(']');
+ return buf.toString();
+ }
+ }
+}
diff --git a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/package.html b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/package.html
index 92689cf5f2..9ca357a440 100644
--- a/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/package.html
+++ b/usr/src/lib/libdtrace_jni/java/src/org/opensolaris/os/dtrace/package.html
@@ -47,7 +47,7 @@ end commented-out block -->
For overviews, tutorials, examples, guides, and tool documentation, please see:
<br><br>
-<a href="http://docs.sun.com/db/doc/817-6223">
+<a href="http://docs.sun.com/app/docs/doc/817-6223">
<i>Solaris Dynamic Tracing Guide</i></a><br>
<a href="http://www.opensolaris.org/os/community/dtrace">
OpenSolaris DTrace Website</a><br>
diff --git a/usr/src/pkgdefs/SUNWdtrc/prototype_doc b/usr/src/pkgdefs/SUNWdtrc/prototype_doc
index 520b6184f7..d79313545b 100644
--- a/usr/src/pkgdefs/SUNWdtrc/prototype_doc
+++ b/usr/src/pkgdefs/SUNWdtrc/prototype_doc
@@ -69,6 +69,7 @@ f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/Interface
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/InterfaceAttributes.Stability.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/InterfaceAttributes.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/KernelStackRecord.html 0644 root other
+f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/KernelSymbolRecord.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/LinearDistribution.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/LocalConsumer.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/LogDistribution.html 0644 root other
@@ -93,9 +94,12 @@ f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/Record.ht
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/ScalarRecord.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/StackFrame.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/StackValueRecord.html 0644 root other
+f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/SymbolValueRecord.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/SumValue.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/Tuple.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/UserStackRecord.html 0644 root other
+f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/UserSymbolRecord.html 0644 root other
+f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/UserSymbolRecord.Value.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/ValueRecord.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/package-frame.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/package-summary.html 0644 root other
@@ -130,6 +134,7 @@ f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/InterfaceAttributes.Stability.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/InterfaceAttributes.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/KernelStackRecord.html 0644 root other
+f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/KernelSymbolRecord.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/LinearDistribution.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/LocalConsumer.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/LogDistribution.html 0644 root other
@@ -154,9 +159,12 @@ f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/ScalarRecord.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/StackFrame.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/StackValueRecord.html 0644 root other
+f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/SymbolValueRecord.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/SumValue.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/Tuple.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/UserStackRecord.html 0644 root other
+f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/UserSymbolRecord.html 0644 root other
+f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/UserSymbolRecord.Value.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/class-use/ValueRecord.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/org/opensolaris/os/dtrace/package-use.html 0644 root other
f none usr/share/lib/java/javadoc/dtrace/api/package-list 0644 root other