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
c8923950
Commit
c8923950
authored
Feb 04, 2019
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: redone finally extract
parent
4ce5cc84
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
62 changed files
with
1073 additions
and
1225 deletions
+1073
-1225
Jadx.java
jadx-core/src/main/java/jadx/core/Jadx.java
+6
-4
InsnGen.java
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
+0
-1
NameGen.java
jadx-core/src/main/java/jadx/core/codegen/NameGen.java
+13
-0
RegionGen.java
jadx-core/src/main/java/jadx/core/codegen/RegionGen.java
+8
-1
AFlag.java
jadx-core/src/main/java/jadx/core/dex/attributes/AFlag.java
+5
-3
PhiListAttr.java
...main/java/jadx/core/dex/attributes/nodes/PhiListAttr.java
+3
-0
RegDebugInfoAttr.java
...java/jadx/core/dex/attributes/nodes/RegDebugInfoAttr.java
+1
-1
FillArrayNode.java
...c/main/java/jadx/core/dex/instructions/FillArrayNode.java
+20
-17
InsnDecoder.java
...src/main/java/jadx/core/dex/instructions/InsnDecoder.java
+2
-5
InsnType.java
...re/src/main/java/jadx/core/dex/instructions/InsnType.java
+0
-3
PhiInsn.java
...ore/src/main/java/jadx/core/dex/instructions/PhiInsn.java
+1
-0
ArgType.java
...rc/main/java/jadx/core/dex/instructions/args/ArgType.java
+2
-0
CodeVar.java
...rc/main/java/jadx/core/dex/instructions/args/CodeVar.java
+9
-6
SSAVar.java
...src/main/java/jadx/core/dex/instructions/args/SSAVar.java
+1
-0
IfCondition.java
...in/java/jadx/core/dex/regions/conditions/IfCondition.java
+4
-2
IfRegion.java
.../main/java/jadx/core/dex/regions/conditions/IfRegion.java
+5
-9
LoopRegion.java
...src/main/java/jadx/core/dex/regions/loops/LoopRegion.java
+4
-8
CodeShrinker.java
...re/src/main/java/jadx/core/dex/visitors/CodeShrinker.java
+8
-0
ConstInlineVisitor.java
.../main/java/jadx/core/dex/visitors/ConstInlineVisitor.java
+35
-4
DotGraphVisitor.java
...src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java
+3
-3
InitCodeVariables.java
...c/main/java/jadx/core/dex/visitors/InitCodeVariables.java
+87
-0
MarkFinallyVisitor.java
.../main/java/jadx/core/dex/visitors/MarkFinallyVisitor.java
+435
-0
ModVisitor.java
...core/src/main/java/jadx/core/dex/visitors/ModVisitor.java
+0
-1
PrepareForCodeGen.java
...c/main/java/jadx/core/dex/visitors/PrepareForCodeGen.java
+3
-0
SimplifyVisitor.java
...src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java
+12
-1
BlockExceptionHandler.java
.../core/dex/visitors/blocksmaker/BlockExceptionHandler.java
+11
-13
BlockFinallyExtract.java
...dx/core/dex/visitors/blocksmaker/BlockFinallyExtract.java
+0
-821
BlockProcessor.java
...va/jadx/core/dex/visitors/blocksmaker/BlockProcessor.java
+2
-5
BlocksPair.java
...adx/core/dex/visitors/blocksmaker/helpers/BlocksPair.java
+0
-43
BlocksRemoveInfo.java
...re/dex/visitors/blocksmaker/helpers/BlocksRemoveInfo.java
+0
-122
FinallyExtractInfo.java
.../dex/visitors/blocksmaker/helpers/FinallyExtractInfo.java
+48
-0
InsnsSlice.java
...adx/core/dex/visitors/blocksmaker/helpers/InsnsSlice.java
+72
-0
DebugInfoApplyVisitor.java
...dx/core/dex/visitors/debuginfo/DebugInfoApplyVisitor.java
+1
-3
CheckRegions.java
...ain/java/jadx/core/dex/visitors/regions/CheckRegions.java
+1
-0
CleanRegions.java
...ain/java/jadx/core/dex/visitors/regions/CleanRegions.java
+39
-16
IfMakerHelper.java
...in/java/jadx/core/dex/visitors/regions/IfMakerHelper.java
+7
-3
LoopRegionVisitor.java
...ava/jadx/core/dex/visitors/regions/LoopRegionVisitor.java
+2
-1
ProcessTryCatchRegions.java
...adx/core/dex/visitors/regions/ProcessTryCatchRegions.java
+0
-5
RegionMaker.java
...main/java/jadx/core/dex/visitors/regions/RegionMaker.java
+8
-5
RegionMakerVisitor.java
...va/jadx/core/dex/visitors/regions/RegionMakerVisitor.java
+59
-59
SSATransform.java
...rc/main/java/jadx/core/dex/visitors/ssa/SSATransform.java
+12
-3
TypeCompare.java
...ava/jadx/core/dex/visitors/typeinference/TypeCompare.java
+3
-0
TypeInferenceVisitor.java
...core/dex/visitors/typeinference/TypeInferenceVisitor.java
+3
-1
TypeUpdate.java
...java/jadx/core/dex/visitors/typeinference/TypeUpdate.java
+0
-1
DebugUtils.java
jadx-core/src/main/java/jadx/core/utils/DebugUtils.java
+2
-2
TypeCompareTest.java
...jadx/core/dex/visitors/typeinference/TypeCompareTest.java
+3
-0
IntegrationTest.java
jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java
+7
-19
TestUtils.java
jadx-core/src/test/java/jadx/tests/api/utils/TestUtils.java
+4
-1
TestFieldIncrement2.java
...ava/jadx/tests/integration/arith/TestFieldIncrement2.java
+3
-3
TestTernary2.java
.../java/jadx/tests/integration/conditions/TestTernary2.java
+8
-4
TestEnums4.java
...rc/test/java/jadx/tests/integration/enums/TestEnums4.java
+3
-3
TestGenerics2.java
...t/java/jadx/tests/integration/generics/TestGenerics2.java
+3
-3
TestFinallyExtract.java
...a/jadx/tests/integration/trycatch/TestFinallyExtract.java
+46
-6
TestTryCatch7.java
...t/java/jadx/tests/integration/trycatch/TestTryCatch7.java
+12
-2
TestTryCatch8.java
...t/java/jadx/tests/integration/trycatch/TestTryCatch8.java
+14
-4
TestTryCatchFinally6.java
...jadx/tests/integration/trycatch/TestTryCatchFinally6.java
+24
-0
TestTryCatchFinally7.java
...jadx/tests/integration/trycatch/TestTryCatchFinally7.java
+1
-1
TestTryCatchFinally8.java
...jadx/tests/integration/trycatch/TestTryCatchFinally8.java
+3
-2
TestTryCatchNoMoveExc.java
...adx/tests/integration/trycatch/TestTryCatchNoMoveExc.java
+2
-2
TestTryCatchNoMoveExc2.java
...dx/tests/integration/trycatch/TestTryCatchNoMoveExc2.java
+1
-1
TestTryCatchNoMoveExc.smali
...-core/src/test/smali/trycatch/TestTryCatchNoMoveExc.smali
+1
-1
TestTryCatchNoMoveExc2.smali
...core/src/test/smali/trycatch/TestTryCatchNoMoveExc2.smali
+1
-1
No files found.
jadx-core/src/main/java/jadx/core/Jadx.java
View file @
c8923950
...
...
@@ -20,6 +20,8 @@ import jadx.core.dex.visitors.EnumVisitor;
import
jadx.core.dex.visitors.ExtractFieldInit
;
import
jadx.core.dex.visitors.FallbackModeVisitor
;
import
jadx.core.dex.visitors.IDexTreeVisitor
;
import
jadx.core.dex.visitors.InitCodeVariables
;
import
jadx.core.dex.visitors.MarkFinallyVisitor
;
import
jadx.core.dex.visitors.MethodInlineVisitor
;
import
jadx.core.dex.visitors.ModVisitor
;
import
jadx.core.dex.visitors.PrepareForCodeGen
;
...
...
@@ -27,19 +29,18 @@ import jadx.core.dex.visitors.ReSugarCode;
import
jadx.core.dex.visitors.RenameVisitor
;
import
jadx.core.dex.visitors.SimplifyVisitor
;
import
jadx.core.dex.visitors.blocksmaker.BlockExceptionHandler
;
import
jadx.core.dex.visitors.blocksmaker.BlockFinallyExtract
;
import
jadx.core.dex.visitors.blocksmaker.BlockFinish
;
import
jadx.core.dex.visitors.blocksmaker.BlockProcessor
;
import
jadx.core.dex.visitors.blocksmaker.BlockSplitter
;
import
jadx.core.dex.visitors.debuginfo.DebugInfoApplyVisitor
;
import
jadx.core.dex.visitors.debuginfo.DebugInfoParseVisitor
;
import
jadx.core.dex.visitors.regions.CheckRegions
;
import
jadx.core.dex.visitors.regions.CleanRegions
;
import
jadx.core.dex.visitors.regions.IfRegionVisitor
;
import
jadx.core.dex.visitors.regions.LoopRegionVisitor
;
import
jadx.core.dex.visitors.regions.RegionMakerVisitor
;
import
jadx.core.dex.visitors.regions.ReturnVisitor
;
import
jadx.core.dex.visitors.regions.variables.ProcessVariables
;
import
jadx.core.dex.visitors.ssa.EliminatePhiNodes
;
import
jadx.core.dex.visitors.ssa.SSATransform
;
import
jadx.core.dex.visitors.typeinference.TypeInferenceVisitor
;
...
...
@@ -68,14 +69,14 @@ public class Jadx {
passes
.
add
(
new
BlockProcessor
());
passes
.
add
(
new
BlockExceptionHandler
());
passes
.
add
(
new
BlockFinallyExtract
());
passes
.
add
(
new
BlockFinish
());
passes
.
add
(
new
SSATransform
());
passes
.
add
(
new
ConstructorVisitor
());
passes
.
add
(
new
InitCodeVariables
());
passes
.
add
(
new
MarkFinallyVisitor
());
passes
.
add
(
new
ConstInlineVisitor
());
passes
.
add
(
new
TypeInferenceVisitor
());
passes
.
add
(
new
EliminatePhiNodes
());
passes
.
add
(
new
DebugInfoApplyVisitor
());
passes
.
add
(
new
ModVisitor
());
...
...
@@ -88,6 +89,7 @@ public class Jadx {
passes
.
add
(
new
RegionMakerVisitor
());
passes
.
add
(
new
IfRegionVisitor
());
passes
.
add
(
new
ReturnVisitor
());
passes
.
add
(
new
CleanRegions
());
passes
.
add
(
new
CodeShrinker
());
passes
.
add
(
new
SimplifyVisitor
());
...
...
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
View file @
c8923950
...
...
@@ -499,7 +499,6 @@ public class InsnGen {
break
;
case
PHI:
case
MERGE:
fallbackOnlyInsn
(
insn
);
code
.
add
(
insn
.
getType
().
toString
()).
add
(
"("
);
for
(
InsnArg
insnArg
:
insn
.
getArguments
())
{
...
...
jadx-core/src/main/java/jadx/core/codegen/NameGen.java
View file @
c8923950
...
...
@@ -19,6 +19,8 @@ import jadx.core.dex.instructions.args.NamedArg;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.instructions.args.SSAVar
;
import
jadx.core.dex.instructions.mods.ConstructorInsn
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.FieldNode
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.utils.StringUtils
;
...
...
@@ -55,6 +57,17 @@ public class NameGen {
public
NameGen
(
MethodNode
mth
,
boolean
fallback
)
{
this
.
mth
=
mth
;
this
.
fallback
=
fallback
;
addNamesUsedInClass
();
}
private
void
addNamesUsedInClass
()
{
ClassNode
parentClass
=
mth
.
getParentClass
();
for
(
FieldNode
field
:
parentClass
.
getFields
())
{
varNames
.
add
(
field
.
getAlias
());
}
for
(
ClassNode
innerClass
:
parentClass
.
getInnerClasses
())
{
varNames
.
add
(
innerClass
.
getAlias
().
getShortName
());
}
}
public
String
assignArg
(
CodeVar
var
)
{
...
...
jadx-core/src/main/java/jadx/core/codegen/RegionGen.java
View file @
c8923950
...
...
@@ -3,6 +3,7 @@ package jadx.core.codegen;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Objects
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -36,6 +37,7 @@ import jadx.core.dex.regions.loops.ForLoop;
import
jadx.core.dex.regions.loops.LoopRegion
;
import
jadx.core.dex.regions.loops.LoopType
;
import
jadx.core.dex.trycatch.ExceptionHandler
;
import
jadx.core.utils.BlockUtils
;
import
jadx.core.utils.ErrorsCounter
;
import
jadx.core.utils.RegionUtils
;
import
jadx.core.utils.exceptions.CodegenException
;
...
...
@@ -98,6 +100,10 @@ public class RegionGen extends InsnGen {
}
private
void
makeSimpleBlock
(
IBlock
block
,
CodeWriter
code
)
throws
CodegenException
{
if
(
block
.
contains
(
AFlag
.
DONT_GENERATE
))
{
return
;
}
for
(
InsnNode
insn
:
block
.
getInstructions
())
{
if
(!
insn
.
contains
(
AFlag
.
DONT_GENERATE
))
{
makeInsn
(
insn
,
code
);
...
...
@@ -233,7 +239,8 @@ public class RegionGen extends InsnGen {
}
private
CodeWriter
makeSwitch
(
SwitchRegion
sw
,
CodeWriter
code
)
throws
CodegenException
{
SwitchNode
insn
=
(
SwitchNode
)
sw
.
getHeader
().
getInstructions
().
get
(
0
);
SwitchNode
insn
=
(
SwitchNode
)
BlockUtils
.
getLastInsn
(
sw
.
getHeader
());
Objects
.
requireNonNull
(
insn
,
"Switch insn not found in header"
);
InsnArg
arg
=
insn
.
getArg
(
0
);
code
.
startLine
(
"switch ("
);
addArg
(
code
,
arg
,
false
);
...
...
jadx-core/src/main/java/jadx/core/dex/attributes/AFlag.java
View file @
c8923950
...
...
@@ -8,26 +8,28 @@ public enum AFlag {
LOOP_END
,
SYNTHETIC
,
FINAL
,
// SSAVar attribute for make var final
RETURN
,
// block contains only return instruction
ORIG_RETURN
,
DECLARE_VAR
,
DONT_WRAP
,
DONT_INLINE
,
DONT_GENERATE
,
// process as usual, but don't output to generated code
REMOVE
,
// can be completely removed
ADDED_TO_REGION
,
FINALLY_INSNS
,
SKIP_FIRST_ARG
,
SKIP_ARG
,
// skip argument in invoke call
ANONYMOUS_CONSTRUCTOR
,
ANONYMOUS_CLASS
,
THIS
,
METHOD_ARGUMENT
,
// RegisterArg attribute for method arguments
CUSTOM_DECLARE
,
// variable for this register don't need declaration
DECLARE_VAR
,
ELSE_IF_CHAIN
,
...
...
jadx-core/src/main/java/jadx/core/dex/attributes/nodes/PhiListAttr.java
View file @
c8923950
...
...
@@ -27,6 +27,9 @@ public class PhiListAttr implements IAttribute {
for
(
PhiInsn
phiInsn
:
list
)
{
sb
.
append
(
'r'
).
append
(
phiInsn
.
getResult
().
getRegNum
()).
append
(
" "
);
}
for
(
PhiInsn
phiInsn
:
list
)
{
sb
.
append
(
"\n "
).
append
(
phiInsn
).
append
(
" "
).
append
(
phiInsn
.
getAttributesString
());
}
return
sb
.
toString
();
}
}
jadx-core/src/main/java/jadx/core/dex/attributes/nodes/RegDebugInfoAttr.java
View file @
c8923950
...
...
@@ -30,7 +30,7 @@ public class RegDebugInfoAttr implements IAttribute {
}
@Override
public
AType
getType
()
{
public
AType
<
RegDebugInfoAttr
>
getType
()
{
return
AType
.
REG_DEBUG_INFO
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/FillArrayNode.java
View file @
c8923950
...
...
@@ -15,35 +15,38 @@ import jadx.core.utils.exceptions.JadxRuntimeException;
public
final
class
FillArrayNode
extends
InsnNode
{
private
static
final
ArgType
ONE_BYTE_TYPE
=
ArgType
.
unknown
(
PrimitiveType
.
BOOLEAN
,
PrimitiveType
.
BYTE
);
private
static
final
ArgType
TWO_BYTES_TYPE
=
ArgType
.
unknown
(
PrimitiveType
.
SHORT
,
PrimitiveType
.
CHAR
);
private
static
final
ArgType
FOUR_BYTES_TYPE
=
ArgType
.
unknown
(
PrimitiveType
.
INT
,
PrimitiveType
.
FLOAT
);
private
static
final
ArgType
EIGHT_BYTES_TYPE
=
ArgType
.
unknown
(
PrimitiveType
.
LONG
,
PrimitiveType
.
DOUBLE
);
private
final
Object
data
;
private
final
int
size
;
private
ArgType
elemType
;
public
FillArrayNode
(
int
resReg
,
FillArrayDataPayloadDecodedInstruction
payload
)
{
super
(
InsnType
.
FILL_ARRAY
,
1
);
ArgType
elType
;
switch
(
payload
.
getElementWidthUnit
())
{
ArgType
elType
=
getElementType
(
payload
.
getElementWidthUnit
());
addArg
(
InsnArg
.
reg
(
resReg
,
ArgType
.
array
(
elType
)));
this
.
data
=
payload
.
getData
();
this
.
size
=
payload
.
getSize
();
this
.
elemType
=
elType
;
}
private
static
ArgType
getElementType
(
short
elementWidthUnit
)
{
switch
(
elementWidthUnit
)
{
case
1
:
elType
=
ArgType
.
unknown
(
PrimitiveType
.
BOOLEAN
,
PrimitiveType
.
BYTE
);
break
;
return
ONE_BYTE_TYPE
;
case
2
:
elType
=
ArgType
.
unknown
(
PrimitiveType
.
SHORT
,
PrimitiveType
.
CHAR
);
break
;
return
TWO_BYTES_TYPE
;
case
4
:
elType
=
ArgType
.
unknown
(
PrimitiveType
.
INT
,
PrimitiveType
.
FLOAT
);
break
;
return
FOUR_BYTES_TYPE
;
case
8
:
elType
=
ArgType
.
unknown
(
PrimitiveType
.
LONG
,
PrimitiveType
.
DOUBLE
);
break
;
return
EIGHT_BYTES_TYPE
;
default
:
throw
new
JadxRuntimeException
(
"Unknown array element width: "
+
payload
.
getElementWidthUnit
()
);
throw
new
JadxRuntimeException
(
"Unknown array element width: "
+
elementWidthUnit
);
}
addArg
(
InsnArg
.
reg
(
resReg
,
ArgType
.
array
(
elType
)));
this
.
data
=
payload
.
getData
();
this
.
size
=
payload
.
getSize
();
this
.
elemType
=
elType
;
}
public
Object
getData
()
{
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java
View file @
c8923950
...
...
@@ -19,7 +19,6 @@ import jadx.core.dex.info.MethodInfo;
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.instructions.args.RegisterArg
;
import
jadx.core.dex.nodes.DexNode
;
import
jadx.core.dex.nodes.FieldNode
;
...
...
@@ -405,12 +404,10 @@ public class InsnDecoder {
return
new
GotoNode
(
insn
.
getTarget
());
case
Opcodes
.
THROW
:
return
insn
(
InsnType
.
THROW
,
null
,
InsnArg
.
reg
(
insn
,
0
,
ArgType
.
unknown
(
PrimitiveType
.
OBJECT
)));
return
insn
(
InsnType
.
THROW
,
null
,
InsnArg
.
reg
(
insn
,
0
,
ArgType
.
THROWABLE
));
case
Opcodes
.
MOVE_EXCEPTION
:
return
insn
(
InsnType
.
MOVE_EXCEPTION
,
InsnArg
.
reg
(
insn
,
0
,
ArgType
.
unknown
(
PrimitiveType
.
OBJECT
)));
return
insn
(
InsnType
.
MOVE_EXCEPTION
,
InsnArg
.
reg
(
insn
,
0
,
ArgType
.
UNKNOWN_OBJECT_NO_ARRAY
));
case
Opcodes
.
RETURN_VOID
:
return
new
InsnNode
(
InsnType
.
RETURN
,
0
);
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/InsnType.java
View file @
c8923950
...
...
@@ -66,9 +66,6 @@ public enum InsnType {
ONE_ARG
,
PHI
,
// merge all arguments in one
MERGE
,
// TODO: now multidimensional arrays created using Array.newInstance function
NEW_MULTIDIM_ARRAY
}
jadx-core/src/main/java/jadx/core/dex/instructions/PhiInsn.java
View file @
c8923950
...
...
@@ -24,6 +24,7 @@ public final class PhiInsn extends InsnNode {
this
.
blockBinds
=
new
LinkedHashMap
<>(
predecessors
);
setResult
(
InsnArg
.
reg
(
regNum
,
ArgType
.
UNKNOWN
));
add
(
AFlag
.
DONT_INLINE
);
add
(
AFlag
.
DONT_GENERATE
);
}
public
RegisterArg
bindArg
(
BlockNode
pred
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java
View file @
c8923950
...
...
@@ -30,6 +30,8 @@ public abstract class ArgType {
public
static
final
ArgType
UNKNOWN
=
unknown
(
PrimitiveType
.
values
());
public
static
final
ArgType
UNKNOWN_OBJECT
=
unknown
(
PrimitiveType
.
OBJECT
,
PrimitiveType
.
ARRAY
);
public
static
final
ArgType
UNKNOWN_OBJECT_NO_ARRAY
=
unknown
(
PrimitiveType
.
OBJECT
);
public
static
final
ArgType
UNKNOWN_ARRAY
=
array
(
UNKNOWN
);
public
static
final
ArgType
NARROW
=
unknown
(
PrimitiveType
.
INT
,
PrimitiveType
.
FLOAT
,
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/args/CodeVar.java
View file @
c8923950
package
jadx
.
core
.
dex
.
instructions
.
args
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
public
class
CodeVar
{
private
String
name
;
private
ArgType
type
;
private
List
<
SSAVar
>
ssaVars
;
private
List
<
SSAVar
>
ssaVars
=
new
ArrayList
<>(
3
)
;
private
boolean
isFinal
;
private
boolean
isThis
;
...
...
@@ -42,13 +43,15 @@ public class CodeVar {
return
ssaVars
;
}
public
void
addSsaVar
(
SSAVar
ssaVar
)
{
if
(!
ssaVars
.
contains
(
ssaVar
))
{
ssaVars
.
add
(
ssaVar
);
}
}
public
void
setSsaVars
(
List
<
SSAVar
>
ssaVars
)
{
if
(
ssaVars
.
size
()
==
1
)
{
this
.
ssaVars
=
Collections
.
singletonList
(
ssaVars
.
get
(
0
));
}
else
{
this
.
ssaVars
=
ssaVars
;
}
}
public
boolean
isFinal
()
{
return
isFinal
;
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java
View file @
c8923950
...
...
@@ -139,6 +139,7 @@ public class SSAVar extends AttrNode {
public
void
setCodeVar
(
@NotNull
CodeVar
codeVar
)
{
this
.
codeVar
=
codeVar
;
codeVar
.
addSsaVar
(
this
);
}
public
boolean
isCodeVarSet
()
{
...
...
jadx-core/src/main/java/jadx/core/dex/regions/conditions/IfCondition.java
View file @
c8923950
...
...
@@ -15,6 +15,7 @@ import jadx.core.dex.instructions.args.LiteralArg;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.utils.BlockUtils
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
public
final
class
IfCondition
{
...
...
@@ -54,10 +55,11 @@ public final class IfCondition {
}
public
static
IfCondition
fromIfBlock
(
BlockNode
header
)
{
if
(
header
==
null
)
{
InsnNode
lastInsn
=
BlockUtils
.
getLastInsn
(
header
);
if
(
lastInsn
==
null
)
{
return
null
;
}
return
fromIfNode
((
IfNode
)
header
.
getInstructions
().
get
(
0
)
);
return
fromIfNode
((
IfNode
)
lastInsn
);
}
public
static
IfCondition
fromIfNode
(
IfNode
insn
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/regions/conditions/IfRegion.java
View file @
c8923950
...
...
@@ -8,8 +8,9 @@ import jadx.core.dex.nodes.BlockNode;
import
jadx.core.dex.nodes.IBranchRegion
;
import
jadx.core.dex.nodes.IContainer
;
import
jadx.core.dex.nodes.IRegion
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.regions.AbstractRegion
;
import
jadx.core.utils.
exceptions.JadxRuntimeException
;
import
jadx.core.utils.
BlockUtils
;
public
final
class
IfRegion
extends
AbstractRegion
implements
IBranchRegion
{
...
...
@@ -21,9 +22,6 @@ public final class IfRegion extends AbstractRegion implements IBranchRegion {
public
IfRegion
(
IRegion
parent
,
BlockNode
header
)
{
super
(
parent
);
if
(
header
.
getInstructions
().
size
()
!=
1
)
{
throw
new
JadxRuntimeException
(
"Expected only one instruction in 'if' header"
);
}
this
.
header
=
header
;
this
.
condition
=
IfCondition
.
fromIfBlock
(
header
);
}
...
...
@@ -74,10 +72,8 @@ public final class IfRegion extends AbstractRegion implements IBranchRegion {
}
public
int
getSourceLine
()
{
if
(
header
.
getInstructions
().
isEmpty
())
{
return
0
;
}
return
header
.
getInstructions
().
get
(
0
).
getSourceLine
();
InsnNode
lastInsn
=
BlockUtils
.
getLastInsn
(
header
);
return
lastInsn
==
null
?
0
:
lastInsn
.
getSourceLine
();
}
@Override
...
...
@@ -130,6 +126,6 @@ public final class IfRegion extends AbstractRegion implements IBranchRegion {
@Override
public
String
toString
()
{
return
"IF "
+
header
+
"
then ("
+
thenRegion
+
") else ("
+
elseRegion
+
")"
;
return
"IF "
+
header
+
"
THEN:"
+
thenRegion
+
" ELSE:"
+
elseRegion
;
}
}
jadx-core/src/main/java/jadx/core/dex/regions/loops/LoopRegion.java
View file @
c8923950
...
...
@@ -15,6 +15,7 @@ import jadx.core.dex.nodes.IRegion;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.regions.AbstractRegion
;
import
jadx.core.dex.regions.conditions.IfCondition
;
import
jadx.core.utils.BlockUtils
;
public
final
class
LoopRegion
extends
AbstractRegion
{
...
...
@@ -76,7 +77,7 @@ public final class LoopRegion extends AbstractRegion {
}
private
IfNode
getIfInsn
()
{
return
(
IfNode
)
conditionBlock
.
getInstructions
().
get
(
0
);
return
(
IfNode
)
BlockUtils
.
getLastInsn
(
conditionBlock
);
}
/**
...
...
@@ -132,13 +133,8 @@ public final class LoopRegion extends AbstractRegion {
}
public
int
getConditionSourceLine
()
{
if
(
conditionBlock
!=
null
)
{
List
<
InsnNode
>
condInsns
=
conditionBlock
.
getInstructions
();
if
(!
condInsns
.
isEmpty
())
{
return
condInsns
.
get
(
0
).
getSourceLine
();
}
}
return
0
;
InsnNode
lastInsn
=
BlockUtils
.
getLastInsn
(
conditionBlock
);
return
lastInsn
==
null
?
0
:
lastInsn
.
getSourceLine
();
}
public
LoopType
getType
()
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java
View file @
c8923950
...
...
@@ -223,6 +223,14 @@ public class CodeShrinker extends AbstractVisitor {
if
(
assignInsn
==
null
||
assignInsn
.
contains
(
AFlag
.
DONT_INLINE
))
{
continue
;
}
List
<
RegisterArg
>
useList
=
sVar
.
getUseList
();
if
(!
useList
.
isEmpty
())
{
InsnNode
parentInsn
=
useList
.
get
(
0
).
getParentInsn
();
if
(
parentInsn
!=
null
&&
parentInsn
.
contains
(
AFlag
.
DONT_GENERATE
))
{
continue
;
}
}
int
assignPos
=
insnList
.
getIndex
(
assignInsn
);
if
(
assignPos
!=
-
1
)
{
WrapInfo
wrapInfo
=
argsInfo
.
checkInline
(
assignPos
,
arg
);
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ConstInlineVisitor.java
View file @
c8923950
...
...
@@ -27,7 +27,10 @@ import jadx.core.utils.exceptions.JadxOverflowException;
@JadxVisitor
(
name
=
"Constants Inline"
,
desc
=
"Inline constant registers into instructions"
,
runAfter
=
SSATransform
.
class
,
runAfter
=
{
SSATransform
.
class
,
MarkFinallyVisitor
.
class
},
runBefore
=
TypeInferenceVisitor
.
class
)
public
class
ConstInlineVisitor
extends
AbstractVisitor
{
...
...
@@ -48,7 +51,7 @@ public class ConstInlineVisitor extends AbstractVisitor {
}
private
static
void
checkInsn
(
MethodNode
mth
,
InsnNode
insn
,
List
<
InsnNode
>
toRemove
)
{
if
(
insn
.
contains
(
AFlag
.
DONT_INLINE
))
{
if
(
insn
.
contains
(
AFlag
.
DONT_INLINE
)
||
insn
.
contains
(
AFlag
.
DONT_GENERATE
)
)
{
return
;
}
InsnType
insnType
=
insn
.
getType
();
...
...
@@ -71,9 +74,36 @@ public class ConstInlineVisitor extends AbstractVisitor {
}
return
;
}
if
(
checkForFinallyBlock
(
sVar
))
{
return
;
}
// all check passed, run replace
replaceConst
(
mth
,
insn
,
lit
,
toRemove
);
}
private
static
boolean
checkForFinallyBlock
(
SSAVar
sVar
)
{
List
<
SSAVar
>
ssaVars
=
sVar
.
getCodeVar
().
getSsaVars
();
if
(
ssaVars
.
size
()
<=
1
)
{
return
false
;
}
int
countInsns
=
0
;
int
countFinallyInsns
=
0
;
for
(
SSAVar
ssaVar
:
ssaVars
)
{
for
(
RegisterArg
reg
:
ssaVar
.
getUseList
())
{
InsnNode
parentInsn
=
reg
.
getParentInsn
();
if
(
parentInsn
!=
null
)
{
countInsns
++;
if
(
parentInsn
.
contains
(
AFlag
.
FINALLY_INSNS
))
{
countFinallyInsns
++;
}
}
}
}
return
countFinallyInsns
!=
0
&&
countFinallyInsns
!=
countInsns
;
}
/**
* Don't inline null object if:
* - used as instance arg in invoke instruction
...
...
@@ -101,7 +131,7 @@ public class ConstInlineVisitor extends AbstractVisitor {
return
false
;
}
private
static
void
replaceConst
(
MethodNode
mth
,
InsnNode
constInsn
,
long
literal
,
List
<
InsnNode
>
toRemove
)
{
private
static
int
replaceConst
(
MethodNode
mth
,
InsnNode
constInsn
,
long
literal
,
List
<
InsnNode
>
toRemove
)
{
SSAVar
ssaVar
=
constInsn
.
getResult
().
getSVar
();
List
<
RegisterArg
>
useList
=
new
ArrayList
<>(
ssaVar
.
getUseList
());
int
replaceCount
=
0
;
...
...
@@ -113,6 +143,7 @@ public class ConstInlineVisitor extends AbstractVisitor {
if
(
replaceCount
==
useList
.
size
())
{
toRemove
.
add
(
constInsn
);
}
return
replaceCount
;
}
private
static
boolean
replaceArg
(
MethodNode
mth
,
RegisterArg
arg
,
long
literal
,
InsnNode
constInsn
,
List
<
InsnNode
>
toRemove
)
{
...
...
@@ -121,7 +152,7 @@ public class ConstInlineVisitor extends AbstractVisitor {
return
false
;
}
InsnType
insnType
=
useInsn
.
getType
();
if
(
insnType
==
InsnType
.
PHI
||
insnType
==
InsnType
.
MERGE
)
{
if
(
insnType
==
InsnType
.
PHI
)
{
return
false
;
}
ArgType
argType
=
arg
.
getInitType
();
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java
View file @
c8923950
...
...
@@ -185,9 +185,9 @@ public class DotGraphVisitor extends AbstractVisitor {
dot
.
add
(
"}\"];"
);
BlockNode
falsePath
=
null
;
List
<
InsnNode
>
list
=
block
.
getInstructions
(
);
if
(
!
list
.
isEmpty
()
&&
list
.
get
(
0
)
.
getType
()
==
InsnType
.
IF
)
{
falsePath
=
((
IfNode
)
l
ist
.
get
(
0
)
).
getElseBlock
();
InsnNode
lastInsn
=
BlockUtils
.
getLastInsn
(
block
);
if
(
lastInsn
!=
null
&&
lastInsn
.
getType
()
==
InsnType
.
IF
)
{
falsePath
=
((
IfNode
)
l
astInsn
).
getElseBlock
();
}
for
(
BlockNode
next
:
block
.
getSuccessors
())
{
String
style
=
next
==
falsePath
?
"[style=dashed]"
:
""
;
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/
ssa/EliminatePhiNod
es.java
→
jadx-core/src/main/java/jadx/core/dex/visitors/
InitCodeVariabl
es.java
View file @
c8923950
package
jadx
.
core
.
dex
.
visitors
.
ssa
;
package
jadx
.
core
.
dex
.
visitors
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Set
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.nodes.PhiListAttr
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.PhiInsn
;
import
jadx.core.dex.instructions.args.CodeVar
;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.instructions.args.SSAVar
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.visitors.AbstractVisitor
;
import
jadx.core.utils.BlockUtils
;
import
jadx.core.dex.visitors.ssa.SSATransform
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
public
class
EliminatePhiNodes
extends
AbstractVisitor
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
EliminatePhiNodes
.
class
);
@JadxVisitor
(
name
=
"InitCodeVariables"
,
desc
=
"Initialize code variables"
,
runAfter
=
SSATransform
.
class
)
public
class
InitCodeVariables
extends
AbstractVisitor
{
@Override
public
void
visit
(
MethodNode
mth
)
throws
JadxException
{
if
(
mth
.
isNoCode
())
{
return
;
}
replaceMergeInstructions
(
mth
);
removePhiInstructions
(
mth
);
initCodeVars
(
mth
);
}
private
static
void
removePhiInstructions
(
MethodNode
mth
)
{
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
PhiListAttr
phiList
=
block
.
get
(
AType
.
PHI_LIST
);
if
(
phiList
==
null
)
{
continue
;
}
List
<
PhiInsn
>
list
=
phiList
.
getList
();
for
(
PhiInsn
phiInsn
:
list
)
{
removeInsn
(
mth
,
block
,
phiInsn
);
}
}
}
private
static
void
removeInsn
(
MethodNode
mth
,
BlockNode
block
,
PhiInsn
phiInsn
)
{
Iterator
<
InsnNode
>
it
=
block
.
getInstructions
().
iterator
();
while
(
it
.
hasNext
())
{
InsnNode
insn
=
it
.
next
();
if
(
insn
==
phiInsn
)
{
it
.
remove
();
return
;
}
}
LOG
.
warn
(
"Phi node not removed: {}, mth: {}"
,
phiInsn
,
mth
);
phiInsn
.
add
(
AFlag
.
DONT_GENERATE
);
}
private
void
replaceMergeInstructions
(
MethodNode
mth
)
{
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
List
<
InsnNode
>
insns
=
block
.
getInstructions
();
if
(
insns
.
isEmpty
())
{
continue
;
}
InsnNode
insn
=
insns
.
get
(
0
);
if
(
insn
.
getType
()
==
InsnType
.
MERGE
)
{
replaceMerge
(
mth
,
block
,
insn
);
}
}
}
/**
* Replace 'MERGE' with 'PHI' insn.
*/
private
void
replaceMerge
(
MethodNode
mth
,
BlockNode
block
,
InsnNode
insn
)
{
if
(
insn
.
getArgsCount
()
!=
2
)
{
throw
new
JadxRuntimeException
(
"Unexpected count of arguments in merge insn: "
+
insn
);
}
RegisterArg
oldArg
=
(
RegisterArg
)
insn
.
getArg
(
1
);
RegisterArg
newArg
=
(
RegisterArg
)
insn
.
getArg
(
0
);
int
newRegNum
=
newArg
.
getRegNum
();
if
(
oldArg
.
getRegNum
()
==
newRegNum
)
{
throw
new
JadxRuntimeException
(
"Unexpected register number in merge insn: "
+
insn
);
}
SSAVar
oldSVar
=
oldArg
.
getSVar
();
RegisterArg
assignArg
=
oldSVar
.
getAssign
();
InsnNode
assignParentInsn
=
assignArg
.
getParentInsn
();
BlockNode
assignBlock
=
BlockUtils
.
getBlockByInsn
(
mth
,
assignParentInsn
);
if
(
assignBlock
==
null
)
{
throw
new
JadxRuntimeException
(
"Unknown assign block for "
+
assignParentInsn
);
}
BlockNode
assignPred
=
null
;
for
(
BlockNode
pred
:
block
.
getPredecessors
())
{
if
(
BlockUtils
.
isPathExists
(
assignBlock
,
pred
))
{
assignPred
=
pred
;
break
;
}
}
if
(
assignPred
==
null
)
{
throw
new
JadxRuntimeException
(
"Assign predecessor not found for "
+
assignBlock
+
" from "
+
block
);
}
// all checks passed
RegisterArg
newAssignArg
=
oldArg
.
duplicate
(
newRegNum
,
null
);
SSAVar
newSVar
=
mth
.
makeNewSVar
(
newRegNum
,
newAssignArg
);
newSVar
.
setName
(
oldSVar
.
getName
());
mth
.
root
().
getTypeUpdate
().
apply
(
newSVar
,
assignArg
.
getType
());
if
(
assignParentInsn
!=
null
)
{
assignParentInsn
.
setResult
(
newAssignArg
);
}
for
(
RegisterArg
useArg
:
new
ArrayList
<>(
oldSVar
.
getUseList
()))
{
RegisterArg
newUseArg
=
useArg
.
duplicate
(
newRegNum
,
newSVar
);
InsnNode
parentInsn
=
useArg
.
getParentInsn
();
if
(
parentInsn
!=
null
)
{
newSVar
.
use
(
newUseArg
);
parentInsn
.
replaceArg
(
useArg
,
newUseArg
);
}
}
block
.
getInstructions
().
remove
(
0
);
PhiInsn
phiInsn
=
SSATransform
.
addPhi
(
mth
,
block
,
newRegNum
);
phiInsn
.
setResult
(
insn
.
getResult
());
phiInsn
.
bindArg
(
newAssignArg
.
duplicate
(),
assignPred
);
phiInsn
.
bindArg
(
newArg
.
duplicate
(),
BlockUtils
.
selectOtherSafe
(
assignPred
,
block
.
getPredecessors
()));
}
private
void
initCodeVars
(
MethodNode
mth
)
{
private
static
void
initCodeVars
(
MethodNode
mth
)
{
for
(
RegisterArg
mthArg
:
mth
.
getArguments
(
true
))
{
initCodeVar
(
mthArg
.
getSVar
());
}
...
...
@@ -144,7 +36,7 @@ public class EliminatePhiNodes extends AbstractVisitor {
}
}
p
rivate
void
initCodeVar
(
SSAVar
ssaVar
)
{
p
ublic
static
void
initCodeVar
(
SSAVar
ssaVar
)
{
if
(
ssaVar
.
isCodeVarSet
())
{
return
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/MarkFinallyVisitor.java
0 → 100644
View file @
c8923950
This diff is collapsed.
Click to expand it.
jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java
View file @
c8923950
...
...
@@ -235,7 +235,6 @@ public class ModVisitor extends AbstractVisitor {
RegisterArg
reg
=
(
RegisterArg
)
arg
;
SSAVar
sVar
=
reg
.
getSVar
();
if
(
sVar
!=
null
)
{
sVar
.
add
(
AFlag
.
FINAL
);
sVar
.
getCodeVar
().
setFinal
(
true
);
sVar
.
add
(
AFlag
.
DONT_INLINE
);
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/PrepareForCodeGen.java
View file @
c8923950
...
...
@@ -36,6 +36,9 @@ public class PrepareForCodeGen extends AbstractVisitor {
return
;
}
for
(
BlockNode
block
:
blocks
)
{
if
(
block
.
contains
(
AFlag
.
DONT_GENERATE
))
{
continue
;
}
removeInstructions
(
block
);
checkInline
(
block
);
// removeParenthesis(block);
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java
View file @
c8923950
...
...
@@ -4,13 +4,21 @@ import java.util.ArrayList;
import
java.util.Collections
;
import
java.util.List
;
import
jadx.core.dex.instructions.*
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.Consts
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.info.FieldInfo
;
import
jadx.core.dex.info.MethodInfo
;
import
jadx.core.dex.instructions.ArithNode
;
import
jadx.core.dex.instructions.ArithOp
;
import
jadx.core.dex.instructions.CallMthInterface
;
import
jadx.core.dex.instructions.ConstStringNode
;
import
jadx.core.dex.instructions.IfNode
;
import
jadx.core.dex.instructions.IndexInsnNode
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.InvokeNode
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.instructions.args.FieldArg
;
import
jadx.core.dex.instructions.args.InsnArg
;
...
...
@@ -44,6 +52,9 @@ public class SimplifyVisitor extends AbstractVisitor {
}
private
static
InsnNode
simplifyInsn
(
MethodNode
mth
,
InsnNode
insn
)
{
if
(
insn
.
contains
(
AFlag
.
DONT_GENERATE
))
{
return
null
;
}
for
(
InsnArg
arg
:
insn
.
getArguments
())
{
if
(
arg
.
isInsnWrap
())
{
InsnNode
ni
=
simplifyInsn
(
mth
,
((
InsnWrapArg
)
arg
).
getWrapInsn
());
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockExceptionHandler.java
View file @
c8923950
...
...
@@ -49,9 +49,8 @@ public class BlockExceptionHandler extends AbstractVisitor {
}
ExceptionHandler
excHandler
=
handlerAttr
.
getHandler
();
ArgType
argType
=
excHandler
.
getArgType
();
if
(!
block
.
getInstructions
().
isEmpty
())
{
InsnNode
me
=
block
.
getInstructions
().
get
(
0
);
if
(
me
.
getType
()
==
InsnType
.
MOVE_EXCEPTION
)
{
InsnNode
me
=
BlockUtils
.
getLastInsn
(
block
);
if
(
me
!=
null
&&
me
.
getType
()
==
InsnType
.
MOVE_EXCEPTION
)
{
// set correct type for 'move-exception' operation
RegisterArg
resArg
=
InsnArg
.
reg
(
me
.
getResult
().
getRegNum
(),
argType
);
resArg
.
copyAttributesFrom
(
me
);
...
...
@@ -62,7 +61,6 @@ public class BlockExceptionHandler extends AbstractVisitor {
me
.
addAttr
(
handlerAttr
);
return
;
}
}
// handler arguments not used
excHandler
.
setArg
(
new
NamedArg
(
"unused"
,
argType
));
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockFinallyExtract.java
deleted
100644 → 0
View file @
4ce5cc84
This diff is collapsed.
Click to expand it.
jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockProcessor.java
View file @
c8923950
...
...
@@ -560,11 +560,8 @@ public class BlockProcessor extends AbstractVisitor {
}
private
static
RegisterArg
getMoveExceptionRegister
(
BlockNode
block
)
{
if
(
block
.
getInstructions
().
isEmpty
())
{
return
null
;
}
InsnNode
insn
=
block
.
getInstructions
().
get
(
0
);
if
(
insn
.
getType
()
!=
InsnType
.
MOVE_EXCEPTION
)
{
InsnNode
insn
=
BlockUtils
.
getLastInsn
(
block
);
if
(
insn
==
null
||
insn
.
getType
()
!=
InsnType
.
MOVE_EXCEPTION
)
{
return
null
;
}
return
insn
.
getResult
();
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/helpers/BlocksPair.java
deleted
100644 → 0
View file @
4ce5cc84
package
jadx
.
core
.
dex
.
visitors
.
blocksmaker
.
helpers
;
import
jadx.core.dex.nodes.BlockNode
;
public
final
class
BlocksPair
{
private
final
BlockNode
first
;
private
final
BlockNode
second
;
public
BlocksPair
(
BlockNode
first
,
BlockNode
second
)
{
this
.
first
=
first
;
this
.
second
=
second
;
}
public
BlockNode
getFirst
()
{
return
first
;
}
public
BlockNode
getSecond
()
{
return
second
;
}
@Override
public
int
hashCode
()
{
return
31
*
first
.
hashCode
()
+
second
.
hashCode
();
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
{
return
true
;
}
if
(!(
o
instanceof
BlocksPair
))
{
return
false
;
}
BlocksPair
other
=
(
BlocksPair
)
o
;
return
first
.
equals
(
other
.
first
)
&&
second
.
equals
(
other
.
second
);
}
@Override
public
String
toString
()
{
return
"("
+
first
+
", "
+
second
+
")"
;
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/helpers/BlocksRemoveInfo.java
deleted
100644 → 0
View file @
4ce5cc84
package
jadx
.
core
.
dex
.
visitors
.
blocksmaker
.
helpers
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Map
;
import
java.util.Set
;
import
org.jetbrains.annotations.Nullable
;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.nodes.BlockNode
;
public
final
class
BlocksRemoveInfo
{
private
final
Set
<
BlocksPair
>
processed
=
new
HashSet
<>();
private
final
Set
<
BlocksPair
>
outs
=
new
HashSet
<>();
private
final
Map
<
RegisterArg
,
RegisterArg
>
regMap
=
new
HashMap
<>();
private
BlocksPair
start
;
private
BlocksPair
end
;
private
int
startSplitIndex
;
private
int
endSplitIndex
;
private
BlockNode
startPredecessor
;
private
boolean
applied
;
public
BlocksRemoveInfo
(
BlocksPair
start
)
{
this
.
start
=
start
;
}
public
Set
<
BlocksPair
>
getProcessed
()
{
return
processed
;
}
public
Set
<
BlocksPair
>
getOuts
()
{
return
outs
;
}
public
BlocksPair
getStart
()
{
return
start
;
}
public
void
setStart
(
BlocksPair
start
)
{
this
.
start
=
start
;
}
public
BlocksPair
getEnd
()
{
return
end
;
}
public
void
setEnd
(
BlocksPair
end
)
{
this
.
end
=
end
;
}
public
int
getStartSplitIndex
()
{
return
startSplitIndex
;
}
public
void
setStartSplitIndex
(
int
startSplitIndex
)
{
this
.
startSplitIndex
=
startSplitIndex
;
}
public
int
getEndSplitIndex
()
{
return
endSplitIndex
;
}
public
void
setEndSplitIndex
(
int
endSplitIndex
)
{
this
.
endSplitIndex
=
endSplitIndex
;
}
public
void
setStartPredecessor
(
BlockNode
startPredecessor
)
{
this
.
startPredecessor
=
startPredecessor
;
}
public
BlockNode
getStartPredecessor
()
{
return
startPredecessor
;
}
public
Map
<
RegisterArg
,
RegisterArg
>
getRegMap
()
{
return
regMap
;
}
@Nullable
public
BlockNode
getByFirst
(
BlockNode
first
)
{
for
(
BlocksPair
blocksPair
:
processed
)
{
if
(
blocksPair
.
getFirst
()
==
first
)
{
return
blocksPair
.
getSecond
();
}
}
return
null
;
}
@Nullable
public
BlockNode
getBySecond
(
BlockNode
second
)
{
for
(
BlocksPair
blocksPair
:
processed
)
{
if
(
blocksPair
.
getSecond
()
==
second
)
{
return
blocksPair
.
getSecond
();
}
}
return
null
;
}
public
boolean
isApplied
()
{
return
applied
;
}
public
void
setApplied
(
boolean
applied
)
{
this
.
applied
=
applied
;
}
@Override
public
String
toString
()
{
return
"BRI{start: "
+
start
+
", end: "
+
end
+
", processed: "
+
processed
+
", outs: "
+
outs
+
", regMap: "
+
regMap
+
", split: "
+
startSplitIndex
+
"-"
+
endSplitIndex
+
"}"
;
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/helpers/FinallyExtractInfo.java
0 → 100644
View file @
c8923950
package
jadx
.
core
.
dex
.
visitors
.
blocksmaker
.
helpers
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.dex.trycatch.ExceptionHandler
;
public
class
FinallyExtractInfo
{
private
final
ExceptionHandler
finallyHandler
;
private
final
List
<
BlockNode
>
allHandlerBlocks
;
private
final
List
<
InsnsSlice
>
duplicateSlices
=
new
ArrayList
<>();
private
final
Set
<
BlockNode
>
checkedBlocks
=
new
HashSet
<>();
private
final
InsnsSlice
finallyInsnsSlice
=
new
InsnsSlice
();
private
final
BlockNode
startBlock
;
public
FinallyExtractInfo
(
ExceptionHandler
finallyHandler
,
BlockNode
startBlock
,
List
<
BlockNode
>
allHandlerBlocks
)
{
this
.
finallyHandler
=
finallyHandler
;
this
.
startBlock
=
startBlock
;
this
.
allHandlerBlocks
=
allHandlerBlocks
;
}
public
ExceptionHandler
getFinallyHandler
()
{
return
finallyHandler
;
}
public
List
<
BlockNode
>
getAllHandlerBlocks
()
{
return
allHandlerBlocks
;
}
public
InsnsSlice
getFinallyInsnsSlice
()
{
return
finallyInsnsSlice
;
}
public
List
<
InsnsSlice
>
getDuplicateSlices
()
{
return
duplicateSlices
;
}
public
Set
<
BlockNode
>
getCheckedBlocks
()
{
return
checkedBlocks
;
}
public
BlockNode
getStartBlock
()
{
return
startBlock
;
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/helpers/InsnsSlice.java
0 → 100644
View file @
c8923950
package
jadx
.
core
.
dex
.
visitors
.
blocksmaker
.
helpers
;
import
java.util.ArrayList
;
import
java.util.IdentityHashMap
;
import
java.util.LinkedHashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
import
org.jetbrains.annotations.Nullable
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.dex.nodes.InsnNode
;
public
class
InsnsSlice
{
private
final
List
<
InsnNode
>
insnsList
=
new
ArrayList
<>();
private
final
Map
<
InsnNode
,
BlockNode
>
insnMap
=
new
IdentityHashMap
<>();
private
boolean
complete
;
public
void
addInsn
(
InsnNode
insn
,
BlockNode
block
)
{
insnsList
.
add
(
insn
);
insnMap
.
put
(
insn
,
block
);
}
public
void
addBlock
(
BlockNode
block
)
{
for
(
InsnNode
insn
:
block
.
getInstructions
())
{
addInsn
(
insn
,
block
);
}
}
public
void
addInsns
(
BlockNode
block
,
int
startIndex
,
int
endIndex
)
{
List
<
InsnNode
>
insns
=
block
.
getInstructions
();
for
(
int
i
=
startIndex
;
i
<
endIndex
;
i
++)
{
addInsn
(
insns
.
get
(
i
),
block
);
}
}
@Nullable
public
BlockNode
getBlock
(
InsnNode
insn
)
{
return
insnMap
.
get
(
insn
);
}
public
List
<
InsnNode
>
getInsnsList
()
{
return
insnsList
;
}
public
Set
<
BlockNode
>
getBlocks
()
{
Set
<
BlockNode
>
set
=
new
LinkedHashSet
<>();
for
(
InsnNode
insn
:
insnsList
)
{
set
.
add
(
insnMap
.
get
(
insn
));
}
return
set
;
}
public
boolean
isComplete
()
{
return
complete
;
}
public
void
setComplete
(
boolean
complete
)
{
this
.
complete
=
complete
;
}
@Override
public
String
toString
()
{
return
"{["
+
insnsList
.
stream
().
map
(
insn
->
insn
.
getType
().
toString
()).
collect
(
Collectors
.
joining
(
", "
))
+
"]"
+
(
complete
?
" complete"
:
""
)
+
"}"
;
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/DebugInfoApplyVisitor.java
View file @
c8923950
...
...
@@ -26,7 +26,6 @@ import jadx.core.dex.nodes.InsnNode;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.visitors.AbstractVisitor
;
import
jadx.core.dex.visitors.JadxVisitor
;
import
jadx.core.dex.visitors.ssa.EliminatePhiNodes
;
import
jadx.core.dex.visitors.ssa.SSATransform
;
import
jadx.core.dex.visitors.typeinference.TypeInferenceVisitor
;
import
jadx.core.dex.visitors.typeinference.TypeUpdateResult
;
...
...
@@ -39,8 +38,7 @@ import jadx.core.utils.exceptions.JadxException;
desc
=
"Apply debug info to registers (type and names)"
,
runAfter
=
{
SSATransform
.
class
,
TypeInferenceVisitor
.
class
,
EliminatePhiNodes
.
class
TypeInferenceVisitor
.
class
}
)
public
class
DebugInfoApplyVisitor
extends
AbstractVisitor
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java
View file @
c8923950
...
...
@@ -59,6 +59,7 @@ public class CheckRegions extends AbstractVisitor {
if
(!
blocksInRegions
.
contains
(
block
)
&&
!
block
.
getInstructions
().
isEmpty
()
&&
!
block
.
contains
(
AFlag
.
ADDED_TO_REGION
)
&&
!
block
.
contains
(
AFlag
.
DONT_GENERATE
)
&&
!
block
.
contains
(
AFlag
.
REMOVE
))
{
String
blockCode
=
getBlockInsnStr
(
mth
,
block
);
mth
.
addWarn
(
"Missing block: "
+
block
+
", code skipped:"
+
CodeWriter
.
NL
+
blockCode
);
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/CleanRegions.java
View file @
c8923950
package
jadx
.
core
.
dex
.
visitors
.
regions
;
import
java.util.List
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.dex.nodes.IContainer
;
import
jadx.core.dex.nodes.IRegion
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.regions.Region
;
import
jadx.core.dex.visitors.AbstractVisitor
;
public
class
CleanRegions
extends
AbstractVisitor
{
private
static
final
IRegionVisitor
REMOVE_REGION_VISITOR
=
new
RemoveRegionVisitor
();
public
class
CleanRegions
{
@Override
public
void
visit
(
MethodNode
mth
)
{
process
(
mth
);
}
public
static
void
process
(
MethodNode
mth
)
{
if
(
mth
.
isNoCode
()
||
mth
.
getBasicBlocks
().
isEmpty
())
{
return
;
}
IRegionVisitor
removeEmptyBlocks
=
new
AbstractRegionVisitor
()
{
DepthRegionTraversal
.
traverse
(
mth
,
REMOVE_REGION_VISITOR
);
}
private
static
class
RemoveRegionVisitor
extends
AbstractRegionVisitor
{
@Override
public
boolean
enterRegion
(
MethodNode
mth
,
IRegion
region
)
{
if
(
region
instanceof
Region
)
{
region
.
getSubBlocks
().
removeIf
(
container
->
{
region
.
getSubBlocks
().
removeIf
(
RemoveRegionVisitor:
:
canRemoveRegion
);
}
return
true
;
}
private
static
boolean
canRemoveRegion
(
IContainer
container
)
{
if
(
container
.
contains
(
AFlag
.
DONT_GENERATE
))
{
return
true
;
}
if
(
container
instanceof
BlockNode
)
{
BlockNode
block
=
(
BlockNode
)
container
;
return
block
.
getInstructions
().
isEmpty
();
}
if
(
container
instanceof
IRegion
)
{
List
<
IContainer
>
subBlocks
=
((
IRegion
)
container
).
getSubBlocks
();
for
(
IContainer
subBlock
:
subBlocks
)
{
if
(!
canRemoveRegion
(
subBlock
))
{
return
false
;
}
);
}
}
return
true
;
}
};
DepthRegionTraversal
.
traverse
(
mth
,
removeEmptyBlocks
);
return
false
;
}
private
CleanRegions
()
{
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/regions/IfMakerHelper.java
View file @
c8923950
...
...
@@ -36,7 +36,10 @@ public class IfMakerHelper {
}
static
IfInfo
makeIfInfo
(
BlockNode
ifBlock
)
{
IfNode
ifNode
=
(
IfNode
)
ifBlock
.
getInstructions
().
get
(
0
);
IfNode
ifNode
=
(
IfNode
)
BlockUtils
.
getLastInsn
(
ifBlock
);
if
(
ifNode
==
null
)
{
throw
new
JadxRuntimeException
(
"Empty IF block: "
+
ifBlock
);
}
IfCondition
condition
=
IfCondition
.
fromIfNode
(
ifNode
);
IfInfo
info
=
new
IfInfo
(
condition
,
ifNode
.
getThenBlock
(),
ifNode
.
getElseBlock
());
info
.
setIfBlock
(
ifBlock
);
...
...
@@ -328,8 +331,8 @@ public class IfMakerHelper {
if
(
block
==
null
||
block
.
contains
(
AType
.
LOOP
)
||
block
.
contains
(
AFlag
.
ADDED_TO_REGION
))
{
return
null
;
}
List
<
InsnNode
>
insns
=
block
.
getInstructions
(
);
if
(
insns
.
size
()
==
1
&&
insns
.
get
(
0
)
.
getType
()
==
InsnType
.
IF
)
{
InsnNode
lastInsn
=
BlockUtils
.
getLastInsn
(
block
);
if
(
lastInsn
!=
null
&&
lastInsn
.
getType
()
==
InsnType
.
IF
)
{
return
block
;
}
// skip this block and search in successors chain
...
...
@@ -342,6 +345,7 @@ public class IfMakerHelper {
if
(
next
.
getPredecessors
().
size
()
!=
1
)
{
return
null
;
}
List
<
InsnNode
>
insns
=
block
.
getInstructions
();
boolean
pass
=
true
;
if
(!
insns
.
isEmpty
())
{
// check that all instructions can be inlined
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/LoopRegionVisitor.java
View file @
c8923950
...
...
@@ -197,7 +197,6 @@ public class LoopRegionVisitor extends AbstractVisitor implements IRegionVisitor
}
// array for each loop confirmed
len
.
add
(
AFlag
.
DONT_GENERATE
);
incrInsn
.
getResult
().
add
(
AFlag
.
DONT_GENERATE
);
condArg
.
add
(
AFlag
.
DONT_GENERATE
);
bCondArg
.
add
(
AFlag
.
DONT_GENERATE
);
...
...
@@ -208,6 +207,8 @@ public class LoopRegionVisitor extends AbstractVisitor implements IRegionVisitor
((
RegisterArg
)
arrayArg
).
getSVar
().
removeUse
((
RegisterArg
)
arrGetInsn
.
getArg
(
0
));
}
CodeShrinker
.
shrinkMethod
(
mth
);
len
.
add
(
AFlag
.
DONT_GENERATE
);
if
(
arrGetInsn
.
contains
(
AFlag
.
WRAPPED
))
{
InsnArg
wrapArg
=
BlockUtils
.
searchWrappedInsnParent
(
mth
,
arrGetInsn
);
if
(
wrapArg
!=
null
&&
wrapArg
.
getParentInsn
()
!=
null
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java
View file @
c8923950
...
...
@@ -7,9 +7,6 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Set
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.dex.nodes.IBranchRegion
;
...
...
@@ -33,8 +30,6 @@ import jadx.core.utils.RegionUtils;
*/
public
class
ProcessTryCatchRegions
extends
AbstractRegionVisitor
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
ProcessTryCatchRegions
.
class
);
public
static
void
process
(
MethodNode
mth
)
{
if
(
mth
.
isNoCode
()
||
mth
.
isNoExceptionHandlers
())
{
return
;
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java
View file @
c8923950
...
...
@@ -115,8 +115,8 @@ public class RegionMaker {
}
}
if
(!
processed
&&
block
.
getInstructions
().
size
()
==
1
)
{
InsnNode
insn
=
block
.
getInstructions
().
get
(
0
);
InsnNode
insn
=
BlockUtils
.
getLastInsn
(
block
);
if
(!
processed
&&
insn
!=
null
)
{
switch
(
insn
.
getType
())
{
case
IF:
next
=
processIf
(
r
,
block
,
(
IfNode
)
insn
,
stack
);
...
...
@@ -247,9 +247,11 @@ public class RegionMaker {
*/
private
LoopRegion
makeLoopRegion
(
IRegion
curRegion
,
LoopInfo
loop
,
List
<
BlockNode
>
exitBlocks
)
{
for
(
BlockNode
block
:
exitBlocks
)
{
if
(
block
.
contains
(
AType
.
EXC_HANDLER
)
||
block
.
getInstructions
().
size
()
!=
1
||
block
.
getInstructions
().
get
(
0
).
getType
()
!=
InsnType
.
IF
)
{
if
(
block
.
contains
(
AType
.
EXC_HANDLER
))
{
continue
;
}
InsnNode
lastInsn
=
BlockUtils
.
getLastInsn
(
block
);
if
(
lastInsn
==
null
||
lastInsn
.
getType
()
!=
InsnType
.
IF
)
{
continue
;
}
List
<
LoopInfo
>
loops
=
block
.
getAll
(
AType
.
LOOP
);
...
...
@@ -533,6 +535,7 @@ public class RegionMaker {
insnBlock
.
add
(
AFlag
.
DONT_GENERATE
);
}
exitInsn
.
add
(
AFlag
.
DONT_GENERATE
);
exitInsn
.
add
(
AFlag
.
REMOVE
);
InstructionRemover
.
unbindInsn
(
mth
,
exitInsn
);
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMakerVisitor.java
View file @
c8923950
...
...
@@ -54,7 +54,6 @@ public class RegionMakerVisitor extends AbstractVisitor {
mth
.
getRegion
().
add
(
expOutBlock
);
}
}
postProcessRegions
(
mth
);
}
...
...
@@ -85,7 +84,6 @@ public class RegionMakerVisitor extends AbstractVisitor {
insertEdgeInsn
((
Region
)
region
);
}
}
}
/**
* Insert insn block from edge insn attribute.
...
...
@@ -110,28 +108,38 @@ public class RegionMakerVisitor extends AbstractVisitor {
private
static
void
processSwitch
(
MethodNode
mth
,
SwitchRegion
sw
)
{
for
(
IContainer
c
:
sw
.
getBranches
())
{
if
(!(
c
instanceof
Region
))
{
continue
;
}
if
(
c
instanceof
Region
)
{
Set
<
IBlock
>
blocks
=
new
HashSet
<>();
RegionUtils
.
getAllRegionBlocks
(
c
,
blocks
);
if
(
blocks
.
isEmpty
())
{
addBreakToContainer
((
Region
)
c
);
continue
;
}
}
else
{
for
(
IBlock
block
:
blocks
)
{
if
(!(
block
instanceof
BlockNode
))
{
continue
;
if
(
block
instanceof
BlockNode
)
{
addBreakForBlock
(
mth
,
c
,
blocks
,
(
BlockNode
)
block
);
}
}
}
}
BlockNode
bn
=
(
BlockNode
)
block
;
}
}
private
static
void
addBreakToContainer
(
Region
c
)
{
if
(
RegionUtils
.
hasExitEdge
(
c
))
{
return
;
}
List
<
InsnNode
>
insns
=
new
ArrayList
<>(
1
);
insns
.
add
(
new
InsnNode
(
InsnType
.
BREAK
,
0
));
c
.
add
(
new
InsnContainer
(
insns
));
}
private
static
void
addBreakForBlock
(
MethodNode
mth
,
IContainer
c
,
Set
<
IBlock
>
blocks
,
BlockNode
bn
)
{
for
(
BlockNode
s
:
bn
.
getCleanSuccessors
())
{
if
(!
blocks
.
contains
(
s
)
&&
!
bn
.
contains
(
AFlag
.
ADDED_TO_REGION
)
&&
!
s
.
contains
(
AFlag
.
FALL_THROUGH
))
{
addBreak
(
mth
,
c
,
bn
);
break
;
}
}
return
;
}
}
}
...
...
@@ -146,14 +154,6 @@ public class RegionMakerVisitor extends AbstractVisitor {
LOG
.
warn
(
"Can't insert break, container: {}, block: {}, mth: {}"
,
blockContainer
,
bn
,
mth
);
}
}
private
static
void
addBreakToContainer
(
Region
c
)
{
if
(
RegionUtils
.
hasExitEdge
(
c
))
{
return
;
}
List
<
InsnNode
>
insns
=
new
ArrayList
<>(
1
);
insns
.
add
(
new
InsnNode
(
InsnType
.
BREAK
,
0
));
c
.
add
(
new
InsnContainer
(
insns
));
}
private
static
void
removeSynchronized
(
MethodNode
mth
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java
View file @
c8923950
...
...
@@ -43,6 +43,10 @@ public class SSATransform extends AbstractVisitor {
}
private
static
void
process
(
MethodNode
mth
)
{
if
(!
mth
.
getSVars
().
isEmpty
())
{
return
;
}
LiveVarAnalysis
la
=
new
LiveVarAnalysis
(
mth
);
la
.
runAnalysis
();
int
regsCount
=
mth
.
getRegsCount
();
...
...
@@ -63,6 +67,8 @@ public class SSATransform extends AbstractVisitor {
throw
new
JadxRuntimeException
(
"Phi nodes fix limit reached!"
);
}
}
while
(
repeatFix
);
hidePhiInsns
(
mth
);
}
private
static
void
placePhi
(
MethodNode
mth
,
int
regNum
,
LiveVarAnalysis
la
)
{
...
...
@@ -117,9 +123,6 @@ public class SSATransform extends AbstractVisitor {
}
private
static
void
renameVariables
(
MethodNode
mth
)
{
if
(!
mth
.
getSVars
().
isEmpty
())
{
throw
new
JadxRuntimeException
(
"SSA rename variables already executed"
);
}
int
regsCount
=
mth
.
getRegsCount
();
SSAVar
[]
vars
=
new
SSAVar
[
regsCount
];
int
[]
versions
=
new
int
[
regsCount
];
...
...
@@ -432,4 +435,10 @@ public class SSATransform extends AbstractVisitor {
}
}
}
private
static
void
hidePhiInsns
(
MethodNode
mth
)
{
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
block
.
getInstructions
().
removeIf
(
insn
->
insn
.
getType
()
==
InsnType
.
PHI
);
}
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeCompare.java
View file @
c8923950
...
...
@@ -114,6 +114,9 @@ public class TypeCompare {
if
(
unknown
==
ArgType
.
UNKNOWN_OBJECT
&&
(
known
.
isObject
()
||
known
.
isArray
()))
{
return
NARROW
;
}
if
(
known
.
equals
(
ArgType
.
OBJECT
)
&&
unknown
.
isArray
())
{
return
WIDER
;
}
PrimitiveType
knownPrimitive
;
if
(
known
.
isPrimitive
())
{
knownPrimitive
=
known
.
getPrimitiveType
();
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java
View file @
c8923950
...
...
@@ -33,6 +33,7 @@ import jadx.core.dex.nodes.RootNode;
import
jadx.core.dex.trycatch.ExcHandlerAttr
;
import
jadx.core.dex.visitors.AbstractVisitor
;
import
jadx.core.dex.visitors.ConstInlineVisitor
;
import
jadx.core.dex.visitors.InitCodeVariables
;
import
jadx.core.dex.visitors.JadxVisitor
;
import
jadx.core.dex.visitors.ssa.SSATransform
;
import
jadx.core.utils.Utils
;
...
...
@@ -131,7 +132,7 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
if
(
Consts
.
DEBUG
)
{
if
(
ssaVar
.
getTypeInfo
().
getType
().
equals
(
candidateType
))
{
LOG
.
info
(
"Same type rejected: {} -> {}, bounds: {}"
,
ssaVar
,
candidateType
,
bounds
);
}
else
{
}
else
if
(
candidateType
.
isTypeKnown
())
{
LOG
.
debug
(
"Type set rejected: {} -> {}, bounds: {}"
,
ssaVar
,
candidateType
,
bounds
);
}
}
...
...
@@ -311,6 +312,7 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
for
(
InsnArg
phiArg
:
phiInsn
.
getArguments
())
{
mergePhiBounds
(((
RegisterArg
)
phiArg
).
getSVar
());
}
InitCodeVariables
.
initCodeVar
(
newSsaVar
);
return
true
;
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdate.java
View file @
c8923950
...
...
@@ -246,7 +246,6 @@ public final class TypeUpdate {
registry
.
put
(
InsnType
.
CONST
,
this
::
sameFirstArgListener
);
registry
.
put
(
InsnType
.
MOVE
,
this
::
moveListener
);
registry
.
put
(
InsnType
.
PHI
,
this
::
allSameListener
);
registry
.
put
(
InsnType
.
MERGE
,
this
::
allSameListener
);
registry
.
put
(
InsnType
.
AGET
,
this
::
arrayGetListener
);
registry
.
put
(
InsnType
.
APUT
,
this
::
arrayPutListener
);
registry
.
put
(
InsnType
.
IF
,
this
::
ifListener
);
...
...
jadx-core/src/main/java/jadx/core/utils/DebugUtils.java
View file @
c8923950
...
...
@@ -107,9 +107,9 @@ public class DebugUtils {
CodeWriter
code
=
new
CodeWriter
();
ig
.
makeInsn
(
insn
,
code
);
String
insnStr
=
code
.
toString
().
substring
(
CodeWriter
.
NL
.
length
());
LOG
.
debug
(
"{}> {}\t{}"
,
indent
,
insnStr
,
insn
.
getAttributesString
());
LOG
.
debug
(
"{}
|
> {}\t{}"
,
indent
,
insnStr
,
insn
.
getAttributesString
());
}
catch
(
CodegenException
e
)
{
LOG
.
debug
(
"{}>!! {}"
,
indent
,
insn
);
LOG
.
debug
(
"{}
|
>!! {}"
,
indent
,
insn
);
}
}
}
...
...
jadx-core/src/test/java/jadx/core/dex/visitors/typeinference/TypeCompareTest.java
View file @
c8923950
...
...
@@ -16,6 +16,7 @@ import static jadx.core.dex.instructions.args.ArgType.NARROW;
import
static
jadx
.
core
.
dex
.
instructions
.
args
.
ArgType
.
NARROW_INTEGRAL
;
import
static
jadx
.
core
.
dex
.
instructions
.
args
.
ArgType
.
OBJECT
;
import
static
jadx
.
core
.
dex
.
instructions
.
args
.
ArgType
.
UNKNOWN
;
import
static
jadx
.
core
.
dex
.
instructions
.
args
.
ArgType
.
UNKNOWN_ARRAY
;
import
static
jadx
.
core
.
dex
.
instructions
.
args
.
ArgType
.
UNKNOWN_OBJECT
;
import
static
jadx
.
core
.
dex
.
instructions
.
args
.
ArgType
.
array
;
import
static
org
.
hamcrest
.
Matchers
.
is
;
...
...
@@ -60,6 +61,8 @@ public class TypeCompareTest {
firstIsNarrow
(
array
(
OBJECT
),
OBJECT
);
firstIsNarrow
(
array
(
OBJECT
),
array
(
UNKNOWN_OBJECT
));
firstIsNarrow
(
UNKNOWN_ARRAY
,
OBJECT
);
}
@Test
...
...
jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java
View file @
c8923950
...
...
@@ -17,7 +17,6 @@ import java.util.jar.JarOutputStream;
import
jadx.api.JadxArgs
;
import
jadx.api.JadxDecompiler
;
import
jadx.api.JadxInternalAccess
;
import
jadx.core.Jadx
;
import
jadx.core.ProcessClass
;
import
jadx.core.codegen.CodeGen
;
import
jadx.core.dex.attributes.AFlag
;
...
...
@@ -29,7 +28,6 @@ import jadx.core.dex.nodes.MethodNode;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.dex.visitors.DepthTraversal
;
import
jadx.core.dex.visitors.IDexTreeVisitor
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.xmlgen.ResourceStorage
;
import
jadx.core.xmlgen.entry.ResourceEntry
;
import
jadx.tests.api.compiler.DynamicCompiler
;
...
...
@@ -141,34 +139,19 @@ public abstract class IntegrationTest extends TestUtils {
}
protected
void
decompile
(
JadxDecompiler
jadx
,
ClassNode
cls
)
{
List
<
IDexTreeVisitor
>
passes
=
getPasse
sList
(
jadx
);
List
<
IDexTreeVisitor
>
passes
=
JadxInternalAccess
.
getPas
sList
(
jadx
);
ProcessClass
.
process
(
cls
,
passes
,
new
CodeGen
());
}
protected
void
decompileWithoutUnload
(
JadxDecompiler
jadx
,
ClassNode
cls
)
{
cls
.
load
();
List
<
IDexTreeVisitor
>
passes
=
getPassesList
(
jadx
);
for
(
IDexTreeVisitor
visitor
:
passes
)
{
for
(
IDexTreeVisitor
visitor
:
JadxInternalAccess
.
getPassList
(
jadx
))
{
DepthTraversal
.
visit
(
visitor
,
cls
);
}
generateClsCode
(
cls
);
// don't unload class
}
private
List
<
IDexTreeVisitor
>
getPassesList
(
JadxDecompiler
jadx
)
{
RootNode
root
=
JadxInternalAccess
.
getRoot
(
jadx
);
List
<
IDexTreeVisitor
>
passesList
=
Jadx
.
getPassesList
(
jadx
.
getArgs
());
passesList
.
forEach
(
pass
->
{
try
{
pass
.
init
(
root
);
}
catch
(
JadxException
e
)
{
e
.
printStackTrace
();
fail
(
e
.
getMessage
());
}
});
return
passesList
;
}
protected
void
generateClsCode
(
ClassNode
cls
)
{
try
{
new
CodeGen
().
visit
(
cls
);
...
...
@@ -442,6 +425,11 @@ public abstract class IntegrationTest extends TestUtils {
protected
void
setOutputCFG
()
{
this
.
args
.
setCfgOutput
(
true
);
this
.
args
.
setRawCFGOutput
(
true
);
}
// Use only for debug purpose
@Deprecated
protected
void
setOutputRawCFG
()
{
this
.
args
.
setRawCFGOutput
(
true
);
}
// Use only for debug purpose
...
...
jadx-core/src/test/java/jadx/tests/api/utils/TestUtils.java
View file @
c8923950
...
...
@@ -4,6 +4,10 @@ import jadx.core.codegen.CodeWriter;
public
class
TestUtils
{
public
static
String
indent
()
{
return
CodeWriter
.
INDENT_STR
;
}
public
static
String
indent
(
int
indent
)
{
if
(
indent
==
1
)
{
return
CodeWriter
.
INDENT_STR
;
...
...
@@ -24,5 +28,4 @@ public class TestUtils {
}
return
count
;
}
}
jadx-core/src/test/java/jadx/tests/integration/arith/TestFieldIncrement2.java
View file @
c8923950
...
...
@@ -32,8 +32,8 @@ public class TestFieldIncrement2 extends IntegrationTest {
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsString
(
"this.a.f += n;"
));
assertThat
(
code
,
containsString
(
"a.f *= n;"
));
// TODO
assertThat
(
code
,
containsString
(
"a
2
.f *= n;"
));
// TODO
:
// assertThat(code, containsString("this.a.f *= n;"));
}
}
jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernary2.java
View file @
c8923950
...
...
@@ -6,19 +6,24 @@ import jadx.core.dex.nodes.ClassNode;
import
jadx.tests.api.IntegrationTest
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
public
class
TestTernary2
extends
IntegrationTest
{
public
static
class
TestCls
{
public
void
test
()
{
assertTru
e
(
f
(
1
,
0
)
==
0
);
checkFals
e
(
f
(
1
,
0
)
==
0
);
}
private
int
f
(
int
a
,
int
b
)
{
return
a
+
b
;
}
private
void
checkFalse
(
boolean
b
)
{
if
(
b
)
{
throw
new
AssertionError
(
"Must be false"
);
}
}
}
@Test
...
...
@@ -26,9 +31,8 @@ public class TestTernary2 extends IntegrationTest {
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertEquals
(
1
,
count
(
code
,
"assertTrue"
));
assertEquals
(
1
,
count
(
code
,
"f(1, 0)"
));
// TODO:
// assertThat(code, containsString("
assertTru
e(f(1, 0) == 0);"));
// assertThat(code, containsString("
checkFals
e(f(1, 0) == 0);"));
}
}
jadx-core/src/test/java/jadx/tests/integration/enums/TestEnums4.java
View file @
c8923950
...
...
@@ -24,8 +24,8 @@ public class TestEnums4 extends IntegrationTest {
private
final
String
[]
exts
;
private
ResType
(
String
...
exts
)
{
this
.
exts
=
exts
;
private
ResType
(
String
...
ext
ension
s
)
{
this
.
exts
=
ext
ension
s
;
}
public
String
[]
getExts
()
{
...
...
@@ -44,7 +44,7 @@ public class TestEnums4 extends IntegrationTest {
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"CODE(\".dex\", \".class\"),"
));
assertThat
(
code
,
containsOne
(
"ResType(String... exts) {"
));
assertThat
(
code
,
containsOne
(
"ResType(String... ext
ension
s) {"
));
// assertThat(code, not(containsString("private ResType")));
}
}
jadx-core/src/test/java/jadx/tests/integration/generics/TestGenerics2.java
View file @
c8923950
...
...
@@ -19,9 +19,9 @@ public class TestGenerics2 extends IntegrationTest {
private
static
class
ItemReference
<
V
>
extends
WeakReference
<
V
>
{
private
Object
id
;
public
ItemReference
(
V
item
,
Object
i
d
,
ReferenceQueue
<?
super
V
>
queue
)
{
public
ItemReference
(
V
item
,
Object
objI
d
,
ReferenceQueue
<?
super
V
>
queue
)
{
super
(
item
,
queue
);
this
.
id
=
i
d
;
this
.
id
=
objI
d
;
}
}
...
...
@@ -43,7 +43,7 @@ public class TestGenerics2 extends IntegrationTest {
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsString
(
"public ItemReference(V item, Object
i
d, ReferenceQueue<? super V> queue) {"
));
assertThat
(
code
,
containsString
(
"public ItemReference(V item, Object
objI
d, ReferenceQueue<? super V> queue) {"
));
assertThat
(
code
,
containsString
(
"public V get(Object id) {"
));
assertThat
(
code
,
containsString
(
"WeakReference<V> ref = "
));
assertThat
(
code
,
containsString
(
"return ref.get();"
));
...
...
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestFinallyExtract.java
View file @
c8923950
package
jadx
.
tests
.
integration
.
trycatch
;
import
java.io.IOException
;
import
org.junit.Test
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.IntegrationTest
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
hamcrest
.
Matchers
.
containsString
;
import
static
org
.
hamcrest
.
Matchers
.
not
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestFinallyExtract
extends
IntegrationTest
{
public
static
class
TestCls
{
private
int
result
=
0
;
public
String
test
()
throws
IOException
{
public
String
test
()
{
boolean
success
=
false
;
try
{
String
value
=
test
();
String
value
=
call
();
result
++;
success
=
true
;
return
value
;
}
finally
{
if
(!
success
)
{
test
();
result
-=
2
;
}
}
}
private
String
call
()
{
return
"call"
;
}
public
void
check
()
{
test
();
assertEquals
(
result
,
1
);
}
}
...
...
@@ -33,10 +45,38 @@ public class TestFinallyExtract extends IntegrationTest {
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
not
(
containsString
(
"if (0 == 0) {"
)));
assertThat
(
code
,
containsOne
(
"boolean success = false;"
));
assertThat
(
code
,
containsOne
(
"try {"
));
assertThat
(
code
,
containsOne
(
"success = true;"
));
assertThat
(
code
,
containsOne
(
"return value;"
));
assertThat
(
code
,
containsOne
(
"try {"
));
assertThat
(
code
,
containsOne
(
"} finally {"
));
assertThat
(
code
,
containsOne
(
"if (!success) {"
));
}
@Test
public
void
testNoDebug
()
{
noDebugInfo
();
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
// java compiler optimization: 'success' variable completely removed and no code duplication:
/*
public String test() {
try {
String call = call();
this.result++;
return call;
} catch (Throwable th) {
this.result -= 2;
throw th;
}
}
*/
assertThat
(
code
,
containsOne
(
"this.result++;"
));
assertThat
(
code
,
containsOne
(
"} catch (Throwable th) {"
));
assertThat
(
code
,
containsOne
(
"this.result -= 2;"
));
assertThat
(
code
,
containsOne
(
"throw th;"
));
}
}
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatch7.java
View file @
c8923950
...
...
@@ -24,13 +24,23 @@ public class TestTryCatch7 extends IntegrationTest {
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
check
(
code
,
"e"
,
"ex"
);
}
@Test
public
void
testNoDebug
()
{
noDebugInfo
();
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
String
excVarName
=
"exception"
;
String
catchExcVarName
=
"e"
;
check
(
code
,
"e"
,
"e2"
);
}
private
void
check
(
String
code
,
String
excVarName
,
String
catchExcVarName
)
{
assertThat
(
code
,
containsOne
(
"Exception "
+
excVarName
+
" = new Exception();"
));
assertThat
(
code
,
containsOne
(
"} catch (Exception "
+
catchExcVarName
+
") {"
));
assertThat
(
code
,
containsOne
(
excVarName
+
" = "
+
catchExcVarName
+
";"
));
...
...
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatch8.java
View file @
c8923950
...
...
@@ -31,8 +31,8 @@ public class TestTryCatch8 extends IntegrationTest {
synchronized
(
this
)
{
try
{
throw
new
MyException
();
}
catch
(
MyException
e
)
{
this
.
e
=
e
;
}
catch
(
MyException
myExc
)
{
this
.
e
=
myExc
;
}
catch
(
Exception
x
)
{
this
.
e
=
new
MyException
(
"MyExc"
,
x
);
}
...
...
@@ -54,9 +54,19 @@ public class TestTryCatch8 extends IntegrationTest {
assertThat
(
code
,
containsOne
(
"synchronized (this) {"
));
assertThat
(
code
,
containsOne
(
"throw new MyException();"
));
assertThat
(
code
,
containsOne
(
"} catch (MyException
e
) {"
));
assertThat
(
code
,
containsOne
(
"this.e =
e
;"
));
assertThat
(
code
,
containsOne
(
"} catch (MyException
myExc
) {"
));
assertThat
(
code
,
containsOne
(
"this.e =
myExc
;"
));
assertThat
(
code
,
containsOne
(
"} catch (Exception x) {"
));
assertThat
(
code
,
containsOne
(
"this.e = new MyException(\"MyExc\", x);"
));
}
@Test
public
void
testNoDebug
()
{
noDebugInfo
();
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"synchronized (this) {"
));
assertThat
(
code
,
containsOne
(
"throw new MyException();"
));
}
}
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatchFinally6.java
View file @
c8923950
...
...
@@ -18,6 +18,7 @@ public class TestTryCatchFinally6 extends IntegrationTest {
public
static
void
test
()
throws
IOException
{
InputStream
is
=
null
;
try
{
call
();
is
=
new
FileInputStream
(
"1.txt"
);
}
finally
{
if
(
is
!=
null
)
{
...
...
@@ -25,6 +26,9 @@ public class TestTryCatchFinally6 extends IntegrationTest {
}
}
}
private
static
void
call
()
{
}
}
@Test
...
...
@@ -35,6 +39,7 @@ public class TestTryCatchFinally6 extends IntegrationTest {
assertThat
(
code
,
containsLines
(
2
,
"InputStream is = null;"
,
"try {"
,
indent
(
1
)
+
"call();"
,
indent
(
1
)
+
"is = new FileInputStream(\"1.txt\");"
,
"} finally {"
,
indent
(
1
)
+
"if (is != null) {"
,
...
...
@@ -43,4 +48,23 @@ public class TestTryCatchFinally6 extends IntegrationTest {
"}"
));
}
@Test
public
void
testNoDebug
()
{
noDebugInfo
();
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsLines
(
2
,
"FileInputStream fileInputStream = null;"
,
"try {"
,
indent
()
+
"call();"
,
indent
()
+
"fileInputStream = new FileInputStream(\"1.txt\");"
,
"} finally {"
,
indent
()
+
"if (fileInputStream != null) {"
,
indent
()
+
indent
()
+
"fileInputStream.close();"
,
indent
()
+
"}"
,
"}"
));
}
}
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatch
3
.java
→
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatch
Finally7
.java
View file @
c8923950
...
...
@@ -11,7 +11,7 @@ import static org.junit.Assert.assertEquals;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
public
class
TestTryCatch
3
extends
IntegrationTest
{
public
class
TestTryCatch
Finally7
extends
IntegrationTest
{
public
static
class
TestCls
{
private
int
f
=
0
;
...
...
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatch
5
.java
→
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatch
Finally8
.java
View file @
c8923950
...
...
@@ -4,6 +4,7 @@ import java.io.File;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
org.junit.Ignore
;
import
org.junit.Test
;
import
jadx.core.dex.nodes.ClassNode
;
...
...
@@ -12,7 +13,7 @@ import jadx.tests.api.IntegrationTest;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestTryCatch
5
extends
IntegrationTest
{
public
class
TestTryCatch
Finally8
extends
IntegrationTest
{
public
static
class
TestCls
{
private
Object
test
(
Object
obj
)
{
...
...
@@ -41,9 +42,9 @@ public class TestTryCatch5 extends IntegrationTest {
}
}
@Ignore
(
"Fix merged catch blocks (shared code between catches)"
)
@Test
public
void
test
()
{
disableCompilation
();
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
...
...
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatchNoMove.java
→
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatchNoMove
Exc
.java
View file @
c8923950
...
...
@@ -8,7 +8,7 @@ import jadx.tests.api.SmaliTest;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestTryCatchNoMove
extends
SmaliTest
{
public
class
TestTryCatchNoMove
Exc
extends
SmaliTest
{
// private static void test(AutoCloseable closeable) {
// if (closeable != null) {
...
...
@@ -21,7 +21,7 @@ public class TestTryCatchNoMove extends SmaliTest {
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNodeFromSmaliWithP
ath
(
"trycatch"
,
"TestTryCatchNoMove
"
);
ClassNode
cls
=
getClassNodeFromSmaliWithP
kg
(
"trycatch"
,
"TestTryCatchNoMoveExc
"
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"if (autoCloseable != null) {"
));
...
...
jadx-core/src/test/java/jadx/tests/integration/trycatch/TestTryCatchNoMoveExc2.java
View file @
c8923950
...
...
@@ -26,7 +26,7 @@ public class TestTryCatchNoMoveExc2 extends SmaliTest {
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNodeFromSmaliWithP
ath
(
"trycatch"
,
"TestTryCatchNoMoveExc2"
);
ClassNode
cls
=
getClassNodeFromSmaliWithP
kg
(
"trycatch"
,
"TestTryCatchNoMoveExc2"
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"try {"
));
...
...
jadx-core/src/test/smali/trycatch/TestTryCatchNoMove.smali
→
jadx-core/src/test/smali/trycatch/TestTryCatchNoMove
Exc
.smali
View file @
c8923950
.class public L
TestTryCatchNoMove
;
.class public L
trycatch/TestTryCatchNoMoveExc
;
.super Ljava/lang/Object;
.method private static test(Ljava/lang/AutoCloseable;)V
...
...
jadx-core/src/test/smali/trycatch/TestTryCatchNoMoveExc2.smali
View file @
c8923950
.class public LTestTryCatchNoMoveExc2;
.class public L
trycatch/
TestTryCatchNoMoveExc2;
.super Ljava/lang/Object;
.method private static test(Ljava/lang/AutoCloseable;)V
...
...
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