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
8a6cdec7
Commit
8a6cdec7
authored
Feb 14, 2015
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: refactor fill-array instruction processing and constants replace (fix #48)
parent
c5c4499a
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
347 additions
and
205 deletions
+347
-205
InsnGen.java
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
+25
-83
NameGen.java
jadx-core/src/main/java/jadx/core/codegen/NameGen.java
+1
-3
FillArrayNode.java
...c/main/java/jadx/core/dex/instructions/FillArrayNode.java
+35
-0
FilledNewArrayNode.java
...n/java/jadx/core/dex/instructions/FilledNewArrayNode.java
+39
-0
InsnDecoder.java
...src/main/java/jadx/core/dex/instructions/InsnDecoder.java
+8
-14
ModVisitor.java
...core/src/main/java/jadx/core/dex/visitors/ModVisitor.java
+131
-91
ReSugarCode.java
...ore/src/main/java/jadx/core/dex/visitors/ReSugarCode.java
+4
-1
BlockExceptionHandler.java
.../core/dex/visitors/blocksmaker/BlockExceptionHandler.java
+0
-12
TestArrayFillConstReplace.java
...x/tests/integration/arrays/TestArrayFillConstReplace.java
+28
-0
TestArrays2.java
.../test/java/jadx/tests/integration/arrays/TestArrays2.java
+42
-0
TestFallbackMode.java
...ava/jadx/tests/integration/fallback/TestFallbackMode.java
+1
-1
TestArithConst.java
jadx-core/src/test/java/jadx/tests/smali/TestArithConst.java
+21
-0
TestArithConst.smali
jadx-core/src/test/smali/TestArithConst.smali
+12
-0
No files found.
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
View file @
8a6cdec7
...
...
@@ -13,6 +13,7 @@ import jadx.core.dex.instructions.ArithOp;
import
jadx.core.dex.instructions.ConstClassNode
;
import
jadx.core.dex.instructions.ConstStringNode
;
import
jadx.core.dex.instructions.FillArrayNode
;
import
jadx.core.dex.instructions.FilledNewArrayNode
;
import
jadx.core.dex.instructions.GotoNode
;
import
jadx.core.dex.instructions.IfNode
;
import
jadx.core.dex.instructions.IndexInsnNode
;
...
...
@@ -34,14 +35,13 @@ import jadx.core.dex.nodes.FieldNode;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.utils.ErrorsCounter
;
import
jadx.core.utils.InsnUtils
;
import
jadx.core.utils.RegionUtils
;
import
jadx.core.utils.StringUtils
;
import
jadx.core.utils.exceptions.CodegenException
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.EnumSet
;
import
java.util.HashMap
;
import
java.util.Iterator
;
...
...
@@ -359,12 +359,8 @@ public class InsnGen {
code
.
add
(
".length"
);
break
;
case
FILL_ARRAY:
fillArray
((
FillArrayNode
)
insn
,
code
);
break
;
case
FILLED_NEW_ARRAY:
filledNewArray
(
insn
,
code
);
filledNewArray
(
(
FilledNewArrayNode
)
insn
,
code
);
break
;
case
AGET:
...
...
@@ -490,6 +486,25 @@ public class InsnGen {
code
.
startLine
(
'}'
);
break
;
case
FILL_ARRAY:
assert
isFallback
();
FillArrayNode
arrayNode
=
(
FillArrayNode
)
insn
;
Object
data
=
arrayNode
.
getData
();
String
arrStr
;
if
(
data
instanceof
int
[])
{
arrStr
=
Arrays
.
toString
((
int
[])
data
);
}
else
if
(
data
instanceof
short
[])
{
arrStr
=
Arrays
.
toString
((
short
[])
data
);
}
else
if
(
data
instanceof
byte
[])
{
arrStr
=
Arrays
.
toString
((
byte
[])
data
);
}
else
if
(
data
instanceof
long
[])
{
arrStr
=
Arrays
.
toString
((
long
[])
data
);
}
else
{
arrStr
=
"?"
;
}
code
.
add
(
'{'
).
add
(
arrStr
.
substring
(
1
,
arrStr
.
length
()
-
1
)).
add
(
'}'
);
break
;
case
NEW_INSTANCE:
// only fallback - make new instance in constructor invoke
assert
isFallback
();
...
...
@@ -501,11 +516,11 @@ public class InsnGen {
}
}
private
void
filledNewArray
(
InsnNode
insn
,
CodeWriter
code
)
throws
CodegenException
{
int
c
=
insn
.
getArgsCount
();
private
void
filledNewArray
(
FilledNewArrayNode
insn
,
CodeWriter
code
)
throws
CodegenException
{
code
.
add
(
"new "
);
useType
(
code
,
insn
.
get
Result
().
get
Type
());
useType
(
code
,
insn
.
get
Array
Type
());
code
.
add
(
'{'
);
int
c
=
insn
.
getArgsCount
();
for
(
int
i
=
0
;
i
<
c
;
i
++)
{
addArg
(
code
,
insn
.
getArg
(
i
),
false
);
if
(
i
+
1
<
c
)
{
...
...
@@ -515,76 +530,6 @@ public class InsnGen {
code
.
add
(
'}'
);
}
private
void
fillArray
(
FillArrayNode
insn
,
CodeWriter
code
)
throws
CodegenException
{
String
filledArray
=
makeArrayElements
(
insn
);
code
.
add
(
"new "
);
useType
(
code
,
insn
.
getElementType
());
code
.
add
(
"[]{"
).
add
(
filledArray
).
add
(
'}'
);
}
private
String
makeArrayElements
(
FillArrayNode
insn
)
throws
CodegenException
{
ArgType
insnArrayType
=
insn
.
getResult
().
getType
();
ArgType
insnElementType
=
insnArrayType
.
getArrayElement
();
ArgType
elType
=
insn
.
getElementType
();
if
(!
elType
.
equals
(
insnElementType
)
&&
!
insnArrayType
.
equals
(
ArgType
.
OBJECT
))
{
ErrorsCounter
.
methodError
(
mth
,
"Incorrect type for fill-array insn "
+
InsnUtils
.
formatOffset
(
insn
.
getOffset
())
+
", element type: "
+
elType
+
", insn element type: "
+
insnElementType
);
}
if
(!
elType
.
isTypeKnown
())
{
LOG
.
warn
(
"Unknown array element type: {} in mth: {}"
,
elType
,
mth
);
elType
=
insnElementType
.
isTypeKnown
()
?
insnElementType
:
elType
.
selectFirst
();
if
(
elType
==
null
)
{
throw
new
JadxRuntimeException
(
"Null array element type"
);
}
}
insn
.
mergeElementType
(
elType
);
StringBuilder
str
=
new
StringBuilder
();
Object
data
=
insn
.
getData
();
switch
(
elType
.
getPrimitiveType
())
{
case
BOOLEAN:
case
BYTE:
byte
[]
array
=
(
byte
[])
data
;
for
(
byte
b
:
array
)
{
str
.
append
(
TypeGen
.
literalToString
(
b
,
elType
));
str
.
append
(
", "
);
}
break
;
case
SHORT:
case
CHAR:
short
[]
sarray
=
(
short
[])
data
;
for
(
short
b
:
sarray
)
{
str
.
append
(
TypeGen
.
literalToString
(
b
,
elType
));
str
.
append
(
", "
);
}
break
;
case
INT:
case
FLOAT:
int
[]
iarray
=
(
int
[])
data
;
for
(
int
b
:
iarray
)
{
str
.
append
(
TypeGen
.
literalToString
(
b
,
elType
));
str
.
append
(
", "
);
}
break
;
case
LONG:
case
DOUBLE:
long
[]
larray
=
(
long
[])
data
;
for
(
long
b
:
larray
)
{
str
.
append
(
TypeGen
.
literalToString
(
b
,
elType
));
str
.
append
(
", "
);
}
break
;
default
:
throw
new
CodegenException
(
mth
,
"Unknown type: "
+
elType
);
}
int
len
=
str
.
length
();
str
.
delete
(
len
-
2
,
len
);
return
str
.
toString
();
}
private
void
makeConstructor
(
ConstructorInsn
insn
,
CodeWriter
code
)
throws
CodegenException
{
ClassNode
cls
=
mth
.
dex
().
resolveClass
(
insn
.
getClassType
());
...
...
@@ -734,9 +679,6 @@ public class InsnGen {
}
}
return
true
;
}
else
if
(
insn
.
getType
()
==
InsnType
.
FILL_ARRAY
)
{
code
.
add
(
makeArrayElements
((
FillArrayNode
)
insn
));
return
true
;
}
return
false
;
}
...
...
jadx-core/src/main/java/jadx/core/codegen/NameGen.java
View file @
8a6cdec7
...
...
@@ -115,9 +115,7 @@ public class NameGen {
}
private
String
getFallbackName
(
RegisterArg
arg
)
{
String
name
=
arg
.
getName
();
String
base
=
"r"
+
arg
.
getRegNum
();
return
name
!=
null
?
base
+
"_"
+
name
:
base
;
return
"r"
+
arg
.
getRegNum
();
}
private
static
String
makeNameForType
(
ArgType
type
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/FillArrayNode.java
View file @
8a6cdec7
...
...
@@ -2,15 +2,20 @@ package jadx.core.dex.instructions;
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.nodes.InsnNode
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
com.android.dx.io.instructions.FillArrayDataPayloadDecodedInstruction
;
public
final
class
FillArrayNode
extends
InsnNode
{
private
final
Object
data
;
private
final
int
size
;
private
ArgType
elemType
;
public
FillArrayNode
(
int
resReg
,
FillArrayDataPayloadDecodedInstruction
payload
)
{
...
...
@@ -36,6 +41,7 @@ public final class FillArrayNode extends InsnNode {
setResult
(
InsnArg
.
reg
(
resReg
,
ArgType
.
array
(
elType
)));
this
.
data
=
payload
.
getData
();
this
.
size
=
payload
.
getSize
();
this
.
elemType
=
elType
;
}
...
...
@@ -43,6 +49,10 @@ public final class FillArrayNode extends InsnNode {
return
data
;
}
public
int
getSize
()
{
return
size
;
}
public
ArgType
getElementType
()
{
return
elemType
;
}
...
...
@@ -54,6 +64,31 @@ public final class FillArrayNode extends InsnNode {
}
}
public
List
<
LiteralArg
>
getLiteralArgs
()
{
List
<
LiteralArg
>
list
=
new
ArrayList
<
LiteralArg
>(
size
);
Object
array
=
data
;
if
(
array
instanceof
int
[])
{
for
(
int
b
:
(
int
[])
array
)
{
list
.
add
(
InsnArg
.
lit
(
b
,
elemType
));
}
}
else
if
(
array
instanceof
byte
[])
{
for
(
byte
b
:
(
byte
[])
array
)
{
list
.
add
(
InsnArg
.
lit
(
b
,
elemType
));
}
}
else
if
(
array
instanceof
short
[])
{
for
(
short
b
:
(
short
[])
array
)
{
list
.
add
(
InsnArg
.
lit
(
b
,
elemType
));
}
}
else
if
(
array
instanceof
long
[])
{
for
(
long
b
:
(
long
[])
array
)
{
list
.
add
(
InsnArg
.
lit
(
b
,
elemType
));
}
}
else
{
throw
new
JadxRuntimeException
(
"Unknown type: "
+
data
.
getClass
()
+
", expected: "
+
elemType
);
}
return
list
;
}
@Override
public
boolean
isSame
(
InsnNode
obj
)
{
if
(
this
==
obj
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/FilledNewArrayNode.java
0 → 100644
View file @
8a6cdec7
package
jadx
.
core
.
dex
.
instructions
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.nodes.InsnNode
;
public
class
FilledNewArrayNode
extends
InsnNode
{
private
final
ArgType
elemType
;
public
FilledNewArrayNode
(
ArgType
elemType
,
int
size
)
{
super
(
InsnType
.
FILLED_NEW_ARRAY
,
size
);
this
.
elemType
=
elemType
;
}
public
ArgType
getElemType
()
{
return
elemType
;
}
public
ArgType
getArrayType
()
{
return
ArgType
.
array
(
elemType
);
}
@Override
public
boolean
isSame
(
InsnNode
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
FilledNewArrayNode
)
||
!
super
.
isSame
(
obj
))
{
return
false
;
}
FilledNewArrayNode
other
=
(
FilledNewArrayNode
)
obj
;
return
elemType
==
other
.
elemType
;
}
@Override
public
String
toString
()
{
return
super
.
toString
()
+
" elemType: "
+
elemType
;
}
}
jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java
View file @
8a6cdec7
...
...
@@ -620,9 +620,14 @@ public class InsnDecoder {
regs
[
i
]
=
InsnArg
.
reg
(
regNum
,
elType
,
typeImmutable
);
}
}
return
insn
(
InsnType
.
FILLED_NEW_ARRAY
,
resReg
==
-
1
?
null
:
InsnArg
.
reg
(
resReg
,
arrType
),
regs
);
InsnNode
node
=
new
FilledNewArrayNode
(
elType
,
regs
==
null
?
0
:
regs
.
length
);
node
.
setResult
(
resReg
==
-
1
?
null
:
InsnArg
.
reg
(
resReg
,
arrType
));
if
(
regs
!=
null
)
{
for
(
InsnArg
arg
:
regs
)
{
node
.
addArg
(
arg
);
}
}
return
node
;
}
private
InsnNode
cmp
(
DecodedInstruction
insn
,
InsnType
itype
,
ArgType
argType
)
{
...
...
@@ -690,17 +695,6 @@ public class InsnDecoder {
return
node
;
}
private
InsnNode
insn
(
InsnType
type
,
RegisterArg
res
,
InsnArg
...
args
)
{
InsnNode
node
=
new
InsnNode
(
type
,
args
==
null
?
0
:
args
.
length
);
node
.
setResult
(
res
);
if
(
args
!=
null
)
{
for
(
InsnArg
arg
:
args
)
{
node
.
addArg
(
arg
);
}
}
return
node
;
}
private
int
getMoveResultRegister
(
DecodedInstruction
[]
insnArr
,
int
offset
)
{
int
nextOffset
=
getNextInsnOffset
(
insnArr
,
offset
);
if
(
nextOffset
>=
0
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java
View file @
8a6cdec7
...
...
@@ -4,9 +4,11 @@ import jadx.core.codegen.TypeGen;
import
jadx.core.deobf.NameMapper
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.info.MethodInfo
;
import
jadx.core.dex.instructions.ArithNode
;
import
jadx.core.dex.instructions.ConstClassNode
;
import
jadx.core.dex.instructions.ConstStringNode
;
import
jadx.core.dex.instructions.FillArrayNode
;
import
jadx.core.dex.instructions.FilledNewArrayNode
;
import
jadx.core.dex.instructions.IndexInsnNode
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.InvokeNode
;
...
...
@@ -25,9 +27,13 @@ import jadx.core.dex.nodes.InsnNode;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.trycatch.ExcHandlerAttr
;
import
jadx.core.dex.trycatch.ExceptionHandler
;
import
jadx.core.utils.ErrorsCounter
;
import
jadx.core.utils.InsnUtils
;
import
jadx.core.utils.InstructionRemover
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -95,20 +101,64 @@ public class ModVisitor extends AbstractVisitor {
}
break
;
case
RETURN:
if
(
insn
.
getArgsCount
()
>
0
&&
insn
.
getArg
(
0
).
isLiteral
())
{
LiteralArg
arg
=
(
LiteralArg
)
insn
.
getArg
(
0
);
FieldNode
f
=
parentClass
.
getConstFieldByLiteralArg
(
arg
);
if
(
f
!=
null
)
{
arg
.
wrapInstruction
(
new
IndexInsnNode
(
InsnType
.
SGET
,
f
.
getFieldInfo
(),
0
));
case
NEW_ARRAY:
// create array in 'fill-array' instruction
int
next
=
i
+
1
;
if
(
next
<
size
)
{
InsnNode
ni
=
block
.
getInstructions
().
get
(
next
);
if
(
ni
.
getType
()
==
InsnType
.
FILL_ARRAY
)
{
ni
.
getResult
().
merge
(
insn
.
getResult
());
((
FillArrayNode
)
ni
).
mergeElementType
(
insn
.
getResult
().
getType
().
getArrayElement
());
remover
.
add
(
insn
);
}
}
break
;
case
FILL_ARRAY:
InsnNode
filledArr
=
makeFilledArrayInsn
(
mth
,
(
FillArrayNode
)
insn
);
replaceInsn
(
block
,
i
,
filledArr
);
break
;
case
MOVE_EXCEPTION:
processMoveException
(
mth
,
block
,
insn
,
remover
);
break
;
case
ARITH:
ArithNode
arithNode
=
(
ArithNode
)
insn
;
if
(
arithNode
.
getArgsCount
()
==
2
)
{
InsnArg
litArg
=
arithNode
.
getArg
(
1
);
if
(
litArg
.
isLiteral
())
{
FieldNode
f
=
parentClass
.
getConstFieldByLiteralArg
((
LiteralArg
)
litArg
);
if
(
f
!=
null
)
{
InsnNode
fGet
=
new
IndexInsnNode
(
InsnType
.
SGET
,
f
.
getFieldInfo
(),
0
);
insn
.
replaceArg
(
litArg
,
InsnArg
.
wrapArg
(
fGet
));
}
}
}
break
;
default
:
break
;
}
}
remover
.
perform
();
}
}
/**
* Remove unnecessary instructions
*/
private
static
void
removeStep
(
MethodNode
mth
,
InstructionRemover
remover
)
{
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
remover
.
setBlock
(
block
);
for
(
InsnNode
insn
:
block
.
getInstructions
())
{
switch
(
insn
.
getType
())
{
case
NOP:
case
GOTO:
case
NEW_INSTANCE:
remover
.
add
(
insn
);
break
;
default
:
break
;
}
...
...
@@ -122,50 +172,51 @@ public class ModVisitor extends AbstractVisitor {
InsnNode
insn
=
block
.
getInstructions
().
get
(
insnNumber
);
InvokeNode
inv
=
(
InvokeNode
)
insn
;
MethodInfo
callMth
=
inv
.
getCallMth
();
if
(
callMth
.
isConstructor
())
{
InsnNode
instArgAssignInsn
=
((
RegisterArg
)
inv
.
getArg
(
0
)).
getAssignInsn
();
ConstructorInsn
co
=
new
ConstructorInsn
(
mth
,
inv
);
boolean
remove
=
false
;
if
(
co
.
isSuper
()
&&
(
co
.
getArgsCount
()
==
0
||
parentClass
.
isEnum
()))
{
remove
=
true
;
}
else
if
(
co
.
isThis
()
&&
co
.
getArgsCount
()
==
0
)
{
MethodNode
defCo
=
parentClass
.
searchMethodByName
(
callMth
.
getShortId
());
if
(
defCo
==
null
||
defCo
.
isNoCode
())
{
// default constructor not implemented
remove
=
true
;
}
}
// remove super() call in instance initializer
if
(
parentClass
.
isAnonymous
()
&&
mth
.
isDefaultConstructor
()
&&
co
.
isSuper
())
{
if
(!
callMth
.
isConstructor
())
{
return
;
}
InsnNode
instArgAssignInsn
=
((
RegisterArg
)
inv
.
getArg
(
0
)).
getAssignInsn
();
ConstructorInsn
co
=
new
ConstructorInsn
(
mth
,
inv
);
boolean
remove
=
false
;
if
(
co
.
isSuper
()
&&
(
co
.
getArgsCount
()
==
0
||
parentClass
.
isEnum
()))
{
remove
=
true
;
}
else
if
(
co
.
isThis
()
&&
co
.
getArgsCount
()
==
0
)
{
MethodNode
defCo
=
parentClass
.
searchMethodByName
(
callMth
.
getShortId
());
if
(
defCo
==
null
||
defCo
.
isNoCode
())
{
// default constructor not implemented
remove
=
true
;
}
if
(
remove
)
{
remover
.
add
(
insn
);
}
else
{
replaceInsn
(
block
,
insnNumber
,
co
);
if
(
co
.
isNewInstance
())
{
InsnNode
newInstInsn
=
removeAssignChain
(
instArgAssignInsn
,
remover
,
InsnType
.
NEW_INSTANCE
);
if
(
newInstInsn
!=
null
)
{
RegisterArg
instArg
=
newInstInsn
.
getResult
();
RegisterArg
resultArg
=
co
.
getResult
();
if
(!
resultArg
.
equals
(
instArg
))
{
// replace all usages of 'instArg' with result of this constructor instruction
for
(
RegisterArg
useArg
:
new
ArrayList
<
RegisterArg
>(
instArg
.
getSVar
().
getUseList
()))
{
RegisterArg
dup
=
resultArg
.
duplicate
();
InsnNode
parentInsn
=
useArg
.
getParentInsn
();
parentInsn
.
replaceArg
(
useArg
,
dup
);
dup
.
setParentInsn
(
parentInsn
);
resultArg
.
getSVar
().
use
(
dup
);
}
}
}
// remove super() call in instance initializer
if
(
parentClass
.
isAnonymous
()
&&
mth
.
isDefaultConstructor
()
&&
co
.
isSuper
())
{
remove
=
true
;
}
if
(
remove
)
{
remover
.
add
(
insn
);
return
;
}
replaceInsn
(
block
,
insnNumber
,
co
);
if
(
co
.
isNewInstance
())
{
InsnNode
newInstInsn
=
removeAssignChain
(
instArgAssignInsn
,
remover
,
InsnType
.
NEW_INSTANCE
);
if
(
newInstInsn
!=
null
)
{
RegisterArg
instArg
=
newInstInsn
.
getResult
();
RegisterArg
resultArg
=
co
.
getResult
();
if
(!
resultArg
.
equals
(
instArg
))
{
// replace all usages of 'instArg' with result of this constructor instruction
for
(
RegisterArg
useArg
:
new
ArrayList
<
RegisterArg
>(
instArg
.
getSVar
().
getUseList
()))
{
RegisterArg
dup
=
resultArg
.
duplicate
();
InsnNode
parentInsn
=
useArg
.
getParentInsn
();
parentInsn
.
replaceArg
(
useArg
,
dup
);
dup
.
setParentInsn
(
parentInsn
);
resultArg
.
getSVar
().
use
(
dup
);
}
}
ConstructorInsn
replace
=
processConstructor
(
mth
,
co
);
if
(
replace
!=
null
)
{
replaceInsn
(
block
,
insnNumber
,
replace
);
}
}
}
ConstructorInsn
replace
=
processConstructor
(
mth
,
co
);
if
(
replace
!=
null
)
{
replaceInsn
(
block
,
insnNumber
,
replace
);
}
}
/**
...
...
@@ -193,6 +244,41 @@ public class ModVisitor extends AbstractVisitor {
return
newInsn
;
}
private
static
InsnNode
makeFilledArrayInsn
(
MethodNode
mth
,
FillArrayNode
insn
)
{
ArgType
insnArrayType
=
insn
.
getResult
().
getType
();
ArgType
insnElementType
=
insnArrayType
.
getArrayElement
();
ArgType
elType
=
insn
.
getElementType
();
if
(!
elType
.
equals
(
insnElementType
)
&&
!
insnArrayType
.
equals
(
ArgType
.
OBJECT
))
{
ErrorsCounter
.
methodError
(
mth
,
"Incorrect type for fill-array insn "
+
InsnUtils
.
formatOffset
(
insn
.
getOffset
())
+
", element type: "
+
elType
+
", insn element type: "
+
insnElementType
);
}
if
(!
elType
.
isTypeKnown
())
{
LOG
.
warn
(
"Unknown array element type: {} in mth: {}"
,
elType
,
mth
);
elType
=
insnElementType
.
isTypeKnown
()
?
insnElementType
:
elType
.
selectFirst
();
if
(
elType
==
null
)
{
throw
new
JadxRuntimeException
(
"Null array element type"
);
}
}
insn
.
mergeElementType
(
elType
);
elType
=
insn
.
getElementType
();
List
<
LiteralArg
>
list
=
insn
.
getLiteralArgs
();
InsnNode
filledArr
=
new
FilledNewArrayNode
(
elType
,
list
.
size
());
filledArr
.
setResult
(
insn
.
getResult
());
for
(
LiteralArg
arg
:
list
)
{
FieldNode
f
=
mth
.
getParentClass
().
getConstFieldByLiteralArg
(
arg
);
if
(
f
!=
null
)
{
InsnNode
fGet
=
new
IndexInsnNode
(
InsnType
.
SGET
,
f
.
getFieldInfo
(),
0
);
filledArr
.
addArg
(
InsnArg
.
wrapArg
(
fGet
));
}
else
{
filledArr
.
addArg
(
arg
);
}
}
return
filledArr
;
}
private
static
boolean
allArgsNull
(
InsnNode
insn
)
{
for
(
InsnArg
insnArg
:
insn
.
getArguments
())
{
if
(
insnArg
.
isLiteral
())
{
...
...
@@ -226,53 +312,6 @@ public class ModVisitor extends AbstractVisitor {
return
null
;
}
/**
* Remove unnecessary instructions
*/
private
static
void
removeStep
(
MethodNode
mth
,
InstructionRemover
remover
)
{
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
remover
.
setBlock
(
block
);
int
size
=
block
.
getInstructions
().
size
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
InsnNode
insn
=
block
.
getInstructions
().
get
(
i
);
switch
(
insn
.
getType
())
{
case
NOP:
case
GOTO:
case
NEW_INSTANCE:
remover
.
add
(
insn
);
break
;
case
NEW_ARRAY:
// create array in 'fill-array' instruction
int
next
=
i
+
1
;
if
(
next
<
size
)
{
InsnNode
ni
=
block
.
getInstructions
().
get
(
next
);
if
(
ni
.
getType
()
==
InsnType
.
FILL_ARRAY
)
{
ni
.
getResult
().
merge
(
insn
.
getResult
());
((
FillArrayNode
)
ni
).
mergeElementType
(
insn
.
getResult
().
getType
().
getArrayElement
());
remover
.
add
(
insn
);
}
}
break
;
case
RETURN:
if
(
insn
.
getArgsCount
()
==
0
)
{
if
(
mth
.
getBasicBlocks
().
size
()
==
1
&&
i
==
size
-
1
)
{
remover
.
add
(
insn
);
}
else
if
(
mth
.
getMethodInfo
().
isClassInit
())
{
remover
.
add
(
insn
);
}
}
break
;
default
:
break
;
}
}
remover
.
perform
();
}
}
private
static
void
processMoveException
(
MethodNode
mth
,
BlockNode
block
,
InsnNode
insn
,
InstructionRemover
remover
)
{
ExcHandlerAttr
excHandlerAttr
=
block
.
get
(
AType
.
EXC_HANDLER
);
...
...
@@ -310,6 +349,7 @@ public class ModVisitor extends AbstractVisitor {
private
static
void
replaceInsn
(
BlockNode
block
,
int
i
,
InsnNode
insn
)
{
InsnNode
prevInsn
=
block
.
getInstructions
().
get
(
i
);
insn
.
copyAttributesFrom
(
prevInsn
);
insn
.
setSourceLine
(
prevInsn
.
getSourceLine
());
block
.
getInstructions
().
set
(
i
,
insn
);
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ReSugarCode.java
View file @
8a6cdec7
...
...
@@ -5,10 +5,12 @@ import jadx.core.dex.attributes.AType;
import
jadx.core.dex.attributes.nodes.EnumMapAttr
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.core.dex.info.FieldInfo
;
import
jadx.core.dex.instructions.FilledNewArrayNode
;
import
jadx.core.dex.instructions.IndexInsnNode
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.InvokeNode
;
import
jadx.core.dex.instructions.SwitchNode
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.instructions.args.InsnArg
;
import
jadx.core.dex.instructions.args.InsnWrapArg
;
import
jadx.core.dex.instructions.args.LiteralArg
;
...
...
@@ -78,7 +80,8 @@ public class ReSugarCode extends AbstractVisitor {
if
(
len
<=
0
||
i
+
len
>=
size
||
instructions
.
get
(
i
+
len
).
getType
()
!=
InsnType
.
APUT
)
{
return
null
;
}
InsnNode
filledArr
=
new
InsnNode
(
InsnType
.
FILLED_NEW_ARRAY
,
len
);
ArgType
arrType
=
insn
.
getResult
().
getType
();
InsnNode
filledArr
=
new
FilledNewArrayNode
(
arrType
.
getArrayElement
(),
len
);
filledArr
.
setResult
(
insn
.
getResult
());
for
(
int
j
=
0
;
j
<
len
;
j
++)
{
InsnNode
put
=
instructions
.
get
(
i
+
1
+
j
);
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockExceptionHandler.java
View file @
8a6cdec7
...
...
@@ -17,8 +17,6 @@ import jadx.core.dex.visitors.AbstractVisitor;
import
jadx.core.utils.BlockUtils
;
import
jadx.core.utils.InstructionRemover
;
import
java.util.Iterator
;
public
class
BlockExceptionHandler
extends
AbstractVisitor
{
@Override
...
...
@@ -38,16 +36,6 @@ public class BlockExceptionHandler extends AbstractVisitor {
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
processTryCatchBlocks
(
mth
,
block
);
}
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
Iterator
<
InsnNode
>
it
=
block
.
getInstructions
().
iterator
();
while
(
it
.
hasNext
())
{
InsnNode
insn
=
it
.
next
();
if
(
insn
.
getType
()
==
InsnType
.
NOP
)
{
it
.
remove
();
}
}
}
}
/**
...
...
jadx-core/src/test/java/jadx/tests/integration/arrays/TestArrayFillConstReplace.java
0 → 100644
View file @
8a6cdec7
package
jadx
.
tests
.
integration
.
arrays
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.IntegrationTest
;
import
org.junit.Test
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestArrayFillConstReplace
extends
IntegrationTest
{
public
static
class
TestCls
{
public
static
final
int
CONST_INT
=
0xffff
;
public
int
[]
test
()
{
return
new
int
[]{
127
,
129
,
CONST_INT
};
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"return new int[]{127, 129, CONST_INT};"
));
}
}
jadx-core/src/test/java/jadx/tests/integration/arrays/TestArrays2.java
0 → 100644
View file @
8a6cdec7
package
jadx
.
tests
.
integration
.
arrays
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.IntegrationTest
;
import
org.junit.Test
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
hamcrest
.
CoreMatchers
.
instanceOf
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestArrays2
extends
IntegrationTest
{
public
static
class
TestCls
{
private
static
Object
test4
(
int
type
)
{
if
(
type
==
1
)
{
return
new
int
[]{
1
,
2
};
}
else
if
(
type
==
2
)
{
return
new
float
[]{
1
,
2
};
}
else
if
(
type
==
3
)
{
return
new
short
[]{
1
,
2
};
}
else
if
(
type
==
4
)
{
return
new
byte
[]{
1
,
2
};
}
else
{
return
null
;
}
}
public
void
check
()
{
assertThat
(
test4
(
4
),
instanceOf
(
byte
[].
class
));
}
}
@Test
public
void
test
()
{
noDebugInfo
();
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"new int[]{1, 2}"
));
}
}
jadx-core/src/test/java/jadx/tests/integration/fallback/TestFallbackMode.java
View file @
8a6cdec7
...
...
@@ -30,7 +30,7 @@ public class TestFallbackMode extends IntegrationTest {
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsString
(
"public int test(int r2) {"
));
assertThat
(
code
,
containsString
(
"r1
_this
= this;"
));
assertThat
(
code
,
containsString
(
"r1 = this;"
));
assertThat
(
code
,
containsString
(
"L_0x0004:"
));
assertThat
(
code
,
not
(
containsString
(
"throw new UnsupportedOperationException"
)));
}
...
...
jadx-core/src/test/java/jadx/tests/smali/TestArithConst.java
0 → 100644
View file @
8a6cdec7
package
jadx
.
tests
.
smali
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.tests.api.SmaliTest
;
import
org.junit.Test
;
import
static
jadx
.
tests
.
api
.
utils
.
JadxMatchers
.
containsOne
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestArithConst
extends
SmaliTest
{
@Test
public
void
test
()
{
noDebugInfo
();
ClassNode
cls
=
getClassNodeFromSmali
(
"TestArithConst"
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"return i + CONST_INT;"
));
}
}
jadx-core/src/test/smali/TestArithConst.smali
0 → 100644
View file @
8a6cdec7
.class public LTestArithConst;
.super Ljava/lang/Object;
.field public static final CONST_INT:I = 0xff
.method private test(I)I
.registers 2
add-int/lit16 v0, p1, 0xff
return v0
.end method
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