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
ecbb53aa
Commit
ecbb53aa
authored
Aug 22, 2018
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: fixed 'this' attribute propagation for move insn (#345)
parent
ffe739b7
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
129 additions
and
49 deletions
+129
-49
NameGen.java
jadx-core/src/main/java/jadx/core/codegen/NameGen.java
+4
-9
InsnArg.java
...rc/main/java/jadx/core/dex/instructions/args/InsnArg.java
+1
-2
RegisterArg.java
...ain/java/jadx/core/dex/instructions/args/RegisterArg.java
+8
-17
TypeImmutableArg.java
...ava/jadx/core/dex/instructions/args/TypeImmutableArg.java
+0
-13
CodeShrinker.java
...re/src/main/java/jadx/core/dex/visitors/CodeShrinker.java
+3
-4
SSATransform.java
...rc/main/java/jadx/core/dex/visitors/ssa/SSATransform.java
+24
-4
TestDontInlineThis.java
...va/jadx/tests/integration/usethis/TestDontInlineThis.java
+42
-0
TestInlineThis2.java
.../java/jadx/tests/integration/usethis/TestInlineThis2.java
+47
-0
No files found.
jadx-core/src/main/java/jadx/core/codegen/NameGen.java
View file @
ecbb53aa
...
...
@@ -102,16 +102,11 @@ public class NameGen {
if
(
fallback
)
{
return
getFallbackName
(
arg
);
}
String
name
=
arg
.
getName
();
String
varName
;
if
(
name
!=
null
)
{
if
(
"this"
.
equals
(
name
))
{
return
name
;
}
varName
=
name
;
}
else
{
varName
=
guessName
(
arg
);
if
(
arg
.
isThis
())
{
return
RegisterArg
.
THIS_ARG_NAME
;
}
String
name
=
arg
.
getName
();
String
varName
=
name
!=
null
?
name
:
guessName
(
arg
);
if
(
NameMapper
.
isReserved
(
varName
))
{
return
varName
+
"R"
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java
View file @
ecbb53aa
...
...
@@ -140,7 +140,6 @@ public abstract class InsnArg extends Typed {
}
public
boolean
isThis
()
{
// must be implemented in RegisterArg
return
false
;
return
contains
(
AFlag
.
THIS
);
}
}
jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java
View file @
ecbb53aa
...
...
@@ -4,7 +4,6 @@ import java.util.Objects;
import
org.jetbrains.annotations.NotNull
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.PhiInsn
;
import
jadx.core.dex.nodes.DexNode
;
...
...
@@ -13,6 +12,8 @@ import jadx.core.utils.InsnUtils;
public
class
RegisterArg
extends
InsnArg
implements
Named
{
public
static
final
String
THIS_ARG_NAME
=
"this"
;
protected
final
int
regNum
;
// not null after SSATransform pass
private
SSAVar
sVar
;
...
...
@@ -44,6 +45,9 @@ public class RegisterArg extends InsnArg implements Named {
}
public
String
getName
()
{
if
(
isThis
())
{
return
THIS_ARG_NAME
;
}
if
(
sVar
==
null
)
{
return
null
;
}
...
...
@@ -117,22 +121,6 @@ public class RegisterArg extends InsnArg implements Named {
return
InsnUtils
.
getConstValueByInsn
(
dex
,
parInsn
);
}
@Override
public
boolean
isThis
()
{
if
(
contains
(
AFlag
.
THIS
))
{
return
true
;
}
// maybe it was moved from 'this' register
InsnNode
ai
=
getAssignInsn
();
if
(
ai
!=
null
&&
ai
.
getType
()
==
InsnType
.
MOVE
)
{
InsnArg
arg
=
ai
.
getArg
(
0
);
if
(
arg
!=
this
)
{
return
arg
.
isThis
();
}
}
return
false
;
}
public
InsnNode
getAssignInsn
()
{
if
(
sVar
==
null
)
{
return
null
;
...
...
@@ -188,6 +176,9 @@ public class RegisterArg extends InsnArg implements Named {
}
sb
.
append
(
" "
);
sb
.
append
(
type
);
if
(!
isAttrStorageEmpty
())
{
sb
.
append
(
' '
).
append
(
getAttributesString
());
}
sb
.
append
(
")"
);
return
sb
.
toString
();
}
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/args/TypeImmutableArg.java
View file @
ecbb53aa
...
...
@@ -4,8 +4,6 @@ import org.jetbrains.annotations.NotNull;
public
class
TypeImmutableArg
extends
RegisterArg
{
public
static
final
String
THIS_ARG_NAME
=
"this"
;
public
TypeImmutableArg
(
int
rn
,
ArgType
type
)
{
super
(
rn
,
type
);
}
...
...
@@ -21,18 +19,7 @@ public class TypeImmutableArg extends RegisterArg {
}
@Override
public
String
getName
()
{
if
(
isThis
())
{
return
THIS_ARG_NAME
;
}
return
super
.
getName
();
}
@Override
void
setSVar
(
@NotNull
SSAVar
sVar
)
{
if
(
isThis
())
{
sVar
.
setName
(
THIS_ARG_NAME
);
}
sVar
.
setTypeImmutable
(
type
);
super
.
setSVar
(
sVar
);
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java
View file @
ecbb53aa
...
...
@@ -89,8 +89,7 @@ public class CodeShrinker extends AbstractVisitor {
}
public
WrapInfo
checkInline
(
int
assignPos
,
RegisterArg
arg
)
{
if
(!
arg
.
isThis
()
&&
(
assignPos
>=
inlineBorder
||
!
canMove
(
assignPos
,
inlineBorder
)))
{
if
(
assignPos
>=
inlineBorder
||
!
canMove
(
assignPos
,
inlineBorder
))
{
return
null
;
}
inlineBorder
=
assignPos
;
...
...
@@ -214,9 +213,9 @@ public class CodeShrinker extends AbstractVisitor {
// continue;
// }
SSAVar
sVar
=
arg
.
getSVar
();
// allow inline only one use arg
or 'this'
// allow inline only one use arg
if
(
sVar
==
null
||
sVar
.
getVariableUseCount
()
!=
1
&&
!
arg
.
isThis
()
||
sVar
.
getVariableUseCount
()
!=
1
||
sVar
.
contains
(
AFlag
.
DONT_INLINE
))
{
continue
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ssa/SSATransform.java
View file @
ecbb53aa
...
...
@@ -53,7 +53,7 @@ public class SSATransform extends AbstractVisitor {
fixLastAssignInTry
(
mth
);
removeBlockerInsns
(
mth
);
markThisArg
(
mth
);
markThisArg
s
(
mth
.
getThisArg
()
);
boolean
repeatFix
;
int
k
=
0
;
...
...
@@ -407,10 +407,30 @@ public class SSATransform extends AbstractVisitor {
return
true
;
}
private
static
void
markThisArg
(
MethodNode
mth
)
{
RegisterArg
thisArg
=
mth
.
getThisArg
();
private
static
void
markThisArgs
(
RegisterArg
thisArg
)
{
if
(
thisArg
!=
null
)
{
thisArg
.
getSVar
().
getUseList
().
forEach
(
arg
->
arg
.
add
(
AFlag
.
THIS
));
markOneArgAsThis
(
thisArg
);
thisArg
.
getSVar
().
getUseList
().
forEach
(
SSATransform:
:
markOneArgAsThis
);
}
}
private
static
void
markOneArgAsThis
(
RegisterArg
arg
)
{
if
(
arg
==
null
)
{
return
;
}
arg
.
add
(
AFlag
.
THIS
);
arg
.
setName
(
RegisterArg
.
THIS_ARG_NAME
);
// mark all moved 'this'
InsnNode
parentInsn
=
arg
.
getParentInsn
();
if
(
parentInsn
!=
null
&&
parentInsn
.
getType
()
==
InsnType
.
MOVE
&&
parentInsn
.
getArg
(
0
)
==
arg
)
{
RegisterArg
resArg
=
parentInsn
.
getResult
();
if
(
resArg
.
getRegNum
()
!=
arg
.
getRegNum
()
&&
!
resArg
.
getSVar
().
isUsedInPhi
())
{
markThisArgs
(
resArg
);
parentInsn
.
add
(
AFlag
.
SKIP
);
}
}
}
}
jadx-core/src/test/java/jadx/tests/integration/usethis/TestDontInlineThis.java
0 → 100644
View file @
ecbb53aa
package
jadx
.
tests
.
integration
.
usethis
;
import
java.util.Random
;
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
.
junit
.
Assert
.
assertThat
;
public
class
TestDontInlineThis
extends
IntegrationTest
{
public
static
class
TestCls
{
public
int
field
=
new
Random
().
nextInt
();
private
TestCls
test
()
{
TestCls
res
;
if
(
field
==
7
)
{
res
=
this
;
}
else
{
res
=
new
TestCls
();
}
res
.
method
();
return
res
;
}
private
void
method
()
{
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"TestDontInlineThis$TestCls res"
));
assertThat
(
code
,
containsOne
(
"res = this;"
));
assertThat
(
code
,
containsOne
(
"res = new TestDontInlineThis$TestCls();"
));
}
}
jadx-core/src/test/java/jadx/tests/integration/usethis/TestInlineThis2.java
0 → 100644
View file @
ecbb53aa
package
jadx
.
tests
.
integration
.
usethis
;
import
java.util.Objects
;
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
.
CoreMatchers
.
containsString
;
import
static
org
.
hamcrest
.
CoreMatchers
.
not
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestInlineThis2
extends
IntegrationTest
{
public
static
class
TestCls
{
public
int
field
;
private
void
test
()
{
TestCls
thisVar
=
this
;
if
(
Objects
.
isNull
(
thisVar
))
{
System
.
out
.
println
(
"null"
);
}
thisVar
.
method
();
thisVar
.
field
=
123
;
}
private
void
method
()
{
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
not
(
containsString
(
"thisVar"
)));
assertThat
(
code
,
not
(
containsString
(
"thisVar.method()"
)));
assertThat
(
code
,
not
(
containsString
(
"thisVar.field"
)));
assertThat
(
code
,
not
(
containsString
(
"= this"
)));
assertThat
(
code
,
containsOne
(
"if (Objects.isNull(this)) {"
));
assertThat
(
code
,
containsOne
(
"this.field = 123;"
));
assertThat
(
code
,
containsOne
(
"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