Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
游着的黑鱼
jadx
提交
073d66ce
J
jadx
项目概览
游着的黑鱼
/
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 搜索 >>
未验证
提交
073d66ce
编写于
3月 05, 2022
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: add 'simple' decompilation mode
上级
b008568a
变更
26
隐藏空白更改
内联
并排
Showing
26 changed file
with
580 addition
and
120 deletion
+580
-120
README.md
README.md
+6
-1
jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
+35
-2
jadx-core/src/main/java/jadx/api/DecompilationMode.java
jadx-core/src/main/java/jadx/api/DecompilationMode.java
+23
-0
jadx-core/src/main/java/jadx/api/JadxArgs.java
jadx-core/src/main/java/jadx/api/JadxArgs.java
+21
-6
jadx-core/src/main/java/jadx/core/Jadx.java
jadx-core/src/main/java/jadx/core/Jadx.java
+65
-17
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
+1
-1
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
+19
-7
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
+152
-52
jadx-core/src/main/java/jadx/core/codegen/SimpleModeHelper.java
...ore/src/main/java/jadx/core/codegen/SimpleModeHelper.java
+129
-0
jadx-core/src/main/java/jadx/core/dex/attributes/AFlag.java
jadx-core/src/main/java/jadx/core/dex/attributes/AFlag.java
+2
-0
jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxError.java
...c/main/java/jadx/core/dex/attributes/nodes/JadxError.java
+1
-5
jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
+8
-0
jadx-core/src/main/java/jadx/core/dex/visitors/MethodVisitor.java
...e/src/main/java/jadx/core/dex/visitors/MethodVisitor.java
+31
-0
jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockExceptionHandler.java
.../jadx/core/dex/visitors/blocks/BlockExceptionHandler.java
+14
-6
jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockProcessor.java
...in/java/jadx/core/dex/visitors/blocks/BlockProcessor.java
+4
-2
jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockSplitter.java
...ain/java/jadx/core/dex/visitors/blocks/BlockSplitter.java
+4
-4
jadx-core/src/main/java/jadx/core/utils/BlockUtils.java
jadx-core/src/main/java/jadx/core/utils/BlockUtils.java
+25
-0
jadx-core/src/main/java/jadx/core/utils/CodeGenUtils.java
jadx-core/src/main/java/jadx/core/utils/CodeGenUtils.java
+11
-8
jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
+14
-1
jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
...i/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
+9
-8
jadx-gui/src/main/resources/i18n/Messages_de_DE.properties
jadx-gui/src/main/resources/i18n/Messages_de_DE.properties
+1
-0
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
+1
-0
jadx-gui/src/main/resources/i18n/Messages_es_ES.properties
jadx-gui/src/main/resources/i18n/Messages_es_ES.properties
+1
-0
jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties
jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties
+1
-0
jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties
jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties
+1
-0
jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties
jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties
+1
-0
未找到文件。
README.md
浏览文件 @
073d66ce
...
...
@@ -84,6 +84,11 @@ options:
--output-format - can be 'java' or 'json', default: java
-e, --export-gradle - save as android gradle project
-j, --threads-count - processing threads count, default: 4
-m, --decompilation-mode - code output mode:
'auto' - trying best options (default)
'restructure' - restore code structure (normal java code)
'simple' - simplified instructions (linear, with goto's)
'fallback' - raw instructions without modifications
--show-bad-code - show inconsistent code (incorrectly decompiled)
--no-imports - disable use of imports, always write entire package name
--no-debug-info - disable debug info
...
...
@@ -115,7 +120,7 @@ options:
--fs-case-sensitive - treat filesystem as case sensitive, false by default
--cfg - save methods control flow graph to dot file
--raw-cfg - save methods control flow graph (use raw instructions)
-f, --fallback -
make simple dump (using goto instead of 'if', 'for', etc
)
-f, --fallback -
set '--decompilation-mode' to 'fallback' (deprecated
)
--use-dx - use dx/d8 to convert java bytecode
--comments-level - set code comments level, values: error, warn, info, debug, user-only, none, default: info
--log-level - set log level, values: quiet, progress, error, warn, info, debug, default: progress
...
...
jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
浏览文件 @
073d66ce
...
...
@@ -15,6 +15,7 @@ import com.beust.jcommander.IStringConverter;
import
com.beust.jcommander.Parameter
;
import
jadx.api.CommentsLevel
;
import
jadx.api.DecompilationMode
;
import
jadx.api.JadxArgs
;
import
jadx.api.JadxArgs.RenameEnum
;
import
jadx.api.JadxArgs.UseKotlinMethodsForVarNames
;
...
...
@@ -58,6 +59,17 @@ public class JadxCLIArgs {
@Parameter
(
names
=
{
"-j"
,
"--threads-count"
},
description
=
"processing threads count"
)
protected
int
threadsCount
=
JadxArgs
.
DEFAULT_THREADS_COUNT
;
@Parameter
(
names
=
{
"-m"
,
"--decompilation-mode"
},
description
=
"code output mode:"
+
"\n 'auto' - trying best options (default)"
+
"\n 'restructure' - restore code structure (normal java code)"
+
"\n 'simple' - simplified instructions (linear, with goto's)"
+
"\n 'fallback' - raw instructions without modifications"
,
converter
=
RenameConverter
.
class
)
protected
DecompilationMode
decompilationMode
=
DecompilationMode
.
AUTO
;
@Parameter
(
names
=
{
"--show-bad-code"
},
description
=
"show inconsistent code (incorrectly decompiled)"
)
protected
boolean
showInconsistentCode
=
false
;
...
...
@@ -148,7 +160,7 @@ public class JadxCLIArgs {
@Parameter
(
names
=
{
"--raw-cfg"
},
description
=
"save methods control flow graph (use raw instructions)"
)
protected
boolean
rawCfgOutput
=
false
;
@Parameter
(
names
=
{
"-f"
,
"--fallback"
},
description
=
"
make simple dump (using goto instead of 'if', 'for', etc
)"
)
@Parameter
(
names
=
{
"-f"
,
"--fallback"
},
description
=
"
set '--decompilation-mode' to 'fallback' (deprecated
)"
)
protected
boolean
fallbackMode
=
false
;
@Parameter
(
names
=
{
"--use-dx"
},
description
=
"use dx/d8 to convert java bytecode"
)
...
...
@@ -236,7 +248,11 @@ public class JadxCLIArgs {
args
.
setThreadsCount
(
threadsCount
);
args
.
setSkipSources
(
skipSources
);
args
.
setSkipResources
(
skipResources
);
args
.
setFallbackMode
(
fallbackMode
);
if
(
fallbackMode
)
{
args
.
setDecompilationMode
(
DecompilationMode
.
FALLBACK
);
}
else
{
args
.
setDecompilationMode
(
decompilationMode
);
}
args
.
setShowInconsistentCode
(
showInconsistentCode
);
args
.
setCfgOutput
(
cfgOutput
);
args
.
setRawCFGOutput
(
rawCfgOutput
);
...
...
@@ -313,6 +329,10 @@ public class JadxCLIArgs {
return
useDx
;
}
public
DecompilationMode
getDecompilationMode
()
{
return
decompilationMode
;
}
public
boolean
isShowInconsistentCode
()
{
return
showInconsistentCode
;
}
...
...
@@ -493,6 +513,19 @@ public class JadxCLIArgs {
}
}
public
static
class
DecompilationModeConverter
implements
IStringConverter
<
DecompilationMode
>
{
@Override
public
DecompilationMode
convert
(
String
value
)
{
try
{
return
DecompilationMode
.
valueOf
(
value
.
toUpperCase
());
}
catch
(
Exception
e
)
{
throw
new
IllegalArgumentException
(
'\''
+
value
+
"' is unknown, possible values are: "
+
JadxCLIArgs
.
enumValuesString
(
DecompilationMode
.
values
()));
}
}
}
public
static
String
enumValuesString
(
Enum
<?>[]
values
)
{
return
Stream
.
of
(
values
)
.
map
(
v
->
v
.
name
().
replace
(
'_'
,
'-'
).
toLowerCase
(
Locale
.
ROOT
))
...
...
jadx-core/src/main/java/jadx/api/DecompilationMode.java
0 → 100644
浏览文件 @
073d66ce
package
jadx.api
;
public
enum
DecompilationMode
{
/**
* Trying best options (default)
*/
AUTO
,
/**
* Restore code structure (normal java code)
*/
RESTRUCTURE
,
/**
* Simplified instructions (linear with goto's)
*/
SIMPLE
,
/**
* Raw instructions without modifications
*/
FALLBACK
}
jadx-core/src/main/java/jadx/api/JadxArgs.java
浏览文件 @
073d66ce
...
...
@@ -38,7 +38,6 @@ public class JadxArgs {
private
boolean
cfgOutput
=
false
;
private
boolean
rawCFGOutput
=
false
;
private
boolean
fallbackMode
=
false
;
private
boolean
showInconsistentCode
=
false
;
private
boolean
useImports
=
true
;
...
...
@@ -85,6 +84,8 @@ public class JadxArgs {
private
OutputFormatEnum
outputFormat
=
OutputFormatEnum
.
JAVA
;
private
DecompilationMode
decompilationMode
=
DecompilationMode
.
AUTO
;
private
ICodeData
codeData
;
private
CommentsLevel
commentsLevel
=
CommentsLevel
.
INFO
;
...
...
@@ -175,11 +176,17 @@ public class JadxArgs {
}
public
boolean
isFallbackMode
()
{
return
fallbackMode
;
return
decompilationMode
==
DecompilationMode
.
FALLBACK
;
}
/**
* Deprecated: use 'decompilation mode' property
*/
@Deprecated
public
void
setFallbackMode
(
boolean
fallbackMode
)
{
this
.
fallbackMode
=
fallbackMode
;
if
(
fallbackMode
)
{
this
.
decompilationMode
=
DecompilationMode
.
FALLBACK
;
}
}
public
boolean
isShowInconsistentCode
()
{
...
...
@@ -422,6 +429,14 @@ public class JadxArgs {
this
.
outputFormat
=
outputFormat
;
}
public
DecompilationMode
getDecompilationMode
()
{
return
decompilationMode
;
}
public
void
setDecompilationMode
(
DecompilationMode
decompilationMode
)
{
this
.
decompilationMode
=
decompilationMode
;
}
public
ICodeCache
getCodeCache
()
{
return
codeCache
;
}
...
...
@@ -493,9 +508,7 @@ public class JadxArgs {
+
", outDirSrc="
+
outDirSrc
+
", outDirRes="
+
outDirRes
+
", threadsCount="
+
threadsCount
+
", cfgOutput="
+
cfgOutput
+
", rawCFGOutput="
+
rawCFGOutput
+
", fallbackMode="
+
fallbackMode
+
", decompilationMode="
+
decompilationMode
+
", showInconsistentCode="
+
showInconsistentCode
+
", useImports="
+
useImports
+
", skipResources="
+
skipResources
...
...
@@ -520,6 +533,8 @@ public class JadxArgs {
+
", codeWriter="
+
codeWriterProvider
.
apply
(
this
).
getClass
().
getSimpleName
()
+
", useDxInput="
+
useDxInput
+
", pluginOptions="
+
pluginOptions
+
", cfgOutput="
+
cfgOutput
+
", rawCFGOutput="
+
rawCFGOutput
+
'}'
;
}
}
jadx-core/src/main/java/jadx/core/Jadx.java
浏览文件 @
073d66ce
...
...
@@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory;
import
jadx.api.CommentsLevel
;
import
jadx.api.JadxArgs
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.visitors.AnonymousClassVisitor
;
import
jadx.core.dex.visitors.AttachCommentsVisitor
;
import
jadx.core.dex.visitors.AttachMethodDetails
;
...
...
@@ -32,6 +33,7 @@ import jadx.core.dex.visitors.InitCodeVariables;
import
jadx.core.dex.visitors.InlineMethods
;
import
jadx.core.dex.visitors.MarkMethodsForInline
;
import
jadx.core.dex.visitors.MethodInvokeVisitor
;
import
jadx.core.dex.visitors.MethodVisitor
;
import
jadx.core.dex.visitors.ModVisitor
;
import
jadx.core.dex.visitors.MoveInlineVisitor
;
import
jadx.core.dex.visitors.OverrideMethodVisitor
;
...
...
@@ -62,6 +64,7 @@ import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
import
jadx.core.dex.visitors.ssa.SSATransform
;
import
jadx.core.dex.visitors.typeinference.TypeInferenceVisitor
;
import
jadx.core.dex.visitors.usage.UsageInfoVisitor
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
public
class
Jadx
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
Jadx
.
class
);
...
...
@@ -69,21 +72,20 @@ public class Jadx {
private
Jadx
()
{
}
static
{
if
(
Consts
.
DEBUG
)
{
LOG
.
info
(
"debug enabled"
);
public
static
List
<
IDexTreeVisitor
>
getPassesList
(
JadxArgs
args
)
{
switch
(
args
.
getDecompilationMode
())
{
case
AUTO:
case
RESTRUCTURE:
return
getRegionsModePasses
(
args
);
case
SIMPLE:
return
getSimpleModePasses
(
args
);
case
FALLBACK:
return
getFallbackPassesList
();
default
:
throw
new
JadxRuntimeException
(
"Unknown decompilation mode: "
+
args
.
getDecompilationMode
());
}
}
public
static
List
<
IDexTreeVisitor
>
getFallbackPassesList
()
{
List
<
IDexTreeVisitor
>
passes
=
new
ArrayList
<>();
passes
.
add
(
new
AttachTryCatchVisitor
());
passes
.
add
(
new
AttachCommentsVisitor
());
passes
.
add
(
new
ProcessInstructionsVisitor
());
passes
.
add
(
new
FallbackModeVisitor
());
return
passes
;
}
public
static
List
<
IDexTreeVisitor
>
getPreDecompilePassesList
()
{
List
<
IDexTreeVisitor
>
passes
=
new
ArrayList
<>();
passes
.
add
(
new
SignatureProcessor
());
...
...
@@ -95,12 +97,8 @@ public class Jadx {
return
passes
;
}
public
static
List
<
IDexTreeVisitor
>
getPassesList
(
JadxArgs
args
)
{
if
(
args
.
isFallbackMode
())
{
return
getFallbackPassesList
();
}
public
static
List
<
IDexTreeVisitor
>
getRegionsModePasses
(
JadxArgs
args
)
{
List
<
IDexTreeVisitor
>
passes
=
new
ArrayList
<>();
// instructions IR
passes
.
add
(
new
CheckCode
());
if
(
args
.
isDebugInfo
())
{
...
...
@@ -178,6 +176,56 @@ public class Jadx {
return
passes
;
}
public
static
List
<
IDexTreeVisitor
>
getSimpleModePasses
(
JadxArgs
args
)
{
List
<
IDexTreeVisitor
>
passes
=
new
ArrayList
<>();
if
(
args
.
isDebugInfo
())
{
passes
.
add
(
new
DebugInfoAttachVisitor
());
}
passes
.
add
(
new
AttachTryCatchVisitor
());
if
(
args
.
getCommentsLevel
()
!=
CommentsLevel
.
NONE
)
{
passes
.
add
(
new
AttachCommentsVisitor
());
}
passes
.
add
(
new
ProcessInstructionsVisitor
());
passes
.
add
(
new
AttachMethodDetails
());
passes
.
add
(
new
ProcessInstructionsVisitor
());
passes
.
add
(
new
BlockSplitter
());
passes
.
add
(
new
MethodVisitor
(
mth
->
mth
.
add
(
AFlag
.
DISABLE_BLOCKS_LOCK
)));
passes
.
add
(
new
BlockProcessor
());
passes
.
add
(
new
SSATransform
());
passes
.
add
(
new
MoveInlineVisitor
());
passes
.
add
(
new
ConstructorVisitor
());
passes
.
add
(
new
InitCodeVariables
());
passes
.
add
(
new
ConstInlineVisitor
());
passes
.
add
(
new
TypeInferenceVisitor
());
if
(
args
.
isDebugInfo
())
{
passes
.
add
(
new
DebugInfoApplyVisitor
());
}
passes
.
add
(
new
CodeRenameVisitor
());
passes
.
add
(
new
DeboxingVisitor
());
passes
.
add
(
new
ModVisitor
());
passes
.
add
(
new
CodeShrinkVisitor
());
passes
.
add
(
new
ReSugarCode
());
passes
.
add
(
new
CodeShrinkVisitor
());
passes
.
add
(
new
SimplifyVisitor
());
if
(
args
.
isRawCFGOutput
())
{
passes
.
add
(
DotGraphVisitor
.
dumpRaw
());
}
if
(
args
.
isCfgOutput
())
{
passes
.
add
(
DotGraphVisitor
.
dump
());
}
return
passes
;
}
public
static
List
<
IDexTreeVisitor
>
getFallbackPassesList
()
{
List
<
IDexTreeVisitor
>
passes
=
new
ArrayList
<>();
passes
.
add
(
new
AttachTryCatchVisitor
());
passes
.
add
(
new
AttachCommentsVisitor
());
passes
.
add
(
new
ProcessInstructionsVisitor
());
passes
.
add
(
new
FallbackModeVisitor
());
return
passes
;
}
public
static
final
String
VERSION_DEV
=
"dev"
;
private
static
String
version
;
...
...
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
浏览文件 @
073d66ce
...
...
@@ -356,7 +356,7 @@ public class ClassGen {
badCode
=
false
;
}
MethodGen
mthGen
;
if
(
badCode
||
fallback
||
mth
.
contains
(
AType
.
JADX_ERROR
)
||
mth
.
getRegion
()
==
null
)
{
if
(
badCode
||
fallback
||
mth
.
contains
(
AType
.
JADX_ERROR
))
{
mthGen
=
MethodGen
.
getFallbackMethodGen
(
mth
);
}
else
{
mthGen
=
new
MethodGen
(
this
,
mth
);
...
...
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
浏览文件 @
073d66ce
...
...
@@ -50,6 +50,7 @@ import jadx.core.dex.instructions.args.RegisterArg;
import
jadx.core.dex.instructions.args.SSAVar
;
import
jadx.core.dex.instructions.mods.ConstructorInsn
;
import
jadx.core.dex.instructions.mods.TernaryInsn
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.FieldNode
;
import
jadx.core.dex.nodes.InsnNode
;
...
...
@@ -517,7 +518,7 @@ public class InsnGen {
code
.
add
(
' '
);
code
.
add
(
ifInsn
.
getOp
().
getSymbol
()).
add
(
' '
);
addArg
(
code
,
insn
.
getArg
(
1
));
code
.
add
(
") goto "
).
add
(
MethodGen
.
getLabelName
(
ifInsn
.
getTarget
()
));
code
.
add
(
") goto "
).
add
(
MethodGen
.
getLabelName
(
ifInsn
));
break
;
case
GOTO:
...
...
@@ -538,13 +539,24 @@ public class InsnGen {
code
.
add
(
") {"
);
code
.
incIndent
();
int
[]
keys
=
sw
.
getKeys
();
int
[]
targets
=
sw
.
getTargets
();
for
(
int
i
=
0
;
i
<
keys
.
length
;
i
++)
{
code
.
startLine
(
"case "
).
add
(
Integer
.
toString
(
keys
[
i
])).
add
(
": goto "
);
code
.
add
(
MethodGen
.
getLabelName
(
targets
[
i
])).
add
(
';'
);
int
size
=
keys
.
length
;
BlockNode
[]
targetBlocks
=
sw
.
getTargetBlocks
();
if
(
targetBlocks
!=
null
)
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
code
.
startLine
(
"case "
).
add
(
Integer
.
toString
(
keys
[
i
])).
add
(
": goto "
);
code
.
add
(
MethodGen
.
getLabelName
(
targetBlocks
[
i
])).
add
(
';'
);
}
code
.
startLine
(
"default: goto "
);
code
.
add
(
MethodGen
.
getLabelName
(
sw
.
getDefTargetBlock
())).
add
(
';'
);
}
else
{
int
[]
targets
=
sw
.
getTargets
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
code
.
startLine
(
"case "
).
add
(
Integer
.
toString
(
keys
[
i
])).
add
(
": goto "
);
code
.
add
(
MethodGen
.
getLabelName
(
targets
[
i
])).
add
(
';'
);
}
code
.
startLine
(
"default: goto "
);
code
.
add
(
MethodGen
.
getLabelName
(
sw
.
getDefaultCaseOffset
())).
add
(
';'
);
}
code
.
startLine
(
"default: goto "
);
code
.
add
(
MethodGen
.
getLabelName
(
sw
.
getDefaultCaseOffset
())).
add
(
';'
);
code
.
decIndent
();
code
.
startLine
(
'}'
);
break
;
...
...
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
浏览文件 @
073d66ce
...
...
@@ -6,11 +6,13 @@ import java.util.List;
import
java.util.Objects
;
import
java.util.stream.Stream
;
import
org.jetbrains.annotations.Nullable
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.api.CommentsLevel
;
import
jadx.api.ICodeWriter
;
import
jadx.api.JadxArgs
;
import
jadx.api.data.annotations.InsnCodeOffset
;
import
jadx.api.data.annotations.VarDeclareRef
;
import
jadx.api.plugins.input.data.AccessFlags
;
...
...
@@ -32,13 +34,14 @@ import jadx.core.dex.instructions.args.ArgType;
import
jadx.core.dex.instructions.args.CodeVar
;
import
jadx.core.dex.instructions.args.RegisterArg
;
import
jadx.core.dex.instructions.args.SSAVar
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.trycatch.CatchAttr
;
import
jadx.core.dex.trycatch.ExceptionHandler
;
import
jadx.core.dex.visitors.DepthTraversal
;
import
jadx.core.dex.visitors.IDexTreeVisitor
;
import
jadx.core.utils.CodeGenUtils
;
import
jadx.core.utils.InsnUtils
;
import
jadx.core.utils.Utils
;
import
jadx.core.utils.exceptions.CodegenException
;
import
jadx.core.utils.exceptions.JadxOverflowException
;
...
...
@@ -252,12 +255,28 @@ public class MethodGen {
}
public
void
addInstructions
(
ICodeWriter
code
)
throws
CodegenException
{
if
(
mth
.
root
().
getArgs
().
isFallbackMode
())
{
addFallbackMethodCode
(
code
,
FALLBACK_MODE
);
}
else
if
(
classGen
.
isFallbackMode
())
{
dumpInstructions
(
code
);
}
else
{
addRegionInsns
(
code
);
JadxArgs
args
=
mth
.
root
().
getArgs
();
switch
(
args
.
getDecompilationMode
())
{
case
AUTO:
if
(
classGen
.
isFallbackMode
())
{
// TODO: try simple mode first
dumpInstructions
(
code
);
}
else
{
addRegionInsns
(
code
);
}
break
;
case
RESTRUCTURE:
addRegionInsns
(
code
);
break
;
case
SIMPLE:
addSimpleMethodCode
(
code
);
break
;
case
FALLBACK:
addFallbackMethodCode
(
code
,
FALLBACK_MODE
);
break
;
}
}
...
...
@@ -279,6 +298,55 @@ public class MethodGen {
}
}
private
void
addSimpleMethodCode
(
ICodeWriter
code
)
{
if
(
mth
.
getBasicBlocks
()
==
null
)
{
code
.
startLine
(
"// Blocks not ready for simple mode, using fallback"
);
addFallbackMethodCode
(
code
,
FALLBACK_MODE
);
return
;
}
JadxArgs
args
=
mth
.
root
().
getArgs
();
ICodeWriter
tmpCode
=
args
.
getCodeWriterProvider
().
apply
(
args
);
try
{
tmpCode
.
setIndent
(
code
.
getIndent
());
generateSimpleCode
(
tmpCode
);
code
.
add
(
tmpCode
);
}
catch
(
Exception
e
)
{
mth
.
addError
(
"Simple mode code generation failed"
,
e
);
CodeGenUtils
.
addError
(
code
,
"Simple mode code generation failed"
,
e
);
dumpInstructions
(
code
);
}
}
private
void
generateSimpleCode
(
ICodeWriter
code
)
throws
CodegenException
{
SimpleModeHelper
helper
=
new
SimpleModeHelper
(
mth
);
List
<
BlockNode
>
blocks
=
helper
.
prepareBlocks
();
InsnGen
insnGen
=
new
InsnGen
(
this
,
true
);
for
(
BlockNode
block
:
blocks
)
{
if
(
block
.
contains
(
AFlag
.
DONT_GENERATE
))
{
continue
;
}
if
(
helper
.
isNeedStartLabel
(
block
))
{
code
.
decIndent
();
code
.
startLine
(
getLabelName
(
block
)).
add
(
':'
);
code
.
incIndent
();
}
for
(
InsnNode
insn
:
block
.
getInstructions
())
{
if
(!
insn
.
contains
(
AFlag
.
DONT_GENERATE
))
{
if
(
insn
.
getResult
()
!=
null
)
{
insn
.
add
(
AFlag
.
DECLARE_VAR
);
}
InsnCodeOffset
.
attach
(
code
,
insn
);
insnGen
.
makeInsn
(
insn
,
code
);
addCatchComment
(
code
,
insn
);
CodeGenUtils
.
addCodeComments
(
code
,
mth
,
insn
);
}
}
if
(
helper
.
isNeedEndGoto
(
block
))
{
code
.
startLine
(
"goto "
).
add
(
getLabelName
(
block
.
getSuccessors
().
get
(
0
)));
}
}
}
public
void
dumpInstructions
(
ICodeWriter
code
)
{
if
(
mth
.
checkCommentsLevel
(
CommentsLevel
.
ERROR
))
{
code
.
startLine
(
"/*"
);
...
...
@@ -353,60 +421,77 @@ public class MethodGen {
public
static
void
addFallbackInsns
(
ICodeWriter
code
,
MethodNode
mth
,
InsnNode
[]
insnArr
,
FallbackOption
option
)
{
int
startIndent
=
code
.
getIndent
();
InsnGen
insnGen
=
new
InsnGen
(
getFallbackMethodGen
(
mth
),
true
);
MethodGen
methodGen
=
getFallbackMethodGen
(
mth
);
InsnGen
insnGen
=
new
InsnGen
(
methodGen
,
true
);
InsnNode
prevInsn
=
null
;
for
(
InsnNode
insn
:
insnArr
)
{
if
(
insn
==
null
)
{
continue
;
}
if
(
insn
.
contains
(
AType
.
JADX_ERROR
))
{
for
(
JadxError
error
:
insn
.
getAll
(
AType
.
JADX_ERROR
))
{
code
.
startLine
(
"// "
).
add
(
error
.
getError
());
}
continue
;
methodGen
.
dumpInsn
(
code
,
insnGen
,
option
,
startIndent
,
prevInsn
,
insn
);
prevInsn
=
insn
;
}
}
private
boolean
dumpInsn
(
ICodeWriter
code
,
InsnGen
insnGen
,
FallbackOption
option
,
int
startIndent
,
@Nullable
InsnNode
prevInsn
,
InsnNode
insn
)
{
if
(
insn
.
contains
(
AType
.
JADX_ERROR
))
{
for
(
JadxError
error
:
insn
.
getAll
(
AType
.
JADX_ERROR
))
{
code
.
startLine
(
"// "
).
add
(
error
.
getError
());
}
if
(
option
!=
BLOCK_DUMP
&&
needLabel
(
insn
,
prevInsn
))
{
return
true
;
}
if
(
option
!=
BLOCK_DUMP
&&
needLabel
(
insn
,
prevInsn
))
{
code
.
decIndent
();
code
.
startLine
(
getLabelName
(
insn
.
getOffset
())
+
':'
);
code
.
incIndent
();
}
if
(
insn
.
getType
()
==
InsnType
.
NOP
)
{
return
true
;
}
try
{
boolean
escapeComment
=
isCommentEscapeNeeded
(
insn
,
option
);
if
(
escapeComment
)
{
code
.
decIndent
();
code
.
startLine
(
getLabelName
(
insn
.
getOffset
())
+
':'
);
code
.
incIndent
();
}
if
(
insn
.
getType
()
==
InsnType
.
NOP
)
{
continue
;
code
.
startLine
(
"*/"
);
code
.
startLine
(
"// "
);
}
else
{
code
.
startLineWithNum
(
insn
.
getSourceLine
());
}
try
{
boolean
escapeComment
=
isCommentEscapeNeeded
(
insn
,
option
);
if
(
escapeComment
)
{
code
.
decIndent
();
code
.
startLine
(
"*/"
);
code
.
startLine
(
"// "
);
}
else
{
code
.
startLineWithNum
(
insn
.
getSourceLine
());
}
InsnCodeOffset
.
attach
(
code
,
insn
);
RegisterArg
resArg
=
insn
.
getResult
();
if
(
resArg
!=
null
)
{
ArgType
varType
=
resArg
.
getInitType
();
if
(
varType
.
isTypeKnown
())
{
code
.
add
(
varType
.
toString
()).
add
(
' '
);
}
}
insnGen
.
makeInsn
(
insn
,
code
,
InsnGen
.
Flags
.
INLINE
);
if
(
escapeComment
)
{
code
.
startLine
(
"/*"
);
code
.
incIndent
();
}
CatchAttr
catchAttr
=
insn
.
get
(
AType
.
EXC_CATCH
);
if
(
catchAttr
!=
null
)
{
code
.
add
(
" // "
+
catchAttr
);
InsnCodeOffset
.
attach
(
code
,
insn
);
RegisterArg
resArg
=
insn
.
getResult
();
if
(
resArg
!=
null
)
{
ArgType
varType
=
resArg
.
getInitType
();
if
(
varType
.
isTypeKnown
())
{
code
.
add
(
varType
.
toString
()).
add
(
' '
);
}
CodeGenUtils
.
addCodeComments
(
code
,
mth
,
insn
);
}
catch
(
Exception
e
)
{
LOG
.
debug
(
"Error generate fallback instruction: "
,
e
.
getCause
());
code
.
setIndent
(
startIndent
);
code
.
startLine
(
"// error: "
+
insn
);
}
prevInsn
=
insn
;
insnGen
.
makeInsn
(
insn
,
code
,
InsnGen
.
Flags
.
INLINE
);
if
(
escapeComment
)
{
code
.
startLine
(
"/*"
);
code
.
incIndent
();
}
addCatchComment
(
code
,
insn
);
CodeGenUtils
.
addCodeComments
(
code
,
mth
,
insn
);
}
catch
(
Exception
e
)
{
LOG
.
debug
(
"Error generate fallback instruction: "
,
e
.
getCause
());
code
.
setIndent
(
startIndent
);
code
.
startLine
(
"// error: "
+
insn
);
}
return
false
;
}
private
void
addCatchComment
(
ICodeWriter
code
,
InsnNode
insn
)
{
CatchAttr
catchAttr
=
insn
.
get
(
AType
.
EXC_CATCH
);
if
(
catchAttr
==
null
)
{
return
;
}
code
.
add
(
" // Catch:"
);
for
(
ExceptionHandler
handler
:
catchAttr
.
getHandlers
())
{
code
.
add
(
' '
);
classGen
.
useClass
(
code
,
handler
.
getArgType
());
code
.
add
(
" -> "
);
code
.
add
(
getLabelName
(
handler
.
getHandlerOffset
()));
}
}
...
...
@@ -449,7 +534,22 @@ public class MethodGen {
return
new
MethodGen
(
clsGen
,
mth
);
}
public
static
String
getLabelName
(
BlockNode
block
)
{
return
String
.
format
(
"L%d"
,
block
.
getId
());
}
public
static
String
getLabelName
(
IfNode
insn
)
{
BlockNode
thenBlock
=
insn
.
getThenBlock
();
if
(
thenBlock
!=
null
)
{
return
getLabelName
(
thenBlock
);
}
return
getLabelName
(
insn
.
getTarget
());
}
public
static
String
getLabelName
(
int
offset
)
{
return
"L_"
+
InsnUtils
.
formatOffset
(
offset
);
if
(
offset
<
0
)
{
return
String
.
format
(
"LB_%x"
,
-
offset
);
}
return
String
.
format
(
"L%x"
,
offset
);
}
}
jadx-core/src/main/java/jadx/core/codegen/SimpleModeHelper.java
0 → 100644
浏览文件 @
073d66ce
package
jadx.core.codegen
;
import
java.util.ArrayList
;
import
java.util.BitSet
;
import
java.util.List
;
import
org.jetbrains.annotations.Nullable
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.instructions.IfNode
;
import
jadx.core.dex.instructions.TargetInsnNode
;
import
jadx.core.dex.nodes.BlockNode
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.trycatch.ExceptionHandler
;
import
jadx.core.dex.visitors.blocks.BlockProcessor
;
import
jadx.core.dex.visitors.blocks.BlockSplitter
;
import
jadx.core.utils.BlockUtils
;
public
class
SimpleModeHelper
{
private
final
MethodNode
mth
;
private
final
BitSet
startLabel
;
private
final
BitSet
endGoto
;
public
SimpleModeHelper
(
MethodNode
mth
)
{
this
.
mth
=
mth
;
this
.
startLabel
=
BlockUtils
.
newBlocksBitSet
(
mth
);
this
.
endGoto
=
BlockUtils
.
newBlocksBitSet
(
mth
);
}
public
List
<
BlockNode
>
prepareBlocks
()
{
removeEmptyBlocks
();
List
<
BlockNode
>
blocksList
=
getSortedBlocks
();
blocksList
.
removeIf
(
b
->
b
.
equals
(
mth
.
getEnterBlock
())
||
b
.
equals
(
mth
.
getExitBlock
()));
unbindExceptionHandlers
();
@Nullable
BlockNode
prev
=
null
;
int
blocksCount
=
blocksList
.
size
();
for
(
int
i
=
0
;
i
<
blocksCount
;
i
++)
{
BlockNode
block
=
blocksList
.
get
(
i
);
List
<
BlockNode
>
preds
=
block
.
getPredecessors
();
int
predsCount
=
preds
.
size
();
if
(
predsCount
>
1
)
{
startLabel
.
set
(
block
.
getId
());
}
else
if
(
predsCount
==
1
&&
prev
!=
null
)
{
if
(!
prev
.
equals
(
preds
.
get
(
0
)))
{
startLabel
.
set
(
block
.
getId
());
if
(
prev
.
getSuccessors
().
size
()
==
1
&&
!
prev
.
contains
(
AFlag
.
RETURN
))
{
endGoto
.
set
(
prev
.
getId
());
}
}
}
InsnNode
lastInsn
=
BlockUtils
.
getLastInsn
(
block
);
if
(
lastInsn
instanceof
TargetInsnNode
)
{
processTargetInsn
(
block
,
lastInsn
);
}
if
(
block
.
contains
(
AType
.
EXC_HANDLER
))
{
startLabel
.
set
(
block
.
getId
());
}
if
(
i
+
1
>=
blocksCount
&&
!
mth
.
isPreExitBlocks
(
block
))
{
endGoto
.
set
(
block
.
getId
());
}
prev
=
block
;
}
return
blocksList
;
}
private
void
removeEmptyBlocks
()
{
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
if
(
block
.
getInstructions
().
isEmpty
()
&&
block
.
getPredecessors
().
size
()
>
0
&&
block
.
getSuccessors
().
size
()
==
1
)
{
BlockNode
successor
=
block
.
getSuccessors
().
get
(
0
);
List
<
BlockNode
>
predecessors
=
block
.
getPredecessors
();
BlockSplitter
.
removeConnection
(
block
,
successor
);
if
(
predecessors
.
size
()
==
1
)
{
BlockSplitter
.
replaceConnection
(
predecessors
.
get
(
0
),
block
,
successor
);
}
else
{
for
(
BlockNode
pred
:
new
ArrayList
<>(
predecessors
))
{
BlockSplitter
.
replaceConnection
(
pred
,
block
,
successor
);
}
}
block
.
add
(
AFlag
.
REMOVE
);
}
}
BlockProcessor
.
removeMarkedBlocks
(
mth
);
}
private
void
unbindExceptionHandlers
()
{
if
(
mth
.
isNoExceptionHandlers
())
{
return
;
}
for
(
ExceptionHandler
handler
:
mth
.
getExceptionHandlers
())
{
BlockNode
handlerBlock
=
handler
.
getHandlerBlock
();
if
(
handlerBlock
!=
null
)
{
BlockSplitter
.
removePredecessors
(
handlerBlock
);
}
}
}
private
void
processTargetInsn
(
BlockNode
block
,
InsnNode
lastInsn
)
{
if
(
lastInsn
instanceof
IfNode
)
{
BlockNode
thenBlock
=
((
IfNode
)
lastInsn
).
getThenBlock
();
startLabel
.
set
(
thenBlock
.
getId
());
}
else
{
for
(
BlockNode
successor
:
block
.
getSuccessors
())
{
startLabel
.
set
(
successor
.
getId
());
}
}
}
public
boolean
isNeedStartLabel
(
BlockNode
block
)
{
return
startLabel
.
get
(
block
.
getId
());
}
public
boolean
isNeedEndGoto
(
BlockNode
block
)
{
return
endGoto
.
get
(
block
.
getId
());
}
// DFS sort blocks to reduce goto count
private
List
<
BlockNode
>
getSortedBlocks
()
{
List
<
BlockNode
>
list
=
new
ArrayList
<>(
mth
.
getBasicBlocks
().
size
());
BlockUtils
.
dfsVisit
(
mth
,
list:
:
add
);
return
list
;
}
}
jadx-core/src/main/java/jadx/core/dex/attributes/AFlag.java
浏览文件 @
073d66ce
...
...
@@ -81,6 +81,8 @@ public enum AFlag {
METHOD_CANDIDATE_FOR_INLINE
,
DISABLE_BLOCKS_LOCK
,
// Class processing flags
RESTART_CODEGEN
,
// codegen must be executed again
RELOAD_AT_CODEGEN_STAGE
,
// class can't be analyzed at 'process' stage => unload before 'codegen' stage
...
...
jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxError.java
浏览文件 @
073d66ce
...
...
@@ -50,11 +50,7 @@ public class JadxError implements Comparable<JadxError> {
@Override
public
String
toString
()
{
StringBuilder
str
=
new
StringBuilder
();
str
.
append
(
"JadxError: "
);
if
(
error
!=
null
)
{
str
.
append
(
error
);
str
.
append
(
' '
);
}
str
.
append
(
"JadxError: "
).
append
(
error
).
append
(
' '
);
if
(
cause
!=
null
)
{
str
.
append
(
cause
.
getClass
());
str
.
append
(
':'
);
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
浏览文件 @
073d66ce
...
...
@@ -336,6 +336,14 @@ public class MethodNode extends NotificationAttrNode implements IMethodDetails,
return
exitBlock
.
getPredecessors
();
}
public
boolean
isPreExitBlocks
(
BlockNode
block
)
{
List
<
BlockNode
>
successors
=
block
.
getSuccessors
();
if
(
successors
.
size
()
==
1
)
{
return
successors
.
get
(
0
).
equals
(
exitBlock
);
}
return
exitBlock
.
getPredecessors
().
contains
(
block
);
}
public
void
registerLoop
(
LoopInfo
loop
)
{
if
(
loops
.
isEmpty
())
{
loops
=
new
ArrayList
<>(
5
);
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/MethodVisitor.java
0 → 100644
浏览文件 @
073d66ce
package
jadx.core.dex.visitors
;
import
java.util.function.Consumer
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.utils.exceptions.JadxException
;
public
class
MethodVisitor
implements
IDexTreeVisitor
{
private
final
Consumer
<
MethodNode
>
visitor
;
public
MethodVisitor
(
Consumer
<
MethodNode
>
visitor
)
{
this
.
visitor
=
visitor
;
}
@Override
public
void
visit
(
MethodNode
mth
)
throws
JadxException
{
visitor
.
accept
(
mth
);
}
@Override
public
void
init
(
RootNode
root
)
throws
JadxException
{
}
@Override
public
boolean
visit
(
ClassNode
cls
)
throws
JadxException
{
return
true
;
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockExceptionHandler.java
浏览文件 @
073d66ce
...
...
@@ -149,12 +149,7 @@ public class BlockExceptionHandler {
continue
;
}
firstInsn
.
remove
(
AType
.
EXC_HANDLER
);
TmpEdgeAttr
tmpEdgeAttr
=
block
.
get
(
AType
.
TMP_EDGE
);
if
(
tmpEdgeAttr
!=
null
)
{
// remove temp connection
BlockSplitter
.
removeConnection
(
tmpEdgeAttr
.
getBlock
(),
block
);
block
.
remove
(
AType
.
TMP_EDGE
);
}
removeTmpConnection
(
block
);
ExceptionHandler
excHandler
=
excHandlerAttr
.
getHandler
();
if
(
block
.
getPredecessors
().
isEmpty
())
{
...
...
@@ -176,6 +171,19 @@ public class BlockExceptionHandler {
}
}
protected
static
void
removeTmpConnections
(
MethodNode
mth
)
{
mth
.
getBasicBlocks
().
forEach
(
BlockExceptionHandler:
:
removeTmpConnection
);
}
private
static
void
removeTmpConnection
(
BlockNode
block
)
{
TmpEdgeAttr
tmpEdgeAttr
=
block
.
get
(
AType
.
TMP_EDGE
);
if
(
tmpEdgeAttr
!=
null
)
{
// remove temp connection
BlockSplitter
.
removeConnection
(
tmpEdgeAttr
.
getBlock
(),
block
);
block
.
remove
(
AType
.
TMP_EDGE
);
}
}
private
static
List
<
TryCatchBlockAttr
>
prepareTryBlocks
(
MethodNode
mth
)
{
Map
<
ExceptionHandler
,
List
<
BlockNode
>>
blocksByHandler
=
new
HashMap
<>();
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockProcessor.java
浏览文件 @
073d66ce
...
...
@@ -77,7 +77,9 @@ public class BlockProcessor extends AbstractVisitor {
processNestedLoops
(
mth
);
updateCleanSuccessors
(
mth
);
mth
.
finishBasicBlocks
();
if
(!
mth
.
contains
(
AFlag
.
DISABLE_BLOCKS_LOCK
))
{
mth
.
finishBasicBlocks
();
}
}
static
void
updateCleanSuccessors
(
MethodNode
mth
)
{
...
...
@@ -686,7 +688,7 @@ public class BlockProcessor extends AbstractVisitor {
return
false
;
}
static
void
removeMarkedBlocks
(
MethodNode
mth
)
{
public
static
void
removeMarkedBlocks
(
MethodNode
mth
)
{
mth
.
getBasicBlocks
().
removeIf
(
block
->
{
if
(
block
.
contains
(
AFlag
.
REMOVE
))
{
if
(!
block
.
getPredecessors
().
isEmpty
()
||
!
block
.
getSuccessors
().
isEmpty
())
{
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/blocks/BlockSplitter.java
浏览文件 @
073d66ce
...
...
@@ -142,7 +142,7 @@ public class BlockSplitter extends AbstractVisitor {
return
block
;
}
static
void
connect
(
BlockNode
from
,
BlockNode
to
)
{
public
static
void
connect
(
BlockNode
from
,
BlockNode
to
)
{
if
(!
from
.
getSuccessors
().
contains
(
to
))
{
from
.
getSuccessors
().
add
(
to
);
}
...
...
@@ -151,19 +151,19 @@ public class BlockSplitter extends AbstractVisitor {
}
}
static
void
removeConnection
(
BlockNode
from
,
BlockNode
to
)
{
public
static
void
removeConnection
(
BlockNode
from
,
BlockNode
to
)
{
from
.
getSuccessors
().
remove
(
to
);
to
.
getPredecessors
().
remove
(
from
);
}
static
void
removePredecessors
(
BlockNode
block
)
{
public
static
void
removePredecessors
(
BlockNode
block
)
{
for
(
BlockNode
pred
:
block
.
getPredecessors
())
{
pred
.
getSuccessors
().
remove
(
block
);
}
block
.
getPredecessors
().
clear
();
}
static
void
replaceConnection
(
BlockNode
source
,
BlockNode
oldDest
,
BlockNode
newDest
)
{
public
static
void
replaceConnection
(
BlockNode
source
,
BlockNode
oldDest
,
BlockNode
newDest
)
{
removeConnection
(
source
,
oldDest
);
connect
(
source
,
newDest
);
replaceTarget
(
source
,
oldDest
,
newDest
);
...
...
jadx-core/src/main/java/jadx/core/utils/BlockUtils.java
浏览文件 @
073d66ce
...
...
@@ -453,6 +453,31 @@ public class BlockUtils {
}
}
public
static
void
dfsVisit
(
MethodNode
mth
,
Consumer
<
BlockNode
>
visitor
)
{
BitSet
visited
=
newBlocksBitSet
(
mth
);
Deque
<
BlockNode
>
queue
=
new
ArrayDeque
<>();
BlockNode
enterBlock
=
mth
.
getEnterBlock
();
queue
.
addLast
(
enterBlock
);
visited
.
set
(
mth
.
getEnterBlock
().
getId
());
while
(
true
)
{
BlockNode
current
=
queue
.
pollLast
();
if
(
current
==
null
)
{
return
;
}
visitor
.
accept
(
current
);
List
<
BlockNode
>
successors
=
current
.
getSuccessors
();
int
count
=
successors
.
size
();
for
(
int
i
=
count
-
1
;
i
>=
0
;
i
--)
{
// to preserve order in queue
BlockNode
next
=
successors
.
get
(
i
);
int
nextId
=
next
.
getId
();
if
(!
visited
.
get
(
nextId
))
{
queue
.
addLast
(
next
);
visited
.
set
(
nextId
);
}
}
}
}
public
static
List
<
BlockNode
>
collectPredecessors
(
MethodNode
mth
,
BlockNode
start
,
Collection
<
BlockNode
>
stopBlocks
)
{
BitSet
bs
=
newBlocksBitSet
(
mth
);
if
(!
stopBlocks
.
isEmpty
())
{
...
...
jadx-core/src/main/java/jadx/core/utils/CodeGenUtils.java
浏览文件 @
073d66ce
...
...
@@ -35,18 +35,21 @@ public class CodeGenUtils {
List
<
JadxError
>
errors
=
node
.
getAll
(
AType
.
JADX_ERROR
);
if
(!
errors
.
isEmpty
())
{
errors
.
stream
().
distinct
().
sorted
().
forEach
(
err
->
{
code
.
startLine
(
"/* JADX ERROR: "
).
add
(
err
.
getError
());
Throwable
cause
=
err
.
getCause
();
if
(
cause
!=
null
)
{
code
.
incIndent
();
Utils
.
appendStackTrace
(
code
,
cause
);
code
.
decIndent
();
}
code
.
add
(
"*/"
);
addError
(
code
,
err
.
getError
(),
err
.
getCause
());
});
}
}
public
static
void
addError
(
ICodeWriter
code
,
String
errMsg
,
Throwable
cause
)
{
code
.
startLine
(
"/* JADX ERROR: "
).
add
(
errMsg
);
if
(
cause
!=
null
)
{
code
.
incIndent
();
Utils
.
appendStackTrace
(
code
,
cause
);
code
.
decIndent
();
}
code
.
add
(
"*/"
);
}
public
static
void
addComments
(
ICodeWriter
code
,
NotificationAttrNode
node
)
{
JadxCommentsAttr
commentsAttr
=
node
.
get
(
AType
.
JADX_COMMENTS
);
if
(
commentsAttr
!=
null
)
{
...
...
jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
浏览文件 @
073d66ce
...
...
@@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory;
import
com.beust.jcommander.Parameter
;
import
jadx.api.CommentsLevel
;
import
jadx.api.DecompilationMode
;
import
jadx.api.JadxArgs
;
import
jadx.api.args.DeobfuscationMapFileMode
;
import
jadx.cli.JadxCLIArgs
;
...
...
@@ -44,7 +45,7 @@ public class JadxSettings extends JadxCLIArgs {
private
static
final
Path
USER_HOME
=
Paths
.
get
(
System
.
getProperty
(
"user.home"
));
private
static
final
int
RECENT_PROJECTS_COUNT
=
15
;
private
static
final
int
CURRENT_SETTINGS_VERSION
=
1
6
;
private
static
final
int
CURRENT_SETTINGS_VERSION
=
1
7
;
private
static
final
Font
DEFAULT_FONT
=
new
RSyntaxTextArea
().
getFont
();
...
...
@@ -291,6 +292,10 @@ public class JadxSettings extends JadxCLIArgs {
this
.
skipSources
=
skipSources
;
}
public
void
setDecompilationMode
(
DecompilationMode
decompilationMode
)
{
this
.
decompilationMode
=
decompilationMode
;
}
public
void
setShowInconsistentCode
(
boolean
showInconsistentCode
)
{
this
.
showInconsistentCode
=
showInconsistentCode
;
}
...
...
@@ -672,6 +677,14 @@ public class JadxSettings extends JadxCLIArgs {
}
fromVersion
++;
}
if
(
fromVersion
==
16
)
{
if
(
fallbackMode
)
{
decompilationMode
=
DecompilationMode
.
FALLBACK
;
}
else
{
decompilationMode
=
DecompilationMode
.
AUTO
;
}
fromVersion
++;
}
if
(
fromVersion
!=
CURRENT_SETTINGS_VERSION
)
{
throw
new
JadxRuntimeException
(
"Incorrect settings upgrade"
);
}
...
...
jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
浏览文件 @
073d66ce
...
...
@@ -59,6 +59,7 @@ import com.google.gson.JsonObject;
import
say.swing.JFontChooser
;
import
jadx.api.CommentsLevel
;
import
jadx.api.DecompilationMode
;
import
jadx.api.JadxArgs
;
import
jadx.api.JadxArgs.UseKotlinMethodsForVarNames
;
import
jadx.api.args.DeobfuscationMapFileMode
;
...
...
@@ -419,13 +420,6 @@ public class JadxSettingsWindow extends JDialog {
}
private
SettingsGroup
makeDecompilationGroup
()
{
JCheckBox
fallback
=
new
JCheckBox
();
fallback
.
setSelected
(
settings
.
isFallbackMode
());
fallback
.
addItemListener
(
e
->
{
settings
.
setFallbackMode
(
e
.
getStateChange
()
==
ItemEvent
.
SELECTED
);
needReload
();
});
JCheckBox
useDx
=
new
JCheckBox
();
useDx
.
setSelected
(
settings
.
isUseDx
());
useDx
.
addItemListener
(
e
->
{
...
...
@@ -433,6 +427,13 @@ public class JadxSettingsWindow extends JDialog {
needReload
();
});
JComboBox
<
DecompilationMode
>
decompilationModeComboBox
=
new
JComboBox
<>(
DecompilationMode
.
values
());
decompilationModeComboBox
.
setSelectedItem
(
settings
.
getDecompilationMode
());
decompilationModeComboBox
.
addActionListener
(
e
->
{
settings
.
setDecompilationMode
((
DecompilationMode
)
decompilationModeComboBox
.
getSelectedItem
());
needReload
();
});
JCheckBox
showInconsistentCode
=
new
JCheckBox
();
showInconsistentCode
.
setSelected
(
settings
.
isShowInconsistentCode
());
showInconsistentCode
.
addItemListener
(
e
->
{
...
...
@@ -543,6 +544,7 @@ public class JadxSettingsWindow extends JDialog {
other
.
addRow
(
NLS
.
str
(
"preferences.excludedPackages"
),
NLS
.
str
(
"preferences.excludedPackages.tooltip"
),
editExcludedPackages
);
other
.
addRow
(
NLS
.
str
(
"preferences.start_jobs"
),
autoStartJobs
);
other
.
addRow
(
NLS
.
str
(
"preferences.decompilationMode"
),
decompilationModeComboBox
);
other
.
addRow
(
NLS
.
str
(
"preferences.showInconsistentCode"
),
showInconsistentCode
);
other
.
addRow
(
NLS
.
str
(
"preferences.escapeUnicode"
),
escapeUnicode
);
other
.
addRow
(
NLS
.
str
(
"preferences.replaceConsts"
),
replaceConsts
);
...
...
@@ -551,7 +553,6 @@ public class JadxSettingsWindow extends JDialog {
other
.
addRow
(
NLS
.
str
(
"preferences.inlineAnonymous"
),
inlineAnonymous
);
other
.
addRow
(
NLS
.
str
(
"preferences.inlineMethods"
),
inlineMethods
);
other
.
addRow
(
NLS
.
str
(
"preferences.fsCaseSensitive"
),
fsCaseSensitive
);
other
.
addRow
(
NLS
.
str
(
"preferences.fallback"
),
fallback
);
other
.
addRow
(
NLS
.
str
(
"preferences.useDx"
),
useDx
);
other
.
addRow
(
NLS
.
str
(
"preferences.skipResourcesDecode"
),
resourceDecode
);
other
.
addRow
(
NLS
.
str
(
"preferences.useKotlinMethodsForVarNames"
),
kotlinRenameVars
);
...
...
jadx-gui/src/main/resources/i18n/Messages_de_DE.properties
浏览文件 @
073d66ce
...
...
@@ -127,6 +127,7 @@ preferences.lineNumbersMode=Editor Zeilennummern-Modus
preferences.check_for_updates
=
Nach Updates beim Start suchen
preferences.fallback
=
Zwischencode ausgeben (einfacher Speicherauszug)
#preferences.useDx=Use dx/d8 to convert java bytecode
#preferences.decompilationMode=Decompilation mode
preferences.showInconsistentCode
=
Inkonsistenten Code anzeigen
preferences.escapeUnicode
=
Unicodezeichen escapen
preferences.replaceConsts
=
Konstanten ersetzen
...
...
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
浏览文件 @
073d66ce
...
...
@@ -127,6 +127,7 @@ preferences.lineNumbersMode=Editor line numbers mode
preferences.check_for_updates
=
Check for updates on startup
preferences.fallback
=
Fallback mode (simple dump)
preferences.useDx
=
Use dx/d8 to convert java bytecode
preferences.decompilationMode
=
Decompilation mode
preferences.showInconsistentCode
=
Show inconsistent code
preferences.escapeUnicode
=
Escape unicode
preferences.replaceConsts
=
Replace constants
...
...
jadx-gui/src/main/resources/i18n/Messages_es_ES.properties
浏览文件 @
073d66ce
...
...
@@ -127,6 +127,7 @@ preferences.language=Idioma
preferences.check_for_updates
=
Buscar actualizaciones al iniciar
preferences.fallback
=
Modo fallback (simple dump)
#preferences.useDx=Use dx/d8 to convert java bytecode
#preferences.decompilationMode=Decompilation mode
preferences.showInconsistentCode
=
Mostrar código inconsistente
preferences.escapeUnicode
=
Escape unicode
preferences.replaceConsts
=
Reemplazar constantes
...
...
jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties
浏览文件 @
073d66ce
...
...
@@ -127,6 +127,7 @@ preferences.lineNumbersMode=편집기 줄 번호 모드
preferences.check_for_updates
=
시작시 업데이트 확인
preferences.fallback
=
대체 모드 (단순 덤프)
#preferences.useDx=Use dx/d8 to convert java bytecode
#preferences.decompilationMode=Decompilation mode
preferences.showInconsistentCode
=
디컴파일 안된 코드 표시
preferences.escapeUnicode
=
유니코드 이스케이프
preferences.replaceConsts
=
상수 바꾸기
...
...
jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties
浏览文件 @
073d66ce
...
...
@@ -127,6 +127,7 @@ preferences.lineNumbersMode=编辑器行号模式
preferences.check_for_updates
=
启动时检查更新
preferences.fallback
=
输出中间代码
#preferences.useDx=Use dx/d8 to convert java bytecode
#preferences.decompilationMode=Decompilation mode
preferences.showInconsistentCode
=
显示不一致的代码
preferences.escapeUnicode
=
将 Unicode 字符转义
preferences.replaceConsts
=
替换常量
...
...
jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties
浏览文件 @
073d66ce
...
...
@@ -127,6 +127,7 @@ preferences.lineNumbersMode=編輯器行號模式
preferences.check_for_updates
=
啟動時檢查更新
preferences.fallback
=
後援模式 (簡易傾印)
preferences.useDx
=
使用 dx/d8 來轉換 Java 位元組碼
#preferences.decompilationMode=Decompilation mode
preferences.showInconsistentCode
=
顯示不一致的程式碼
preferences.escapeUnicode
=
Unicode 逸出
preferences.replaceConsts
=
替換常數
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录