Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Quincy379
jadx
提交
bae36f97
J
jadx
项目概览
Quincy379
/
jadx
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jadx
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
bae36f97
编写于
10月 30, 2019
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix: merge const block before return (#699)
上级
11db454b
变更
7
显示空白变更内容
内联
并排
Showing
7 changed file
with
218 addition
and
41 deletion
+218
-41
jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java
...ain/java/jadx/core/dex/instructions/args/RegisterArg.java
+7
-0
jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockProcessor.java
...va/jadx/core/dex/visitors/blocksmaker/BlockProcessor.java
+82
-34
jadx-core/src/main/java/jadx/core/utils/Utils.java
jadx-core/src/main/java/jadx/core/utils/Utils.java
+8
-0
jadx-core/src/test/java/jadx/tests/integration/conditions/TestConditions18.java
...a/jadx/tests/integration/conditions/TestConditions18.java
+17
-2
jadx-core/src/test/java/jadx/tests/integration/conditions/TestConditions21.java
...a/jadx/tests/integration/conditions/TestConditions21.java
+37
-0
jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernaryInIf2.java
...a/jadx/tests/integration/conditions/TestTernaryInIf2.java
+34
-5
jadx-core/src/test/smali/conditions/TestConditions21.smali
jadx-core/src/test/smali/conditions/TestConditions21.smali
+33
-0
未找到文件。
jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java
浏览文件 @
bae36f97
...
...
@@ -151,6 +151,13 @@ public class RegisterArg extends InsnArg implements Named {
&&
Objects
.
equals
(
sVar
,
reg
.
getSVar
());
}
public
boolean
sameReg
(
InsnArg
arg
)
{
if
(!
arg
.
isRegister
())
{
return
false
;
}
return
regNum
==
((
RegisterArg
)
arg
).
getRegNum
();
}
public
boolean
sameCodeVar
(
RegisterArg
arg
)
{
return
this
.
getSVar
().
getCodeVar
()
==
arg
.
getSVar
().
getCodeVar
();
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockProcessor.java
浏览文件 @
bae36f97
...
...
@@ -16,6 +16,7 @@ import jadx.core.dex.attributes.AFlag;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.nodes.LoopInfo
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.instructions.args.InsnArg
;
import
jadx.core.dex.instructions.args.LiteralArg
;
import
jadx.core.dex.instructions.args.RegisterArg
;
...
...
@@ -29,6 +30,7 @@ import jadx.core.dex.trycatch.ExceptionHandler;
import
jadx.core.dex.trycatch.TryCatchBlock
;
import
jadx.core.dex.visitors.AbstractVisitor
;
import
jadx.core.utils.BlockUtils
;
import
jadx.core.utils.Utils
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
static
jadx
.
core
.
dex
.
visitors
.
blocksmaker
.
BlockSplitter
.
connect
;
...
...
@@ -413,7 +415,48 @@ public class BlockProcessor extends AbstractVisitor {
return
true
;
}
}
return
splitReturn
(
mth
);
if
(
mergeConstReturn
(
mth
))
{
return
true
;
}
return
splitReturnBlocks
(
mth
);
}
private
static
boolean
mergeConstReturn
(
MethodNode
mth
)
{
if
(
mth
.
getReturnType
()
==
ArgType
.
VOID
)
{
return
false
;
}
boolean
changed
=
false
;
for
(
BlockNode
exitBlock
:
new
ArrayList
<>(
mth
.
getExitBlocks
()))
{
BlockNode
pred
=
Utils
.
getOne
(
exitBlock
.
getPredecessors
());
if
(
pred
!=
null
)
{
InsnNode
constInsn
=
Utils
.
getOne
(
pred
.
getInstructions
());
if
(
constInsn
!=
null
&&
constInsn
.
isConstInsn
())
{
RegisterArg
constArg
=
constInsn
.
getResult
();
InsnNode
returnInsn
=
BlockUtils
.
getLastInsn
(
exitBlock
);
if
(
returnInsn
!=
null
)
{
InsnArg
retArg
=
returnInsn
.
getArg
(
0
);
if
(
constArg
.
sameReg
(
retArg
))
{
mergeConstAndReturnBlocks
(
mth
,
exitBlock
,
pred
);
changed
=
true
;
}
}
}
}
}
if
(
changed
)
{
removeMarkedBlocks
(
mth
);
cleanExitNodes
(
mth
);
}
return
changed
;
}
private
static
void
mergeConstAndReturnBlocks
(
MethodNode
mth
,
BlockNode
exitBlock
,
BlockNode
pred
)
{
pred
.
getInstructions
().
addAll
(
exitBlock
.
getInstructions
());
pred
.
copyAttributesFrom
(
exitBlock
);
BlockSplitter
.
removeConnection
(
pred
,
exitBlock
);
exitBlock
.
getInstructions
().
clear
();
exitBlock
.
add
(
AFlag
.
REMOVE
);
}
private
static
boolean
independentBlockTreeMod
(
MethodNode
mth
)
{
...
...
@@ -604,16 +647,25 @@ public class BlockProcessor extends AbstractVisitor {
return
true
;
}
private
static
boolean
splitReturnBlocks
(
MethodNode
mth
)
{
boolean
changed
=
false
;
for
(
BlockNode
exitBlock
:
mth
.
getExitBlocks
())
{
if
(
splitReturn
(
mth
,
exitBlock
))
{
changed
=
true
;
}
}
if
(
changed
)
{
cleanExitNodes
(
mth
);
}
return
changed
;
}
/**
* Splice return block if several predecessors presents
*/
private
static
boolean
splitReturn
(
MethodNode
mth
)
{
if
(
mth
.
getExitBlocks
().
size
()
!=
1
)
{
return
false
;
}
BlockNode
exitBlock
=
mth
.
getExitBlocks
().
get
(
0
);
if
(
exitBlock
.
getInstructions
().
size
()
!=
1
||
exitBlock
.
contains
(
AFlag
.
SYNTHETIC
)
private
static
boolean
splitReturn
(
MethodNode
mth
,
BlockNode
exitBlock
)
{
if
(
exitBlock
.
contains
(
AFlag
.
SYNTHETIC
)
||
exitBlock
.
contains
(
AFlag
.
ORIG_RETURN
)
||
exitBlock
.
contains
(
AType
.
SPLITTER_BLOCK
))
{
return
false
;
}
...
...
@@ -625,31 +677,38 @@ public class BlockProcessor extends AbstractVisitor {
if
(
preds
.
size
()
<
2
)
{
return
false
;
}
InsnNode
returnInsn
=
exitBlock
.
getInstructions
().
get
(
0
);
if
(
returnInsn
.
getArgsCount
()
!=
0
&&
!
isReturnArgAssignInPred
(
preds
,
returnInsn
))
{
InsnNode
returnInsn
=
BlockUtils
.
getLastInsn
(
exitBlock
);
if
(
returnInsn
==
null
)
{
return
false
;
}
if
(
returnInsn
.
getArgsCount
()
==
1
&&
exitBlock
.
getInstructions
().
size
()
==
1
&&
!
isReturnArgAssignInPred
(
preds
,
returnInsn
))
{
return
false
;
}
boolean
first
=
true
;
for
(
BlockNode
pred
:
preds
)
{
BlockNode
newRetBlock
=
BlockSplitter
.
startNewBlock
(
mth
,
-
1
);
newRetBlock
.
add
(
AFlag
.
SYNTHETIC
);
InsnNode
newRetInsn
;
if
(
first
)
{
newRetInsn
=
returnInsn
;
newRetBlock
.
add
(
AFlag
.
ORIG_RETURN
);
newRetBlock
.
getInstructions
().
addAll
(
exitBlock
.
getInstructions
());
first
=
false
;
}
else
{
newRetInsn
=
duplicateReturnInsn
(
returnInsn
);
for
(
InsnNode
oldInsn
:
exitBlock
.
getInstructions
())
{
newRetBlock
.
getInstructions
().
add
(
oldInsn
.
copy
());
}
}
newRetBlock
.
getInstructions
().
add
(
newRetInsn
);
BlockSplitter
.
replaceConnection
(
pred
,
exitBlock
,
newRetBlock
);
}
cleanExitNodes
(
mth
);
return
true
;
}
private
static
boolean
isReturnArgAssignInPred
(
List
<
BlockNode
>
preds
,
InsnNode
returnInsn
)
{
RegisterArg
arg
=
(
RegisterArg
)
returnInsn
.
getArg
(
0
);
InsnArg
retArg
=
returnInsn
.
getArg
(
0
);
if
(
retArg
.
isRegister
())
{
RegisterArg
arg
=
(
RegisterArg
)
retArg
;
int
regNum
=
arg
.
getRegNum
();
for
(
BlockNode
pred
:
preds
)
{
for
(
InsnNode
insnNode
:
pred
.
getInstructions
())
{
...
...
@@ -659,6 +718,7 @@ public class BlockProcessor extends AbstractVisitor {
}
}
}
}
return
false
;
}
...
...
@@ -673,18 +733,6 @@ public class BlockProcessor extends AbstractVisitor {
}
}
private
static
InsnNode
duplicateReturnInsn
(
InsnNode
returnInsn
)
{
InsnNode
insn
=
new
InsnNode
(
returnInsn
.
getType
(),
returnInsn
.
getArgsCount
());
if
(
returnInsn
.
getArgsCount
()
==
1
)
{
RegisterArg
arg
=
(
RegisterArg
)
returnInsn
.
getArg
(
0
);
insn
.
addArg
(
arg
.
duplicate
());
}
insn
.
copyAttributesFrom
(
returnInsn
);
insn
.
setOffset
(
returnInsn
.
getOffset
());
insn
.
setSourceLine
(
returnInsn
.
getSourceLine
());
return
insn
;
}
private
static
void
removeMarkedBlocks
(
MethodNode
mth
)
{
mth
.
getBasicBlocks
().
removeIf
(
block
->
{
if
(
block
.
contains
(
AFlag
.
REMOVE
))
{
...
...
jadx-core/src/main/java/jadx/core/utils/Utils.java
浏览文件 @
bae36f97
...
...
@@ -204,6 +204,14 @@ public class Utils {
return
Collections
.
unmodifiableMap
(
result
);
}
@Nullable
public
static
<
T
>
T
getOne
(
@Nullable
List
<
T
>
list
)
{
if
(
list
==
null
||
list
.
size
()
!=
1
)
{
return
null
;
}
return
list
.
get
(
0
);
}
@Nullable
public
static
<
T
>
T
last
(
List
<
T
>
list
)
{
if
(
list
.
isEmpty
())
{
...
...
jadx-core/src/test/java/jadx/tests/integration/conditions/TestConditions18.java
浏览文件 @
bae36f97
...
...
@@ -2,9 +2,11 @@ package jadx.tests.integration.conditions;
import
org.junit.jupiter.api.Test
;
import
jadx.NotYetImplemented
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.SmaliTest
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsLines
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
...
...
@@ -31,7 +33,20 @@ public class TestConditions18 extends SmaliTest {
ClassNode
cls
=
getClassNodeFromSmali
();
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"return this == obj"
+
" || ((obj instanceof TestConditions18) && st(this.map, ((TestConditions18) obj).map));"
));
assertThat
(
code
,
containsLines
(
2
,
"if (this != obj) {"
,
indent
()
+
"return (obj instanceof TestConditions18) && st(this.map, ((TestConditions18) obj).map);"
,
"}"
,
"return true;"
));
}
@Test
@NotYetImplemented
public
void
testNYI
()
{
ClassNode
cls
=
getClassNodeFromSmali
();
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"return this == obj || ((obj instanceof TestConditions18) && st(this.map, ((TestConditions18) obj).map));"
));
}
}
jadx-core/src/test/java/jadx/tests/integration/conditions/TestConditions21.java
0 → 100644
浏览文件 @
bae36f97
package
jadx.tests.integration.conditions
;
import
org.junit.jupiter.api.Test
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.SmaliTest
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
public
class
TestConditions21
extends
SmaliTest
{
// @formatter:off
/*
public boolean check(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof List) {
List list = (List) obj;
if (!list.isEmpty() && list.contains(this)) {
return true;
}
}
return false;
}
*/
// @formatter:on
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNodeFromSmali
();
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"!list.isEmpty() && list.contains(this)"
));
}
}
jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernaryInIf2.java
浏览文件 @
bae36f97
...
...
@@ -2,17 +2,19 @@ package jadx.tests.integration.conditions;
import
org.junit.jupiter.api.Test
;
import
jadx.NotYetImplemented
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.SmaliTest
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsLines
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
org
.
hamcrest
.
Matchers
.
is
;
public
class
TestTernaryInIf2
extends
SmaliTest
{
public
static
class
TestCls
{
private
String
a
;
private
String
b
;
private
String
a
=
"a"
;
private
String
b
=
"b"
;
public
boolean
equals
(
TestCls
other
)
{
if
(
this
.
a
==
null
?
other
.
a
==
null
:
this
.
a
.
equals
(
other
.
a
))
{
...
...
@@ -22,6 +24,22 @@ public class TestTernaryInIf2 extends SmaliTest {
}
return
false
;
}
public
void
check
()
{
TestCls
other
=
new
TestCls
();
other
.
a
=
"a"
;
other
.
b
=
"b"
;
assertThat
(
this
.
equals
(
other
),
is
(
true
));
other
.
b
=
"not-b"
;
assertThat
(
this
.
equals
(
other
),
is
(
false
));
other
.
b
=
null
;
assertThat
(
this
.
equals
(
other
),
is
(
false
));
this
.
b
=
null
;
assertThat
(
this
.
equals
(
other
),
is
(
true
));
}
}
@Test
...
...
@@ -30,9 +48,20 @@ public class TestTernaryInIf2 extends SmaliTest {
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsLines
(
2
,
"if (this.a != null ? this.a.equals(other.a) : other.a == null) {"
));
assertThat
(
code
,
containsLines
(
3
,
"if (this.b != null ? this.b.equals(other.b) : other.b == null) {"
));
assertThat
(
code
,
containsLines
(
4
,
"return true;"
));
assertThat
(
code
,
containsLines
(
2
,
"return false;"
));
// assertThat(code, containsLines(3, "if (this.b != null ? this.b.equals(other.b) : other.b == null)
// {"));
// assertThat(code, containsLines(4, "return true;"));
// assertThat(code, containsLines(2, "return false;"));
}
@Test
@NotYetImplemented
public
void
testNYI
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsLines
(
2
,
"return (this.a != null ? this.a.equals(other.a) : other.a == null) "
+
"&& (this.b == null ? other.b == null : this.b.equals(other.b));"
));
}
@Test
...
...
jadx-core/src/test/smali/conditions/TestConditions21.smali
0 → 100644
浏览文件 @
bae36f97
.class public final Lconditions/TestConditions21;
.super Ljava/lang/Object;
.method public check(Ljava/lang/Object;)Z
.locals 2
if-eq p0, p1, :ret_true
instance-of v0, p1, Ljava/util/List;
if-eqz v0, :ret_false
check-cast p1, Ljava/util/List;
invoke-interface {p1}, Ljava/util/List;->isEmpty()Z
move-result v0
if-nez v0, :ret_false
invoke-interface {p1, p0}, Ljava/util/List;->contains(Ljava/lang/Object;)Z
move-result v0
if-eqz v0, :ret_false
goto :ret_true
:ret_false
const/4 p1, 0x0
return p1
:ret_true
const/4 p1, 0x1
return p1
.end method
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录