blob: 6a8f54b3f600939800eeab5aa5f6055acd045a60 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2018 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat - initial API and implementation
*******************************************************************************/
package org.eclipse.linuxtools.internal.callgraph.launch;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.model.IBinary;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.linuxtools.internal.callgraph.core.PluginConstants;
import org.eclipse.linuxtools.internal.callgraph.core.SystemTapUIErrorMessages;
import org.eclipse.ui.IEditorPart;
public class LaunchStapGraph extends SystemTapLaunchShortcut {
//TODO: Do not let this class persist, or otherwise change it so persistence doesn't matter.
private String partialScriptPath;
private String funcs;
private List<String> exclusions;
private String projectName;
protected static final String ATTR_PARSER = "org.eclipse.linuxtools.callgraph.graphparser"; //$NON-NLS-1$
protected static final String ATTR_VIEWER = "org.eclipse.linuxtools.callgraph.callgraphview"; //$NON-NLS-1$
public LaunchStapGraph() {
funcs = null;
exclusions = new ArrayList<>();
projectName = null;
}
@Override
public void launch(IEditorPart ed, String mode) {
resourceToSearchFor = ed.getTitle();
searchForResource = true;
//Note: This launch will eventually end up calling
//launch(IBinary bin, String mode) below
super.launch(ed, mode);
}
@Override
public void launch(IBinary bin, String mode) {
launch(bin, mode, null);
}
public void launch(IBinary bin, String mode, ILaunchConfigurationWorkingCopy wc) {
super.initialize();
this.bin = bin;
name = "SystemTapGraph"; //$NON-NLS-1$
binName = getName(bin);
partialScriptPath = PluginConstants.getPluginLocation()
+ "parse_function_partial.stp"; //$NON-NLS-1$
viewID = "org.eclipse.linuxtools.callgraph.callgraphview"; //$NON-NLS-1$
projectName = bin.getCProject().getElementName();
try {
if (wc == null) {
wc = createConfiguration(bin, name);
}
binaryPath = bin.getResource().getLocation().toString();
arguments = binaryPath;
outputPath = PluginConstants.getDefaultIOPath();
if (writeFunctionListToScript(resourceToSearchFor) == null) {
return;
}
if (funcs == null || funcs.length() < 0) {
return;
}
needToGenerate = true;
finishLaunch(name, mode, wc);
} catch (IOException e) {
SystemTapUIErrorMessages mess = new SystemTapUIErrorMessages(
"LaunchShortcutScriptGen", //$NON-NLS-1$
Messages.getString("LaunchStapGraph.ScriptGenErr"), //$NON-NLS-1$
Messages.getString("LaunchStapGraph.ScriptGenErrMsg")); //$NON-NLS-1$
mess.schedule();
e.printStackTrace();
} finally {
resourceToSearchFor = ""; //$NON-NLS-1$
searchForResource = false;
}
}
/**
* Generates the call and return function probes for the specified function
* @param function
* @return
*/
private String generateProbe(String function) {
return "probe process(@1).function(\"" + function + "\").call ? { if ( ! isinstr(\"" + function + "\", \"___STAP_MARKER___\")) { callFunction(\"" + function + "\",tid()) } } probe process(@1).function(\"" + function + "\").return ? { if ( ! isinstr(\"" + function + "\", \"___STAP_MARKER___\")) returnFunction(\"" + function + "\",tid()) else { printf(\"?%d,,%s\\n\", tid(), user_string(strtol(tokenize($$return, \"return=\"),16)))}}\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
}
/**
* Prompts the user for a list of functions to probe
*
* @param bw
* @return
*/
private String writeFunctionListToScript(String resourceToSearchFor) {
String toWrite = getFunctionsFromBinary(bin, resourceToSearchFor);
if (toWrite == null || toWrite.isEmpty()) {
return null;
}
StringBuffer output = new StringBuffer();
for (String func : toWrite.split(" ")) { //$NON-NLS-1$
if (!func.isEmpty()
&& (exclusions == null || exclusions.size() < 1 || exclusions
.contains(func))) {
output.append(generateProbe(func));
}
}
funcs = output.toString();
return funcs;
}
/**
* Copies the contents of the specified partial script. You should call writeStapMarkers first
* if you want StapMarkers to function properly.
*
* @param bw
* @return
* @throws IOException
*/
private String writeFromPartialScript(String projectName) throws IOException {
String toWrite = ""; //$NON-NLS-1$
String temp = ""; //$NON-NLS-1$
toWrite += "\nprobe begin{\n" + //$NON-NLS-1$
"printf(\"\\nPROBE_BEGIN\\n\")\n" + //$NON-NLS-1$
"serial=1\n" + //$NON-NLS-1$
"startTime = 0;\n" + //$NON-NLS-1$
"printf(\"" + projectName + "\\n\")\n" + //$NON-NLS-1$ //$NON-NLS-2$
"}"; //$NON-NLS-1$
File partialScript = new File(partialScriptPath);
try (BufferedReader scriptReader = new BufferedReader(new FileReader(
partialScript))) {
while ((temp = scriptReader.readLine()) != null) {
toWrite += temp + "\n"; //$NON-NLS-1$
}
scriptReader.close();
}
return toWrite;
}
@Override
public String generateScript() throws IOException {
String scriptContents = ""; //$NON-NLS-1$
scriptContents += funcs;
scriptContents += writeFromPartialScript(projectName);
return scriptContents;
}
@Override
public String setScriptPath() {
scriptPath = PluginConstants.getDefaultOutput()
+ "callgraphGen.stp"; //$NON-NLS-1$
return scriptPath;
}
@Override
public String setParserID() {
parserID = ATTR_PARSER;
return parserID;
}
@Override
public String setViewID() {
return ATTR_VIEWER;
}
}