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
37857e88
Commit
37857e88
authored
Jun 23, 2014
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: fix switch statement processing (issue #9 case 2)
parent
6fbcf46a
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
122 additions
and
20 deletions
+122
-20
RegionGen.java
jadx-core/src/main/java/jadx/core/codegen/RegionGen.java
+1
-1
RegionMaker.java
...main/java/jadx/core/dex/visitors/regions/RegionMaker.java
+19
-13
BlockUtils.java
jadx-core/src/main/java/jadx/core/utils/BlockUtils.java
+1
-4
TestSwitch.java
...rc/test/java/jadx/tests/internal/switches/TestSwitch.java
+6
-1
TestSwitchLabels.java
...t/java/jadx/tests/internal/switches/TestSwitchLabels.java
+1
-1
TestSwitchNoDefault.java
...ava/jadx/tests/internal/switches/TestSwitchNoDefault.java
+42
-0
TestSwitchSimple.java
...t/java/jadx/tests/internal/switches/TestSwitchSimple.java
+52
-0
No files found.
jadx-core/src/main/java/jadx/core/codegen/RegionGen.java
View file @
37857e88
...
...
@@ -199,7 +199,7 @@ public class RegionGen extends InsnGen {
SwitchNode
insn
=
(
SwitchNode
)
sw
.
getHeader
().
getInstructions
().
get
(
0
);
InsnArg
arg
=
insn
.
getArg
(
0
);
code
.
startLine
(
"switch ("
);
addArg
(
code
,
arg
);
addArg
(
code
,
arg
,
false
);
code
.
add
(
") {"
);
code
.
incIndent
();
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java
View file @
37857e88
...
...
@@ -627,7 +627,7 @@ public class RegionMaker {
BitSet
succ
=
BlockUtils
.
blocksToBitSet
(
mth
,
block
.
getSuccessors
());
BitSet
domsOn
=
BlockUtils
.
blocksToBitSet
(
mth
,
block
.
getDominatesOn
());
domsOn
.
and
(
succ
);
// filter 'out' block
domsOn
.
xor
(
succ
);
// filter 'out' block
BlockNode
defCase
=
getBlockByOffset
(
insn
.
getDefaultCaseOffset
(),
block
.
getSuccessors
());
if
(
defCase
!=
null
)
{
...
...
@@ -642,13 +642,11 @@ public class RegionMaker {
}
if
(
outCount
>
1
)
{
// filter successors of other blocks
List
<
BlockNode
>
blocks
=
mth
.
getBasicBlocks
();
for
(
int
i
=
domsOn
.
nextSetBit
(
0
);
i
>=
0
;
i
=
domsOn
.
nextSetBit
(
i
+
1
))
{
BlockNode
b
=
mth
.
getBasicBlocks
()
.
get
(
i
);
BlockNode
b
=
blocks
.
get
(
i
);
for
(
BlockNode
s
:
b
.
getCleanSuccessors
())
{
int
id
=
s
.
getId
();
if
(
domsOn
.
get
(
id
))
{
domsOn
.
clear
(
id
);
}
domsOn
.
clear
(
s
.
getId
());
}
}
outCount
=
domsOn
.
cardinality
();
...
...
@@ -658,19 +656,27 @@ public class RegionMaker {
if
(
outCount
==
1
)
{
out
=
mth
.
getBasicBlocks
().
get
(
domsOn
.
nextSetBit
(
0
));
}
else
if
(
outCount
==
0
)
{
// default and out blocks are same
out
=
defCase
;
// one or several case blocks are empty,
// run expensive algorithm for find 'out' block
for
(
BlockNode
maybeOut
:
block
.
getSuccessors
())
{
boolean
allReached
=
true
;
for
(
BlockNode
s
:
block
.
getSuccessors
())
{
if
(!
BlockUtils
.
isPathExists
(
s
,
maybeOut
))
{
allReached
=
false
;
break
;
}
}
if
(
allReached
)
{
out
=
maybeOut
;
break
;
}
}
}
stack
.
push
(
sw
);
if
(
out
!=
null
)
{
stack
.
addExit
(
out
);
}
// else {
// for (BlockNode e : BlockUtils.bitSetToBlocks(mth, domsOn)) {
// stack.addExit(e);
// }
// }
if
(!
stack
.
containsExit
(
defCase
))
{
sw
.
setDefaultCase
(
makeRegion
(
defCase
,
stack
));
...
...
jadx-core/src/main/java/jadx/core/utils/BlockUtils.java
View file @
37857e88
...
...
@@ -203,10 +203,7 @@ public class BlockUtils {
}
public
static
boolean
isPathExists
(
BlockNode
start
,
BlockNode
end
)
{
if
(
start
==
end
)
{
return
true
;
}
if
(
end
.
isDominator
(
start
))
{
if
(
start
==
end
||
end
.
isDominator
(
start
))
{
return
true
;
}
return
traverseSuccessorsUntil
(
start
,
end
,
new
BitSet
());
...
...
jadx-core/src/test/java/jadx/tests/internal/TestSwitch.java
→
jadx-core/src/test/java/jadx/tests/internal/
switches/
TestSwitch.java
View file @
37857e88
package
jadx
.
tests
.
internal
;
package
jadx
.
tests
.
internal
.
switches
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
...
...
@@ -6,6 +6,7 @@ import jadx.core.dex.nodes.ClassNode;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestSwitch
extends
InternalJadxTest
{
...
...
@@ -45,5 +46,9 @@ public class TestSwitch extends InternalJadxTest {
assertThat
(
code
,
containsString
(
"case '/':"
));
assertThat
(
code
,
containsString
(
indent
(
5
)
+
"break;"
));
assertThat
(
code
,
containsString
(
indent
(
4
)
+
"default:"
));
assertEquals
(
1
,
count
(
code
,
"i++"
));
assertEquals
(
4
,
count
(
code
,
"break;"
));
}
}
jadx-core/src/test/java/jadx/tests/internal/TestSwitchLabels.java
→
jadx-core/src/test/java/jadx/tests/internal/
switches/
TestSwitchLabels.java
View file @
37857e88
package
jadx
.
tests
.
internal
;
package
jadx
.
tests
.
internal
.
switches
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
...
...
jadx-core/src/test/java/jadx/tests/internal/switches/TestSwitchNoDefault.java
0 → 100644
View file @
37857e88
package
jadx
.
tests
.
internal
.
switches
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
public
class
TestSwitchNoDefault
extends
InternalJadxTest
{
public
static
class
TestCls
{
public
void
test
(
int
a
)
{
String
s
=
null
;
switch
(
a
)
{
case
1
:
s
=
"1"
;
break
;
case
2
:
s
=
"2"
;
break
;
case
3
:
s
=
"3"
;
break
;
case
4
:
s
=
"4"
;
break
;
}
System
.
out
.
println
(
s
);
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertEquals
(
4
,
count
(
code
,
"break;"
));
assertEquals
(
1
,
count
(
code
,
"System.out.println(s);"
));
}
}
jadx-core/src/test/java/jadx/tests/internal/switches/TestSwitchSimple.java
0 → 100644
View file @
37857e88
package
jadx
.
tests
.
internal
.
switches
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
hamcrest
.
CoreMatchers
.
not
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestSwitchSimple
extends
InternalJadxTest
{
public
static
class
TestCls
{
public
void
test
(
int
a
)
{
String
s
=
null
;
switch
(
a
%
4
)
{
case
1
:
s
=
"1"
;
break
;
case
2
:
s
=
"2"
;
break
;
case
3
:
s
=
"3"
;
break
;
case
4
:
s
=
"4"
;
break
;
default
:
System
.
out
.
println
(
"Not Reach"
);
break
;
}
System
.
out
.
println
(
s
);
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertEquals
(
5
,
count
(
code
,
"break;"
));
assertEquals
(
1
,
count
(
code
,
"System.out.println(s);"
));
assertEquals
(
1
,
count
(
code
,
"System.out.println(\"Not Reach\");"
));
assertThat
(
code
,
not
(
containsString
(
"switch ((a % 4)) {"
)));
assertThat
(
code
,
containsString
(
"switch (a % 4) {"
));
}
}
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