Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
colcode
jadx
提交
2a60ac47
J
jadx
项目概览
colcode
/
jadx
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jadx
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2a60ac47
编写于
3月 09, 2014
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
core: annotate generated code with reference to used methods
上级
9cd72fe1
变更
19
隐藏空白更改
内联
并排
Showing
19 changed file
with
461 addition
and
215 deletion
+461
-215
jadx-core/src/main/java/jadx/api/CodePosition.java
jadx-core/src/main/java/jadx/api/CodePosition.java
+54
-0
jadx-core/src/main/java/jadx/api/JavaClass.java
jadx-core/src/main/java/jadx/api/JavaClass.java
+54
-12
jadx-core/src/main/java/jadx/core/Jadx.java
jadx-core/src/main/java/jadx/core/Jadx.java
+2
-0
jadx-core/src/main/java/jadx/core/codegen/AnnotationGen.java
jadx-core/src/main/java/jadx/core/codegen/AnnotationGen.java
+42
-62
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
+5
-5
jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java
jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java
+69
-36
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
+70
-72
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
+6
-9
jadx-core/src/main/java/jadx/core/dex/instructions/ArithNode.java
...e/src/main/java/jadx/core/dex/instructions/ArithNode.java
+1
-1
jadx-core/src/main/java/jadx/core/dex/instructions/InsnType.java
...re/src/main/java/jadx/core/dex/instructions/InsnType.java
+1
-0
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
+16
-0
jadx-core/src/main/java/jadx/core/dex/nodes/FieldNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/FieldNode.java
+6
-0
jadx-core/src/main/java/jadx/core/dex/visitors/ClassModifier.java
...e/src/main/java/jadx/core/dex/visitors/ClassModifier.java
+1
-1
jadx-core/src/main/java/jadx/core/dex/visitors/PrepareForCodeGen.java
...c/main/java/jadx/core/dex/visitors/PrepareForCodeGen.java
+66
-0
jadx-core/src/test/java/jadx/tests/internal/TestFieldIncrement.java
...src/test/java/jadx/tests/internal/TestFieldIncrement.java
+2
-16
jadx-core/src/test/java/jadx/tests/internal/TestSynchronized.java
...e/src/test/java/jadx/tests/internal/TestSynchronized.java
+2
-0
jadx-core/src/test/java/jadx/tests/internal/arith/TestArith.java
...re/src/test/java/jadx/tests/internal/arith/TestArith.java
+33
-0
jadx-core/src/test/java/jadx/tests/internal/arith/TestArith2.java
...e/src/test/java/jadx/tests/internal/arith/TestArith2.java
+30
-0
jadx-core/src/test/java/jadx/tests/internal/debuginfo/TestLineNumbers.java
...t/java/jadx/tests/internal/debuginfo/TestLineNumbers.java
+1
-1
未找到文件。
jadx-core/src/main/java/jadx/api/CodePosition.java
0 → 100644
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
2a60ac47
...
...
@@ -16,6 +16,7 @@ import jadx.core.dex.instructions.FillArrayNode;
import
jadx.core.dex.instructions.GotoNode
;
import
jadx.core.dex.instructions.IfNode
;
import
jadx.core.dex.instructions.IndexInsnNode
;
import
jadx.core.dex.instructions.InsnType
;
import
jadx.core.dex.instructions.InvokeNode
;
import
jadx.core.dex.instructions.InvokeType
;
import
jadx.core.dex.instructions.SwitchNode
;
...
...
@@ -38,6 +39,7 @@ 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.EnumSet
;
...
...
@@ -57,12 +59,7 @@ public class InsnGen {
protected
final
RootNode
root
;
private
final
boolean
fallback
;
private
static
enum
IGState
{
SKIP
,
NO_SEMICOLON
,
NO_RESULT
,
private
static
enum
Flags
{
BODY_ONLY
,
BODY_ONLY_NOWRAP
,
}
...
...
@@ -113,7 +110,7 @@ public class InsnGen {
}
else
if
(
arg
.
isLiteral
())
{
code
.
add
(
lit
((
LiteralArg
)
arg
));
}
else
if
(
arg
.
isInsnWrap
())
{
IGState
flag
=
wrap
?
IGState
.
BODY_ONLY
:
IGState
.
BODY_ONLY_NOWRAP
;
Flags
flag
=
wrap
?
Flags
.
BODY_ONLY
:
Flags
.
BODY_ONLY_NOWRAP
;
makeInsn
(((
InsnWrapArg
)
arg
).
getWrapInsn
(),
code
,
flag
);
}
else
if
(
arg
.
isNamed
())
{
code
.
add
(((
NamedArg
)
arg
).
getName
());
...
...
@@ -164,18 +161,17 @@ public class InsnGen {
code
.
add
(
field
.
getName
());
}
protected
String
staticField
(
FieldInfo
field
)
{
String
thisClass
=
mth
.
getParentClass
().
getFullName
();
public
static
String
makeStaticFieldAccess
(
FieldInfo
field
,
ClassGen
clsGen
)
{
ClassInfo
declClass
=
field
.
getDeclClass
();
if
(
thisClass
.
startsWith
(
declClass
.
getFullName
()))
{
if
(
clsGen
.
getClassNode
().
getFullName
()
.
startsWith
(
declClass
.
getFullName
()))
{
return
field
.
getName
();
}
// Android specific resources class handler
ClassInfo
parentClass
=
declClass
.
getParentClass
();
if
(
parentClass
!=
null
&&
parentClass
.
getShortName
().
equals
(
"R"
))
{
return
useClass
(
parentClass
)
+
"."
+
declClass
.
getShortName
()
+
"."
+
field
.
getName
();
return
clsGen
.
useClass
(
parentClass
)
+
"."
+
declClass
.
getShortName
()
+
"."
+
field
.
getName
();
}
return
useClass
(
declClass
)
+
'.'
+
field
.
getName
();
return
clsGen
.
useClass
(
declClass
)
+
'.'
+
field
.
getName
();
}
private
void
fieldPut
(
IndexInsnNode
insn
)
{
...
...
@@ -190,6 +186,10 @@ public class InsnGen {
}
}
protected
String
staticField
(
FieldInfo
field
)
{
return
makeStaticFieldAccess
(
field
,
mgen
.
getClassGen
());
}
public
String
useClass
(
ClassInfo
cls
)
{
return
mgen
.
getClassGen
().
useClass
(
cls
);
}
...
...
@@ -202,31 +202,25 @@ public class InsnGen {
return
makeInsn
(
insn
,
code
,
null
);
}
private
boolean
makeInsn
(
InsnNode
insn
,
CodeWriter
code
,
IGState
flag
)
throws
CodegenException
{
private
boolean
makeInsn
(
InsnNode
insn
,
CodeWriter
code
,
Flags
flag
)
throws
CodegenException
{
try
{
EnumSet
<
IGState
>
state
=
EnumSet
.
noneOf
(
IGState
.
class
);
if
(
flag
==
IGState
.
BODY_ONLY
||
flag
==
IGState
.
BODY_ONLY_NOWRAP
)
{
if
(
insn
.
getType
()
==
InsnType
.
NOP
)
{
return
false
;
}
EnumSet
<
Flags
>
state
=
EnumSet
.
noneOf
(
Flags
.
class
);
if
(
flag
==
Flags
.
BODY_ONLY
||
flag
==
Flags
.
BODY_ONLY_NOWRAP
)
{
state
.
add
(
flag
);
makeInsnBody
(
code
,
insn
,
state
);
}
else
{
CodeWriter
body
=
new
CodeWriter
(
code
.
getIndent
());
makeInsnBody
(
body
,
insn
,
state
);
if
(
state
.
contains
(
IGState
.
SKIP
))
{
return
false
;
}
code
.
startLine
();
if
(
insn
.
getSourceLine
()
!=
0
)
{
code
.
attachAnnotation
(
insn
.
getSourceLine
());
}
if
(
insn
.
getResult
()
!=
null
&&
!
state
.
contains
(
IGState
.
NO_RESULT
)
)
{
if
(
insn
.
getResult
()
!=
null
&&
insn
.
getType
()
!=
InsnType
.
ARITH_ONEARG
)
{
code
.
add
(
assignVar
(
insn
)).
add
(
" = "
);
}
code
.
add
(
body
);
if
(!
state
.
contains
(
IGState
.
NO_SEMICOLON
))
{
code
.
add
(
';'
);
}
makeInsnBody
(
code
,
insn
,
state
);
code
.
add
(
';'
);
}
}
catch
(
Throwable
th
)
{
throw
new
CodegenException
(
mth
,
"Error generate insn: "
+
insn
,
th
);
...
...
@@ -234,7 +228,7 @@ public class InsnGen {
return
true
;
}
private
void
makeInsnBody
(
CodeWriter
code
,
InsnNode
insn
,
EnumSet
<
IGState
>
state
)
throws
CodegenException
{
private
void
makeInsnBody
(
CodeWriter
code
,
InsnNode
insn
,
EnumSet
<
Flags
>
state
)
throws
CodegenException
{
switch
(
insn
.
getType
())
{
case
CONST_STR:
String
str
=
((
ConstStringNode
)
insn
).
getString
();
...
...
@@ -257,7 +251,7 @@ public class InsnGen {
case
CHECK_CAST:
case
CAST:
{
boolean
wrap
=
state
.
contains
(
IGState
.
BODY_ONLY
);
boolean
wrap
=
state
.
contains
(
Flags
.
BODY_ONLY
);
if
(
wrap
)
{
code
.
add
(
'('
);
}
...
...
@@ -270,13 +264,18 @@ public class InsnGen {
}
break
;
}
case
ARITH:
makeArith
((
ArithNode
)
insn
,
code
,
state
);
break
;
case
ARITH_ONEARG:
makeArithOneArg
((
ArithNode
)
insn
,
code
,
state
);
break
;
case
NEG:
String
base
=
"-"
+
arg
(
insn
.
getArg
(
0
));
if
(
state
.
contains
(
IGState
.
BODY_ONLY
))
{
if
(
state
.
contains
(
Flags
.
BODY_ONLY
))
{
code
.
add
(
'('
).
add
(
base
).
add
(
')'
);
}
else
{
code
.
add
(
base
);
...
...
@@ -311,7 +310,7 @@ public class InsnGen {
break
;
case
INSTANCE_OF:
{
boolean
wrap
=
state
.
contains
(
IGState
.
BODY_ONLY
);
boolean
wrap
=
state
.
contains
(
Flags
.
BODY_ONLY
);
if
(
wrap
)
{
code
.
add
(
'('
);
}
...
...
@@ -400,7 +399,7 @@ public class InsnGen {
}
}
// TODO: wrap in braces only if necessary
if
(
state
.
contains
(
IGState
.
BODY_ONLY
))
{
if
(
state
.
contains
(
Flags
.
BODY_ONLY
))
{
code
.
add
(
'('
).
add
(
sb
.
toString
()).
add
(
')'
);
}
else
{
code
.
add
(
sb
.
toString
());
...
...
@@ -410,16 +409,12 @@ public class InsnGen {
case
MONITOR_ENTER:
if
(
isFallback
())
{
code
.
add
(
"monitor-enter("
).
add
(
arg
(
insn
.
getArg
(
0
))).
add
(
')'
);
}
else
{
state
.
add
(
IGState
.
SKIP
);
}
break
;
case
MONITOR_EXIT:
if
(
isFallback
())
{
code
.
add
(
"monitor-exit("
).
add
(
arg
(
insn
,
0
)).
add
(
')'
);
}
else
{
state
.
add
(
IGState
.
SKIP
);
}
break
;
...
...
@@ -439,10 +434,6 @@ public class InsnGen {
code
.
add
(
arg
(
insn
,
0
));
break
;
case
NOP:
state
.
add
(
IGState
.
SKIP
);
break
;
/* fallback mode instructions */
case
IF:
assert
isFallback
()
:
"if insn in not fallback mode"
;
...
...
@@ -472,7 +463,6 @@ public class InsnGen {
code
.
add
(
MethodGen
.
getLabelName
(
sw
.
getDefaultCaseOffset
())).
add
(
';'
);
code
.
decIndent
();
code
.
startLine
(
'}'
);
state
.
add
(
IGState
.
NO_SEMICOLON
);
break
;
case
NEW_INSTANCE:
...
...
@@ -556,7 +546,7 @@ public class InsnGen {
code
.
add
(
"new "
).
add
(
useType
(
elType
)).
add
(
"[]{"
).
add
(
str
.
toString
()).
add
(
'}'
);
}
private
void
makeConstructor
(
ConstructorInsn
insn
,
CodeWriter
code
,
EnumSet
<
IGState
>
state
)
private
void
makeConstructor
(
ConstructorInsn
insn
,
CodeWriter
code
,
EnumSet
<
Flags
>
state
)
throws
CodegenException
{
ClassNode
cls
=
mth
.
dex
().
resolveClass
(
insn
.
getClassType
());
if
(
cls
!=
null
&&
cls
.
isAnonymous
())
{
...
...
@@ -579,9 +569,7 @@ public class InsnGen {
return
;
}
if
(
insn
.
isSelf
())
{
// skip
state
.
add
(
IGState
.
SKIP
);
return
;
throw
new
JadxRuntimeException
(
"Constructor 'self' invoke must be removed!"
);
}
if
(
insn
.
isSuper
())
{
code
.
add
(
"super"
);
...
...
@@ -632,6 +620,9 @@ public class InsnGen {
}
break
;
}
if
(
callMthNode
!=
null
)
{
code
.
attachAnnotation
(
callMthNode
);
}
code
.
add
(
callMth
.
getName
());
generateArguments
(
code
,
insn
,
k
,
callMthNode
);
}
...
...
@@ -678,7 +669,7 @@ public class InsnGen {
IAttribute
mia
=
callMthNode
.
getAttributes
().
get
(
AttributeType
.
METHOD_INLINE
);
InsnNode
inl
=
((
MethodInlineAttr
)
mia
).
getInsn
();
if
(
callMthNode
.
getMethodInfo
().
getArgumentsTypes
().
isEmpty
())
{
makeInsn
(
inl
,
code
,
IGState
.
BODY_ONLY
);
makeInsn
(
inl
,
code
,
Flags
.
BODY_ONLY
);
}
else
{
// remap args
InsnArg
[]
regs
=
new
InsnArg
[
callMthNode
.
getRegsCount
()];
...
...
@@ -705,7 +696,7 @@ public class InsnGen {
}
}
}
makeInsn
(
inl
,
code
,
IGState
.
BODY_ONLY
);
makeInsn
(
inl
,
code
,
Flags
.
BODY_ONLY
);
// revert changes
for
(
Map
.
Entry
<
RegisterArg
,
InsnArg
>
e
:
toRevert
.
entrySet
())
{
inl
.
replaceArg
(
e
.
getValue
(),
e
.
getKey
());
...
...
@@ -713,14 +704,14 @@ public class InsnGen {
}
}
private
void
makeTernary
(
TernaryInsn
insn
,
CodeWriter
code
,
EnumSet
<
IGState
>
state
)
throws
CodegenException
{
private
void
makeTernary
(
TernaryInsn
insn
,
CodeWriter
code
,
EnumSet
<
Flags
>
state
)
throws
CodegenException
{
String
cond
=
ConditionGen
.
make
(
this
,
insn
.
getCondition
());
CodeWriter
th
=
arg
(
insn
.
getArg
(
0
),
false
);
CodeWriter
els
=
arg
(
insn
.
getArg
(
1
),
false
);
if
(
th
.
toString
().
equals
(
"true"
)
&&
els
.
toString
().
equals
(
"false"
))
{
code
.
add
(
cond
);
}
else
{
if
(
state
.
contains
(
IGState
.
BODY_ONLY
))
{
if
(
state
.
contains
(
Flags
.
BODY_ONLY
))
{
code
.
add
(
"(("
).
add
(
cond
).
add
(
')'
).
add
(
" ? "
).
add
(
th
).
add
(
" : "
).
add
(
els
).
add
(
')'
);
}
else
{
code
.
add
(
'('
).
add
(
cond
).
add
(
')'
).
add
(
" ? "
).
add
(
th
).
add
(
" : "
).
add
(
els
);
...
...
@@ -728,33 +719,40 @@ public class InsnGen {
}
}
private
void
makeArith
(
ArithNode
insn
,
CodeWriter
code
,
EnumSet
<
IGState
>
state
)
throws
CodegenException
{
private
void
makeArith
(
ArithNode
insn
,
CodeWriter
code
,
EnumSet
<
Flags
>
state
)
throws
CodegenException
{
ArithOp
op
=
insn
.
getOp
();
CodeWriter
v1
=
arg
(
insn
.
getArg
(
0
));
CodeWriter
v2
=
arg
(
insn
.
getArg
(
1
));
if
(
state
.
contains
(
IGState
.
BODY_ONLY
))
{
if
(
state
.
contains
(
Flags
.
BODY_ONLY
))
{
// wrap insn in brackets for save correct operation order
code
.
add
(
'('
).
add
(
v1
).
add
(
' '
).
add
(
op
.
getSymbol
()).
add
(
' '
).
add
(
v2
).
add
(
')'
);
}
else
if
(
state
.
contains
(
IGState
.
BODY_ONLY_NOWRAP
))
{
code
.
add
(
v1
).
add
(
' '
).
add
(
op
.
getSymbol
()).
add
(
' '
).
add
(
v2
);
code
.
add
(
'('
);
addArg
(
code
,
insn
.
getArg
(
0
));
code
.
add
(
' '
);
code
.
add
(
op
.
getSymbol
());
code
.
add
(
' '
);
addArg
(
code
,
insn
.
getArg
(
1
));
code
.
add
(
')'
);
}
else
{
CodeWriter
res
=
arg
(
insn
.
getResult
());
if
(
res
.
equals
(
v1
)
&&
insn
.
getResult
().
equals
(
insn
.
getArg
(
0
)))
{
state
.
add
(
IGState
.
NO_RESULT
);
// "++" or "--"
if
(
insn
.
getArg
(
1
).
isLiteral
()
&&
(
op
==
ArithOp
.
ADD
||
op
==
ArithOp
.
SUB
))
{
LiteralArg
lit
=
(
LiteralArg
)
insn
.
getArg
(
1
);
if
(
lit
.
isInteger
()
&&
lit
.
getLiteral
()
==
1
)
{
code
.
add
(
assignVar
(
insn
)).
add
(
op
.
getSymbol
()).
add
(
op
.
getSymbol
());
return
;
}
}
// +=, -= ...
v2
=
arg
(
insn
.
getArg
(
1
),
false
);
code
.
add
(
assignVar
(
insn
)).
add
(
' '
).
add
(
op
.
getSymbol
()).
add
(
"= "
).
add
(
v2
);
}
else
{
code
.
add
(
v1
).
add
(
' '
).
add
(
op
.
getSymbol
()).
add
(
' '
).
add
(
v2
);
addArg
(
code
,
insn
.
getArg
(
0
));
code
.
add
(
' '
);
code
.
add
(
op
.
getSymbol
());
code
.
add
(
' '
);
addArg
(
code
,
insn
.
getArg
(
1
));
}
}
private
void
makeArithOneArg
(
ArithNode
insn
,
CodeWriter
code
,
EnumSet
<
Flags
>
state
)
throws
CodegenException
{
ArithOp
op
=
insn
.
getOp
();
InsnArg
arg
=
insn
.
getArg
(
0
);
// "++" or "--"
if
(
arg
.
isLiteral
()
&&
(
op
==
ArithOp
.
ADD
||
op
==
ArithOp
.
SUB
))
{
LiteralArg
lit
=
(
LiteralArg
)
arg
;
if
(
lit
.
isInteger
()
&&
lit
.
getLiteral
()
==
1
)
{
String
opSymbol
=
op
.
getSymbol
();
code
.
add
(
assignVar
(
insn
)).
add
(
opSymbol
).
add
(
opSymbol
);
return
;
}
}
// +=, -= ...
code
.
add
(
assignVar
(
insn
)).
add
(
' '
).
add
(
op
.
getSymbol
()).
add
(
"= "
);
addArg
(
code
,
arg
,
false
);
}
}
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
2a60ac47
package
jadx.tests.internal
;
package
jadx.tests.internal
.debuginfo
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.codegen.CodeWriter
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录