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
30355cc9
Commit
30355cc9
authored
Dec 06, 2013
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: remove synthetic fields for inner classes
parent
ed67f8e1
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
233 additions
and
111 deletions
+233
-111
ClassGen.java
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
+3
-0
InsnGen.java
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
+43
-29
AttributeFlag.java
...src/main/java/jadx/core/dex/attributes/AttributeFlag.java
+2
-0
AccessInfo.java
jadx-core/src/main/java/jadx/core/dex/info/AccessInfo.java
+14
-5
ArgType.java
...rc/main/java/jadx/core/dex/instructions/args/ArgType.java
+49
-28
MethodNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
+5
-0
ClassModifier.java
...e/src/main/java/jadx/core/dex/visitors/ClassModifier.java
+104
-17
ModVisitor.java
...core/src/main/java/jadx/core/dex/visitors/ModVisitor.java
+8
-29
TestInnerClass.java
...ore/src/test/java/jadx/tests/internal/TestInnerClass.java
+2
-2
TestStringBuilderElimination.java
...ava/jadx/tests/internal/TestStringBuilderElimination.java
+3
-1
No files found.
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
View file @
30355cc9
...
...
@@ -297,6 +297,9 @@ public class ClassGen {
}
for
(
FieldNode
f
:
fields
)
{
if
(
f
.
getAttributes
().
contains
(
AttributeFlag
.
DONT_GENERATE
))
{
continue
;
}
annotationGen
.
addForField
(
code
,
f
);
code
.
startLine
(
f
.
getAccessFlags
().
makeString
());
code
.
add
(
TypeGen
.
translate
(
this
,
f
.
getType
()));
...
...
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
View file @
30355cc9
package
jadx
.
core
.
codegen
;
import
jadx.core.dex.attributes.AttributeFlag
;
import
jadx.core.dex.attributes.AttributeType
;
import
jadx.core.dex.attributes.IAttribute
;
import
jadx.core.dex.attributes.MethodInlineAttr
;
...
...
@@ -127,8 +128,12 @@ public class InsnGen {
}
private
String
ifield
(
FieldInfo
field
,
InsnArg
arg
)
throws
CodegenException
{
FieldNode
fieldNode
=
mth
.
getParentClass
().
searchField
(
field
);
if
(
fieldNode
!=
null
&&
fieldNode
.
getAttributes
().
contains
(
AttributeFlag
.
DONT_GENERATE
))
{
return
""
;
}
String
name
=
field
.
getName
();
// TODO: add jadx argument ""
// TODO: add jadx argument "
add this
"
// FIXME: check variable names in scope
if
(
false
&&
arg
.
isThis
())
{
boolean
useShort
=
true
;
...
...
@@ -143,7 +148,8 @@ public class InsnGen {
return
name
;
}
}
return
arg
(
arg
)
+
"."
+
name
;
String
argStr
=
arg
(
arg
);
return
argStr
.
isEmpty
()
?
name
:
argStr
+
"."
+
name
;
}
protected
String
sfield
(
FieldInfo
field
)
{
...
...
@@ -513,7 +519,7 @@ public class InsnGen {
private
void
makeConstructor
(
ConstructorInsn
insn
,
CodeWriter
code
,
EnumSet
<
IGState
>
state
)
throws
CodegenException
{
ClassNode
cls
=
root
.
resolveClass
(
insn
.
getClassType
());
ClassNode
cls
=
mth
.
dex
()
.
resolveClass
(
insn
.
getClassType
());
if
(
cls
!=
null
&&
cls
.
isAnonymous
())
{
// anonymous class construction
ClassInfo
parent
;
...
...
@@ -527,19 +533,21 @@ public class InsnGen {
code
.
incIndent
(
2
);
new
ClassGen
(
cls
,
mgen
.
getClassGen
().
getParentGen
(),
fallback
).
makeClassBody
(
code
);
code
.
decIndent
(
2
);
}
else
if
(
insn
.
isSuper
())
{
return
;
}
if
(
insn
.
isSelf
())
{
// skip
state
.
add
(
IGState
.
SKIP
);
return
;
}
if
(
insn
.
isSuper
())
{
code
.
add
(
"super"
);
addArgs
(
code
,
insn
,
0
);
}
else
if
(
insn
.
isThis
())
{
code
.
add
(
"this"
);
addArgs
(
code
,
insn
,
0
);
}
else
if
(
insn
.
isSelf
())
{
// skip
state
.
add
(
IGState
.
SKIP
);
}
else
{
code
.
add
(
"new "
).
add
(
useClass
(
insn
.
getClassType
()));
addArgs
(
code
,
insn
,
0
);
}
generateArguments
(
code
,
insn
,
0
,
mth
.
dex
().
resolveMethod
(
insn
.
getCallMth
()));
}
private
void
makeInvoke
(
InvokeNode
insn
,
CodeWriter
code
)
throws
CodegenException
{
...
...
@@ -560,8 +568,12 @@ public class InsnGen {
case
VIRTUAL:
case
INTERFACE:
InsnArg
arg
=
insn
.
getArg
(
0
);
if
(!
arg
.
isThis
())
{
// FIXME: add 'this' for equals methods in scope
code
.
add
(
arg
(
arg
)).
add
(
'.'
);
// FIXME: add 'this' for equals methods in scope
if
(!
arg
.
isThis
())
{
String
argStr
=
arg
(
arg
);
if
(!
argStr
.
isEmpty
())
{
code
.
add
(
argStr
).
add
(
'.'
);
}
}
k
++;
break
;
...
...
@@ -581,11 +593,18 @@ public class InsnGen {
break
;
}
code
.
add
(
callMth
.
getName
());
if
(
callMthNode
!=
null
&&
callMthNode
.
isArgsOverload
())
{
int
argsCount
=
insn
.
getArgsCount
();
List
<
ArgType
>
originalType
=
callMth
.
getArgumentsTypes
();
int
origPos
=
0
;
generateArguments
(
code
,
insn
,
k
,
callMthNode
);
}
private
void
generateArguments
(
CodeWriter
code
,
InsnNode
insn
,
int
k
,
MethodNode
callMth
)
throws
CodegenException
{
if
(
callMth
!=
null
&&
callMth
.
getAttributes
().
contains
(
AttributeFlag
.
SKIP_FIRST_ARG
))
{
k
++;
}
int
argsCount
=
insn
.
getArgsCount
();
if
(
callMth
!=
null
&&
callMth
.
isArgsOverload
())
{
// add additional argument casts for overloaded methods
List
<
ArgType
>
originalType
=
callMth
.
getMethodInfo
().
getArgumentsTypes
();
int
origPos
=
0
;
code
.
add
(
'('
);
for
(
int
i
=
k
;
i
<
argsCount
;
i
++)
{
InsnArg
arg
=
insn
.
getArg
(
i
);
...
...
@@ -602,21 +621,16 @@ public class InsnGen {
}
code
.
add
(
')'
);
}
else
{
addArgs
(
code
,
insn
,
k
);
}
}
private
void
addArgs
(
CodeWriter
code
,
InsnNode
insn
,
int
k
)
throws
CodegenException
{
int
argsCount
=
insn
.
getArgsCount
();
code
.
add
(
'('
);
if
(
k
<
argsCount
)
{
code
.
add
(
arg
(
insn
.
getArg
(
k
),
false
));
for
(
int
i
=
k
+
1
;
i
<
argsCount
;
i
++)
{
code
.
add
(
", "
);
code
.
add
(
arg
(
insn
.
getArg
(
i
),
false
));
code
.
add
(
'('
);
if
(
k
<
argsCount
)
{
code
.
add
(
arg
(
insn
.
getArg
(
k
),
false
));
for
(
int
i
=
k
+
1
;
i
<
argsCount
;
i
++)
{
code
.
add
(
", "
);
code
.
add
(
arg
(
insn
.
getArg
(
i
),
false
));
}
}
code
.
add
(
')'
);
}
code
.
add
(
')'
);
}
private
void
inlineMethod
(
MethodNode
callMthNode
,
InvokeNode
insn
,
CodeWriter
code
)
throws
CodegenException
{
...
...
jadx-core/src/main/java/jadx/core/dex/attributes/AttributeFlag.java
View file @
30355cc9
...
...
@@ -16,5 +16,7 @@ public enum AttributeFlag {
DONT_GENERATE
,
SKIP
,
SKIP_FIRST_ARG
,
INCONSISTENT_CODE
,
// warning about incorrect decompilation
}
jadx-core/src/main/java/jadx/core/dex/info/AccessInfo.java
View file @
30355cc9
...
...
@@ -105,10 +105,6 @@ public class AccessInfo {
return
(
accFlags
&
AccessFlags
.
ACC_VOLATILE
)
!=
0
;
}
public
int
getFlags
()
{
return
accFlags
;
}
public
AFType
getType
()
{
return
type
;
}
...
...
@@ -178,8 +174,21 @@ public class AccessInfo {
return
code
.
toString
();
}
public
String
rawString
()
{
switch
(
type
){
case
CLASS:
return
AccessFlags
.
classString
(
accFlags
);
case
FIELD:
return
AccessFlags
.
fieldString
(
accFlags
);
case
METHOD:
return
AccessFlags
.
methodString
(
accFlags
);
default
:
return
"?"
;
}
}
@Override
public
String
toString
()
{
return
"AccessInfo: "
+
type
+
"
"
+
accFlags
+
" ("
+
make
String
()
+
")"
;
return
"AccessInfo: "
+
type
+
"
0x"
+
Integer
.
toHexString
(
accFlags
)
+
" ("
+
raw
String
()
+
")"
;
}
}
jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java
View file @
30355cc9
...
...
@@ -82,7 +82,7 @@ public abstract class ArgType {
return
new
UnknownArg
(
types
);
}
private
static
abstract
class
KnownTypeArg
extends
ArgType
{
private
abstract
static
class
KnownTypeArg
extends
ArgType
{
@Override
public
boolean
isTypeKnown
()
{
return
true
;
...
...
@@ -234,7 +234,7 @@ public abstract class ArgType {
}
private
static
final
class
UnknownArg
extends
ArgType
{
private
final
PrimitiveType
possibleTypes
[]
;
private
final
PrimitiveType
[]
possibleTypes
;
public
UnknownArg
(
PrimitiveType
[]
types
)
{
this
.
possibleTypes
=
types
;
...
...
@@ -253,19 +253,22 @@ public abstract class ArgType {
@Override
public
boolean
contains
(
PrimitiveType
type
)
{
for
(
PrimitiveType
t
:
possibleTypes
)
if
(
t
==
type
)
for
(
PrimitiveType
t
:
possibleTypes
)
{
if
(
t
==
type
)
{
return
true
;
}
}
return
false
;
}
@Override
public
ArgType
selectFirst
()
{
PrimitiveType
f
=
possibleTypes
[
0
];
if
(
f
==
PrimitiveType
.
OBJECT
||
f
==
PrimitiveType
.
ARRAY
)
if
(
f
==
PrimitiveType
.
OBJECT
||
f
==
PrimitiveType
.
ARRAY
)
{
return
object
(
Consts
.
CLASS_OBJECT
);
else
}
else
{
return
primitive
(
f
);
}
}
@Override
...
...
@@ -275,10 +278,11 @@ public abstract class ArgType {
@Override
public
String
toString
()
{
if
(
possibleTypes
.
length
==
PrimitiveType
.
values
().
length
)
if
(
possibleTypes
.
length
==
PrimitiveType
.
values
().
length
)
{
return
"?"
;
else
}
else
{
return
"?"
+
Arrays
.
toString
(
possibleTypes
);
}
}
}
...
...
@@ -358,32 +362,39 @@ public abstract class ArgType {
}
if
(!
a
.
isTypeKnown
())
{
if
(
b
.
isTypeKnown
())
{
if
(
a
.
contains
(
b
.
getPrimitiveType
()))
if
(
a
.
contains
(
b
.
getPrimitiveType
()))
{
return
b
;
else
}
else
{
return
null
;
}
}
else
{
// both types unknown
List
<
PrimitiveType
>
types
=
new
ArrayList
<
PrimitiveType
>();
for
(
PrimitiveType
type
:
a
.
getPossibleTypes
())
{
if
(
b
.
contains
(
type
))
if
(
b
.
contains
(
type
))
{
types
.
add
(
type
);
}
}
if
(
types
.
size
()
==
0
)
{
return
null
;
}
else
if
(
types
.
size
()
==
1
)
{
PrimitiveType
nt
=
types
.
get
(
0
);
if
(
nt
==
PrimitiveType
.
OBJECT
||
nt
==
PrimitiveType
.
ARRAY
)
if
(
nt
==
PrimitiveType
.
OBJECT
||
nt
==
PrimitiveType
.
ARRAY
)
{
return
unknown
(
nt
);
else
}
else
{
return
primitive
(
nt
);
}
}
else
{
return
unknown
(
types
.
toArray
(
new
PrimitiveType
[
types
.
size
()]));
}
}
}
else
{
if
(
a
.
isGenericType
())
return
a
;
if
(
b
.
isGenericType
())
return
b
;
if
(
a
.
isGenericType
())
{
return
a
;
}
if
(
b
.
isGenericType
())
{
return
b
;
}
if
(
a
.
isObject
()
&&
b
.
isObject
())
{
String
aObj
=
a
.
getObject
();
...
...
@@ -450,19 +461,20 @@ public abstract class ArgType {
public
static
ArgType
parseSignature
(
String
sign
)
{
int
b
=
sign
.
indexOf
(
'<'
);
if
(
b
==
-
1
)
if
(
b
==
-
1
)
{
return
parse
(
sign
);
if
(
sign
.
charAt
(
0
)
==
'['
)
}
if
(
sign
.
charAt
(
0
)
==
'['
)
{
return
array
(
parseSignature
(
sign
.
substring
(
1
)));
}
String
obj
=
sign
.
substring
(
0
,
b
)
+
";"
;
String
genericsStr
=
sign
.
substring
(
b
+
1
,
sign
.
length
()
-
2
);
List
<
ArgType
>
generics
=
parseSignatureList
(
genericsStr
);
if
(
generics
!=
null
)
if
(
generics
!=
null
)
{
return
generic
(
obj
,
generics
.
toArray
(
new
ArgType
[
generics
.
size
()]));
else
}
else
{
return
object
(
obj
);
}
}
public
static
List
<
ArgType
>
parseSignatureList
(
String
str
)
{
...
...
@@ -481,7 +493,6 @@ public abstract class ArgType {
if
(
str
.
equals
(
"*"
))
{
return
Arrays
.
asList
(
UNKNOWN
);
}
List
<
ArgType
>
signs
=
new
ArrayList
<
ArgType
>(
3
);
int
obj
=
0
;
int
objStart
=
0
;
...
...
@@ -513,8 +524,9 @@ public abstract class ArgType {
if
(
gen
==
0
)
{
obj
=
0
;
String
o
=
str
.
substring
(
objStart
,
pos
);
if
(
o
.
length
()
>
0
)
if
(
o
.
length
()
>
0
)
{
type
=
genericType
(
o
);
}
}
break
;
...
...
@@ -572,8 +584,9 @@ public abstract class ArgType {
}
prev
=
arg
;
}
else
{
if
(!
arg
.
getObject
().
equals
(
Consts
.
CLASS_OBJECT
))
if
(!
arg
.
getObject
().
equals
(
Consts
.
CLASS_OBJECT
))
{
genList
.
add
(
arg
);
}
}
}
if
(
prev
!=
null
)
{
...
...
@@ -640,10 +653,18 @@ public abstract class ArgType {
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
hash
!=
obj
.
hashCode
())
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
if
(
this
==
obj
)
{
return
true
;
}
if
(
obj
==
null
)
{
return
false
;
}
if
(
hash
!=
obj
.
hashCode
())
{
return
false
;
}
if
(
getClass
()
!=
obj
.
getClass
())
{
return
false
;
}
return
internalEquals
(
obj
);
}
}
jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
View file @
30355cc9
...
...
@@ -229,6 +229,11 @@ public class MethodNode extends LineAttrNode implements ILoadable {
}
}
public
RegisterArg
removeFirstArgument
()
{
this
.
getAttributes
().
add
(
AttributeFlag
.
SKIP_FIRST_ARG
);
return
argsList
.
remove
(
0
);
}
public
RegisterArg
getThisArg
()
{
return
thisArg
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ClassModifier.java
View file @
30355cc9
package
jadx
.
core
.
dex
.
visitors
;
import
jadx.core.dex.attributes.AttributeFlag
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.core.dex.info.ClassInfo
;
import
jadx.core.dex.info.FieldInfo
;
import
jadx.core.dex.info.MethodInfo
;
import
jadx.core.dex.instructions.IndexInsnNode
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.args.InsnArg
;
import
jadx.core.dex.instructions.args.RegisterArg
;
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.utils.exceptions.JadxException
;
...
...
@@ -18,6 +27,78 @@ public class ClassModifier extends AbstractVisitor {
visit
(
inner
);
}
removeSyntheticFields
(
cls
);
removeSyntheticMethods
(
cls
);
removeEmptyMethods
(
cls
);
return
false
;
}
private
static
void
removeSyntheticFields
(
ClassNode
cls
)
{
if
(!
cls
.
getClassInfo
().
isInner
()
||
cls
.
getAccessFlags
().
isStatic
())
{
return
;
}
// remove fields if it is synthetic and type is a outer class
for
(
FieldNode
field
:
cls
.
getFields
())
{
if
(
field
.
getAccessFlags
().
isSynthetic
()
&&
field
.
getType
().
isObject
())
{
ClassNode
fieldsCls
=
cls
.
dex
().
resolveClass
(
ClassInfo
.
fromType
(
field
.
getType
()));
if
(
fieldsCls
!=
null
&&
cls
.
getClassInfo
().
getParentClass
().
equals
(
fieldsCls
.
getClassInfo
()))
{
int
found
=
0
;
for
(
MethodNode
mth
:
cls
.
getMethods
())
{
if
(
removeFieldUsage
(
field
,
fieldsCls
,
mth
))
{
found
++;
}
}
if
(
found
!=
0
)
{
// TODO: make new flag for skip field generation and usage
field
.
getAttributes
().
add
(
AttributeFlag
.
DONT_GENERATE
);
}
}
}
}
}
private
static
boolean
removeFieldUsage
(
FieldNode
field
,
ClassNode
fieldsCls
,
MethodNode
mth
)
{
if
(!
mth
.
getAccessFlags
().
isConstructor
())
{
return
false
;
}
List
<
RegisterArg
>
args
=
mth
.
getArguments
(
false
);
if
(
args
.
isEmpty
())
{
return
false
;
}
RegisterArg
arg
=
args
.
get
(
0
);
if
(!
arg
.
getType
().
equals
(
fieldsCls
.
getClassInfo
().
getType
()))
{
return
false
;
}
BlockNode
block
=
mth
.
getBasicBlocks
().
get
(
0
);
List
<
InsnNode
>
instructions
=
block
.
getInstructions
();
if
(
instructions
.
isEmpty
())
{
return
false
;
}
InsnNode
insn
=
instructions
.
get
(
0
);
if
(
insn
.
getType
()
!=
InsnType
.
IPUT
)
{
return
false
;
}
IndexInsnNode
putInsn
=
(
IndexInsnNode
)
insn
;
FieldInfo
fieldInfo
=
(
FieldInfo
)
putInsn
.
getIndex
();
if
(!
fieldInfo
.
equals
(
field
.
getFieldInfo
())
||
!
putInsn
.
getArg
(
0
).
equals
(
arg
))
{
return
false
;
}
mth
.
removeFirstArgument
();
InstructionRemover
.
remove
(
block
,
insn
);
// other arg usage -> wrap with IGET insn
List
<
InsnArg
>
useList
=
arg
.
getTypedVar
().
getUseList
();
if
(
useList
.
size
()
>
1
)
{
InsnNode
iget
=
new
IndexInsnNode
(
InsnType
.
IGET
,
fieldInfo
,
1
);
iget
.
addArg
(
insn
.
getArg
(
1
));
for
(
InsnArg
insnArg
:
useList
)
{
insnArg
.
wrapInstruction
(
iget
);
}
}
return
true
;
}
private
static
void
removeSyntheticMethods
(
ClassNode
cls
)
{
for
(
Iterator
<
MethodNode
>
it
=
cls
.
getMethods
().
iterator
();
it
.
hasNext
();
)
{
MethodNode
mth
=
it
.
next
();
AccessInfo
af
=
mth
.
getAccessFlags
();
...
...
@@ -29,6 +110,27 @@ public class ClassModifier extends AbstractVisitor {
it
.
remove
();
}
}
}
}
private
static
boolean
isMethodUniq
(
ClassNode
cls
,
MethodNode
mth
)
{
MethodInfo
mi
=
mth
.
getMethodInfo
();
for
(
MethodNode
otherMth
:
cls
.
getMethods
())
{
MethodInfo
omi
=
otherMth
.
getMethodInfo
();
if
(
omi
.
getName
().
equals
(
mi
.
getName
())
&&
otherMth
!=
mth
)
{
if
(
omi
.
getArgumentsTypes
().
size
()
==
mi
.
getArgumentsTypes
().
size
())
{
// TODO: check to args objects types
return
false
;
}
}
}
return
true
;
}
private
static
void
removeEmptyMethods
(
ClassNode
cls
)
{
for
(
MethodNode
mth
:
cls
.
getMethods
())
{
AccessInfo
af
=
mth
.
getAccessFlags
();
// remove public empty constructors
if
(
af
.
isConstructor
()
...
...
@@ -36,31 +138,16 @@ public class ClassModifier extends AbstractVisitor {
&&
mth
.
getArguments
(
false
).
isEmpty
())
{
List
<
BlockNode
>
bb
=
mth
.
getBasicBlocks
();
if
(
bb
.
isEmpty
()
||
allBlocksEmpty
(
bb
))
{
it
.
remove
(
);
mth
.
getAttributes
().
add
(
AttributeFlag
.
DONT_GENERATE
);
}
}
}
return
false
;
}
private
static
boolean
allBlocksEmpty
(
List
<
BlockNode
>
blocks
)
{
for
(
BlockNode
block
:
blocks
)
{
if
(
block
.
getInstructions
().
size
()
!=
0
)
if
(
block
.
getInstructions
().
size
()
!=
0
)
{
return
false
;
}
return
true
;
}
private
static
boolean
isMethodUniq
(
ClassNode
cls
,
MethodNode
mth
)
{
MethodInfo
mi
=
mth
.
getMethodInfo
();
for
(
MethodNode
otherMth
:
cls
.
getMethods
())
{
MethodInfo
omi
=
otherMth
.
getMethodInfo
();
if
(
omi
.
getName
().
equals
(
mi
.
getName
())
&&
otherMth
!=
mth
)
{
if
(
omi
.
getArgumentsTypes
().
size
()
==
mi
.
getArgumentsTypes
().
size
())
{
// TODO: check to args objects types
return
false
;
}
}
}
return
true
;
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java
View file @
30355cc9
package
jadx
.
core
.
dex
.
visitors
;
import
jadx.core.deobf.NameMapper
;
import
jadx.core.dex.attributes.AttributeFlag
;
import
jadx.core.dex.attributes.AttributeType
;
import
jadx.core.dex.info.MethodInfo
;
import
jadx.core.dex.instructions.ConstClassNode
;
...
...
@@ -23,7 +22,6 @@ 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.exceptions.JadxRuntimeException
;
import
java.util.List
;
...
...
@@ -54,7 +52,6 @@ public class ModVisitor extends AbstractVisitor {
private
void
replaceStep
(
MethodNode
mth
)
{
ClassNode
parentClass
=
mth
.
getParentClass
();
ConstructorInsn
superCall
=
null
;
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
InstructionRemover
remover
=
new
InstructionRemover
(
block
.
getInstructions
());
...
...
@@ -67,32 +64,18 @@ public class ModVisitor extends AbstractVisitor {
MethodInfo
callMth
=
inv
.
getCallMth
();
if
(
callMth
.
isConstructor
())
{
ConstructorInsn
co
=
new
ConstructorInsn
(
mth
,
inv
);
if
(
co
.
isSuper
())
{
try
{
// inline super call args
for
(
int
j
=
0
;
j
<
co
.
getArgsCount
();
j
++)
{
InsnArg
arg
=
co
.
getArg
(
j
);
if
(
arg
.
isRegister
())
{
CodeShrinker
.
inlineArgument
(
mth
,
(
RegisterArg
)
arg
);
}
}
}
catch
(
JadxRuntimeException
e
)
{
// inline args into super fail
LOG
.
warn
(
"Can't inline args into super call: "
+
inv
+
", mth: "
+
mth
);
mth
.
getAttributes
().
add
(
AttributeFlag
.
INCONSISTENT_CODE
);
}
finally
{
superCall
=
co
;
remover
.
add
(
insn
);
}
boolean
remove
=
false
;
if
(
co
.
isSuper
()
&&
(
co
.
getArgsCount
()
==
0
||
parentClass
.
isEnum
()))
{
remove
=
true
;
}
else
if
(
co
.
isThis
()
&&
co
.
getArgsCount
()
==
0
)
{
MethodNode
defCo
=
mth
.
getParentClass
()
.
searchMethodByName
(
co
.
getCallMth
().
getShortId
());
MethodNode
defCo
=
mth
.
getParentClass
().
searchMethodByName
(
callMth
.
getShortId
());
if
(
defCo
==
null
||
defCo
.
isNoCode
())
{
// default constructor not implemented
remover
.
add
(
insn
);
}
else
{
replaceInsn
(
block
,
i
,
co
);
remove
=
true
;
}
}
if
(
remove
)
{
remover
.
add
(
insn
);
}
else
{
replaceInsn
(
block
,
i
,
co
);
}
...
...
@@ -158,10 +141,6 @@ public class ModVisitor extends AbstractVisitor {
}
remover
.
perform
();
}
if
(
superCall
!=
null
&&
!
parentClass
.
isEnum
()
&&
superCall
.
getArgsCount
()
!=
0
)
{
List
<
InsnNode
>
insns
=
mth
.
getEnterBlock
().
getInstructions
();
insns
.
add
(
0
,
superCall
);
}
}
/**
...
...
jadx-core/src/test/java/jadx/tests/internal/TestInnerClass.java
View file @
30355cc9
...
...
@@ -27,7 +27,7 @@ public class TestInnerClass extends InternalJadxTest {
assertThat
(
code
,
containsString
(
"Inner {"
));
assertThat
(
code
,
containsString
(
"Inner2 extends Thread {"
));
assertThat
(
code
,
not
(
containsString
(
"super();"
)));
// assertThat(code, not(containsString("this$0
")));
//
assertThat(code, not(containsString("/* synthetic */")));
assertThat
(
code
,
not
(
containsString
(
"this$
"
)));
assertThat
(
code
,
not
(
containsString
(
"/* synthetic */"
)));
}
}
jadx-core/src/test/java/jadx/tests/internal/TestStringBuilderElimination.java
View file @
30355cc9
...
...
@@ -3,6 +3,8 @@ 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
;
...
...
@@ -21,7 +23,7 @@ public class TestStringBuilderElimination extends InternalJadxTest {
}
}
//
@Test
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
MyException
.
class
);
String
code
=
cls
.
getCode
().
toString
();
...
...
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