Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jadx
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open-source
jadx
Commits
b2f189b5
Commit
b2f189b5
authored
Nov 12, 2013
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: process complex condition in loop header
parent
eec524ad
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
404 additions
and
126 deletions
+404
-126
ClassGen.java
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
+10
-0
MethodGen.java
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
+2
-13
IfNode.java
...core/src/main/java/jadx/core/dex/instructions/IfNode.java
+34
-5
IfCondition.java
...core/src/main/java/jadx/core/dex/regions/IfCondition.java
+25
-4
IfInfo.java
jadx-core/src/main/java/jadx/core/dex/regions/IfInfo.java
+42
-0
LoopRegion.java
...-core/src/main/java/jadx/core/dex/regions/LoopRegion.java
+10
-2
BlockProcessingHelper.java
...in/java/jadx/core/dex/visitors/BlockProcessingHelper.java
+25
-4
RegionMaker.java
...main/java/jadx/core/dex/visitors/regions/RegionMaker.java
+146
-92
InsnUtils.java
jadx-core/src/main/java/jadx/core/utils/InsnUtils.java
+5
-1
InternalJadxTest.java
jadx-core/src/test/java/jadx/api/InternalJadxTest.java
+4
-0
TestLoopCondition.java
.../src/test/java/jadx/tests/internal/TestLoopCondition.java
+54
-0
TestCF3.java
jadx-samples/src/main/java/jadx/samples/TestCF3.java
+47
-5
No files found.
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
View file @
b2f189b5
...
...
@@ -30,9 +30,14 @@ import java.util.Map;
import
java.util.Map.Entry
;
import
java.util.Set
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
com.android.dx.rop.code.AccessFlags
;
public
class
ClassGen
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ClassGen
.
class
);
private
final
ClassNode
cls
;
private
final
ClassGen
parentGen
;
private
final
AnnotationGen
annotationGen
;
...
...
@@ -232,6 +237,11 @@ public class ClassGen {
continue
;
MethodGen
mthGen
=
new
MethodGen
(
this
,
mth
);
if
(
mth
.
getAttributes
().
contains
(
AttributeFlag
.
INCONSISTENT_CODE
))
{
code
.
startLine
(
"/* JADX WARNING: inconsistent code */"
);
LOG
.
error
(
ErrorsCounter
.
formatErrorMsg
(
mth
,
" Inconsistent code"
));
mthGen
.
makeMethodDump
(
code
);
}
mthGen
.
addDefinition
(
code
);
code
.
add
(
" {"
);
insertSourceFileInfo
(
code
,
mth
);
...
...
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
View file @
b2f189b5
package
jadx
.
core
.
codegen
;
import
jadx.core.Consts
;
import
jadx.core.dex.attributes.AttributeFlag
;
import
jadx.core.dex.attributes.AttributeType
;
import
jadx.core.dex.attributes.AttributesList
;
import
jadx.core.dex.attributes.JadxErrorAttr
;
...
...
@@ -61,11 +60,6 @@ public class MethodGen {
if
(
mth
.
getMethodInfo
().
isClassInit
())
{
code
.
startLine
(
"static"
);
}
else
{
if
(
mth
.
getAttributes
().
contains
(
AttributeFlag
.
INCONSISTENT_CODE
)
&&
!
mth
.
getAttributes
().
contains
(
AttributeType
.
JADX_ERROR
))
{
code
.
startLine
(
"// jadx: inconsistent code"
);
}
annotationGen
.
addForMethod
(
code
,
mth
);
AccessInfo
clsAccFlags
=
mth
.
getParentClass
().
getAccessFlags
();
...
...
@@ -235,16 +229,11 @@ public class MethodGen {
code
.
startLine
(
"Error: "
).
add
(
Utils
.
getStackTrace
(
cause
));
code
.
add
(
"*/"
);
}
makeMethodDump
(
code
,
mth
);
makeMethodDump
(
code
);
}
else
{
if
(
mth
.
getRegion
()
!=
null
)
{
CodeWriter
insns
=
new
CodeWriter
(
mthIndent
+
1
);
(
new
RegionGen
(
this
,
mth
)).
makeRegion
(
insns
,
mth
.
getRegion
());
if
(
mth
.
getAttributes
().
contains
(
AttributeFlag
.
INCONSISTENT_CODE
))
{
LOG
.
debug
(
ErrorsCounter
.
formatErrorMsg
(
mth
,
" Inconsistent code"
));
// makeMethodDump(code, mth);
}
code
.
add
(
insns
);
}
else
{
makeFallbackMethod
(
code
,
mth
);
...
...
@@ -253,7 +242,7 @@ public class MethodGen {
return
code
;
}
public
void
makeMethodDump
(
CodeWriter
code
,
MethodNode
mth
)
{
public
void
makeMethodDump
(
CodeWriter
code
)
{
code
.
startLine
(
"/*"
);
getFallbackMethodGen
(
mth
).
addDefinition
(
code
);
code
.
add
(
" {"
);
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/IfNode.java
View file @
b2f189b5
...
...
@@ -4,15 +4,22 @@ 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.PrimitiveType
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.utils.InsnUtils
;
import
com.android.dx.io.instructions.DecodedInstruction
;
import
static
jadx
.
core
.
utils
.
BlockUtils
.
getBlockByOffset
;
import
static
jadx
.
core
.
utils
.
BlockUtils
.
selectOther
;
public
class
IfNode
extends
GotoNode
{
protected
boolean
zeroCmp
;
protected
IfOp
op
;
private
BlockNode
thenBlock
;
private
BlockNode
elseBlock
;
public
IfNode
(
int
targ
,
InsnArg
then
,
InsnArg
els
)
{
super
(
InsnType
.
IF
,
targ
);
addArg
(
then
);
...
...
@@ -49,9 +56,12 @@ public class IfNode extends GotoNode {
return
zeroCmp
;
}
public
void
invert
Op
(
int
targ
)
{
public
void
invert
Condition
(
)
{
op
=
op
.
invert
();
target
=
targ
;
BlockNode
tmp
=
thenBlock
;
thenBlock
=
elseBlock
;
elseBlock
=
tmp
;
target
=
thenBlock
.
getStartOffset
();
}
public
void
changeCondition
(
InsnArg
arg1
,
InsnArg
arg2
,
IfOp
op
)
{
...
...
@@ -59,12 +69,31 @@ public class IfNode extends GotoNode {
this
.
zeroCmp
=
arg2
.
isLiteral
()
&&
((
LiteralArg
)
arg2
).
getLiteral
()
==
0
;
setArg
(
0
,
arg1
);
if
(!
zeroCmp
)
{
if
(
getArgsCount
()
==
2
)
if
(
getArgsCount
()
==
2
)
{
setArg
(
1
,
arg2
);
else
}
else
{
addArg
(
arg2
);
}
}
}
public
void
initBlocks
(
BlockNode
curBlock
)
{
thenBlock
=
getBlockByOffset
(
target
,
curBlock
.
getSuccessors
());
if
(
curBlock
.
getSuccessors
().
size
()
==
1
)
{
elseBlock
=
thenBlock
;
}
else
{
elseBlock
=
selectOther
(
thenBlock
,
curBlock
.
getSuccessors
());
}
target
=
thenBlock
.
getStartOffset
();
}
public
BlockNode
getThenBlock
()
{
return
thenBlock
;
}
public
BlockNode
getElseBlock
()
{
return
elseBlock
;
}
@Override
public
String
toString
()
{
...
...
@@ -72,6 +101,6 @@ public class IfNode extends GotoNode {
+
InsnUtils
.
insnTypeToString
(
insnType
)
+
getArg
(
0
)
+
" "
+
op
.
getSymbol
()
+
" "
+
(
zeroCmp
?
"0"
:
getArg
(
1
))
+
" -> "
+
InsnUtils
.
formatOffset
(
target
);
+
" -> "
+
(
thenBlock
!=
null
?
thenBlock
:
InsnUtils
.
formatOffset
(
target
)
);
}
}
jadx-core/src/main/java/jadx/core/dex/regions/IfCondition.java
View file @
b2f189b5
...
...
@@ -12,9 +12,9 @@ import java.util.List;
public
final
class
IfCondition
{
public
static
IfCondition
fromIfBlock
(
BlockNode
header
)
{
if
(
header
==
null
)
if
(
header
==
null
)
{
return
null
;
}
return
fromIfNode
((
IfNode
)
header
.
getInstructions
().
get
(
0
));
}
...
...
@@ -39,8 +39,8 @@ public final class IfCondition {
public
static
final
class
Compare
{
private
final
IfNode
insn
;
public
Compare
(
IfNode
i
fNode
)
{
this
.
insn
=
i
fNode
;
public
Compare
(
IfNode
i
nsn
)
{
this
.
insn
=
i
nsn
;
}
public
IfOp
getOp
()
{
...
...
@@ -57,6 +57,10 @@ public final class IfCondition {
else
return
insn
.
getArg
(
1
);
}
public
Compare
invert
()
{
insn
.
invertCondition
();
return
this
;
}
@Override
public
String
toString
()
{
...
...
@@ -113,6 +117,23 @@ public final class IfCondition {
return
compare
;
}
public
IfCondition
invert
()
{
switch
(
mode
)
{
case
COMPARE:
return
new
IfCondition
(
compare
.
invert
());
case
NOT:
return
new
IfCondition
(
args
.
get
(
0
));
case
AND:
case
OR:
List
<
IfCondition
>
newArgs
=
new
ArrayList
<
IfCondition
>(
args
.
size
());
for
(
IfCondition
arg
:
args
)
{
newArgs
.
add
(
arg
.
invert
());
}
return
new
IfCondition
(
mode
==
Mode
.
AND
?
Mode
.
OR
:
Mode
.
AND
,
newArgs
);
}
throw
new
RuntimeException
(
"Unknown mode for invert: "
+
mode
);
}
@Override
public
String
toString
()
{
switch
(
mode
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/regions/IfInfo.java
0 → 100644
View file @
b2f189b5
package
jadx
.
core
.
dex
.
regions
;
import
jadx.core.dex.nodes.BlockNode
;
public
final
class
IfInfo
{
IfCondition
condition
;
BlockNode
ifnode
;
BlockNode
thenBlock
;
BlockNode
elseBlock
;
public
IfCondition
getCondition
()
{
return
condition
;
}
public
void
setCondition
(
IfCondition
condition
)
{
this
.
condition
=
condition
;
}
public
BlockNode
getIfnode
()
{
return
ifnode
;
}
public
void
setIfnode
(
BlockNode
ifnode
)
{
this
.
ifnode
=
ifnode
;
}
public
BlockNode
getThenBlock
()
{
return
thenBlock
;
}
public
void
setThenBlock
(
BlockNode
thenBlock
)
{
this
.
thenBlock
=
thenBlock
;
}
public
BlockNode
getElseBlock
()
{
return
elseBlock
;
}
public
void
setElseBlock
(
BlockNode
elseBlock
)
{
this
.
elseBlock
=
elseBlock
;
}
}
jadx-core/src/main/java/jadx/core/dex/regions/LoopRegion.java
View file @
b2f189b5
...
...
@@ -14,8 +14,8 @@ import java.util.List;
public
final
class
LoopRegion
extends
AbstractRegion
{
// loop header contains one 'if' insn, equals null for infinite loop
private
final
IfCondition
condition
;
private
final
BlockNode
conditionBlock
;
private
IfCondition
condition
;
private
BlockNode
conditionBlock
;
// instruction which must be executed before condition in every loop
private
BlockNode
preCondition
=
null
;
private
IContainer
body
;
...
...
@@ -32,10 +32,18 @@ public final class LoopRegion extends AbstractRegion {
return
condition
;
}
public
void
setCondition
(
IfCondition
condition
)
{
this
.
condition
=
condition
;
}
public
BlockNode
getHeader
()
{
return
conditionBlock
;
}
public
void
setHeader
(
BlockNode
conditionBlock
)
{
this
.
conditionBlock
=
conditionBlock
;
}
public
IContainer
getBody
()
{
return
body
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/BlockProcessingHelper.java
View file @
b2f189b5
package
jadx
.
core
.
dex
.
visitors
;
import
jadx.core.dex.attributes.AttributeType
;
import
jadx.core.dex.instructions.IfNode
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.instructions.args.NamedArg
;
...
...
@@ -14,17 +15,21 @@ import jadx.core.dex.trycatch.ExceptionHandler;
import
jadx.core.dex.trycatch.TryCatchBlock
;
import
jadx.core.utils.BlockUtils
;
import
java.util.List
;
public
class
BlockProcessingHelper
{
public
static
void
visit
(
MethodNode
mth
)
{
if
(
mth
.
isNoCode
())
if
(
mth
.
isNoCode
())
{
return
;
}
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
markExceptionHandlers
(
block
);
}
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
block
.
updateCleanSuccessors
();
initBlocksInIfNodes
(
block
);
}
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
processExceptionHandlers
(
mth
,
block
);
...
...
@@ -77,12 +82,14 @@ public class BlockProcessingHelper {
// remove 'monitor-exit' from exception handler blocks
InstructionRemover
remover
=
new
InstructionRemover
(
excBlock
.
getInstructions
());
for
(
InsnNode
insn
:
excBlock
.
getInstructions
())
{
if
(
insn
.
getType
()
==
InsnType
.
MONITOR_ENTER
)
if
(
insn
.
getType
()
==
InsnType
.
MONITOR_ENTER
)
{
break
;
}
if
(
insn
.
getType
()
==
InsnType
.
MONITOR_EXIT
)
if
(
insn
.
getType
()
==
InsnType
.
MONITOR_EXIT
)
{
remover
.
add
(
insn
);
}
}
remover
.
perform
();
// if 'throw' in exception handler block have 'catch' - merge these catch blocks
...
...
@@ -108,8 +115,9 @@ public class BlockProcessingHelper {
CatchAttr
commonCatchAttr
=
null
;
for
(
InsnNode
insn
:
block
.
getInstructions
())
{
CatchAttr
catchAttr
=
(
CatchAttr
)
insn
.
getAttributes
().
get
(
AttributeType
.
CATCH_BLOCK
);
if
(
catchAttr
==
null
)
if
(
catchAttr
==
null
)
{
continue
;
}
if
(
commonCatchAttr
==
null
)
{
commonCatchAttr
=
catchAttr
;
...
...
@@ -137,4 +145,17 @@ public class BlockProcessingHelper {
}
}
}
/**
* Init 'then' and 'else' blocks for 'if' instruction.
*/
private
static
void
initBlocksInIfNodes
(
BlockNode
block
)
{
List
<
InsnNode
>
instructions
=
block
.
getInstructions
();
if
(
instructions
.
size
()
==
1
)
{
InsnNode
insn
=
instructions
.
get
(
0
);
if
(
insn
.
getType
()
==
InsnType
.
IF
)
{
((
IfNode
)
insn
).
initBlocks
(
block
);
}
}
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java
View file @
b2f189b5
This diff is collapsed.
Click to expand it.
jadx-core/src/main/java/jadx/core/utils/InsnUtils.java
View file @
b2f189b5
...
...
@@ -23,8 +23,12 @@ public class InsnUtils {
}
public
static
String
formatOffset
(
int
offset
)
{
if
(
offset
<
0
)
{
return
"?"
;
}
else
{
return
String
.
format
(
"0x%04x"
,
offset
);
}
}
public
static
String
insnTypeToString
(
InsnType
type
)
{
return
insnTypeToString
(
type
.
toString
());
...
...
jadx-core/src/test/java/jadx/api/InternalJadxTest.java
View file @
b2f189b5
...
...
@@ -125,4 +125,8 @@ public abstract class InternalJadxTest {
}
}
}
protected
void
setOutputCFG
()
{
this
.
outputCFG
=
true
;
}
}
jadx-core/src/test/java/jadx/tests/internal/TestLoopCondition.java
0 → 100644
View file @
b2f189b5
package
jadx
.
tests
.
internal
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestLoopCondition
extends
InternalJadxTest
{
@SuppressWarnings
(
"serial"
)
public
static
class
TestCls
extends
Exception
{
public
String
f
;
private
void
setEnabled
(
boolean
r1z
)
{
}
private
void
testIfInLoop
()
{
int
j
=
0
;
for
(
int
i
=
0
;
i
<
f
.
length
();
i
++)
{
char
ch
=
f
.
charAt
(
i
);
if
(
ch
==
'/'
)
{
j
++;
if
(
j
==
2
)
{
setEnabled
(
true
);
return
;
}
}
}
setEnabled
(
false
);
}
public
int
testComplexIfInLoop
(
boolean
a
)
{
int
i
=
0
;
while
(
a
&&
i
<
10
)
{
i
++;
}
return
i
;
}
}
@Test
public
void
test
()
{
setOutputCFG
();
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsString
(
"i < f.length()"
));
assertThat
(
code
,
containsString
(
"while (a && i < 10) {"
));
}
}
jadx-samples/src/main/java/jadx/samples/TestCF3.java
View file @
b2f189b5
...
...
@@ -60,15 +60,17 @@ public class TestCF3 extends AbstractTest {
while
(
it2
.
hasNext
())
{
String
s2
=
it2
.
next
();
if
(
s1
.
equals
(
s2
))
{
if
(
s1
.
length
()
==
5
)
if
(
s1
.
length
()
==
5
)
{
l2
.
add
(
s1
);
else
}
else
{
l1
.
remove
(
s2
);
}
}
}
if
(
l2
.
size
()
>
0
)
}
if
(
l2
.
size
()
>
0
)
{
l1
.
clear
();
}
return
l1
.
size
()
==
0
;
}
...
...
@@ -111,9 +113,10 @@ public class TestCF3 extends AbstractTest {
Iterator
<
String
>
it
=
list
.
iterator
();
while
(
it
.
hasNext
())
{
String
ver
=
it
.
next
();
if
(
ver
!=
null
)
if
(
ver
!=
null
)
{
return
ver
;
}
}
return
"error"
;
}
...
...
@@ -123,15 +126,44 @@ public class TestCF3 extends AbstractTest {
while
(
it
.
hasNext
())
{
String
ver
=
it
.
next
();
exc
();
if
(
ver
!=
null
)
if
(
ver
!=
null
)
{
return
ver
;
}
}
}
catch
(
Exception
e
)
{
setEnabled
(
false
);
}
return
"error"
;
}
public
int
testComplexIfInLoop
(
boolean
a
)
{
int
i
=
0
;
while
(
a
&&
i
<
10
)
{
i
++;
}
return
i
;
}
public
int
testComplexIfInLoop2
(
int
k
)
{
int
i
=
k
;
while
(
i
>
5
&&
i
<
10
)
{
i
++;
}
return
i
;
}
public
int
testComplexIfInLoop3
(
int
k
)
{
int
i
=
k
;
while
(
i
>
5
&&
i
<
k
*
3
)
{
if
(
k
==
8
)
{
i
++;
}
else
{
break
;
}
}
return
i
;
}
@Override
public
boolean
testRun
()
throws
Exception
{
setEnabled
(
false
);
...
...
@@ -158,6 +190,16 @@ public class TestCF3 extends AbstractTest {
// assertEquals(testReturnInLoop2(list2), "error");
// assertTrue(testLabeledBreakContinue());
assertEquals
(
testComplexIfInLoop
(
false
),
0
);
assertEquals
(
testComplexIfInLoop
(
true
),
10
);
assertEquals
(
testComplexIfInLoop2
(
2
),
2
);
assertEquals
(
testComplexIfInLoop2
(
6
),
10
);
assertEquals
(
testComplexIfInLoop3
(
2
),
2
);
assertEquals
(
testComplexIfInLoop3
(
6
),
6
);
assertEquals
(
testComplexIfInLoop3
(
8
),
24
);
return
true
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment