Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2301_76393173
jadx
提交
9ea3f0f2
J
jadx
项目概览
2301_76393173
/
jadx
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
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,体验更适合开发者的 AI 搜索 >>
未验证
提交
9ea3f0f2
编写于
8月 20, 2021
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix: support 'swap' and 'wide' opcodes, other fixes for java-input
上级
868fa900
变更
21
隐藏空白更改
内联
并排
Showing
21 changed file
with
425 addition
and
111 deletion
+425
-111
jadx-core/build.gradle
jadx-core/build.gradle
+4
-1
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
+0
-1
jadx-core/src/main/java/jadx/core/dex/info/AccessInfo.java
jadx-core/src/main/java/jadx/core/dex/info/AccessInfo.java
+7
-0
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
+32
-17
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
+22
-8
jadx-core/src/test/java/jadx/tests/external/BaseExternalTest.java
...e/src/test/java/jadx/tests/external/BaseExternalTest.java
+6
-5
jadx-core/src/test/java/jadx/tests/integration/others/TestJavaSwap.java
...test/java/jadx/tests/integration/others/TestJavaSwap.java
+95
-0
jadx-plugins/jadx-dex-input/src/main/java/jadx/plugins/input/dex/sections/DexClassData.java
...in/java/jadx/plugins/input/dex/sections/DexClassData.java
+5
-1
jadx-plugins/jadx-java-convert/src/main/java/jadx/plugins/input/javaconvert/JavaConvertLoader.java
...ava/jadx/plugins/input/javaconvert/JavaConvertLoader.java
+4
-34
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/JavaFileLoader.java
...src/main/java/jadx/plugins/input/java/JavaFileLoader.java
+28
-24
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/ConstPoolReader.java
...in/java/jadx/plugins/input/java/data/ConstPoolReader.java
+7
-4
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/JavaClassData.java
...main/java/jadx/plugins/input/java/data/JavaClassData.java
+4
-2
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/AttributesReader.java
.../plugins/input/java/data/attributes/AttributesReader.java
+3
-3
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/JavaAttrType.java
...jadx/plugins/input/java/data/attributes/JavaAttrType.java
+17
-0
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaCodeReader.java
...ava/jadx/plugins/input/java/data/code/JavaCodeReader.java
+11
-8
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaInsnsRegister.java
.../jadx/plugins/input/java/data/code/JavaInsnsRegister.java
+6
-1
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/decoders/WideDecoder.java
...dx/plugins/input/java/data/code/decoders/WideDecoder.java
+69
-0
jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/IClassData.java
...src/main/java/jadx/api/plugins/input/data/IClassData.java
+1
-2
jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/ISeqConsumer.java
...c/main/java/jadx/api/plugins/input/data/ISeqConsumer.java
+13
-0
jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/impl/ListConsumer.java
...n/java/jadx/api/plugins/input/data/impl/ListConsumer.java
+35
-0
jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/utils/CommonFileUtils.java
...src/main/java/jadx/api/plugins/utils/CommonFileUtils.java
+56
-0
未找到文件。
jadx-core/build.gradle
浏览文件 @
9ea3f0f2
...
@@ -6,10 +6,13 @@ dependencies {
...
@@ -6,10 +6,13 @@ dependencies {
api
(
project
(
':jadx-plugins:jadx-plugins-api'
))
api
(
project
(
':jadx-plugins:jadx-plugins-api'
))
implementation
'com.google.code.gson:gson:2.8.7'
implementation
'com.google.code.gson:gson:2.8.7'
implementation
'com.android.tools.build:aapt2-proto:4.2.1-7147631'
implementation
'com.android.tools.build:aapt2-proto:4.2.1-7147631'
testImplementation
'org.apache.commons:commons-lang3:3.12.0'
testImplementation
'org.apache.commons:commons-lang3:3.12.0'
testImplementation
'org.ow2.asm:asm:9.2'
testImplementation
'org.ow2.asm:asm-util:9.2'
testRuntimeOnly
(
project
(
':jadx-plugins:jadx-dex-input'
))
testRuntimeOnly
(
project
(
':jadx-plugins:jadx-dex-input'
))
testRuntimeOnly
(
project
(
':jadx-plugins:jadx-smali-input'
))
testRuntimeOnly
(
project
(
':jadx-plugins:jadx-smali-input'
))
testRuntimeOnly
(
project
(
':jadx-plugins:jadx-java-convert'
))
testRuntimeOnly
(
project
(
':jadx-plugins:jadx-java-convert'
))
...
...
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
浏览文件 @
9ea3f0f2
...
@@ -586,7 +586,6 @@ public class InsnGen {
...
@@ -586,7 +586,6 @@ public class InsnGen {
case
MOVE_MULTI:
case
MOVE_MULTI:
fallbackOnlyInsn
(
insn
);
fallbackOnlyInsn
(
insn
);
code
.
add
(
"move-multi: "
);
int
len
=
insn
.
getArgsCount
();
int
len
=
insn
.
getArgsCount
();
for
(
int
i
=
0
;
i
<
len
-
1
;
i
+=
2
)
{
for
(
int
i
=
0
;
i
<
len
-
1
;
i
+=
2
)
{
addArg
(
code
,
insn
.
getArg
(
i
));
addArg
(
code
,
insn
.
getArg
(
i
));
...
...
jadx-core/src/main/java/jadx/core/dex/info/AccessInfo.java
浏览文件 @
9ea3f0f2
...
@@ -147,6 +147,10 @@ public class AccessInfo {
...
@@ -147,6 +147,10 @@ public class AccessInfo {
return
(
accFlags
&
AccessFlags
.
VOLATILE
)
!=
0
;
return
(
accFlags
&
AccessFlags
.
VOLATILE
)
!=
0
;
}
}
public
boolean
isModuleInfo
()
{
return
(
accFlags
&
AccessFlags
.
MODULE
)
!=
0
;
}
public
AFType
getType
()
{
public
AFType
getType
()
{
return
type
;
return
type
;
}
}
...
@@ -200,6 +204,9 @@ public class AccessInfo {
...
@@ -200,6 +204,9 @@ public class AccessInfo {
if
((
accFlags
&
AccessFlags
.
STRICT
)
!=
0
)
{
if
((
accFlags
&
AccessFlags
.
STRICT
)
!=
0
)
{
code
.
append
(
"strict "
);
code
.
append
(
"strict "
);
}
}
if
(
isModuleInfo
())
{
code
.
append
(
"/* module-info */ "
);
}
if
(
Consts
.
DEBUG
)
{
if
(
Consts
.
DEBUG
)
{
if
((
accFlags
&
AccessFlags
.
SUPER
)
!=
0
)
{
if
((
accFlags
&
AccessFlags
.
SUPER
)
!=
0
)
{
code
.
append
(
"/* super */ "
);
code
.
append
(
"/* super */ "
);
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
浏览文件 @
9ea3f0f2
...
@@ -20,6 +20,8 @@ import jadx.api.ICodeCache;
...
@@ -20,6 +20,8 @@ import jadx.api.ICodeCache;
import
jadx.api.ICodeInfo
;
import
jadx.api.ICodeInfo
;
import
jadx.api.ICodeWriter
;
import
jadx.api.ICodeWriter
;
import
jadx.api.plugins.input.data.IClassData
;
import
jadx.api.plugins.input.data.IClassData
;
import
jadx.api.plugins.input.data.IFieldData
;
import
jadx.api.plugins.input.data.IMethodData
;
import
jadx.api.plugins.input.data.annotations.EncodedValue
;
import
jadx.api.plugins.input.data.annotations.EncodedValue
;
import
jadx.api.plugins.input.data.attributes.JadxAttrType
;
import
jadx.api.plugins.input.data.attributes.JadxAttrType
;
import
jadx.api.plugins.input.data.attributes.types.AnnotationDefaultAttr
;
import
jadx.api.plugins.input.data.attributes.types.AnnotationDefaultAttr
;
...
@@ -27,6 +29,7 @@ import jadx.api.plugins.input.data.attributes.types.AnnotationDefaultClassAttr;
...
@@ -27,6 +29,7 @@ import jadx.api.plugins.input.data.attributes.types.AnnotationDefaultClassAttr;
import
jadx.api.plugins.input.data.attributes.types.InnerClassesAttr
;
import
jadx.api.plugins.input.data.attributes.types.InnerClassesAttr
;
import
jadx.api.plugins.input.data.attributes.types.InnerClsInfo
;
import
jadx.api.plugins.input.data.attributes.types.InnerClsInfo
;
import
jadx.api.plugins.input.data.attributes.types.SourceFileAttr
;
import
jadx.api.plugins.input.data.attributes.types.SourceFileAttr
;
import
jadx.api.plugins.input.data.impl.ListConsumer
;
import
jadx.core.Consts
;
import
jadx.core.Consts
;
import
jadx.core.ProcessClass
;
import
jadx.core.ProcessClass
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AFlag
;
...
@@ -97,34 +100,46 @@ public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeN
...
@@ -97,34 +100,46 @@ public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeN
private
void
initialLoad
(
IClassData
cls
)
{
private
void
initialLoad
(
IClassData
cls
)
{
try
{
try
{
String
superType
=
cls
.
getSuperType
();
addAttrs
(
cls
.
getAttributes
());
if
(
superType
==
null
)
{
this
.
accessFlags
=
new
AccessInfo
(
getAccessFlags
(
cls
),
AFType
.
CLASS
);
// only java.lang.Object don't have super class
this
.
superClass
=
checkSuperType
(
cls
);
if
(!
clsInfo
.
getType
().
getObject
().
equals
(
Consts
.
CLASS_OBJECT
))
{
throw
new
JadxRuntimeException
(
"No super class in "
+
clsInfo
.
getType
());
}
this
.
superClass
=
null
;
}
else
{
this
.
superClass
=
ArgType
.
object
(
superType
);
}
this
.
interfaces
=
Utils
.
collectionMap
(
cls
.
getInterfacesTypes
(),
ArgType:
:
object
);
this
.
interfaces
=
Utils
.
collectionMap
(
cls
.
getInterfacesTypes
(),
ArgType:
:
object
);
methods
=
new
ArrayList
<>(
);
ListConsumer
<
IFieldData
,
FieldNode
>
fieldsConsumer
=
new
ListConsumer
<>(
fld
->
FieldNode
.
build
(
this
,
fld
)
);
fields
=
new
ArrayList
<>(
);
ListConsumer
<
IMethodData
,
MethodNode
>
methodsConsumer
=
new
ListConsumer
<>(
mth
->
MethodNode
.
build
(
this
,
mth
)
);
cls
.
visitFieldsAndMethods
(
cls
.
visitFieldsAndMethods
(
fieldsConsumer
,
methodsConsumer
);
fld
->
fields
.
add
(
FieldNode
.
build
(
this
,
fld
)),
this
.
fields
=
fieldsConsumer
.
getResult
();
mth
->
methods
.
add
(
MethodNode
.
build
(
this
,
mth
))
);
this
.
methods
=
methodsConsumer
.
getResult
(
);
addAttrs
(
cls
.
getAttributes
());
accessFlags
=
new
AccessInfo
(
getAccessFlags
(
cls
),
AFType
.
CLASS
);
initStaticValues
(
fields
);
initStaticValues
(
fields
);
processAttributes
(
this
);
processAttributes
(
this
);
buildCache
();
buildCache
();
// TODO: implement module attribute parsing
if
(
this
.
accessFlags
.
isModuleInfo
())
{
this
.
addWarnComment
(
"Modules not supported yet"
);
}
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
throw
new
JadxRuntimeException
(
"Error decode class: "
+
clsInfo
,
e
);
throw
new
JadxRuntimeException
(
"Error decode class: "
+
clsInfo
,
e
);
}
}
}
}
private
ArgType
checkSuperType
(
IClassData
cls
)
{
String
superType
=
cls
.
getSuperType
();
if
(
superType
==
null
)
{
if
(
clsInfo
.
getType
().
getObject
().
equals
(
Consts
.
CLASS_OBJECT
))
{
// java.lang.Object don't have super class
return
null
;
}
if
(
this
.
accessFlags
.
isModuleInfo
())
{
// module-info also don't have super class
return
null
;
}
throw
new
JadxRuntimeException
(
"No super class in "
+
clsInfo
.
getType
());
}
return
ArgType
.
object
(
superType
);
}
public
void
updateGenericClsData
(
ArgType
superClass
,
List
<
ArgType
>
interfaces
,
List
<
ArgType
>
generics
)
{
public
void
updateGenericClsData
(
ArgType
superClass
,
List
<
ArgType
>
interfaces
,
List
<
ArgType
>
generics
)
{
this
.
superClass
=
superClass
;
this
.
superClass
=
superClass
;
this
.
interfaces
=
interfaces
;
this
.
interfaces
=
interfaces
;
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
浏览文件 @
9ea3f0f2
...
@@ -97,14 +97,7 @@ public class RootNode {
...
@@ -97,14 +97,7 @@ public class RootNode {
}
}
if
(
classes
.
size
()
!=
clsMap
.
size
())
{
if
(
classes
.
size
()
!=
clsMap
.
size
())
{
// class name duplication detected
// class name duplication detected
classes
.
stream
().
collect
(
Collectors
.
groupingBy
(
ClassNode:
:
getClassInfo
))
markDuplicatedClasses
(
classes
);
.
entrySet
().
stream
()
.
filter
(
entry
->
entry
.
getValue
().
size
()
>
1
)
.
forEach
(
entry
->
{
LOG
.
warn
(
"Found duplicated class: {}, count: {}. Only one will be loaded!"
,
entry
.
getKey
(),
entry
.
getValue
().
size
());
entry
.
getValue
().
forEach
(
cls
->
cls
.
addAttr
(
AType
.
COMMENTS
,
"WARNING: Classes with same name are omitted"
));
});
}
}
classes
=
new
ArrayList
<>(
clsMap
.
values
());
classes
=
new
ArrayList
<>(
clsMap
.
values
());
// sort classes by name, expect top classes before inner
// sort classes by name, expect top classes before inner
...
@@ -135,6 +128,27 @@ public class RootNode {
...
@@ -135,6 +128,27 @@ public class RootNode {
ErrorsCounter
.
error
(
clsNode
,
"Load error"
,
exc
);
ErrorsCounter
.
error
(
clsNode
,
"Load error"
,
exc
);
}
}
private
static
void
markDuplicatedClasses
(
List
<
ClassNode
>
classes
)
{
classes
.
stream
()
.
collect
(
Collectors
.
groupingBy
(
ClassNode:
:
getClassInfo
))
.
entrySet
()
.
stream
()
.
filter
(
entry
->
entry
.
getValue
().
size
()
>
1
)
.
forEach
(
entry
->
{
List
<
String
>
sources
=
Utils
.
collectionMap
(
entry
.
getValue
(),
ClassNode:
:
getInputFileName
);
LOG
.
warn
(
"Found duplicated class: {}, count: {}. Only one will be loaded!\n {}"
,
entry
.
getKey
(),
entry
.
getValue
().
size
(),
String
.
join
(
"\n "
,
sources
));
entry
.
getValue
().
forEach
(
cls
->
{
String
thisSource
=
cls
.
getInputFileName
();
String
otherSourceStr
=
sources
.
stream
()
.
filter
(
s
->
!
s
.
equals
(
thisSource
))
.
sorted
()
.
collect
(
Collectors
.
joining
(
"\n "
));
cls
.
addAttr
(
AType
.
COMMENTS
,
"WARNING: Classes with same name are omitted:\n "
+
otherSourceStr
+
'\n'
);
});
});
}
public
void
addClassNode
(
ClassNode
clsNode
)
{
public
void
addClassNode
(
ClassNode
clsNode
)
{
classes
.
add
(
clsNode
);
classes
.
add
(
clsNode
);
clsMap
.
put
(
clsNode
.
getClassInfo
(),
clsNode
);
clsMap
.
put
(
clsNode
.
getClassInfo
(),
clsNode
);
...
...
jadx-core/src/test/java/jadx/tests/external/BaseExternalTest.java
浏览文件 @
9ea3f0f2
...
@@ -41,15 +41,15 @@ public abstract class BaseExternalTest extends IntegrationTest {
...
@@ -41,15 +41,15 @@ public abstract class BaseExternalTest extends IntegrationTest {
return
args
;
return
args
;
}
}
protected
void
decompile
(
JadxArgs
jadxArgs
)
{
protected
JadxDecompiler
decompile
(
JadxArgs
jadxArgs
)
{
decompile
(
jadxArgs
,
null
,
null
);
return
decompile
(
jadxArgs
,
null
,
null
);
}
}
protected
void
decompile
(
JadxArgs
jadxArgs
,
String
clsPatternStr
)
{
protected
JadxDecompiler
decompile
(
JadxArgs
jadxArgs
,
String
clsPatternStr
)
{
decompile
(
jadxArgs
,
clsPatternStr
,
null
);
return
decompile
(
jadxArgs
,
clsPatternStr
,
null
);
}
}
protected
void
decompile
(
JadxArgs
jadxArgs
,
@Nullable
String
clsPatternStr
,
@Nullable
String
mthPatternStr
)
{
protected
JadxDecompiler
decompile
(
JadxArgs
jadxArgs
,
@Nullable
String
clsPatternStr
,
@Nullable
String
mthPatternStr
)
{
JadxDecompiler
jadx
=
new
JadxDecompiler
(
jadxArgs
);
JadxDecompiler
jadx
=
new
JadxDecompiler
(
jadxArgs
);
jadx
.
getPluginManager
().
unload
(
"java-convert"
);
jadx
.
getPluginManager
().
unload
(
"java-convert"
);
jadx
.
load
();
jadx
.
load
();
...
@@ -61,6 +61,7 @@ public abstract class BaseExternalTest extends IntegrationTest {
...
@@ -61,6 +61,7 @@ public abstract class BaseExternalTest extends IntegrationTest {
processByPatterns
(
jadx
,
clsPatternStr
,
mthPatternStr
);
processByPatterns
(
jadx
,
clsPatternStr
,
mthPatternStr
);
}
}
printErrorReport
(
jadx
);
printErrorReport
(
jadx
);
return
jadx
;
}
}
private
void
processAll
(
JadxDecompiler
jadx
)
{
private
void
processAll
(
JadxDecompiler
jadx
)
{
...
...
jadx-core/src/test/java/jadx/tests/integration/others/TestJavaSwap.java
0 → 100644
浏览文件 @
9ea3f0f2
package
jadx.tests.integration.others
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.PrintWriter
;
import
java.io.StringWriter
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.util.Collections
;
import
java.util.List
;
import
org.junit.jupiter.api.Test
;
import
org.objectweb.asm.ClassReader
;
import
org.objectweb.asm.ClassWriter
;
import
org.objectweb.asm.MethodVisitor
;
import
org.objectweb.asm.Opcodes
;
import
org.objectweb.asm.util.CheckClassAdapter
;
import
jadx.core.utils.files.FileUtils
;
import
jadx.tests.api.IntegrationTest
;
import
static
jadx
.
tests
.
api
.
utils
.
assertj
.
JadxAssertions
.
assertThat
;
public
class
TestJavaSwap
extends
IntegrationTest
{
@SuppressWarnings
(
"StringBufferReplaceableByString"
)
public
static
class
TestCls
{
private
Iterable
<
String
>
field
;
@Override
public
String
toString
()
{
String
string
=
String
.
valueOf
(
this
.
field
);
return
new
StringBuilder
(
8
+
String
.
valueOf
(
string
).
length
())
.
append
(
"concat("
).
append
(
string
).
append
(
")"
)
.
toString
();
}
}
@Test
public
void
testJava
()
{
useJavaInput
();
assertThat
(
getClassNode
(
TestCls
.
class
))
.
code
();
}
@Test
public
void
test
()
throws
IOException
{
// TODO: find up-to-date assembler/disassembler in java
ClassWriter
cw
=
new
ClassWriter
(
ClassWriter
.
COMPUTE_FRAMES
);
cw
.
visit
(
Opcodes
.
V1_8
,
0
,
"TestCls"
,
null
,
"java/lang/Object"
,
new
String
[]
{});
cw
.
visitField
(
Opcodes
.
ACC_PRIVATE
,
"field"
,
"Ljava/lang/Iterable;"
,
null
,
null
).
visitEnd
();
MethodVisitor
mv
=
cw
.
visitMethod
(
Opcodes
.
ACC_PUBLIC
,
"toString"
,
"()Ljava/lang/String;"
,
null
,
new
String
[]
{});
mv
.
visitCode
();
mv
.
visitVarInsn
(
Opcodes
.
ALOAD
,
0
);
mv
.
visitFieldInsn
(
Opcodes
.
GETFIELD
,
"TestCls"
,
"field"
,
"Ljava/lang/Iterable;"
);
mv
.
visitMethodInsn
(
Opcodes
.
INVOKESTATIC
,
"java/lang/String"
,
"valueOf"
,
"(Ljava/lang/Object;)Ljava/lang/String;"
,
false
);
mv
.
visitVarInsn
(
Opcodes
.
ASTORE
,
1
);
mv
.
visitIntInsn
(
Opcodes
.
BIPUSH
,
8
);
mv
.
visitVarInsn
(
Opcodes
.
ALOAD
,
1
);
mv
.
visitMethodInsn
(
Opcodes
.
INVOKESTATIC
,
"java/lang/String"
,
"valueOf"
,
"(Ljava/lang/Object;)Ljava/lang/String;"
,
false
);
mv
.
visitMethodInsn
(
Opcodes
.
INVOKEVIRTUAL
,
"java/lang/String"
,
"length"
,
"()I"
,
false
);
mv
.
visitInsn
(
Opcodes
.
IADD
);
mv
.
visitTypeInsn
(
Opcodes
.
NEW
,
"java/lang/StringBuilder"
);
mv
.
visitInsn
(
Opcodes
.
DUP_X1
);
mv
.
visitInsn
(
Opcodes
.
SWAP
);
mv
.
visitMethodInsn
(
Opcodes
.
INVOKESPECIAL
,
"java/lang/StringBuilder"
,
"<init>"
,
"(I)V"
,
false
);
mv
.
visitLdcInsn
(
"concat("
);
mv
.
visitMethodInsn
(
Opcodes
.
INVOKEVIRTUAL
,
"java/lang/StringBuilder"
,
"append"
,
"(Ljava/lang/String;)Ljava/lang/StringBuilder;"
,
false
);
mv
.
visitVarInsn
(
Opcodes
.
ALOAD
,
1
);
mv
.
visitMethodInsn
(
Opcodes
.
INVOKEVIRTUAL
,
"java/lang/StringBuilder"
,
"append"
,
"(Ljava/lang/String;)Ljava/lang/StringBuilder;"
,
false
);
mv
.
visitLdcInsn
(
")"
);
mv
.
visitMethodInsn
(
Opcodes
.
INVOKEVIRTUAL
,
"java/lang/StringBuilder"
,
"append"
,
"(Ljava/lang/String;)Ljava/lang/StringBuilder;"
,
false
);
mv
.
visitMethodInsn
(
Opcodes
.
INVOKEVIRTUAL
,
"java/lang/StringBuilder"
,
"toString"
,
"()Ljava/lang/String;"
,
false
);
mv
.
visitInsn
(
Opcodes
.
ARETURN
);
mv
.
visitMaxs
(
0
,
0
);
// auto calculated
mv
.
visitEnd
();
cw
.
visitEnd
();
byte
[]
clsBytes
=
cw
.
toByteArray
();
StringWriter
results
=
new
StringWriter
();
CheckClassAdapter
.
verify
(
new
ClassReader
(
clsBytes
),
false
,
new
PrintWriter
(
results
));
assertThat
(
results
.
toString
()).
isEmpty
();
Path
clsFile
=
FileUtils
.
createTempFile
(
".class"
);
Files
.
write
(
clsFile
,
clsBytes
);
List
<
File
>
files
=
Collections
.
singletonList
(
clsFile
.
toFile
());
useJavaInput
();
assertThat
(
getClassNodeFromFiles
(
files
,
"TestCls"
))
.
code
();
}
}
jadx-plugins/jadx-dex-input/src/main/java/jadx/plugins/input/dex/sections/DexClassData.java
浏览文件 @
9ea3f0f2
...
@@ -13,6 +13,7 @@ import org.slf4j.LoggerFactory;
...
@@ -13,6 +13,7 @@ import org.slf4j.LoggerFactory;
import
jadx.api.plugins.input.data.IClassData
;
import
jadx.api.plugins.input.data.IClassData
;
import
jadx.api.plugins.input.data.IFieldData
;
import
jadx.api.plugins.input.data.IFieldData
;
import
jadx.api.plugins.input.data.IMethodData
;
import
jadx.api.plugins.input.data.IMethodData
;
import
jadx.api.plugins.input.data.ISeqConsumer
;
import
jadx.api.plugins.input.data.annotations.EncodedValue
;
import
jadx.api.plugins.input.data.annotations.EncodedValue
;
import
jadx.api.plugins.input.data.annotations.IAnnotation
;
import
jadx.api.plugins.input.data.annotations.IAnnotation
;
import
jadx.api.plugins.input.data.attributes.IJadxAttribute
;
import
jadx.api.plugins.input.data.attributes.IJadxAttribute
;
...
@@ -92,7 +93,7 @@ public class DexClassData implements IClassData {
...
@@ -92,7 +93,7 @@ public class DexClassData implements IClassData {
}
}
@Override
@Override
public
void
visitFieldsAndMethods
(
Consumer
<
IFieldData
>
fieldConsumer
,
Consumer
<
IMethodData
>
mthConsumer
)
{
public
void
visitFieldsAndMethods
(
ISeqConsumer
<
IFieldData
>
fieldConsumer
,
ISeq
Consumer
<
IMethodData
>
mthConsumer
)
{
int
classDataOff
=
getClassDataOff
();
int
classDataOff
=
getClassDataOff
();
if
(
classDataOff
==
0
)
{
if
(
classDataOff
==
0
)
{
return
;
return
;
...
@@ -103,6 +104,9 @@ public class DexClassData implements IClassData {
...
@@ -103,6 +104,9 @@ public class DexClassData implements IClassData {
int
directMthCount
=
data
.
readUleb128
();
int
directMthCount
=
data
.
readUleb128
();
int
virtualMthCount
=
data
.
readUleb128
();
int
virtualMthCount
=
data
.
readUleb128
();
fieldConsumer
.
init
(
staticFieldsCount
+
instanceFieldsCount
);
mthConsumer
.
init
(
directMthCount
+
virtualMthCount
);
annotationsParser
.
setOffset
(
getAnnotationsOff
());
annotationsParser
.
setOffset
(
getAnnotationsOff
());
visitFields
(
fieldConsumer
,
data
,
staticFieldsCount
,
instanceFieldsCount
);
visitFields
(
fieldConsumer
,
data
,
staticFieldsCount
,
instanceFieldsCount
);
visitMethods
(
mthConsumer
,
data
,
directMthCount
,
virtualMthCount
);
visitMethods
(
mthConsumer
,
data
,
directMthCount
,
virtualMthCount
);
...
...
jadx-plugins/jadx-java-convert/src/main/java/jadx/plugins/input/javaconvert/JavaConvertLoader.java
浏览文件 @
9ea3f0f2
package
jadx.plugins.input.javaconvert
;
package
jadx.plugins.input.javaconvert
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.nio.file.FileSystems
;
import
java.nio.file.FileSystems
;
import
java.nio.file.Files
;
import
java.nio.file.Files
;
import
java.nio.file.LinkOption
;
import
java.nio.file.LinkOption
;
...
@@ -20,6 +17,7 @@ import java.util.stream.Stream;
...
@@ -20,6 +17,7 @@ import java.util.stream.Stream;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
jadx.api.plugins.utils.CommonFileUtils
;
import
jadx.api.plugins.utils.ZipSecurity
;
import
jadx.api.plugins.utils.ZipSecurity
;
public
class
JavaConvertLoader
{
public
class
JavaConvertLoader
{
...
@@ -81,7 +79,7 @@ public class JavaConvertLoader {
...
@@ -81,7 +79,7 @@ public class JavaConvertLoader {
try
{
try
{
String
entryName
=
entry
.
getName
();
String
entryName
=
entry
.
getName
();
if
(
entryName
.
endsWith
(
".jar"
))
{
if
(
entryName
.
endsWith
(
".jar"
))
{
Path
tempJar
=
saveInputStreamTo
File
(
in
,
".jar"
);
Path
tempJar
=
CommonFileUtils
.
saveToTemp
File
(
in
,
".jar"
);
result
.
addTempPath
(
tempJar
);
result
.
addTempPath
(
tempJar
);
LOG
.
debug
(
"Loading jar: {} ..."
,
entryName
);
LOG
.
debug
(
"Loading jar: {} ..."
,
entryName
);
convertJar
(
result
,
tempJar
);
convertJar
(
result
,
tempJar
);
...
@@ -134,14 +132,14 @@ public class JavaConvertLoader {
...
@@ -134,14 +132,14 @@ public class JavaConvertLoader {
||
entryName
.
startsWith
(
"META-INF/versions/"
))
{
||
entryName
.
startsWith
(
"META-INF/versions/"
))
{
return
;
return
;
}
}
byte
[]
clsFileContent
=
inputStreamToByteArray
(
in
);
byte
[]
clsFileContent
=
CommonFileUtils
.
loadBytes
(
in
);
String
clsName
=
AsmUtils
.
getNameFromClassFile
(
clsFileContent
);
String
clsName
=
AsmUtils
.
getNameFromClassFile
(
clsFileContent
);
if
(
clsName
==
null
||
!
ZipSecurity
.
isValidZipEntryName
(
clsName
))
{
if
(
clsName
==
null
||
!
ZipSecurity
.
isValidZipEntryName
(
clsName
))
{
throw
new
IOException
(
"Can't read class name from file: "
+
entryName
);
throw
new
IOException
(
"Can't read class name from file: "
+
entryName
);
}
}
addJarEntry
(
jo
,
clsName
+
".class"
,
clsFileContent
,
entry
.
getLastModifiedTime
());
addJarEntry
(
jo
,
clsName
+
".class"
,
clsFileContent
,
entry
.
getLastModifiedTime
());
}
else
if
(
entryName
.
endsWith
(
".jar"
))
{
}
else
if
(
entryName
.
endsWith
(
".jar"
))
{
Path
tempJar
=
saveInputStreamTo
File
(
in
,
".jar"
);
Path
tempJar
=
CommonFileUtils
.
saveToTemp
File
(
in
,
".jar"
);
result
.
addTempPath
(
tempJar
);
result
.
addTempPath
(
tempJar
);
convertJar
(
result
,
tempJar
);
convertJar
(
result
,
tempJar
);
}
}
...
@@ -190,32 +188,4 @@ public class JavaConvertLoader {
...
@@ -190,32 +188,4 @@ public class JavaConvertLoader {
jar
.
write
(
content
);
jar
.
write
(
content
);
jar
.
closeEntry
();
jar
.
closeEntry
();
}
}
private
static
void
copyStream
(
InputStream
input
,
OutputStream
output
)
throws
IOException
{
byte
[]
buffer
=
new
byte
[
8
*
1024
];
while
(
true
)
{
int
count
=
input
.
read
(
buffer
);
if
(
count
==
-
1
)
{
break
;
}
output
.
write
(
buffer
,
0
,
count
);
}
}
private
static
byte
[]
inputStreamToByteArray
(
InputStream
input
)
throws
IOException
{
try
(
ByteArrayOutputStream
output
=
new
ByteArrayOutputStream
())
{
copyStream
(
input
,
output
);
return
output
.
toByteArray
();
}
}
private
static
Path
saveInputStreamToFile
(
InputStream
in
,
String
suffix
)
throws
IOException
{
Path
tempJar
=
Files
.
createTempFile
(
"jadx-temp-"
,
suffix
);
try
(
OutputStream
out
=
Files
.
newOutputStream
(
tempJar
))
{
copyStream
(
in
,
out
);
}
catch
(
Exception
e
)
{
throw
new
IOException
(
"Failed to save temp file"
,
e
);
}
return
tempJar
;
}
}
}
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/JavaFileLoader.java
浏览文件 @
9ea3f0f2
package
jadx.plugins.input.java
;
package
jadx.plugins.input.java
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.File
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileInputStream
;
import
java.io.IOException
;
import
java.io.IOException
;
...
@@ -13,9 +12,11 @@ import java.util.Collections;
...
@@ -13,9 +12,11 @@ import java.util.Collections;
import
java.util.List
;
import
java.util.List
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
import
org.jetbrains.annotations.Nullable
;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
jadx.api.plugins.utils.CommonFileUtils
;
import
jadx.api.plugins.utils.ZipSecurity
;
import
jadx.api.plugins.utils.ZipSecurity
;
public
class
JavaFileLoader
{
public
class
JavaFileLoader
{
...
@@ -38,35 +39,53 @@ public class JavaFileLoader {
...
@@ -38,35 +39,53 @@ public class JavaFileLoader {
private
List
<
JavaClassReader
>
loadFromFile
(
File
file
)
{
private
List
<
JavaClassReader
>
loadFromFile
(
File
file
)
{
try
(
InputStream
inputStream
=
new
BufferedInputStream
(
new
FileInputStream
(
file
)))
{
try
(
InputStream
inputStream
=
new
BufferedInputStream
(
new
FileInputStream
(
file
)))
{
return
loadReader
(
file
,
inputStream
,
file
.
getAbsolutePath
()
);
return
loadReader
(
inputStream
,
file
.
getName
(),
file
,
null
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
LOG
.
error
(
"File open error: {}"
,
file
.
getAbsolutePath
(),
e
);
LOG
.
error
(
"File open error: {}"
,
file
.
getAbsolutePath
(),
e
);
return
Collections
.
emptyList
();
return
Collections
.
emptyList
();
}
}
}
}
private
List
<
JavaClassReader
>
loadReader
(
File
file
,
InputStream
in
,
String
inputFileName
)
throws
IOException
{
private
List
<
JavaClassReader
>
loadReader
(
InputStream
in
,
String
name
,
@Nullable
File
file
,
@Nullable
String
parentFileName
)
throws
IOException
{
byte
[]
magic
=
new
byte
[
MAX_MAGIC_SIZE
];
byte
[]
magic
=
new
byte
[
MAX_MAGIC_SIZE
];
if
(
in
.
read
(
magic
)
!=
magic
.
length
)
{
if
(
in
.
read
(
magic
)
!=
magic
.
length
)
{
return
Collections
.
emptyList
();
return
Collections
.
emptyList
();
}
}
if
(
isStartWithBytes
(
magic
,
JAVA_CLASS_FILE_MAGIC
))
{
if
(
isStartWithBytes
(
magic
,
JAVA_CLASS_FILE_MAGIC
))
{
byte
[]
data
=
loadBytes
(
magic
,
in
);
byte
[]
data
=
CommonFileUtils
.
loadBytes
(
magic
,
in
);
JavaClassReader
reader
=
new
JavaClassReader
(
getNextUniqId
(),
inputFileName
,
data
);
String
source
=
concatSource
(
parentFileName
,
name
);
JavaClassReader
reader
=
new
JavaClassReader
(
getNextUniqId
(),
source
,
data
);
return
Collections
.
singletonList
(
reader
);
return
Collections
.
singletonList
(
reader
);
}
}
if
(
file
!=
null
&&
isStartWithBytes
(
magic
,
ZIP_FILE_MAGIC
))
{
if
(
isStartWithBytes
(
magic
,
ZIP_FILE_MAGIC
))
{
return
collectFromZip
(
file
);
if
(
file
!=
null
)
{
return
collectFromZip
(
file
,
name
);
}
File
zipFile
=
CommonFileUtils
.
saveToTempFile
(
magic
,
in
,
".zip"
).
toFile
();
return
collectFromZip
(
zipFile
,
concatSource
(
parentFileName
,
name
));
}
}
return
Collections
.
emptyList
();
return
Collections
.
emptyList
();
}
}
private
List
<
JavaClassReader
>
collectFromZip
(
File
file
)
{
private
static
String
concatSource
(
@Nullable
String
parentFileName
,
String
name
)
{
if
(
parentFileName
==
null
)
{
return
name
;
}
return
parentFileName
+
':'
+
name
;
}
private
List
<
JavaClassReader
>
collectFromZip
(
File
file
,
String
name
)
{
List
<
JavaClassReader
>
result
=
new
ArrayList
<>();
List
<
JavaClassReader
>
result
=
new
ArrayList
<>();
try
{
try
{
ZipSecurity
.
readZipEntries
(
file
,
(
entry
,
in
)
->
{
ZipSecurity
.
readZipEntries
(
file
,
(
entry
,
in
)
->
{
try
{
try
{
result
.
addAll
(
loadReader
(
null
,
in
,
entry
.
getName
()));
String
entryName
=
entry
.
getName
();
if
(
entryName
.
startsWith
(
"META-INF/versions/"
))
{
// skip classes for different java versions
return
;
}
result
.
addAll
(
loadReader
(
in
,
entryName
,
null
,
name
));
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Failed to read zip entry: {}"
,
entry
,
e
);
LOG
.
error
(
"Failed to read zip entry: {}"
,
entry
,
e
);
}
}
...
@@ -90,21 +109,6 @@ public class JavaFileLoader {
...
@@ -90,21 +109,6 @@ public class JavaFileLoader {
return
true
;
return
true
;
}
}
public
static
byte
[]
loadBytes
(
byte
[]
prefix
,
InputStream
in
)
throws
IOException
{
int
estimateSize
=
prefix
.
length
+
in
.
available
();
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
(
estimateSize
);
out
.
write
(
prefix
);
byte
[]
buffer
=
new
byte
[
8
*
1024
];
while
(
true
)
{
int
len
=
in
.
read
(
buffer
);
if
(
len
==
-
1
)
{
break
;
}
out
.
write
(
buffer
,
0
,
len
);
}
return
out
.
toByteArray
();
}
private
int
getNextUniqId
()
{
private
int
getNextUniqId
()
{
return
classUniqId
++;
return
classUniqId
++;
}
}
...
...
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/ConstPoolReader.java
浏览文件 @
9ea3f0f2
...
@@ -239,14 +239,17 @@ public class ConstPoolReader {
...
@@ -239,14 +239,17 @@ public class ConstPoolReader {
private
String
fixType
(
String
clsName
)
{
private
String
fixType
(
String
clsName
)
{
switch
(
clsName
.
charAt
(
0
))
{
switch
(
clsName
.
charAt
(
0
))
{
case
'L'
:
case
'T'
:
case
'['
:
case
'['
:
return
clsName
;
return
clsName
;
default
:
case
'L'
:
return
'L'
+
clsName
+
';'
;
case
'T'
:
if
(
clsName
.
endsWith
(
";"
))
{
return
clsName
;
}
break
;
}
}
return
'L'
+
clsName
+
';'
;
}
}
private
void
jumpToData
(
int
idx
)
{
private
void
jumpToData
(
int
idx
)
{
...
...
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/JavaClassData.java
浏览文件 @
9ea3f0f2
...
@@ -3,7 +3,6 @@ package jadx.plugins.input.java.data;
...
@@ -3,7 +3,6 @@ package jadx.plugins.input.java.data;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.List
;
import
java.util.function.Consumer
;
import
org.jetbrains.annotations.Nullable
;
import
org.jetbrains.annotations.Nullable
;
...
@@ -11,6 +10,7 @@ import jadx.api.plugins.input.data.AccessFlags;
...
@@ -11,6 +10,7 @@ import jadx.api.plugins.input.data.AccessFlags;
import
jadx.api.plugins.input.data.IClassData
;
import
jadx.api.plugins.input.data.IClassData
;
import
jadx.api.plugins.input.data.IFieldData
;
import
jadx.api.plugins.input.data.IFieldData
;
import
jadx.api.plugins.input.data.IMethodData
;
import
jadx.api.plugins.input.data.IMethodData
;
import
jadx.api.plugins.input.data.ISeqConsumer
;
import
jadx.api.plugins.input.data.attributes.IJadxAttribute
;
import
jadx.api.plugins.input.data.attributes.IJadxAttribute
;
import
jadx.api.plugins.utils.Utils
;
import
jadx.api.plugins.utils.Utils
;
import
jadx.plugins.input.java.JavaClassReader
;
import
jadx.plugins.input.java.JavaClassReader
;
...
@@ -74,11 +74,12 @@ public class JavaClassData implements IClassData {
...
@@ -74,11 +74,12 @@ public class JavaClassData implements IClassData {
}
}
@Override
@Override
public
void
visitFieldsAndMethods
(
Consumer
<
IFieldData
>
fieldsConsumer
,
Consumer
<
IMethodData
>
mthConsumer
)
{
public
void
visitFieldsAndMethods
(
ISeqConsumer
<
IFieldData
>
fieldsConsumer
,
ISeq
Consumer
<
IMethodData
>
mthConsumer
)
{
int
clsIdx
=
data
.
absPos
(
offsets
.
getClsTypeOffset
()).
readU2
();
int
clsIdx
=
data
.
absPos
(
offsets
.
getClsTypeOffset
()).
readU2
();
String
classType
=
constPoolReader
.
getClass
(
clsIdx
);
String
classType
=
constPoolReader
.
getClass
(
clsIdx
);
DataReader
reader
=
data
.
absPos
(
offsets
.
getFieldsOffset
()).
copy
();
DataReader
reader
=
data
.
absPos
(
offsets
.
getFieldsOffset
()).
copy
();
int
fieldsCount
=
reader
.
readU2
();
int
fieldsCount
=
reader
.
readU2
();
fieldsConsumer
.
init
(
fieldsCount
);
if
(
fieldsCount
!=
0
)
{
if
(
fieldsCount
!=
0
)
{
JavaFieldData
field
=
new
JavaFieldData
();
JavaFieldData
field
=
new
JavaFieldData
();
field
.
setParentClassType
(
classType
);
field
.
setParentClassType
(
classType
);
...
@@ -89,6 +90,7 @@ public class JavaClassData implements IClassData {
...
@@ -89,6 +90,7 @@ public class JavaClassData implements IClassData {
}
}
int
methodsCount
=
reader
.
readU2
();
int
methodsCount
=
reader
.
readU2
();
mthConsumer
.
init
(
methodsCount
);
if
(
methodsCount
!=
0
)
{
if
(
methodsCount
!=
0
)
{
JavaMethodRef
methodRef
=
new
JavaMethodRef
();
JavaMethodRef
methodRef
=
new
JavaMethodRef
();
methodRef
.
setParentClassType
(
classType
);
methodRef
.
setParentClassType
(
classType
);
...
...
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/AttributesReader.java
浏览文件 @
9ea3f0f2
...
@@ -16,7 +16,7 @@ public class AttributesReader {
...
@@ -16,7 +16,7 @@ public class AttributesReader {
private
final
JavaClassData
clsData
;
private
final
JavaClassData
clsData
;
private
final
ConstPoolReader
constPool
;
private
final
ConstPoolReader
constPool
;
private
final
Map
<
Integer
,
JavaAttrType
<?>>
attr
Map
=
new
HashMap
<>(
JavaAttrType
.
size
());
private
final
Map
<
Integer
,
JavaAttrType
<?>>
attr
Cache
=
new
HashMap
<>(
JavaAttrType
.
size
());
public
AttributesReader
(
JavaClassData
clsData
,
ConstPoolReader
constPoolReader
)
{
public
AttributesReader
(
JavaClassData
clsData
,
ConstPoolReader
constPoolReader
)
{
this
.
clsData
=
clsData
;
this
.
clsData
=
clsData
;
...
@@ -95,8 +95,8 @@ public class AttributesReader {
...
@@ -95,8 +95,8 @@ public class AttributesReader {
}
}
private
JavaAttrType
<?>
resolveAttrReader
(
int
nameIdx
)
{
private
JavaAttrType
<?>
resolveAttrReader
(
int
nameIdx
)
{
return
attr
Map
.
computeIfAbsent
(
nameIdx
,
idx
->
{
return
attr
Cache
.
computeIfAbsent
(
nameIdx
,
idx
->
{
String
attrName
=
constPool
.
getUtf8
(
nameI
dx
);
String
attrName
=
constPool
.
getUtf8
(
i
dx
);
JavaAttrType
<?>
attrType
=
JavaAttrType
.
byName
(
attrName
);
JavaAttrType
<?>
attrType
=
JavaAttrType
.
byName
(
attrName
);
if
(
attrType
==
null
)
{
if
(
attrType
==
null
)
{
LOG
.
warn
(
"Unknown java class attribute type: {}"
,
attrName
);
LOG
.
warn
(
"Unknown java class attribute type: {}"
,
attrName
);
...
...
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/attributes/JavaAttrType.java
浏览文件 @
9ea3f0f2
...
@@ -39,6 +39,8 @@ public final class JavaAttrType<T extends IJavaAttribute> {
...
@@ -39,6 +39,8 @@ public final class JavaAttrType<T extends IJavaAttribute> {
public
static
final
JavaAttrType
<
JavaAnnotationsAttr
>
BUILD_ANNOTATIONS
;
public
static
final
JavaAttrType
<
JavaAnnotationsAttr
>
BUILD_ANNOTATIONS
;
public
static
final
JavaAttrType
<
JavaParamAnnsAttr
>
RUNTIME_PARAMETER_ANNOTATIONS
;
public
static
final
JavaAttrType
<
JavaParamAnnsAttr
>
RUNTIME_PARAMETER_ANNOTATIONS
;
public
static
final
JavaAttrType
<
JavaParamAnnsAttr
>
BUILD_PARAMETER_ANNOTATIONS
;
public
static
final
JavaAttrType
<
JavaParamAnnsAttr
>
BUILD_PARAMETER_ANNOTATIONS
;
public
static
final
JavaAttrType
<
IgnoredAttr
>
RUNTIME_TYPE_ANNOTATIONS
;
public
static
final
JavaAttrType
<
IgnoredAttr
>
BUILD_TYPE_ANNOTATIONS
;
public
static
final
JavaAttrType
<
JavaAnnotationDefaultAttr
>
ANNOTATION_DEFAULT
;
public
static
final
JavaAttrType
<
JavaAnnotationDefaultAttr
>
ANNOTATION_DEFAULT
;
public
static
final
JavaAttrType
<
JavaSourceFileAttr
>
SOURCE_FILE
;
public
static
final
JavaAttrType
<
JavaSourceFileAttr
>
SOURCE_FILE
;
...
@@ -46,7 +48,10 @@ public final class JavaAttrType<T extends IJavaAttribute> {
...
@@ -46,7 +48,10 @@ public final class JavaAttrType<T extends IJavaAttribute> {
public
static
final
JavaAttrType
<
JavaExceptionsAttr
>
EXCEPTIONS
;
public
static
final
JavaAttrType
<
JavaExceptionsAttr
>
EXCEPTIONS
;
public
static
final
JavaAttrType
<
IgnoredAttr
>
DEPRECATED
;
public
static
final
JavaAttrType
<
IgnoredAttr
>
DEPRECATED
;
public
static
final
JavaAttrType
<
IgnoredAttr
>
SYNTHETIC
;
public
static
final
JavaAttrType
<
IgnoredAttr
>
STACK_MAP_TABLE
;
public
static
final
JavaAttrType
<
IgnoredAttr
>
STACK_MAP_TABLE
;
public
static
final
JavaAttrType
<
IgnoredAttr
>
ENCLOSING_METHOD
;
public
static
final
JavaAttrType
<
IgnoredAttr
>
MODULE
;
static
{
static
{
NAME_TO_TYPE_MAP
=
new
HashMap
<>();
NAME_TO_TYPE_MAP
=
new
HashMap
<>();
...
@@ -74,7 +79,14 @@ public final class JavaAttrType<T extends IJavaAttribute> {
...
@@ -74,7 +79,14 @@ public final class JavaAttrType<T extends IJavaAttribute> {
// ignored
// ignored
DEPRECATED
=
bind
(
"Deprecated"
,
null
);
// duplicated by annotation
DEPRECATED
=
bind
(
"Deprecated"
,
null
);
// duplicated by annotation
SYNTHETIC
=
bind
(
"Synthetic"
,
null
);
// duplicated by access flag
STACK_MAP_TABLE
=
bind
(
"StackMapTable"
,
null
);
STACK_MAP_TABLE
=
bind
(
"StackMapTable"
,
null
);
ENCLOSING_METHOD
=
bind
(
"EnclosingMethod"
,
null
);
// TODO: not supported yet
RUNTIME_TYPE_ANNOTATIONS
=
bind
(
"RuntimeVisibleTypeAnnotations"
,
null
);
BUILD_TYPE_ANNOTATIONS
=
bind
(
"RuntimeInvisibleTypeAnnotations"
,
null
);
MODULE
=
bind
(
"Module"
,
null
);
}
}
private
static
<
A
extends
IJavaAttribute
>
JavaAttrType
<
A
>
bind
(
String
name
,
IJavaAttributeReader
reader
)
{
private
static
<
A
extends
IJavaAttribute
>
JavaAttrType
<
A
>
bind
(
String
name
,
IJavaAttributeReader
reader
)
{
...
@@ -113,4 +125,9 @@ public final class JavaAttrType<T extends IJavaAttribute> {
...
@@ -113,4 +125,9 @@ public final class JavaAttrType<T extends IJavaAttribute> {
public
IJavaAttributeReader
getReader
()
{
public
IJavaAttributeReader
getReader
()
{
return
reader
;
return
reader
;
}
}
@Override
public
String
toString
()
{
return
name
;
}
}
}
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaCodeReader.java
浏览文件 @
9ea3f0f2
...
@@ -52,8 +52,7 @@ public class JavaCodeReader implements ICodeReader {
...
@@ -52,8 +52,7 @@ public class JavaCodeReader implements ICodeReader {
@Override
@Override
public
void
visitInstructions
(
Consumer
<
InsnData
>
insnConsumer
)
{
public
void
visitInstructions
(
Consumer
<
InsnData
>
insnConsumer
)
{
Set
<
Integer
>
excHandlers
=
getExcHandlers
();
Set
<
Integer
>
excHandlers
=
getExcHandlers
();
reader
.
absPos
(
codeOffset
);
int
maxStack
=
readMaxStack
();
int
maxStack
=
reader
.
readU2
();
reader
.
skip
(
2
);
reader
.
skip
(
2
);
int
codeSize
=
reader
.
readU4
();
int
codeSize
=
reader
.
readU4
();
...
@@ -96,16 +95,20 @@ public class JavaCodeReader implements ICodeReader {
...
@@ -96,16 +95,20 @@ public class JavaCodeReader implements ICodeReader {
@Override
@Override
public
int
getRegistersCount
()
{
public
int
getRegistersCount
()
{
reader
.
absPos
(
codeOffset
);
int
maxStack
=
readMaxStack
();
int
maxStack
=
reader
.
readU2
();
int
maxLocals
=
reader
.
readU2
();
int
maxLocals
=
reader
.
readU2
();
return
maxStack
+
maxLocals
;
return
maxStack
+
maxLocals
;
}
}
@Override
@Override
public
int
getArgsStartReg
()
{
public
int
getArgsStartReg
()
{
return
readMaxStack
();
}
private
int
readMaxStack
()
{
reader
.
absPos
(
codeOffset
);
reader
.
absPos
(
codeOffset
);
return
reader
.
readU2
();
// maxStack
int
maxStack
=
reader
.
readU2
();
return
maxStack
+
1
;
// add one temporary register (for `swap` opcode)
}
}
@Override
@Override
...
@@ -114,9 +117,9 @@ public class JavaCodeReader implements ICodeReader {
...
@@ -114,9 +117,9 @@ public class JavaCodeReader implements ICodeReader {
}
}
@Override
@Override
public
@Nullable
IDebugInfo
getDebugInfo
()
{
@Nullable
reader
.
absPos
(
codeOffset
);
public
IDebugInfo
getDebugInfo
()
{
int
maxStack
=
read
er
.
readU2
();
int
maxStack
=
read
MaxStack
();
reader
.
skip
(
2
);
reader
.
skip
(
2
);
reader
.
skip
(
reader
.
readU4
());
reader
.
skip
(
reader
.
readU4
());
reader
.
skip
(
reader
.
readU2
()
*
8
);
reader
.
skip
(
reader
.
readU2
()
*
8
);
...
...
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/JavaInsnsRegister.java
浏览文件 @
9ea3f0f2
...
@@ -10,6 +10,7 @@ import jadx.plugins.input.java.data.code.decoders.InvokeDecoder;
...
@@ -10,6 +10,7 @@ import jadx.plugins.input.java.data.code.decoders.InvokeDecoder;
import
jadx.plugins.input.java.data.code.decoders.LoadConstDecoder
;
import
jadx.plugins.input.java.data.code.decoders.LoadConstDecoder
;
import
jadx.plugins.input.java.data.code.decoders.LookupSwitchDecoder
;
import
jadx.plugins.input.java.data.code.decoders.LookupSwitchDecoder
;
import
jadx.plugins.input.java.data.code.decoders.TableSwitchDecoder
;
import
jadx.plugins.input.java.data.code.decoders.TableSwitchDecoder
;
import
jadx.plugins.input.java.data.code.decoders.WideDecoder
;
import
static
jadx
.
plugins
.
input
.
java
.
data
.
code
.
StackState
.
SVType
.
NARROW
;
import
static
jadx
.
plugins
.
input
.
java
.
data
.
code
.
StackState
.
SVType
.
NARROW
;
import
static
jadx
.
plugins
.
input
.
java
.
data
.
code
.
StackState
.
SVType
.
WIDE
;
import
static
jadx
.
plugins
.
input
.
java
.
data
.
code
.
StackState
.
SVType
.
WIDE
;
...
@@ -172,6 +173,10 @@ public class JavaInsnsRegister {
...
@@ -172,6 +173,10 @@ public class JavaInsnsRegister {
.
peekFrom
(
2
,
4
).
peekFrom
(
0
,
5
);
.
peekFrom
(
2
,
4
).
peekFrom
(
0
,
5
);
}
}
});
});
register
(
arr
,
0x5f
,
"swap"
,
0
,
6
,
Opcode
.
MOVE_MULTI
,
s
->
s
.
peekFrom
(-
1
,
0
).
peekFrom
(
1
,
1
)
.
peekFrom
(
1
,
2
).
peekFrom
(
0
,
3
)
.
peekFrom
(
0
,
4
).
peekFrom
(-
1
,
5
));
register
(
arr
,
0x60
,
"iadd"
,
0
,
3
,
Opcode
.
ADD_INT
,
twoRegsWithResult
(
NARROW
));
register
(
arr
,
0x60
,
"iadd"
,
0
,
3
,
Opcode
.
ADD_INT
,
twoRegsWithResult
(
NARROW
));
register
(
arr
,
0x61
,
"ladd"
,
0
,
3
,
Opcode
.
ADD_LONG
,
twoRegsWithResult
(
WIDE
));
register
(
arr
,
0x61
,
"ladd"
,
0
,
3
,
Opcode
.
ADD_LONG
,
twoRegsWithResult
(
WIDE
));
...
@@ -295,7 +300,7 @@ public class JavaInsnsRegister {
...
@@ -295,7 +300,7 @@ public class JavaInsnsRegister {
register
(
arr
,
0xc2
,
"monitorenter"
,
0
,
1
,
Opcode
.
MONITOR_ENTER
,
s
->
s
.
pop
(
0
));
register
(
arr
,
0xc2
,
"monitorenter"
,
0
,
1
,
Opcode
.
MONITOR_ENTER
,
s
->
s
.
pop
(
0
));
register
(
arr
,
0xc3
,
"monitorexit"
,
0
,
1
,
Opcode
.
MONITOR_EXIT
,
s
->
s
.
pop
(
0
));
register
(
arr
,
0xc3
,
"monitorexit"
,
0
,
1
,
Opcode
.
MONITOR_EXIT
,
s
->
s
.
pop
(
0
));
// register(arr, 0xc4, "wide", 0, 1, Opcode.NOP, s -> s.pop(0
));
register
(
arr
,
0xc4
,
"wide"
,
-
1
,
-
1
,
Opcode
.
NOP
,
new
WideDecoder
(
));
register
(
arr
,
0xc5
,
"multianewarray"
,
3
,
-
1
,
Opcode
.
NEW_ARRAY
,
InsnIndexType
.
TYPE_REF
,
newArrayMulti
());
register
(
arr
,
0xc5
,
"multianewarray"
,
3
,
-
1
,
Opcode
.
NEW_ARRAY
,
InsnIndexType
.
TYPE_REF
,
newArrayMulti
());
register
(
arr
,
0xc6
,
"ifnull"
,
2
,
1
,
Opcode
.
IF_EQZ
,
zeroCmp
());
register
(
arr
,
0xc6
,
"ifnull"
,
2
,
1
,
Opcode
.
IF_EQZ
,
zeroCmp
());
...
...
jadx-plugins/jadx-java-input/src/main/java/jadx/plugins/input/java/data/code/decoders/WideDecoder.java
0 → 100644
浏览文件 @
9ea3f0f2
package
jadx.plugins.input.java.data.code.decoders
;
import
jadx.api.plugins.input.insns.Opcode
;
import
jadx.plugins.input.java.data.DataReader
;
import
jadx.plugins.input.java.data.code.CodeDecodeState
;
import
jadx.plugins.input.java.data.code.JavaInsnData
;
import
jadx.plugins.input.java.utils.JavaClassParseException
;
public
class
WideDecoder
implements
IJavaInsnDecoder
{
private
static
final
int
IINC
=
0x84
;
@Override
public
void
decode
(
CodeDecodeState
state
)
{
DataReader
reader
=
state
.
reader
();
JavaInsnData
insn
=
state
.
insn
();
int
opcode
=
reader
.
readU1
();
if
(
opcode
==
IINC
)
{
int
varNum
=
reader
.
readU2
();
int
constValue
=
reader
.
readS2
();
state
.
local
(
0
,
varNum
).
local
(
1
,
varNum
).
lit
(
constValue
);
insn
.
setPayloadSize
(
5
);
insn
.
setRegsCount
(
2
);
insn
.
setOpcode
(
Opcode
.
ADD_INT_LIT
);
return
;
}
int
index
=
reader
.
readU2
();
switch
(
opcode
)
{
case
0x15
:
// iload,
case
0x17
:
// fload
case
0x19
:
// aload
state
.
local
(
1
,
index
).
push
(
0
);
break
;
case
0x16
:
// lload
case
0x18
:
// dload
state
.
local
(
1
,
index
).
pushWide
(
0
);
break
;
case
0x36
:
case
0x37
:
case
0x38
:
case
0x39
:
case
0x3a
:
// *store
state
.
pop
(
1
).
local
(
0
,
index
);
break
;
default
:
throw
new
JavaClassParseException
(
"Unexpected opcode in 'wide': 0x"
+
Integer
.
toHexString
(
opcode
));
}
insn
.
setPayloadSize
(
3
);
insn
.
setRegsCount
(
2
);
insn
.
setOpcode
(
Opcode
.
MOVE
);
}
@Override
public
void
skip
(
CodeDecodeState
state
)
{
DataReader
reader
=
state
.
reader
();
JavaInsnData
insn
=
state
.
insn
();
int
opcode
=
reader
.
readU1
();
if
(
opcode
==
IINC
)
{
reader
.
skip
(
4
);
insn
.
setPayloadSize
(
5
);
}
else
{
reader
.
skip
(
2
);
insn
.
setPayloadSize
(
3
);
}
}
}
jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/IClassData.java
浏览文件 @
9ea3f0f2
package
jadx.api.plugins.input.data
;
package
jadx.api.plugins.input.data
;
import
java.util.List
;
import
java.util.List
;
import
java.util.function.Consumer
;
import
org.jetbrains.annotations.Nullable
;
import
org.jetbrains.annotations.Nullable
;
...
@@ -21,7 +20,7 @@ public interface IClassData {
...
@@ -21,7 +20,7 @@ public interface IClassData {
List
<
String
>
getInterfacesTypes
();
List
<
String
>
getInterfacesTypes
();
void
visitFieldsAndMethods
(
Consumer
<
IFieldData
>
fieldsConsumer
,
Consumer
<
IMethodData
>
mthConsumer
);
void
visitFieldsAndMethods
(
ISeqConsumer
<
IFieldData
>
fieldsConsumer
,
ISeq
Consumer
<
IMethodData
>
mthConsumer
);
List
<
IJadxAttribute
>
getAttributes
();
List
<
IJadxAttribute
>
getAttributes
();
...
...
jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/ISeqConsumer.java
0 → 100644
浏览文件 @
9ea3f0f2
package
jadx.api.plugins.input.data
;
import
java.util.function.Consumer
;
/**
* "Sequence consumer" allows getting count of elements available
*/
public
interface
ISeqConsumer
<
T
>
extends
Consumer
<
T
>
{
default
void
init
(
int
count
)
{
// no-op implementation
}
}
jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/input/data/impl/ListConsumer.java
0 → 100644
浏览文件 @
9ea3f0f2
package
jadx.api.plugins.input.data.impl
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.function.Function
;
import
jadx.api.plugins.input.data.ISeqConsumer
;
public
class
ListConsumer
<
T
,
R
>
implements
ISeqConsumer
<
T
>
{
private
final
Function
<
T
,
R
>
convert
;
private
List
<
R
>
list
;
public
ListConsumer
(
Function
<
T
,
R
>
convert
)
{
this
.
convert
=
convert
;
}
@Override
public
void
init
(
int
count
)
{
list
=
count
==
0
?
Collections
.
emptyList
()
:
new
ArrayList
<>(
count
);
}
@Override
public
void
accept
(
T
t
)
{
list
.
add
(
convert
.
apply
(
t
));
}
public
List
<
R
>
getResult
()
{
if
(
list
==
null
)
{
// init not called
return
Collections
.
emptyList
();
}
return
list
;
}
}
jadx-plugins/jadx-plugins-api/src/main/java/jadx/api/plugins/utils/CommonFileUtils.java
0 → 100644
浏览文件 @
9ea3f0f2
package
jadx.api.plugins.utils
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
public
class
CommonFileUtils
{
public
static
Path
saveToTempFile
(
InputStream
in
,
String
suffix
)
throws
IOException
{
return
saveToTempFile
(
null
,
in
,
suffix
);
}
public
static
Path
saveToTempFile
(
byte
[]
dataPrefix
,
InputStream
in
,
String
suffix
)
throws
IOException
{
Path
tempFile
=
Files
.
createTempFile
(
"jadx-temp-"
,
suffix
);
try
(
OutputStream
out
=
Files
.
newOutputStream
(
tempFile
))
{
if
(
dataPrefix
!=
null
)
{
out
.
write
(
dataPrefix
);
}
copyStream
(
in
,
out
);
}
catch
(
Exception
e
)
{
throw
new
IOException
(
"Failed to save temp file"
,
e
);
}
return
tempFile
;
}
public
static
byte
[]
loadBytes
(
InputStream
input
)
throws
IOException
{
return
loadBytes
(
null
,
input
);
}
public
static
byte
[]
loadBytes
(
byte
[]
dataPrefix
,
InputStream
in
)
throws
IOException
{
int
estimateSize
=
dataPrefix
==
null
?
in
.
available
()
:
dataPrefix
.
length
+
in
.
available
();
try
(
ByteArrayOutputStream
out
=
new
ByteArrayOutputStream
(
estimateSize
))
{
if
(
dataPrefix
!=
null
)
{
out
.
write
(
dataPrefix
);
}
copyStream
(
in
,
out
);
return
out
.
toByteArray
();
}
catch
(
Exception
e
)
{
throw
new
IOException
(
"Failed to read input stream to bytes array"
,
e
);
}
}
public
static
void
copyStream
(
InputStream
input
,
OutputStream
output
)
throws
IOException
{
byte
[]
buffer
=
new
byte
[
8
*
1024
];
while
(
true
)
{
int
count
=
input
.
read
(
buffer
);
if
(
count
==
-
1
)
{
break
;
}
output
.
write
(
buffer
,
0
,
count
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录