Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
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
68f5565b
Commit
68f5565b
authored
Oct 07, 2014
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: improve processing of 'try/catch' and 'break' in loops
parent
c552fb85
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
249 additions
and
72 deletions
+249
-72
InsnDecoder.java
...src/main/java/jadx/core/dex/instructions/InsnDecoder.java
+1
-1
MethodNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
+15
-9
LoopRegion.java
...src/main/java/jadx/core/dex/regions/loops/LoopRegion.java
+17
-18
BlockMakerVisitor.java
...c/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java
+11
-5
RegionMaker.java
...main/java/jadx/core/dex/visitors/regions/RegionMaker.java
+78
-36
BlockUtils.java
jadx-core/src/main/java/jadx/core/utils/BlockUtils.java
+3
-3
TestNestedLoops3.java
...t/java/jadx/tests/integration/loops/TestNestedLoops3.java
+71
-0
TestTryCatchInLoop.java
...java/jadx/tests/integration/loops/TestTryCatchInLoop.java
+53
-0
No files found.
jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java
View file @
68f5565b
...
...
@@ -44,7 +44,7 @@ public class InsnDecoder {
while
(
in
.
hasMore
())
{
decoded
[
in
.
cursor
()]
=
DecodedInstruction
.
decode
(
in
);
}
}
catch
(
E
OFE
xception
e
)
{
}
catch
(
Exception
e
)
{
throw
new
DecodeException
(
method
,
""
,
e
);
}
insnArr
=
decoded
;
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
View file @
68f5565b
...
...
@@ -230,6 +230,9 @@ public class MethodNode extends LineAttrNode implements ILoadable {
InsnNode
[]
insnByOffset
=
instructions
;
CatchHandler
[]
catchBlocks
=
mthCode
.
getCatchHandlers
();
Try
[]
tries
=
mthCode
.
getTries
();
if
(
catchBlocks
.
length
==
0
&&
tries
.
length
==
0
)
{
return
;
}
int
hc
=
0
;
Set
<
Integer
>
addrs
=
new
HashSet
<
Integer
>();
...
...
@@ -287,13 +290,17 @@ public class MethodNode extends LineAttrNode implements ILoadable {
int
offset
=
aTry
.
getStartAddress
();
int
end
=
offset
+
aTry
.
getInstructionCount
()
-
1
;
insnByOffset
[
offset
].
add
(
AFlag
.
TRY_ENTER
);
InsnNode
insn
=
insnByOffset
[
offset
];
insn
.
add
(
AFlag
.
TRY_ENTER
);
while
(
offset
<=
end
&&
offset
>=
0
)
{
catchBlock
.
addInsn
(
insnByOffset
[
offset
]);
insn
=
insnByOffset
[
offset
];
catchBlock
.
addInsn
(
insn
);
offset
=
InsnDecoder
.
getNextInsnOffset
(
insnByOffset
,
offset
);
}
if
(
insnByOffset
[
end
]
!=
null
)
{
insnByOffset
[
end
].
add
(
AFlag
.
TRY_LEAVE
);
}
else
{
insn
.
add
(
AFlag
.
TRY_LEAVE
);
}
}
}
...
...
@@ -498,13 +505,12 @@ public class MethodNode extends LineAttrNode implements ILoadable {
/** workaround for non-static inner class constructor, that has
* synthetic argument */
if
((
parentClass
!=
null
)
&&
parentClass
.
getClassInfo
().
isInner
())
{
if
(!
parentClass
.
getAccessFlags
().
isStatic
())
{
ClassNode
outerCls
=
parentClass
.
getParentClass
();
if
((
argsList
!=
null
)
&&
(
argsList
.
size
()
>=
1
))
{
if
(
argsList
.
get
(
0
).
getType
().
equals
(
outerCls
.
getClassInfo
().
getType
()))
{
defaultArgCount
=
1
;
}
if
(
parentClass
.
getClassInfo
().
isInner
()
&&
!
parentClass
.
getAccessFlags
().
isStatic
())
{
ClassNode
outerCls
=
parentClass
.
getParentClass
();
if
((
argsList
!=
null
)
&&
(
argsList
.
size
()
>=
1
))
{
if
(
argsList
.
get
(
0
).
getType
().
equals
(
outerCls
.
getClassInfo
().
getType
()))
{
defaultArgCount
=
1
;
}
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/regions/loops/LoopRegion.java
View file @
68f5565b
...
...
@@ -88,25 +88,24 @@ public final class LoopRegion extends AbstractRegion {
InsnNode
insn
=
insns
.
get
(
i
);
if
(
insn
.
getResult
()
==
null
)
{
return
false
;
}
else
{
RegisterArg
res
=
insn
.
getResult
();
if
(
res
.
getSVar
().
getUseCount
()
>
1
)
{
return
false
;
}
boolean
found
=
false
;
// search result arg in other insns
for
(
int
j
=
i
+
1
;
j
<
size
;
j
++)
{
if
(
insns
.
get
(
i
).
containsArg
(
res
))
{
found
=
true
;
}
}
// or in if insn
if
(!
found
&&
ifInsn
.
containsArg
(
res
))
{
}
RegisterArg
res
=
insn
.
getResult
();
if
(
res
.
getSVar
().
getUseCount
()
>
1
)
{
return
false
;
}
boolean
found
=
false
;
// search result arg in other insns
for
(
int
j
=
i
+
1
;
j
<
size
;
j
++)
{
if
(
insns
.
get
(
i
).
containsArg
(
res
))
{
found
=
true
;
}
if
(!
found
)
{
return
false
;
}
}
// or in if insn
if
(!
found
&&
ifInsn
.
containsArg
(
res
))
{
found
=
true
;
}
if
(!
found
)
{
return
false
;
}
}
return
true
;
...
...
@@ -163,6 +162,6 @@ public final class LoopRegion extends AbstractRegion {
@Override
public
String
toString
()
{
return
"LOOP: "
+
baseString
();
return
"LOOP:
"
+
info
.
getId
()
+
":
"
+
baseString
();
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java
View file @
68f5565b
...
...
@@ -103,7 +103,9 @@ public class BlockMakerVisitor extends AbstractVisitor {
// add this insn in new block
block
=
startNewBlock
(
mth
,
-
1
);
curBlock
.
add
(
AFlag
.
SYNTHETIC
);
block
.
addAttr
(
new
SplitterBlockAttr
(
curBlock
));
SplitterBlockAttr
splitter
=
new
SplitterBlockAttr
(
curBlock
);
block
.
addAttr
(
splitter
);
curBlock
.
addAttr
(
splitter
);
connect
(
curBlock
,
block
);
curBlock
=
block
;
}
else
{
...
...
@@ -131,12 +133,16 @@ public class BlockMakerVisitor extends AbstractVisitor {
// get synthetic block for handlers
SplitterBlockAttr
spl
=
block
.
get
(
AType
.
SPLITTER_BLOCK
);
if
(
catches
!=
null
&&
spl
!=
null
)
{
BlockNode
connBlock
=
spl
.
getBlock
();
BlockNode
splitterBlock
=
spl
.
getBlock
();
boolean
tryEnd
=
insn
.
contains
(
AFlag
.
TRY_LEAVE
);
for
(
ExceptionHandler
h
:
catches
.
getTryBlock
().
getHandlers
())
{
BlockNode
dest
Block
=
getBlock
(
h
.
getHandleOffset
(),
blocksMap
);
BlockNode
handler
Block
=
getBlock
(
h
.
getHandleOffset
(),
blocksMap
);
// skip self loop in handler
if
(
connBlock
!=
destBlock
)
{
connect
(
connBlock
,
destBlock
);
if
(
splitterBlock
!=
handlerBlock
)
{
connect
(
splitterBlock
,
handlerBlock
);
}
if
(
tryEnd
)
{
connect
(
block
,
handlerBlock
);
}
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java
View file @
68f5565b
...
...
@@ -182,7 +182,7 @@ public class RegionMaker {
loopRegion
.
setCondition
(
condInfo
.
getCondition
());
exitBlocks
.
removeAll
(
condInfo
.
getMergedBlocks
());
if
(
exitBlocks
.
size
()
>
0
)
{
if
(
!
exitBlocks
.
isEmpty
()
)
{
BlockNode
loopExit
=
condInfo
.
getElseBlock
();
if
(
loopExit
!=
null
)
{
// add 'break' instruction before path cross between main loop exit and sub-exit
...
...
@@ -264,6 +264,25 @@ public class RegionMaker {
found
=
false
;
}
if
(
found
)
{
List
<
LoopInfo
>
list
=
mth
.
getAllLoopsForBlock
(
block
);
if
(
list
.
size
()
>=
2
)
{
// bad condition if successors going out of all loops
boolean
allOuter
=
true
;
for
(
BlockNode
outerBlock
:
block
.
getCleanSuccessors
())
{
List
<
LoopInfo
>
outLoopList
=
mth
.
getAllLoopsForBlock
(
outerBlock
);
outLoopList
.
remove
(
loop
);
if
(!
outLoopList
.
isEmpty
())
{
// goes to outer loop
allOuter
=
false
;
break
;
}
}
if
(
allOuter
)
{
found
=
false
;
}
}
}
if
(
found
)
{
return
loopRegion
;
}
}
...
...
@@ -281,16 +300,13 @@ public class RegionMaker {
BlockNode
loopExit
=
null
;
// insert 'break' for exits
List
<
Edge
>
exitEdges
=
loop
.
getExitEdges
();
if
(
exitEdges
.
size
()
==
1
)
{
for
(
Edge
exitEdge
:
exitEdges
)
{
BlockNode
exit
=
exitEdge
.
getTarget
();
if
(
canInsertBreak
(
exit
))
{
exit
.
getInstructions
().
add
(
new
InsnNode
(
InsnType
.
BREAK
,
0
));
BlockNode
nextBlock
=
getNextBlock
(
exit
);
if
(
nextBlock
!=
null
)
{
stack
.
addExit
(
nextBlock
);
loopExit
=
nextBlock
;
}
for
(
Edge
exitEdge
:
exitEdges
)
{
BlockNode
exit
=
exitEdge
.
getTarget
();
if
(
tryInsertBreak
(
stack
,
exit
,
exitEdge
))
{
BlockNode
nextBlock
=
getNextBlock
(
exit
);
if
(
nextBlock
!=
null
)
{
stack
.
addExit
(
nextBlock
);
loopExit
=
nextBlock
;
}
}
}
...
...
@@ -313,7 +329,8 @@ public class RegionMaker {
}
private
boolean
canInsertBreak
(
BlockNode
exit
)
{
if
(
exit
.
contains
(
AFlag
.
RETURN
))
{
if
(
exit
.
contains
(
AFlag
.
RETURN
)
||
BlockUtils
.
checkLastInsnType
(
exit
,
InsnType
.
BREAK
))
{
return
false
;
}
List
<
BlockNode
>
simplePath
=
BlockUtils
.
buildSimplePath
(
exit
);
...
...
@@ -331,35 +348,60 @@ public class RegionMaker {
return
true
;
}
private
void
tryInsertBreak
(
RegionStack
stack
,
BlockNode
loopExit
,
Edge
exitEdge
)
{
BlockNode
prev
=
null
;
private
boolean
tryInsertBreak
(
RegionStack
stack
,
BlockNode
loopExit
,
Edge
exitEdge
)
{
BlockNode
exit
=
exitEdge
.
getTarget
();
while
(
exit
!=
null
)
{
if
(
prev
!=
null
&&
isPathExists
(
loopExit
,
exit
))
{
// found cross
if
(
canInsertBreak
(
exit
))
{
InsnNode
breakInsn
=
new
InsnNode
(
InsnType
.
BREAK
,
0
);
prev
.
getInstructions
().
add
(
breakInsn
);
stack
.
addExit
(
exit
);
// add label to 'break' if needed
List
<
LoopInfo
>
loops
=
mth
.
getAllLoopsForBlock
(
exitEdge
.
getSource
());
if
(
loops
.
size
()
>=
2
)
{
// find parent loop
for
(
LoopInfo
loop
:
loops
)
{
if
(
loop
.
getParentLoop
()
==
null
)
{
LoopLabelAttr
labelAttr
=
new
LoopLabelAttr
(
loop
);
breakInsn
.
addAttr
(
labelAttr
);
loop
.
getStart
().
addAttr
(
labelAttr
);
break
;
}
}
BlockNode
insertBlock
=
null
;
boolean
confirm
=
false
;
// process special cases
if
(
loopExit
==
exit
)
{
// try/catch at loop end
BlockNode
source
=
exitEdge
.
getSource
();
if
(
source
.
contains
(
AType
.
CATCH_BLOCK
))
{
BlockNode
other
=
BlockUtils
.
selectOther
(
loopExit
,
source
.
getSuccessors
());
if
(
other
!=
null
&&
other
.
contains
(
AType
.
EXC_HANDLER
))
{
insertBlock
=
source
;
confirm
=
true
;
}
}
}
if
(!
confirm
)
{
while
(
exit
!=
null
)
{
if
(
insertBlock
!=
null
&&
isPathExists
(
loopExit
,
exit
))
{
// found cross
if
(
canInsertBreak
(
insertBlock
))
{
confirm
=
true
;
break
;
}
return
false
;
}
insertBlock
=
exit
;
List
<
BlockNode
>
cs
=
exit
.
getCleanSuccessors
();
exit
=
cs
.
size
()
==
1
?
cs
.
get
(
0
)
:
null
;
}
}
if
(!
confirm
)
{
return
false
;
}
InsnNode
breakInsn
=
new
InsnNode
(
InsnType
.
BREAK
,
0
);
insertBlock
.
getInstructions
().
add
(
breakInsn
);
stack
.
addExit
(
exit
);
// add label to 'break' if needed
List
<
LoopInfo
>
loops
=
mth
.
getAllLoopsForBlock
(
exitEdge
.
getSource
());
if
(
loops
.
size
()
>=
2
)
{
// find parent loop
for
(
LoopInfo
loop
:
loops
)
{
LoopInfo
parentLoop
=
loop
.
getParentLoop
();
if
(
parentLoop
==
null
&&
loop
.
getEnd
()
!=
exit
&&
!
loop
.
getExitNodes
().
contains
(
exit
))
{
LoopLabelAttr
labelAttr
=
new
LoopLabelAttr
(
loop
);
breakInsn
.
addAttr
(
labelAttr
);
loop
.
getStart
().
addAttr
(
labelAttr
);
break
;
}
return
;
}
prev
=
exit
;
exit
=
getNextBlock
(
exit
);
}
return
true
;
}
private
final
Set
<
BlockNode
>
cacheSet
=
new
HashSet
<
BlockNode
>();
...
...
jadx-core/src/main/java/jadx/core/utils/BlockUtils.java
View file @
68f5565b
...
...
@@ -246,16 +246,16 @@ public class BlockUtils {
Set
<
BlockNode
>
set
=
new
HashSet
<
BlockNode
>();
set
.
add
(
start
);
if
(
start
!=
end
)
{
addPredcessors
(
set
,
end
,
start
);
addPred
e
cessors
(
set
,
end
,
start
);
}
return
set
;
}
private
static
void
addPredcessors
(
Set
<
BlockNode
>
set
,
BlockNode
from
,
BlockNode
until
)
{
private
static
void
addPred
e
cessors
(
Set
<
BlockNode
>
set
,
BlockNode
from
,
BlockNode
until
)
{
set
.
add
(
from
);
for
(
BlockNode
pred
:
from
.
getPredecessors
())
{
if
(
pred
!=
until
&&
!
set
.
contains
(
pred
))
{
addPredcessors
(
set
,
pred
,
until
);
addPred
e
cessors
(
set
,
pred
,
until
);
}
}
}
...
...
jadx-core/src/test/java/jadx/tests/integration/loops/TestNestedLoops3.java
0 → 100644
View file @
68f5565b
package
jadx
.
tests
.
integration
.
loops
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.IntegrationTest
;
import
org.junit.Test
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestNestedLoops3
extends
IntegrationTest
{
public
static
class
TestCls
{
int
c
=
0
;
public
int
test
(
int
b
)
{
int
i
;
loop0:
while
(
true
)
{
f1
();
i
=
0
;
while
(
true
)
{
f2
();
if
(
i
!=
0
)
{
break
loop0
;
}
i
+=
3
;
if
(
b
>=
16
)
{
break
loop0
;
}
try
{
exc
();
break
;
}
catch
(
Exception
e
)
{
//
}
}
}
return
i
;
}
private
void
exc
()
throws
Exception
{
if
(
c
>
200
)
{
throw
new
Exception
();
}
}
private
void
f1
()
{
c
+=
1
;
}
private
void
f2
()
{
c
+=
100
;
}
public
void
check
()
{
test
(
1
);
assertEquals
(
302
,
c
);
}
}
@Test
public
void
test
()
{
setOutputCFG
();
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"} catch (Exception e) {"
));
}
}
jadx-core/src/test/java/jadx/tests/integration/loops/TestTryCatchInLoop.java
0 → 100644
View file @
68f5565b
package
jadx
.
tests
.
integration
.
loops
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.IntegrationTest
;
import
org.junit.Test
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestTryCatchInLoop
extends
IntegrationTest
{
public
static
class
TestCls
{
int
c
=
0
;
public
int
test
()
{
while
(
true
)
{
try
{
exc
();
break
;
}
catch
(
Exception
e
)
{
//
}
}
if
(
c
==
5
)
{
System
.
out
.
println
(
c
);
}
return
0
;
}
private
void
exc
()
throws
Exception
{
c
++;
if
(
c
<
3
)
{
throw
new
Exception
();
}
}
public
void
check
()
{
test
();
assertEquals
(
3
,
c
);
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"} catch (Exception e) {"
));
assertThat
(
code
,
containsOne
(
"break;"
));
}
}
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