diff options
author | tomee <none@none> | 2006-09-20 15:54:32 -0700 |
---|---|---|
committer | tomee <none@none> | 2006-09-20 15:54:32 -0700 |
commit | 127bbe13a6d36580af6a8ded154f1201a6250772 (patch) | |
tree | 097be6f91574dfb4082ee912defd3692c619a155 /usr/src | |
parent | d7ab25acb993ab117834d04e877943640f215b79 (diff) | |
download | illumos-gate-127bbe13a6d36580af6a8ded154f1201a6250772.tar.gz |
6457918 Java DTrace API does not support umod()/ufunc()/usym(), mod()/func()/sym()
6467507 Java DTrace API javadoc links to DTrace guide broken
6468139 ufunc() aggregation key sorts strangely
6470482 Aggregation key integer representation and ordering differs between Java API and libdtrace
6470519 LocalConsumer CLOSED state reverts to STOPPED
Diffstat (limited to 'usr/src')
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 Binary files differindex 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 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 |