Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
qq_39073359
jadx
提交
4c4af792
J
jadx
项目概览
qq_39073359
/
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,发现更多精彩内容 >>
提交
4c4af792
编写于
3月 19, 2014
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
core: fix dot graph dump
上级
a0d8d9fc
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
147 addition
and
168 deletion
+147
-168
jadx-core/src/main/java/jadx/api/Decompiler.java
jadx-core/src/main/java/jadx/api/Decompiler.java
+5
-15
jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java
...src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java
+142
-153
未找到文件。
jadx-core/src/main/java/jadx/api/Decompiler.java
浏览文件 @
4c4af792
...
...
@@ -8,7 +8,6 @@ import jadx.core.dex.nodes.RootNode;
import
jadx.core.dex.visitors.IDexTreeVisitor
;
import
jadx.core.dex.visitors.SaveCode
;
import
jadx.core.utils.ErrorsCounter
;
import
jadx.core.utils.exceptions.CodegenException
;
import
jadx.core.utils.exceptions.DecodeException
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
jadx.core.utils.files.InputFile
;
...
...
@@ -116,21 +115,12 @@ public final class Decompiler {
LOG
.
info
(
"processing ..."
);
ThreadPoolExecutor
executor
=
(
ThreadPoolExecutor
)
Executors
.
newFixedThreadPool
(
threadsCount
);
for
(
final
ClassNode
cls
:
root
.
getClasses
(
false
))
{
if
(
cls
.
getCode
()
==
null
)
{
Runnable
job
=
new
Runnable
()
{
@Override
public
void
run
()
{
ProcessClass
.
process
(
cls
,
passList
);
}
};
executor
.
execute
(
job
);
}
else
{
try
{
savePass
.
visit
(
cls
);
}
catch
(
CodegenException
e
)
{
LOG
.
error
(
"Can't save class {}"
,
cls
,
e
);
executor
.
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
ProcessClass
.
process
(
cls
,
passList
);
}
}
}
);
}
executor
.
shutdown
();
return
executor
;
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java
浏览文件 @
4c4af792
...
...
@@ -23,15 +23,11 @@ import java.util.Set;
public
class
DotGraphVisitor
extends
AbstractVisitor
{
private
static
final
String
NL
=
"\\l"
;
private
static
final
boolean
PRINT_REGISTERS_STATES
=
false
;
private
final
File
dir
;
private
final
boolean
useRegions
;
private
final
boolean
rawInsn
;
private
CodeWriter
dot
;
private
CodeWriter
conn
;
public
DotGraphVisitor
(
File
outDir
,
boolean
useRegions
,
boolean
rawInsn
)
{
this
.
dir
=
outDir
;
this
.
useRegions
=
useRegions
;
...
...
@@ -47,186 +43,179 @@ public class DotGraphVisitor extends AbstractVisitor {
if
(
mth
.
isNoCode
())
{
return
;
}
dot
=
new
CodeWriter
(
);
conn
=
new
CodeWriter
();
new
DumpDotGraph
().
process
(
mth
);
}
dot
.
startLine
(
"digraph \"CFG for"
);
dot
.
add
(
escape
(
mth
.
getParentClass
().
getFullName
()
+
"."
+
mth
.
getMethodInfo
().
getShortId
())
);
dot
.
add
(
"\" {"
);
private
class
DumpDotGraph
{
private
CodeWriter
dot
=
new
CodeWriter
(
);
private
CodeWriter
conn
=
new
CodeWriter
(
);
if
(
useRegions
)
{
if
(
mth
.
getRegion
()
==
null
)
{
return
;
}
processMethodRegion
(
mth
);
}
else
{
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
processBlock
(
mth
,
block
);
public
void
process
(
MethodNode
mth
)
{
dot
.
startLine
(
"digraph \"CFG for"
);
dot
.
add
(
escape
(
mth
.
getParentClass
().
getFullName
()
+
"."
+
mth
.
getMethodInfo
().
getShortId
()));
dot
.
add
(
"\" {"
);
if
(
useRegions
)
{
if
(
mth
.
getRegion
()
==
null
)
{
return
;
}
processMethodRegion
(
mth
);
}
else
{
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
processBlock
(
mth
,
block
,
false
);
}
}
}
dot
.
startLine
(
"MethodNode[shape=record,label=\"{"
);
dot
.
add
(
escape
(
mth
.
getAccessFlags
().
makeString
()));
dot
.
add
(
escape
(
mth
.
getReturnType
()
+
" "
+
mth
.
getParentClass
().
getFullName
()
+
"."
+
mth
.
getName
()
+
"("
+
Utils
.
listToString
(
mth
.
getArguments
(
true
))
+
") "
));
dot
.
startLine
(
"MethodNode[shape=record,label=\"{"
);
dot
.
add
(
escape
(
mth
.
getAccessFlags
().
makeString
()));
dot
.
add
(
escape
(
mth
.
getReturnType
()
+
" "
+
mth
.
getParentClass
().
getFullName
()
+
"."
+
mth
.
getName
()
+
"("
+
Utils
.
listToString
(
mth
.
getArguments
(
true
))
+
") "
));
String
attrs
=
attributesString
(
mth
);
if
(
attrs
.
length
()
!=
0
)
{
dot
.
add
(
" | "
).
add
(
attrs
);
}
dot
.
add
(
"}\"];"
);
String
attrs
=
attributesString
(
mth
);
if
(
attrs
.
length
()
!=
0
)
{
dot
.
add
(
" | "
).
add
(
attrs
);
}
dot
.
add
(
"}\"];"
);
dot
.
startLine
(
"MethodNode -> "
).
add
(
makeName
(
mth
.
getEnterBlock
())).
add
(
';'
);
dot
.
startLine
(
"MethodNode -> "
).
add
(
makeName
(
mth
.
getEnterBlock
())).
add
(
';'
);
dot
.
add
(
conn
.
toString
());
dot
.
add
(
conn
.
toString
());
dot
.
startLine
(
'}'
);
dot
.
startLine
();
dot
.
startLine
(
'}'
);
dot
.
startLine
();
String
fileName
=
Utils
.
escape
(
mth
.
getMethodInfo
().
getShortId
())
+
(
useRegions
?
".regions"
:
""
)
+
(
rawInsn
?
".raw"
:
""
)
+
".dot"
;
dot
.
save
(
dir
,
mth
.
getParentClass
().
getClassInfo
().
getFullPath
()
+
"_graphs"
,
fileName
);
}
String
fileName
=
Utils
.
escape
(
mth
.
getMethodInfo
().
getShortId
())
+
(
useRegions
?
".regions"
:
""
)
+
(
rawInsn
?
".raw"
:
""
)
+
".dot"
;
dot
.
save
(
dir
,
mth
.
getParentClass
().
getClassInfo
().
getFullPath
()
+
"_graphs"
,
fileName
);
}
private
void
processMethodRegion
(
MethodNode
mth
)
{
processRegion
(
mth
,
mth
.
getRegion
());
for
(
ExceptionHandler
h
:
mth
.
getExceptionHandlers
())
{
if
(
h
.
getHandlerRegion
()
!=
null
)
{
processRegion
(
mth
,
h
.
getHandlerRegion
());
private
void
processMethodRegion
(
MethodNode
mth
)
{
processRegion
(
mth
,
mth
.
getRegion
());
for
(
ExceptionHandler
h
:
mth
.
getExceptionHandlers
())
{
if
(
h
.
getHandlerRegion
()
!=
null
)
{
processRegion
(
mth
,
h
.
getHandlerRegion
());
}
}
}
Set
<
BlockNode
>
regionsBlocks
=
new
HashSet
<
BlockNode
>(
mth
.
getBasicBlocks
().
size
()
);
RegionUtils
.
getAllRegionBlocks
(
mth
.
getRegion
(),
regionsBlocks
);
for
(
ExceptionHandler
handler
:
mth
.
getExceptionHandlers
())
{
IContainer
handlerRegion
=
handler
.
getHandlerRegion
();
if
(
handlerRegion
!=
null
)
{
RegionUtils
.
getAllRegionBlocks
(
handlerRegion
,
regionsBlocks
);
Set
<
BlockNode
>
regionsBlocks
=
new
HashSet
<
BlockNode
>(
mth
.
getBasicBlocks
().
size
());
RegionUtils
.
getAllRegionBlocks
(
mth
.
getRegion
(),
regionsBlocks
);
for
(
ExceptionHandler
handler
:
mth
.
getExceptionHandlers
())
{
IContainer
handlerRegion
=
handler
.
getHandlerRegion
();
if
(
handlerRegion
!=
null
)
{
RegionUtils
.
getAllRegionBlocks
(
handlerRegion
,
regionsBlocks
);
}
}
}
for
(
BlockNode
block
:
mth
.
getBasicBlocks
(
))
{
if
(!
regionsBlocks
.
contains
(
block
))
{
processBlock
(
mth
,
block
,
true
);
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
if
(!
regionsBlocks
.
contains
(
block
))
{
processBlock
(
mth
,
block
,
true
);
}
}
}
}
private
void
processRegion
(
MethodNode
mth
,
IContainer
region
)
{
if
(
region
instanceof
IRegion
)
{
IRegion
r
=
(
IRegion
)
region
;
dot
.
startLine
(
"subgraph "
+
makeName
(
region
)
+
" {"
);
dot
.
startLine
(
"label = \""
).
add
(
r
);
String
attrs
=
attributesString
(
r
);
if
(
attrs
.
length
()
!=
0
)
{
dot
.
add
(
" | "
).
add
(
attrs
);
}
dot
.
add
(
"\";"
);
dot
.
startLine
(
"node [shape=record,color=blue];"
);
private
void
processRegion
(
MethodNode
mth
,
IContainer
region
)
{
if
(
region
instanceof
IRegion
)
{
IRegion
r
=
(
IRegion
)
region
;
dot
.
startLine
(
"subgraph "
+
makeName
(
region
)
+
" {"
);
dot
.
startLine
(
"label = \""
).
add
(
r
);
String
attrs
=
attributesString
(
r
);
if
(
attrs
.
length
()
!=
0
)
{
dot
.
add
(
" | "
).
add
(
attrs
);
}
dot
.
add
(
"\";"
);
dot
.
startLine
(
"node [shape=record,color=blue];"
);
for
(
IContainer
c
:
r
.
getSubBlocks
())
{
processRegion
(
mth
,
c
);
}
for
(
IContainer
c
:
r
.
getSubBlocks
())
{
processRegion
(
mth
,
c
);
}
dot
.
startLine
(
'}'
);
}
else
if
(
region
instanceof
BlockNode
)
{
processBlock
(
mth
,
(
BlockNode
)
region
);
dot
.
startLine
(
'}'
);
}
else
if
(
region
instanceof
BlockNode
)
{
processBlock
(
mth
,
(
BlockNode
)
region
,
false
);
}
}
}
private
void
processBlock
(
MethodNode
mth
,
BlockNode
block
)
{
processBlock
(
mth
,
block
,
false
);
}
private
void
processBlock
(
MethodNode
mth
,
BlockNode
block
,
boolean
error
)
{
String
attrs
=
attributesString
(
block
);
dot
.
startLine
(
makeName
(
block
));
dot
.
add
(
" [shape=record,"
);
if
(
error
)
{
dot
.
add
(
"color=red,"
);
}
dot
.
add
(
"label=\"{"
);
dot
.
add
(
block
.
getId
()).
add
(
"\\:\\ "
);
dot
.
add
(
InsnUtils
.
formatOffset
(
block
.
getStartOffset
()));
if
(
attrs
.
length
()
!=
0
)
{
dot
.
add
(
'|'
).
add
(
attrs
);
}
String
insns
=
insertInsns
(
mth
,
block
);
if
(
insns
.
length
()
!=
0
)
{
dot
.
add
(
'|'
).
add
(
insns
);
}
dot
.
add
(
"}\"];"
);
private
void
processBlock
(
MethodNode
mth
,
BlockNode
block
,
boolean
error
)
{
String
attrs
=
attributesString
(
block
);
if
(
PRINT_REGISTERS_STATES
)
{
if
(
block
.
getStartState
()
!=
null
)
{
if
(
attrs
.
length
()
!=
0
)
{
attrs
+=
"|"
;
BlockNode
falsePath
=
null
;
List
<
InsnNode
>
list
=
block
.
getInstructions
();
if
(!
list
.
isEmpty
()
&&
list
.
get
(
0
).
getType
()
==
InsnType
.
IF
)
{
falsePath
=
((
IfNode
)
list
.
get
(
0
)).
getElseBlock
();
}
for
(
BlockNode
next
:
block
.
getSuccessors
())
{
conn
.
startLine
(
makeName
(
block
)).
add
(
" -> "
).
add
(
makeName
(
next
));
if
(
next
==
falsePath
)
{
conn
.
add
(
"[style=dotted]"
);
}
attrs
+=
escape
(
"RS: "
+
block
.
getStartState
())
+
NL
;
attrs
+=
escape
(
"RE: "
+
block
.
getEndState
())
+
NL
;
conn
.
add
(
';'
);
}
}
dot
.
startLine
(
makeName
(
block
));
dot
.
add
(
" [shape=record,"
);
if
(
error
)
{
dot
.
add
(
"color=red,"
);
}
dot
.
add
(
"label=\"{"
);
dot
.
add
(
block
.
getId
()).
add
(
"\\:\\ "
);
dot
.
add
(
InsnUtils
.
formatOffset
(
block
.
getStartOffset
()));
if
(
attrs
.
length
()
!=
0
)
{
dot
.
add
(
'|'
).
add
(
attrs
);
}
String
insns
=
insertInsns
(
mth
,
block
);
if
(
insns
.
length
()
!=
0
)
{
dot
.
add
(
'|'
).
add
(
insns
);
}
dot
.
add
(
"}\"];"
);
BlockNode
falsePath
=
null
;
List
<
InsnNode
>
list
=
block
.
getInstructions
();
if
(!
list
.
isEmpty
()
&&
list
.
get
(
0
).
getType
()
==
InsnType
.
IF
)
{
falsePath
=
((
IfNode
)
list
.
get
(
0
)).
getElseBlock
();
}
for
(
BlockNode
next
:
block
.
getSuccessors
())
{
conn
.
startLine
(
makeName
(
block
)).
add
(
" -> "
).
add
(
makeName
(
next
));
if
(
next
==
falsePath
)
{
conn
.
add
(
"[style=dotted]"
);
private
String
attributesString
(
IAttributeNode
block
)
{
StringBuilder
attrs
=
new
StringBuilder
();
for
(
String
attr
:
block
.
getAttributes
().
getAttributeStrings
())
{
attrs
.
append
(
escape
(
attr
)).
append
(
NL
);
}
conn
.
add
(
';'
);
return
attrs
.
toString
(
);
}
}
private
String
attributesString
(
IAttributeNode
block
)
{
StringBuilder
attrs
=
new
StringBuilder
();
for
(
String
attr
:
block
.
getAttributes
().
getAttributeStrings
())
{
attrs
.
append
(
escape
(
attr
)).
append
(
NL
);
private
String
makeName
(
IContainer
c
)
{
String
name
;
if
(
c
instanceof
BlockNode
)
{
name
=
"Node_"
+
((
BlockNode
)
c
).
getId
();
}
else
{
name
=
"cluster_"
+
c
.
getClass
().
getSimpleName
()
+
"_"
+
c
.
hashCode
();
}
return
name
;
}
return
attrs
.
toString
();
}
private
static
String
makeName
(
IContainer
c
)
{
String
name
;
if
(
c
instanceof
BlockNode
)
{
name
=
"Node_"
+
((
BlockNode
)
c
).
getId
();
}
else
{
name
=
"cluster_"
+
c
.
getClass
().
getSimpleName
()
+
"_"
+
c
.
hashCode
();
}
return
name
;
}
private
String
insertInsns
(
MethodNode
mth
,
BlockNode
block
)
{
if
(
rawInsn
)
{
StringBuilder
str
=
new
StringBuilder
();
for
(
InsnNode
insn
:
block
.
getInstructions
())
{
str
.
append
(
escape
(
insn
+
" "
+
insn
.
getAttributes
()));
str
.
append
(
NL
);
}
return
str
.
toString
();
}
else
{
CodeWriter
code
=
new
CodeWriter
(
0
);
MethodGen
.
addFallbackInsns
(
code
,
mth
,
block
.
getInstructions
(),
false
);
String
str
=
escape
(
code
.
newLine
().
toString
());
if
(
str
.
startsWith
(
NL
))
{
str
=
str
.
substring
(
NL
.
length
());
private
String
insertInsns
(
MethodNode
mth
,
BlockNode
block
)
{
if
(
rawInsn
)
{
StringBuilder
str
=
new
StringBuilder
();
for
(
InsnNode
insn
:
block
.
getInstructions
())
{
str
.
append
(
escape
(
insn
+
" "
+
insn
.
getAttributes
()));
str
.
append
(
NL
);
}
return
str
.
toString
();
}
else
{
CodeWriter
code
=
new
CodeWriter
(
0
);
MethodGen
.
addFallbackInsns
(
code
,
mth
,
block
.
getInstructions
(),
false
);
String
str
=
escape
(
code
.
newLine
().
toString
());
if
(
str
.
startsWith
(
NL
))
{
str
=
str
.
substring
(
NL
.
length
());
}
return
str
;
}
return
str
;
}
}
private
static
String
escape
(
String
string
)
{
return
string
.
replace
(
"\\"
,
""
)
// TODO replace \"
.
replace
(
"/"
,
"\\/"
)
.
replace
(
">"
,
"\\>"
).
replace
(
"<"
,
"\\<"
)
.
replace
(
"{"
,
"\\{"
).
replace
(
"}"
,
"\\}"
)
.
replace
(
"\""
,
"\\\""
)
.
replace
(
"-"
,
"\\-"
)
.
replace
(
"|"
,
"\\|"
)
.
replace
(
"\n"
,
NL
);
private
String
escape
(
String
string
)
{
return
string
.
replace
(
"\\"
,
""
)
// TODO replace \"
.
replace
(
"/"
,
"\\/"
)
.
replace
(
">"
,
"\\>"
).
replace
(
"<"
,
"\\<"
)
.
replace
(
"{"
,
"\\{"
).
replace
(
"}"
,
"\\}"
)
.
replace
(
"\""
,
"\\\""
)
.
replace
(
"-"
,
"\\-"
)
.
replace
(
"|"
,
"\\|"
)
.
replace
(
"\n"
,
NL
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录