Package com.ibm.wala.shrikeBT
Class MethodEditor
- java.lang.Object
-
- com.ibm.wala.shrikeBT.MethodEditor
-
public final class MethodEditor extends Object
The MethodEditor is the core of the ShrikeBT code rewriting mechanism. To rewrite code, construct a MethodEditor initialized with the intial code for the method. Then perform a series of passes. In each pass you call beginPass(), insert a number of patches using the insert...() or replace...() methods, then optionally call applyPatches() to update the code with your changes, then call endPass(). The end of each pass updates the code in the MethodData that you passed in, so the new code can be extracted from that MethodData object. Note that if applyPatches() is not called, or it is called but no patches had been inserted, then the code will not be updated and that pass is essentially aborted. A patch is simply a subclass of MethodEditor.Patch, representing a code sequence to insert into the method. Each patch class implements one method, emitTo(), which writes the patch code into the code stream using the provided MethodEditor.Output instance. Anonymous inner classes are very useful for writing patches. Patches can be inserted at the following points:- Before the start of the method
- Before or after a particular instruction
- Replacing a particular instruction
- Handling an exception on a particular instruction
- Handling an exception anywhere in the method
- After the end of the method, where code will not normally be executed, but can be branched to by another patch
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
MethodEditor.Output
Output is the interface that patches use to emit their code into a method body.static class
MethodEditor.Patch
This class is subclassed for each kind of patch that you want to apply.static class
MethodEditor.Visitor
A specialized Instruction.Visitor providing convenience methods for inserting patches.
-
Constructor Summary
Constructors Constructor Description MethodEditor(Instruction[] instructions, ExceptionHandler[][] handlers, int[] instructionsToBytecodes)
Build an editor for specific method data.MethodEditor(MethodData info)
Build an editor for the given method.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description void
addInstructionExceptionHandler(int i, String catchClass, MethodEditor.Patch p)
An "instruction exception handler" handles exceptions generated by a specific instruction (including patch code that may be inserted before, after, or instead of the instruction in this pass).void
addMethodExceptionHandler(String catchClass, MethodEditor.Patch p)
A "method exception handler" handles exceptions generated anywhere in the method.int
allocateLabel()
Allocate a fresh label.boolean
applyPatches()
This method finishes a pass.void
beginPass()
This must be called before inserting any patches.void
endPass()
This must be called after inserting any patches.MethodData
getData()
ExceptionHandler[][]
getHandlers()
IInstruction[]
getInstructions()
int[]
getInstructionsToBytecodes()
void
insertAfter(int i, MethodEditor.Patch p)
Insert code to be executed after the instruction.void
insertAfterBody(MethodEditor.Patch p)
This method inserts code that will be placed after the method body.void
insertAtStart(MethodEditor.Patch p)
Insert code to be executed whenever the method is entered.void
insertBefore(int i, MethodEditor.Patch p)
Insert code to be executed before the instruction.void
replaceWith(int i, MethodEditor.Patch p)
Insert code to replace the instruction.void
visitInstructions(MethodEditor.Visitor v)
Apply Visitor v to each instruction in the code, for the purpose of patching the code.
-
-
-
Constructor Detail
-
MethodEditor
public MethodEditor(MethodData info)
Build an editor for the given method. This editor will write back its changes to the method info.- Throws:
IllegalArgumentException
- if info is null
-
MethodEditor
public MethodEditor(Instruction[] instructions, ExceptionHandler[][] handlers, int[] instructionsToBytecodes)
Build an editor for specific method data. After patching the code you can retrieve the new code, handlers and instructions-to-bytecode-offsets map.
-
-
Method Detail
-
getHandlers
public ExceptionHandler[][] getHandlers()
- Returns:
- the current handler array
-
getInstructions
public IInstruction[] getInstructions()
- Returns:
- the current instruction array
-
getInstructionsToBytecodes
public int[] getInstructionsToBytecodes()
- Returns:
- the current instructions-to-bytecode-offsets map
-
beginPass
public void beginPass()
This must be called before inserting any patches.
-
endPass
public void endPass()
This must be called after inserting any patches.
-
allocateLabel
public int allocateLabel() throws IllegalArgumentException
Allocate a fresh label. This must be called during a pass and not during code emission.- Throws:
IllegalArgumentException
-
insertAtStart
public void insertAtStart(MethodEditor.Patch p)
Insert code to be executed whenever the method is entered. This code is not protected by any exception handlers (other than handlers declared in the patch). When multiple 'start' patches are given, the last one added is first in execution order.- Throws:
IllegalArgumentException
- if p is null
-
insertBefore
public void insertBefore(int i, MethodEditor.Patch p)
Insert code to be executed before the instruction. Branches to the instruction will branch to this code. Exception handlers that cover the instruction will be extended to cover the patch. When multiple 'before' patches are given, the last one added is first in execution order.- Throws:
IllegalArgumentException
- if p is null
-
insertAfter
public void insertAfter(int i, MethodEditor.Patch p)
Insert code to be executed after the instruction. This code will only execute if the instruction "falls through". For example, code inserted after a "goto" will never be executed. Likewise if the instruction throws an execution the 'after' code will not be executed. Exception handlers that cover the instruction will be extended to cover the patch. When multiple 'after' patches are given, the last one added is LAST in execution order.
-
replaceWith
public void replaceWith(int i, MethodEditor.Patch p) throws NullPointerException
Insert code to replace the instruction. Exception handlers that cover the instruction will cover the patch. Multiple replacements are not allowed.- Throws:
NullPointerException
- if p is nullIllegalArgumentException
- if p is null
-
addInstructionExceptionHandler
public void addInstructionExceptionHandler(int i, String catchClass, MethodEditor.Patch p)
An "instruction exception handler" handles exceptions generated by a specific instruction (including patch code that may be inserted before, after, or instead of the instruction in this pass). If the patch code falls through, control resumes with the next instruction. This exception handler handles exceptions before any exception handler already attached to the instruction. Furthermore, the patch itself is covered by the exception handlers already attached to the instruction. If multiple instruction exception handlers are given, then the last one added handles the exception first; if an exception is rethrown, then the next-to-last one added handles that exception, etc.
-
addMethodExceptionHandler
public void addMethodExceptionHandler(String catchClass, MethodEditor.Patch p)
A "method exception handler" handles exceptions generated anywhere in the method. The patch code must not fall through; it must return or throw an exception. If multiple method exception handlers are given, then the last one added handles the exception first; if an exception is rethrown, then the next-to-last one added handles that exception, etc.
-
insertAfterBody
public void insertAfterBody(MethodEditor.Patch p)
This method inserts code that will be placed after the method body. This code will not be executed normally, but it can emit label definitions that other patches can branch to. No exception handlers cover this code (other than exception handlers emitted by patch p itself).- Throws:
IllegalArgumentException
- if p is null
-
getData
public MethodData getData()
- Returns:
- the MethodData used to create this editor, or null if no MethodData is linked to this editor
-
applyPatches
public boolean applyPatches() throws IllegalArgumentException
This method finishes a pass. All code is updated; instructions are reordered and old labels may not be valid. If no patches were issued, we don't need to do anything at all; this case is detected quickly and no updates are made.- Returns:
- true iff non-trivial patches were applied
- Throws:
IllegalArgumentException
-
visitInstructions
public void visitInstructions(MethodEditor.Visitor v)
Apply Visitor v to each instruction in the code, for the purpose of patching the code.
-
-