■ ■ ■ ■ ■ ■
jadx-gui/src/main/java/jadx/gui/ui/codearea/FridaAction.java
| skipped 22 lines |
23 | 23 | | import jadx.core.codegen.TypeGen; |
24 | 24 | | import jadx.core.dex.info.MethodInfo; |
25 | 25 | | import jadx.core.dex.instructions.args.ArgType; |
26 | | - | import jadx.core.dex.nodes.ClassNode; |
27 | 26 | | import jadx.core.dex.nodes.MethodNode; |
28 | 27 | | import jadx.core.utils.exceptions.JadxRuntimeException; |
29 | 28 | | import jadx.gui.treemodel.JClass; |
| skipped 46 lines |
76 | 75 | | } |
77 | 76 | | |
78 | 77 | | private String generateMethodSnippet(JMethod jMth) { |
79 | | - | JavaMethod javaMethod = jMth.getJavaMethod(); |
80 | | - | MethodInfo methodInfo = javaMethod.getMethodNode().getMethodInfo(); |
81 | | - | String methodName = StringEscapeUtils.escapeEcmaScript(methodInfo.getName()); |
82 | | - | |
| 78 | + | MethodNode mth = jMth.getJavaMethod().getMethodNode(); |
| 79 | + | MethodInfo methodInfo = mth.getMethodInfo(); |
| 80 | + | String methodName; |
83 | 81 | | if (methodInfo.isConstructor()) { |
84 | 82 | | methodName = "$init"; |
| 83 | + | } else { |
| 84 | + | methodName = StringEscapeUtils.escapeEcmaScript(methodInfo.getName()); |
85 | 85 | | } |
86 | | - | |
87 | | - | String callMethodName = methodName; |
88 | | - | String shortClassName = javaMethod.getDeclaringClass().getName(); |
89 | | - | |
90 | | - | String functionUntilImplementation; |
91 | | - | if (isOverloaded(javaMethod.getMethodNode())) { |
92 | | - | List<ArgType> methodArgs = methodInfo.getArgumentsTypes(); |
93 | | - | String overloadStr = methodArgs.stream().map(this::parseArgType).collect(Collectors.joining(", ")); |
94 | | - | functionUntilImplementation = String.format("%s[\"%s\"].overload(%s).implementation", shortClassName, methodName, overloadStr); |
| 86 | + | String overload; |
| 87 | + | if (isOverloaded(mth)) { |
| 88 | + | String overloadArgs = methodInfo.getArgumentsTypes().stream() |
| 89 | + | .map(this::parseArgType).collect(Collectors.joining(", ")); |
| 90 | + | overload = ".overload(" + overloadArgs + ")"; |
| 91 | + | } else { |
| 92 | + | overload = ""; |
| 93 | + | } |
| 94 | + | List<String> argNames = collectMethodArgNames(jMth.getJavaMethod()); |
| 95 | + | String args = String.join(", ", argNames); |
| 96 | + | String logArgs; |
| 97 | + | if (argNames.isEmpty()) { |
| 98 | + | logArgs = ""; |
95 | 99 | | } else { |
96 | | - | functionUntilImplementation = String.format("%s[\"%s\"].implementation", shortClassName, methodName); |
| 100 | + | String joinStr = " + ', ' + "; |
| 101 | + | logArgs = joinStr + argNames.stream().map(a -> "'" + a + ": ' + " + a).collect(Collectors.joining(joinStr)); |
97 | 102 | | } |
98 | | - | |
99 | | - | List<String> methodArgNames = collectMethodArgNames(javaMethod); |
100 | | - | |
101 | | - | String functionParametersString = String.join(", ", methodArgNames); |
102 | | - | String logParametersString = |
103 | | - | methodArgNames.stream().map(e -> String.format("'%s: ' + %s", e, e)).collect(Collectors.joining(" + ', ' + ")); |
104 | | - | if (logParametersString.length() > 0) { |
105 | | - | logParametersString = " + ', ' + " + logParametersString; |
| 103 | + | String shortClassName = mth.getParentClass().getShortName(); |
| 104 | + | String classSnippet = generateClassSnippet(jMth.getJParent()); |
| 105 | + | if (methodInfo.isConstructor() || methodInfo.getReturnType() == ArgType.VOID) { |
| 106 | + | // no return value |
| 107 | + | return classSnippet + "\n" |
| 108 | + | + shortClassName + "[\"" + methodName + "\"]" + overload + ".implementation = function (" + args + ") {\n" |
| 109 | + | + " console.log('" + shortClassName + "." + methodName + " is called'" + logArgs + ");\n" |
| 110 | + | + " this[\"" + methodName + "\"](" + args + ");\n" |
| 111 | + | + "};"; |
106 | 112 | | } |
107 | | - | String functionParameterAndBody = String.format( |
108 | | - | "%s = function (%s) {\n" |
109 | | - | + " console.log('%s is called'%s);\n" |
110 | | - | + " let ret = this.%s(%s);\n" |
111 | | - | + " console.log('%s ret value is ' + ret);\n" |
112 | | - | + " return ret;\n" |
113 | | - | + "};", |
114 | | - | functionUntilImplementation, functionParametersString, methodName, logParametersString, callMethodName, |
115 | | - | functionParametersString, methodName); |
116 | | - | |
117 | | - | return generateClassSnippet(jMth.getJParent()) + "\n" + functionParameterAndBody; |
| 113 | + | return classSnippet + "\n" |
| 114 | + | + shortClassName + "[\"" + methodName + "\"]" + overload + ".implementation = function (" + args + ") {\n" |
| 115 | + | + " console.log('" + shortClassName + "." + methodName + " is called'" + logArgs + ");\n" |
| 116 | + | + " let ret = this[\"" + methodName + "\"](" + args + ");\n" |
| 117 | + | + " console.log('" + shortClassName + "." + methodName + " return: ' + ret);\n" |
| 118 | + | + " return ret;\n" |
| 119 | + | + "};"; |
118 | 120 | | } |
119 | 121 | | |
120 | 122 | | private List<String> collectMethodArgNames(JavaMethod javaMethod) { |
| skipped 38 lines |
159 | 161 | | break; |
160 | 162 | | } |
161 | 163 | | } |
162 | | - | |
163 | 164 | | JClass jc = jf.getRootClass(); |
164 | 165 | | String classSnippet = generateClassSnippet(jc); |
165 | 166 | | return String.format("%s\n%s = %s.%s.value;", classSnippet, fieldName, jc.getName(), rawFieldName); |
166 | 167 | | } |
167 | 168 | | |
168 | 169 | | public Boolean isOverloaded(MethodNode methodNode) { |
169 | | - | ClassNode parentClass = methodNode.getParentClass(); |
170 | | - | List<MethodNode> methods = parentClass.getMethods(); |
171 | | - | return methods.stream() |
| 170 | + | return methodNode.getParentClass().getMethods().stream() |
172 | 171 | | .anyMatch(m -> m.getName().equals(methodNode.getName()) |
173 | 172 | | && !Objects.equals(methodNode.getMethodInfo().getShortId(), m.getMethodInfo().getShortId())); |
174 | 173 | | } |
175 | 174 | | |
176 | 175 | | private String parseArgType(ArgType x) { |
177 | | - | StringBuilder parsedArgType = new StringBuilder("'"); |
| 176 | + | String typeStr; |
178 | 177 | | if (x.isArray()) { |
179 | | - | parsedArgType.append(TypeGen.signature(x).replace("/", ".")); |
| 178 | + | typeStr = TypeGen.signature(x).replace("/", "."); |
180 | 179 | | } else { |
181 | | - | parsedArgType.append(x); |
| 180 | + | typeStr = x.toString(); |
182 | 181 | | } |
183 | | - | return parsedArgType.append("'").toString(); |
| 182 | + | return "'" + typeStr + "'"; |
184 | 183 | | } |
185 | 184 | | } |
186 | 185 | | |