aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Berk2012-09-24 11:19:47 (EDT)
committerRoland Grunberg2012-09-24 16:44:40 (EDT)
commit21f3355c4cdcd607146d5e5451add1ba21201064 (patch)
treee7799f869ab54916e1ba26ed6ffa52f888bff1ba
parentf4ce880b10d1859e7e4dbd4634fa6f1746e013dc (diff)
downloadorg.eclipse.linuxtools-21f3355c4cdcd607146d5e5451add1ba21201064.zip
org.eclipse.linuxtools-21f3355c4cdcd607146d5e5451add1ba21201064.tar.gz
org.eclipse.linuxtools-21f3355c4cdcd607146d5e5451add1ba21201064.tar.bz2
Re-write of systemtap probe and function parsers.
This commit alters how eclipse finds the probe points and functions that systemtap has available to users and developers. By leveraging stap -L '**' we are able to simplify the probe points parsing process. Probe points remain clickable to enter into the .stp file under development and java doc continues to appear listing related variables. For probing systemtap functions, stap -v -p1 -e 'probe begin{}' is still used, however, a second uncompressed pass is not required to list all available functions that systemtap intends a typical user to use. Functions starting with _ or __ are intended to be internal to the tapset. In addition, functions are now listed in alphabetical order, instead of by tapset file, to make them easier to discover/locate. Change-Id: I852dc429bb3ca4f5b61aeb7f4ef1765f401fecf8 Reviewed-on: https://git.eclipse.org/r/7898 Tested-by: Hudson CI Reviewed-by: Roland Grunberg <rgrunber@redhat.com> IP-Clean: Roland Grunberg <rgrunber@redhat.com> Tested-by: Roland Grunberg <rgrunber@redhat.com>
-rw-r--r--systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/views/BrowserView.java2
-rw-r--r--systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/systemtap/ui/ide/structures/TapsetLibrary.java4
-rw-r--r--systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/systemtap/ui/ide/structures/TapsetParser.java450
3 files changed, 104 insertions, 352 deletions
diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/views/BrowserView.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/views/BrowserView.java
index 699d8cd..943a182 100644
--- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/views/BrowserView.java
+++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/internal/systemtap/ui/ide/views/BrowserView.java
@@ -127,6 +127,8 @@ public abstract class BrowserView extends ViewPart {
img = IDEPlugin.getImageDescriptor("icons/vars/var_str.gif").createImage();
else if(item.endsWith(":unknown"))
img = IDEPlugin.getImageDescriptor("icons/vars/var_unk.gif").createImage();
+ else
+ img = IDEPlugin.getImageDescriptor("icons/vars/var_long.gif").createImage();
}
return img;
diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/systemtap/ui/ide/structures/TapsetLibrary.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/systemtap/ui/ide/structures/TapsetLibrary.java
index 97d0f8b..bdb03c7 100644
--- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/systemtap/ui/ide/structures/TapsetLibrary.java
+++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/systemtap/ui/ide/structures/TapsetLibrary.java
@@ -52,7 +52,7 @@ public final class TapsetLibrary {
public static void init() {
if(null != stpp && stpp.isRunning())
return;
-
+
if(IDEPlugin.getDefault().getPreferenceStore()
.getBoolean(IDEPreferenceConstants.P_STORED_TREE) &&
isTreeFileCurrent())
@@ -68,7 +68,7 @@ public final class TapsetLibrary {
private static void runStapParser() {
String[] tapsets = IDEPlugin.getDefault().getPreferenceStore()
.getString(IDEPreferenceConstants.P_TAPSETS).split(File.pathSeparator);
-
+
stpp = new TapsetParser(tapsets);
stpp.start();
stpp.addListener(completionListener);
diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/systemtap/ui/ide/structures/TapsetParser.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/systemtap/ui/ide/structures/TapsetParser.java
index 85bc633..64327d5 100644
--- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/systemtap/ui/ide/structures/TapsetParser.java
+++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide/src/org/eclipse/linuxtools/systemtap/ui/ide/structures/TapsetParser.java
@@ -14,6 +14,8 @@ package org.eclipse.linuxtools.systemtap.ui.ide.structures;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.StringTokenizer;
+import java.util.regex.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
@@ -135,8 +137,6 @@ public class TapsetParser implements Runnable {
public void run() {
runPass2Functions();
fireUpdateEvent(); //Inform listeners that a new batch of functions has variable info
- runPass2Probes();
- fireUpdateEvent(); //Inform listeners that a new batch of probes has variable info
successfulFinish = true;
fireUpdateEvent(); //Inform listeners that everything is done
}
@@ -231,19 +231,18 @@ public class TapsetParser implements Runnable {
}
/**
- * Returns a String containing all of the content from the files
- * contained in the tapset libraries. This file always returns
- * what ever it could get, even if an exception was generated.
+ * Returns a String containing all of the content from the probe
+ * point list, including variables and their type.
*
- * stap -vp1 -e 'probe begin{}'
- * Will list everything defined in the tapsets
- * @return the tapset library consolodated into a single string
+ * stap -v -p1 -L
+ * Will list all available probe points
+ * @return the probe points consolidated into a single string
*/
private String readPass1(String script) {
String[] options;
if(null == script) {
- script = "probe begin{}";
- options = new String[] {"-p1", "-v", "-e"};
+ script = "**";
+ options = new String[] {"-p1", "-v", "-L"};
} else {
options = null;
}
@@ -252,7 +251,7 @@ public class TapsetParser implements Runnable {
}
/**
- * Parses the output generated from running stap -vp1. Pulls out all functions
+ * Parses the output generated from running stap -v -p1 -L. Pulls out all functions
* and probe aliases from the provided string. Populates the probe and function
* trees.
*
@@ -261,226 +260,108 @@ public class TapsetParser implements Runnable {
*
* FunctionTree organized as:
* Root->Files->Functions
- * @param s The entire output from running stap -vp1.
+ * @param s The entire output from running stap -v -p1 -L.
*/
private void parseLevel1(String s) {
String prev = null;
- String prev2 = null;
StringBuilder token = new StringBuilder("");
TreeNode parent;
TreeNode item;
- char currChar;
- boolean isProbe = false;
-
- boolean contains;
- TreeNode child;
- int z;
-
- for(int i=0; i<s.length(); i++) {
- currChar = s.charAt(i);
- if(!Character.isWhitespace(currChar) && '}' != currChar && '{' != currChar) {
- token.append(currChar);
- } else if(token.length() > 0){
- prev2 = prev;
- prev = token.toString();
- token.delete(0, token.length());
- }
- //Only check for new values when starting a fresh token.
- if(1 == token.length()) {
- if("probe".equals(prev2) && "=".equals(token.toString())) {
- //Probe alias found
- do {
- currChar = s.charAt(++i);
- token.append(currChar);
- } while('{' != currChar && i < s.length());
-
- parent = probes.getChildAt(probes.getChildCount()-1);
- parent.add(new TreeDefinitionNode("probe " + token.toString().substring(2, token.length()-1), prev, parent.getData().toString(), true));
- isProbe = true;
- } else if("function".equals(prev2)) {
- //Function found
- do {
- currChar = s.charAt(++i);
- token.append(currChar);
- } while(')' != currChar && i < s.length());
-
- parent = functions.getChildAt(functions.getChildCount()-1);
- parent.add(new TreeDefinitionNode(prev + token.toString(), prev + token.toString(), parent.getData().toString(), true));
- isProbe = false;
- } else if("file".equals(prev2)) {
- //New file started
- if(prev.lastIndexOf('/') > 0)
- prev2 = prev.substring(prev.lastIndexOf('/')+1);
- functions.add(new TreeNode(prev, prev2, false));
- probes.add(new TreeNode(prev, prev2, false));
- isProbe = false;
- }
- } else if(prev2 != null && prev2.length() > 2 && token.length() > 2 && isProbe &&
- '(' == prev2.charAt(0) && ')' == prev2.charAt(prev2.length()-1) &&
- '(' == token.charAt(0) && ')' == token.charAt(token.length()-1) &&
- "=".equals(prev)) {
- //Put all variables in the probe tree
- item = probes.getChildAt(probes.getChildCount()-1);
- prev2 = prev2.substring(1,prev2.length()-1);
- child = item.getChildAt(item.getChildCount()-1);
- contains = false;
- for(z=0; z<child.getChildCount(); z++) {
- if(child.getChildAt(z).toString().equals(prev2)) {
- contains = true;
- break;
- }
- }
-
- if(!contains)
- child.add(new TreeNode(prev2 + ":unknown", prev2, false));
-
- prev2 = null;
- } else if ("/*".equals(token.toString())){
- // Skip comments
- for(; i<s.length()-1; i++) {
- if (s.regionMatches(i, "*/", 0, 2)){
- i++;
- break;
- }
- }
- // clear token
- token.delete(0, token.length());
- } else if ("//".equals(token.toString())){
- // Skip comments
- for(; i<s.length(); i++) {
- if (s.charAt(i) == '\n'){
- break;
- }
- }
- // clear token
- token.delete(0, token.length());
- }
- }
+ TreeNode child;
+
+ StringTokenizer st = new StringTokenizer(s, "\n", false);
+ st.nextToken(); //skip the stap command itself
+ while(st.hasMoreTokens()){
+ StringTokenizer next_level = new StringTokenizer(st.nextToken());
+ token.setLength(0);
+ int total = next_level.countTokens();
+ for(int i = 0; i < total; i++){
+ prev = next_level.nextToken();
+ if(i == 0) {
+ probes.add(new TreeNode(prev, prev, true));
+ parent = probes.getChildAt(probes.getChildCount()-1);
+ parent.add(new TreeDefinitionNode("probe " + prev, prev, parent.getData().toString(), true));
+ }
+ else if(i < (total - 1)) {
+ //if the token is empty, of course add it
+ if(token.length() == 0) {
+ token.append(prev);
+ }
+ //if the token has a : already, and the current token doesn't, append it
+ else if(!(token.length()==0) && !prev.contains(":")) {
+ token.append(prev + " ");
+ }
+ //if token isn't empty, and the current one contains a ':', add token, empty, and append prev
+ else if(!(token.length()==0) && prev.contains(":")) {
+ item = probes.getChildAt(probes.getChildCount()-1);
+ child = item.getChildAt(item.getChildCount()-1);
+ child.add(new TreeNode(token.toString(), token.toString(), false));
+ token.setLength(0);
+ token.append(prev + " ");
+ }
+ }
+ else if(i == (total - 1)) {
+ if(prev.contains(":")) { //add token, then add prev
+ item = probes.getChildAt(probes.getChildCount()-1);
+ child = item.getChildAt(item.getChildCount()-1);
+ child.add(new TreeNode(token.toString(), token.toString(), false));
+ item = probes.getChildAt(probes.getChildCount()-1);
+ child = item.getChildAt(item.getChildCount()-1);
+ child.add(new TreeNode(prev, prev, false));
+ }
+ else { // end var type, append to token, then add token
+ token.append(prev);
+ item = probes.getChildAt(probes.getChildCount()-1);
+ child = item.getChildAt(item.getChildCount()-1);
+ child.add(new TreeNode(token.toString(), token.toString(), false));
+ }
+ }
+ }
+ }
}
/**
* This method is used to build up the list of functions that were found
- * durring the first pass of stap. These functions will then all be passed
- * on to have stap -up2 run on them in order to find the variable types
- * associated with them.
+ * during the first pass of stap. Stap is invoked by: $stap -v -p1 -e
+ * 'probe begin{}' and parsing the output.
*/
private void runPass2Functions() {
- int i, j, k, l=0;
- TreeNode child;
- String function;
- String[] parameters = new String[0];
- StringBuilder probe = new StringBuilder("");
-
- ArrayList<String> functionNames = new ArrayList<String>();
-
- //Add Functions
- for(i=0; i<functions.getChildCount(); i++) {
- child = functions.getChildAt(i);
- for(j=0; j<child.getChildCount(); j++) {
- probe.delete(0, probe.length());
- function = child.getChildAt(j).toString();
- probe.append(function.substring(0, function.indexOf("(")+1));
- function = function.substring(function.indexOf("(")+1, function.indexOf(")"));
- parameters = function.split(",");
-
- //Make sure each parameter has a distinct name so there isn't a type problem
- if(parameters[0].length() > 0) {
- for(k=0; k<parameters.length; k++) {
- if(k>0)
- probe.append(",");
- probe.append(parameters[k] + l++);
+ int i = 0;
+ TreeNode parent;
+ String script = "probe begin{}";
+ String result = runStap(new String[] {"-v", "-p1", "-e"}, script);
+ StringTokenizer st = new StringTokenizer(result, "\n", false);
+ st.nextToken(); //skip that stap command
+ String tok = "";
+ while(st.hasMoreTokens()) {
+ tok = st.nextToken().toString();
+ String regex = "^function .*\\)\n$"; //match ^function and ending the line with ')'
+ Pattern p = Pattern.compile(regex, Pattern.MULTILINE | Pattern.UNIX_LINES | Pattern.COMMENTS);
+ Matcher m = p.matcher(tok);
+ while(m.find()) {
+ // this gives us function foo (bar, bar)
+ // we need to strip the ^function and functions with a leading _
+ Pattern secondp = Pattern.compile("[\\W]"); //take our function line and split it up
+ Pattern underscorep = Pattern.compile("^function _.*"); //remove any lines that "^function _"
+ String[] us = underscorep.split(m.group().toString());
+
+ for(String s : us) {
+ String[] test = secondp.split(s);
+ i = 0;
+ for(String t : test) {
+ if(i == 1) {
+ functions.add(new TreeNode(t, t, true));
+ }
+ else if(i > 1 && t.length() >= 1) {
+ parent = functions.getChildAt(functions.getChildCount()-1);
+ parent.add(new TreeDefinitionNode("function " + t, t, parent.getData().toString(), false));
+ }
+ i++;
}
}
- probe.append(")\n");
- functionNames.add(probe.toString());
- }
- }
- parameters = functionNames.toArray(parameters);
- runPass2FunctionSet(parameters, 0, parameters.length-1);
- }
-
- /**
- * This method runs stap -up2 on the specified group of functions.
- * If errors result, it will break the batch in half and run again
- * on each subset
- * @param funcs The list of all functions available in the tapsets
- * @param low The lower bound of functions to use in this set
- * @param high The upper bound of functions to use in this set
- */
- private void runPass2FunctionSet(String[] funcs, int low, int high) {
- if(low == high)
- return;
- if(stopped)
- return;
-
- StringBuilder functionStr = new StringBuilder("probe begin{\n");
- for(int i=low; i<high; i++)
- functionStr.append(funcs[i]);
- functionStr.append("}\n");
-
- String result = runStap(new String[] {"-u", "-p2", "-e"}, functionStr.toString());
-
- if(0 < result.trim().length()) {
- parsePass2Functions(result);
- } else if(low+1 != high) {
- runPass2FunctionSet(funcs, low, low+((high-low)>>1));
- runPass2FunctionSet(funcs, low+((high-low)>>1), high);
- }
- }
-
- /**
- * Runs stap -up2 on the probe tree. The tree is broken up into
- * smaller components to allow components to be completed at a time.
- */
- private void runPass2Probes() {
- //Add Probes
- TreeNode temp;
- for(int i=0; i<probes.getChildCount(); i++) {
- if(stopped)
- return;
- temp = probes.getChildAt(i);
- runPass2ProbeSet(temp, 0, temp.getChildCount());
- }
- }
-
- /**
- * Does a depth first search for valid probes: Runs stap -up2 on the
- * selected probe group, using high and low to determine which
- * subelements to select. If an error is encountered in a group this
- * function divides the group into a top and bottom half and makes a
- * recursive call on each subgroup to isolate the failing probes.
- * @param probe The top level probe group to probe.
- * @param low The lower bound of child elements of probe to include
- * @param high The upper bound of child elements of probe to include
- */
- private void runPass2ProbeSet(TreeNode probe, int low, int high) {
-
- if(low == high || this.stopped)
- return;
-
- TreeNode temp;
- StringBuilder probeStr = new StringBuilder("");
- String result;
-
- for(int i=low; i<high; i++) {
- temp = probe.getChildAt(i);
- if(temp.getData().toString().startsWith("probe"))
- probeStr.append("\nprobe " + temp.toString() + "{}");
- else
- runPass2ProbeSet(temp, 0, temp.getChildCount());
- }
- result = runStap(new String[] {"-u", "-p2", "-e"}, probeStr.toString());
-
- if(0 < result.trim().length()) {
- boolean success = parsePass2Probes(result,probe);
- if(!success && low+1 != high) {
- runPass2ProbeSet(probe, low, low+((high-low)>>1));
- runPass2ProbeSet(probe, low+((high-low)>>1), high);
}
- } else if(low+1 != high) {
- runPass2ProbeSet(probe, low, low+((high-low)>>1));
- runPass2ProbeSet(probe, low+((high-low)>>1), high);
+ functions.sortTree();
}
}
@@ -533,14 +414,16 @@ public class TapsetParser implements Runnable {
fileNode = probes.getChildAt(i);
for(j=0; j<fileNode.getChildCount(); j++) { //Actual probes
probe = fileNode.getChildAt(j);
-
directory = probe.toString();
+
if(directory.endsWith(".return") || directory.endsWith(".entry"))
directory = directory.substring(0, directory.lastIndexOf('.'));
+
folders = directory.split("\\.");
-
probeGroup = probes2;
+
for(int k=0; k<folders.length-1; k++) { //Complete path directory
+
added = false;
for(int l=0; l<probeGroup.getChildCount(); l++) { //Destination folder
probeFolder = probeGroup.getChildAt(l);
@@ -562,140 +445,7 @@ public class TapsetParser implements Runnable {
probes = probes2;
probes.sortTree();
}
-
- /**
- * Parses the output generated from running stap -up2 on the list of functions.
- * Will update the function tree with return values for each function.
- * @param s The entire output from running stap -up2 on the functions.
- */
- private void parsePass2Functions(String s) {
- int i, j, k;
- TreeNode child, child2;
- String childString;
- String[] functionLines = new String[0];
- if(s.contains("# functions") && s.contains("# probes"))
- functionLines = s.substring(s.indexOf("# functions"), s.indexOf("# probes")).split("\n");
-
- //Rename the functions with types
- for(i=0; i<functionLines.length; i++) {
- for(j=0; j<functions.getChildCount(); j++) {
- child = functions.getChildAt(j);
- for(k=0; k<child.getChildCount(); k++) {
- child2 = child.getChildAt(k);
- childString = child2.toString();
- if (childString.indexOf("(") != -1) {
- if(functionLines[i].startsWith(childString.substring(0, childString.indexOf("(")).trim() + ":")) {
- child2.setData(functionLines[i]);
- break;
- }
- }
- }
- }
- }
- }
-
- /**
- * Parses the output generated from running stap -up2 on the list of probes.
- * Will update the probe alias tree with additional variables, as well as
- * placing the type associated with the variable.
- * @param s The entire output from running stap -up2 on the provided probeSet.
- * @param probeSet The group of probes that the String s corresponds to
- */
- private boolean parsePass2Probes(String s, TreeNode probeSet) {
- LogManager.logDebug("Start parseLevel2Probes: probeSet-" + probeSet, this); //$NON-NLS-1$
- TreeNode tree = new TreeNode("", false);
- TreeNode probe = null;
- String[] probeLines = null;
- boolean variables = false;
- String line;
- if(s.contains("# probes"))
- probeLines = s.substring(s.indexOf("# probes")).split("\n");
-
- if(null == probeLines)
- return false;
-
- //Build Pass 2 tree
- for(int i=0; i<probeLines.length; i++) {
- line = probeLines[i].trim();
-
- if(line.startsWith("kernel.")) {
- probe = new TreeNode(line, false);
- tree.add(probe);
- //probe = lookupProbe(line, probeSet);
- variables = false;
- } else if(line.equals("# locals") && null != probe) {
- variables = true;
- } else if(null != probe && variables) {
- if(line.contains(":"))
- probe.add(new TreeNode(line, line.substring(0, line.lastIndexOf(":")).trim(), false));
- } else {
- probe = null;
- }
- }
-
- //Consolidate pass1 and pass2 trees
- int i, j, k, l;
- boolean matched;
- TreeNode one, two, oneC, twoC;
- for(i=0; i<probeSet.getChildCount(); i++) {
- for(j=0; j<tree.getChildCount(); j++) {
- one = probeSet.getChildAt(i);
- two = tree.getChildAt(j);
-
- if(probesMatch(one, two)) {
- for(l=0; l<two.getChildCount(); l++) {
- matched = false;
- twoC = two.getChildAt(l);
- for(k=0; k<one.getChildCount(); k++) {
- oneC = one.getChildAt(k);
- if(oneC.getData().toString().substring(0, oneC.getData().toString().indexOf(":")).
- equals(twoC.getData().toString().substring(0, twoC.getData().toString().indexOf(":")))) {
- oneC.setData(twoC.getData());
- matched = true;
- }
- }
- if(!matched)
- one.add(new TreeNode(twoC.getData(), twoC.toString(), false));
- }
- }
- }
- }
-
- tree.dispose();
- tree = null;
- return true;
- }
-
- /**
- * Compares the probes contained in the treeNodes to make sure they
- * are actually probing the same kernel location.
- * @param one A treeNode generated from stap -p1.
- * @param two A treeNode generated from stap -up2.
- * @return A boolean signifing if the treeNodes represent the same probe point.
- */
- private boolean probesMatch(TreeNode one, TreeNode two) {
- try {
- String valOneA = one.getData().toString();
- String valTwoA = two.getData().toString();
- String valOneB = "";
- String valTwoB = valTwoA.substring(valTwoA.indexOf("\"")+1, valTwoA.indexOf("@"));
-
- if(valOneA.contains("\""))
- valOneB = valOneA.substring(valOneA.indexOf("\"")+1);
- if(valOneB.contains("\""))
- valOneB = valOneB.substring(0, valOneB.indexOf("\""));
-
- if(valOneB.equals(valTwoB)) {
- if(valOneA.contains(".return") == valTwoA.contains(".return"))
- return true;
- }
- } catch(Exception e) {
- LogManager.logCritical("Exception probesMatch: " + e.getMessage() + "\n" + one + "\n" + two, this); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
- return false;
- }
-
/**
* This method will clean up everything from the run.
*/