public class CFG extends Object
RuleTriggerMethodAdapter
for an example of how the methods provided by this class are invoked during visiting of the method byte code.
Methods provided for driving CFG construction include:
add(int)
, add(int, int)
,
add(int, int, int)
add(int, int[])
add(int, String)
,
add(int, String, String, String)
, add(int, String, int)
,
split(org.objectweb.asm.Label)
, split(org.objectweb.asm.Label, org.objectweb.asm.Label)
,
split(org.objectweb.asm.Label, org.objectweb.asm.Label, org.objectweb.asm.Label)
,
split(org.objectweb.asm.Label, org.objectweb.asm.Label, org.objectweb.asm.Label[])
,
visitLabel(org.objectweb.asm.Label)
,
visitTryCatchBlock(org.objectweb.asm.Label, org.objectweb.asm.Label, org.objectweb.asm.Label, String)
,
visitTriggerStart(org.objectweb.asm.Label)
, visitTriggerEnd(org.objectweb.asm.Label)
,
visitMaxs()
, visitEnd()
,
Normal control flow linkage is explicitly represented in the blocks as a list containing the labels of the target blocks. Labels are used rather than handles on the block themselves so that forward links to blocks which have not yet been generated can be modelled. Labels are resolved to the relevant block and instruction index as they are visited during walking of the bytecode.
The outgoing control flow link count can be obtained by calling methodBBlock.nOuts()
. The label of the block to which control is transferred can be identified by calling
method BBlock.nthOut(int)
. Note that valid link indices run from 1 to nOuts() (see below). Once
a label has been visited it can be resolved to a CodeLocation
by calling method
getLocation(org.objectweb.asm.Label)
. The returned value identifies both a block and an instruction
offset in the block.
Several caveats apply to this simple picture. Firstly, blocks ending in return or throw have no control flow -- they
pass control back to the caller rather than to another basic block. So, the count returned by BBlock.nOuts()
will be 0 for such blocks.
Secondly, all blocks except the last have a distinguished link which identifies the block successor link
relationship. The successor block can be obtained by supplying value 0 as argument to method
BBlock.nthOut(int)
. This link is additional to any control flow links and it is not
included in the count returned by BBlock.nOuts()
. Note that where there is a control flow link to the
next block in line (e.g. where the block ends in an ifXX instruction) the label employed for the distinguished 0
link will also appear in the set of control flow links (as link 1 in the case of an ifXX instruction).
The final caveat is that this graph model does not identify control flow which occurs as a consequence of
generated exceptions.
TryCatchDetails
which identify the location of the try/catch start, its end and the associated handler
start location. Once again labels are used so as to allow modelling of forward references to code locations
which have not yet been generated.
Note that handler start labels always refer to a code location which is at the start of a basic block. Start
and end labels for a given try/catch block may refer to code locations offset into their containing basic block
and possibly in distinct blocks.
Methods tryCatchStart(org.objectweb.asm.Label)
, tryCatchEnd(org.objectweb.asm.Label)
and tryCatchHandlerStart(org.objectweb.asm.Label)
can be called to determine whether a given label
identifies, respectively, the start of a try catch block, the end of a try catch block or the start of a handler
block. Methods tryCatchStartDetails(org.objectweb.asm.Label)
tryCatchEndDetails(org.objectweb.asm.Label)
,
and tryCatchHandlerStartDetails(org.objectweb.asm.Label)
can be used to retrieve the associated
TryCatchDetails
information.
getBlock(org.objectweb.asm.Label)
to resolve the primary label for a block (i.e. the
one supplied as argument to a split call) to the associated block. It also provides method
getBlockInstructionIdx(org.objectweb.asm.Label)
to resolve a label to a CodeLocation
i.e.
block and instruction index within a block. Both methods return null if the label has not yet been visited.
Method getContains(BBlock)
is also provided to obtain a list of all labels contained within a
specific block. There may be more than one label which resolves to a location within a specific block. For
example, the handler start label associated with a try/catch handler is contained in the handler block at
offset 0 but is never the primary label for the block. Iteration over the contained set is used internally
in the cfg to resolve equivalent labels.
getPairedEnter(CodeLocation)
,
and getPairedExit(CodeLocation, BBlock)
9note that a given enter will never have more than one
exit in any given block).
The cfg associates monitor enters and exits with their enclosing block, allowing it to identify the start and/or
end of synchronized regions within a specific block. This information can be propagated along control flow links
to identify outstanding monitor enters at any point in a given control flow path. Whenever a block is created
it is associated with a set of open enter instructions i.e. enter instructions occurring along all control flow
paths to the block for which no corresponding exit has been executed.
carryForward()
. This
method identifies the current block's open enters list (how will emerge below), updates it with any enters and
exits performed in the block and then, for each each outgoing control link, associates the new list with the
linked block by inserting the list into a hash table keyed by the block label. Clearly, if the current block was
itself arrived at via normal control flow then its open enters list will already be available in the hash table.
Handler blocks require a different lookup.
carryForward()
. This requires identifying all try/catch regions which enclose the block
and tagging the corresponding TryCatchDetails
object with the location of any monitor enter instructions
which are open at some point in the try catch region. If this is done for every block encountered during
the bytecode walk then at the point where the handler block is split all enter instructions which are still open
somewhere within the try/catch region will be listed in the TryCatchDetails
. So, at the split point
the old block can be tested to see if it is labelled as a try/catch handler target and, if so, its open enters
list can be looked up by locating the TryCatchDetails
associated with the handler start label.
Modifier and Type | Field | Description |
---|---|---|
static org.objectweb.asm.Type |
EARLY_RETURN_EXCEPTION_TYPE |
Type identifying return exceptions thrown by runtime
|
static String |
EARLY_RETURN_EXCEPTION_TYPE_NAME |
name of type identifying return exceptions thrown by runtime
|
static org.objectweb.asm.Type |
EXECUTE_EXCEPTION_TYPE |
Type identifying execute exceptions thrown by runtime
|
static String |
EXECUTE_EXCEPTION_TYPE_NAME |
name of type identifying execute exceptions thrown by runtime
|
static org.objectweb.asm.Type |
THROW_EXCEPTION_TYPE |
Type identifying throw exceptions thrown by runtime
|
static String |
THROW_EXCEPTION_TYPE_NAME |
name of type identifying throw exceptions thrown by runtime
|
Constructor | Description |
---|---|
CFG(String methodName,
org.objectweb.asm.Label start) |
construct a CFG labelling the initial block with a given label
|
Modifier and Type | Method | Description |
---|---|---|
void |
add(int instruction) |
aopend an instruction to the current block
|
void |
add(int instruction,
int operand) |
append an instruction with one operand to the current block
|
void |
add(int instruction,
int[] operands) |
append an operand with more than two operands ot the current block
|
void |
add(int instruction,
int operand1,
int operand2) |
append an instruction with two operands to the current block
|
void |
add(int instruction,
String name) |
append an instruction with a String operand to the current block
|
void |
add(int instruction,
String name,
int dims) |
append a multiarray create instruction to the current block
|
void |
add(int instruction,
String name,
String desc) |
append an invokedynamic instruction with 2 String operands to the current block
|
void |
add(int instruction,
String owner,
String name,
String desc) |
append a field instruction with 3 String operands to the current block
|
void |
add(int instruction,
String owner,
String name,
String desc,
boolean itf) |
append a method instruction with 3 String operands
and a boolean operand to the current block
|
BBlock |
getBlock(org.objectweb.asm.Label label) |
return the block containing a label if known
|
int |
getBlockInstructionIdx(org.objectweb.asm.Label label) |
return the index of the label in its enclosing block's instruction sequence or -1 if the
label has not yet been visited.
|
FanOut |
getContains(BBlock block) |
return a link object listing all the labels contained in a given block
|
CodeLocation |
getLocation(org.objectweb.asm.Label label) |
return the location of the label if known or null if it has not yet been reached.
|
String |
getName(int nameIdx) |
|
List<CodeLocation> |
getOpenMonitorEnters(BBlock block) |
retrieve the list of monitor enter locations open at the start of a given block
|
List<CodeLocation> |
getOpenMonitorEnters(org.objectweb.asm.Label label) |
retrieve the list of monitor enter locations open at the start of a given block
|
Iterator<CodeLocation> |
getOpenMonitors(TriggerDetails triggerDetails) |
retrieve the list of monitor enter locations associated with a trigger block.
|
CodeLocation |
getPairedEnter(CodeLocation exit) |
locate the monitor enter instruction associated with a given monitor exit
|
int |
getSavedMonitorIdx(CodeLocation open) |
return the index of the local var at which this monitorenter saved its lock object
|
boolean |
hasLocation(org.objectweb.asm.Label label) |
test whether the location of a label is known yet
|
boolean |
inBytemanHandler() |
check if the current block is a byteman-generated handler i.e.
|
boolean |
inBytemanTrigger() |
check if the current block is a byteman-generated trigger section.
|
boolean |
inOpenMonitor() |
test whether there are any open monitorenters with no corresponding monitorexit on a path to
the current instruction
|
boolean |
inRethrowHandler() |
return true if the current block is a rethrow handler i.e.
|
CodeLocation |
nextLocation() |
return a location which will identify the next instruction added to the current block
|
CodeLocation |
setLocation(org.objectweb.asm.Label label) |
set the location of a label to the next instruction offset in the current block
|
void |
split(org.objectweb.asm.Label newStart) |
split the graph at a control-flow dead-end using the label provided to identify the new current
block.
|
void |
split(org.objectweb.asm.Label newStart,
org.objectweb.asm.Label out) |
split the graph at a control-flow goto point using the labels provided to identify the new current
block and the goto target.
|
void |
split(org.objectweb.asm.Label newStart,
org.objectweb.asm.Label out,
org.objectweb.asm.Label out2) |
split the graph at a control-flow if branch point using the labels provided to identify the new current
block the if branch target and the else branch target.
|
void |
split(org.objectweb.asm.Label newStart,
org.objectweb.asm.Label dflt,
org.objectweb.asm.Label[] labels) |
split the graph at a control-flow switch branch point using the labels provided to identify the new
current block, the switch case default branch target and the rest of the switch case branch targets.
|
String |
toString() |
generate a string representation of the CFG
|
Iterator<TriggerDetails> |
triggerDetails() |
return an iterator ovver all known trigger details
|
boolean |
triggerEnd(org.objectweb.asm.Label label) |
test if a label marks the end of a trigger block
|
TriggerDetails |
triggerEndDetails(org.objectweb.asm.Label label) |
return the list of details of try catch blocks which end at this label
|
boolean |
triggerStart(org.objectweb.asm.Label label) |
test if a label marks the start of a trigger block
|
TriggerDetails |
triggerStartDetails(org.objectweb.asm.Label label) |
return details of any trigger block which starts at this label
|
boolean |
tryCatchEnd(org.objectweb.asm.Label label) |
test if a label marks the end of a try catch block
|
List<TryCatchDetails> |
tryCatchEndDetails(org.objectweb.asm.Label label) |
return the list of details of try catch blocks which end at this label
|
boolean |
tryCatchHandlerStart(org.objectweb.asm.Label label) |
test if a label marks the start of the handler for a try catch block
|
List<TryCatchDetails> |
tryCatchHandlerStartDetails(org.objectweb.asm.Label label) |
return the list of details of try catch blocks whose handler starts at this label
|
boolean |
tryCatchStart(org.objectweb.asm.Label label) |
test if a label marks the start of a try catch block
|
List<TryCatchDetails> |
tryCatchStartDetails(org.objectweb.asm.Label label) |
return the list of details of try catch blocks which start at this label
|
void |
visitEnd() |
|
void |
visitLabel(org.objectweb.asm.Label label) |
notify the CFG that a label has been visited by the method visitor and hence its position will now
be resolved
|
void |
visitMaxs() |
this can be called when the code generator call visiMaxs but it does nothing just now
|
void |
visitTriggerEnd(org.objectweb.asm.Label label) |
notify the CFG that a label which represents the end of a trigger injection sequence has just been visited
by the method visitor.
|
void |
visitTriggerStart(org.objectweb.asm.Label label) |
notify the CFG that a label which represents the start of a trigger injection sequence has just been visited
by the method visitor.
|
void |
visitTryCatchBlock(org.objectweb.asm.Label start,
org.objectweb.asm.Label end,
org.objectweb.asm.Label handler,
String type) |
notify the CFG of the location of a try catch block.
|
public static final org.objectweb.asm.Type EXECUTE_EXCEPTION_TYPE
public static final org.objectweb.asm.Type EARLY_RETURN_EXCEPTION_TYPE
public static final org.objectweb.asm.Type THROW_EXCEPTION_TYPE
public static final String EXECUTE_EXCEPTION_TYPE_NAME
public static final String EARLY_RETURN_EXCEPTION_TYPE_NAME
public static final String THROW_EXCEPTION_TYPE_NAME
public CFG(String methodName, org.objectweb.asm.Label start)
methodName
- the name of the method fro which this is a CFGstart
- a label for the entry block of the CFGpublic void add(int instruction)
instruction
- the instruction to be appendedpublic void add(int instruction, int operand)
instruction
- the instruction to be appendedoperand
- the instruction's operandpublic void add(int instruction, int operand1, int operand2)
instruction
- the instruction to be appendedoperand1
- the instruction's first operandoperand2
- the instruction's second operandpublic void add(int instruction, int[] operands)
instruction
- the instruction to be appendedoperands
- the instruction's operandspublic void add(int instruction, String name)
instruction
- the instruction to be appendedname
- the String operandpublic void add(int instruction, String name, int dims)
instruction
- the instruction to be appendedname
- the name of the array base typedims
- the number of array dimensionspublic void add(int instruction, String name, String desc)
instruction
- the invokedynamic instruction to be appendedname
- the first String operanddesc
- the second String operandpublic void add(int instruction, String owner, String name, String desc)
instruction
- the instruction to be appendedowner
- the first String operandname
- the second String operanddesc
- the third String operandpublic void add(int instruction, String owner, String name, String desc, boolean itf)
instruction
- the instruction to be appendedowner
- the first String operandname
- the second String operanddesc
- the third String operanditf
- the boolean operandpublic CodeLocation setLocation(org.objectweb.asm.Label label)
label
- the label whose location is to be setpublic CodeLocation getLocation(org.objectweb.asm.Label label)
label
- the label whose location is desiredpublic boolean hasLocation(org.objectweb.asm.Label label)
label
- the label whose location is desiredpublic CodeLocation nextLocation()
public BBlock getBlock(org.objectweb.asm.Label label)
label
- the label whose containing block is desiredpublic FanOut getContains(BBlock block)
block
- the block whose labels are being soughtpublic List<CodeLocation> getOpenMonitorEnters(org.objectweb.asm.Label label)
label
- the label of the blockpublic List<CodeLocation> getOpenMonitorEnters(BBlock block)
block
- the blockpublic Iterator<CodeLocation> getOpenMonitors(TriggerDetails triggerDetails)
triggerDetails
- the trigger being checkedpublic CodeLocation getPairedEnter(CodeLocation exit)
exit
- the location of the monitor exitpublic int getSavedMonitorIdx(CodeLocation open)
open
- the location of th emonitor enterpublic boolean inOpenMonitor()
public void split(org.objectweb.asm.Label newStart)
newStart
- the label to be used to identify the new current blockpublic void split(org.objectweb.asm.Label newStart, org.objectweb.asm.Label out)
newStart
- the label to be used to identify the new current blockout
- the target of the GOTOpublic void split(org.objectweb.asm.Label newStart, org.objectweb.asm.Label out, org.objectweb.asm.Label out2)
newStart
- the label to be used to identify the new current blockout
- the target of the if branchout2
- the target of the else branch which probably ought to be the same label as passed for the
current block (IF instructions assume drop-through)public void split(org.objectweb.asm.Label newStart, org.objectweb.asm.Label dflt, org.objectweb.asm.Label[] labels)
newStart
- the label to be used to identify the new current blockdflt
- the switch case default branch targetlabels
- the other switch case branch targetspublic boolean tryCatchStart(org.objectweb.asm.Label label)
label
- the label to be testedpublic boolean tryCatchEnd(org.objectweb.asm.Label label)
label
- the label to be testedpublic boolean tryCatchHandlerStart(org.objectweb.asm.Label label)
label
- the label to be testedpublic List<TryCatchDetails> tryCatchStartDetails(org.objectweb.asm.Label label)
label
- the start labelpublic List<TryCatchDetails> tryCatchEndDetails(org.objectweb.asm.Label label)
label
- the end labelpublic List<TryCatchDetails> tryCatchHandlerStartDetails(org.objectweb.asm.Label label)
label
- the handler start labelpublic boolean triggerStart(org.objectweb.asm.Label label)
label
- the label to be testedpublic boolean triggerEnd(org.objectweb.asm.Label label)
label
- the label to be testedpublic TriggerDetails triggerStartDetails(org.objectweb.asm.Label label)
label
- the labelpublic TriggerDetails triggerEndDetails(org.objectweb.asm.Label label)
label
- the labelpublic Iterator<TriggerDetails> triggerDetails()
public void visitLabel(org.objectweb.asm.Label label)
label
- the label being visitedpublic void visitTriggerStart(org.objectweb.asm.Label label)
label
- the label being visitedpublic void visitTriggerEnd(org.objectweb.asm.Label label)
label
- the label being visitedpublic void visitTryCatchBlock(org.objectweb.asm.Label start, org.objectweb.asm.Label end, org.objectweb.asm.Label handler, String type)
start
- the block start labelend
- the block end labelhandler
- the block handler labeltype
- handled exception type namepublic boolean inBytemanHandler()
public boolean inRethrowHandler()
public boolean inBytemanTrigger()
public void visitMaxs()
public void visitEnd()
public String toString()
public int getBlockInstructionIdx(org.objectweb.asm.Label label)
label
- the label whose index is soughtpublic String getName(int nameIdx)
Copyright © 2018. All rights reserved.