/* * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package compiler.codecache.dtrace; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class DtraceRunner { private static final String DTRACE_DEFAULT_PATH = "/usr/sbin/dtrace"; private static final String DTRACE_PATH_PROPERTY = "com.oracle.test.dtrace.path"; private static final String OUTPUT_FILE_DTRACE_OPTION = "o"; private static final String RUN_COMMAND_DTRACE_OPTION = "c"; private static final String RUN_SCRIPT_DTRACE_OPTION = "s"; private static final String ALLOW_ZERO_PROBE_DESCRIPTION_DTRACE_OPTION = "Z"; private static final String DTRACE_OPTION_PREFIX = "-"; public static final String PERMIT_DESTRUCTIVE_ACTIONS_DTRACE_OPTION = "w"; public static final String DTRACE_OUT_LOG = "dtrace.out"; private final String dtraceExecutable; public DtraceRunner() { dtraceExecutable = getDtracePath(); } private List<String> getLaunchCmd(String java, String javaOpts, String execClass, String testArgs, String dtraceScript, String dtraceAddOpts) { Asserts.assertTrue(!java.matches("\\s"), "Current dtrace implementation" + " can't handle whitespaces in application path"); List<String> result = new ArrayList<>(); result.add(dtraceExecutable); result.add(DTRACE_OPTION_PREFIX + System.getProperty("sun.arch.data.model")); result.add(DTRACE_OPTION_PREFIX + ALLOW_ZERO_PROBE_DESCRIPTION_DTRACE_OPTION + ((dtraceAddOpts == null) ? "" : dtraceAddOpts) + RUN_SCRIPT_DTRACE_OPTION); // run_script should be last one result.add(dtraceScript); result.add(DTRACE_OPTION_PREFIX + OUTPUT_FILE_DTRACE_OPTION); result.add(DTRACE_OUT_LOG); result.add(DTRACE_OPTION_PREFIX + RUN_COMMAND_DTRACE_OPTION); result.add(java + " " + javaOpts + " " + execClass + " " + testArgs); return result; } private void backupLogFile(File file) { if (file.exists()) { file.renameTo(new File(file.getPath() + ".bak")); } } public void runDtrace(String java, String javaOpts, String execClass, String testArgs, String dtraceScript, String dtraceAddOpts, DtraceResultsAnalyzer analyzer) { backupLogFile(new File(DTRACE_OUT_LOG)); ProcessBuilder pbuilder = new ProcessBuilder( getLaunchCmd(java, javaOpts, execClass, testArgs, dtraceScript, dtraceAddOpts)); OutputAnalyzer oa; try { oa = new OutputAnalyzer(pbuilder.start()); } catch (IOException e) { throw new Error("TESTBUG: Can't start process", e); } analyzer.analyze(oa, DTRACE_OUT_LOG); } public static boolean dtraceAvailable() { String path = getDtracePath(); if (path == null) { return false; } // now we'll launch dtrace to trace itself just to be sure it works // and have all additional previleges set ProcessBuilder pbuilder = new ProcessBuilder(path, path); try { OutputAnalyzer oa = new OutputAnalyzer(pbuilder.start()); if (oa.getExitValue() != 0) { return false; } } catch (IOException e) { throw new Error("Couldn't launch dtrace", e); } return true; } private static String getDtracePath() { String propPath = System.getProperty(DTRACE_PATH_PROPERTY); if (propPath != null && new File(propPath).exists()) { return propPath; } else if (new File(DTRACE_DEFAULT_PATH).exists()) { return DTRACE_DEFAULT_PATH; } return null; } }