通过语法构造Java反编译器会出现什么问题?

通过语法构造Java反编译器会出现什么问题?,java,jvm,antlr3,decompiling,decompiler,Java,Jvm,Antlr3,Decompiling,Decompiler,我目前正在构建一个Java反编译器 为了帮助模式识别,我正在通过ANTLR构造一个简单的语法,并使用ANTLRWorks解释器进行调试 以下是到目前为止的初步语法。在沿着这条路线走下去时,我假设我能够将某些JVM字节代码简化为下面语法可以检测到的表达式 您认为这种方法存在哪些问题? 6月29日格林尼治标准时间2:36更新爱尔兰共和军评论语法 例如,当前语法(上述语法的进一步发展)可以 进入 如果您只想识别单个JVM指令,那么语法就可以了。你可能会花时间修改语法,以获得正确的细节。这可能是简单的过

我目前正在构建一个Java反编译器

为了帮助模式识别,我正在通过ANTLR构造一个简单的语法,并使用ANTLRWorks解释器进行调试

以下是到目前为止的初步语法。在沿着这条路线走下去时,我假设我能够将某些JVM字节代码简化为下面语法可以检测到的表达式

您认为这种方法存在哪些问题? 6月29日格林尼治标准时间2:36更新爱尔兰共和军评论语法

例如,当前语法(上述语法的进一步发展)可以

进入


如果您只想识别单个JVM指令,那么语法就可以了。你可能会花时间修改语法,以获得正确的细节。这可能是简单的过激行为。字节操作码驱动的有限状态自动机(FSA)实现为一个巨型case语句可能更容易;毕竟,JVM指令应该易于解码,以便半快速解释器可以执行这些指令

基于模糊回忆,类文件中还有其他部分(表,例如文本)。您可能也可以通过解析器识别它们,但也可能是矫枉过正

第二个问题是在识别指令/表格信息后收集它们;解析器生成器倾向于帮助您构建某种AST。说明不是AST;它们至少是一个线性链,如果包含跳转目标,它们将形成一个带有表引用的图形。因此,我怀疑您最终将难以获得语义操作以按您希望的方式收集数据


这是您可能想要捕获的图形。如果图形具有某种层次结构(从结构化编程语言派生),您可能希望发现该层次结构。解析器方法在这里没有任何作用。

这种方法存在识别参数嵌套的问题

比如说,在声明中,

int func1(int x, int y, int z) {
    return 0;
}

int func0() {
    return 0;
}
电话呢

Object[] x = new Object[func1(2, 3, 4)];
x = new Object[func0()];
x = new Object[func1(func1(func1(0, 1, 2), 3, 4), 5, 6)];
它生成以下字节码:

Offset  Instruction       Comments (Method: none)
0       aload_0           (cheewee.helloworld.test000031_applet this)
1       iconst_2
2       iconst_3
3       iconst_4
4       invokevirtual 79  (cheewee.helloworld.test000031_applet.func1)
7       anewarray 81      (java.lang.Object)
10      astore_1          (java.lang.Object[] x)
11      aload_0           (cheewee.helloworld.test000031_applet this)
12      invokevirtual 83  (cheewee.helloworld.test000031_applet.func0)
15      anewarray 81      (java.lang.Object)
18      astore_1          (java.lang.Object[] x)
19      aload_0           (cheewee.helloworld.test000031_applet this)
20      aload_0           (cheewee.helloworld.test000031_applet this)
21      aload_0           (cheewee.helloworld.test000031_applet this)
22      iconst_0
23      iconst_1
24      iconst_2
25      invokevirtual 79  (cheewee.helloworld.test000031_applet.func1)
28      iconst_3
29      iconst_4
30      invokevirtual 79  (cheewee.helloworld.test000031_applet.func1)
33      iconst_5
34      bipush 6
36      invokevirtual 79  (cheewee.helloworld.test000031_applet.func1)
39      anewarray 81      (java.lang.Object)
42      astore_1          (java.lang.Object[] x)
43      return
它无法检测是否涉及嵌套。我不确定这是否是ANTLR的局限性,或者这是否是我学习如何编写ANTLR语法的局限性


下一步是使用混合方法,首先将字节码组简化为标记(以便将它们识别为更简单的模式),然后将其传递给解析器以检测更高级别的模式。

小建议。有什么问题和这个有关?这是一个有趣的问题。这是一个开源项目吗?你可能想看看jreversepro。那么“碎片”业务呢?我不是ANTLR专家;但是我希望规则看起来像“lhs:rhs1 | rhs2 | | | | | | rhsn”;而不是“fragment lhs:…”Ira,fragment是子规则-你可以忽略“fragment”关键字,假装fragment XXX与XXX.carlspring相同,现在谈论它是否是开源还为时过早。Ira,你能扩展FSA吗?你是说有限状态自动机吗?@chuacw:是的,我就是这个意思。解析器方法实际上是让我快速测试字节码识别(使用文本),而不是编写自己识别字节码的高级代码。一旦语法正确,我将把它改写成高级代码。@chuacw:我认为这项工作比它的价值还大。我猜想您只需要一个大型case语句,而且很难有一个比它更简单的代码框架。如果您将跟踪信息放在case语句的顶部(“在偏移量N处,我正在解码字节码m”)和每个arm中(“我解码了一个具有文本值17的PUSH文本”),我认为您的调试过程将非常快。谢谢,Ira。case语句方法的问题是,我不知道如何将每个字节码组织成可识别的模式。另一方面,在语法方法中,当我将字节码(例如0x62、0x30)转换为它们的文本等价物(例如fadd、faload)时,语法可以告诉我它识别了哪些模式。你在问题中提出的语法似乎专注于识别单个操作码,而不管“表达式”如何就像非终结符一样。如果你只想要单独的操作码,我认为ANTLR是完全多余的;坚持使用操作码FSA。但是,如果要识别“表达式”,则需要语法规则,即表达式可以是一系列表达式,后跟一个invokevirtual操作码。抽象地说,我希望能够提取参数,但您可能需要无限的前瞻性,以确保解析器能够根据callIra“猜测”正确数量的参数,我所拥有的语法的更高版本,后面有一个invokexxx操作码的表达式。不幸的是,同样的问题也发生了。表达式可以嵌套。对。表达式嵌套也出现在常规语言的语法中,常规解析器可以识别它们。如果JVM代码总是在结构化块中生成,那么您可能可以使用语法识别结构;正如我之前所观察到的,如果将其组织为一个算术图(如汇编代码),那么上下文无关语法将很难实现。按照前一种情况,您需要生成如下内容:stmt=exp;stmt=exp jlt_操作码目标;stmt=exp-store\u指令;以及exp=push_literal;exp=push\u变量var\u nameexp=exp-exp-add\u操作码;exp=expression\u list invokevirtual;表达式_list=;表达式列表=表达式列表表达式;最后一个应该处理嵌套表达式。你现在的语法是这样组织的吗?Ira,我更新了语法以回应你上面的评论。调用属性。语法与偏移量19到偏移量42处的代码有问题,
Object[] x = new Object[func1(2, 3, 4)];
x = new Object[func0()];
x = new Object[func1(func1(func1(0, 1, 2), 3, 4), 5, 6)];
Offset  Instruction       Comments (Method: none)
0       aload_0           (cheewee.helloworld.test000031_applet this)
1       iconst_2
2       iconst_3
3       iconst_4
4       invokevirtual 79  (cheewee.helloworld.test000031_applet.func1)
7       anewarray 81      (java.lang.Object)
10      astore_1          (java.lang.Object[] x)
11      aload_0           (cheewee.helloworld.test000031_applet this)
12      invokevirtual 83  (cheewee.helloworld.test000031_applet.func0)
15      anewarray 81      (java.lang.Object)
18      astore_1          (java.lang.Object[] x)
19      aload_0           (cheewee.helloworld.test000031_applet this)
20      aload_0           (cheewee.helloworld.test000031_applet this)
21      aload_0           (cheewee.helloworld.test000031_applet this)
22      iconst_0
23      iconst_1
24      iconst_2
25      invokevirtual 79  (cheewee.helloworld.test000031_applet.func1)
28      iconst_3
29      iconst_4
30      invokevirtual 79  (cheewee.helloworld.test000031_applet.func1)
33      iconst_5
34      bipush 6
36      invokevirtual 79  (cheewee.helloworld.test000031_applet.func1)
39      anewarray 81      (java.lang.Object)
42      astore_1          (java.lang.Object[] x)
43      return