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
5dc4c28d
Commit
5dc4c28d
authored
Nov 15, 2013
by
skylot
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2 from 13-beta2/master
Handy core improvement
parents
36cfc9d1
7342ae18
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
263 additions
and
83 deletions
+263
-83
InsnGen.java
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
+1
-1
RegionGen.java
jadx-core/src/main/java/jadx/core/codegen/RegionGen.java
+20
-7
InsnDecoder.java
...src/main/java/jadx/core/dex/instructions/InsnDecoder.java
+5
-3
SwitchNode.java
.../src/main/java/jadx/core/dex/instructions/SwitchNode.java
+3
-3
ClassNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
+27
-1
SwitchRegion.java
...ore/src/main/java/jadx/core/dex/regions/SwitchRegion.java
+4
-4
BlockMakerVisitor.java
...c/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java
+46
-20
CodeShrinker.java
...re/src/main/java/jadx/core/dex/visitors/CodeShrinker.java
+10
-6
ModVisitor.java
...core/src/main/java/jadx/core/dex/visitors/ModVisitor.java
+27
-30
RegionMaker.java
...main/java/jadx/core/dex/visitors/regions/RegionMaker.java
+8
-8
TestReturnWrapping.java
...src/test/java/jadx/tests/internal/TestReturnWrapping.java
+63
-0
TestSwitchLabels.java
...e/src/test/java/jadx/tests/internal/TestSwitchLabels.java
+49
-0
No files found.
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
View file @
5dc4c28d
...
...
@@ -146,7 +146,7 @@ public class InsnGen {
private
String
sfield
(
FieldInfo
field
)
{
String
thisClass
=
mth
.
getParentClass
().
getFullName
();
if
(
field
.
getDeclClass
().
getFullName
().
equals
(
thisClass
))
{
if
(
thisClass
.
startsWith
(
field
.
getDeclClass
().
getFullName
()
))
{
return
field
.
getName
();
}
else
{
return
useClass
(
field
.
getDeclClass
())
+
'.'
+
field
.
getName
();
...
...
jadx-core/src/main/java/jadx/core/codegen/RegionGen.java
View file @
5dc4c28d
...
...
@@ -5,8 +5,10 @@ import jadx.core.dex.attributes.AttributeType;
import
jadx.core.dex.attributes.DeclareVariableAttr
;
import
jadx.core.dex.attributes.ForceReturnAttr
;
import
jadx.core.dex.attributes.IAttribute
;
import
jadx.core.dex.info.FieldInfo
;
import
jadx.core.dex.instructions.ArithNode
;
import
jadx.core.dex.instructions.IfOp
;
import
jadx.core.dex.instructions.IndexInsnNode
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.SwitchNode
;
import
jadx.core.dex.instructions.args.ArgType
;
...
...
@@ -232,15 +234,19 @@ public class RegionGen extends InsnGen {
SwitchNode
insn
=
(
SwitchNode
)
sw
.
getHeader
().
getInstructions
().
get
(
0
);
InsnArg
arg
=
insn
.
getArg
(
0
);
code
.
startLine
(
"switch("
).
add
(
arg
(
arg
)).
add
(
") {"
);
code
.
incIndent
();
int
size
=
sw
.
getKeys
().
size
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
List
<
Integer
>
keys
=
sw
.
getKeys
().
get
(
i
);
List
<
Object
>
keys
=
sw
.
getKeys
().
get
(
i
);
IContainer
c
=
sw
.
getCases
().
get
(
i
);
for
(
Integer
k
:
keys
)
{
for
(
Object
k
:
keys
)
{
code
.
startLine
(
"case "
);
code
.
add
(
TypeGen
.
literalToString
(
k
,
arg
.
getType
()));
if
(
k
instanceof
IndexInsnNode
)
{
code
.
add
(
sfield
((
FieldInfo
)
((
IndexInsnNode
)
k
).
getIndex
()));
}
else
{
code
.
add
(
TypeGen
.
literalToString
((
Integer
)
k
,
arg
.
getType
()));
}
code
.
add
(
':'
);
}
makeCaseBlock
(
c
,
code
);
...
...
@@ -249,13 +255,12 @@ public class RegionGen extends InsnGen {
code
.
startLine
(
"default:"
);
makeCaseBlock
(
sw
.
getDefaultCase
(),
code
);
}
code
.
decIndent
();
code
.
startLine
(
'}'
);
return
code
;
}
private
void
makeCaseBlock
(
IContainer
c
,
CodeWriter
code
)
throws
CodegenException
{
code
.
add
(
" {"
);
if
(
RegionUtils
.
notEmpty
(
c
))
{
makeRegionIndent
(
code
,
c
);
if
(
RegionUtils
.
hasExitEdge
(
c
))
{
...
...
@@ -264,7 +269,6 @@ public class RegionGen extends InsnGen {
}
else
{
code
.
startLine
(
1
,
"break;"
);
}
code
.
startLine
(
'}'
);
}
private
void
makeTryCatch
(
IContainer
region
,
TryCatchBlock
tryCatchBlock
,
CodeWriter
code
)
...
...
@@ -305,4 +309,13 @@ public class RegionGen extends InsnGen {
}
}
// FIXME: !!code from InsnGen.sfield
private
String
sfield
(
FieldInfo
field
)
{
String
thisClass
=
mth
.
getParentClass
().
getFullName
();
if
(
thisClass
.
startsWith
(
field
.
getDeclClass
().
getFullName
()))
{
return
field
.
getName
();
}
else
{
return
useClass
(
field
.
getDeclClass
())
+
'.'
+
field
.
getName
();
}
}
}
jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java
View file @
5dc4c28d
...
...
@@ -571,19 +571,21 @@ public class InsnDecoder {
private
InsnNode
decodeSwitch
(
DecodedInstruction
insn
,
int
offset
,
boolean
packed
)
{
int
payloadOffset
=
insn
.
getTarget
();
DecodedInstruction
payload
=
insnArr
[
payloadOffset
];
in
t
[]
keys
;
Objec
t
[]
keys
;
int
[]
targets
;
if
(
packed
)
{
PackedSwitchPayloadDecodedInstruction
ps
=
(
PackedSwitchPayloadDecodedInstruction
)
payload
;
targets
=
ps
.
getTargets
();
keys
=
new
in
t
[
targets
.
length
];
keys
=
new
Objec
t
[
targets
.
length
];
int
k
=
ps
.
getFirstKey
();
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++)
keys
[
i
]
=
k
++;
}
else
{
SparseSwitchPayloadDecodedInstruction
ss
=
(
SparseSwitchPayloadDecodedInstruction
)
payload
;
targets
=
ss
.
getTargets
();
keys
=
ss
.
getKeys
();
keys
=
new
Object
[
targets
.
length
];
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++)
keys
[
i
]
=
ss
.
getKeys
()[
i
];
}
// convert from relative to absolute offsets
for
(
int
i
=
0
;
i
<
targets
.
length
;
i
++)
{
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/SwitchNode.java
View file @
5dc4c28d
...
...
@@ -8,11 +8,11 @@ import java.util.Arrays;
public
class
SwitchNode
extends
InsnNode
{
private
final
in
t
[]
keys
;
private
final
Objec
t
[]
keys
;
private
final
int
[]
targets
;
private
final
int
def
;
// next instruction
public
SwitchNode
(
InsnArg
arg
,
in
t
[]
keys
,
int
[]
targets
,
int
def
)
{
public
SwitchNode
(
InsnArg
arg
,
Objec
t
[]
keys
,
int
[]
targets
,
int
def
)
{
super
(
InsnType
.
SWITCH
,
1
);
this
.
keys
=
keys
;
this
.
targets
=
targets
;
...
...
@@ -24,7 +24,7 @@ public class SwitchNode extends InsnNode {
return
keys
.
length
;
}
public
in
t
[]
getKeys
()
{
public
Objec
t
[]
getKeys
()
{
return
keys
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
View file @
5dc4c28d
...
...
@@ -12,6 +12,7 @@ import jadx.core.dex.info.ClassInfo;
import
jadx.core.dex.info.FieldInfo
;
import
jadx.core.dex.info.MethodInfo
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.instructions.args.LiteralArg
;
import
jadx.core.dex.nodes.parser.AnnotationsParser
;
import
jadx.core.dex.nodes.parser.FieldValueAttr
;
import
jadx.core.dex.nodes.parser.StaticValuesParser
;
...
...
@@ -237,12 +238,37 @@ public class ClassNode extends LineAttrNode implements ILoadable {
}
public
FieldNode
getConstField
(
Object
o
)
{
FieldNode
field
=
constFields
.
get
(
o
);
ClassNode
cn
=
this
;
FieldNode
field
;
do
{
field
=
cn
.
constFields
.
get
(
o
);
}
while
(
field
==
null
&&
(
cn
.
clsInfo
.
getParentClass
()
!=
null
)
&&
(
cn
=
dex
.
resolveClass
(
cn
.
clsInfo
.
getParentClass
()))
!=
null
);
if
(
field
==
null
)
field
=
dex
.
getConstFields
().
get
(
o
);
return
field
;
}
public
FieldNode
getConstFieldByLiteralArg
(
LiteralArg
arg
)
{
ArgType
type
=
arg
.
getType
();
long
literal
=
arg
.
getLiteral
();
if
(
type
.
equals
(
ArgType
.
DOUBLE
))
return
getConstField
(
Double
.
longBitsToDouble
(
literal
));
else
if
(
type
.
equals
(
ArgType
.
FLOAT
))
return
getConstField
(
Float
.
intBitsToFloat
((
int
)
literal
));
else
if
(
Math
.
abs
(
literal
)
>
0x1
)
{
if
(
type
.
equals
(
ArgType
.
INT
))
return
getConstField
((
int
)
literal
);
else
if
(
type
.
equals
(
ArgType
.
LONG
))
return
getConstField
(
literal
);
}
return
null
;
}
public
FieldNode
searchFieldById
(
int
id
)
{
String
name
=
FieldInfo
.
getNameById
(
dex
,
id
);
for
(
FieldNode
f
:
fields
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/regions/SwitchRegion.java
View file @
5dc4c28d
...
...
@@ -12,14 +12,14 @@ public final class SwitchRegion extends AbstractRegion {
private
final
BlockNode
header
;
private
final
List
<
List
<
Integer
>>
keys
;
private
final
List
<
List
<
Object
>>
keys
;
private
final
List
<
IContainer
>
cases
;
private
IContainer
defCase
;
public
SwitchRegion
(
IRegion
parent
,
BlockNode
header
)
{
super
(
parent
);
this
.
header
=
header
;
this
.
keys
=
new
ArrayList
<
List
<
Integer
>>();
this
.
keys
=
new
ArrayList
<
List
<
Object
>>();
this
.
cases
=
new
ArrayList
<
IContainer
>();
}
...
...
@@ -27,7 +27,7 @@ public final class SwitchRegion extends AbstractRegion {
return
header
;
}
public
void
addCase
(
List
<
Integer
>
keysList
,
IContainer
c
)
{
public
void
addCase
(
List
<
Object
>
keysList
,
IContainer
c
)
{
keys
.
add
(
keysList
);
cases
.
add
(
c
);
}
...
...
@@ -40,7 +40,7 @@ public final class SwitchRegion extends AbstractRegion {
return
defCase
;
}
public
List
<
List
<
Integer
>>
getKeys
()
{
public
List
<
List
<
Object
>>
getKeys
()
{
return
keys
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java
View file @
5dc4c28d
...
...
@@ -349,44 +349,70 @@ public class BlockMakerVisitor extends AbstractVisitor {
return
true
;
}
}
// splice return block if several precessors presents
if
(
false
&&
block
.
getAttributes
().
contains
(
AttributeFlag
.
RETURN
)
&&
block
.
getPredecessors
().
size
()
>
1
&&
!
block
.
getInstructions
().
get
(
0
).
getAttributes
().
contains
(
AttributeType
.
CATCH_BLOCK
))
{
}
// splice return block if several predecessors presents
for
(
BlockNode
block
:
mth
.
getExitBlocks
())
{
if
(
block
.
getInstructions
().
size
()
==
1
&&
block
.
getInstructions
().
get
(
0
).
getArgsCount
()
>
0
&&
!
block
.
getInstructions
().
get
(
0
).
getAttributes
().
contains
(
AttributeType
.
CATCH_BLOCK
)
&&
!
block
.
getAttributes
().
contains
(
AttributeFlag
.
SYNTHETIC
))
{
List
<
BlockNode
>
preds
=
new
ArrayList
<
BlockNode
>(
block
.
getPredecessors
());
BlockNode
origRetBlock
=
block
;
origRetBlock
.
getPredecessors
().
clear
();
origRetBlock
.
getPredecessors
().
add
(
preds
.
get
(
0
));
preds
.
remove
(
0
);
InsnNode
origReturnInsn
=
origRetBlock
.
getInstructions
().
get
(
0
);
InsnNode
origReturnInsn
=
block
.
getInstructions
().
get
(
0
);
RegisterArg
retArg
=
null
;
if
(
origReturnInsn
.
getArgsCount
()
!=
0
)
retArg
=
(
RegisterArg
)
origReturnInsn
.
getArg
(
0
);
for
(
BlockNode
pred
:
preds
)
{
pred
.
getSuccessors
().
remove
(
origRetBlock
);
// make copy of return block and connect to predecessor
BlockNode
newRetBlock
=
startNewBlock
(
mth
,
origRetBlock
.
getStartOffset
());
BlockNode
newRetBlock
;
InsnNode
predInsn
=
pred
.
getInstructions
().
get
(
0
);
switch
(
predInsn
.
getType
())
{
case
IF:
// make copy of return block and connect to predecessor
newRetBlock
=
startNewBlock
(
mth
,
block
.
getStartOffset
());
newRetBlock
.
getAttributes
().
add
(
AttributeFlag
.
SYNTHETIC
);
if
(
pred
.
getSuccessors
().
get
(
0
)
==
block
)
{
pred
.
getSuccessors
().
set
(
0
,
newRetBlock
);
}
else
if
(
pred
.
getSuccessors
().
get
(
1
)
==
block
){
pred
.
getSuccessors
().
set
(
1
,
newRetBlock
);
}
block
.
getPredecessors
().
remove
(
pred
);
newRetBlock
.
getPredecessors
().
add
(
pred
);
break
;
case
SWITCH:
// TODO: is it ok to just skip this predecessor?
block
.
getAttributes
().
add
(
AttributeFlag
.
SYNTHETIC
);
continue
;
default
:
removeConnection
(
pred
,
block
);
newRetBlock
=
pred
;
break
;
}
InsnNode
ret
=
new
InsnNode
(
InsnType
.
RETURN
,
1
);
if
(
retArg
!=
null
)
if
(
retArg
!=
null
)
{
ret
.
addArg
(
InsnArg
.
reg
(
retArg
.
getRegNum
(),
retArg
.
getType
()));
ret
.
getArg
(
0
).
forceSetTypedVar
(
retArg
.
getTypedVar
());
}
ret
.
getAttributes
().
addAll
(
origReturnInsn
.
getAttributes
());
newRetBlock
.
getInstructions
().
add
(
ret
);
newRetBlock
.
getAttributes
().
add
(
AttributeFlag
.
RETURN
);
connect
(
pred
,
newRetBlock
);
mth
.
addExitBlock
(
newRetBlock
);
}
return
true
;
if
(
block
.
getPredecessors
().
size
()
==
0
)
{
mth
.
getBasicBlocks
().
remove
(
block
);
mth
.
getExitBlocks
().
remove
(
block
);
return
true
;
}
return
block
.
getAttributes
().
contains
(
AttributeFlag
.
SYNTHETIC
);
}
// TODO detect ternary operator
}
// TODO detect ternary operator
return
false
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java
View file @
5dc4c28d
...
...
@@ -81,13 +81,17 @@ public class CodeShrinker extends AbstractVisitor {
}
}
if
(
wrap
)
{
// if (useInsn.getType() == InsnType.MOVE) {
// // TODO
// // remover.add(useInsn);
// } else {
useInsnArg
.
wrapInstruction
(
insn
);
if
(
insn
.
getType
()
==
InsnType
.
MOVE
)
{
for
(
int
r
=
0
;
r
<
useInsn
.
getArgsCount
();
r
++)
{
if
(
useInsn
.
getArg
(
r
).
getTypedVar
()
==
insn
.
getResult
().
getTypedVar
())
{
useInsn
.
setArg
(
r
,
insn
.
getArg
(
0
));
break
;
}
}
}
else
{
useInsnArg
.
wrapInstruction
(
insn
);
}
remover
.
add
(
insn
);
// }
}
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java
View file @
5dc4c28d
...
...
@@ -3,22 +3,10 @@ package jadx.core.dex.visitors;
import
jadx.core.deobf.NameMapper
;
import
jadx.core.dex.attributes.AttributeType
;
import
jadx.core.dex.info.MethodInfo
;
import
jadx.core.dex.instructions.ConstClassNode
;
import
jadx.core.dex.instructions.ConstStringNode
;
import
jadx.core.dex.instructions.FillArrayNode
;
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.InsnArg
;
import
jadx.core.dex.instructions.args.LiteralArg
;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.instructions.*
;
import
jadx.core.dex.instructions.args.*
;
import
jadx.core.dex.instructions.mods.ConstructorInsn
;
import
jadx.core.dex.nodes.BlockNode
;
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.dex.nodes.*
;
import
jadx.core.dex.trycatch.ExcHandlerAttr
;
import
jadx.core.dex.trycatch.ExceptionHandler
;
import
jadx.core.utils.BlockUtils
;
...
...
@@ -59,6 +47,8 @@ public class ModVisitor extends AbstractVisitor {
int
size
=
block
.
getInstructions
().
size
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
InsnNode
insn
=
block
.
getInstructions
().
get
(
i
);
ClassNode
parentClass
=
mth
.
getParentClass
();
FieldNode
f
=
null
;
switch
(
insn
.
getType
())
{
case
INVOKE:
...
...
@@ -102,8 +92,6 @@ public class ModVisitor extends AbstractVisitor {
case
CONST:
case
CONST_STR:
case
CONST_CLASS:
ClassNode
parentClass
=
mth
.
getParentClass
();
FieldNode
f
=
null
;
if
(
insn
.
getType
()
==
InsnType
.
CONST_STR
)
{
String
s
=
((
ConstStringNode
)
insn
).
getString
();
f
=
parentClass
.
getConstField
(
s
);
...
...
@@ -111,19 +99,7 @@ public class ModVisitor extends AbstractVisitor {
ArgType
t
=
((
ConstClassNode
)
insn
).
getClsType
();
f
=
parentClass
.
getConstField
(
t
);
}
else
{
LiteralArg
arg
=
(
LiteralArg
)
insn
.
getArg
(
0
);
ArgType
type
=
arg
.
getType
();
long
lit
=
arg
.
getLiteral
();
if
(
Math
.
abs
(
lit
)
>
0xFF
)
{
if
(
type
.
equals
(
ArgType
.
INT
))
f
=
parentClass
.
getConstField
((
int
)
lit
);
else
if
(
type
.
equals
(
ArgType
.
LONG
))
f
=
parentClass
.
getConstField
(
lit
);
}
if
(
type
.
equals
(
ArgType
.
DOUBLE
))
f
=
parentClass
.
getConstField
(
Double
.
longBitsToDouble
(
lit
));
else
if
(
type
.
equals
(
ArgType
.
FLOAT
))
f
=
parentClass
.
getConstField
(
Float
.
intBitsToFloat
((
int
)
lit
));
f
=
parentClass
.
getConstFieldByLiteralArg
((
LiteralArg
)
insn
.
getArg
(
0
));
}
if
(
f
!=
null
)
{
InsnNode
inode
=
new
IndexInsnNode
(
InsnType
.
SGET
,
f
.
getFieldInfo
(),
0
);
...
...
@@ -132,6 +108,27 @@ public class ModVisitor extends AbstractVisitor {
}
break
;
case
SWITCH:
SwitchNode
sn
=
(
SwitchNode
)
insn
;
for
(
int
k
=
0
;
k
<
sn
.
getCasesCount
();
k
++)
{
f
=
parentClass
.
getConstField
(
sn
.
getKeys
()[
k
]);
if
(
f
!=
null
)
{
sn
.
getKeys
()[
k
]
=
new
IndexInsnNode
(
InsnType
.
SGET
,
f
.
getFieldInfo
(),
0
);
}
}
break
;
case
RETURN:
if
(
insn
.
getArgsCount
()
>
0
&&
insn
.
getArg
(
0
).
isLiteral
())
{
LiteralArg
arg
=
(
LiteralArg
)
insn
.
getArg
(
0
);
f
=
parentClass
.
getConstFieldByLiteralArg
(
arg
);
if
(
f
!=
null
)
{
arg
.
wrapInstruction
(
new
IndexInsnNode
(
InsnType
.
SGET
,
f
.
getFieldInfo
(),
0
));
}
}
break
;
default
:
break
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java
View file @
5dc4c28d
...
...
@@ -583,21 +583,21 @@ public class RegionMaker {
int
len
=
insn
.
getTargets
().
length
;
// sort by target
Map
<
Integer
,
List
<
Integer
>>
casesMap
=
new
LinkedHashMap
<
Integer
,
List
<
Integer
>>(
len
);
Map
<
Integer
,
List
<
Object
>>
casesMap
=
new
LinkedHashMap
<
Integer
,
List
<
Object
>>(
len
);
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
in
t
key
=
insn
.
getKeys
()[
i
];
Objec
t
key
=
insn
.
getKeys
()[
i
];
int
targ
=
insn
.
getTargets
()[
i
];
List
<
Integer
>
keys
=
casesMap
.
get
(
targ
);
List
<
Object
>
keys
=
casesMap
.
get
(
targ
);
if
(
keys
==
null
)
{
keys
=
new
ArrayList
<
Integer
>(
1
);
keys
=
new
ArrayList
<
Object
>(
2
);
casesMap
.
put
(
targ
,
keys
);
}
keys
.
add
(
key
);
}
Map
<
BlockNode
,
List
<
Integer
>>
blocksMap
=
new
LinkedHashMap
<
BlockNode
,
List
<
Integer
>>(
len
);
for
(
Entry
<
Integer
,
List
<
Integer
>>
entry
:
casesMap
.
entrySet
())
{
BlockNode
c
=
getBlockByOffset
(
entry
.
getKey
(),
block
.
getSuccessors
());
Map
<
BlockNode
,
List
<
Object
>>
blocksMap
=
new
LinkedHashMap
<
BlockNode
,
List
<
Object
>>(
len
);
for
(
Entry
<
Integer
,
List
<
Object
>>
entry
:
casesMap
.
entrySet
())
{
BlockNode
c
=
getBlockByOffset
(
(
int
)
entry
.
getKey
(),
block
.
getSuccessors
());
assert
c
!=
null
;
blocksMap
.
put
(
c
,
entry
.
getValue
());
}
...
...
@@ -650,7 +650,7 @@ public class RegionMaker {
if
(!
stack
.
containsExit
(
defCase
))
{
sw
.
setDefaultCase
(
makeRegion
(
defCase
,
stack
));
}
for
(
Entry
<
BlockNode
,
List
<
Integer
>>
entry
:
blocksMap
.
entrySet
())
{
for
(
Entry
<
BlockNode
,
List
<
Object
>>
entry
:
blocksMap
.
entrySet
())
{
BlockNode
c
=
entry
.
getKey
();
if
(
stack
.
containsExit
(
c
))
{
// empty case block
...
...
jadx-core/src/test/java/jadx/tests/internal/TestReturnWrapping.java
0 → 100644
View file @
5dc4c28d
package
jadx
.
tests
.
internal
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestReturnWrapping
extends
InternalJadxTest
{
public
static
class
TestCls
{
/**/
public
static
int
f1
(
int
arg0
)
{
switch
(
arg0
)
{
case
1
:
return
255
;
}
return
arg0
+
1
;
}
/**/
/**/
public
static
Object
f2
(
Object
arg0
,
int
arg1
)
{
Object
ret
=
null
;
int
i
=
arg1
;
if
(
arg0
==
null
)
{
return
ret
+
Integer
.
toHexString
(
i
);
}
else
{
i
++;
try
{
ret
=
new
Object
().
getClass
();
}
catch
(
Exception
e
)
{
ret
=
"Qwerty"
;
}
return
i
>
128
?
arg0
.
toString
()
+
ret
.
toString
()
:
i
;
}
}
/**/
/**/
public
static
int
f3
(
int
arg0
)
{
while
(
arg0
>
10
)
{
int
abc
=
951
;
if
(
arg0
==
255
)
{
return
arg0
+
2
;
}
arg0
-=
abc
;
}
return
arg0
;
}
/**/
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsString
(
"return 255;"
));
assertThat
(
code
,
containsString
(
"return arg0 + 1;"
));
//assertThat(code, containsString("return Integer.toHexString(i);"));
assertThat
(
code
,
containsString
(
"return arg0.toString() + ret.toString();"
));
assertThat
(
code
,
containsString
(
"return arg0 + 2;"
));
assertThat
(
code
,
containsString
(
"arg0 -= 951;"
));
}
}
jadx-core/src/test/java/jadx/tests/internal/TestSwitchLabels.java
0 → 100644
View file @
5dc4c28d
package
jadx
.
tests
.
internal
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
hamcrest
.
CoreMatchers
.
not
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
mockito
.
AdditionalMatchers
.
or
;
public
class
TestSwitchLabels
extends
InternalJadxTest
{
public
static
class
TestCls
{
public
static
final
int
CONST_ABC
=
0xABC
;
public
static
final
int
CONST_CDE
=
0xCDE
;
public
static
class
Inner
{
private
static
final
int
CONST_CDE_PRIVATE
=
0xCDE
;
public
int
f1
(
int
arg0
)
{
switch
(
arg0
)
{
case
CONST_CDE_PRIVATE:
return
CONST_ABC
;
}
return
0
;
}
}
public
static
int
f1
(
int
arg0
)
{
switch
(
arg0
)
{
case
CONST_ABC:
return
CONST_CDE
;
}
return
0
;
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsString
(
"case CONST_ABC:"
));
assertThat
(
code
,
containsString
(
"return CONST_CDE;"
));
cls
.
addInnerClass
(
getClassNode
(
TestCls
.
Inner
.
class
));
assertThat
(
code
,
containsString
(
"case CONST_CDE_PRIVATE:"
));
assertThat
(
code
,
containsString
(
".CONST_ABC;"
));
}
}
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