Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
J
jadx
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open-source
jadx
Commits
b940b99e
Commit
b940b99e
authored
Jun 03, 2014
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: fix issues in variable names and try/catch blocks
parent
868e0706
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
456 additions
and
79 deletions
+456
-79
MethodGen.java
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
+2
-1
RegionGen.java
jadx-core/src/main/java/jadx/core/codegen/RegionGen.java
+2
-2
MethodNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
+1
-1
ExceptionHandler.java
...rc/main/java/jadx/core/dex/trycatch/ExceptionHandler.java
+5
-5
TryCatchBlock.java
...e/src/main/java/jadx/core/dex/trycatch/TryCatchBlock.java
+20
-14
BlockMakerVisitor.java
...c/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java
+2
-2
BlockProcessingHelper.java
...in/java/jadx/core/dex/visitors/BlockProcessingHelper.java
+1
-1
ProcessTryCatchRegions.java
...adx/core/dex/visitors/regions/ProcessTryCatchRegions.java
+30
-28
ProcessVariables.java
...java/jadx/core/dex/visitors/regions/ProcessVariables.java
+71
-7
RegionMaker.java
...main/java/jadx/core/dex/visitors/regions/RegionMaker.java
+46
-5
RegionMakerVisitor.java
...va/jadx/core/dex/visitors/regions/RegionMakerVisitor.java
+1
-5
RegionStack.java
...main/java/jadx/core/dex/visitors/regions/RegionStack.java
+7
-0
BlockUtils.java
jadx-core/src/main/java/jadx/core/utils/BlockUtils.java
+1
-1
RegionUtils.java
jadx-core/src/main/java/jadx/core/utils/RegionUtils.java
+19
-4
TestClassGen.java
...-core/src/test/java/jadx/tests/internal/TestClassGen.java
+40
-0
TestWrongCode.java
...core/src/test/java/jadx/tests/internal/TestWrongCode.java
+9
-1
TestLineNumbers2.java
.../java/jadx/tests/internal/debuginfo/TestLineNumbers2.java
+1
-1
TestTryCatch5.java
...test/java/jadx/tests/internal/trycatch/TestTryCatch5.java
+56
-0
TestVariables2.java
...st/java/jadx/tests/internal/variables/TestVariables2.java
+32
-0
TestVariables3.java
...st/java/jadx/tests/internal/variables/TestVariables3.java
+38
-0
TestVariables4.java
...st/java/jadx/tests/internal/variables/TestVariables4.java
+71
-0
TestVariablesDefinitions.java
...dx/tests/internal/variables/TestVariablesDefinitions.java
+1
-1
No files found.
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
View file @
b940b99e
...
...
@@ -77,9 +77,10 @@ public class MethodGen {
AccessInfo
clsAccFlags
=
mth
.
getParentClass
().
getAccessFlags
();
AccessInfo
ai
=
mth
.
getAccessFlags
();
// don't add 'abstract' to methods in interface
// don't add 'abstract'
and 'public'
to methods in interface
if
(
clsAccFlags
.
isInterface
())
{
ai
=
ai
.
remove
(
AccessFlags
.
ACC_ABSTRACT
);
ai
=
ai
.
remove
(
AccessFlags
.
ACC_PUBLIC
);
}
// don't add 'public' for annotations
if
(
clsAccFlags
.
isAnnotation
())
{
...
...
jadx-core/src/main/java/jadx/core/codegen/RegionGen.java
View file @
b940b99e
...
...
@@ -259,9 +259,9 @@ public class RegionGen extends InsnGen {
if
(
allHandler
!=
null
)
{
makeCatchBlock
(
code
,
allHandler
);
}
if
(
tryCatchBlock
.
getFinal
Block
()
!=
null
)
{
if
(
tryCatchBlock
.
getFinal
Region
()
!=
null
)
{
code
.
startLine
(
"} finally {"
);
makeRegionIndent
(
code
,
tryCatchBlock
.
getFinal
Block
());
makeRegionIndent
(
code
,
tryCatchBlock
.
getFinal
Region
());
}
code
.
startLine
(
'}'
);
}
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java
View file @
b940b99e
...
...
@@ -273,7 +273,7 @@ public class MethodNode extends LineAttrNode implements ILoadable {
// each handler must be only in one try/catch block
for
(
TryCatchBlock
ct1
:
catches
)
{
for
(
TryCatchBlock
ct2
:
catches
)
{
if
(
ct1
!=
ct2
&&
ct2
.
getHandlers
().
containsAll
(
ct1
.
getHandlers
()
))
{
if
(
ct1
!=
ct2
&&
ct2
.
containsAllHandlers
(
ct1
))
{
for
(
ExceptionHandler
h
:
ct1
.
getHandlers
())
{
ct2
.
removeHandler
(
this
,
h
);
}
...
...
jadx-core/src/main/java/jadx/core/dex/trycatch/ExceptionHandler.java
View file @
b940b99e
...
...
@@ -15,7 +15,7 @@ public class ExceptionHandler {
private
final
ClassInfo
catchType
;
private
final
int
handleOffset
;
private
BlockNode
handleBlock
;
private
BlockNode
handle
r
Block
;
private
final
List
<
BlockNode
>
blocks
=
new
ArrayList
<
BlockNode
>();
private
IContainer
handlerRegion
;
private
NamedArg
arg
;
...
...
@@ -39,12 +39,12 @@ public class ExceptionHandler {
return
handleOffset
;
}
public
BlockNode
getHandleBlock
()
{
return
handleBlock
;
public
BlockNode
getHandle
r
Block
()
{
return
handle
r
Block
;
}
public
void
setHandle
Block
(
BlockNode
handle
Block
)
{
this
.
handle
Block
=
handle
Block
;
public
void
setHandle
rBlock
(
BlockNode
handler
Block
)
{
this
.
handle
rBlock
=
handler
Block
;
}
public
List
<
BlockNode
>
getBlocks
()
{
...
...
jadx-core/src/main/java/jadx/core/dex/trycatch/TryCatchBlock.java
View file @
b940b99e
...
...
@@ -12,8 +12,6 @@ import jadx.core.utils.InstructionRemover;
import
jadx.core.utils.Utils
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Iterator
;
import
java.util.LinkedList
;
import
java.util.List
;
...
...
@@ -21,7 +19,7 @@ import java.util.List;
public
class
TryCatchBlock
{
private
final
List
<
ExceptionHandler
>
handlers
;
private
IContainer
final
Block
;
private
IContainer
final
Region
;
// references for fast remove/modify
private
final
List
<
InsnNode
>
insns
;
...
...
@@ -33,8 +31,16 @@ public class TryCatchBlock {
attr
=
new
CatchAttr
(
this
);
}
public
Collection
<
ExceptionHandler
>
getHandlers
()
{
return
Collections
.
unmodifiableCollection
(
handlers
);
public
Iterable
<
ExceptionHandler
>
getHandlers
()
{
return
handlers
;
}
public
int
getHandlersCount
()
{
return
handlers
.
size
();
}
public
boolean
containsAllHandlers
(
TryCatchBlock
tb
)
{
return
handlers
.
containsAll
(
tb
.
handlers
);
}
public
ExceptionHandler
addHandler
(
MethodNode
mth
,
int
addr
,
ClassInfo
type
)
{
...
...
@@ -59,7 +65,7 @@ public class TryCatchBlock {
}
private
void
removeWholeBlock
(
MethodNode
mth
)
{
if
(
final
Block
!=
null
)
{
if
(
final
Region
!=
null
)
{
// search catch attr
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
CatchAttr
cb
=
block
.
get
(
AType
.
CATCH_BLOCK
);
...
...
@@ -67,7 +73,7 @@ public class TryCatchBlock {
for
(
ExceptionHandler
eh
:
mth
.
getExceptionHandlers
())
{
if
(
eh
.
getBlocks
().
contains
(
block
))
{
TryCatchBlock
tb
=
eh
.
getTryBlock
();
tb
.
setFinal
BlockFromInsns
(
mth
,
((
IBlock
)
finalBlock
).
getInstructions
());
tb
.
setFinal
RegionFromInsns
(
mth
,
((
IBlock
)
finalRegion
).
getInstructions
());
}
}
}
...
...
@@ -102,17 +108,17 @@ public class TryCatchBlock {
return
attr
;
}
public
IContainer
getFinal
Block
()
{
return
final
Block
;
public
IContainer
getFinal
Region
()
{
return
final
Region
;
}
public
void
setFinal
Block
(
IContainer
finalBlock
)
{
this
.
final
Block
=
finalBlock
;
public
void
setFinal
Region
(
IContainer
finalRegion
)
{
this
.
final
Region
=
finalRegion
;
}
public
void
setFinal
Block
FromInsns
(
MethodNode
mth
,
List
<
InsnNode
>
insns
)
{
public
void
setFinal
Region
FromInsns
(
MethodNode
mth
,
List
<
InsnNode
>
insns
)
{
List
<
InsnNode
>
finalBlockInsns
=
new
ArrayList
<
InsnNode
>(
insns
);
setFinal
Block
(
new
InsnContainer
(
finalBlockInsns
));
setFinal
Region
(
new
InsnContainer
(
finalBlockInsns
));
InstructionRemover
.
unbindInsnList
(
mth
,
finalBlockInsns
);
...
...
@@ -135,7 +141,7 @@ public class TryCatchBlock {
for
(
InsnNode
insn
:
tryBlock
.
getInsns
())
{
this
.
addInsn
(
insn
);
}
this
.
handlers
.
addAll
(
tryBlock
.
getHandlers
()
);
this
.
handlers
.
addAll
(
tryBlock
.
handlers
);
for
(
ExceptionHandler
eh
:
handlers
)
{
eh
.
setTryBlock
(
this
);
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java
View file @
b940b99e
...
...
@@ -119,8 +119,8 @@ public class BlockMakerVisitor extends AbstractVisitor {
List
<
JumpInfo
>
jumps
=
insn
.
getAll
(
AType
.
JUMP
);
for
(
JumpInfo
jump
:
jumps
)
{
BlockNode
srcBlock
=
getBlock
(
jump
.
getSrc
(),
blocksMap
);
BlockNode
this
b
lock
=
getBlock
(
jump
.
getDest
(),
blocksMap
);
connect
(
srcBlock
,
this
b
lock
);
BlockNode
this
B
lock
=
getBlock
(
jump
.
getDest
(),
blocksMap
);
connect
(
srcBlock
,
this
B
lock
);
}
// connect exception handlers
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/BlockProcessingHelper.java
View file @
b940b99e
...
...
@@ -137,7 +137,7 @@ public class BlockProcessingHelper {
for
(
BlockNode
block
:
mth
.
getBasicBlocks
())
{
ExcHandlerAttr
bh
=
block
.
get
(
AType
.
EXC_HANDLER
);
if
(
bh
!=
null
&&
bh
.
getHandler
().
getHandleOffset
()
==
addr
)
{
handler
.
setHandleBlock
(
block
);
handler
.
setHandle
r
Block
(
block
);
break
;
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java
View file @
b940b99e
...
...
@@ -119,41 +119,43 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
assert
tb
!=
null
;
for
(
IContainer
cont
:
region
.
getSubBlocks
())
{
if
(
RegionUtils
.
isDominaterBy
(
dominator
,
cont
))
{
boolean
pathFromExcHandler
=
false
;
for
(
ExceptionHandler
h
:
tb
.
getHandlers
())
{
if
(
RegionUtils
.
hasPathThruBlock
(
h
.
getHandleBlock
(),
cont
))
{
pathFromExcHandler
=
true
;
break
;
}
}
if
(!
pathFromExcHandler
)
{
newRegion
.
getSubBlocks
().
add
(
cont
);
}
else
{
if
(
RegionUtils
.
isDominatedBy
(
dominator
,
cont
))
{
if
(
isHandlerPath
(
tb
,
cont
))
{
break
;
}
newRegion
.
getSubBlocks
().
add
(
cont
);
}
}
if
(!
newRegion
.
getSubBlocks
().
isEmpty
())
{
if
(
DEBUG
)
{
LOG
.
debug
(
"ProcessTryCatchRegions mark: {}"
,
newRegion
);
if
(
newRegion
.
getSubBlocks
().
isEmpty
())
{
return
;
}
if
(
DEBUG
)
{
LOG
.
debug
(
"ProcessTryCatchRegions mark: {}"
,
newRegion
);
}
// replace first node by region
IContainer
firstNode
=
newRegion
.
getSubBlocks
().
get
(
0
);
int
i
=
region
.
getSubBlocks
().
indexOf
(
firstNode
);
region
.
getSubBlocks
().
set
(
i
,
newRegion
);
region
.
getSubBlocks
().
removeAll
(
newRegion
.
getSubBlocks
());
newRegion
.
addAttr
(
tb
.
getCatchAttr
());
// fix parents
for
(
IContainer
cont
:
newRegion
.
getSubBlocks
())
{
if
(
cont
instanceof
AbstractRegion
)
{
AbstractRegion
aReg
=
(
AbstractRegion
)
cont
;
aReg
.
setParent
(
newRegion
);
}
// replace first node by region
IContainer
firstNode
=
newRegion
.
getSubBlocks
().
get
(
0
);
int
i
=
region
.
getSubBlocks
().
indexOf
(
firstNode
);
region
.
getSubBlocks
().
set
(
i
,
newRegion
);
region
.
getSubBlocks
().
removeAll
(
newRegion
.
getSubBlocks
());
newRegion
.
addAttr
(
tb
.
getCatchAttr
());
// fix parents
for
(
IContainer
cont
:
newRegion
.
getSubBlocks
())
{
if
(
cont
instanceof
AbstractRegion
)
{
AbstractRegion
aReg
=
(
AbstractRegion
)
cont
;
aReg
.
setParent
(
newRegion
);
}
}
}
private
boolean
isHandlerPath
(
TryCatchBlock
tb
,
IContainer
cont
)
{
for
(
ExceptionHandler
h
:
tb
.
getHandlers
())
{
if
(
RegionUtils
.
hasPathThruBlock
(
h
.
getHandlerBlock
(),
cont
))
{
return
true
;
}
}
return
false
;
}
}
jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java
View file @
b940b99e
...
...
@@ -10,11 +10,14 @@ import jadx.core.dex.nodes.IContainer;
import
jadx.core.dex.nodes.IRegion
;
import
jadx.core.dex.nodes.InsnNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.regions.IfRegion
;
import
jadx.core.dex.regions.SwitchRegion
;
import
jadx.core.dex.visitors.AbstractVisitor
;
import
jadx.core.utils.RegionUtils
;
import
jadx.core.utils.exceptions.JadxException
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.LinkedHashMap
;
...
...
@@ -137,6 +140,13 @@ public class ProcessVariables extends AbstractVisitor {
usageMap
.
remove
(
new
Variable
(
arg
));
}
if
(
usageMap
.
isEmpty
())
{
return
;
}
Map
<
IContainer
,
Integer
>
regionsOrder
=
new
HashMap
<
IContainer
,
Integer
>();
calculateOrder
(
mth
.
getRegion
(),
regionsOrder
,
0
,
true
);
for
(
Iterator
<
Entry
<
Variable
,
Usage
>>
it
=
usageMap
.
entrySet
().
iterator
();
it
.
hasNext
();
)
{
Entry
<
Variable
,
Usage
>
entry
=
it
.
next
();
Usage
u
=
entry
.
getValue
();
...
...
@@ -147,10 +157,10 @@ public class ProcessVariables extends AbstractVisitor {
continue
;
}
// check if
we can declare variable
at current assigns
// check if
variable can be declared
at current assigns
for
(
IRegion
assignRegion
:
u
.
getAssigns
())
{
if
(
u
.
getArgRegion
()
==
assignRegion
&&
canDeclareInRegion
(
u
,
assignRegion
))
{
&&
canDeclareInRegion
(
u
,
assignRegion
,
regionsOrder
))
{
u
.
getArg
().
getParentInsn
().
add
(
AFlag
.
DECLARE_VAR
);
it
.
remove
();
break
;
...
...
@@ -178,7 +188,7 @@ public class ProcessVariables extends AbstractVisitor {
IRegion
parent
=
region
;
boolean
declare
=
false
;
while
(
parent
!=
null
)
{
if
(
canDeclareInRegion
(
u
,
region
))
{
if
(
canDeclareInRegion
(
u
,
region
,
regionsOrder
))
{
declareVar
(
region
,
u
.
getArg
());
declare
=
true
;
break
;
...
...
@@ -212,13 +222,67 @@ public class ProcessVariables extends AbstractVisitor {
dv
.
addVar
(
arg
);
}
private
static
boolean
canDeclareInRegion
(
Usage
u
,
IRegion
region
)
{
for
(
IRegion
r
:
u
.
getAssigns
())
{
if
(!
RegionUtils
.
isRegionContainsRegion
(
region
,
r
))
{
private
static
int
calculateOrder
(
IContainer
container
,
Map
<
IContainer
,
Integer
>
regionsOrder
,
int
id
,
boolean
inc
)
{
if
(!(
container
instanceof
IRegion
))
{
return
id
;
}
IRegion
region
=
(
IRegion
)
container
;
Integer
previous
=
regionsOrder
.
put
(
region
,
id
);
if
(
previous
!=
null
)
{
return
id
;
}
for
(
IContainer
c
:
region
.
getSubBlocks
())
{
if
(
c
instanceof
IfRegion
||
c
instanceof
SwitchRegion
)
{
// on branch set for all inner regions same order id
id
=
calculateOrder
(
c
,
regionsOrder
,
inc
?
id
+
1
:
id
,
false
);
}
else
{
List
<
IContainer
>
handlers
=
RegionUtils
.
getExcHandlersForRegion
(
c
);
if
(!
handlers
.
isEmpty
())
{
for
(
IContainer
handler
:
handlers
)
{
id
=
calculateOrder
(
handler
,
regionsOrder
,
inc
?
id
+
1
:
id
,
inc
);
}
}
id
=
calculateOrder
(
c
,
regionsOrder
,
inc
?
id
+
1
:
id
,
inc
);
}
}
return
id
;
}
private
static
boolean
canDeclareInRegion
(
Usage
u
,
IRegion
region
,
Map
<
IContainer
,
Integer
>
regionsOrder
)
{
Integer
pos
=
regionsOrder
.
get
(
region
);
if
(
pos
==
null
)
{
LOG
.
debug
(
"TODO: Not found order for region {} for {}"
,
region
,
u
);
return
false
;
}
return
isAllRegionsAfter
(
region
,
pos
,
u
.
getAssigns
(),
regionsOrder
)
&&
isAllRegionsAfter
(
region
,
pos
,
u
.
getUseRegions
(),
regionsOrder
);
}
private
static
boolean
isAllRegionsAfter
(
IRegion
region
,
Integer
pos
,
Set
<
IRegion
>
regions
,
Map
<
IContainer
,
Integer
>
regionsOrder
)
{
for
(
IRegion
r
:
regions
)
{
if
(
r
==
region
)
{
continue
;
}
Integer
rPos
=
regionsOrder
.
get
(
r
);
if
(
rPos
==
null
)
{
LOG
.
debug
(
"TODO: Not found order for region {} in {}"
,
r
,
regionsOrder
);
return
false
;
}
if
(
pos
>
rPos
)
{
return
false
;
}
if
(
pos
.
equals
(
rPos
))
{
return
isAllRegionsAfterRecursive
(
region
,
regions
);
}
}
for
(
IRegion
r
:
u
.
getUseRegions
())
{
return
true
;
}
private
static
boolean
isAllRegionsAfterRecursive
(
IRegion
region
,
Set
<
IRegion
>
others
)
{
for
(
IRegion
r
:
others
)
{
if
(!
RegionUtils
.
isRegionContainsRegion
(
region
,
r
))
{
return
false
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java
View file @
b940b99e
...
...
@@ -23,6 +23,7 @@ import jadx.core.dex.regions.SwitchRegion;
import
jadx.core.dex.regions.SynchronizedRegion
;
import
jadx.core.dex.trycatch.ExcHandlerAttr
;
import
jadx.core.dex.trycatch.ExceptionHandler
;
import
jadx.core.dex.trycatch.TryCatchBlock
;
import
jadx.core.utils.BlockUtils
;
import
jadx.core.utils.ErrorsCounter
;
import
jadx.core.utils.InstructionRemover
;
...
...
@@ -410,7 +411,7 @@ public class RegionMaker {
ifRegion
.
setCondition
(
mergedIf
.
getCondition
());
thenBlock
=
mergedIf
.
getThenBlock
();
elseBlock
=
mergedIf
.
getElseBlock
();
out
=
BlockUtils
.
getPathCross
BlockFor
(
mth
,
thenBlock
,
elseBlock
);
out
=
BlockUtils
.
getPathCross
(
mth
,
thenBlock
,
elseBlock
);
}
else
{
// invert condition (compiler often do it)
ifnode
.
invertCondition
();
...
...
@@ -432,7 +433,7 @@ public class RegionMaker {
}
else
if
(
block
.
getDominatesOn
().
size
()
==
2
)
{
thenBlock
=
bThen
;
elseBlock
=
bElse
;
out
=
BlockUtils
.
getPathCross
BlockFor
(
mth
,
bThen
,
bElse
);
out
=
BlockUtils
.
getPathCross
(
mth
,
bThen
,
bElse
);
}
else
if
(
bElse
.
getPredecessors
().
size
()
!=
1
)
{
thenBlock
=
bThen
;
elseBlock
=
null
;
...
...
@@ -679,14 +680,54 @@ public class RegionMaker {
return
out
;
}
public
void
processExcHandler
(
ExceptionHandler
handler
,
RegionStack
stack
)
{
BlockNode
start
=
handler
.
getHandleBlock
();
public
void
processTryCatchBlocks
(
MethodNode
mth
)
{
Set
<
TryCatchBlock
>
tcs
=
new
HashSet
<
TryCatchBlock
>();
for
(
ExceptionHandler
handler
:
mth
.
getExceptionHandlers
())
{
tcs
.
add
(
handler
.
getTryBlock
());
}
for
(
TryCatchBlock
tc
:
tcs
)
{
List
<
BlockNode
>
blocks
=
new
ArrayList
<
BlockNode
>(
tc
.
getHandlersCount
());
Set
<
BlockNode
>
splitters
=
new
HashSet
<
BlockNode
>();
for
(
ExceptionHandler
handler
:
tc
.
getHandlers
())
{
BlockNode
handlerBlock
=
handler
.
getHandlerBlock
();
if
(
handlerBlock
!=
null
)
{
blocks
.
add
(
handlerBlock
);
splitters
.
addAll
(
handlerBlock
.
getPredecessors
());
}
else
{
LOG
.
debug
(
ErrorsCounter
.
formatErrorMsg
(
mth
,
"No exception handler block: "
+
handler
));
}
}
Set
<
BlockNode
>
exits
=
new
HashSet
<
BlockNode
>();
for
(
BlockNode
splitter
:
splitters
)
{
for
(
BlockNode
handler
:
blocks
)
{
List
<
BlockNode
>
s
=
splitter
.
getCleanSuccessors
();
if
(
s
.
isEmpty
())
{
LOG
.
debug
(
ErrorsCounter
.
formatErrorMsg
(
mth
,
"No successors for splitter: "
+
splitter
));
continue
;
}
BlockNode
cross
=
BlockUtils
.
getPathCross
(
mth
,
s
.
get
(
0
),
handler
);
if
(
cross
!=
null
)
{
exits
.
add
(
cross
);
}
}
}
for
(
ExceptionHandler
handler
:
tc
.
getHandlers
())
{
processExcHandler
(
handler
,
exits
);
}
}
}
private
void
processExcHandler
(
ExceptionHandler
handler
,
Set
<
BlockNode
>
exits
)
{
BlockNode
start
=
handler
.
getHandlerBlock
();
if
(
start
==
null
)
{
LOG
.
debug
(
ErrorsCounter
.
formatErrorMsg
(
mth
,
"No exception handler block: "
+
handler
));
return
;
}
// TODO extract finally part which exists in all handlers from same try block
// TODO add blocks common for several handlers to some region
RegionStack
stack
=
new
RegionStack
(
mth
);
stack
.
addExits
(
exits
);
handler
.
setHandlerRegion
(
makeRegion
(
start
,
stack
));
ExcHandlerAttr
excHandlerAttr
=
start
.
get
(
AType
.
EXC_HANDLER
);
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMakerVisitor.java
View file @
b940b99e
...
...
@@ -7,7 +7,6 @@ import jadx.core.dex.nodes.MethodNode;
import
jadx.core.dex.regions.LoopRegion
;
import
jadx.core.dex.regions.Region
;
import
jadx.core.dex.regions.SynchronizedRegion
;
import
jadx.core.dex.trycatch.ExceptionHandler
;
import
jadx.core.dex.visitors.AbstractVisitor
;
import
jadx.core.utils.InstructionRemover
;
import
jadx.core.utils.exceptions.JadxException
;
...
...
@@ -35,10 +34,7 @@ public class RegionMakerVisitor extends AbstractVisitor {
mth
.
setRegion
(
rm
.
makeRegion
(
mth
.
getEnterBlock
(),
state
));
if
(!
mth
.
isNoExceptionHandlers
())
{
state
=
new
RegionStack
(
mth
);
for
(
ExceptionHandler
handler
:
mth
.
getExceptionHandlers
())
{
rm
.
processExcHandler
(
handler
,
state
);
}
rm
.
processTryCatchBlocks
(
mth
);
}
postProcessRegions
(
mth
);
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionStack.java
View file @
b940b99e
...
...
@@ -5,6 +5,7 @@ import jadx.core.dex.nodes.IRegion;
import
jadx.core.dex.nodes.MethodNode
;
import
java.util.ArrayDeque
;
import
java.util.Collection
;
import
java.util.Deque
;
import
java.util.HashSet
;
import
java.util.Set
;
...
...
@@ -85,6 +86,12 @@ final class RegionStack {
}
}
public
void
addExits
(
Collection
<
BlockNode
>
exits
)
{
for
(
BlockNode
exit
:
exits
)
{
addExit
(
exit
);
}
}
public
boolean
containsExit
(
BlockNode
exit
)
{
return
curState
.
exits
.
contains
(
exit
);
}
...
...
jadx-core/src/main/java/jadx/core/utils/BlockUtils.java
View file @
b940b99e
...
...
@@ -245,7 +245,7 @@ public class BlockUtils {
return
null
;
}
public
static
BlockNode
getPathCross
BlockFor
(
MethodNode
mth
,
BlockNode
b1
,
BlockNode
b2
)
{
public
static
BlockNode
getPathCross
(
MethodNode
mth
,
BlockNode
b1
,
BlockNode
b2
)
{
if
(
b1
==
null
||
b2
==
null
)
{
return
null
;
}
...
...
jadx-core/src/main/java/jadx/core/utils/RegionUtils.java
View file @
b940b99e
...
...
@@ -10,6 +10,8 @@ import jadx.core.dex.trycatch.ExceptionHandler;
import
jadx.core.dex.trycatch.TryCatchBlock
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Set
;
...
...
@@ -111,6 +113,19 @@ public class RegionUtils {
}
}
public
static
List
<
IContainer
>
getExcHandlersForRegion
(
IContainer
region
)
{
CatchAttr
cb
=
region
.
get
(
AType
.
CATCH_BLOCK
);
if
(
cb
!=
null
)
{
TryCatchBlock
tb
=
cb
.
getTryBlock
();
List
<
IContainer
>
list
=
new
ArrayList
<
IContainer
>(
tb
.
getHandlersCount
());
for
(
ExceptionHandler
eh
:
tb
.
getHandlers
())
{
list
.
add
(
eh
.
getHandlerRegion
());
}
return
list
;
}
return
Collections
.
emptyList
();
}
private
static
boolean
isRegionContainsExcHandlerRegion
(
IContainer
container
,
IRegion
region
)
{
if
(
container
==
region
)
{
return
true
;
...
...
@@ -129,8 +144,8 @@ public class RegionUtils {
return
true
;
}
}
if
(
tb
.
getFinal
Block
()
!=
null
&&
isRegionContainsRegion
(
tb
.
getFinal
Block
(),
region
))
{
if
(
tb
.
getFinal
Region
()
!=
null
&&
isRegionContainsRegion
(
tb
.
getFinal
Region
(),
region
))
{
return
true
;
}
}
...
...
@@ -169,7 +184,7 @@ public class RegionUtils {
return
true
;
}
public
static
boolean
isDominate
r
By
(
BlockNode
dom
,
IContainer
cont
)
{
public
static
boolean
isDominate
d
By
(
BlockNode
dom
,
IContainer
cont
)
{
if
(
dom
==
cont
)
{
return
true
;
}
...
...
@@ -179,7 +194,7 @@ public class RegionUtils {
}
else
if
(
cont
instanceof
IRegion
)
{
IRegion
region
=
(
IRegion
)
cont
;
for
(
IContainer
c
:
region
.
getSubBlocks
())
{
if
(!
isDominate
r
By
(
dom
,
c
))
{
if
(!
isDominate
d
By
(
dom
,
c
))
{
return
false
;
}
}
...
...
jadx-core/src/test/java/jadx/tests/internal/TestClassGen.java
0 → 100644
View file @
b940b99e
package
jadx
.
tests
.
internal
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
hamcrest
.
CoreMatchers
.
not
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestClassGen
extends
InternalJadxTest
{
public
static
class
TestCls
{
public
static
interface
I
{
int
test
();
public
int
test3
();
}
public
static
abstract
class
A
{
public
abstract
int
test2
();
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsString
(
"public static interface I {"
));
assertThat
(
code
,
containsString
(
indent
(
2
)
+
"int test();"
));
assertThat
(
code
,
not
(
containsString
(
"public int test();"
)));
assertThat
(
code
,
containsString
(
indent
(
2
)
+
"int test3();"
));
assertThat
(
code
,
containsString
(
"public static abstract class A {"
));
assertThat
(
code
,
containsString
(
indent
(
2
)
+
"public abstract int test2();"
));
}
}
jadx-core/src/test/java/jadx/tests/internal/TestWrongCode.java
View file @
b940b99e
...
...
@@ -12,10 +12,16 @@ import static org.junit.Assert.assertThat;
public
class
TestWrongCode
extends
InternalJadxTest
{
public
static
class
TestCls
{
private
int
f
()
{
private
int
test
()
{
int
[]
a
=
null
;
return
a
.
length
;
}
@SuppressWarnings
(
"empty"
)
private
int
test2
(
int
a
)
{
if
(
a
==
0
);
return
a
;
}
}
@Test
...
...
@@ -26,5 +32,7 @@ public class TestWrongCode extends InternalJadxTest {
assertThat
(
code
,
not
(
containsString
(
"return false.length;"
)));
assertThat
(
code
,
containsString
(
"return null.length;"
));
assertThat
(
code
,
containsString
(
"return a == 0 ? a : a;"
));
}
}
jadx-core/src/test/java/jadx/tests/internal/debuginfo/TestLineNumbers2.java
View file @
b940b99e
...
...
@@ -41,7 +41,7 @@ public class TestLineNumbers2 extends InternalJadxTest {
System
.
out
.
println
(
code
);
Map
<
Integer
,
Integer
>
lineMapping
=
codeWriter
.
getLineMapping
();
assertEquals
(
"{8=18, 11=22, 1
3=23, 14=24, 15=28, 17=25, 18=26, 19=28, 22=31, 23
=32}"
,
assertEquals
(
"{8=18, 11=22, 1
2=23, 13=24, 14=28, 16=25, 17=26, 18=28, 21=31, 22
=32}"
,
lineMapping
.
toString
());
}
}
jadx-core/src/test/java/jadx/tests/internal/trycatch/TestTryCatch5.java
0 → 100644
View file @
b940b99e
package
jadx
.
tests
.
internal
.
trycatch
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.io.IOException
;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestTryCatch5
extends
InternalJadxTest
{
public
static
class
TestCls
{
private
Object
test
(
Object
obj
)
{
File
file
=
new
File
(
"r"
);
FileOutputStream
output
=
null
;
try
{
output
=
new
FileOutputStream
(
file
);
if
(
obj
.
equals
(
"a"
))
{
return
new
Object
();
}
else
{
return
null
;
}
}
catch
(
IOException
e
)
{
System
.
out
.
println
(
"Exception"
);
return
null
;
}
finally
{
if
(
output
!=
null
)
{
try
{
output
.
close
();
}
catch
(
IOException
e
)
{
// Ignored
}
}
file
.
delete
();
}
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsString
(
"try {"
));
// TODO:
// assertThat(code, containsString("output = new FileOutputStream(file);"));
// assertThat(code, containsString("} catch (IOException e) {"));
assertThat
(
code
,
containsString
(
"file.delete();"
));
}
}
jadx-core/src/test/java/jadx/tests/internal/variables/TestVariables2.java
0 → 100644
View file @
b940b99e
package
jadx
.
tests
.
internal
.
variables
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestVariables2
extends
InternalJadxTest
{
public
static
class
TestCls
{
Object
test
(
Object
s
)
{
Object
store
=
s
!=
null
?
s
:
null
;
if
(
store
==
null
)
{
store
=
new
Object
();
s
=
store
;
}
return
store
;
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsString
(
"Object store = s != null ? s : null;"
));
}
}
jadx-core/src/test/java/jadx/tests/internal/variables/TestVariables3.java
0 → 100644
View file @
b940b99e
package
jadx
.
tests
.
internal
.
variables
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestVariables3
extends
InternalJadxTest
{
public
static
class
TestCls
{
String
test
(
Object
s
)
{
int
i
;
if
(
s
==
null
)
{
i
=
2
;
}
else
{
i
=
3
;
s
=
null
;
}
return
s
+
" "
+
i
;
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsString
(
"int i;"
));
assertThat
(
code
,
containsString
(
"i = 2;"
));
assertThat
(
code
,
containsString
(
"i = 3;"
));
assertThat
(
code
,
containsString
(
"s = null;"
));
assertThat
(
code
,
containsString
(
"return s + \" \" + i;"
));
}
}
jadx-core/src/test/java/jadx/tests/internal/variables/TestVariables4.java
0 → 100644
View file @
b940b99e
package
jadx
.
tests
.
internal
.
variables
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
org.junit.Test
;
import
static
org
.
hamcrest
.
CoreMatchers
.
containsString
;
import
static
org
.
junit
.
Assert
.
assertThat
;
public
class
TestVariables4
extends
InternalJadxTest
{
public
static
class
TestCls
{
private
static
boolean
runTest
(
String
clsName
)
{
try
{
boolean
pass
=
false
;
String
msg
=
null
;
Throwable
exc
=
null
;
Class
<?>
cls
=
Class
.
forName
(
clsName
);
if
(
cls
.
getSuperclass
()
==
AbstractTest
.
class
)
{
Method
mth
=
cls
.
getMethod
(
"testRun"
);
try
{
AbstractTest
test
=
(
AbstractTest
)
cls
.
getConstructor
().
newInstance
();
pass
=
(
Boolean
)
mth
.
invoke
(
test
);
}
catch
(
InvocationTargetException
e
)
{
pass
=
false
;
exc
=
e
.
getCause
();
}
catch
(
Throwable
e
)
{
pass
=
false
;
exc
=
e
;
}
}
else
{
msg
=
"not extends AbstractTest"
;
}
System
.
err
.
println
(
">> "
+
(
pass
?
"PASS"
:
"FAIL"
)
+
"\t"
+
clsName
+
(
msg
==
null
?
""
:
"\t - "
+
msg
));
if
(
exc
!=
null
)
{
exc
.
printStackTrace
();
}
return
pass
;
}
catch
(
ClassNotFoundException
e
)
{
System
.
err
.
println
(
"Class '"
+
clsName
+
"' not found"
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
false
;
}
private
static
class
AbstractTest
{
}
}
@Test
public
void
test
()
{
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
System
.
out
.
println
(
code
);
assertThat
(
code
,
containsString
(
"} catch (InvocationTargetException e) {"
));
assertThat
(
code
,
containsString
(
"pass = false;"
));
assertThat
(
code
,
containsString
(
"exc = e.getCause();"
));
assertThat
(
code
,
containsString
(
"System.err.println(\"Class '\" + clsName + \"' not found\");"
));
assertThat
(
code
,
containsString
(
"return pass;"
));
}
}
jadx-core/src/test/java/jadx/tests/internal/TestVariablesDefinitions.java
→
jadx-core/src/test/java/jadx/tests/internal/
variables/
TestVariablesDefinitions.java
View file @
b940b99e
package
jadx
.
tests
.
internal
;
package
jadx
.
tests
.
internal
.
variables
;
import
jadx.api.InternalJadxTest
;
import
jadx.core.dex.nodes.ClassNode
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment