use of org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException in project intellij-community by JetBrains.
the class BytecodeAnalysisTest method checkLeakingParameters.
private static void checkLeakingParameters(Class<?> jClass) throws IOException {
final HashMap<Method, boolean[]> map = new HashMap<>();
// collecting leakedParameters
final ClassReader classReader = new ClassReader(jClass.getResourceAsStream("/" + jClass.getName().replace('.', '/') + ".class"));
classReader.accept(new ClassVisitor(Opcodes.API_VERSION) {
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
final MethodNode node = new MethodNode(Opcodes.API_VERSION, access, name, desc, signature, exceptions);
final Method method = new Method(classReader.getClassName(), name, desc);
return new MethodVisitor(Opcodes.API_VERSION, node) {
@Override
public void visitEnd() {
super.visitEnd();
try {
map.put(method, LeakingParameters.build(classReader.getClassName(), node, false).parameters);
} catch (AnalyzerException ignore) {
}
}
};
}
}, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
for (java.lang.reflect.Method jMethod : jClass.getDeclaredMethods()) {
Method method = new Method(Type.getType(jClass).getInternalName(), jMethod.getName(), Type.getMethodDescriptor(jMethod));
Annotation[][] annotations = jMethod.getParameterAnnotations();
for (int i = 0; i < annotations.length; i++) {
boolean isLeaking = false;
Annotation[] parameterAnnotations = annotations[i];
for (Annotation parameterAnnotation : parameterAnnotations) {
if (parameterAnnotation.annotationType() == ExpectLeaking.class) {
isLeaking = true;
}
}
assertEquals(method.toString() + " #" + i, isLeaking, map.get(method)[i]);
}
}
}
use of org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException in project intellij-community by JetBrains.
the class LiteAnalyzer method analyze.
public Frame<V>[] analyze(final String owner, final MethodNode m) throws AnalyzerException {
if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0 || m.instructions.size() == 0) {
frames = (Frame<V>[]) new Frame<?>[0];
return frames;
}
int n = m.instructions.size();
InsnList insns = m.instructions;
List<TryCatchBlockNode>[] handlers = (List<TryCatchBlockNode>[]) new List<?>[n];
frames = (Frame<V>[]) new Frame<?>[n];
queued = new boolean[n];
queue = new int[n];
top = 0;
// computes exception handlers for each instruction
for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
TryCatchBlockNode tcb = m.tryCatchBlocks.get(i);
int begin = insns.indexOf(tcb.start);
int end = insns.indexOf(tcb.end);
for (int j = begin; j < end; ++j) {
List<TryCatchBlockNode> insnHandlers = handlers[j];
if (insnHandlers == null) {
insnHandlers = new ArrayList<>();
handlers[j] = insnHandlers;
}
insnHandlers.add(tcb);
}
}
// initializes the data structures for the control flow analysis
Frame<V> current = new Frame<>(m.maxLocals, m.maxStack);
Frame<V> handler = new Frame<>(m.maxLocals, m.maxStack);
current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)));
Type[] args = Type.getArgumentTypes(m.desc);
int local = 0;
if ((m.access & ACC_STATIC) == 0) {
Type ctype = Type.getObjectType(owner);
current.setLocal(local++, interpreter.newValue(ctype));
}
for (int i = 0; i < args.length; ++i) {
current.setLocal(local++, interpreter.newValue(args[i]));
if (args[i].getSize() == 2) {
current.setLocal(local++, interpreter.newValue(null));
}
}
while (local < m.maxLocals) {
current.setLocal(local++, interpreter.newValue(null));
}
merge(0, current);
// control flow analysis
while (top > 0) {
int insn = queue[--top];
Frame<V> f = frames[insn];
queued[insn] = false;
AbstractInsnNode insnNode = null;
try {
insnNode = m.instructions.get(insn);
int insnOpcode = insnNode.getOpcode();
int insnType = insnNode.getType();
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
merge(insn + 1, f);
} else {
current.init(f).execute(insnNode, interpreter);
if (insnNode instanceof JumpInsnNode) {
JumpInsnNode j = (JumpInsnNode) insnNode;
if (insnOpcode != GOTO && insnOpcode != JSR) {
merge(insn + 1, current);
}
int jump = insns.indexOf(j.label);
merge(jump, current);
} else if (insnNode instanceof LookupSwitchInsnNode) {
LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
int jump = insns.indexOf(lsi.dflt);
merge(jump, current);
for (int j = 0; j < lsi.labels.size(); ++j) {
LabelNode label = lsi.labels.get(j);
jump = insns.indexOf(label);
merge(jump, current);
}
} else if (insnNode instanceof TableSwitchInsnNode) {
TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
int jump = insns.indexOf(tsi.dflt);
merge(jump, current);
for (int j = 0; j < tsi.labels.size(); ++j) {
LabelNode label = tsi.labels.get(j);
jump = insns.indexOf(label);
merge(jump, current);
}
} else if (insnOpcode != ATHROW && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
merge(insn + 1, current);
}
}
List<TryCatchBlockNode> insnHandlers = handlers[insn];
if (insnHandlers != null) {
for (int i = 0; i < insnHandlers.size(); ++i) {
TryCatchBlockNode tcb = insnHandlers.get(i);
int jump = insns.indexOf(tcb.handler);
handler.init(f);
handler.clearStack();
handler.push(interpreter.newValue(ASMUtils.THROWABLE_TYPE));
merge(jump, handler);
}
}
} catch (AnalyzerException e) {
throw new AnalyzerException(e.node, "Error at instruction " + insn + ": " + e.getMessage(), e);
} catch (Exception e) {
throw new AnalyzerException(insnNode, "Error at instruction " + insn + ": " + e.getMessage(), e);
}
}
return frames;
}
use of org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException in project intellij-community by JetBrains.
the class ClassDataIndexer method processClass.
public static Map<Key, List<Equation>> processClass(final ClassReader classReader, final String presentableUrl) {
// It is OK to share pending states, actions and results for analyses.
// Analyses are designed in such a way that they first write to states/actions/results and then read only those portion
// of states/actions/results which were written by the current pass of the analysis.
// Since states/actions/results are quite expensive to create (32K array) for each analysis, we create them once per class analysis.
final State[] sharedPendingStates = new State[Analysis.STEPS_LIMIT];
final PendingAction[] sharedPendingActions = new PendingAction[Analysis.STEPS_LIMIT];
final PResults.PResult[] sharedResults = new PResults.PResult[Analysis.STEPS_LIMIT];
final Map<Key, List<Equation>> equations = new HashMap<>();
classReader.accept(new KeyedMethodVisitor() {
protected MethodVisitor visitMethod(final MethodNode node, final Key key) {
return new MethodVisitor(Opcodes.API_VERSION, node) {
private boolean jsr;
@Override
public void visitJumpInsn(int opcode, Label label) {
if (opcode == Opcodes.JSR) {
jsr = true;
}
super.visitJumpInsn(opcode, label);
}
@Override
public void visitEnd() {
super.visitEnd();
equations.put(key, processMethod(node, jsr, key.method, key.stable));
}
};
}
/**
* Facade for analysis, it invokes specialized analyses for branching/non-branching methods.
*
* @param methodNode asm node for method
* @param jsr whether a method has jsr instruction
*/
private List<Equation> processMethod(final MethodNode methodNode, boolean jsr, Method method, boolean stable) {
ProgressManager.checkCanceled();
final Type[] argumentTypes = Type.getArgumentTypes(methodNode.desc);
final Type resultType = Type.getReturnType(methodNode.desc);
final boolean isReferenceResult = ASMUtils.isReferenceType(resultType);
final boolean isBooleanResult = ASMUtils.isBooleanType(resultType);
final boolean isInterestingResult = isReferenceResult || isBooleanResult;
// 4*n: for each reference parameter: @NotNull IN, @Nullable, null -> ... contract, !null -> contract
// 3: @NotNull OUT, @Nullable OUT, purity analysis
List<Equation> equations = new ArrayList<>(argumentTypes.length * 4 + 3);
equations.add(PurityAnalysis.analyze(method, methodNode, stable));
if (argumentTypes.length == 0 && !isInterestingResult) {
// no need to continue analysis
return equations;
}
try {
final ControlFlowGraph graph = ControlFlowGraph.build(className, methodNode, jsr);
if (graph.transitions.length > 0) {
final DFSTree dfs = DFSTree.build(graph.transitions, graph.edgeCount);
boolean branching = !dfs.back.isEmpty();
if (!branching) {
for (int[] transition : graph.transitions) {
if (transition != null && transition.length > 1) {
branching = true;
break;
}
}
}
if (branching) {
RichControlFlow richControlFlow = new RichControlFlow(graph, dfs);
if (richControlFlow.reducible()) {
NegationAnalysis negated = tryNegation(method, argumentTypes, graph, isBooleanResult, dfs, jsr);
processBranchingMethod(method, methodNode, richControlFlow, argumentTypes, isReferenceResult, isBooleanResult, stable, jsr, equations, negated);
return equations;
}
LOG.debug(method + ": CFG is not reducible");
} else // simple
{
processNonBranchingMethod(method, argumentTypes, graph, isReferenceResult, isBooleanResult, stable, equations);
return equations;
}
}
return topEquations(method, argumentTypes, isReferenceResult, isInterestingResult, stable);
} catch (ProcessCanceledException e) {
throw e;
} catch (Throwable e) {
// incorrect bytecode may result in Runtime exceptions during analysis
// so here we suppose that exception is due to incorrect bytecode
LOG.debug("Unexpected Error during processing of " + method + " in " + presentableUrl, e);
return topEquations(method, argumentTypes, isReferenceResult, isInterestingResult, stable);
}
}
private NegationAnalysis tryNegation(final Method method, final Type[] argumentTypes, final ControlFlowGraph graph, final boolean isBooleanResult, final DFSTree dfs, final boolean jsr) throws AnalyzerException {
class Util {
boolean isMethodCall(int opCode) {
return opCode == Opcodes.INVOKESTATIC || opCode == Opcodes.INVOKESPECIAL || opCode == Opcodes.INVOKEVIRTUAL || opCode == Opcodes.INVOKEINTERFACE;
}
boolean singleIfBranch() {
int branch = 0;
for (int i = 0; i < graph.transitions.length; i++) {
int[] transition = graph.transitions[i];
if (transition.length == 2) {
branch++;
int opCode = graph.methodNode.instructions.get(i).getOpcode();
boolean isIfInsn = opCode == Opcodes.IFEQ || opCode == Opcodes.IFNE;
if (!isIfInsn) {
return false;
}
}
if (branch > 1)
return false;
}
return branch == 1;
}
boolean singleMethodCall() {
int callCount = 0;
for (int i = 0; i < graph.transitions.length; i++) {
if (isMethodCall(graph.methodNode.instructions.get(i).getOpcode())) {
callCount++;
if (callCount > 1) {
return false;
}
}
}
return callCount == 1;
}
public boolean booleanConstResult() {
try {
final boolean[] origins = OriginsAnalysis.resultOrigins(leakingParametersAndFrames(method, graph.methodNode, argumentTypes, jsr).frames, graph.methodNode.instructions, graph);
for (int i = 0; i < origins.length; i++) {
if (origins[i]) {
int opCode = graph.methodNode.instructions.get(i).getOpcode();
boolean isBooleanConst = opCode == Opcodes.ICONST_0 || opCode == Opcodes.ICONST_1;
if (!isBooleanConst) {
return false;
}
}
}
return true;
} catch (AnalyzerException ignore) {
}
return false;
}
}
if (graph.methodNode.instructions.size() < 20 && isBooleanResult && dfs.back.isEmpty() && !jsr) {
Util util = new Util();
if (util.singleIfBranch() && util.singleMethodCall() && util.booleanConstResult()) {
NegationAnalysis analyzer = new NegationAnalysis(method, graph);
try {
analyzer.analyze();
return analyzer;
} catch (NegationAnalysisFailure ignore) {
return null;
}
}
}
return null;
}
private void processBranchingMethod(final Method method, final MethodNode methodNode, final RichControlFlow richControlFlow, Type[] argumentTypes, boolean isReferenceResult, boolean isBooleanResult, final boolean stable, boolean jsr, List<Equation> result, NegationAnalysis negatedAnalysis) throws AnalyzerException {
boolean isInterestingResult = isBooleanResult || isReferenceResult;
boolean maybeLeakingParameter = isInterestingResult;
for (Type argType : argumentTypes) {
if (ASMUtils.isReferenceType(argType)) {
maybeLeakingParameter = true;
break;
}
}
final LeakingParameters leakingParametersAndFrames = maybeLeakingParameter ? leakingParametersAndFrames(method, methodNode, argumentTypes, jsr) : null;
boolean[] leakingParameters = leakingParametersAndFrames != null ? leakingParametersAndFrames.parameters : null;
boolean[] leakingNullableParameters = leakingParametersAndFrames != null ? leakingParametersAndFrames.nullableParameters : null;
final boolean[] origins = isInterestingResult ? OriginsAnalysis.resultOrigins(leakingParametersAndFrames.frames, methodNode.instructions, richControlFlow.controlFlow) : null;
Equation outEquation = isInterestingResult ? new InOutAnalysis(richControlFlow, Out, origins, stable, sharedPendingStates).analyze() : null;
if (isReferenceResult) {
result.add(outEquation);
result.add(new Equation(new Key(method, NullableOut, stable), NullableMethodAnalysis.analyze(methodNode, origins, jsr)));
}
boolean withCycle = !richControlFlow.dfsTree.back.isEmpty();
if (argumentTypes.length > 50 && withCycle) {
// IDEA-137443 - do not analyze very complex methods
return;
}
// arguments and contract clauses
for (int i = 0; i < argumentTypes.length; i++) {
boolean notNullParam = false;
if (ASMUtils.isReferenceType(argumentTypes[i])) {
boolean possibleNPE = false;
if (leakingParameters[i]) {
NonNullInAnalysis notNullInAnalysis = new NonNullInAnalysis(richControlFlow, new In(i, In.NOT_NULL_MASK), stable, sharedPendingActions, sharedResults);
Equation notNullParamEquation = notNullInAnalysis.analyze();
possibleNPE = notNullInAnalysis.possibleNPE;
notNullParam = notNullParamEquation.rhs.equals(FINAL_NOT_NULL);
result.add(notNullParamEquation);
} else {
// parameter is not leaking, so it is definitely NOT @NotNull
result.add(new Equation(new Key(method, new In(i, In.NOT_NULL_MASK), stable), FINAL_TOP));
}
if (leakingNullableParameters[i]) {
if (notNullParam || possibleNPE) {
result.add(new Equation(new Key(method, new In(i, In.NULLABLE_MASK), stable), FINAL_TOP));
} else {
result.add(new NullableInAnalysis(richControlFlow, new In(i, In.NULLABLE_MASK), stable, sharedPendingStates).analyze());
}
} else {
result.add(new Equation(new Key(method, new In(i, In.NULLABLE_MASK), stable), FINAL_NULL));
}
if (isInterestingResult) {
if (leakingParameters[i]) {
if (notNullParam) {
// @NotNull, so "null->fail"
result.add(new Equation(new Key(method, new InOut(i, Value.Null), stable), FINAL_BOT));
} else {
// may be null on some branch, running "null->..." analysis
if (isBooleanResult && negatedAnalysis != null) {
result.add(negatedAnalysis.contractEquation(i, Value.Null, stable));
} else {
result.add(new InOutAnalysis(richControlFlow, new InOut(i, Value.Null), origins, stable, sharedPendingStates).analyze());
}
}
if (isBooleanResult && negatedAnalysis != null) {
result.add(negatedAnalysis.contractEquation(i, Value.NotNull, stable));
} else {
result.add(new InOutAnalysis(richControlFlow, new InOut(i, Value.NotNull), origins, stable, sharedPendingStates).analyze());
}
} else {
// parameter is not leaking, so a contract is the same as for the whole method
result.add(new Equation(new Key(method, new InOut(i, Value.Null), stable), outEquation.rhs));
result.add(new Equation(new Key(method, new InOut(i, Value.NotNull), stable), outEquation.rhs));
}
}
}
}
}
private void processNonBranchingMethod(Method method, Type[] argumentTypes, ControlFlowGraph graph, boolean isReferenceResult, boolean isBooleanResult, boolean stable, List<Equation> result) throws AnalyzerException {
CombinedAnalysis analyzer = new CombinedAnalysis(method, graph);
analyzer.analyze();
if (isReferenceResult) {
result.add(analyzer.outContractEquation(stable));
result.add(analyzer.nullableResultEquation(stable));
}
for (int i = 0; i < argumentTypes.length; i++) {
Type argType = argumentTypes[i];
if (ASMUtils.isReferenceType(argType)) {
result.add(analyzer.notNullParamEquation(i, stable));
result.add(analyzer.nullableParamEquation(i, stable));
if (isReferenceResult || isBooleanResult) {
result.add(analyzer.contractEquation(i, Value.Null, stable));
result.add(analyzer.contractEquation(i, Value.NotNull, stable));
}
}
}
}
private List<Equation> topEquations(Method method, Type[] argumentTypes, boolean isReferenceResult, boolean isInterestingResult, boolean stable) {
// 4 = @NotNull parameter, @Nullable parameter, null -> ..., !null -> ...
List<Equation> result = new ArrayList<>(argumentTypes.length * 4 + 2);
if (isReferenceResult) {
result.add(new Equation(new Key(method, Out, stable), FINAL_TOP));
result.add(new Equation(new Key(method, NullableOut, stable), FINAL_BOT));
}
for (int i = 0; i < argumentTypes.length; i++) {
if (ASMUtils.isReferenceType(argumentTypes[i])) {
result.add(new Equation(new Key(method, new In(i, In.NOT_NULL_MASK), stable), FINAL_TOP));
result.add(new Equation(new Key(method, new In(i, In.NULLABLE_MASK), stable), FINAL_TOP));
if (isInterestingResult) {
result.add(new Equation(new Key(method, new InOut(i, Value.Null), stable), FINAL_TOP));
result.add(new Equation(new Key(method, new InOut(i, Value.NotNull), stable), FINAL_TOP));
}
}
}
return result;
}
@NotNull
private LeakingParameters leakingParametersAndFrames(Method method, MethodNode methodNode, Type[] argumentTypes, boolean jsr) throws AnalyzerException {
return argumentTypes.length < 32 ? LeakingParameters.buildFast(method.internalClassName, methodNode, jsr) : LeakingParameters.build(method.internalClassName, methodNode, jsr);
}
}, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return equations;
}
use of org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException in project intellij-community by JetBrains.
the class FramelessAnalyzer method analyze.
public void analyze(final MethodNode m) throws AnalyzerException {
n = m.instructions.size();
if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0 || n == 0) {
return;
}
insns = m.instructions;
handlers = (List<TryCatchBlockNode>[]) new List<?>[n];
subroutines = new Subroutine[n];
queued = new boolean[n];
wasQueued = new boolean[n];
queue = new int[n];
top = 0;
// computes exception handlers for each instruction
for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
TryCatchBlockNode tcb = m.tryCatchBlocks.get(i);
int begin = insns.indexOf(tcb.start);
int end = insns.indexOf(tcb.end);
for (int j = begin; j < end; ++j) {
List<TryCatchBlockNode> insnHandlers = handlers[j];
if (insnHandlers == null) {
insnHandlers = new ArrayList<>();
handlers[j] = insnHandlers;
}
insnHandlers.add(tcb);
}
}
// computes the subroutine for each instruction:
Subroutine main = new Subroutine(null, m.maxLocals, null);
List<AbstractInsnNode> subroutineCalls = new ArrayList<>();
Map<LabelNode, Subroutine> subroutineHeads = new HashMap<>();
findSubroutine(0, main, subroutineCalls);
while (!subroutineCalls.isEmpty()) {
JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0);
Subroutine sub = subroutineHeads.get(jsr.label);
if (sub == null) {
sub = new Subroutine(jsr.label, m.maxLocals, jsr);
subroutineHeads.put(jsr.label, sub);
findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls);
} else {
sub.callers.add(jsr);
}
}
for (int i = 0; i < n; ++i) {
if (subroutines[i] != null && subroutines[i].start == null) {
subroutines[i] = null;
}
}
merge(0, null);
// control flow analysis
while (top > 0) {
int insn = queue[--top];
Subroutine subroutine = subroutines[insn];
queued[insn] = false;
AbstractInsnNode insnNode = null;
try {
insnNode = m.instructions.get(insn);
int insnOpcode = insnNode.getOpcode();
int insnType = insnNode.getType();
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
merge(insn + 1, subroutine);
newControlFlowEdge(insn, insn + 1);
} else {
subroutine = subroutine == null ? null : subroutine.copy();
if (insnNode instanceof JumpInsnNode) {
JumpInsnNode j = (JumpInsnNode) insnNode;
if (insnOpcode != GOTO && insnOpcode != JSR) {
merge(insn + 1, subroutine);
newControlFlowEdge(insn, insn + 1);
}
int jump = insns.indexOf(j.label);
if (insnOpcode == JSR) {
merge(jump, new Subroutine(j.label, m.maxLocals, j));
} else {
merge(jump, subroutine);
}
newControlFlowEdge(insn, jump);
} else if (insnNode instanceof LookupSwitchInsnNode) {
LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
int jump = insns.indexOf(lsi.dflt);
merge(jump, subroutine);
newControlFlowEdge(insn, jump);
for (int j = 0; j < lsi.labels.size(); ++j) {
LabelNode label = lsi.labels.get(j);
jump = insns.indexOf(label);
merge(jump, subroutine);
newControlFlowEdge(insn, jump);
}
} else if (insnNode instanceof TableSwitchInsnNode) {
TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
int jump = insns.indexOf(tsi.dflt);
merge(jump, subroutine);
newControlFlowEdge(insn, jump);
for (int j = 0; j < tsi.labels.size(); ++j) {
LabelNode label = tsi.labels.get(j);
jump = insns.indexOf(label);
merge(jump, subroutine);
newControlFlowEdge(insn, jump);
}
} else if (insnOpcode == RET) {
if (subroutine == null) {
throw new AnalyzerException(insnNode, "RET instruction outside of a sub routine");
}
for (int i = 0; i < subroutine.callers.size(); ++i) {
JumpInsnNode caller = subroutine.callers.get(i);
int call = insns.indexOf(caller);
if (wasQueued[call]) {
merge(call + 1, subroutines[call], subroutine.access);
newControlFlowEdge(insn, call + 1);
}
}
} else if (insnOpcode != ATHROW && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
if (subroutine != null) {
if (insnNode instanceof VarInsnNode) {
int var = ((VarInsnNode) insnNode).var;
subroutine.access[var] = true;
if (insnOpcode == LLOAD || insnOpcode == DLOAD || insnOpcode == LSTORE || insnOpcode == DSTORE) {
subroutine.access[var + 1] = true;
}
} else if (insnNode instanceof IincInsnNode) {
int var = ((IincInsnNode) insnNode).var;
subroutine.access[var] = true;
}
}
merge(insn + 1, subroutine);
newControlFlowEdge(insn, insn + 1);
}
}
List<TryCatchBlockNode> insnHandlers = handlers[insn];
if (insnHandlers != null) {
for (TryCatchBlockNode tcb : insnHandlers) {
newControlFlowExceptionEdge(insn, tcb);
merge(insns.indexOf(tcb.handler), subroutine);
}
}
} catch (AnalyzerException e) {
throw new AnalyzerException(e.node, "Error at instruction " + insn + ": " + e.getMessage(), e);
} catch (Exception e) {
throw new AnalyzerException(insnNode, "Error at instruction " + insn + ": " + e.getMessage(), e);
}
}
}
use of org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException in project kotlin by JetBrains.
the class CodegenTestCase method verifyWithAsm.
private static boolean verifyWithAsm(@NotNull OutputFile file, ClassLoader loader) {
ClassNode classNode = new ClassNode();
new ClassReader(file.asByteArray()).accept(classNode, 0);
SimpleVerifier verifier = new SimpleVerifier();
verifier.setClassLoader(loader);
Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(verifier);
boolean noErrors = true;
for (MethodNode method : classNode.methods) {
try {
analyzer.analyze(classNode.name, method);
} catch (Throwable e) {
System.err.println(file.asText());
System.err.println(classNode.name + "::" + method.name + method.desc);
//noinspection InstanceofCatchParameter
if (e instanceof AnalyzerException) {
// Print the erroneous instruction
TraceMethodVisitor tmv = new TraceMethodVisitor(new Textifier());
((AnalyzerException) e).node.accept(tmv);
PrintWriter pw = new PrintWriter(System.err);
tmv.p.print(pw);
pw.flush();
}
e.printStackTrace();
noErrors = false;
}
}
return noErrors;
}
Aggregations