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
f6f883b9
Commit
f6f883b9
authored
Sep 08, 2018
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: change resource fields generations in R class (#308)
parent
5de4d079
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
145 additions
and
92 deletions
+145
-92
ClassGen.java
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
+8
-6
AType.java
jadx-core/src/main/java/jadx/core/dex/attributes/AType.java
+1
-0
ConstStorage.java
jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java
+32
-7
ClassNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
+10
-11
DexNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java
+6
-3
ResRefField.java
jadx-core/src/main/java/jadx/core/dex/nodes/ResRefField.java
+0
-15
RootNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
+5
-2
EnumVisitor.java
...ore/src/main/java/jadx/core/dex/visitors/EnumVisitor.java
+1
-1
CodegenUtils.java
jadx-core/src/main/java/jadx/core/utils/CodegenUtils.java
+14
-0
ErrorsCounter.java
jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java
+2
-2
AndroidResourcesUtils.java
...n/java/jadx/core/utils/android/AndroidResourcesUtils.java
+48
-39
IntegrationTest.java
jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java
+17
-2
TestRFieldRestore2.java
...java/jadx/tests/integration/inner/TestRFieldRestore2.java
+1
-4
No files found.
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
View file @
f6f883b9
...
...
@@ -34,6 +34,7 @@ import jadx.core.dex.nodes.InsnNode;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.nodes.parser.FieldInitAttr
;
import
jadx.core.dex.nodes.parser.FieldInitAttr.InitType
;
import
jadx.core.utils.CodegenUtils
;
import
jadx.core.utils.ErrorsCounter
;
import
jadx.core.utils.Utils
;
import
jadx.core.utils.exceptions.CodegenException
;
...
...
@@ -105,9 +106,8 @@ public class ClassGen {
if
(
cls
.
contains
(
AFlag
.
DONT_GENERATE
))
{
return
;
}
if
(
cls
.
contains
(
AFlag
.
INCONSISTENT_CODE
))
{
code
.
startLine
(
"// jadx: inconsistent code"
);
}
CodegenUtils
.
addComments
(
code
,
cls
);
insertDecompilationProblems
(
code
,
cls
);
addClassDeclaration
(
code
);
addClassBody
(
code
);
}
...
...
@@ -296,6 +296,7 @@ public class ClassGen {
}
code
.
add
(
';'
);
}
else
{
CodegenUtils
.
addComments
(
code
,
mth
);
insertDecompilationProblems
(
code
,
mth
);
boolean
badCode
=
mth
.
contains
(
AFlag
.
INCONSISTENT_CODE
);
if
(
badCode
&&
showInconsistentCode
)
{
...
...
@@ -325,9 +326,9 @@ public class ClassGen {
}
}
private
void
insertDecompilationProblems
(
CodeWriter
code
,
MethodNode
mth
)
{
List
<
JadxError
>
errors
=
mth
.
getAll
(
AType
.
JADX_ERROR
);
List
<
JadxWarn
>
warns
=
mth
.
getAll
(
AType
.
JADX_WARN
);
private
void
insertDecompilationProblems
(
CodeWriter
code
,
AttrNode
node
)
{
List
<
JadxError
>
errors
=
node
.
getAll
(
AType
.
JADX_ERROR
);
List
<
JadxWarn
>
warns
=
node
.
getAll
(
AType
.
JADX_WARN
);
if
(!
errors
.
isEmpty
())
{
errors
.
forEach
(
err
->
{
code
.
startLine
(
"/* JADX ERROR: "
).
add
(
err
.
getError
());
...
...
@@ -351,6 +352,7 @@ public class ClassGen {
if
(
f
.
contains
(
AFlag
.
DONT_GENERATE
))
{
continue
;
}
CodegenUtils
.
addComments
(
code
,
f
);
annotationGen
.
addForField
(
code
,
f
);
if
(
f
.
getFieldInfo
().
isRenamed
())
{
...
...
jadx-core/src/main/java/jadx/core/dex/attributes/AType.java
View file @
f6f883b9
...
...
@@ -36,6 +36,7 @@ public class AType<T extends IAttribute> {
public
static
final
AType
<
AttrList
<
JadxError
>>
JADX_ERROR
=
new
AType
<>();
public
static
final
AType
<
AttrList
<
JadxWarn
>>
JADX_WARN
=
new
AType
<>();
public
static
final
AType
<
AttrList
<
String
>>
COMMENTS
=
new
AType
<>();
public
static
final
AType
<
ExcHandlerAttr
>
EXC_HANDLER
=
new
AType
<>();
public
static
final
AType
<
CatchAttr
>
CATCH_BLOCK
=
new
AType
<>();
...
...
jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java
View file @
f6f883b9
...
...
@@ -15,8 +15,8 @@ import jadx.core.dex.instructions.args.PrimitiveType;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.DexNode
;
import
jadx.core.dex.nodes.FieldNode
;
import
jadx.core.dex.nodes.ResRefField
;
import
jadx.core.dex.nodes.parser.FieldInitAttr
;
import
jadx.core.utils.ErrorsCounter
;
public
class
ConstStorage
{
...
...
@@ -101,15 +101,15 @@ public class ConstStorage {
@Nullable
public
FieldNode
getConstField
(
ClassNode
cls
,
Object
value
,
boolean
searchGlobal
)
{
if
(!
replaceEnabled
)
{
return
null
;
}
DexNode
dex
=
cls
.
dex
();
if
(
value
instanceof
Integer
)
{
String
str
=
resourcesNames
.
get
(
value
);
if
(
str
!=
null
)
{
return
new
ResRefField
(
dex
,
str
.
replace
(
'/'
,
'.'
));
}
FieldNode
rField
=
getResourceField
((
Integer
)
value
,
dex
);
if
(
rField
!=
null
)
{
return
rField
;
}
if
(!
replaceEnabled
)
{
return
null
;
}
boolean
foundInGlobal
=
globalValues
.
contains
(
value
);
if
(
foundInGlobal
&&
!
searchGlobal
)
{
...
...
@@ -140,6 +140,31 @@ public class ConstStorage {
}
@Nullable
private
FieldNode
getResourceField
(
Integer
value
,
DexNode
dex
)
{
String
str
=
resourcesNames
.
get
(
value
);
if
(
str
==
null
)
{
return
null
;
}
ClassNode
appResClass
=
dex
.
root
().
getAppResClass
();
if
(
appResClass
==
null
)
{
return
null
;
}
String
[]
parts
=
str
.
split
(
"/"
,
2
);
if
(
parts
.
length
!=
2
)
{
return
null
;
}
String
typeName
=
parts
[
0
];
String
fieldName
=
parts
[
1
];
for
(
ClassNode
innerClass
:
appResClass
.
getInnerClasses
())
{
if
(
innerClass
.
getShortName
().
equals
(
typeName
))
{
return
innerClass
.
searchFieldByName
(
fieldName
);
}
}
ErrorsCounter
.
classWarn
(
appResClass
,
"Not found resource field with id: "
+
value
+
", name: "
+
str
.
replace
(
'/'
,
'.'
));
return
null
;
}
@Nullable
public
FieldNode
getConstFieldByLiteralArg
(
ClassNode
cls
,
LiteralArg
arg
)
{
PrimitiveType
type
=
arg
.
getType
().
getPrimitiveType
();
if
(
type
==
null
)
{
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java
View file @
f6f883b9
...
...
@@ -13,7 +13,6 @@ import com.android.dex.ClassData.Field;
import
com.android.dex.ClassData.Method
;
import
com.android.dex.ClassDef
;
import
com.android.dex.Dex
;
import
com.android.dx.rop.code.AccessFlags
;
import
org.jetbrains.annotations.Nullable
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -51,7 +50,7 @@ public class ClassNode extends LineAttrNode implements ILoadable, IDexNode {
private
final
List
<
MethodNode
>
methods
;
private
final
List
<
FieldNode
>
fields
;
private
List
<
ClassNode
>
innerClasses
=
Collections
.
emptyList
();
private
List
<
ClassNode
>
innerClasses
=
new
ArrayList
<>
();
// store decompiled code
private
CodeWriter
code
;
...
...
@@ -132,14 +131,16 @@ public class ClassNode extends LineAttrNode implements ILoadable, IDexNode {
}
// empty synthetic class
public
ClassNode
(
DexNode
dex
,
ClassInfo
clsInfo
)
{
public
ClassNode
(
DexNode
dex
,
String
name
,
int
accessFlags
)
{
this
.
dex
=
dex
;
this
.
clsInfo
=
clsInfo
;
this
.
interfaces
=
Collections
.
emptyList
();
this
.
methods
=
Collections
.
emptyList
();
this
.
fields
=
Collections
.
emptyList
();
this
.
accessFlags
=
new
AccessInfo
(
AccessFlags
.
ACC_PUBLIC
|
AccessFlags
.
ACC_SYNTHETIC
,
AFType
.
CLASS
);
this
.
clsInfo
=
ClassInfo
.
fromName
(
dex
.
root
(),
name
)
;
this
.
interfaces
=
new
ArrayList
<>
();
this
.
methods
=
new
ArrayList
<>
();
this
.
fields
=
new
ArrayList
<>
();
this
.
accessFlags
=
new
AccessInfo
(
accessFlags
,
AFType
.
CLASS
);
this
.
parentClass
=
this
;
dex
.
addClassNode
(
this
);
}
private
void
loadAnnotations
(
ClassDef
cls
)
{
...
...
@@ -368,10 +369,8 @@ public class ClassNode extends LineAttrNode implements ILoadable, IDexNode {
}
public
void
addInnerClass
(
ClassNode
cls
)
{
if
(
innerClasses
.
isEmpty
())
{
innerClasses
=
new
ArrayList
<>(
3
);
}
innerClasses
.
add
(
cls
);
cls
.
parentClass
=
this
;
}
public
boolean
isEnum
()
{
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java
View file @
f6f883b9
...
...
@@ -46,11 +46,14 @@ public class DexNode implements IDexNode {
public
void
loadClasses
()
{
for
(
ClassDef
cls
:
dexBuf
.
classDefs
())
{
ClassNode
clsNode
=
new
ClassNode
(
this
,
cls
);
addClassNode
(
new
ClassNode
(
this
,
cls
));
}
}
public
void
addClassNode
(
ClassNode
clsNode
)
{
classes
.
add
(
clsNode
);
clsMap
.
put
(
clsNode
.
getClassInfo
(),
clsNode
);
}
}
void
initInnerClasses
()
{
// move inner classes
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/ResRefField.java
deleted
100644 → 0
View file @
5de4d079
package
jadx
.
core
.
dex
.
nodes
;
import
com.android.dx.rop.code.AccessFlags
;
import
jadx.core.dex.info.FieldInfo
;
import
jadx.core.dex.instructions.args.ArgType
;
public
class
ResRefField
extends
FieldNode
{
public
ResRefField
(
DexNode
dex
,
String
str
)
{
super
(
dex
.
root
().
getAppResClass
(),
FieldInfo
.
from
(
dex
,
dex
.
root
().
getAppResClass
().
getClassInfo
(),
str
,
ArgType
.
INT
),
AccessFlags
.
ACC_PUBLIC
);
}
}
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
View file @
f6f883b9
...
...
@@ -37,11 +37,12 @@ public class RootNode {
private
final
ConstStorage
constValues
;
private
final
InfoStorage
infoStorage
=
new
InfoStorage
();
private
ClspGraph
clsp
;
private
List
<
DexNode
>
dexNodes
;
@Nullable
private
String
appPackage
;
@Nullable
private
ClassNode
appResClass
;
private
ClspGraph
clsp
;
public
RootNode
(
JadxArgs
args
)
{
this
.
args
=
args
;
...
...
@@ -90,8 +91,10 @@ public class RootNode {
LOG
.
error
(
"Failed to parse '.arsc' file"
,
e
);
return
;
}
processResources
(
parser
.
getResStorage
());
}
ResourceStorage
resStorage
=
parser
.
getResStorage
();
public
void
processResources
(
ResourceStorage
resStorage
)
{
constValues
.
setResourcesNames
(
resStorage
.
getResourcesNames
());
appPackage
=
resStorage
.
getAppPackage
();
appResClass
=
AndroidResourcesUtils
.
searchAppResClass
(
this
,
resStorage
);
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/EnumVisitor.java
View file @
f6f883b9
...
...
@@ -52,7 +52,7 @@ public class EnumVisitor extends AbstractVisitor {
}
}
if
(
staticMethod
==
null
)
{
ErrorsCounter
.
class
Error
(
cls
,
"Enum class init method not found"
);
ErrorsCounter
.
class
Warn
(
cls
,
"Enum class init method not found"
);
return
true
;
}
...
...
jadx-core/src/main/java/jadx/core/utils/CodegenUtils.java
0 → 100644
View file @
f6f883b9
package
jadx
.
core
.
utils
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.attributes.AttrNode
;
public
class
CodegenUtils
{
public
static
void
addComments
(
CodeWriter
code
,
AttrNode
node
)
{
for
(
String
comment
:
node
.
getAll
(
AType
.
COMMENTS
))
{
code
.
startLine
(
"/* "
).
add
(
comment
).
add
(
" */"
);
}
}
}
jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java
View file @
f6f883b9
...
...
@@ -74,8 +74,8 @@ public class ErrorsCounter {
return
cls
.
dex
().
root
().
getErrorsCounter
().
addError
(
cls
,
errorMsg
,
e
);
}
public
static
String
class
Error
(
ClassNode
cls
,
String
error
Msg
)
{
return
cl
assError
(
cls
,
errorMsg
,
null
);
public
static
String
class
Warn
(
ClassNode
cls
,
String
warn
Msg
)
{
return
cl
s
.
dex
().
root
().
getErrorsCounter
().
addWarning
(
cls
,
warnMsg
);
}
public
static
String
methodError
(
MethodNode
mth
,
String
errorMsg
,
Throwable
e
)
{
...
...
jadx-core/src/main/java/jadx/core/utils/android/AndroidResourcesUtils.java
View file @
f6f883b9
package
jadx
.
core
.
utils
.
android
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.
Set
;
import
java.util.
TreeMap
;
import
com.android.dx.rop.code.AccessFlags
;
import
org.jetbrains.annotations.Nullable
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.core.codegen.ClassGen
;
import
jadx.core.codegen.CodeWriter
;
import
jadx.core.dex.attributes.AType
;
import
jadx.core.dex.info.ClassInfo
;
import
jadx.core.dex.info.FieldInfo
;
import
jadx.core.dex.instructions.args.ArgType
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.DexNode
;
import
jadx.core.dex.nodes.FieldNode
;
import
jadx.core.dex.nodes.ProcessState
;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.dex.nodes.parser.FieldInitAttr
;
import
jadx.core.xmlgen.ResourceStorage
;
import
jadx.core.xmlgen.entry.ResourceEntry
;
...
...
@@ -28,22 +33,29 @@ public class AndroidResourcesUtils {
private
AndroidResourcesUtils
()
{
}
@Nullable
public
static
ClassNode
searchAppResClass
(
RootNode
root
,
ResourceStorage
resStorage
)
{
String
appPackage
=
root
.
getAppPackage
();
String
fullName
=
appPackage
!=
null
?
appPackage
+
".R"
:
"R"
;
ClassNode
resCls
=
root
.
searchClassByName
(
fullName
);
if
(
resCls
!=
null
)
{
addResourceFields
(
resCls
,
resStorage
,
true
);
return
resCls
;
}
LOG
.
info
(
"Can't find 'R' class in app package: {}"
,
appPackage
);
List
<
ClassNode
>
candidates
=
root
.
searchClassByShortName
(
"R"
);
if
(
candidates
.
size
()
==
1
)
{
return
candidates
.
get
(
0
);
resCls
=
candidates
.
get
(
0
);
addResourceFields
(
resCls
,
resStorage
,
true
);
return
resCls
;
}
if
(!
candidates
.
isEmpty
())
{
LOG
.
info
(
"Found several 'R' class candidates: {}"
,
candidates
);
}
LOG
.
warn
(
"Unknown 'R' class, create references to '{}'"
,
fullName
);
return
makeClass
(
root
,
fullName
,
resStorage
);
LOG
.
info
(
"App 'R' class not found, put all resources ids to : '{}'"
,
fullName
);
resCls
=
makeClass
(
root
,
fullName
,
resStorage
);
addResourceFields
(
resCls
,
resStorage
,
false
);
return
resCls
;
}
public
static
boolean
handleAppResField
(
CodeWriter
code
,
ClassGen
clsGen
,
ClassInfo
declClass
)
{
...
...
@@ -57,48 +69,45 @@ public class AndroidResourcesUtils {
return
false
;
}
@Nullable
private
static
ClassNode
makeClass
(
RootNode
root
,
String
clsName
,
ResourceStorage
resStorage
)
{
List
<
DexNode
>
dexNodes
=
root
.
getDexNodes
();
if
(
dexNodes
.
isEmpty
())
{
return
null
;
}
Class
Info
r
=
ClassInfo
.
fromName
(
root
,
clsName
);
ClassNode
classNode
=
new
ClassNode
(
dexNodes
.
get
(
0
),
r
);
generateMissingRCode
(
classNode
,
resStorage
);
return
classNode
;
Class
Node
rCls
=
new
ClassNode
(
dexNodes
.
get
(
0
),
clsName
,
AccessFlags
.
ACC_PUBLIC
|
AccessFlags
.
ACC_FINAL
);
rCls
.
addAttr
(
AType
.
COMMENTS
,
"This class is generated by JADX"
);
rCls
.
setState
(
ProcessState
.
PROCESSED
);
return
rCls
;
}
private
static
void
generateMissingRCode
(
ClassNode
cls
,
ResourceStorage
resStorage
)
{
Map
<
String
,
List
<
ResourceEntry
>>
sortedMap
=
new
HashMap
<>();
for
(
ResourceEntry
ri
:
resStorage
.
getResources
())
{
List
<
ResourceEntry
>
entries
=
sortedMap
.
get
(
ri
.
getTypeName
());
if
(
entries
==
null
)
{
entries
=
new
LinkedList
<>();
sortedMap
.
put
(
ri
.
getTypeName
(),
entries
);
private
static
void
addResourceFields
(
ClassNode
cls
,
ResourceStorage
resStorage
,
boolean
rClsExists
)
{
Map
<
String
,
ClassNode
>
innerClsMap
=
new
TreeMap
<>();
if
(
rClsExists
)
{
for
(
ClassNode
innerClass
:
cls
.
getInnerClasses
())
{
innerClsMap
.
put
(
innerClass
.
getShortName
(),
innerClass
);
}
}
for
(
ResourceEntry
resource
:
resStorage
.
getResources
())
{
ClassNode
typeCls
=
innerClsMap
.
computeIfAbsent
(
resource
.
getTypeName
(),
name
->
{
ClassNode
newTypeCls
=
new
ClassNode
(
cls
.
dex
(),
cls
.
getFullName
()
+
"$"
+
name
,
AccessFlags
.
ACC_PUBLIC
|
AccessFlags
.
ACC_STATIC
|
AccessFlags
.
ACC_FINAL
);
cls
.
addInnerClass
(
newTypeCls
);
if
(
rClsExists
)
{
newTypeCls
.
addAttr
(
AType
.
COMMENTS
,
"added by JADX"
);
}
return
newTypeCls
;
});
FieldNode
rField
=
typeCls
.
searchFieldByName
(
resource
.
getKeyName
());
if
(
rField
==
null
)
{
FieldInfo
rFieldInfo
=
FieldInfo
.
from
(
typeCls
.
dex
(),
typeCls
.
getClassInfo
(),
resource
.
getKeyName
(),
ArgType
.
INT
);
rField
=
new
FieldNode
(
typeCls
,
rFieldInfo
,
AccessFlags
.
ACC_PUBLIC
|
AccessFlags
.
ACC_STATIC
|
AccessFlags
.
ACC_FINAL
);
rField
.
addAttr
(
FieldInitAttr
.
constValue
(
resource
.
getId
()));
typeCls
.
getFields
().
add
(
rField
);
if
(
rClsExists
)
{
rField
.
addAttr
(
AType
.
COMMENTS
,
"added by JADX"
);
}
entries
.
add
(
ri
);
}
Set
<
String
>
addedValues
=
new
HashSet
<>();
CodeWriter
clsCode
=
new
CodeWriter
();
if
(!
""
.
equals
(
cls
.
getPackage
()))
{
clsCode
.
add
(
"package "
).
add
(
cls
.
getPackage
()).
add
(
';'
).
newLine
();
}
clsCode
.
startLine
(
"public final class "
).
add
(
cls
.
getShortName
()).
add
(
" {"
).
incIndent
();
for
(
String
typeName
:
sortedMap
.
keySet
())
{
clsCode
.
startLine
(
"public static final class "
).
add
(
typeName
).
add
(
" {"
).
incIndent
();
for
(
ResourceEntry
ri
:
sortedMap
.
get
(
typeName
))
{
if
(
addedValues
.
add
(
ri
.
getTypeName
()
+
"."
+
ri
.
getKeyName
()))
{
clsCode
.
startLine
(
"public static final int "
).
add
(
ri
.
getKeyName
()).
add
(
" = "
)
.
add
(
""
+
ri
.
getId
()).
add
(
";"
);
}
}
clsCode
.
decIndent
();
clsCode
.
add
(
"}"
);
}
clsCode
.
decIndent
();
clsCode
.
add
(
"}"
);
cls
.
setCode
(
clsCode
);
}
}
jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java
View file @
f6f883b9
...
...
@@ -27,7 +27,8 @@ import jadx.core.dex.nodes.MethodNode;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.dex.visitors.DepthTraversal
;
import
jadx.core.dex.visitors.IDexTreeVisitor
;
import
jadx.core.utils.exceptions.CodegenException
;
import
jadx.core.xmlgen.ResourceStorage
;
import
jadx.core.xmlgen.entry.ResourceEntry
;
import
jadx.tests.api.compiler.DynamicCompiler
;
import
jadx.tests.api.compiler.StaticCompiler
;
import
jadx.tests.api.utils.TestUtils
;
...
...
@@ -99,7 +100,7 @@ public abstract class IntegrationTest extends TestUtils {
fail
(
e
.
getMessage
());
}
RootNode
root
=
JadxInternalAccess
.
getRoot
(
d
);
root
.
getConstValues
().
getResourcesNames
().
putAll
(
resMap
);
insertResources
(
root
);
ClassNode
cls
=
root
.
searchClassByName
(
clsName
);
assertThat
(
"Class not found: "
+
clsName
,
cls
,
notNullValue
());
...
...
@@ -121,6 +122,20 @@ public abstract class IntegrationTest extends TestUtils {
return
cls
;
}
private
void
insertResources
(
RootNode
root
)
{
if
(
resMap
.
isEmpty
())
{
return
;
}
ResourceStorage
resStorage
=
new
ResourceStorage
();
for
(
Map
.
Entry
<
Integer
,
String
>
entry
:
resMap
.
entrySet
())
{
Integer
id
=
entry
.
getKey
();
String
name
=
entry
.
getValue
();
String
[]
parts
=
name
.
split
(
"\\."
);
resStorage
.
add
(
new
ResourceEntry
(
id
,
""
,
parts
[
0
],
parts
[
1
]));
}
root
.
processResources
(
resStorage
);
}
protected
void
decompile
(
JadxDecompiler
jadx
,
ClassNode
cls
)
{
List
<
IDexTreeVisitor
>
passes
=
Jadx
.
getPassesList
(
jadx
.
getArgs
());
ProcessClass
.
process
(
cls
,
passes
,
new
CodeGen
());
...
...
jadx-core/src/test/java/jadx/tests/integration/inner/TestRFieldRestore2.java
View file @
f6f883b9
...
...
@@ -25,15 +25,12 @@ public class TestRFieldRestore2 extends IntegrationTest {
@Test
public
void
test
()
{
// unknown id.Button
disableCompilation
();
Map
<
Integer
,
String
>
map
=
new
HashMap
<>();
map
.
put
(
2131230730
,
"id.Button"
);
setResMap
(
map
);
ClassNode
cls
=
getClassNode
(
TestCls
.
class
);
String
code
=
cls
.
getCode
().
toString
();
assertThat
(
code
,
containsOne
(
"
return
R.id.Button;"
));
assertThat
(
code
,
containsOne
(
"R.id.Button;"
));
}
}
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