123b5c241Stomee /* 223b5c241Stomee * CDDL HEADER START 323b5c241Stomee * 423b5c241Stomee * The contents of this file are subject to the terms of the 523b5c241Stomee * Common Development and Distribution License (the "License"). 623b5c241Stomee * You may not use this file except in compliance with the License. 723b5c241Stomee * 823b5c241Stomee * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 923b5c241Stomee * or http://www.opensolaris.org/os/licensing. 1023b5c241Stomee * See the License for the specific language governing permissions 1123b5c241Stomee * and limitations under the License. 1223b5c241Stomee * 1323b5c241Stomee * When distributing Covered Code, include this CDDL HEADER in each 1423b5c241Stomee * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1523b5c241Stomee * If applicable, add the following below this CDDL HEADER, with the 1623b5c241Stomee * fields enclosed by brackets "[]" replaced with your own identifying 1723b5c241Stomee * information: Portions Copyright [yyyy] [name of copyright owner] 1823b5c241Stomee * 1923b5c241Stomee * CDDL HEADER END 2023b5c241Stomee */ 2123b5c241Stomee 2223b5c241Stomee /* 23e77b06d2Stomee * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2423b5c241Stomee * Use is subject to license terms. 2523b5c241Stomee * 2623b5c241Stomee */ 2723b5c241Stomee import org.opensolaris.os.dtrace.*; 2823b5c241Stomee import java.io.*; 2923b5c241Stomee import java.util.*; 3023b5c241Stomee import java.util.logging.*; 3123b5c241Stomee 3223b5c241Stomee /** 33*bbf21555SRichard Lowe * Emulates {@code dtrace(8)} using the Java DTrace API. 3423b5c241Stomee */ 3523b5c241Stomee public class JDTrace { 3623b5c241Stomee static Logger logger = Logger.getLogger(JDTrace.class.getName()); 3723b5c241Stomee 3823b5c241Stomee static Consumer dtrace; 3923b5c241Stomee 4023b5c241Stomee static { 4123b5c241Stomee Handler handler = new ConsoleHandler(); 4223b5c241Stomee handler.setLevel(Level.ALL); 4323b5c241Stomee logger.addHandler(handler); 4423b5c241Stomee } 4523b5c241Stomee 4623b5c241Stomee static final String CLASSNAME = "JDTrace"; 4723b5c241Stomee static final String OPTSTR = 4823b5c241Stomee "3:6:b:c:CD:ef:Fi:I:lL:m:n:o:p:P:qs:U:vVwx:X:Z"; 4923b5c241Stomee static boolean heading = false; 5023b5c241Stomee static boolean quiet = false; 5123b5c241Stomee static boolean flow = false; 5223b5c241Stomee static int stackindent = 14; 5323b5c241Stomee static int exitStatus = 0; 5423b5c241Stomee static boolean started; 5523b5c241Stomee static boolean stopped; 5623b5c241Stomee static PrintStream out = System.out; 5723b5c241Stomee static final String ATS = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"; 5823b5c241Stomee static final String SPACES = " "; 5923b5c241Stomee static final int QUANTIZE_ZERO_BUCKET = 63; 6023b5c241Stomee 6123b5c241Stomee enum Mode { 6223b5c241Stomee EXEC, 6323b5c241Stomee INFO, 6423b5c241Stomee LIST, 6523b5c241Stomee VERSION 6623b5c241Stomee } 6723b5c241Stomee 6823b5c241Stomee enum ProgramType { 6923b5c241Stomee STRING, 7023b5c241Stomee FILE 7123b5c241Stomee } 7223b5c241Stomee 7323b5c241Stomee static class CompileRequest { 7423b5c241Stomee String s; 7523b5c241Stomee ProgramType type; 7623b5c241Stomee ProbeDescription.Spec probespec; 7723b5c241Stomee } 7823b5c241Stomee 7923b5c241Stomee // Modify program string by expanding an incomplete probe 8023b5c241Stomee // description according to the requested probespec. 8123b5c241Stomee static void applyProbespec(CompileRequest req)8223b5c241Stomee applyProbespec(CompileRequest req) 8323b5c241Stomee { 8423b5c241Stomee ProbeDescription.Spec spec = ((req.probespec == null) 8523b5c241Stomee ? ProbeDescription.Spec.NAME 8623b5c241Stomee : req.probespec); 8723b5c241Stomee 8823b5c241Stomee int colons = 0; 8923b5c241Stomee switch (req.probespec) { 9023b5c241Stomee case PROVIDER: 9123b5c241Stomee colons = 3; 9223b5c241Stomee break; 9323b5c241Stomee case MODULE: 9423b5c241Stomee colons = 2; 9523b5c241Stomee break; 9623b5c241Stomee case FUNCTION: 9723b5c241Stomee colons = 1; 9823b5c241Stomee break; 9923b5c241Stomee } 10023b5c241Stomee 10123b5c241Stomee StringBuffer buf = new StringBuffer(); 10223b5c241Stomee if (colons > 0) { 10323b5c241Stomee char ch; 10423b5c241Stomee int len = req.s.length(); 10523b5c241Stomee 10623b5c241Stomee int i = 0; 10723b5c241Stomee // Find first whitespace character not including leading 10823b5c241Stomee // whitespace (end of first token). Ignore whitespace 10923b5c241Stomee // inside a block if the block is concatenated with the 11023b5c241Stomee // probe description. 11123b5c241Stomee for (; (i < len) && Character.isWhitespace(req.s.charAt(i)); ++i); 11223b5c241Stomee int npos = i; 11323b5c241Stomee boolean inBlock = false; 11423b5c241Stomee for (; (npos < len) && 11523b5c241Stomee (!Character.isWhitespace(ch = req.s.charAt(npos)) || 11623b5c241Stomee inBlock); ++npos) { 11723b5c241Stomee if (ch == '{') { 11823b5c241Stomee inBlock = true; 11923b5c241Stomee } else if (ch == '}') { 12023b5c241Stomee inBlock = false; 12123b5c241Stomee } 12223b5c241Stomee } 12323b5c241Stomee 12423b5c241Stomee // libdtrace lets you concatenate multiple probe 12523b5c241Stomee // descriptions separated by code blocks in curly braces, 12623b5c241Stomee // for example genunix::'{printf("FOUND");}'::entry, as long 12723b5c241Stomee // as the concatenated probe descriptions begin with ':' and 12823b5c241Stomee // not a specific field such as 'syscall'. So to expand the 12923b5c241Stomee // possibly multiple probe descriptions, we need to insert 13023b5c241Stomee // colons before each open curly brace, and again at the end 13123b5c241Stomee // only if there is at least one non-whitespace (probe 13223b5c241Stomee // specifying) character after the last closing curly brace. 13323b5c241Stomee 13423b5c241Stomee int prev_i = 0; 13523b5c241Stomee while (i < npos) { 13623b5c241Stomee for (; (i < npos) && (req.s.charAt(i) != '{'); ++i); 13723b5c241Stomee buf.append(req.s.substring(prev_i, i)); 13823b5c241Stomee if ((i < npos) || ((i > 0) && (req.s.charAt(i - 1) != '}'))) { 13923b5c241Stomee for (int c = 0; c < colons; ++c) { 14023b5c241Stomee buf.append(':'); 14123b5c241Stomee } 14223b5c241Stomee } 14323b5c241Stomee if (i < npos) { 14423b5c241Stomee buf.append(req.s.charAt(i++)); 14523b5c241Stomee } 14623b5c241Stomee prev_i = i; 14723b5c241Stomee } 14823b5c241Stomee 14923b5c241Stomee // append remainder of program text 15023b5c241Stomee buf.append(req.s.substring(i)); 15123b5c241Stomee 15223b5c241Stomee req.s = buf.toString(); 15323b5c241Stomee } 15423b5c241Stomee } 15523b5c241Stomee 15623b5c241Stomee static void printValue(Object value, int bytes, String stringFormat)15723b5c241Stomee printValue(Object value, int bytes, String stringFormat) 15823b5c241Stomee { 15923b5c241Stomee if (value instanceof Integer) { 16023b5c241Stomee if (bytes == 1) { 16123b5c241Stomee out.printf(" %3d", (Integer)value); 16223b5c241Stomee } else if (bytes == 2) { 16323b5c241Stomee out.printf(" %5d", (Integer)value); 16423b5c241Stomee } else { 16523b5c241Stomee out.printf(" %8d", (Integer)value); 16623b5c241Stomee } 16723b5c241Stomee } else if (value instanceof Long) { 16823b5c241Stomee out.printf(" %16d", (Long)value); 16923b5c241Stomee } else { 17023b5c241Stomee out.printf(stringFormat, value.toString()); 17123b5c241Stomee } 17223b5c241Stomee } 17323b5c241Stomee 17423b5c241Stomee static void consumeProbeData(ProbeData data)17523b5c241Stomee consumeProbeData(ProbeData data) 17623b5c241Stomee { 17723b5c241Stomee if (logger.isLoggable(Level.FINER)) { 17823b5c241Stomee logger.finer(data.toString()); 17923b5c241Stomee } 18023b5c241Stomee 18123b5c241Stomee if (!heading) { 18223b5c241Stomee if (flow) { 18323b5c241Stomee out.printf("%3s %-41s\n", "CPU", "FUNCTION"); 18423b5c241Stomee } else { 18523b5c241Stomee if (!quiet) { 18623b5c241Stomee out.printf("%3s %6s %32s\n", 18723b5c241Stomee "CPU", "ID", "FUNCTION:NAME"); 18823b5c241Stomee } 18923b5c241Stomee } 19023b5c241Stomee heading = true; 19123b5c241Stomee } 19223b5c241Stomee ProbeDescription probe = data.getEnabledProbeDescription(); 19323b5c241Stomee if (flow) { 19423b5c241Stomee Flow flow = data.getFlow(); 19523b5c241Stomee int indent = (flow.getDepth() * 2); 19623b5c241Stomee StringBuffer buf = new StringBuffer(); 19723b5c241Stomee // indent 19823b5c241Stomee buf.append(' '); 19923b5c241Stomee for (int i = 0; i < indent; ++i) { 20023b5c241Stomee buf.append(' '); 20123b5c241Stomee } 20223b5c241Stomee // prefix 20323b5c241Stomee switch (flow.getKind()) { 20423b5c241Stomee case ENTRY: 20523b5c241Stomee if (indent == 0) { 20623b5c241Stomee buf.append("=> "); 20723b5c241Stomee } else { 20823b5c241Stomee buf.append("-> "); 20923b5c241Stomee } 21023b5c241Stomee break; 21123b5c241Stomee case RETURN: 21223b5c241Stomee if (indent == 0) { 21323b5c241Stomee buf.append("<= "); 21423b5c241Stomee } else { 21523b5c241Stomee buf.append("<- "); 21623b5c241Stomee } 21723b5c241Stomee break; 21823b5c241Stomee } 21923b5c241Stomee 22023b5c241Stomee switch (flow.getKind()) { 22123b5c241Stomee case NONE: 22223b5c241Stomee buf.append(probe.getFunction()); 22323b5c241Stomee buf.append(':'); 22423b5c241Stomee buf.append(probe.getName()); 22523b5c241Stomee break; 22623b5c241Stomee default: 22723b5c241Stomee buf.append(probe.getFunction()); 22823b5c241Stomee } 22923b5c241Stomee 23023b5c241Stomee out.printf("%3s %-41s ", data.getCPU(), 23123b5c241Stomee buf.toString()); 23223b5c241Stomee } else { 23323b5c241Stomee if (!quiet) { 23423b5c241Stomee StringBuffer buf = new StringBuffer(); 23523b5c241Stomee buf.append(probe.getFunction()); 23623b5c241Stomee buf.append(':'); 23723b5c241Stomee buf.append(probe.getName()); 23823b5c241Stomee out.printf("%3s %6s %32s ", 23923b5c241Stomee data.getCPU(), probe.getID(), 24023b5c241Stomee buf.toString()); 24123b5c241Stomee } 24223b5c241Stomee } 24323b5c241Stomee Record record = null; 24423b5c241Stomee Object value; 24523b5c241Stomee List <Record> records = data.getRecords(); 24623b5c241Stomee Iterator <Record> itr = records.iterator(); 24723b5c241Stomee while (itr.hasNext()) { 24823b5c241Stomee record = itr.next(); 24923b5c241Stomee 25023b5c241Stomee if (record instanceof ExitRecord) { 25123b5c241Stomee exitStatus = ((ExitRecord)record).getStatus(); 25223b5c241Stomee } else if (record instanceof ScalarRecord) { 25323b5c241Stomee ScalarRecord scalar = (ScalarRecord)record; 25423b5c241Stomee value = scalar.getValue(); 25523b5c241Stomee if (value instanceof byte[]) { 25623b5c241Stomee out.print(record.toString()); 25723b5c241Stomee } else { 25823b5c241Stomee if (quiet) { 25923b5c241Stomee out.print(value); 26023b5c241Stomee } else { 26123b5c241Stomee printValue(value, scalar.getNumberOfBytes(), 26223b5c241Stomee " %-33s"); 26323b5c241Stomee } 26423b5c241Stomee } 26523b5c241Stomee } else if (record instanceof PrintfRecord) { 26623b5c241Stomee out.print(record); 26723b5c241Stomee } else if (record instanceof PrintaRecord) { 26823b5c241Stomee PrintaRecord printa = (PrintaRecord)record; 26923b5c241Stomee List <Tuple> tuples = printa.getTuples(); 27023b5c241Stomee if (tuples.isEmpty()) { 27123b5c241Stomee out.print(printa.getOutput()); 27223b5c241Stomee } else { 27323b5c241Stomee for (Tuple t : tuples) { 27423b5c241Stomee out.print(printa.getFormattedString(t)); 27523b5c241Stomee } 27623b5c241Stomee } 27723b5c241Stomee 27823b5c241Stomee if (logger.isLoggable(Level.FINE)) { 27923b5c241Stomee logger.fine(printa.toString()); 28023b5c241Stomee } 28123b5c241Stomee } else if (record instanceof StackValueRecord) { 28223b5c241Stomee printStack((StackValueRecord)record); 28323b5c241Stomee } 28423b5c241Stomee } 28523b5c241Stomee if (!quiet) { 28623b5c241Stomee out.println(); 28723b5c241Stomee } 28823b5c241Stomee } 28923b5c241Stomee 29023b5c241Stomee static void printDistribution(Distribution d)29123b5c241Stomee printDistribution(Distribution d) 29223b5c241Stomee { 29323b5c241Stomee out.printf("\n%16s %41s %-9s\n", "value", 29423b5c241Stomee "------------- Distribution -------------", 29523b5c241Stomee "count"); 29623b5c241Stomee long v; // bucket frequency (value) 29723b5c241Stomee long b; // lower bound of bucket range 29823b5c241Stomee double total = 0; 29923b5c241Stomee boolean positives = false; 30023b5c241Stomee boolean negatives = false; 30123b5c241Stomee 30223b5c241Stomee Distribution.Bucket bucket; 30323b5c241Stomee int b1 = 0; // first displayed bucket 30423b5c241Stomee int b2 = d.size() - 1; // last displayed bucket 305ae94d716SRichard Lowe 30623b5c241Stomee for (; (b1 <= b2) && (d.get(b1).getFrequency() == 0); ++b1); 30723b5c241Stomee // If possible, get one bucket before the first non-zero 30823b5c241Stomee // bucket and one bucket after the last. 30923b5c241Stomee if (b1 > b2) { 31023b5c241Stomee // There isn't any data. This is possible if (and only if) 31123b5c241Stomee // negative increment values have been used. In this case, 31223b5c241Stomee // print the buckets around the base. 31323b5c241Stomee if (d instanceof LinearDistribution) { 31423b5c241Stomee b1 = 0; 31523b5c241Stomee b2 = 2; 31623b5c241Stomee } else { 31723b5c241Stomee b1 = QUANTIZE_ZERO_BUCKET - 1; 31823b5c241Stomee b2 = QUANTIZE_ZERO_BUCKET + 1; 31923b5c241Stomee } 32023b5c241Stomee } else { 32123b5c241Stomee if (b1 > 0) --b1; 32223b5c241Stomee for (; (b2 > 0) && (d.get(b2).getFrequency() == 0); --b2); 32323b5c241Stomee if (b2 < (d.size() - 1)) ++b2; 32423b5c241Stomee } 32523b5c241Stomee for (int i = b1; i <= b2; ++i) { 32623b5c241Stomee v = d.get(i).getFrequency(); 32723b5c241Stomee if (v > 0) { 32823b5c241Stomee positives = true; 32923b5c241Stomee } 33023b5c241Stomee if (v < 0) { 33123b5c241Stomee negatives = true; 33223b5c241Stomee } 33323b5c241Stomee total += Math.abs((double)v); 33423b5c241Stomee } 33523b5c241Stomee for (int i = b1; i <= b2; ++i) { 33623b5c241Stomee bucket = d.get(i); 33723b5c241Stomee v = bucket.getFrequency(); 33823b5c241Stomee b = bucket.getMin(); 33923b5c241Stomee 340ae94d716SRichard Lowe if ((d instanceof LinearDistribution) || 341ae94d716SRichard Lowe (d instanceof LogLinearDistribution)) { 34223b5c241Stomee if (b == Long.MIN_VALUE) { 343ae94d716SRichard Lowe String lt; 344ae94d716SRichard Lowe if (d instanceof LinearDistribution) 345ae94d716SRichard Lowe lt = "< " + ((LinearDistribution)d).getBase(); 346ae94d716SRichard Lowe else 347ae94d716SRichard Lowe lt = "< " + ((LogLinearDistribution)d).getBase(); 34823b5c241Stomee out.printf("%16s ", lt); 34923b5c241Stomee } else if (bucket.getMax() == Long.MAX_VALUE) { 35023b5c241Stomee String ge = ">= " + b; 35123b5c241Stomee out.printf("%16s ", ge); 35223b5c241Stomee } else { 35323b5c241Stomee out.printf("%16d ", b); 35423b5c241Stomee } 35523b5c241Stomee } else { 35623b5c241Stomee out.printf("%16d ", b); 35723b5c241Stomee } 35823b5c241Stomee 35923b5c241Stomee printDistributionLine(v, total, positives, negatives); 36023b5c241Stomee } 36123b5c241Stomee } 36223b5c241Stomee 36323b5c241Stomee static void printDistributionLine(long val, double total, boolean positives, boolean negatives)36423b5c241Stomee printDistributionLine(long val, double total, boolean positives, 36523b5c241Stomee boolean negatives) 36623b5c241Stomee { 36723b5c241Stomee double f; 36823b5c241Stomee int depth, len = 40; 36923b5c241Stomee 37023b5c241Stomee assert (ATS.length() == len && SPACES.length() == len); 37123b5c241Stomee assert (!(total == 0 && (positives || negatives))); 37223b5c241Stomee assert (!(val < 0 && !negatives)); 37323b5c241Stomee assert (!(val > 0 && !positives)); 37423b5c241Stomee assert (!(val != 0 && total == 0)); 37523b5c241Stomee 37623b5c241Stomee if (!negatives) { 37723b5c241Stomee if (positives) { 37823b5c241Stomee f = (Math.abs((double)val) * (double)len) / total; 37923b5c241Stomee depth = (int)(f + 0.5); 38023b5c241Stomee } else { 38123b5c241Stomee depth = 0; 38223b5c241Stomee } 38323b5c241Stomee 38423b5c241Stomee out.printf("|%s%s %-9d\n", ATS.substring(len - depth), 38523b5c241Stomee SPACES.substring(depth), val); 38623b5c241Stomee return; 38723b5c241Stomee } 38823b5c241Stomee 38923b5c241Stomee if (!positives) { 39023b5c241Stomee f = (Math.abs((double)val) * (double)len) / total; 39123b5c241Stomee depth = (int)(f + 0.5); 39223b5c241Stomee 39323b5c241Stomee out.printf("%s%s| %-9d\n", SPACES.substring(depth), 39423b5c241Stomee ATS.substring(len - depth), val); 39523b5c241Stomee return; 39623b5c241Stomee } 39723b5c241Stomee 39823b5c241Stomee /* 39923b5c241Stomee * If we're here, we have both positive and negative bucket values. 40023b5c241Stomee * To express this graphically, we're going to generate both positive 40123b5c241Stomee * and negative bars separated by a centerline. These bars are half 40223b5c241Stomee * the size of normal quantize()/lquantize() bars, so we divide the 40323b5c241Stomee * length in half before calculating the bar length. 40423b5c241Stomee */ 40523b5c241Stomee len /= 2; 40623b5c241Stomee String ats = ATS.substring(len); 40723b5c241Stomee String spaces = SPACES.substring(len); 40823b5c241Stomee 40923b5c241Stomee f = (Math.abs((double)val) * (double)len) / total; 41023b5c241Stomee depth = (int)(f + 0.5); 41123b5c241Stomee 41223b5c241Stomee if (val <= 0) { 41323b5c241Stomee out.printf("%s%s|%s %-9d\n", spaces.substring(depth), 41423b5c241Stomee ats.substring(len - depth), repeat(" ", len), val); 41523b5c241Stomee return; 41623b5c241Stomee } else { 41723b5c241Stomee out.printf("%20s|%s%s %-9d\n", "", ats.substring(len - depth), 41823b5c241Stomee spaces.substring(depth), val); 41923b5c241Stomee } 42023b5c241Stomee } 42123b5c241Stomee 42223b5c241Stomee public static String repeat(String s, int n)42323b5c241Stomee repeat(String s, int n) 42423b5c241Stomee { 42523b5c241Stomee StringBuffer buf = new StringBuffer(); 42623b5c241Stomee for (int i = 0; i < n; ++i) { 42723b5c241Stomee buf.append(s); 42823b5c241Stomee } 42923b5c241Stomee return buf.toString(); 43023b5c241Stomee } 43123b5c241Stomee 43223b5c241Stomee static void printStack(StackValueRecord rec)43323b5c241Stomee printStack(StackValueRecord rec) 43423b5c241Stomee { 43523b5c241Stomee StackFrame[] frames = rec.getStackFrames(); 43623b5c241Stomee int i; 43723b5c241Stomee out.println(); 43823b5c241Stomee String s; 43923b5c241Stomee for (StackFrame f : frames) { 44023b5c241Stomee for (i = 0; i < stackindent; ++i) { 44123b5c241Stomee out.print(' '); 44223b5c241Stomee } 44323b5c241Stomee s = f.getFrame(); 44423b5c241Stomee if (s.indexOf('[') == 0) { 44523b5c241Stomee out.print(" "); 44623b5c241Stomee } 44723b5c241Stomee out.println(s); 44823b5c241Stomee } 44923b5c241Stomee } 45023b5c241Stomee 45123b5c241Stomee static void printAggregate(Aggregate aggregate)45223b5c241Stomee printAggregate(Aggregate aggregate) 45323b5c241Stomee { 454e77b06d2Stomee printAggregationRecords(aggregate.getOrderedRecords()); 45523b5c241Stomee } 45623b5c241Stomee 45723b5c241Stomee static void printAggregationRecords(List <AggregationRecord> list)45823b5c241Stomee printAggregationRecords(List <AggregationRecord> list) 45923b5c241Stomee { 46023b5c241Stomee Tuple tuple; 46123b5c241Stomee AggregationValue value; 46223b5c241Stomee ValueRecord tupleRecord; 46323b5c241Stomee int i; 46423b5c241Stomee int len; 46523b5c241Stomee for (AggregationRecord r : list) { 46623b5c241Stomee tuple = r.getTuple(); 46723b5c241Stomee value = r.getValue(); 46823b5c241Stomee len = tuple.size(); 46923b5c241Stomee for (i = 0; i < len; ++i) { 47023b5c241Stomee tupleRecord = tuple.get(i); 47123b5c241Stomee if (tupleRecord instanceof StackValueRecord) { 47223b5c241Stomee printStack((StackValueRecord)tupleRecord); 47323b5c241Stomee } else if (tupleRecord instanceof SymbolValueRecord) { 47423b5c241Stomee printValue(tupleRecord.toString(), -1, " %-50s"); 47523b5c241Stomee } else { 47623b5c241Stomee printValue(tupleRecord.getValue(), 47723b5c241Stomee ((ScalarRecord)tupleRecord).getNumberOfBytes(), 47823b5c241Stomee " %-50s"); 47923b5c241Stomee } 48023b5c241Stomee } 48123b5c241Stomee if (value instanceof Distribution) { 48223b5c241Stomee Distribution d = (Distribution)value; 48323b5c241Stomee printDistribution(d); 48423b5c241Stomee } else { 48523b5c241Stomee Number v = value.getValue(); 48623b5c241Stomee printValue(v, -1, " %-50s"); 48723b5c241Stomee } 48823b5c241Stomee out.println(); 48923b5c241Stomee } 49023b5c241Stomee } 49123b5c241Stomee 49223b5c241Stomee static void exit(int status)49323b5c241Stomee exit(int status) 49423b5c241Stomee { 49523b5c241Stomee out.flush(); 49623b5c241Stomee System.err.flush(); 49723b5c241Stomee if (status == 0) { 49823b5c241Stomee status = exitStatus; 49923b5c241Stomee } 50023b5c241Stomee System.exit(status); 50123b5c241Stomee } 50223b5c241Stomee 50323b5c241Stomee static void usage()50423b5c241Stomee usage() 50523b5c241Stomee { 50623b5c241Stomee String predact = "[[ predicate ] action ]"; 50723b5c241Stomee System.err.printf("Usage: java %s [-32|-64] [-CeFlqvVwZ] " + 50823b5c241Stomee "[-b bufsz] [-c cmd] [-D name[=def]]\n\t[-I path] [-L path] " + 50923b5c241Stomee "[-o output] [-p pid] [-s script] [-U name]\n\t" + 51023b5c241Stomee "[-x opt[=val]] [-X a|c|s|t]\n\n" + 51123b5c241Stomee "\t[-P provider %s]\n" + 51223b5c241Stomee "\t[-m [ provider: ] module %s]\n" + 51323b5c241Stomee "\t[-f [[ provider: ] module: ] func %s]\n" + 51423b5c241Stomee "\t[-n [[[ provider: ] module: ] func: ] name %s]\n" + 51523b5c241Stomee "\t[-i probe-id %s] [ args ... ]\n\n", CLASSNAME, 51623b5c241Stomee predact, predact, predact, predact, predact); 51723b5c241Stomee System.err.printf("\tpredicate -> '/' D-expression '/'\n"); 51823b5c241Stomee System.err.printf("\t action -> '{' D-statements '}'\n"); 51923b5c241Stomee System.err.printf("\n" + 52023b5c241Stomee "\t-32 generate 32-bit D programs\n" + 52123b5c241Stomee "\t-64 generate 64-bit D programs\n\n" + 52223b5c241Stomee "\t-b set trace buffer size\n" + 52323b5c241Stomee "\t-c run specified command and exit upon its completion\n" + 52423b5c241Stomee "\t-C run cpp(1) preprocessor on script files\n" + 52523b5c241Stomee "\t-D define symbol when invoking preprocessor\n" + 52623b5c241Stomee "\t-e exit after compiling request but prior to enabling " + 52723b5c241Stomee "probes\n" + 52823b5c241Stomee "\t-f enable or list probes matching the specified " + 52923b5c241Stomee "function name\n" + 53023b5c241Stomee "\t-F coalesce trace output by function\n" + 53123b5c241Stomee "\t-i enable or list probes matching the specified probe id\n" + 53223b5c241Stomee "\t-I add include directory to preprocessor search path\n" + 53323b5c241Stomee "\t-l list probes matching specified criteria\n" + 53423b5c241Stomee "\t-L add library directory to library search path\n" + 53523b5c241Stomee "\t-m enable or list probes matching the specified " + 53623b5c241Stomee "module name\n" + 53723b5c241Stomee "\t-n enable or list probes matching the specified probe name\n" + 53823b5c241Stomee "\t-o set output file\n" + 53923b5c241Stomee "\t-p grab specified process-ID and cache its symbol tables\n" + 54023b5c241Stomee "\t-P enable or list probes matching the specified " + 54123b5c241Stomee "provider name\n" + 54223b5c241Stomee "\t-q set quiet mode (only output explicitly traced data)\n" + 54323b5c241Stomee "\t-s enable or list probes according to the specified " + 54423b5c241Stomee "D script\n" + 54523b5c241Stomee "\t-U undefine symbol when invoking preprocessor\n" + 54623b5c241Stomee "\t-v set verbose mode (report stability attributes, " + 54723b5c241Stomee "arguments)\n" + 54823b5c241Stomee "\t-V report DTrace API version\n" + 54923b5c241Stomee "\t-w permit destructive actions\n" + 55023b5c241Stomee "\t-x enable or modify compiler and tracing options\n" + 55123b5c241Stomee "\t-X specify ISO C conformance settings for preprocessor\n" + 55223b5c241Stomee "\t-Z permit probe descriptions that match zero probes\n" + 55323b5c241Stomee "\n" + 55423b5c241Stomee "\tTo log PrintaRecord, set this environment variable:\n" + 55523b5c241Stomee "\t\tJDTRACE_LOGGING_LEVEL=FINE\n" + 55623b5c241Stomee "\tTo log ProbeData, set JDTRACE_LOGGING_LEVEL=FINER\n"); 55723b5c241Stomee exit(2); 55823b5c241Stomee } 55923b5c241Stomee 56023b5c241Stomee static void printProgramStability(String programType, String programDescription, ProgramInfo info)56123b5c241Stomee printProgramStability(String programType, String programDescription, 56223b5c241Stomee ProgramInfo info) 56323b5c241Stomee { 56423b5c241Stomee out.println(); 56523b5c241Stomee out.printf("Stability data for %s %s:\n\n", 56623b5c241Stomee programType, programDescription); 56723b5c241Stomee InterfaceAttributes a; 56823b5c241Stomee out.println("\tMinimum probe description " + 56923b5c241Stomee "attributes"); 57023b5c241Stomee a = info.getMinimumProbeAttributes(); 57123b5c241Stomee out.printf("\t\tIdentifier Names: %s\n", 57223b5c241Stomee a.getNameStability()); 57323b5c241Stomee out.printf("\t\tData Semantics: %s\n", 57423b5c241Stomee a.getDataStability()); 57523b5c241Stomee out.printf("\t\tDependency Class: %s\n", 57623b5c241Stomee a.getDependencyClass()); 57723b5c241Stomee out.println("\tMinimum probe statement attributes"); 57823b5c241Stomee a = info.getMinimumStatementAttributes(); 57923b5c241Stomee out.printf("\t\tIdentifier Names: %s\n", 58023b5c241Stomee a.getNameStability()); 58123b5c241Stomee out.printf("\t\tData Semantics: %s\n", 58223b5c241Stomee a.getDataStability()); 58323b5c241Stomee out.printf("\t\tDependency Class: %s\n", 58423b5c241Stomee a.getDependencyClass()); 58523b5c241Stomee } 58623b5c241Stomee 58723b5c241Stomee static void printProbeDescription(ProbeDescription p)58823b5c241Stomee printProbeDescription(ProbeDescription p) 58923b5c241Stomee { 59023b5c241Stomee out.printf("%5d %10s %17s %33s %s\n", p.getID(), 59123b5c241Stomee p.getProvider(), p.getModule(), 59223b5c241Stomee p.getFunction(), p.getName()); 59323b5c241Stomee } 59423b5c241Stomee 59523b5c241Stomee static void printProbeInfo(ProbeInfo p)59623b5c241Stomee printProbeInfo(ProbeInfo p) 59723b5c241Stomee { 59823b5c241Stomee InterfaceAttributes a; 59923b5c241Stomee out.println("\n\tProbe Description Attributes"); 60023b5c241Stomee 60123b5c241Stomee a = p.getProbeAttributes(); 60223b5c241Stomee out.printf("\t\tIdentifier Names: %s\n", 60323b5c241Stomee a.getNameStability()); 60423b5c241Stomee out.printf("\t\tData Semantics: %s\n", 60523b5c241Stomee a.getDataStability()); 60623b5c241Stomee out.printf("\t\tDependency Class: %s\n", 60723b5c241Stomee a.getDependencyClass()); 60823b5c241Stomee 60923b5c241Stomee out.println("\n\tArgument Attributes"); 61023b5c241Stomee 61123b5c241Stomee a = p.getArgumentAttributes(); 61223b5c241Stomee out.printf("\t\tIdentifier Names: %s\n", 61323b5c241Stomee a.getNameStability()); 61423b5c241Stomee out.printf("\t\tData Semantics: %s\n", 61523b5c241Stomee a.getDataStability()); 61623b5c241Stomee out.printf("\t\tDependency Class: %s\n", 61723b5c241Stomee a.getDependencyClass()); 61823b5c241Stomee 61923b5c241Stomee // Argument types unsupported for now. 62023b5c241Stomee 62123b5c241Stomee out.println(); 62223b5c241Stomee } 62323b5c241Stomee 62423b5c241Stomee public static void main(String[] args)62523b5c241Stomee main(String[] args) 62623b5c241Stomee { 62723b5c241Stomee String loggingLevel = System.getenv().get("JDTRACE_LOGGING_LEVEL"); 62823b5c241Stomee try { 62923b5c241Stomee logger.setLevel(Level.parse(loggingLevel)); 63023b5c241Stomee } catch (Exception e) { 63123b5c241Stomee logger.setLevel(Level.OFF); 63223b5c241Stomee } 63323b5c241Stomee 63423b5c241Stomee if (args.length == 0) { 63523b5c241Stomee usage(); 63623b5c241Stomee } 63723b5c241Stomee 63823b5c241Stomee List <CompileRequest> compileRequests = new LinkedList 63923b5c241Stomee <CompileRequest> (); 64023b5c241Stomee List <Program> programList = new LinkedList <Program> (); 64123b5c241Stomee boolean verbose = false; 64223b5c241Stomee Mode mode = Mode.EXEC; 64323b5c241Stomee 64423b5c241Stomee final ExceptionHandler exceptionHandler = new ExceptionHandler() { 64523b5c241Stomee public void handleException(Throwable e) { 64623b5c241Stomee if (e instanceof DTraceException) { 64723b5c241Stomee DTraceException de = (DTraceException)e; 64823b5c241Stomee System.err.printf("dtrace: %s\n", de.getMessage()); 64923b5c241Stomee } else if (e instanceof ConsumerException) { 65023b5c241Stomee ConsumerException ce = (ConsumerException)e; 65123b5c241Stomee Object msg = ce.getNotificationObject(); 65223b5c241Stomee if ((msg instanceof org.opensolaris.os.dtrace.Error) || 65323b5c241Stomee (msg instanceof Drop)) { 65423b5c241Stomee System.err.printf("dtrace: %s\n", ce.getMessage()); 65523b5c241Stomee } else { 65623b5c241Stomee ce.printStackTrace(); 65723b5c241Stomee } 65823b5c241Stomee } else { 65923b5c241Stomee e.printStackTrace(); 66023b5c241Stomee } 66123b5c241Stomee exit(1); 66223b5c241Stomee } 66323b5c241Stomee }; 66423b5c241Stomee 66523b5c241Stomee Getopt g = new Getopt(CLASSNAME, args, OPTSTR); 66623b5c241Stomee int c = 0; 66723b5c241Stomee 66823b5c241Stomee List <Consumer.OpenFlag> openFlags = 66923b5c241Stomee new ArrayList <Consumer.OpenFlag> (); 67023b5c241Stomee 67123b5c241Stomee while ((c = g.getopt()) != -1) { 67223b5c241Stomee switch (c) { 67323b5c241Stomee case '3': { 67423b5c241Stomee String s = g.getOptarg(); 67523b5c241Stomee if (!s.equals("2")) { 67623b5c241Stomee System.err.println("dtrace: illegal option -- 3" + s); 67723b5c241Stomee usage(); 67823b5c241Stomee } 67923b5c241Stomee openFlags.add(Consumer.OpenFlag.ILP32); 68023b5c241Stomee break; 68123b5c241Stomee } 68223b5c241Stomee case '6': { 68323b5c241Stomee String s = g.getOptarg(); 68423b5c241Stomee if (!s.equals("4")) { 68523b5c241Stomee System.err.println("dtrace: illegal option -- 6" + s); 68623b5c241Stomee usage(); 68723b5c241Stomee } 68823b5c241Stomee openFlags.add(Consumer.OpenFlag.LP64); 68923b5c241Stomee break; 69023b5c241Stomee } 69123b5c241Stomee } 69223b5c241Stomee } 69323b5c241Stomee 69423b5c241Stomee Consumer.OpenFlag[] oflags = new Consumer.OpenFlag[openFlags.size()]; 695e77b06d2Stomee oflags = openFlags.toArray(oflags); 69623b5c241Stomee 69723b5c241Stomee dtrace = new LocalConsumer() { 69823b5c241Stomee protected Thread createThread() { 69923b5c241Stomee Thread t = super.createThread(); 70023b5c241Stomee t.setDaemon(false); 70123b5c241Stomee t.setPriority(Thread.MIN_PRIORITY); 70223b5c241Stomee return t; 70323b5c241Stomee } 70423b5c241Stomee }; 70523b5c241Stomee 70623b5c241Stomee g = new Getopt(CLASSNAME, args, OPTSTR); 70723b5c241Stomee c = 0; 70823b5c241Stomee 70923b5c241Stomee try { 71023b5c241Stomee dtrace.open(oflags); 71123b5c241Stomee 71223b5c241Stomee // Set default options that may be overriden by options or #pragma 71323b5c241Stomee dtrace.setOption(Option.bufsize, Option.mb(4)); 71423b5c241Stomee dtrace.setOption(Option.aggsize, Option.mb(4)); 71523b5c241Stomee 71623b5c241Stomee CompileRequest r; 71723b5c241Stomee while ((c = g.getopt()) != -1) { 71823b5c241Stomee switch (c) { 71923b5c241Stomee case 'b': 72023b5c241Stomee dtrace.setOption(Option.bufsize, g.getOptarg()); 72123b5c241Stomee break; 72223b5c241Stomee case 'c': 72323b5c241Stomee dtrace.createProcess(g.getOptarg()); 72423b5c241Stomee break; 72523b5c241Stomee case 'C': 72623b5c241Stomee dtrace.setOption(Option.cpp); 72723b5c241Stomee break; 72823b5c241Stomee case 'D': 72923b5c241Stomee dtrace.setOption(Option.define, g.getOptarg()); 73023b5c241Stomee break; 73123b5c241Stomee case 'e': 73223b5c241Stomee mode = Mode.INFO; 73323b5c241Stomee break; 73423b5c241Stomee case 'f': 73523b5c241Stomee r = new CompileRequest(); 73623b5c241Stomee r.s = g.getOptarg(); 73723b5c241Stomee r.type = ProgramType.STRING; 73823b5c241Stomee r.probespec = ProbeDescription.Spec.FUNCTION; 73923b5c241Stomee compileRequests.add(r); 74023b5c241Stomee break; 74123b5c241Stomee case 'F': 74223b5c241Stomee dtrace.setOption(Option.flowindent); 74323b5c241Stomee break; 74423b5c241Stomee case 'i': 74523b5c241Stomee r = new CompileRequest(); 74623b5c241Stomee r.s = g.getOptarg(); 74723b5c241Stomee r.type = ProgramType.STRING; 74823b5c241Stomee r.probespec = ProbeDescription.Spec.NAME; 74923b5c241Stomee compileRequests.add(r); 75023b5c241Stomee break; 75123b5c241Stomee case 'I': 75223b5c241Stomee dtrace.setOption(Option.incdir, g.getOptarg()); 75323b5c241Stomee break; 75423b5c241Stomee case 'l': 75523b5c241Stomee mode = Mode.LIST; 75623b5c241Stomee dtrace.setOption(Option.zdefs); // -l implies -Z 75723b5c241Stomee break; 75823b5c241Stomee case 'L': 75923b5c241Stomee dtrace.setOption(Option.libdir, g.getOptarg()); 76023b5c241Stomee break; 76123b5c241Stomee case 'm': 76223b5c241Stomee r = new CompileRequest(); 76323b5c241Stomee r.s = g.getOptarg(); 76423b5c241Stomee r.type = ProgramType.STRING; 76523b5c241Stomee r.probespec = ProbeDescription.Spec.MODULE; 76623b5c241Stomee compileRequests.add(r); 76723b5c241Stomee break; 76823b5c241Stomee case 'n': 76923b5c241Stomee r = new CompileRequest(); 77023b5c241Stomee r.s = g.getOptarg(); 77123b5c241Stomee r.type = ProgramType.STRING; 77223b5c241Stomee r.probespec = ProbeDescription.Spec.NAME; 77323b5c241Stomee compileRequests.add(r); 77423b5c241Stomee break; 77523b5c241Stomee case 'o': 77623b5c241Stomee String outFileName = g.getOptarg(); 77723b5c241Stomee File outFile = new File(outFileName); 77823b5c241Stomee try { 77923b5c241Stomee FileOutputStream fos = new FileOutputStream( 78023b5c241Stomee outFile, true); 78123b5c241Stomee out = new PrintStream(fos); 78223b5c241Stomee } catch (FileNotFoundException e) { 78323b5c241Stomee System.err.println("failed to open " + 78423b5c241Stomee outFileName + " in write mode"); 78523b5c241Stomee exit(1); 78623b5c241Stomee } catch (SecurityException e) { 78723b5c241Stomee System.err.println("failed to open " + 78823b5c241Stomee outFileName); 78923b5c241Stomee exit(1); 79023b5c241Stomee } 79123b5c241Stomee break; 79223b5c241Stomee case 'p': 79323b5c241Stomee String pidstr = g.getOptarg(); 79423b5c241Stomee int pid = -1; 79523b5c241Stomee try { 79623b5c241Stomee pid = Integer.parseInt(pidstr); 79723b5c241Stomee } catch (NumberFormatException e) { 79823b5c241Stomee System.err.println("invalid pid: " + pidstr); 79923b5c241Stomee exit(1); 80023b5c241Stomee } 80123b5c241Stomee dtrace.grabProcess(pid); 80223b5c241Stomee break; 80323b5c241Stomee case 'P': 80423b5c241Stomee r = new CompileRequest(); 80523b5c241Stomee r.s = g.getOptarg(); 80623b5c241Stomee r.type = ProgramType.STRING; 80723b5c241Stomee r.probespec = ProbeDescription.Spec.PROVIDER; 80823b5c241Stomee compileRequests.add(r); 80923b5c241Stomee break; 81023b5c241Stomee case 'q': 81123b5c241Stomee dtrace.setOption(Option.quiet); 81223b5c241Stomee break; 81323b5c241Stomee case 's': 81423b5c241Stomee r = new CompileRequest(); 81523b5c241Stomee r.s = g.getOptarg(); 81623b5c241Stomee r.type = ProgramType.FILE; 81723b5c241Stomee compileRequests.add(r); 81823b5c241Stomee break; 81923b5c241Stomee case 'U': 82023b5c241Stomee dtrace.setOption(Option.undef, g.getOptarg()); 82123b5c241Stomee break; 82223b5c241Stomee case 'v': 82323b5c241Stomee verbose = true; 82423b5c241Stomee break; 82523b5c241Stomee case 'V': 82623b5c241Stomee mode = Mode.VERSION; 82723b5c241Stomee break; 82823b5c241Stomee case 'w': 82923b5c241Stomee dtrace.setOption(Option.destructive); 83023b5c241Stomee break; 83123b5c241Stomee case 'x': 83223b5c241Stomee String[] xarg = g.getOptarg().split("=", 2); 83323b5c241Stomee if (xarg.length > 1) { 83423b5c241Stomee dtrace.setOption(xarg[0], xarg[1]); 83523b5c241Stomee } else if (xarg.length == 1) { 83623b5c241Stomee dtrace.setOption(xarg[0]); 83723b5c241Stomee } 83823b5c241Stomee break; 83923b5c241Stomee case 'X': 84023b5c241Stomee dtrace.setOption(Option.stdc, g.getOptarg()); 84123b5c241Stomee break; 84223b5c241Stomee case 'Z': 84323b5c241Stomee dtrace.setOption(Option.zdefs); 84423b5c241Stomee break; 84523b5c241Stomee case '?': 84623b5c241Stomee usage(); // getopt() already printed an error 84723b5c241Stomee break; 84823b5c241Stomee default: 84923b5c241Stomee System.err.print("getopt() returned " + c + "\n"); 85023b5c241Stomee c = 0; 85123b5c241Stomee } 85223b5c241Stomee } 85323b5c241Stomee c = 0; 85423b5c241Stomee List <String> argList = new LinkedList <String> (); 85523b5c241Stomee for (int i = g.getOptind(); i < args.length; ++i) { 85623b5c241Stomee argList.add(args[i]); 85723b5c241Stomee } 85823b5c241Stomee 85923b5c241Stomee if (mode == Mode.VERSION) { 86023b5c241Stomee out.printf("dtrace: %s\n", dtrace.getVersion()); 86123b5c241Stomee dtrace.close(); 86223b5c241Stomee exit(0); 86323b5c241Stomee } 86423b5c241Stomee 86523b5c241Stomee String[] compileArgs = new String[argList.size()]; 866e77b06d2Stomee compileArgs = argList.toArray(compileArgs); 86723b5c241Stomee 86823b5c241Stomee Program program; 86923b5c241Stomee for (CompileRequest req : compileRequests) { 87023b5c241Stomee switch (req.type) { 87123b5c241Stomee case STRING: 87223b5c241Stomee applyProbespec(req); 87323b5c241Stomee program = dtrace.compile(req.s, compileArgs); 87423b5c241Stomee break; 87523b5c241Stomee case FILE: 87623b5c241Stomee File file = new File(req.s); 87723b5c241Stomee program = dtrace.compile(file, compileArgs); 87823b5c241Stomee break; 87923b5c241Stomee default: 88023b5c241Stomee throw new IllegalArgumentException( 88123b5c241Stomee "Unexpected program type: " + req.type); 88223b5c241Stomee } 88323b5c241Stomee 88423b5c241Stomee programList.add(program); 88523b5c241Stomee } 88623b5c241Stomee 88723b5c241Stomee // Get options set by #pragmas in compiled program 88823b5c241Stomee long optval; 88923b5c241Stomee quiet = (dtrace.getOption(Option.quiet) != Option.UNSET); 89023b5c241Stomee flow = (dtrace.getOption(Option.flowindent) != Option.UNSET); 89123b5c241Stomee optval = dtrace.getOption("stackindent"); 89223b5c241Stomee if (optval != Option.UNSET) { 89323b5c241Stomee stackindent = (int)optval; 89423b5c241Stomee } 89523b5c241Stomee 89623b5c241Stomee if (mode == Mode.LIST) { 89723b5c241Stomee out.printf("%5s %10s %17s %33s %s\n", 89823b5c241Stomee "ID", "PROVIDER", "MODULE", "FUNCTION", "NAME"); 89923b5c241Stomee 90023b5c241Stomee if (verbose) { 90123b5c241Stomee List <List <Probe>> lists = 90223b5c241Stomee new LinkedList <List <Probe>> (); 90323b5c241Stomee for (Program p : programList) { 90423b5c241Stomee lists.add(dtrace.listProgramProbeDetail(p)); 90523b5c241Stomee } 90623b5c241Stomee ProbeDescription p; 90723b5c241Stomee ProbeInfo pinfo; 90823b5c241Stomee for (List <Probe> list : lists) { 90923b5c241Stomee for (Probe probe : list) { 91023b5c241Stomee p = probe.getDescription(); 91123b5c241Stomee pinfo = probe.getInfo(); 91223b5c241Stomee printProbeDescription(p); 91323b5c241Stomee printProbeInfo(pinfo); 91423b5c241Stomee } 91523b5c241Stomee } 91623b5c241Stomee } else { 91723b5c241Stomee List <List <ProbeDescription>> lists = 91823b5c241Stomee new LinkedList <List <ProbeDescription>> (); 91923b5c241Stomee for (Program p : programList) { 92023b5c241Stomee lists.add(dtrace.listProgramProbes(p)); 92123b5c241Stomee } 92223b5c241Stomee for (List <ProbeDescription> list : lists) { 92323b5c241Stomee for (ProbeDescription p : list) { 92423b5c241Stomee printProbeDescription(p); 92523b5c241Stomee } 92623b5c241Stomee } 92723b5c241Stomee } 92823b5c241Stomee exit(0); 92923b5c241Stomee } 93023b5c241Stomee 93123b5c241Stomee String programType; 93223b5c241Stomee String programDescription; 93323b5c241Stomee ProgramInfo info; 93423b5c241Stomee for (Program p : programList) { 93523b5c241Stomee if (p instanceof Program.File) { 93623b5c241Stomee Program.File pf = (Program.File)p; 93723b5c241Stomee programType = "script"; 93823b5c241Stomee programDescription = pf.getFile().getPath(); 93923b5c241Stomee } else { 94023b5c241Stomee programType = "description"; 94123b5c241Stomee programDescription = 94223b5c241Stomee p.getContents().split("[/{;]", 2)[0]; 94323b5c241Stomee } 94423b5c241Stomee 94523b5c241Stomee if (mode == Mode.EXEC) { 94623b5c241Stomee dtrace.enable(p); 94723b5c241Stomee } else { 94823b5c241Stomee dtrace.getProgramInfo(p); 94923b5c241Stomee } 95023b5c241Stomee info = p.getInfo(); 951e77b06d2Stomee if ((mode == Mode.EXEC) && !quiet) { 95223b5c241Stomee System.err.printf("dtrace: %s '%s' matched %d probe%s\n", 95323b5c241Stomee programType, programDescription, 95423b5c241Stomee info.getMatchingProbeCount(), 95523b5c241Stomee info.getMatchingProbeCount() == 1 ? "" : "s"); 95623b5c241Stomee } 95723b5c241Stomee if (verbose) { 95823b5c241Stomee printProgramStability(programType, 95923b5c241Stomee programDescription, info); 96023b5c241Stomee } 96123b5c241Stomee } 96223b5c241Stomee if (mode != Mode.EXEC) { 96323b5c241Stomee exit(0); 96423b5c241Stomee } 96523b5c241Stomee dtrace.addConsumerListener(new ConsumerAdapter() { 96623b5c241Stomee public void consumerStarted(ConsumerEvent e) { 96723b5c241Stomee started = true; 96823b5c241Stomee } 96923b5c241Stomee public void consumerStopped(ConsumerEvent e) { 97023b5c241Stomee stopped = true; 97123b5c241Stomee out.println(); 97223b5c241Stomee try { 97323b5c241Stomee Aggregate aggregate = dtrace.getAggregate(); 97423b5c241Stomee if (aggregate != null) { 97523b5c241Stomee printAggregate(aggregate); 97623b5c241Stomee } 97723b5c241Stomee dtrace.close(); 97823b5c241Stomee } catch (Throwable x) { 97923b5c241Stomee exceptionHandler.handleException(x); 98023b5c241Stomee } 98123b5c241Stomee exit(0); 98223b5c241Stomee } 98323b5c241Stomee public void dataDropped(DropEvent e) { 98423b5c241Stomee System.err.printf("dtrace: %s", 98523b5c241Stomee e.getDrop().getDefaultMessage()); 98623b5c241Stomee } 98723b5c241Stomee public void errorEncountered(ErrorEvent e) 98823b5c241Stomee throws ConsumerException { 98923b5c241Stomee org.opensolaris.os.dtrace.Error error = e.getError(); 99023b5c241Stomee if (logger.isLoggable(Level.FINE)) { 99123b5c241Stomee logger.fine(error.toString()); 99223b5c241Stomee } 99323b5c241Stomee System.err.printf("dtrace: %s", 99423b5c241Stomee error.getDefaultMessage()); 99523b5c241Stomee } 99623b5c241Stomee public void dataReceived(DataEvent e) 99723b5c241Stomee throws ConsumerException { 99823b5c241Stomee consumeProbeData(e.getProbeData()); 99923b5c241Stomee } 100023b5c241Stomee public void processStateChanged(ProcessEvent e) 100123b5c241Stomee throws ConsumerException { 100223b5c241Stomee if (logger.isLoggable(Level.FINE)) { 100323b5c241Stomee logger.fine(e.getProcessState().toString()); 100423b5c241Stomee } 100523b5c241Stomee } 100623b5c241Stomee }); 100723b5c241Stomee // Print unprinted aggregations after Ctrl-C 100823b5c241Stomee Runtime.getRuntime().addShutdownHook(new Thread() { 100923b5c241Stomee public void run() { 101023b5c241Stomee if (stopped || !started) { 101123b5c241Stomee return; 101223b5c241Stomee } 101323b5c241Stomee 101423b5c241Stomee try { 101523b5c241Stomee Aggregate aggregate = dtrace.getAggregate(); 101623b5c241Stomee if (aggregate != null) { 101723b5c241Stomee out.println(); 101823b5c241Stomee out.println(); 101923b5c241Stomee printAggregate(aggregate); 102023b5c241Stomee } 102123b5c241Stomee } catch (Throwable x) { 102223b5c241Stomee exceptionHandler.handleException(x); 102323b5c241Stomee } 102423b5c241Stomee } 102523b5c241Stomee }); 102623b5c241Stomee dtrace.go(exceptionHandler); 102723b5c241Stomee } catch (DTraceException e) { 102823b5c241Stomee if (c > 0) { 102923b5c241Stomee // set option error 103023b5c241Stomee if (g.getOptarg() == null) { 103123b5c241Stomee System.err.printf("dtrace: failed to set -%c: %s\n", 103223b5c241Stomee c, e.getMessage()); 103323b5c241Stomee } else { 103423b5c241Stomee System.err.printf("dtrace: failed to set -%c %s: %s\n", 103523b5c241Stomee c, g.getOptarg(), e.getMessage()); 103623b5c241Stomee } 103723b5c241Stomee } else { 103823b5c241Stomee // any other error 103923b5c241Stomee System.err.printf("dtrace: %s\n", e.getMessage()); 104023b5c241Stomee } 104123b5c241Stomee exit(1); 104223b5c241Stomee } catch (Exception e) { 104323b5c241Stomee e.printStackTrace(); 104423b5c241Stomee exit(1); 104523b5c241Stomee } 104623b5c241Stomee } 104723b5c241Stomee } 1048