Skip to content

Commit 8b87d09

Browse files
committed
Refactor Soot integration
1 parent 550833d commit 8b87d09

File tree

9 files changed

+286
-242
lines changed

9 files changed

+286
-242
lines changed

swan-pipeline/src/main/java/de/fraunhofer/iem/swan/data/Method.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.fasterxml.jackson.annotation.JsonIgnore;
44
import com.fasterxml.jackson.annotation.JsonProperty;
55
import org.apache.commons.lang3.StringUtils;
6+
import soot.SootClass;
67
import soot.SootMethod;
78
import soot.Type;
89

@@ -39,6 +40,10 @@ public class Method {
3940
private Javadoc javadoc = new Javadoc();
4041
@JsonProperty("jar")
4142
private String sourceJar;
43+
@JsonIgnore
44+
private SootMethod sootMethod;
45+
@JsonIgnore
46+
private SootClass sootClass;
4247

4348
public Method() {
4449
cwe = new HashSet<>();
@@ -329,7 +334,7 @@ public String getJavaSignature() {
329334
if (getName().equals("<init>"))
330335
methodName = getClassName().substring(getClassName().lastIndexOf(".") + 1);
331336

332-
return this.returnType + " " + this.className + "." + methodName + "(" + StringUtils.join(this.parameters, ", ") + ")";
337+
return this.returnType + " " + methodName + "(" + StringUtils.join(this.parameters, ", ") + ")";
333338
}
334339

335340
@JsonIgnore
@@ -354,6 +359,22 @@ public void setSourceJar(String source) {
354359
this.sourceJar = source;
355360
}
356361

362+
public SootMethod getSootMethod() {
363+
return sootMethod;
364+
}
365+
366+
public void setSootMethod(SootMethod sootMethod) {
367+
this.sootMethod = sootMethod;
368+
}
369+
370+
public SootClass getSootClass() {
371+
return sootClass;
372+
}
373+
374+
public void setSootClass(SootClass sootClass) {
375+
this.sootClass = sootClass;
376+
}
377+
357378
@Override
358379
public boolean equals(Object another) {
359380
if (super.equals(another))
@@ -366,7 +387,7 @@ public boolean equals(Object another) {
366387
return false;
367388
if (!this.parameters.equals(otherMethod.parameters))
368389
return false;
369-
return this.className.equals(otherMethod.className);
390+
return this.getClassName().equals(otherMethod.getClassName());
370391
}
371392

372393
@Override

swan-pipeline/src/main/java/de/fraunhofer/iem/swan/features/FeatureSet.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public List<FeatureSet.Type> initializeFeatures() {
7979
for (FeatureSet.Type featureSet : featureSets)
8080
switch (featureSet) {
8181
case CODE:
82-
codeFeatureHandler = new CodeFeatureHandler(trainData.getClasspath(), testData.getClasspath());
82+
codeFeatureHandler = new CodeFeatureHandler();
8383
codeFeatureHandler.initializeFeatures();
8484
break;
8585
case DOC_MANUAL:

swan-pipeline/src/main/java/de/fraunhofer/iem/swan/features/MekaFeatureSet.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ public void createFeatures() {
3232
Instances trainInstances = createInstances(featureSets, trainAttributes, trainData.getMethods(), getCategories(options.getAllClasses()), "train-instances");
3333
this.instances.put("train", convertToMekaInstances(trainInstances));
3434

35+
36+
System.out.println(testData.getMethods().size());
3537
//Create and set attributes for the test instances.
3638
ArrayList<Attribute> testAttributes = createAttributes(getCategories(options.getAllClasses()), testData.getMethods(), featureSets);
3739
Instances testInstances = createInstances(featureSets, testAttributes, testData.getMethods(), getCategories(options.getAllClasses()), "test-instances");
Lines changed: 193 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,201 @@
11
package de.fraunhofer.iem.swan.features.code.soot;
22

3+
import de.fraunhofer.iem.swan.data.Method;
4+
import de.fraunhofer.iem.swan.io.dataset.SrmListUtils;
5+
import de.fraunhofer.iem.swan.util.SootUtils;
6+
import de.fraunhofer.iem.swan.util.Util;
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
import soot.G;
310
import soot.Scene;
11+
import soot.SootClass;
12+
import soot.SootMethod;
413
import soot.options.Options;
514

15+
import java.io.IOException;
16+
import java.util.HashSet;
17+
import java.util.Set;
18+
619
public class InitializeSoot {
7-
8-
public InitializeSoot(){
9-
10-
}
11-
12-
private String[] buildArgs(String path){
13-
String[] result = {
14-
"-w",
15-
"-no-bodies-for-excluded",
16-
"-include-all",
17-
"-p",
18-
"cg.spark",
19-
"on",
20-
"-cp",
21-
path,
22-
"-p",
23-
"jb",
24-
"use-original-names:true",
25-
"-f",
26-
"n",
27-
//do not merge variables (causes problems with PointsToSets)
28-
"-p",
29-
"jb.ulp",
30-
"off"
31-
};
32-
33-
return result;
34-
}
35-
36-
public void initialize(String path){
37-
String[] args = buildArgs(path);
38-
39-
Options.v().set_allow_phantom_refs(true);
40-
Options.v().set_prepend_classpath(true);
41-
Options.v().set_output_format(Options.output_format_none);
42-
Options.v().parse(args);
43-
44-
Options.v().set_whole_program(true);
45-
Scene.v().addBasicClass(Object.class.getName());
46-
Scene.v().loadNecessaryClasses();
47-
}
4820

21+
private static boolean SOOT_INITIALIZED = false;
22+
private static final Logger logger = LoggerFactory.getLogger(SrmListUtils.class);
23+
private String classpath;
24+
25+
public InitializeSoot(String... path) {
26+
27+
this.classpath = Util.buildCP(path);
28+
initializeSoot(classpath);
29+
}
30+
31+
private String[] buildArgs(String path) {
32+
String[] result = {
33+
"-w",
34+
"-no-bodies-for-excluded",
35+
"-include-all",
36+
"-p",
37+
"cg.spark",
38+
"on",
39+
"-cp",
40+
path,
41+
"-p",
42+
"jb",
43+
"use-original-names:true",
44+
"-f",
45+
"n",
46+
//do not merge variables (causes problems with PointsToSets)
47+
"-p",
48+
"jb.ulp",
49+
"off"
50+
};
51+
52+
return result;
53+
}
54+
55+
public void initialize(String path) {
56+
String[] args = buildArgs(path);
57+
58+
Options.v().set_allow_phantom_refs(true);
59+
Options.v().set_prepend_classpath(true);
60+
Options.v().set_output_format(Options.output_format_none);
61+
Options.v().parse(args);
62+
63+
Options.v().set_whole_program(true);
64+
Scene.v().addBasicClass(Object.class.getName());
65+
Scene.v().loadNecessaryClasses();
66+
}
67+
68+
69+
public Set<Method> cleanupList(Set<Method> methods) throws IOException {
70+
71+
Set<Method> purgedMethods = prefilterInterfaces(methods);
72+
73+
Util.createSubclassAnnotations(purgedMethods, classpath);
74+
Util.sanityCheck(purgedMethods, new HashSet<>());
75+
76+
return purgedMethods;
77+
}
78+
79+
public void runSoot(String path) {
80+
81+
}
82+
83+
84+
private void initializeSoot(String cp) {
85+
if (SOOT_INITIALIZED)
86+
return;
87+
88+
G.reset();
89+
90+
Options.v().set_allow_phantom_refs(true);
91+
Options.v().set_prepend_classpath(true);
92+
Options.v().set_whole_program(true);
93+
Options.v().set_include_all(true);
94+
Options.v().set_soot_classpath(cp);
95+
96+
Scene.v().loadNecessaryClasses();
97+
SOOT_INITIALIZED = true;
98+
}
99+
100+
protected SootClass getSootClass(Method method) {
101+
102+
SootClass c = Scene.v().forceResolve(method.getClassName(), SootClass.BODIES);
103+
104+
if (c == null || c.isPhantom()) {
105+
return null;
106+
}
107+
108+
return c;
109+
}
110+
111+
protected SootMethod getSootMethod(Method method) {
112+
return getSootMethod(method, true);
113+
}
114+
115+
protected SootMethod getSootMethod(Method method, boolean lookInHierarchy) {
116+
117+
SootClass c = Scene.v().forceResolve(method.getClassName(), SootClass.BODIES);
118+
119+
if (c == null || c.isPhantom()) {
120+
return null;
121+
}
122+
123+
c.setApplicationClass();
124+
if (c.isInterface()) return null;
125+
126+
while (c != null) {
127+
// Does the current class declare the method we are looking for?
128+
if (method.getReturnType().isEmpty()) {
129+
if (c.declaresMethodByName(method.getName()))
130+
return c.getMethodByName(method.getName());
131+
} else {
132+
//System.out.println(method.getSubSignature());
133+
if (c.declaresMethod(method.getSubSignature()))
134+
return c.getMethod(method.getSubSignature());
135+
}
136+
137+
// Continue our search up the class hierarchy
138+
if (lookInHierarchy && c.hasSuperclass())
139+
c = c.getSuperclass();
140+
else
141+
c = null;
142+
}
143+
return null;
144+
}
145+
146+
/**
147+
* Removes all interfaces from the given set of methods and returns the purged
148+
* set.
149+
*/
150+
private Set<Method> prefilterInterfaces(Set<Method> methods) {
151+
Set<Method> purgedMethods = new HashSet<>();
152+
153+
for (Method method : methods) {
154+
155+
SootMethod sootMethod = getSootMethod(method);
156+
method.setSootMethod(sootMethod);
157+
method.setSootClass(getSootClass(method));
158+
159+
if (sootMethod == null)
160+
continue;
161+
162+
if (sootMethod.isAbstract())
163+
logger.info("Method purged from list {}", method.getSignature());
164+
else
165+
purgedMethods.add(method);
166+
}
167+
168+
logger.info("{} methods purged down to {}", methods.size(), purgedMethods.size());
169+
return purgedMethods;
170+
}
171+
172+
public Set<Method> loadMethodsFromTestLib(Set<String> testClasses) {
173+
Set<Method> methods = new HashSet<>();
174+
175+
for (String className : testClasses) {
176+
177+
SootClass sc = Scene.v().forceResolve(className, SootClass.BODIES);
178+
179+
if (sc == null || !testClasses.contains(sc.getName()))
180+
continue;
181+
182+
if (!sc.isInterface() && !sc.isPrivate()) {
183+
for (SootMethod sm : sc.getMethods()) {
184+
185+
if (sm.isConcrete()) {
186+
// This is done by hand here because of the cases where the
187+
// character ' is in the signature. This is not supported by the
188+
// current Soot.
189+
190+
// TODO: Get Soot to support the character '
191+
Method method = SootUtils.convertSootSignature(sm.getSignature());
192+
method.setSootMethod(sm);
193+
method.setSootClass(sc);
194+
methods.add(method);
195+
}
196+
}
197+
}
198+
}
199+
return methods;
200+
}
49201
}

swan-pipeline/src/main/java/de/fraunhofer/iem/swan/features/code/soot/SourceFileLoader.java

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,57 +14,35 @@
1414

1515
public class SourceFileLoader {
1616

17-
private final String classpath;
18-
private Set<Method> methods = new HashSet<>();
19-
Set<String> testClasses;
17+
private Set<Method> methods;
18+
private Set<String> testClasses;
2019

2120
public SourceFileLoader(String sourceFileDir) throws IOException {
2221

2322
testClasses = Util.getAllClassesFromDirectory(sourceFileDir);
24-
this.classpath = Util.buildCP(sourceFileDir);
23+
methods = new HashSet<>();
2524
}
2625

2726
public void load(final Set<Method> trainingSet) {
28-
loadMethodsFromTestLib();
29-
Util.createSubclassAnnotations(methods, classpath);
27+
28+
Util.createSubclassAnnotations(methods, "classpath");
3029
methods = Util.sanityCheck(methods, trainingSet);
3130
}
3231

33-
public void loadMethodsFromTestLib() {
34-
35-
new AbstractSootFeature(classpath) {
36-
37-
@Override
38-
public Type appliesInternal(Method method) {
3932

40-
for (String className : testClasses) {
41-
SootClass sc = Scene.v().forceResolve(className, SootClass.HIERARCHY);
42-
43-
if (sc == null || !testClasses.contains(sc.getName()))
44-
continue;
45-
46-
if (!sc.isInterface() && !sc.isPrivate())
47-
for (SootMethod sm : sc.getMethods()) {
48-
if (sm.isConcrete()) {
49-
// This is done by hand here because of the cases where the
50-
// character ' is in the signature. This is not supported by the
51-
// current Soot.
52-
// TODO: Get Soot to support the character '
53-
methods.add(SootUtils.convertSootSignature(sm.getSignature()));
54-
}
55-
}
56-
}
57-
return Type.NOT_SUPPORTED;
58-
}
33+
public Set<String> getTestClasses() {
34+
return testClasses;
35+
}
5936

60-
}.applies(new Method("a", "void", "x.y"));
37+
public void setTestClasses(Set<String> testClasses) {
38+
this.testClasses = testClasses;
6139
}
6240

6341
public Set<Method> getMethods() {
6442
return methods;
6543
}
6644

67-
public String getClasspath() {
68-
return classpath;
45+
public void setMethods(Set<Method> methods) {
46+
this.methods = methods;
6947
}
7048
}

0 commit comments

Comments
 (0)