![JAR search and dependency download from the Maven repository](/logo.png)
de.hdu.pvs.crashfinder.instrument.InstrumenterBench Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of crashFinder Show documentation
Show all versions of crashFinder Show documentation
A tool for localizing the software regression errors
The newest version!
package de.hdu.pvs.crashfinder.instrument;
//import java.io.BufferedWriter;
//import java.io.FileWriter;
import java.io.PrintStream;
import java.io.Writer;
import com.ibm.wala.shrikeBT.ConditionalBranchInstruction;
import com.ibm.wala.shrikeBT.ConstantInstruction;
import com.ibm.wala.shrikeBT.Constants;
import com.ibm.wala.shrikeBT.Disassembler;
import com.ibm.wala.shrikeBT.GetInstruction;
import com.ibm.wala.shrikeBT.IInstruction;
import com.ibm.wala.shrikeBT.Instruction;
import com.ibm.wala.shrikeBT.MethodData;
import com.ibm.wala.shrikeBT.MethodEditor;
import com.ibm.wala.shrikeBT.MethodEditor.Output;
import com.ibm.wala.shrikeBT.ReturnInstruction;
import com.ibm.wala.shrikeBT.ThrowInstruction;
import com.ibm.wala.shrikeBT.Util;
import com.ibm.wala.shrikeBT.analysis.Verifier;
import com.ibm.wala.shrikeBT.shrikeCT.CTDecoder;
import com.ibm.wala.shrikeBT.shrikeCT.ClassInstrumenter;
import com.ibm.wala.shrikeBT.shrikeCT.OfflineInstrumenter;
import com.ibm.wala.shrikeCT.ClassReader;
import com.ibm.wala.shrikeCT.ClassWriter;
/**
* This is a demo class.
*
* Class files are taken as input arguments (or if there are none, from standard
* input). The methods in those files are instrumented: we insert a
* System.err.println() at ever method call, and a System.err.println() at every
* method entry.
*
* In Unix, I run it like this: java -cp ~/dev/shrike/shrike
* com.ibm.wala.shrikeBT.shrikeCT.tools.Bench test.jar -o output.jar
*
* The instrumented classes are placed in the directory "output" under the
* current directory. Disassembled code is written to the file "report" under
* the current directory.
*/
public class InstrumenterBench extends AbstractInstrumenter {
private final static boolean disasm = true;
private final static boolean verify = true;
private static OfflineInstrumenter instrumenter;
final private static boolean doEntry = true;
private static boolean doExit = false;
private static boolean doException = false;
static final String fieldName = "_Bench_enable_trace";
// Keep these commonly used instructions around
static final Instruction getSysErr = Util.makeGet(System.class, "err");
static final Instruction callPrintln = Util.makeInvoke(PrintStream.class,
"println", new Class[] { String.class });
@Override
protected void doClass(ClassInstrumenter ci, Writer w) throws Exception {
final String className = ci.getReader().getName();
w.write("Class: " + className + "\n");
w.flush();
for (int m = 0; m < ci.getReader().getMethodCount(); m++) {
MethodData d = ci.visitMethod(m);
// d could be null, e.g., if the method is abstract or native
if (d != null) {
w.write("Instrumenting " + ci.getReader().getMethodName(m)
+ " " + ci.getReader().getMethodType(m) + ":\n");
w.flush();
if (disasm) {
w.write("Initial ShrikeBT code:\n");
(new Disassembler(d)).disassembleTo(w);
w.flush();
}
if (verify) {
Verifier v = new Verifier(d);
v.verify();
}
MethodEditor me = new MethodEditor(d);
me.beginPass();
if (doEntry) {
final String msg0 = "Entering call to "
+ Util.makeClass("L" + ci.getReader().getName()
+ ";") + "."
+ ci.getReader().getMethodName(m);
final int noTraceLabel = me.allocateLabel();
me.insertAtStart(new MethodEditor.Patch() {
@Override
public void emitTo(MethodEditor.Output w) {
w.emit(GetInstruction.make(Constants.TYPE_boolean,
CTDecoder.convertClassToType(className),
fieldName, true));
w.emit(ConstantInstruction.make(0));
w.emit(ConditionalBranchInstruction.make(
Constants.TYPE_int,
ConditionalBranchInstruction.Operator.EQ,
noTraceLabel));
w.emit(getSysErr);
w.emit(ConstantInstruction.makeString(msg0));
w.emit(callPrintln);
w.emitLabel(noTraceLabel);
}
});
}
if (doExit) {
final String msg0 = "Exiting call to "
+ Util.makeClass("L" + ci.getReader().getName()
+ ";") + "."
+ ci.getReader().getMethodName(m);
IInstruction[] instr = me.getInstructions();
for (int i = 0; i < instr.length; i++) {
if (instr[i] instanceof ReturnInstruction) {
final int noTraceLabel = me.allocateLabel();
me.insertBefore(i, new MethodEditor.Patch() {
@Override
public void emitTo(MethodEditor.Output w) {
w.emit(GetInstruction.make(
Constants.TYPE_boolean,
CTDecoder
.convertClassToType(className),
fieldName, true));
w.emit(ConstantInstruction.make(0));
w.emit(ConditionalBranchInstruction
.make(Constants.TYPE_int,
ConditionalBranchInstruction.Operator.EQ,
noTraceLabel));
w.emit(getSysErr);
w.emit(ConstantInstruction.makeString(msg0));
w.emit(callPrintln);
w.emitLabel(noTraceLabel);
}
});
}
}
}
if (doException) {
final String msg0 = "Exception exiting call to "
+ Util.makeClass("L" + ci.getReader().getName()
+ ";") + "."
+ ci.getReader().getMethodName(m);
final int noTraceLabel = me.allocateLabel();
me.addMethodExceptionHandler(null,
new MethodEditor.Patch() {
@Override
public void emitTo(Output w) {
w.emit(GetInstruction.make(
Constants.TYPE_boolean,
CTDecoder
.convertClassToType(className),
fieldName, true));
w.emit(ConstantInstruction.make(0));
w.emit(ConditionalBranchInstruction
.make(Constants.TYPE_int,
ConditionalBranchInstruction.Operator.EQ,
noTraceLabel));
w.emit(getSysErr);
w.emit(ConstantInstruction.makeString(msg0));
w.emit(callPrintln);
w.emitLabel(noTraceLabel);
w.emit(ThrowInstruction.make(false));
}
});
}
// this updates the data d
me.applyPatches();
if (disasm) {
w.write("Final ShrikeBT code:\n");
(new Disassembler(d)).disassembleTo(w);
w.flush();
}
}
}
if (ci.isChanged()) {
ClassWriter cw = ci.emitClass();
cw.addField(ClassReader.ACC_PUBLIC | ClassReader.ACC_STATIC,
fieldName, Constants.TYPE_boolean,
new ClassWriter.Element[0]);
instrumenter.outputModifiedClass(ci, cw);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy