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
42eb3197
Commit
42eb3197
authored
May 10, 2014
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix issues reported by Coverity
parent
343bddc6
Hide whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
456 additions
and
126 deletions
+456
-126
README.md
README.md
+5
-4
build.gradle
build.gradle
+1
-1
JadxCLI.java
jadx-cli/src/main/java/jadx/cli/JadxCLI.java
+17
-12
JadxCLIArgs.java
jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
+9
-8
Jadx.java
jadx-core/src/main/java/jadx/core/Jadx.java
+10
-8
ClsSet.java
jadx-core/src/main/java/jadx/core/clsp/ClsSet.java
+84
-62
ConvertToClsSet.java
jadx-core/src/main/java/jadx/core/clsp/ConvertToClsSet.java
+3
-0
InsnGen.java
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
+6
-4
MethodGen.java
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
+1
-0
ArithNode.java
...e/src/main/java/jadx/core/dex/instructions/ArithNode.java
+17
-0
ConstClassNode.java
.../main/java/jadx/core/dex/instructions/ConstClassNode.java
+18
-1
ConstStringNode.java
...main/java/jadx/core/dex/instructions/ConstStringNode.java
+18
-1
FillArrayNode.java
...c/main/java/jadx/core/dex/instructions/FillArrayNode.java
+18
-1
GotoNode.java
...re/src/main/java/jadx/core/dex/instructions/GotoNode.java
+17
-0
IfNode.java
...core/src/main/java/jadx/core/dex/instructions/IfNode.java
+17
-0
IndexInsnNode.java
...c/main/java/jadx/core/dex/instructions/IndexInsnNode.java
+17
-0
InvokeNode.java
.../src/main/java/jadx/core/dex/instructions/InvokeNode.java
+20
-0
SwitchNode.java
.../src/main/java/jadx/core/dex/instructions/SwitchNode.java
+23
-0
FieldArg.java
...c/main/java/jadx/core/dex/instructions/args/FieldArg.java
+26
-0
RegisterArg.java
...ain/java/jadx/core/dex/instructions/args/RegisterArg.java
+3
-0
ConstructorInsn.java
...java/jadx/core/dex/instructions/mods/ConstructorInsn.java
+23
-0
TernaryInsn.java
...ain/java/jadx/core/dex/instructions/mods/TernaryInsn.java
+17
-0
BlockNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/BlockNode.java
+11
-3
LocalVar.java
...re/src/main/java/jadx/core/dex/nodes/parser/LocalVar.java
+10
-0
SignatureParser.java
...main/java/jadx/core/dex/nodes/parser/SignatureParser.java
+9
-0
ClassModifier.java
...e/src/main/java/jadx/core/dex/visitors/ClassModifier.java
+4
-1
Utils.java
jadx-core/src/main/java/jadx/core/utils/Utils.java
+1
-1
InputFile.java
jadx-core/src/main/java/jadx/core/utils/files/InputFile.java
+10
-3
JavaToDex.java
jadx-core/src/main/java/jadx/core/utils/files/JavaToDex.java
+15
-5
TestSignatureParser.groovy
...ore/src/test/groovy/jadx/tests/TestSignatureParser.groovy
+8
-1
JadxGUI.java
jadx-gui/src/main/java/jadx/gui/JadxGUI.java
+5
-2
MainWindow.java
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
+5
-2
SearchBar.java
jadx-gui/src/main/java/jadx/gui/ui/SearchBar.java
+8
-6
No files found.
README.md
View file @
42eb3197
## JADX
## JADX
[
![Build Status
](
https://travis-ci.org/skylot/jadx.png?branch=master
)
](https://travis-ci.org/skylot/jadx)
[
![Build Status
](
https://drone.io/github.com/skylot/jadx/status.png
)
](https://drone.io/github.com/skylot/jadx/latest)
[
![Coverage Status
](
https://coveralls.io/repos/skylot/jadx/badge.png
)
](https://coveralls.io/r/skylot/jadx)
[
![Coverity Scan Build Status
](
https://scan.coverity.com/projects/2166/badge.svg
)
](https://scan.coverity.com/projects/2166)
**jadx**
- Dex to Java decompiler
...
...
@@ -12,14 +13,14 @@ Command line and GUI tools for produce Java source code from Android Dex and Apk
### Downloads
-
[
unstable
](
https://drone.io/github.com/skylot/jadx/files
)
-
from
[
github
](
https://github.com/skylot/jadx/releases
)
-
from
[
sourceforge
](
http://sourceforge.net/projects/jadx/files/
)
-
from
[
sourceforge
](
http://sourceforge.net/projects/jadx/files/
)
### Building from source
### Building from source
git clone https://github.com/skylot/jadx.git
cd jadx
./gradlew dist
(on Windows, use
`gradlew.bat`
instead of
`./gradlew`
)
Scripts for run jadx will be placed in
`build/jadx/bin`
...
...
build.gradle
View file @
42eb3197
...
...
@@ -16,7 +16,7 @@ subprojects {
gradle
.
projectsEvaluated
{
tasks
.
withType
(
Compile
)
{
if
(!
"$
{it}
"
.
contains
(
':jadx-samples:'
))
{
if
(!
"$
it
"
.
contains
(
':jadx-samples:'
))
{
options
.
compilerArgs
<<
'-Xlint'
<<
'-Xlint:unchecked'
<<
'-Xlint:deprecation'
}
}
...
...
jadx-cli/src/main/java/jadx/cli/JadxCLI.java
View file @
42eb3197
...
...
@@ -14,37 +14,41 @@ public class JadxCLI {
public
static
void
main
(
String
[]
args
)
{
try
{
JadxCLIArgs
jadxArgs
=
new
JadxCLIArgs
(
args
);
checkArgs
(
jadxArgs
);
processAndSave
(
jadxArgs
);
}
catch
(
Exception
e
)
{
JadxCLIArgs
jadxArgs
=
new
JadxCLIArgs
();
if
(
processArgs
(
jadxArgs
,
args
))
{
processAndSave
(
jadxArgs
);
}
}
catch
(
JadxException
e
)
{
LOG
.
error
(
e
.
getMessage
());
System
.
exit
(
1
);
}
}
private
static
void
processAndSave
(
JadxCLIArgs
jadxArgs
)
{
static
void
processAndSave
(
JadxCLIArgs
jadxArgs
)
throws
JadxException
{
try
{
Decompiler
jadx
=
new
Decompiler
(
jadxArgs
);
jadx
.
loadFiles
(
jadxArgs
.
getInput
());
jadx
.
setOutputDir
(
jadxArgs
.
getOutDir
());
jadx
.
save
();
LOG
.
info
(
"done"
);
}
catch
(
Throwable
e
)
{
LOG
.
error
(
"jadx error:"
,
e
);
throw
new
JadxException
(
"jadx error: "
+
e
.
getMessage
()
,
e
);
}
int
errorsCount
=
ErrorsCounter
.
getErrorCount
();
if
(
errorsCount
!=
0
)
{
if
(
ErrorsCounter
.
getErrorCount
()
!=
0
)
{
ErrorsCounter
.
printReport
();
throw
new
JadxException
(
"finished with errors"
);
}
System
.
exit
(
errorsCount
);
LOG
.
info
(
"done"
);
}
private
static
void
checkArgs
(
JadxCLIArgs
jadxArgs
)
throws
JadxException
{
static
boolean
processArgs
(
JadxCLIArgs
jadxArgs
,
String
[]
args
)
throws
JadxException
{
if
(!
jadxArgs
.
processArgs
(
args
))
{
return
false
;
}
if
(
jadxArgs
.
getInput
().
isEmpty
())
{
LOG
.
error
(
"Please specify input file"
);
jadxArgs
.
printUsage
();
System
.
exit
(
1
)
;
return
false
;
}
File
outputDir
=
jadxArgs
.
getOutDir
();
if
(
outputDir
==
null
)
{
...
...
@@ -64,5 +68,6 @@ public class JadxCLI {
if
(
outputDir
.
exists
()
&&
!
outputDir
.
isDirectory
())
{
throw
new
JadxException
(
"Output directory exists as file "
+
outputDir
);
}
return
true
;
}
}
jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
View file @
42eb3197
...
...
@@ -47,25 +47,25 @@ public final class JadxCLIArgs implements IJadxArgs {
private
final
List
<
File
>
input
=
new
ArrayList
<
File
>(
1
);
private
File
outputDir
;
public
JadxCLIArgs
(
String
[]
args
)
{
parse
(
args
);
processArgs
();
public
boolean
processArgs
(
String
[]
args
)
{
return
parse
(
args
)
&&
process
();
}
private
void
parse
(
String
[]
args
)
{
private
boolean
parse
(
String
[]
args
)
{
try
{
new
JCommander
(
this
,
args
);
return
true
;
}
catch
(
ParameterException
e
)
{
System
.
err
.
println
(
"Arguments parse error: "
+
e
.
getMessage
());
printUsage
();
System
.
exit
(
1
)
;
return
false
;
}
}
p
ublic
void
processArg
s
()
{
p
rivate
boolean
proces
s
()
{
if
(
isPrintHelp
())
{
printUsage
();
System
.
exit
(
0
)
;
return
false
;
}
try
{
if
(
threadsCount
<=
0
)
{
...
...
@@ -95,8 +95,9 @@ public final class JadxCLIArgs implements IJadxArgs {
}
catch
(
JadxException
e
)
{
System
.
err
.
println
(
"ERROR: "
+
e
.
getMessage
());
printUsage
();
System
.
exit
(
1
)
;
return
false
;
}
return
true
;
}
public
void
printUsage
()
{
...
...
jadx-core/src/main/java/jadx/core/Jadx.java
View file @
42eb3197
...
...
@@ -25,7 +25,6 @@ import jadx.core.dex.visitors.typeinference.TypeInference;
import
jadx.core.utils.Utils
;
import
java.io.File
;
import
java.io.IOException
;
import
java.net.URL
;
import
java.util.ArrayList
;
import
java.util.Enumeration
;
...
...
@@ -95,15 +94,18 @@ public class Jadx {
public
static
String
getVersion
()
{
try
{
Enumeration
<
URL
>
resources
=
Utils
.
class
.
getClassLoader
().
getResources
(
"META-INF/MANIFEST.MF"
);
while
(
resources
.
hasMoreElements
())
{
Manifest
manifest
=
new
Manifest
(
resources
.
nextElement
().
openStream
());
String
ver
=
manifest
.
getMainAttributes
().
getValue
(
"jadx-version"
);
if
(
ver
!=
null
)
{
return
ver
;
ClassLoader
classLoader
=
Utils
.
class
.
getClassLoader
();
if
(
classLoader
!=
null
)
{
Enumeration
<
URL
>
resources
=
classLoader
.
getResources
(
"META-INF/MANIFEST.MF"
);
while
(
resources
.
hasMoreElements
())
{
Manifest
manifest
=
new
Manifest
(
resources
.
nextElement
().
openStream
());
String
ver
=
manifest
.
getMainAttributes
().
getValue
(
"jadx-version"
);
if
(
ver
!=
null
)
{
return
ver
;
}
}
}
}
catch
(
IO
Exception
e
)
{
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Can't get manifest file"
,
e
);
}
return
"dev"
;
...
...
jadx-core/src/main/java/jadx/core/clsp/ClsSet.java
View file @
42eb3197
...
...
@@ -65,6 +65,9 @@ public class ClsSet {
for
(
ClassNode
cls
:
list
)
{
if
(
cls
.
getAccessFlags
().
isPublic
())
{
NClass
nClass
=
getCls
(
cls
.
getRawName
(),
names
);
if
(
nClass
==
null
)
{
throw
new
JadxRuntimeException
(
"Missing class: "
+
cls
);
}
nClass
.
setParents
(
makeParentsArray
(
cls
,
names
));
classes
[
k
]
=
nClass
;
k
++;
...
...
@@ -102,40 +105,47 @@ public class ClsSet {
Utils
.
makeDirsForFile
(
output
);
BufferedOutputStream
outputStream
=
new
BufferedOutputStream
(
new
FileOutputStream
(
output
));
String
outputName
=
output
.
getName
();
if
(
outputName
.
endsWith
(
CLST_EXTENSION
))
{
save
(
outputStream
);
}
else
if
(
outputName
.
endsWith
(
".jar"
))
{
ZipOutputStream
out
=
new
ZipOutputStream
(
outputStream
);
try
{
out
.
putNextEntry
(
new
ZipEntry
(
CLST_PKG_PATH
+
"/"
+
CLST_FILENAME
));
save
(
out
);
out
.
closeEntry
();
}
finally
{
out
.
close
();
outputStream
.
close
();
try
{
String
outputName
=
output
.
getName
();
if
(
outputName
.
endsWith
(
CLST_EXTENSION
))
{
save
(
outputStream
);
}
else
if
(
outputName
.
endsWith
(
".jar"
))
{
ZipOutputStream
out
=
new
ZipOutputStream
(
outputStream
);
try
{
out
.
putNextEntry
(
new
ZipEntry
(
CLST_PKG_PATH
+
"/"
+
CLST_FILENAME
));
save
(
out
);
out
.
closeEntry
();
}
finally
{
out
.
close
();
}
}
else
{
throw
new
JadxRuntimeException
(
"Unknown file format: "
+
outputName
);
}
}
else
{
throw
new
JadxRuntimeException
(
"Unknown file format: "
+
outputName
);
}
finally
{
outputStream
.
close
(
);
}
}
public
void
save
(
OutputStream
output
)
throws
IOException
{
DataOutputStream
out
=
new
DataOutputStream
(
output
);
out
.
writeBytes
(
JADX_CLS_SET_HEADER
);
out
.
writeByte
(
VERSION
);
LOG
.
info
(
"Classes count: "
+
classes
.
length
);
out
.
writeInt
(
classes
.
length
);
for
(
NClass
cls
:
classes
)
{
writeString
(
out
,
cls
.
getName
());
}
for
(
NClass
cls
:
classes
)
{
NClass
[]
parents
=
cls
.
getParents
();
out
.
writeByte
(
parents
.
length
);
for
(
NClass
parent
:
parents
)
{
out
.
writeInt
(
parent
.
getId
());
try
{
out
.
writeBytes
(
JADX_CLS_SET_HEADER
);
out
.
writeByte
(
VERSION
);
LOG
.
info
(
"Classes count: "
+
classes
.
length
);
out
.
writeInt
(
classes
.
length
);
for
(
NClass
cls
:
classes
)
{
writeString
(
out
,
cls
.
getName
());
}
for
(
NClass
cls
:
classes
)
{
NClass
[]
parents
=
cls
.
getParents
();
out
.
writeByte
(
parents
.
length
);
for
(
NClass
parent
:
parents
)
{
out
.
writeInt
(
parent
.
getId
());
}
}
}
finally
{
out
.
close
();
}
}
...
...
@@ -144,55 +154,67 @@ public class ClsSet {
if
(
input
==
null
)
{
throw
new
JadxRuntimeException
(
"Can't load classpath file: "
+
CLST_FILENAME
);
}
load
(
input
);
try
{
load
(
input
);
}
finally
{
input
.
close
();
}
}
public
void
load
(
File
input
)
throws
IOException
,
DecodeException
{
String
name
=
input
.
getName
();
InputStream
inputStream
=
new
FileInputStream
(
input
);
if
(
name
.
endsWith
(
CLST_EXTENSION
))
{
load
(
inputStream
);
}
else
if
(
name
.
endsWith
(
".jar"
))
{
ZipInputStream
in
=
new
ZipInputStream
(
inputStream
);
try
{
ZipEntry
entry
=
in
.
getNextEntry
();
while
(
entry
!=
null
)
{
if
(
entry
.
getName
().
endsWith
(
CLST_EXTENSION
))
{
load
(
in
);
try
{
if
(
name
.
endsWith
(
CLST_EXTENSION
))
{
load
(
inputStream
);
}
else
if
(
name
.
endsWith
(
".jar"
))
{
ZipInputStream
in
=
new
ZipInputStream
(
inputStream
);
try
{
ZipEntry
entry
=
in
.
getNextEntry
();
while
(
entry
!=
null
)
{
if
(
entry
.
getName
().
endsWith
(
CLST_EXTENSION
))
{
load
(
in
);
}
entry
=
in
.
getNextEntry
();
}
entry
=
in
.
getNextEntry
();
}
finally
{
in
.
close
();
}
}
finally
{
in
.
close
(
);
}
else
{
throw
new
JadxRuntimeException
(
"Unknown file format: "
+
name
);
}
}
else
{
throw
new
JadxRuntimeException
(
"Unknown file format: "
+
name
);
}
finally
{
inputStream
.
close
(
);
}
}
public
void
load
(
InputStream
input
)
throws
IOException
,
DecodeException
{
DataInputStream
in
=
new
DataInputStream
(
input
);
byte
[]
header
=
new
byte
[
JADX_CLS_SET_HEADER
.
length
()];
int
readHeaderLength
=
in
.
read
(
header
);
int
version
=
in
.
readByte
();
if
(
readHeaderLength
!=
JADX_CLS_SET_HEADER
.
length
()
||
!
JADX_CLS_SET_HEADER
.
equals
(
new
String
(
header
,
STRING_CHARSET
))
||
version
!=
VERSION
)
{
throw
new
DecodeException
(
"Wrong jadx class set header"
);
}
int
count
=
in
.
readInt
();
classes
=
new
NClass
[
count
];
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
String
name
=
readString
(
in
);
classes
[
i
]
=
new
NClass
(
name
,
i
);
}
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
int
pCount
=
in
.
readByte
();
NClass
[]
parents
=
new
NClass
[
pCount
];
for
(
int
j
=
0
;
j
<
pCount
;
j
++)
{
parents
[
j
]
=
classes
[
in
.
readInt
()];
try
{
byte
[]
header
=
new
byte
[
JADX_CLS_SET_HEADER
.
length
()];
int
readHeaderLength
=
in
.
read
(
header
);
int
version
=
in
.
readByte
();
if
(
readHeaderLength
!=
JADX_CLS_SET_HEADER
.
length
()
||
!
JADX_CLS_SET_HEADER
.
equals
(
new
String
(
header
,
STRING_CHARSET
))
||
version
!=
VERSION
)
{
throw
new
DecodeException
(
"Wrong jadx class set header"
);
}
int
count
=
in
.
readInt
();
classes
=
new
NClass
[
count
];
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
String
name
=
readString
(
in
);
classes
[
i
]
=
new
NClass
(
name
,
i
);
}
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
int
pCount
=
in
.
readByte
();
NClass
[]
parents
=
new
NClass
[
pCount
];
for
(
int
j
=
0
;
j
<
pCount
;
j
++)
{
parents
[
j
]
=
classes
[
in
.
readInt
()];
}
classes
[
i
].
setParents
(
parents
);
}
classes
[
i
].
setParents
(
parents
);
}
finally
{
in
.
close
();
}
}
...
...
jadx-core/src/main/java/jadx/core/clsp/ConvertToClsSet.java
View file @
42eb3197
...
...
@@ -54,6 +54,9 @@ public class ConvertToClsSet {
private
static
void
addFilesFromDirectory
(
File
dir
,
List
<
InputFile
>
inputFiles
)
throws
IOException
,
DecodeException
{
File
[]
files
=
dir
.
listFiles
();
if
(
files
==
null
)
{
return
;
}
for
(
File
file
:
files
)
{
if
(
file
.
isDirectory
())
{
addFilesFromDirectory
(
file
,
inputFiles
);
...
...
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
View file @
42eb3197
...
...
@@ -555,10 +555,12 @@ public class InsnGen {
}
cls
.
getAttributes
().
add
(
AttributeFlag
.
DONT_GENERATE
);
MethodNode
defCtr
=
cls
.
getDefaultConstructor
();
if
(
RegionUtils
.
notEmpty
(
defCtr
.
getRegion
()))
{
defCtr
.
getAttributes
().
add
(
AttributeFlag
.
ANONYMOUS_CONSTRUCTOR
);
}
else
{
defCtr
.
getAttributes
().
add
(
AttributeFlag
.
DONT_GENERATE
);
if
(
defCtr
!=
null
)
{
if
(
RegionUtils
.
notEmpty
(
defCtr
.
getRegion
()))
{
defCtr
.
getAttributes
().
add
(
AttributeFlag
.
ANONYMOUS_CONSTRUCTOR
);
}
else
{
defCtr
.
getAttributes
().
add
(
AttributeFlag
.
DONT_GENERATE
);
}
}
code
.
add
(
"new "
).
add
(
parent
==
null
?
"Object"
:
useClass
(
parent
)).
add
(
"() "
);
new
ClassGen
(
cls
,
mgen
.
getClassGen
().
getParentGen
(),
fallback
).
addClassBody
(
code
);
...
...
jadx-core/src/main/java/jadx/core/codegen/MethodGen.java
View file @
42eb3197
...
...
@@ -312,6 +312,7 @@ public class MethodGen {
}
}
}
catch
(
CodegenException
e
)
{
LOG
.
debug
(
"Error generate fallback instruction: "
,
e
.
getCause
());
code
.
startLine
(
"// error: "
+
insn
);
}
}
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/ArithNode.java
View file @
42eb3197
...
...
@@ -62,6 +62,23 @@ public class ArithNode extends InsnNode {
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
ArithNode
)
||
!
super
.
equals
(
obj
))
{
return
false
;
}
ArithNode
that
=
(
ArithNode
)
obj
;
return
op
==
that
.
op
;
}
@Override
public
int
hashCode
()
{
return
31
*
super
.
hashCode
()
+
op
.
hashCode
();
}
@Override
public
String
toString
()
{
return
InsnUtils
.
formatOffset
(
offset
)
+
": "
+
InsnUtils
.
insnTypeToString
(
insnType
)
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/ConstClassNode.java
View file @
42eb3197
...
...
@@ -3,7 +3,7 @@ package jadx.core.dex.instructions;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.nodes.InsnNode
;
public
class
ConstClassNode
extends
InsnNode
{
public
final
class
ConstClassNode
extends
InsnNode
{
private
final
ArgType
clsType
;
...
...
@@ -17,6 +17,23 @@ public class ConstClassNode extends InsnNode {
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
ConstClassNode
)
||
!
super
.
equals
(
obj
))
{
return
false
;
}
ConstClassNode
that
=
(
ConstClassNode
)
obj
;
return
clsType
.
equals
(
that
.
clsType
);
}
@Override
public
int
hashCode
()
{
return
31
*
super
.
hashCode
()
+
clsType
.
hashCode
();
}
@Override
public
String
toString
()
{
return
super
.
toString
()
+
" "
+
clsType
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/ConstStringNode.java
View file @
42eb3197
...
...
@@ -2,7 +2,7 @@ package jadx.core.dex.instructions;
import
jadx.core.dex.nodes.InsnNode
;
public
class
ConstStringNode
extends
InsnNode
{
public
final
class
ConstStringNode
extends
InsnNode
{
private
final
String
str
;
...
...
@@ -16,6 +16,23 @@ public class ConstStringNode extends InsnNode {
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
ConstStringNode
)
||
!
super
.
equals
(
obj
))
{
return
false
;
}
ConstStringNode
that
=
(
ConstStringNode
)
obj
;
return
str
.
equals
(
that
.
str
);
}
@Override
public
int
hashCode
()
{
return
31
*
super
.
hashCode
()
+
str
.
hashCode
();
}
@Override
public
String
toString
()
{
return
super
.
toString
()
+
" \""
+
str
+
"\""
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/FillArrayNode.java
View file @
42eb3197
...
...
@@ -8,7 +8,7 @@ import jadx.core.utils.exceptions.JadxRuntimeException;
import
com.android.dx.io.instructions.FillArrayDataPayloadDecodedInstruction
;
public
class
FillArrayNode
extends
InsnNode
{
public
final
class
FillArrayNode
extends
InsnNode
{
private
final
Object
data
;
private
ArgType
elemType
;
...
...
@@ -53,4 +53,21 @@ public class FillArrayNode extends InsnNode {
elemType
=
r
;
}
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
FillArrayNode
)
||
!
super
.
equals
(
obj
))
{
return
false
;
}
FillArrayNode
that
=
(
FillArrayNode
)
obj
;
return
elemType
.
equals
(
that
.
elemType
)
&&
data
==
that
.
data
;
}
@Override
public
int
hashCode
()
{
return
31
*
super
.
hashCode
()
+
elemType
.
hashCode
()
+
data
.
hashCode
();
}
}
jadx-core/src/main/java/jadx/core/dex/instructions/GotoNode.java
View file @
42eb3197
...
...
@@ -21,6 +21,23 @@ public class GotoNode extends InsnNode {
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
GotoNode
)
||
!
super
.
equals
(
obj
))
{
return
false
;
}
GotoNode
gotoNode
=
(
GotoNode
)
obj
;
return
target
==
gotoNode
.
target
;
}
@Override
public
int
hashCode
()
{
return
31
*
super
.
hashCode
()
+
target
;
}
@Override
public
String
toString
()
{
return
super
.
toString
()
+
"-> "
+
InsnUtils
.
formatOffset
(
target
);
}
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/IfNode.java
View file @
42eb3197
...
...
@@ -71,6 +71,23 @@ public class IfNode extends GotoNode {
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
IfNode
)
||
!
super
.
equals
(
obj
))
{
return
false
;
}
IfNode
ifNode
=
(
IfNode
)
obj
;
return
op
==
ifNode
.
op
;
}
@Override
public
int
hashCode
()
{
return
31
*
super
.
hashCode
()
+
op
.
hashCode
();
}
@Override
public
String
toString
()
{
return
InsnUtils
.
formatOffset
(
offset
)
+
": "
+
InsnUtils
.
insnTypeToString
(
insnType
)
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/IndexInsnNode.java
View file @
42eb3197
...
...
@@ -17,6 +17,23 @@ public class IndexInsnNode extends InsnNode {
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
IndexInsnNode
)
||
!
super
.
equals
(
obj
))
{
return
false
;
}
IndexInsnNode
that
=
(
IndexInsnNode
)
obj
;
return
index
==
null
?
that
.
index
==
null
:
index
.
equals
(
that
.
index
);
}
@Override
public
int
hashCode
()
{
return
31
*
super
.
hashCode
()
+
(
index
!=
null
?
index
.
hashCode
()
:
0
);
}
@Override
public
String
toString
()
{
return
super
.
toString
()
+
" "
+
InsnUtils
.
indexToString
(
index
);
}
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/InvokeNode.java
View file @
42eb3197
...
...
@@ -45,6 +45,26 @@ public class InvokeNode extends InsnNode {
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
InvokeNode
)
||
!
super
.
equals
(
obj
))
{
return
false
;
}
InvokeNode
that
=
(
InvokeNode
)
obj
;
return
type
==
that
.
type
&&
mth
.
equals
(
that
.
mth
);
}
@Override
public
int
hashCode
()
{
int
result
=
super
.
hashCode
();
result
=
31
*
result
+
type
.
hashCode
();
result
=
31
*
result
+
mth
.
hashCode
();
return
result
;
}
@Override
public
String
toString
()
{
return
InsnUtils
.
formatOffset
(
offset
)
+
": "
+
InsnUtils
.
insnTypeToString
(
insnType
)
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/SwitchNode.java
View file @
42eb3197
...
...
@@ -37,6 +37,29 @@ public class SwitchNode extends InsnNode {
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
SwitchNode
)
||
!
super
.
equals
(
obj
))
{
return
false
;
}
SwitchNode
that
=
(
SwitchNode
)
obj
;
return
def
==
that
.
def
&&
Arrays
.
equals
(
keys
,
that
.
keys
)
&&
Arrays
.
equals
(
targets
,
that
.
targets
);
}
@Override
public
int
hashCode
()
{
int
result
=
super
.
hashCode
();
result
=
31
*
result
+
Arrays
.
hashCode
(
keys
);
result
=
31
*
result
+
Arrays
.
hashCode
(
targets
);
result
=
31
*
result
+
def
;
return
result
;
}
@Override
public
String
toString
()
{
StringBuilder
targ
=
new
StringBuilder
();
targ
.
append
(
'['
);
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/args/FieldArg.java
View file @
42eb3197
...
...
@@ -43,6 +43,32 @@ public final class FieldArg extends RegisterArg {
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
FieldArg
)
||
!
super
.
equals
(
obj
))
{
return
false
;
}
FieldArg
fieldArg
=
(
FieldArg
)
obj
;
if
(!
field
.
equals
(
fieldArg
.
field
))
{
return
false
;
}
if
(
regArg
!=
null
?
!
regArg
.
equals
(
fieldArg
.
regArg
)
:
fieldArg
.
regArg
!=
null
)
{
return
false
;
}
return
true
;
}
@Override
public
int
hashCode
()
{
int
result
=
super
.
hashCode
();
result
=
31
*
result
+
field
.
hashCode
();
result
=
31
*
result
+
(
regArg
!=
null
?
regArg
.
hashCode
()
:
0
);
return
result
;
}
@Override
public
String
toString
()
{
return
"("
+
field
+
")"
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java
View file @
42eb3197
...
...
@@ -126,6 +126,9 @@ public class RegisterArg extends InsnArg implements Named {
}
public
InsnNode
getAssignInsn
()
{
if
(
sVar
==
null
)
{
return
null
;
}
RegisterArg
assign
=
sVar
.
getAssign
();
if
(
assign
!=
null
)
{
return
assign
.
getParentInsn
();
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/mods/ConstructorInsn.java
View file @
42eb3197
...
...
@@ -76,6 +76,29 @@ public class ConstructorInsn extends InsnNode {
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
{
return
true
;
}
if
(!(
o
instanceof
ConstructorInsn
)
||
!
super
.
equals
(
o
))
{
return
false
;
}
ConstructorInsn
that
=
(
ConstructorInsn
)
o
;
return
callMth
.
equals
(
that
.
callMth
)
&&
callType
==
that
.
callType
&&
instanceArg
.
equals
(
that
.
instanceArg
);
}
@Override
public
int
hashCode
()
{
int
result
=
super
.
hashCode
();
result
=
31
*
result
+
callMth
.
hashCode
();
result
=
31
*
result
+
callType
.
hashCode
();
result
=
31
*
result
+
instanceArg
.
hashCode
();
return
result
;
}
@Override
public
String
toString
()
{
return
super
.
toString
()
+
" "
+
callMth
+
" "
+
callType
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/instructions/mods/TernaryInsn.java
View file @
42eb3197
...
...
@@ -34,6 +34,23 @@ public class TernaryInsn extends InsnNode {
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
TernaryInsn
)
||
!
super
.
equals
(
obj
))
{
return
false
;
}
TernaryInsn
that
=
(
TernaryInsn
)
obj
;
return
condition
.
equals
(
that
.
condition
);
}
@Override
public
int
hashCode
()
{
return
31
*
super
.
hashCode
()
+
condition
.
hashCode
();
}
@Override
public
String
toString
()
{
return
InsnUtils
.
formatOffset
(
offset
)
+
": TERNARY"
+
getResult
()
+
" = "
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/BlockNode.java
View file @
42eb3197
...
...
@@ -61,9 +61,17 @@ public class BlockNode extends AttrNode implements IBlock {
}
public
void
lock
()
{
cleanSuccessors
=
Collections
.
unmodifiableList
(
cleanSuccessors
);
successors
=
Collections
.
unmodifiableList
(
successors
);
predecessors
=
Collections
.
unmodifiableList
(
predecessors
);
cleanSuccessors
=
lockList
(
cleanSuccessors
);
successors
=
lockList
(
successors
);
predecessors
=
lockList
(
predecessors
);
dominatesOn
=
lockList
(
dominatesOn
);
}
List
<
BlockNode
>
lockList
(
List
<
BlockNode
>
list
)
{
if
(
list
.
isEmpty
())
{
return
Collections
.
emptyList
();
}
return
Collections
.
unmodifiableList
(
list
);
}
/**
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/parser/LocalVar.java
View file @
42eb3197
...
...
@@ -86,6 +86,16 @@ final class LocalVar extends RegisterArg {
}
@Override
public
boolean
equals
(
Object
obj
)
{
return
super
.
equals
(
obj
);
}
@Override
public
int
hashCode
()
{
return
super
.
hashCode
();
}
@Override
public
String
toString
()
{
return
super
.
toString
()
+
" "
+
(
isEnd
?
"end: "
+
InsnUtils
.
formatOffset
(
startAddr
)
+
"-"
+
InsnUtils
.
formatOffset
(
endAddr
)
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java
View file @
42eb3197
...
...
@@ -13,7 +13,12 @@ import java.util.LinkedList;
import
java.util.List
;
import
java.util.Map
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
public
class
SignatureParser
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
SignatureParser
.
class
);
private
static
final
char
STOP_CHAR
=
0
;
private
final
String
sign
;
...
...
@@ -217,6 +222,10 @@ public class SignatureParser {
break
;
}
String
id
=
consumeUntil
(
':'
);
if
(
id
==
null
)
{
LOG
.
error
(
"Can't parse generic map: {}"
,
sign
);
return
Collections
.
emptyMap
();
}
tryConsume
(
':'
);
List
<
ArgType
>
types
=
consumeExtendsTypesList
();
map
.
put
(
ArgType
.
genericType
(
id
),
types
);
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/ClassModifier.java
View file @
42eb3197
...
...
@@ -73,7 +73,7 @@ public class ClassModifier extends AbstractVisitor {
}
private
static
boolean
removeFieldUsageFromConstructor
(
MethodNode
mth
,
FieldNode
field
,
ClassNode
fieldsCls
)
{
if
(!
mth
.
getAccessFlags
().
isConstructor
())
{
if
(
mth
.
isNoCode
()
||
!
mth
.
getAccessFlags
().
isConstructor
())
{
return
false
;
}
List
<
RegisterArg
>
args
=
mth
.
getArguments
(
false
);
...
...
@@ -114,6 +114,9 @@ public class ClassModifier extends AbstractVisitor {
private
static
void
removeSyntheticMethods
(
ClassNode
cls
)
{
for
(
MethodNode
mth
:
cls
.
getMethods
())
{
if
(
mth
.
isNoCode
())
{
continue
;
}
AccessInfo
af
=
mth
.
getAccessFlags
();
// remove bridge methods
if
(
af
.
isBridge
()
&&
af
.
isSynthetic
()
&&
!
isMethodUniq
(
cls
,
mth
))
{
...
...
jadx-core/src/main/java/jadx/core/utils/Utils.java
View file @
42eb3197
...
...
@@ -97,7 +97,7 @@ public class Utils {
public
static
void
makeDirsForFile
(
File
file
)
{
File
dir
=
file
.
getParentFile
();
if
(!
dir
.
exists
())
{
if
(
dir
!=
null
&&
!
dir
.
exists
())
{
// if directory already created in other thread mkdirs will return false,
// so check dir existence again
if
(!
dir
.
mkdirs
()
&&
!
dir
.
exists
())
{
...
...
jadx-core/src/main/java/jadx/core/utils/files/InputFile.java
View file @
42eb3197
...
...
@@ -2,6 +2,7 @@ package jadx.core.utils.files;
import
jadx.core.utils.exceptions.DecodeException
;
import
jadx.core.utils.exceptions.JadxException
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
java.io.ByteArrayOutputStream
;
import
java.io.File
;
...
...
@@ -56,17 +57,23 @@ public class InputFile {
private
byte
[]
openDexFromApk
(
File
file
)
throws
IOException
{
ZipFile
zf
=
new
ZipFile
(
file
);
ZipEntry
dex
=
zf
.
getEntry
(
"classes.dex"
);
if
(
dex
==
null
)
{
zf
.
close
();
throw
new
JadxRuntimeException
(
"File 'classes.dex' not found in apk file: "
+
file
);
}
ByteArrayOutputStream
bytesOut
=
new
ByteArrayOutputStream
();
InputStream
in
=
null
;
try
{
InputStream
in
=
zf
.
getInputStream
(
dex
);
in
=
zf
.
getInputStream
(
dex
);
byte
[]
buffer
=
new
byte
[
8192
];
int
count
;
while
((
count
=
in
.
read
(
buffer
))
!=
-
1
)
{
bytesOut
.
write
(
buffer
,
0
,
count
);
}
in
.
close
();
}
finally
{
if
(
in
!=
null
)
{
in
.
close
();
}
zf
.
close
();
}
return
bytesOut
.
toByteArray
();
...
...
jadx-core/src/main/java/jadx/core/utils/files/JavaToDex.java
View file @
42eb3197
...
...
@@ -4,6 +4,7 @@ import jadx.core.utils.exceptions.JadxException;
import
java.io.ByteArrayOutputStream
;
import
java.io.PrintStream
;
import
java.io.UnsupportedEncodingException
;
import
com.android.dx.command.DxConsole
;
import
com.android.dx.command.dexer.Main
;
...
...
@@ -11,6 +12,8 @@ import com.android.dx.command.dexer.Main.Arguments;
public
class
JavaToDex
{
private
static
final
String
CHARSET_NAME
=
"UTF-8"
;
public
static
class
DxArgs
extends
Arguments
{
public
DxArgs
(
String
dexFile
,
String
[]
input
)
{
outName
=
dexFile
;
...
...
@@ -27,12 +30,15 @@ public class JavaToDex {
public
byte
[]
convert
(
String
javaFile
)
throws
JadxException
{
ByteArrayOutputStream
errOut
=
new
ByteArrayOutputStream
();
DxConsole
.
err
=
new
PrintStream
(
errOut
);
try
{
DxConsole
.
err
=
new
PrintStream
(
errOut
,
true
,
CHARSET_NAME
);
}
catch
(
UnsupportedEncodingException
e
)
{
throw
new
JadxException
(
e
.
getMessage
(),
e
);
}
PrintStream
oldOut
=
System
.
out
;
ByteArrayOutputStream
baos
=
new
ByteArrayOutputStream
();
try
{
System
.
setOut
(
new
PrintStream
(
baos
));
System
.
setOut
(
new
PrintStream
(
baos
,
true
,
CHARSET_NAME
));
DxArgs
args
=
new
DxArgs
(
"-"
,
new
String
[]{
javaFile
});
Main
.
run
(
args
);
baos
.
close
();
...
...
@@ -41,8 +47,12 @@ public class JavaToDex {
}
finally
{
System
.
setOut
(
oldOut
);
}
// errOut also contains warnings
dxErrors
=
errOut
.
toString
();
try
{
// errOut also contains warnings
dxErrors
=
errOut
.
toString
(
CHARSET_NAME
);
}
catch
(
UnsupportedEncodingException
e
)
{
throw
new
JadxException
(
"Can't save error output"
,
e
);
}
return
baos
.
toByteArray
();
}
...
...
jadx-core/src/test/groovy/jadx/tests/TestSignatureParser.groovy
View file @
42eb3197
package
jadx.tests
import
jadx.core.dex.instructions.args.ArgType
import
jadx.core.dex.nodes.parser.SignatureParser
import
spock.lang.Specification
...
...
@@ -84,4 +83,12 @@ class TestSignatureParser extends Specification {
argTypes
.
size
()
==
1
argTypes
.
get
(
0
)
==
generic
(
"Ljava/util/List;"
,
wildcard
())
}
def
"generic map: bad signature"
()
{
when:
def
map
=
new
SignatureParser
(
"<A:Ljava/lang/Object;B"
).
consumeGenericMap
()
then:
notThrown
(
NullPointerException
)
map
.
isEmpty
()
}
}
jadx-gui/src/main/java/jadx/gui/JadxGUI.java
View file @
42eb3197
...
...
@@ -15,7 +15,10 @@ public class JadxGUI {
public
static
void
main
(
String
[]
args
)
{
try
{
final
JadxCLIArgs
jadxArgs
=
new
JadxCLIArgs
(
args
);
final
JadxCLIArgs
jadxArgs
=
new
JadxCLIArgs
();
if
(!
jadxArgs
.
processArgs
(
args
))
{
return
;
}
UIManager
.
setLookAndFeel
(
UIManager
.
getSystemLookAndFeelClassName
());
SwingUtilities
.
invokeLater
(
new
Runnable
()
{
public
void
run
()
{
...
...
@@ -25,7 +28,7 @@ public class JadxGUI {
window
.
setLocationAndPosition
();
window
.
setVisible
(
true
);
window
.
setLocationRelativeTo
(
null
);
window
.
setDefaultCloseOperation
(
WindowConstants
.
EXIT
_ON_CLOSE
);
window
.
setDefaultCloseOperation
(
WindowConstants
.
DISPOSE
_ON_CLOSE
);
if
(
jadxArgs
.
getInput
().
isEmpty
())
{
window
.
openFile
();
...
...
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
View file @
42eb3197
...
...
@@ -135,7 +135,10 @@ public class MainWindow extends JFrame {
}
private
void
toggleSearch
()
{
tabbedPane
.
getSelectedCodePanel
().
getSearchBar
().
toggle
();
CodePanel
codePanel
=
tabbedPane
.
getSelectedCodePanel
();
if
(
codePanel
!=
null
)
{
codePanel
.
getSearchBar
().
toggle
();
}
}
private
void
initMenuAndToolbar
()
{
...
...
@@ -148,7 +151,7 @@ public class MainWindow extends JFrame {
exit
.
setMnemonic
(
KeyEvent
.
VK_E
);
exit
.
addActionListener
(
new
ActionListener
()
{
public
void
actionPerformed
(
ActionEvent
event
)
{
System
.
exit
(
0
);
dispose
(
);
}
});
...
...
jadx-gui/src/main/java/jadx/gui/ui/SearchBar.java
View file @
42eb3197
...
...
@@ -145,8 +145,10 @@ class SearchBar extends JToolBar {
}
private
void
search
(
int
direction
)
{
String
text
=
searchField
.
getText
();
if
(
text
.
length
()
==
0
)
{
String
searchText
=
searchField
.
getText
();
if
(
searchText
==
null
||
searchText
.
length
()
==
0
||
rTextArea
.
getText
()
==
null
)
{
return
;
}
...
...
@@ -156,20 +158,20 @@ class SearchBar extends JToolBar {
boolean
wholeWord
=
wholeWordCB
.
isSelected
();
if
(
markAllCB
.
isSelected
())
{
rTextArea
.
markAll
(
t
ext
,
matchCase
,
wholeWord
,
regex
);
rTextArea
.
markAll
(
searchT
ext
,
matchCase
,
wholeWord
,
regex
);
}
else
{
rTextArea
.
clearMarkAllHighlights
();
}
SearchContext
context
=
new
SearchContext
();
context
.
setSearchFor
(
t
ext
);
context
.
setSearchFor
(
searchT
ext
);
context
.
setMatchCase
(
matchCase
);
context
.
setRegularExpression
(
regex
);
context
.
setSearchForward
(
forward
);
context
.
setWholeWord
(
wholeWord
);
// TODO hack: move cursor before previous search for not jump to next occurrence
if
(
direction
==
0
&&
!
searchField
.
getBackground
().
equals
(
COLOR_BG_ERROR
))
{
if
(
direction
==
0
&&
!
COLOR_BG_ERROR
.
equals
(
searchField
.
getBackground
()
))
{
try
{
int
caretPos
=
rTextArea
.
getCaretPosition
();
int
lineNum
=
rTextArea
.
getLineOfOffset
(
caretPos
)
-
1
;
...
...
@@ -183,7 +185,7 @@ class SearchBar extends JToolBar {
boolean
found
=
SearchEngine
.
find
(
rTextArea
,
context
);
if
(!
found
)
{
int
pos
=
SearchEngine
.
getNextMatchPos
(
t
ext
,
rTextArea
.
getText
(),
forward
,
matchCase
,
wholeWord
);
int
pos
=
SearchEngine
.
getNextMatchPos
(
searchT
ext
,
rTextArea
.
getText
(),
forward
,
matchCase
,
wholeWord
);
if
(
pos
!=
-
1
)
{
rTextArea
.
setCaretPosition
(
forward
?
0
:
rTextArea
.
getDocument
().
getLength
()
-
1
);
search
(
direction
);
...
...
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