From 027dc6eff903c81b5675fd9b12c8d4b14769c4d3 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 1 Feb 2015 21:15:14 -0500 Subject: [PATCH] Some thinking about exceptions --- .../sigterm/deob/attributes/Attributes.java | 5 ++++ .../info/sigterm/deob/attributes/Code.java | 5 ++++ .../deob/attributes/code/Exception.java | 24 +++++++++++++++- .../deob/attributes/code/Exceptions.java | 19 +++++++++++++ .../attributes/code/instructions/AThrow.java | 2 +- .../info/sigterm/deob/execution/Frame.java | 18 ++++++++++++ .../info/sigterm/deob/execution/Path.java | 28 +++++++++++++++++-- 7 files changed, 96 insertions(+), 5 deletions(-) diff --git a/src/main/java/info/sigterm/deob/attributes/Attributes.java b/src/main/java/info/sigterm/deob/attributes/Attributes.java index f5def18e04..d996e14c3e 100644 --- a/src/main/java/info/sigterm/deob/attributes/Attributes.java +++ b/src/main/java/info/sigterm/deob/attributes/Attributes.java @@ -46,6 +46,11 @@ public class Attributes load(); } + + public Method getMethod() + { + return method; + } public Attribute findType(AttributeType type) { diff --git a/src/main/java/info/sigterm/deob/attributes/Code.java b/src/main/java/info/sigterm/deob/attributes/Code.java index d6fc7114cc..af3b55d7db 100644 --- a/src/main/java/info/sigterm/deob/attributes/Code.java +++ b/src/main/java/info/sigterm/deob/attributes/Code.java @@ -39,6 +39,11 @@ public class Code extends Attribute return maxLocals; } + public Exceptions getExceptions() + { + return exceptions; + } + public Instructions getInstructions() { return instructions; diff --git a/src/main/java/info/sigterm/deob/attributes/code/Exception.java b/src/main/java/info/sigterm/deob/attributes/code/Exception.java index 6d9c2f9b69..7428888562 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/Exception.java +++ b/src/main/java/info/sigterm/deob/attributes/code/Exception.java @@ -1,9 +1,11 @@ package info.sigterm.deob.attributes.code; +import info.sigterm.deob.ConstantPool; + import java.io.DataInputStream; import java.io.IOException; -class Exception +public class Exception { private Exceptions exceptions; @@ -23,4 +25,24 @@ class Exception handlerPc = is.readUnsignedShort(); catchType = is.readUnsignedShort(); } + + public Exceptions getExceptions() + { + return exceptions; + } + + public int getStartPc() + { + return startPc; + } + + public int getEndPc() + { + return endPc; + } + + public int getHandlerPc() + { + return handlerPc; + } } diff --git a/src/main/java/info/sigterm/deob/attributes/code/Exceptions.java b/src/main/java/info/sigterm/deob/attributes/code/Exceptions.java index 3c694ba8b7..66a025d116 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/Exceptions.java +++ b/src/main/java/info/sigterm/deob/attributes/code/Exceptions.java @@ -1,9 +1,12 @@ package info.sigterm.deob.attributes.code; import info.sigterm.deob.attributes.Code; +import info.sigterm.deob.execution.ObjectInstance; import java.io.DataInputStream; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; public class Exceptions { @@ -27,4 +30,20 @@ public class Exceptions { return code; } + + public Collection getHandlersForPc(int pc) + { + ArrayList matches = new ArrayList(); + + for (Exception e : exceptions) + { + if (pc >= e.getStartPc() && pc < e.getEndPc()) + { + /* possible match */ + matches.add(e); + } + } + + return matches; + } } \ No newline at end of file diff --git a/src/main/java/info/sigterm/deob/attributes/code/instructions/AThrow.java b/src/main/java/info/sigterm/deob/attributes/code/instructions/AThrow.java index 729844364f..886b7ea426 100644 --- a/src/main/java/info/sigterm/deob/attributes/code/instructions/AThrow.java +++ b/src/main/java/info/sigterm/deob/attributes/code/instructions/AThrow.java @@ -19,6 +19,6 @@ public class AThrow extends Instruction public void execute(Frame e) { ObjectInstance exception = (ObjectInstance) e.getStack().pop(); - e.getPath().throwException(exception); + e.getPath().throwException(this, exception); } } diff --git a/src/main/java/info/sigterm/deob/execution/Frame.java b/src/main/java/info/sigterm/deob/execution/Frame.java index fcf1b99dca..0b9d3ee857 100644 --- a/src/main/java/info/sigterm/deob/execution/Frame.java +++ b/src/main/java/info/sigterm/deob/execution/Frame.java @@ -1,7 +1,10 @@ package info.sigterm.deob.execution; +import java.util.Collection; + import info.sigterm.deob.Method; import info.sigterm.deob.attributes.Code; +import info.sigterm.deob.attributes.code.Exception; import info.sigterm.deob.attributes.code.Instruction; import info.sigterm.deob.attributes.code.Instructions; @@ -39,6 +42,11 @@ public class Frame { return path; } + + public Method getMethod() + { + return method; + } public Stack getStack() { @@ -102,4 +110,14 @@ public class Frame assert offset != 0; pc += offset; } + + public void jumpAbsolute(int pc) + { + this.pc = pc; + } + + public Collection getExceptionHandlers() + { + return method.getCode().getExceptions().getHandlersForPc(this.pc); + } } diff --git a/src/main/java/info/sigterm/deob/execution/Path.java b/src/main/java/info/sigterm/deob/execution/Path.java index f8ea47774d..a0d62898d9 100644 --- a/src/main/java/info/sigterm/deob/execution/Path.java +++ b/src/main/java/info/sigterm/deob/execution/Path.java @@ -2,9 +2,11 @@ package info.sigterm.deob.execution; import info.sigterm.deob.ClassFile; import info.sigterm.deob.Method; +import info.sigterm.deob.attributes.code.Exception; import info.sigterm.deob.attributes.code.Instruction; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; public class Path @@ -112,9 +114,29 @@ public class Path currentFrame.executing = false; } - public void throwException(ObjectInstance exception) + public void throwException(Instruction ins, ObjectInstance exception) { - System.out.println("XXX throw " + exception); - //XXX + ArrayList exceptions = new ArrayList(); + + /* collect all existing exception handlers */ + for (Frame f : frames) + { + Collection handlers = f.getExceptionHandlers(); + exceptions.addAll(handlers); + } + + for (Exception handler : exceptions) + { + /* jump to handler */ + Method handlerMethod = handler.getExceptions().getCode().getAttributes().getMethod(); + + Path other = this.dup(); + /* walk up the frames until we find the one which holds the exception handler */ + while (handlerMethod != other.getCurrentFrame().getMethod()) + other.returnFrame(); + + /* handler pc is absolute from the beginning instruction */ + other.getCurrentFrame().jumpAbsolute(handler.getHandlerPc()); + } } }