move around some utility methods

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@3810 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
msridhar1 2010-04-24 18:12:17 +00:00
parent f35d4de0d8
commit c1860e180c
3 changed files with 72 additions and 99 deletions

View File

@ -10,6 +10,7 @@
*******************************************************************************/
package com.ibm.wala.shrikeBT;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
@ -40,6 +41,24 @@ public final class MethodData {
private boolean hasChanged = false;
/**
* Create information for a method, with no exception handlers and a dummy mapping of instructions to original bytecodes.
* @param access the access flags
* @param classType the class in which the method is defined, in JVM type format (e.g., Ljava/lang/Object;)
* @param name the method name
* @param signature the method signature, in JVM type format (e.g., (ILjava/lang/Object;)V)
* @param instructions the instructions making up the method
*/
public static MethodData makeWithDefaultHandlersAndInstToBytecodes(int access, String classType, String name, String signature, IInstruction[] instructions) {
ExceptionHandler[][] handlers = new ExceptionHandler[instructions.length][];
Arrays.fill(handlers, new ExceptionHandler[0]);
int[] i2b = new int[instructions.length];
for (int i = 0; i < i2b.length; i++) {
i2b[i] = i;
}
return new MethodData(access, classType, name, signature, instructions, handlers, i2b);
}
/**
* Gather the information for a method "from scratch".
*

View File

@ -11,9 +11,14 @@
package com.ibm.wala.shrikeBT.shrikeCT;
import com.ibm.wala.shrikeBT.Constants;
import com.ibm.wala.shrikeBT.MethodData;
import com.ibm.wala.shrikeBT.analysis.ClassHierarchyStore;
import com.ibm.wala.shrikeCT.ClassReader;
import com.ibm.wala.shrikeCT.ClassWriter;
import com.ibm.wala.shrikeCT.CodeWriter;
import com.ibm.wala.shrikeCT.InvalidClassFileException;
import com.ibm.wala.shrikeCT.LineNumberTableWriter;
import com.ibm.wala.shrikeCT.ClassWriter.Element;
/**
* This is a dumping ground for useful functions that manipulate class info.
@ -38,4 +43,52 @@ public class CTUtils {
.getAccessFlags() & Constants.ACC_FINAL) != 0, superName != null ? CTDecoder.convertClassToType(superName) : null,
superInterfaces);
}
/**
* Compile and add a method to a {@link ClassWriter}.
*
* @param md the method data
* @param classWriter the target class writer
* @param rawLines line number information if available, otherwise <code>null</code>
*/
public static void compileAndAddMethodToClassWriter(MethodData md, ClassWriter classWriter, ClassWriter.Element rawLines) {
if (classWriter == null) {
throw new IllegalArgumentException("classWriter is null");
}
if (md == null) {
throw new IllegalArgumentException("md is null");
}
CTCompiler compiler = CTCompiler.make(classWriter, md);
compiler.compile();
CTCompiler.Output output = compiler.getOutput();
CodeWriter code = new CodeWriter(classWriter);
code.setMaxStack(output.getMaxStack());
code.setMaxLocals(output.getMaxLocals());
code.setCode(output.getCode());
code.setRawHandlers(output.getRawHandlers());
LineNumberTableWriter lines = null;
// I guess it is the line numbers in the java files.
if (rawLines == null) {
// add fake line numbers: just map each bytecode instruction to its own
// 'line'
// NOTE:Should not use md.getInstructions().length, because the
// the length of the created code can be smaller than the md's instruction
// length
// WRONG: int[] newLineMap = new int[md.getInstructions().length];
int[] newLineMap = new int[code.getCodeLength()];
for (int i = 0; i < newLineMap.length; i++) {
newLineMap[i] = i;
}
int[] rawTable = LineNumberTableWriter.makeRawTable(newLineMap);
lines = new LineNumberTableWriter(classWriter);
lines.setRawTable(rawTable);
}
code.setAttributes(new ClassWriter.Element[] { rawLines == null ? lines : rawLines });
Element[] elements = { code };
// System.out.println("Name:"+md.getName()+" Sig:"+md.getSignature());
classWriter.addMethod(md.getAccess(), md.getName(), md.getSignature(), elements);
}
}

View File

@ -10,7 +10,6 @@
*******************************************************************************/
package com.ibm.wala.shrikeBT.shrikeCT;
import java.util.ArrayList;
import java.util.Arrays;
import com.ibm.wala.shrikeBT.Compiler;
@ -32,7 +31,6 @@ import com.ibm.wala.shrikeCT.LineNumberTableReader;
import com.ibm.wala.shrikeCT.LineNumberTableWriter;
import com.ibm.wala.shrikeCT.LocalVariableTableReader;
import com.ibm.wala.shrikeCT.LocalVariableTableWriter;
import com.ibm.wala.shrikeCT.ClassWriter.Element;
/**
* This class provides a convenient way to instrument every method in a class. It assumes you are using ShrikeCT to read and write
@ -162,103 +160,6 @@ final public class ClassInstrumenter {
}
/**
* Xiangyu
*
* @throws IllegalArgumentException if classWriter is null
* @throws IllegalArgumentException if instructions is null
*
*
*/
public void newMethod(String name, String sig, ArrayList<Instruction> instructions, int access, ClassWriter classWriter,
ClassWriter.Element rawLines) {
if (instructions == null) {
throw new IllegalArgumentException("instructions is null");
}
if (classWriter == null) {
throw new IllegalArgumentException("classWriter is null");
}
Instruction[] ins = instructions.toArray(new Instruction[instructions.size()]);
ExceptionHandler[][] handlers = new ExceptionHandler[ins.length][];
Arrays.fill(handlers, noHandlers);
int[] i2b = new int[ins.length];
for (int i = 0; i < i2b.length; i++) {
i2b[i] = i;
}
MethodData md = null;
try {
md = new MethodData(access, Util.makeType(cr.getName()), name, sig, ins, handlers, i2b);
} catch (InvalidClassFileException ex) {
ex.printStackTrace();
}
CTCompiler compiler = CTCompiler.make(classWriter, md);
compiler.compile();
CTCompiler.Output output = compiler.getOutput();
CodeWriter code = new CodeWriter(classWriter);
code.setMaxStack(output.getMaxStack());
code.setMaxLocals(output.getMaxLocals());
code.setCode(output.getCode());
code.setRawHandlers(output.getRawHandlers());
LineNumberTableWriter lines = null;
// I guess it is the line numbers in the java files.
if (rawLines == null) {
// add fake line numbers: just map each bytecode instruction to its own
// 'line'
int[] newLineMap = new int[instructions.size()];
for (int i = 0; i < newLineMap.length; i++) {
newLineMap[i] = i;
}
int[] rawTable = LineNumberTableWriter.makeRawTable(newLineMap);
lines = new LineNumberTableWriter(classWriter);
lines.setRawTable(rawTable);
}
code.setAttributes(new ClassWriter.Element[] { rawLines == null ? lines : rawLines });
Element[] elements = { code };
classWriter.addMethod(access, name, sig, elements);
}
public void newMethod(MethodData md, ClassWriter classWriter, ClassWriter.Element rawLines) {
if (classWriter == null) {
throw new IllegalArgumentException("classWriter is null");
}
if (md == null) {
throw new IllegalArgumentException("md is null");
}
CTCompiler compiler = CTCompiler.make(classWriter, md);
compiler.compile();
CTCompiler.Output output = compiler.getOutput();
CodeWriter code = new CodeWriter(classWriter);
code.setMaxStack(output.getMaxStack());
code.setMaxLocals(output.getMaxLocals());
code.setCode(output.getCode());
code.setRawHandlers(output.getRawHandlers());
LineNumberTableWriter lines = null;
// I guess it is the line numbers in the java files.
if (rawLines == null) {
// add fake line numbers: just map each bytecode instruction to its own
// 'line'
// NOTE:Should not use md.getInstructions().length, because the
// the length of the created code can be smaller than the md's instruction
// length
// WRONG: int[] newLineMap = new int[md.getInstructions().length];
int[] newLineMap = new int[code.getCodeLength()];
for (int i = 0; i < newLineMap.length; i++) {
newLineMap[i] = i;
}
int[] rawTable = LineNumberTableWriter.makeRawTable(newLineMap);
lines = new LineNumberTableWriter(classWriter);
lines.setRawTable(rawTable);
}
code.setAttributes(new ClassWriter.Element[] { rawLines == null ? lines : rawLines });
Element[] elements = { code };
// System.out.println("Name:"+md.getName()+" Sig:"+md.getSignature());
classWriter.addMethod(md.getAccess(), md.getName(), md.getSignature(), elements);
}
/**
* Do something to every method in the class. This will visit all methods, including those already marked for deletion.
*