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
2a60ac47
Commit
2a60ac47
authored
Mar 09, 2014
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: annotate generated code with reference to used methods
parent
9cd72fe1
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
461 additions
and
215 deletions
+461
-215
CodePosition.java
jadx-core/src/main/java/jadx/api/CodePosition.java
+54
-0
JavaClass.java
jadx-core/src/main/java/jadx/api/JavaClass.java
+54
-12
Jadx.java
jadx-core/src/main/java/jadx/core/Jadx.java
+2
-0
AnnotationGen.java
jadx-core/src/main/java/jadx/core/codegen/AnnotationGen.java
+42
-62
ClassGen.java
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
+5
-5
CodeWriter.java
jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java
+69
-36
InsnGen.java
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
+70
-72
MethodGen.java
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
+6
-9
ArithNode.java
...e/src/main/java/jadx/core/dex/instructions/ArithNode.java
+1
-1
InsnType.java
...re/src/main/java/jadx/core/dex/instructions/InsnType.java
+1
-0
ClassNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
+16
-0
FieldNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/FieldNode.java
+6
-0
ClassModifier.java
...e/src/main/java/jadx/core/dex/visitors/ClassModifier.java
+1
-1
PrepareForCodeGen.java
...c/main/java/jadx/core/dex/visitors/PrepareForCodeGen.java
+66
-0
TestFieldIncrement.java
...src/test/java/jadx/tests/internal/TestFieldIncrement.java
+2
-16
TestSynchronized.java
...e/src/test/java/jadx/tests/internal/TestSynchronized.java
+2
-0
TestArith.java
...re/src/test/java/jadx/tests/internal/arith/TestArith.java
+33
-0
TestArith2.java
...e/src/test/java/jadx/tests/internal/arith/TestArith2.java
+30
-0
TestLineNumbers.java
...t/java/jadx/tests/internal/debuginfo/TestLineNumbers.java
+1
-1
No files found.
jadx-core/src/main/java/jadx/api/CodePosition.java
0 → 100644
View file @
2a60ac47
package
jadx
.
api
;
public
final
class
CodePosition
{
private
final
JavaClass
cls
;
private
final
int
line
;
private
final
int
offset
;
public
CodePosition
(
JavaClass
cls
,
int
line
,
int
offset
)
{
this
.
cls
=
cls
;
this
.
line
=
line
;
this
.
offset
=
offset
;
}
public
CodePosition
(
int
line
,
int
offset
)
{
this
.
cls
=
null
;
this
.
line
=
line
;
this
.
offset
=
offset
;
}
public
JavaClass
getJavaClass
()
{
return
cls
;
}
public
int
getLine
()
{
return
line
;
}
public
int
getOffset
()
{
return
offset
;
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
{
return
true
;
}
if
(
o
==
null
||
getClass
()
!=
o
.
getClass
())
{
return
false
;
}
CodePosition
that
=
(
CodePosition
)
o
;
return
line
==
that
.
line
&&
offset
==
that
.
offset
;
}
@Override
public
int
hashCode
()
{
return
line
+
31
*
offset
;
}
@Override
public
String
toString
()
{
return
line
+
":"
+
offset
+
(
cls
!=
null
?
" "
+
cls
:
""
);
}
}
jadx-core/src/main/java/jadx/api/JavaClass.java
View file @
2a60ac47
...
...
@@ -2,6 +2,7 @@ package jadx.api;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.dex.attributes.AttributeFlag
;
import
jadx.core.dex.attributes.LineAttrNode
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.FieldNode
;
...
...
@@ -12,6 +13,7 @@ import java.util.ArrayList;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.List
;
import
java.util.Map
;
public
final
class
JavaClass
{
...
...
@@ -27,12 +29,23 @@ public final class JavaClass {
this
.
cls
=
classNode
;
}
public
String
getCode
()
{
CodeWriter
code
=
cls
.
getCode
();
if
(
code
==
null
)
{
decompile
();
code
=
cls
.
getCode
();
}
return
code
!=
null
?
code
.
toString
()
:
"error processing class"
;
}
public
void
decompile
()
{
if
(
decompiler
==
null
)
{
throw
new
JadxRuntimeException
(
"Can't decompile inner class"
);
}
decompiler
.
processClass
(
cls
);
load
();
if
(
cls
.
getCode
()
==
null
)
{
decompiler
.
processClass
(
cls
);
load
();
}
}
private
void
load
()
{
...
...
@@ -78,13 +91,32 @@ public final class JavaClass {
}
}
public
String
getCode
()
{
CodeWriter
code
=
cls
.
getCode
();
if
(
code
==
null
)
{
decompile
();
code
=
cls
.
getCode
();
private
Map
<
CodePosition
,
Object
>
getCodeAnnotations
()
{
getCode
();
return
cls
.
getCode
().
getAnnotations
();
}
public
CodePosition
getDefinitionPosition
(
int
line
,
int
offset
)
{
Map
<
CodePosition
,
Object
>
map
=
getCodeAnnotations
();
Object
obj
=
map
.
get
(
new
CodePosition
(
line
,
offset
));
if
(
obj
instanceof
LineAttrNode
)
{
ClassNode
clsNode
=
null
;
if
(
obj
instanceof
ClassNode
)
{
clsNode
=
(
ClassNode
)
obj
;
}
else
if
(
obj
instanceof
MethodNode
)
{
clsNode
=
((
MethodNode
)
obj
).
getParentClass
();
}
else
if
(
obj
instanceof
FieldNode
)
{
clsNode
=
((
FieldNode
)
obj
).
getParentClass
();
}
if
(
clsNode
!=
null
)
{
clsNode
=
clsNode
.
getParentClass
();
JavaClass
jCls
=
new
JavaClass
(
decompiler
,
clsNode
);
jCls
.
decompile
();
int
defLine
=
((
LineAttrNode
)
obj
).
getDecompiledLine
();
return
new
CodePosition
(
jCls
,
defLine
,
0
);
}
}
return
code
!=
null
?
code
.
toString
()
:
"error processing class"
;
return
null
;
}
public
String
getFullName
()
{
...
...
@@ -115,12 +147,22 @@ public final class JavaClass {
return
methods
;
}
public
int
getDecompiledLine
()
{
return
cls
.
getDecompiledLine
();
}
@Override
public
String
toString
(
)
{
return
getFullName
(
);
public
boolean
equals
(
Object
o
)
{
return
this
==
o
||
o
instanceof
JavaClass
&&
cls
.
equals
(((
JavaClass
)
o
).
cls
);
}
public
int
getDecompiledLine
()
{
return
cls
.
getDecompiledLine
();
@Override
public
int
hashCode
()
{
return
cls
.
hashCode
();
}
@Override
public
String
toString
()
{
return
getFullName
();
}
}
jadx-core/src/main/java/jadx/core/Jadx.java
View file @
2a60ac47
...
...
@@ -12,6 +12,7 @@ import jadx.core.dex.visitors.FallbackModeVisitor;
import
jadx.core.dex.visitors.IDexTreeVisitor
;
import
jadx.core.dex.visitors.MethodInlineVisitor
;
import
jadx.core.dex.visitors.ModVisitor
;
import
jadx.core.dex.visitors.PrepareForCodeGen
;
import
jadx.core.dex.visitors.SimplifyVisitor
;
import
jadx.core.dex.visitors.regions.CheckRegions
;
import
jadx.core.dex.visitors.regions.ProcessVariables
;
...
...
@@ -82,6 +83,7 @@ public class Jadx {
passes
.
add
(
new
MethodInlineVisitor
());
passes
.
add
(
new
ClassModifier
());
passes
.
add
(
new
PrepareForCodeGen
());
}
passes
.
add
(
new
CodeGen
(
args
));
return
passes
;
...
...
jadx-core/src/main/java/jadx/core/codegen/AnnotationGen.java
View file @
2a60ac47
...
...
@@ -47,7 +47,7 @@ public class AnnotationGen {
return
;
}
for
(
Annotation
a
:
aList
.
getAll
())
{
code
.
add
(
formatAnnotation
(
a
)
);
formatAnnotation
(
code
,
a
);
code
.
add
(
' '
);
}
}
...
...
@@ -66,26 +66,25 @@ public class AnnotationGen {
}
}
else
{
code
.
startLine
();
code
.
add
(
formatAnnotation
(
a
)
);
formatAnnotation
(
code
,
a
);
}
}
}
private
CodeWriter
formatAnnotation
(
Annotation
a
)
{
CodeWriter
code
=
new
CodeWriter
();
private
void
formatAnnotation
(
CodeWriter
code
,
Annotation
a
)
{
code
.
add
(
'@'
);
code
.
add
(
classGen
.
useClass
(
a
.
getType
()));
Map
<
String
,
Object
>
vl
=
a
.
getValues
();
if
(!
vl
.
isEmpty
())
{
code
.
add
(
'('
);
if
(
vl
.
size
()
==
1
&&
vl
.
containsKey
(
"value"
))
{
code
.
add
(
encValueToString
(
vl
.
get
(
"value"
)
));
encodeValue
(
code
,
vl
.
get
(
"value"
));
}
else
{
for
(
Iterator
<
Entry
<
String
,
Object
>>
it
=
vl
.
entrySet
().
iterator
();
it
.
hasNext
();
)
{
Entry
<
String
,
Object
>
e
=
it
.
next
();
code
.
add
(
e
.
getKey
());
code
.
add
(
" = "
);
code
.
add
(
encValueToString
(
e
.
getValue
()
));
encodeValue
(
code
,
e
.
getValue
(
));
if
(
it
.
hasNext
())
{
code
.
add
(
", "
);
}
...
...
@@ -93,7 +92,6 @@ public class AnnotationGen {
}
code
.
add
(
')'
);
}
return
code
;
}
@SuppressWarnings
(
"unchecked"
)
...
...
@@ -122,70 +120,52 @@ public class AnnotationGen {
}
// TODO: refactor this boilerplate code
@SuppressWarnings
(
"unchecked"
)
public
String
encValueToString
(
Object
val
)
{
public
void
encodeValue
(
CodeWriter
code
,
Object
val
)
{
if
(
val
==
null
)
{
return
"null"
;
code
.
add
(
"null"
);
return
;
}
if
(
val
instanceof
String
)
{
return
StringUtils
.
unescapeString
((
String
)
val
);
}
if
(
val
instanceof
Integer
)
{
return
TypeGen
.
formatInteger
((
Integer
)
val
);
}
if
(
val
instanceof
Character
)
{
return
StringUtils
.
unescapeChar
((
Character
)
val
);
}
if
(
val
instanceof
Boolean
)
{
return
Boolean
.
TRUE
.
equals
(
val
)
?
"true"
:
"false"
;
}
if
(
val
instanceof
Float
)
{
return
TypeGen
.
formatFloat
((
Float
)
val
);
}
if
(
val
instanceof
Double
)
{
return
TypeGen
.
formatDouble
((
Double
)
val
);
}
if
(
val
instanceof
Long
)
{
return
TypeGen
.
formatLong
((
Long
)
val
);
}
if
(
val
instanceof
Short
)
{
return
TypeGen
.
formatShort
((
Short
)
val
);
}
if
(
val
instanceof
Byte
)
{
return
TypeGen
.
formatByte
((
Byte
)
val
);
}
if
(
val
instanceof
ArgType
)
{
return
TypeGen
.
translate
(
classGen
,
(
ArgType
)
val
)
+
".class"
;
}
if
(
val
instanceof
FieldInfo
)
{
code
.
add
(
StringUtils
.
unescapeString
((
String
)
val
));
}
else
if
(
val
instanceof
Integer
)
{
code
.
add
(
TypeGen
.
formatInteger
((
Integer
)
val
));
}
else
if
(
val
instanceof
Character
)
{
code
.
add
(
StringUtils
.
unescapeChar
((
Character
)
val
));
}
else
if
(
val
instanceof
Boolean
)
{
code
.
add
(
Boolean
.
TRUE
.
equals
(
val
)
?
"true"
:
"false"
);
}
else
if
(
val
instanceof
Float
)
{
code
.
add
(
TypeGen
.
formatFloat
((
Float
)
val
));
}
else
if
(
val
instanceof
Double
)
{
code
.
add
(
TypeGen
.
formatDouble
((
Double
)
val
));
}
else
if
(
val
instanceof
Long
)
{
code
.
add
(
TypeGen
.
formatLong
((
Long
)
val
));
}
else
if
(
val
instanceof
Short
)
{
code
.
add
(
TypeGen
.
formatShort
((
Short
)
val
));
}
else
if
(
val
instanceof
Byte
)
{
code
.
add
(
TypeGen
.
formatByte
((
Byte
)
val
));
}
else
if
(
val
instanceof
ArgType
)
{
code
.
add
(
TypeGen
.
translate
(
classGen
,
(
ArgType
)
val
)).
add
(
".class"
);
}
else
if
(
val
instanceof
FieldInfo
)
{
// must be a static field
FieldInfo
field
=
(
FieldInfo
)
val
;
// FIXME: !!code from InsnGen.sfield
String
thisClass
=
cls
.
getFullName
();
if
(
field
.
getDeclClass
().
getFullName
().
equals
(
thisClass
))
{
return
field
.
getName
();
}
else
{
return
classGen
.
useClass
(
field
.
getDeclClass
())
+
'.'
+
field
.
getName
();
}
}
if
(
val
instanceof
List
)
{
StringBuilder
str
=
new
StringBuilder
();
str
.
append
(
'{'
);
List
<
Object
>
list
=
(
List
<
Object
>)
val
;
for
(
Iterator
<
Object
>
it
=
list
.
iterator
();
it
.
hasNext
();
)
{
code
.
add
(
InsnGen
.
makeStaticFieldAccess
(
field
,
classGen
));
}
else
if
(
val
instanceof
List
)
{
code
.
add
(
'{'
);
List
list
=
(
List
)
val
;
Iterator
it
=
list
.
iterator
();
while
(
it
.
hasNext
())
{
Object
obj
=
it
.
next
();
str
.
append
(
encValueToString
(
obj
)
);
encodeValue
(
code
,
obj
);
if
(
it
.
hasNext
())
{
str
.
appen
d
(
", "
);
code
.
ad
d
(
", "
);
}
}
str
.
append
(
'}'
);
return
str
.
toString
();
}
if
(
val
instanceof
Annotation
)
{
return
formatAnnotation
((
Annotation
)
val
).
toString
();
code
.
add
(
'}'
);
}
else
if
(
val
instanceof
Annotation
)
{
formatAnnotation
(
code
,
(
Annotation
)
val
);
}
else
{
// TODO: also can be method values
throw
new
JadxRuntimeException
(
"Can't decode value: "
+
val
+
" ("
+
val
.
getClass
()
+
")"
);
}
// TODO: also can be method values
throw
new
JadxRuntimeException
(
"Can't decode value: "
+
val
+
" ("
+
val
.
getClass
()
+
")"
);
}
}
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
View file @
2a60ac47
...
...
@@ -151,7 +151,7 @@ public class ClassGen {
}
}
clsCode
.
attach
Annota
tion
(
cls
);
clsCode
.
attach
Defini
tion
(
cls
);
}
public
boolean
makeGenericMap
(
CodeWriter
code
,
Map
<
ArgType
,
List
<
ArgType
>>
gmap
)
{
...
...
@@ -228,8 +228,8 @@ public class ClassGen {
if
(
cls
.
getAccessFlags
().
isAnnotation
())
{
Object
def
=
annotationGen
.
getAnnotationDefaultValue
(
mth
.
getName
());
if
(
def
!=
null
)
{
String
v
=
annotationGen
.
encValueToString
(
def
);
code
.
add
(
" default "
).
add
(
v
);
code
.
add
(
" default "
);
annotationGen
.
encodeValue
(
code
,
def
);
}
}
code
.
add
(
';'
);
...
...
@@ -282,11 +282,11 @@ public class ClassGen {
if
(
fv
.
getValue
()
==
null
)
{
code
.
add
(
TypeGen
.
literalToString
(
0
,
f
.
getType
()));
}
else
{
code
.
add
(
annotationGen
.
encValueToString
(
fv
.
getValue
()
));
annotationGen
.
encodeValue
(
code
,
fv
.
getValue
(
));
}
}
code
.
add
(
';'
);
code
.
attach
Annota
tion
(
f
);
code
.
attach
Defini
tion
(
f
);
}
return
code
;
}
...
...
jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java
View file @
2a60ac47
package
jadx
.
core
.
codegen
;
import
jadx.api.CodePosition
;
import
jadx.core.dex.attributes.LineAttrNode
;
import
jadx.core.utils.Utils
;
...
...
@@ -7,6 +8,7 @@ import java.io.File;
import
java.io.PrintWriter
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.Map
;
import
org.slf4j.Logger
;
...
...
@@ -17,7 +19,7 @@ public class CodeWriter {
private
static
final
int
MAX_FILENAME_LENGTH
=
128
;
public
static
final
String
NL
=
System
.
getProperty
(
"line.separator"
);
public
static
final
String
INDENT
=
"
\t
"
;
public
static
final
String
INDENT
=
"
"
;
private
static
final
String
[]
INDENT_CACHE
=
{
""
,
...
...
@@ -33,7 +35,8 @@ public class CodeWriter {
private
int
indent
;
private
int
line
=
1
;
private
Map
<
Object
,
Integer
>
annotations
=
Collections
.
emptyMap
();
private
int
offset
=
0
;
private
Map
<
CodePosition
,
Object
>
annotations
=
Collections
.
emptyMap
();
public
CodeWriter
()
{
this
.
indent
=
0
;
...
...
@@ -47,56 +50,66 @@ public class CodeWriter {
public
CodeWriter
startLine
()
{
addLine
();
buf
.
append
(
indentStr
);
addIndent
(
);
return
this
;
}
public
CodeWriter
startLine
(
char
c
)
{
addLine
();
buf
.
append
(
indentStr
);
buf
.
appen
d
(
c
);
addIndent
(
);
ad
d
(
c
);
return
this
;
}
public
CodeWriter
startLine
(
String
str
)
{
addLine
();
buf
.
append
(
indentStr
);
buf
.
appen
d
(
str
);
addIndent
(
);
ad
d
(
str
);
return
this
;
}
public
CodeWriter
startLine
(
int
ind
,
String
str
)
{
addLine
();
buf
.
append
(
indentStr
);
addIndent
(
);
for
(
int
i
=
0
;
i
<
ind
;
i
++)
{
buf
.
append
(
INDENT
);
addIndent
(
);
}
buf
.
appen
d
(
str
);
ad
d
(
str
);
return
this
;
}
public
CodeWriter
add
(
Object
obj
)
{
buf
.
append
(
obj
);
add
(
obj
.
toString
()
);
return
this
;
}
public
CodeWriter
add
(
String
str
)
{
buf
.
append
(
str
);
offset
+=
str
.
length
();
return
this
;
}
public
CodeWriter
add
(
char
c
)
{
buf
.
append
(
c
);
offset
++;
return
this
;
}
@Deprecated
public
CodeWriter
add
(
CodeWriter
code
)
{
line
--;
for
(
Map
.
Entry
<
Object
,
Integer
>
entry
:
code
.
annotations
.
entrySet
())
{
attachAnnotation
(
entry
.
getKey
(),
line
+
entry
.
getValue
());
for
(
Map
.
Entry
<
CodePosition
,
Object
>
entry
:
code
.
annotations
.
entrySet
())
{
CodePosition
pos
=
entry
.
getKey
();
attachAnnotation
(
entry
.
getValue
(),
new
CodePosition
(
line
+
pos
.
getLine
(),
pos
.
getOffset
()));
}
line
+=
code
.
line
;
buf
.
append
(
code
);
String
str
=
code
.
toString
();
buf
.
append
(
str
);
if
(
str
.
contains
(
NL
))
{
offset
=
code
.
offset
;
}
else
{
offset
+=
code
.
offset
;
}
return
this
;
}
...
...
@@ -108,25 +121,12 @@ public class CodeWriter {
private
void
addLine
()
{
buf
.
append
(
NL
);
line
++;
offset
=
0
;
}
public
int
getLine
()
{
return
line
;
}
public
Object
attachAnnotation
(
Object
obj
)
{
return
attachAnnotation
(
obj
,
line
);
}
public
Object
attachAnnotation
(
Object
obj
,
int
line
)
{
if
(
annotations
.
isEmpty
())
{
annotations
=
new
HashMap
<
Object
,
Integer
>();
}
return
annotations
.
put
(
obj
,
line
);
}
public
CodeWriter
indent
()
{
public
CodeWriter
addIndent
()
{
buf
.
append
(
indentStr
);
offset
+=
indentStr
.
length
();
return
this
;
}
...
...
@@ -169,16 +169,49 @@ public class CodeWriter {
updateIndent
();
}
private
static
class
DefinitionWrapper
{
private
final
LineAttrNode
node
;
private
DefinitionWrapper
(
LineAttrNode
node
)
{
this
.
node
=
node
;
}
public
LineAttrNode
getNode
()
{
return
node
;
}
}
public
Object
attachDefinition
(
LineAttrNode
obj
)
{
return
attachAnnotation
(
new
DefinitionWrapper
(
obj
),
new
CodePosition
(
line
,
offset
));
}
public
Object
attachAnnotation
(
Object
obj
)
{
return
attachAnnotation
(
obj
,
new
CodePosition
(
line
,
offset
+
1
));
}
private
Object
attachAnnotation
(
Object
obj
,
CodePosition
pos
)
{
if
(
annotations
.
isEmpty
())
{
annotations
=
new
HashMap
<
CodePosition
,
Object
>();
}
return
annotations
.
put
(
pos
,
obj
);
}
public
Map
<
CodePosition
,
Object
>
getAnnotations
()
{
return
annotations
;
}
public
void
finish
()
{
buf
.
trimToSize
();
for
(
Map
.
Entry
<
Object
,
Integer
>
entry
:
annotations
.
entrySet
())
{
Object
v
=
entry
.
getKey
();
if
(
v
instanceof
LineAttrNode
)
{
LineAttrNode
l
=
(
LineAttrNode
)
v
;
l
.
setDecompiledLine
(
entry
.
getValue
());
Iterator
<
Map
.
Entry
<
CodePosition
,
Object
>>
it
=
annotations
.
entrySet
().
iterator
();
while
(
it
.
hasNext
())
{
Map
.
Entry
<
CodePosition
,
Object
>
entry
=
it
.
next
();
Object
v
=
entry
.
getValue
();
if
(
v
instanceof
DefinitionWrapper
)
{
LineAttrNode
l
=
((
DefinitionWrapper
)
v
).
getNode
();
l
.
setDecompiledLine
(
entry
.
getKey
().
getLine
());
it
.
remove
();
}
}
annotations
.
clear
();
}
private
static
String
removeFirstEmptyLine
(
String
str
)
{
...
...
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
View file @
2a60ac47
This diff is collapsed.
Click to expand it.
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
View file @
2a60ac47
...
...
@@ -61,13 +61,13 @@ public class MethodGen {
public
boolean
addDefinition
(
CodeWriter
code
)
{
if
(
mth
.
getMethodInfo
().
isClassInit
())
{
code
.
startLine
(
"static"
);
code
.
attach
Annota
tion
(
mth
);
code
.
attach
Defini
tion
(
mth
);
return
true
;
}
if
(
mth
.
getAttributes
().
contains
(
AttributeFlag
.
ANONYMOUS_CONSTRUCTOR
))
{
// don't add method name and arguments
code
.
startLine
();
code
.
attach
Annota
tion
(
mth
);
code
.
attach
Defini
tion
(
mth
);
return
false
;
}
annotationGen
.
addForMethod
(
code
,
mth
);
...
...
@@ -110,17 +110,15 @@ public class MethodGen {
));
}
}
code
.
add
(
makeArguments
(
args
)
);
code
.
add
(
")"
);
addMethodArguments
(
code
,
args
);
code
.
add
(
')'
);
annotationGen
.
addThrows
(
mth
,
code
);
code
.
attach
Annota
tion
(
mth
);
code
.
attach
Defini
tion
(
mth
);
return
true
;
}
public
CodeWriter
makeArguments
(
List
<
RegisterArg
>
args
)
{
CodeWriter
argsCode
=
new
CodeWriter
();
private
void
addMethodArguments
(
CodeWriter
argsCode
,
List
<
RegisterArg
>
args
)
{
MethodParameters
paramsAnnotation
=
(
MethodParameters
)
mth
.
getAttributes
().
get
(
AttributeType
.
ANNOTATION_MTH_PARAMETERS
);
...
...
@@ -154,7 +152,6 @@ public class MethodGen {
argsCode
.
add
(
", "
);
}
}
return
argsCode
;
}
/**
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/ArithNode.java
View file @
2a60ac47
...
...
@@ -51,7 +51,7 @@ public class ArithNode extends InsnNode {
}
public
ArithNode
(
ArithOp
op
,
RegisterArg
res
,
InsnArg
a
)
{
super
(
InsnType
.
ARITH
,
1
);
super
(
InsnType
.
ARITH
_ONEARG
,
1
);
this
.
op
=
op
;
setResult
(
res
);
addArg
(
a
);
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/InsnType.java
View file @
2a60ac47
...
...
@@ -54,6 +54,7 @@ public enum InsnType {
CONTINUE
,
STR_CONCAT
,
// strings concatenation
ARITH_ONEARG
,
TERNARY
,
ARGS
,
// just generate arguments
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
View file @
2a60ac47
...
...
@@ -50,7 +50,10 @@ public class ClassNode extends LineAttrNode implements ILoadable {
private
Map
<
Object
,
FieldNode
>
constFields
=
Collections
.
emptyMap
();
private
List
<
ClassNode
>
innerClasses
=
Collections
.
emptyList
();
// store decompiled code
private
CodeWriter
code
;
// store parent for inner classes or 'this' otherwise
private
ClassNode
parentClass
;
public
ClassNode
(
DexNode
dex
,
ClassDef
cls
)
throws
DecodeException
{
this
.
dex
=
dex
;
...
...
@@ -332,6 +335,19 @@ public class ClassNode extends LineAttrNode implements ILoadable {
return
searchMethodByName
(
MethodInfo
.
fromDex
(
dex
,
id
).
getShortId
());
}
public
ClassNode
getParentClass
()
{
if
(
parentClass
==
null
)
{
if
(
clsInfo
.
isInner
())
{
ClassNode
parent
=
dex
().
resolveClass
(
clsInfo
.
getParentClass
());
parent
=
parent
==
null
?
this
:
parent
;
parentClass
=
parent
;
}
else
{
parentClass
=
this
;
}
}
return
parentClass
;
}
public
List
<
ClassNode
>
getInnerClasses
()
{
return
innerClasses
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/FieldNode.java
View file @
2a60ac47
...
...
@@ -10,12 +10,14 @@ import com.android.dx.io.ClassData.Field;
public
class
FieldNode
extends
LineAttrNode
{
private
final
ClassNode
parent
;
private
final
FieldInfo
fieldInfo
;
private
final
AccessInfo
accFlags
;
private
ArgType
type
;
// store signature
public
FieldNode
(
ClassNode
cls
,
Field
field
)
{
this
.
parent
=
cls
;
this
.
fieldInfo
=
FieldInfo
.
fromDex
(
cls
.
dex
(),
field
.
getFieldIndex
());
this
.
type
=
fieldInfo
.
getType
();
this
.
accFlags
=
new
AccessInfo
(
field
.
getAccessFlags
(),
AFType
.
FIELD
);
...
...
@@ -41,6 +43,10 @@ public class FieldNode extends LineAttrNode {
this
.
type
=
type
;
}
public
ClassNode
getParentClass
()
{
return
parent
;
}
@Override
public
int
hashCode
()
{
return
fieldInfo
.
hashCode
();
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ClassModifier.java
View file @
2a60ac47
...
...
@@ -159,7 +159,7 @@ public class ClassModifier extends AbstractVisitor {
&&
af
.
isPublic
()
&&
mth
.
getArguments
(
false
).
isEmpty
())
{
List
<
BlockNode
>
bb
=
mth
.
getBasicBlocks
();
if
(
bb
.
isEmpty
()
||
allBlocksEmpty
(
bb
))
{
if
(
bb
==
null
||
bb
.
isEmpty
()
||
allBlocksEmpty
(
bb
))
{
mth
.
getAttributes
().
add
(
AttributeFlag
.
DONT_GENERATE
);
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/PrepareForCodeGen.java
0 → 100644
View file @
2a60ac47
package
jadx
.
core
.
dex
.
visitors
;
import
jadx.core.dex.instructions.ArithNode
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.args.InsnArg
;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.instructions.mods.ConstructorInsn
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.utils.exceptions.JadxException
;
import
java.util.Iterator
;
import
java.util.List
;
public
class
PrepareForCodeGen
extends
AbstractVisitor
{
@Override
public
void
visit
(
MethodNode
mth
)
throws
JadxException
{
List
<
BlockNode
>
blocks
=
mth
.
getBasicBlocks
();
if
(
blocks
==
null
)
{
return
;
}
for
(
BlockNode
block
:
blocks
)
{
removeInstructions
(
block
);
modifyArith
(
block
);
}
}
private
static
void
removeInstructions
(
BlockNode
block
)
{
Iterator
<
InsnNode
>
it
=
block
.
getInstructions
().
iterator
();
while
(
it
.
hasNext
())
{
InsnNode
insn
=
it
.
next
();
switch
(
insn
.
getType
())
{
case
NOP:
case
MONITOR_ENTER:
case
MONITOR_EXIT:
it
.
remove
();
break
;
case
CONSTRUCTOR:
ConstructorInsn
co
=
(
ConstructorInsn
)
insn
;
if
(
co
.
isSelf
())
{
it
.
remove
();
}
break
;
}
}
}
private
static
void
modifyArith
(
BlockNode
block
)
{
List
<
InsnNode
>
list
=
block
.
getInstructions
();
for
(
int
i
=
0
;
i
<
list
.
size
();
i
++)
{
InsnNode
insn
=
list
.
get
(
i
);
if
(
insn
.
getType
()
==
InsnType
.
ARITH
)
{
ArithNode
arith
=
(
ArithNode
)
insn
;
RegisterArg
res
=
arith
.
getResult
();
InsnArg
arg
=
arith
.
getArg
(
0
);
if
(
res
.
equals
(
arg
))
{
ArithNode
newArith
=
new
ArithNode
(
arith
.
getOp
(),
res
,
arith
.
getArg
(
1
));
list
.
set
(
i
,
newArith
);
}
}
}
}
}
jadx-core/src/test/java/jadx/tests/internal/TestFieldIncrement.java
View file @
2a60ac47
package
jadx
.
tests
.
internal
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.instructions.ArithNode
;
import
jadx.core.dex.instructions.ArithOp
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
java.util.List
;
import
org.junit.Test
;
import
static
junit
.
framework
.
Assert
.
assertEquals
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
junit
.
Assert
.
assertThat
;
...
...
@@ -39,15 +31,9 @@ public class TestFieldIncrement extends InternalJadxTest {
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
MethodNode
mth
=
getMethod
(
cls
,
"method"
);
List
<
InsnNode
>
insns
=
mth
.
getBasicBlocks
().
get
(
0
).
getInstructions
();
assertEquals
(
insns
.
size
(),
1
);
InsnNode
insnNode
=
insns
.
get
(
0
);
assertEquals
(
InsnType
.
ARITH
,
insnNode
.
getType
());
assertEquals
(
ArithOp
.
ADD
,
((
ArithNode
)
insnNode
).
getOp
());
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsString
(
"instanceField++;"
));
assertThat
(
code
,
containsString
(
"staticField--;"
));
assertThat
(
code
,
containsString
(
"result += s + '_';"
));
...
...
jadx-core/src/test/java/jadx/tests/internal/TestSynchronized.java
View file @
2a60ac47
...
...
@@ -37,5 +37,7 @@ public class TestSynchronized extends InternalJadxTest {
assertThat
(
code
,
containsString
(
"public synchronized boolean test1() {"
));
assertThat
(
code
,
containsString
(
"return this.f"
));
assertThat
(
code
,
containsString
(
"synchronized (this.o) {"
));
assertThat
(
code
,
not
(
containsString
(
makeIndent
(
3
)
+
";"
)));
}
}
jadx-core/src/test/java/jadx/tests/internal/arith/TestArith.java
0 → 100644
View file @
2a60ac47
package
jadx
.
tests
.
internal
.
arith
;
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
TestArith
extends
InternalJadxTest
{
public
static
class
TestCls
{
public
void
method
(
int
a
)
{
a
+=
2
;
}
public
void
method2
(
int
a
)
{
a
++;
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsString
(
"a += 2;"
));
assertThat
(
code
,
containsString
(
"a++;"
));
}
}
jadx-core/src/test/java/jadx/tests/internal/arith/TestArith2.java
0 → 100644
View file @
2a60ac47
package
jadx
.
tests
.
internal
.
arith
;
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
;
public
class
TestArith2
extends
InternalJadxTest
{
public
static
class
TestCls
{
public
int
test1
(
int
a
)
{
return
(
a
+
2
)
*
3
;
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsString
(
"return (a + 2) * 3;"
));
assertThat
(
code
,
not
(
containsString
(
"a + 2 * 3"
)));
}
}
jadx-core/src/test/java/jadx/tests/internal/TestLineNumbers.java
→
jadx-core/src/test/java/jadx/tests/internal/
debuginfo/
TestLineNumbers.java
View file @
2a60ac47
package
jadx
.
tests
.
internal
;
package
jadx
.
tests
.
internal
.
debuginfo
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.codegen.CodeWriter
;
...
...
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