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
0a36bfb0
Commit
0a36bfb0
authored
May 24, 2014
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: fix try-catch blocks processing
parent
0d94af09
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
135 additions
and
74 deletions
+135
-74
Jadx.java
jadx-core/src/main/java/jadx/core/Jadx.java
+4
-4
ProcessClass.java
jadx-core/src/main/java/jadx/core/ProcessClass.java
+0
-3
RegisterArg.java
...ain/java/jadx/core/dex/instructions/args/RegisterArg.java
+7
-0
SSAVar.java
...src/main/java/jadx/core/dex/instructions/args/SSAVar.java
+5
-1
ClassNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
+1
-1
MethodNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
+6
-2
LoopRegion.java
...-core/src/main/java/jadx/core/dex/regions/LoopRegion.java
+1
-1
ClassModifier.java
...e/src/main/java/jadx/core/dex/visitors/ClassModifier.java
+2
-3
ModVisitor.java
...core/src/main/java/jadx/core/dex/visitors/ModVisitor.java
+2
-2
PrepareForCodeGen.java
...c/main/java/jadx/core/dex/visitors/PrepareForCodeGen.java
+10
-0
ProcessTryCatchRegions.java
...adx/core/dex/visitors/regions/ProcessTryCatchRegions.java
+3
-3
RegionMaker.java
...main/java/jadx/core/dex/visitors/regions/RegionMaker.java
+0
-5
RegionMakerVisitor.java
...va/jadx/core/dex/visitors/regions/RegionMakerVisitor.java
+4
-3
SSATransform.java
...rc/main/java/jadx/core/dex/visitors/ssa/SSATransform.java
+1
-1
BlockUtils.java
jadx-core/src/main/java/jadx/core/utils/BlockUtils.java
+5
-5
InstructionRemover.java
...ore/src/main/java/jadx/core/utils/InstructionRemover.java
+1
-1
InternalJadxTest.java
jadx-core/src/test/java/jadx/api/InternalJadxTest.java
+37
-37
TestVariablesDefinitions.java
...st/java/jadx/tests/internal/TestVariablesDefinitions.java
+1
-2
TestTryCatch4.java
...test/java/jadx/tests/internal/trycatch/TestTryCatch4.java
+45
-0
No files found.
jadx-core/src/main/java/jadx/core/Jadx.java
View file @
0a36bfb0
...
...
@@ -68,10 +68,6 @@ public class Jadx {
passes
.
add
(
new
ModVisitor
());
passes
.
add
(
new
EnumVisitor
());
if
(
args
.
isCFGOutput
())
{
passes
.
add
(
new
DotGraphVisitor
(
outDir
,
false
));
}
passes
.
add
(
new
CodeShrinker
());
passes
.
add
(
new
RegionMakerVisitor
());
passes
.
add
(
new
IfRegionVisitor
());
...
...
@@ -89,6 +85,10 @@ public class Jadx {
passes
.
add
(
new
MethodInlineVisitor
());
passes
.
add
(
new
ClassModifier
());
passes
.
add
(
new
PrepareForCodeGen
());
if
(
args
.
isCFGOutput
())
{
passes
.
add
(
new
DotGraphVisitor
(
outDir
,
false
));
}
}
passes
.
add
(
new
CodeGen
(
args
));
return
passes
;
...
...
jadx-core/src/main/java/jadx/core/ProcessClass.java
View file @
0a36bfb0
...
...
@@ -3,7 +3,6 @@ package jadx.core;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.visitors.DepthTraversal
;
import
jadx.core.dex.visitors.IDexTreeVisitor
;
import
jadx.core.utils.exceptions.DecodeException
;
import
java.util.List
;
...
...
@@ -22,8 +21,6 @@ public final class ProcessClass {
for
(
IDexTreeVisitor
visitor
:
passes
)
{
DepthTraversal
.
visit
(
visitor
,
cls
);
}
}
catch
(
DecodeException
e
)
{
LOG
.
error
(
"Decode exception: "
+
cls
,
e
);
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Class process exception: "
+
cls
,
e
);
}
finally
{
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java
View file @
0a36bfb0
...
...
@@ -66,6 +66,13 @@ public class RegisterArg extends InsnArg implements Named {
return
name
;
}
public
boolean
isNameEquals
(
InsnArg
arg
)
{
if
(
name
==
null
||
!(
arg
instanceof
Named
))
{
return
false
;
}
return
name
.
equals
(((
Named
)
arg
).
getName
());
}
public
void
setName
(
String
newName
)
{
this
.
name
=
newName
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java
View file @
0a36bfb0
...
...
@@ -47,6 +47,10 @@ public class SSAVar {
return
useList
;
}
public
int
getUseCount
()
{
return
useList
.
size
();
}
public
void
use
(
RegisterArg
arg
)
{
mergeName
(
arg
);
if
(
arg
.
getSVar
()
!=
null
)
{
...
...
@@ -81,7 +85,7 @@ public class SSAVar {
if
(!
isUsedInPhi
())
{
return
useList
.
size
();
}
return
useList
.
size
()
+
usedInPhi
.
getResult
().
getSVar
().
getUse
List
().
size
();
return
useList
.
size
()
+
usedInPhi
.
getResult
().
getSVar
().
getUse
Count
();
}
public
ArgType
getType
()
{
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
View file @
0a36bfb0
...
...
@@ -205,7 +205,7 @@ public class ClassNode extends LineAttrNode implements ILoadable {
}
@Override
public
void
load
()
throws
DecodeException
{
public
void
load
()
{
for
(
MethodNode
mth
:
getMethods
())
{
try
{
mth
.
load
();
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
View file @
0a36bfb0
...
...
@@ -446,8 +446,12 @@ public class MethodNode extends LineAttrNode implements ILoadable {
return
handler
;
}
public
List
<
ExceptionHandler
>
getExceptionHandlers
()
{
return
Collections
.
unmodifiableList
(
exceptionHandlers
);
public
Iterable
<
ExceptionHandler
>
getExceptionHandlers
()
{
return
exceptionHandlers
;
}
public
boolean
isNoExceptionHandlers
()
{
return
exceptionHandlers
.
isEmpty
();
}
/**
...
...
jadx-core/src/main/java/jadx/core/dex/regions/LoopRegion.java
View file @
0a36bfb0
...
...
@@ -79,7 +79,7 @@ public final class LoopRegion extends AbstractRegion {
return
false
;
}
else
{
RegisterArg
res
=
insn
.
getResult
();
if
(
res
.
getSVar
().
getUse
List
().
size
()
>
1
)
{
if
(
res
.
getSVar
().
getUse
Count
()
>
1
)
{
return
false
;
}
boolean
found
=
false
;
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ClassModifier.java
View file @
0a36bfb0
...
...
@@ -99,11 +99,10 @@ public class ClassModifier extends AbstractVisitor {
mth
.
removeFirstArgument
();
InstructionRemover
.
remove
(
mth
,
block
,
insn
);
// other arg usage -> wrap with IGET insn
List
<
RegisterArg
>
useList
=
arg
.
getSVar
().
getUseList
();
if
(
useList
.
size
()
>
0
)
{
if
(
arg
.
getSVar
().
getUseCount
()
!=
0
)
{
InsnNode
iget
=
new
IndexInsnNode
(
InsnType
.
IGET
,
fieldInfo
,
1
);
iget
.
addArg
(
insn
.
getArg
(
1
));
for
(
InsnArg
insnArg
:
useList
)
{
for
(
InsnArg
insnArg
:
arg
.
getSVar
().
getUseList
()
)
{
insnArg
.
wrapInstruction
(
iget
);
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java
View file @
0a36bfb0
...
...
@@ -229,7 +229,7 @@ public class ModVisitor extends AbstractVisitor {
if
(
blockInsns
.
size
()
>
0
)
{
InsnNode
insn
=
blockInsns
.
get
(
0
);
if
(
insn
.
getType
()
==
InsnType
.
MOVE_EXCEPTION
&&
insn
.
getResult
().
getSVar
().
getUse
List
().
isEmpty
()
)
{
&&
insn
.
getResult
().
getSVar
().
getUse
Count
()
==
0
)
{
InstructionRemover
.
remove
(
mth
,
block
,
0
);
}
}
...
...
@@ -257,7 +257,7 @@ public class ModVisitor extends AbstractVisitor {
* In argument not used in other instructions then remove assign instruction.
*/
private
static
void
removeInsnForArg
(
InstructionRemover
remover
,
RegisterArg
arg
)
{
if
(
arg
.
getSVar
().
getUse
List
().
isEmpty
()
if
(
arg
.
getSVar
().
getUse
Count
()
==
0
&&
arg
.
getAssignInsn
()
!=
null
)
{
remover
.
add
(
arg
.
getAssignInsn
());
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/PrepareForCodeGen.java
View file @
0a36bfb0
...
...
@@ -54,6 +54,16 @@ public class PrepareForCodeGen extends AbstractVisitor {
it
.
remove
();
}
break
;
case
MOVE:
// remove redundant moves:
// unused result and same args names (a = a;)
RegisterArg
result
=
insn
.
getResult
();
if
(
result
.
getSVar
().
getUseCount
()
==
0
&&
result
.
isNameEquals
(
insn
.
getArg
(
0
)))
{
it
.
remove
();
}
break
;
}
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java
View file @
0a36bfb0
...
...
@@ -40,7 +40,7 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
private
final
Map
<
BlockNode
,
TryCatchBlock
>
tryBlocksMap
=
new
HashMap
<
BlockNode
,
TryCatchBlock
>(
2
);
public
ProcessTryCatchRegions
(
MethodNode
mth
)
{
if
(
mth
.
isNoCode
()
||
mth
.
getExceptionHandlers
().
isEmpty
())
{
if
(
mth
.
isNoCode
()
||
mth
.
isNoExceptionHandlers
())
{
return
;
}
...
...
@@ -84,7 +84,7 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
TryCatchBlock
prevTB
=
tryBlocksMap
.
put
(
domBlock
,
tb
);
if
(
prevTB
!=
null
)
{
LOG
.
info
(
"!!! TODO merge try blocks in "
+
mth
);
LOG
.
info
(
"!!! TODO
:
merge try blocks in "
+
mth
);
}
}
...
...
@@ -134,7 +134,7 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
}
}
}
if
(
newRegion
.
getSubBlocks
().
size
()
!=
0
)
{
if
(
!
newRegion
.
getSubBlocks
().
isEmpty
()
)
{
if
(
DEBUG
)
{
LOG
.
debug
(
"ProcessTryCatchRegions mark: {}"
,
newRegion
);
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java
View file @
0a36bfb0
...
...
@@ -685,11 +685,6 @@ public class RegionMaker {
LOG
.
debug
(
ErrorsCounter
.
formatErrorMsg
(
mth
,
"No exception handler block: "
+
handler
));
return
;
}
BlockNode
out
=
BlockUtils
.
traverseWhileDominates
(
start
,
start
);
if
(
out
!=
null
)
{
stack
.
addExit
(
out
);
}
// TODO extract finally part which exists in all handlers from same try block
// TODO add blocks common for several handlers to some region
handler
.
setHandlerRegion
(
makeRegion
(
start
,
stack
));
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMakerVisitor.java
View file @
0a36bfb0
...
...
@@ -34,7 +34,7 @@ public class RegionMakerVisitor extends AbstractVisitor {
// fill region structure
mth
.
setRegion
(
rm
.
makeRegion
(
mth
.
getEnterBlock
(),
state
));
if
(!
mth
.
getExceptionHandlers
().
isEmpty
())
{
if
(!
mth
.
isNoExceptionHandlers
())
{
state
=
new
RegionStack
(
mth
);
for
(
ExceptionHandler
handler
:
mth
.
getExceptionHandlers
())
{
rm
.
processExcHandler
(
handler
,
state
);
...
...
@@ -46,8 +46,9 @@ public class RegionMakerVisitor extends AbstractVisitor {
private
static
void
postProcessRegions
(
MethodNode
mth
)
{
// make try-catch regions
DepthRegionTraversal
.
traverse
(
mth
,
new
ProcessTryCatchRegions
(
mth
));
if
(!
mth
.
isNoExceptionHandlers
())
{
DepthRegionTraversal
.
traverse
(
mth
,
new
ProcessTryCatchRegions
(
mth
));
}
// merge conditions in loops
if
(
mth
.
getLoopsCount
()
!=
0
)
{
DepthRegionTraversal
.
traverseAll
(
mth
,
new
AbstractRegionVisitor
()
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java
View file @
0a36bfb0
...
...
@@ -146,7 +146,7 @@ public class SSATransform extends AbstractVisitor {
List
<
PhiInsn
>
insnToRemove
=
new
ArrayList
<
PhiInsn
>();
for
(
SSAVar
var
:
mth
.
getSVars
())
{
// phi result not used
if
(
var
.
getUse
List
().
isEmpty
()
)
{
if
(
var
.
getUse
Count
()
==
0
)
{
InsnNode
assignInsn
=
var
.
getAssign
().
getParentInsn
();
if
(
assignInsn
!=
null
&&
assignInsn
.
getType
()
==
InsnType
.
PHI
)
{
insnToRemove
.
add
((
PhiInsn
)
assignInsn
);
...
...
jadx-core/src/main/java/jadx/core/utils/BlockUtils.java
View file @
0a36bfb0
...
...
@@ -229,14 +229,14 @@ public class BlockUtils {
}
/**
* Search for first node which not dominated by
block, starting from child
* Search for first node which not dominated by
dom, starting from start
*/
public
static
BlockNode
traverseWhileDominates
(
BlockNode
block
,
BlockNode
child
)
{
for
(
BlockNode
node
:
child
.
getCleanSuccessors
())
{
if
(!
node
.
isDominator
(
block
))
{
public
static
BlockNode
traverseWhileDominates
(
BlockNode
dom
,
BlockNode
start
)
{
for
(
BlockNode
node
:
start
.
getCleanSuccessors
())
{
if
(!
node
.
isDominator
(
dom
))
{
return
node
;
}
else
{
BlockNode
out
=
traverseWhileDominates
(
block
,
node
);
BlockNode
out
=
traverseWhileDominates
(
dom
,
node
);
if
(
out
!=
null
)
{
return
out
;
}
...
...
jadx-core/src/main/java/jadx/core/utils/InstructionRemover.java
View file @
0a36bfb0
...
...
@@ -59,7 +59,7 @@ public class InstructionRemover {
public
static
void
unbindInsn
(
MethodNode
mth
,
InsnNode
insn
)
{
RegisterArg
r
=
insn
.
getResult
();
if
(
r
!=
null
&&
r
.
getSVar
()
!=
null
)
{
if
(
Consts
.
DEBUG
&&
!
r
.
getSVar
().
getUseList
().
isEmpty
()
)
{
if
(
Consts
.
DEBUG
&&
r
.
getSVar
().
getUseCount
()
!=
0
)
{
LOG
.
debug
(
"Unbind insn with result: {}"
,
insn
);
}
mth
.
removeSVar
(
r
.
getSVar
());
...
...
jadx-core/src/test/java/jadx/api/InternalJadxTest.java
View file @
0a36bfb0
package
jadx
.
api
;
import
jadx.core.Jadx
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.visitors.DepthTraversal
;
...
...
@@ -23,6 +25,7 @@ import static org.hamcrest.CoreMatchers.not;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
fail
;
public
abstract
class
InternalJadxTest
extends
TestUtils
{
...
...
@@ -33,48 +36,45 @@ public abstract class InternalJadxTest extends TestUtils {
protected
String
outDir
=
"test-out-tmp"
;
public
ClassNode
getClassNode
(
Class
<?>
clazz
)
{
Decompiler
d
=
new
Decompiler
();
try
{
File
temp
=
getJarForClass
(
clazz
);
Decompiler
d
=
new
Decompiler
();
try
{
d
.
loadFile
(
temp
);
}
catch
(
Exception
e
)
{
fail
(
e
.
getMessage
());
}
List
<
ClassNode
>
classes
=
d
.
getRoot
().
getClasses
(
false
);
String
clsName
=
clazz
.
getName
();
ClassNode
cls
=
null
;
for
(
ClassNode
aClass
:
classes
)
{
if
(
aClass
.
getFullName
().
equals
(
clsName
))
{
cls
=
aClass
;
}
}
assertNotNull
(
"Class not found: "
+
clsName
,
cls
);
d
.
loadFile
(
getJarForClass
(
clazz
));
}
catch
(
Exception
e
)
{
fail
(
e
.
getMessage
());
}
String
clsName
=
clazz
.
getName
();
ClassNode
cls
=
d
.
getRoot
().
searchClassByName
(
clsName
);
assertNotNull
(
"Class not found: "
+
clsName
,
cls
);
assertEquals
(
cls
.
getFullName
(),
clazz
.
getName
());
cls
.
load
();
for
(
IDexTreeVisitor
visitor
:
getPasses
())
{
DepthTraversal
.
visit
(
visitor
,
cls
);
}
// don't unload class
assertEquals
(
cls
.
getFullName
(),
clazz
.
getName
());
assertTrue
(
"Inconsistent cls: "
+
cls
,
!
cls
.
contains
(
AFlag
.
INCONSISTENT_CODE
)
&&
!
cls
.
contains
(
AType
.
JADX_ERROR
));
for
(
MethodNode
mthNode
:
cls
.
getMethods
())
{
assertTrue
(
"Inconsistent method: "
+
mthNode
,
!
mthNode
.
contains
(
AFlag
.
INCONSISTENT_CODE
)
&&
!
mthNode
.
contains
(
AType
.
JADX_ERROR
));
}
assertThat
(
cls
.
getCode
().
toString
(),
not
(
containsString
(
"inconsistent"
)));
return
cls
;
}
cls
.
load
();
List
<
IDexTreeVisitor
>
passes
=
Jadx
.
getPassesList
(
new
DefaultJadxArgs
()
{
@Override
public
boolean
isCFGOutput
()
{
return
outputCFG
;
}
protected
List
<
IDexTreeVisitor
>
getPasses
()
{
return
Jadx
.
getPassesList
(
new
DefaultJadxArgs
()
{
@Override
public
boolean
isCFGOutput
()
{
return
outputCFG
;
}
@Override
public
boolean
isRawCFGOutput
()
{
return
outputCFG
;
}
},
new
File
(
outDir
));
for
(
IDexTreeVisitor
visitor
:
passes
)
{
DepthTraversal
.
visit
(
visitor
,
cls
);
@Override
public
boolean
isRawCFGOutput
()
{
return
outputCFG
;
}
assertThat
(
cls
.
getCode
().
toString
(),
not
(
containsString
(
"inconsistent"
)));
return
cls
;
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
fail
(
e
.
getMessage
());
return
null
;
}
},
new
File
(
outDir
));
}
protected
MethodNode
getMethod
(
ClassNode
cls
,
String
method
)
{
...
...
jadx-core/src/test/java/jadx/tests/internal/TestVariablesDefinitions.java
View file @
0a36bfb0
...
...
@@ -4,7 +4,6 @@ import jadx.api.InternalJadxTest;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.visitors.DepthTraversal
;
import
jadx.core.dex.visitors.IDexTreeVisitor
;
import
jadx.core.utils.exceptions.DecodeException
;
import
java.util.Iterator
;
import
java.util.List
;
...
...
@@ -30,7 +29,7 @@ public class TestVariablesDefinitions extends InternalJadxTest {
while
(
iterator
.
hasNext
())
{
DepthTraversal
.
visit
(
iterator
.
next
(),
cls
);
}
}
catch
(
Decode
Exception
e
)
{
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Decode exception: "
+
cls
,
e
);
}
}
...
...
jadx-core/src/test/java/jadx/tests/internal/trycatch/TestTryCatch4.java
0 → 100644
View file @
0a36bfb0
package
jadx
.
tests
.
internal
.
trycatch
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
java.io.File
;
import
java.io.FileNotFoundException
;
import
java.io.FileOutputStream
;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
hamcrest
.
CoreMatchers
.
not
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestTryCatch4
extends
InternalJadxTest
{
public
static
class
TestCls
{
private
Object
test
(
Object
obj
)
{
FileOutputStream
output
=
null
;
try
{
output
=
new
FileOutputStream
(
new
File
(
"f"
));
return
new
Object
();
}
catch
(
FileNotFoundException
e
)
{
System
.
out
.
println
(
"Exception"
);
return
null
;
}
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsString
(
"try {"
));
assertThat
(
code
,
containsString
(
"output = new FileOutputStream(new File(\"f\"));"
));
assertThat
(
code
,
containsString
(
"return new Object();"
));
assertThat
(
code
,
containsString
(
"} catch (FileNotFoundException e) {"
));
assertThat
(
code
,
containsString
(
"System.out.println(\"Exception\");"
));
assertThat
(
code
,
containsString
(
"return null;"
));
assertThat
(
code
,
not
(
containsString
(
"output = output;"
)));
}
}
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