feat: add an option to generate kotlin code for xposed (PR #2070)
* feat: add an option to generate kotlin code for xposed A new setting was added, bumping the settings version to 19. * refactor: applied spotless * refactor: fixed formatting * refactor: fixed formatting once again
This commit is contained in:
@@ -52,7 +52,7 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
|
||||
private static final Path USER_HOME = Paths.get(System.getProperty("user.home"));
|
||||
private static final int RECENT_PROJECTS_COUNT = 30;
|
||||
private static final int CURRENT_SETTINGS_VERSION = 18;
|
||||
private static final int CURRENT_SETTINGS_VERSION = 19;
|
||||
|
||||
private static final Font DEFAULT_FONT = new RSyntaxTextArea().getFont();
|
||||
|
||||
@@ -110,6 +110,8 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
|
||||
private boolean jumpOnDoubleClick = true;
|
||||
|
||||
private XposedCodegenLanguage xposedCodegenLanguage = XposedCodegenLanguage.JAVA;
|
||||
|
||||
/**
|
||||
* UI setting: the width of the tree showing the classes, resources, ...
|
||||
*/
|
||||
@@ -732,6 +734,14 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
partialSync(settings -> this.dockLogViewer = dockLogViewer);
|
||||
}
|
||||
|
||||
public XposedCodegenLanguage getXposedCodegenLanguage() {
|
||||
return xposedCodegenLanguage;
|
||||
}
|
||||
|
||||
public void setXposedCodegenLanguage(XposedCodegenLanguage language) {
|
||||
this.xposedCodegenLanguage = language;
|
||||
}
|
||||
|
||||
private void upgradeSettings(int fromVersion) {
|
||||
LOG.debug("upgrade settings from version: {} to {}", fromVersion, CURRENT_SETTINGS_VERSION);
|
||||
if (fromVersion <= 10) {
|
||||
@@ -769,6 +779,10 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
checkForUpdates = true;
|
||||
fromVersion++;
|
||||
}
|
||||
if (fromVersion == 18) {
|
||||
xposedCodegenLanguage = XposedCodegenLanguage.JAVA;
|
||||
fromVersion++;
|
||||
}
|
||||
if (fromVersion != CURRENT_SETTINGS_VERSION) {
|
||||
LOG.warn("Incorrect settings upgrade. Expected version: {}, got: {}", CURRENT_SETTINGS_VERSION, fromVersion);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package jadx.gui.settings
|
||||
|
||||
enum class XposedCodegenLanguage {
|
||||
JAVA,
|
||||
KOTLIN,
|
||||
}
|
||||
@@ -59,6 +59,7 @@ import jadx.api.plugins.gui.ISettingsGroup;
|
||||
import jadx.gui.settings.JadxSettings;
|
||||
import jadx.gui.settings.JadxSettingsAdapter;
|
||||
import jadx.gui.settings.LineNumbersMode;
|
||||
import jadx.gui.settings.XposedCodegenLanguage;
|
||||
import jadx.gui.settings.ui.cache.CacheSettingsGroup;
|
||||
import jadx.gui.settings.ui.plugins.PluginSettings;
|
||||
import jadx.gui.settings.ui.shortcut.ShortcutsSettingsGroup;
|
||||
@@ -622,6 +623,14 @@ public class JadxSettingsWindow extends JDialog {
|
||||
needReload();
|
||||
});
|
||||
|
||||
JComboBox<XposedCodegenLanguage> xposedCodegenLanguage =
|
||||
new JComboBox<>(XposedCodegenLanguage.getEntries().toArray(new XposedCodegenLanguage[0]));
|
||||
xposedCodegenLanguage.setSelectedItem(settings.getXposedCodegenLanguage());
|
||||
xposedCodegenLanguage.addActionListener(e -> {
|
||||
settings.setXposedCodegenLanguage((XposedCodegenLanguage) xposedCodegenLanguage.getSelectedItem());
|
||||
mainWindow.loadSettings();
|
||||
});
|
||||
|
||||
SettingsGroup group = new SettingsGroup(NLS.str("preferences.other"));
|
||||
group.addRow(NLS.str("preferences.lineNumbersMode"), lineNumbersMode);
|
||||
group.addRow(NLS.str("preferences.jumpOnDoubleClick"), jumpOnDoubleClick);
|
||||
@@ -629,6 +638,7 @@ public class JadxSettingsWindow extends JDialog {
|
||||
group.addRow(NLS.str("preferences.check_for_updates"), update);
|
||||
group.addRow(NLS.str("preferences.cfg"), cfg);
|
||||
group.addRow(NLS.str("preferences.raw_cfg"), rawCfg);
|
||||
group.addRow(NLS.str("preferences.xposed_codegen_language"), xposedCodegenLanguage);
|
||||
return group;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import jadx.api.JavaMethod;
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
import jadx.gui.settings.XposedCodegenLanguage;
|
||||
import jadx.gui.treemodel.JClass;
|
||||
import jadx.gui.treemodel.JField;
|
||||
import jadx.gui.treemodel.JMethod;
|
||||
@@ -85,16 +86,40 @@ public class XposedAction extends JNodeAction {
|
||||
methodName = "\"" + mth.getMethodInfo().getName() + "\", ";
|
||||
}
|
||||
String rawClassName = javaMethod.getDeclaringClass().getRawName();
|
||||
String xposedFormatStr = "XposedHelpers.%s(\"%s\", classLoader, %snew XC_MethodHook() {\n"
|
||||
+ " @Override\n"
|
||||
+ " protected void beforeHookedMethod(MethodHookParam param) throws Throwable {\n"
|
||||
+ " super.beforeHookedMethod(param);\n"
|
||||
+ " }\n"
|
||||
+ " @Override\n"
|
||||
+ " protected void afterHookedMethod(MethodHookParam param) throws Throwable {\n"
|
||||
+ " super.afterHookedMethod(param);\n"
|
||||
+ " }\n"
|
||||
+ "});";
|
||||
String javaXposedFormatStr =
|
||||
"XposedHelpers.%s(\"%s\", classLoader, %snew XC_MethodHook() {\n"
|
||||
+ " @Override\n"
|
||||
+ " protected void beforeHookedMethod(MethodHookParam param) throws Throwable {\n"
|
||||
+ " super.beforeHookedMethod(param);\n"
|
||||
+ " }\n"
|
||||
+ " @Override\n"
|
||||
+ " protected void afterHookedMethod(MethodHookParam param) throws Throwable {\n"
|
||||
+ " super.afterHookedMethod(param);\n"
|
||||
+ " }\n"
|
||||
+ "});";
|
||||
String kotlinXposedFormatStr =
|
||||
"XposedHelpers.%s(\"%s\", classLoader, %sobject : XC_MethodHook() {\n"
|
||||
+ " override fun beforeHookedMethod(param: MethodHookParam) {\n"
|
||||
+ " super.beforeHookedMethod(param)\n"
|
||||
+ " }\n"
|
||||
+ "\n"
|
||||
+ " override fun afterHookedMethod(param: MethodHookParam) {\n"
|
||||
+ " super.afterHookedMethod(param)\n"
|
||||
+ " }\n"
|
||||
+ "})";
|
||||
|
||||
XposedCodegenLanguage language = getLanguage();
|
||||
String xposedFormatStr;
|
||||
switch (language) {
|
||||
case JAVA:
|
||||
xposedFormatStr = javaXposedFormatStr;
|
||||
break;
|
||||
case KOTLIN:
|
||||
xposedFormatStr = kotlinXposedFormatStr;
|
||||
break;
|
||||
default:
|
||||
throw new JadxRuntimeException("Invalid Xposed code generation language: " + language);
|
||||
}
|
||||
|
||||
List<ArgType> mthArgs = mth.getArgTypes();
|
||||
if (mthArgs.isEmpty()) {
|
||||
@@ -119,9 +144,28 @@ public class XposedAction extends JNodeAction {
|
||||
JavaClass javaClass = jc.getCls();
|
||||
String rawClassName = javaClass.getRawName();
|
||||
String shortClassName = javaClass.getName();
|
||||
return String.format("ClassLoader classLoader = lpparam.classLoader;\n"
|
||||
+ "Class<?> %sClass = classLoader.loadClass(\"%s\");",
|
||||
shortClassName, rawClassName);
|
||||
|
||||
String javaXposedFormatStr =
|
||||
"ClassLoader classLoader = lpparam.classLoader;\n"
|
||||
+ "Class<?> %sClass = classLoader.loadClass(\"%s\");";
|
||||
String kotlinXposedFormatStr =
|
||||
"val classLoader = lpparam.classLoader\n"
|
||||
+ "val %sClass = classLoader.loadClass(\"%s\")";
|
||||
|
||||
XposedCodegenLanguage language = getLanguage();
|
||||
String xposedFormatStr;
|
||||
switch (language) {
|
||||
case JAVA:
|
||||
xposedFormatStr = javaXposedFormatStr;
|
||||
break;
|
||||
case KOTLIN:
|
||||
xposedFormatStr = kotlinXposedFormatStr;
|
||||
break;
|
||||
default:
|
||||
throw new JadxRuntimeException("Invalid Xposed code generation language: " + language);
|
||||
}
|
||||
|
||||
return String.format(xposedFormatStr, shortClassName, rawClassName);
|
||||
}
|
||||
|
||||
private String generateFieldSnippet(JField jf) {
|
||||
@@ -129,6 +173,29 @@ public class XposedAction extends JNodeAction {
|
||||
String isStatic = javaField.getAccessFlags().isStatic() ? "Static" : "";
|
||||
String type = PRIMITIVE_TYPE_MAPPING.getOrDefault(javaField.getFieldNode().getType().toString(), "Object");
|
||||
String xposedMethod = "XposedHelpers.get" + isStatic + type + "Field";
|
||||
return String.format("%s(/*runtimeObject*/, \"%s\");", xposedMethod, javaField.getFieldNode().getFieldInfo().getName());
|
||||
|
||||
String javaXposedFormatStr =
|
||||
"%s(/*runtimeObject*/, \"%s\");";
|
||||
String kotlinXposedFormatStr =
|
||||
"%s(/*runtimeObject*/, \"%s\")";
|
||||
|
||||
XposedCodegenLanguage language = getLanguage();
|
||||
String xposedFormatStr;
|
||||
switch (language) {
|
||||
case JAVA:
|
||||
xposedFormatStr = javaXposedFormatStr;
|
||||
break;
|
||||
case KOTLIN:
|
||||
xposedFormatStr = kotlinXposedFormatStr;
|
||||
break;
|
||||
default:
|
||||
throw new JadxRuntimeException("Invalid Xposed code generation language: " + language);
|
||||
}
|
||||
|
||||
return String.format(xposedFormatStr, xposedMethod, javaField.getFieldNode().getFieldInfo().getName());
|
||||
}
|
||||
|
||||
private XposedCodegenLanguage getLanguage() {
|
||||
return getCodeArea().getMainWindow().getSettings().getXposedCodegenLanguage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,6 +203,7 @@ preferences.excludedPackages.button=Bearbeiten
|
||||
preferences.excludedPackages.editDialog=<html>Liste der durch Leerzeichen getrennten Paketnamen, die nicht dekompiliert oder indiziert werden. (spart RAM)<br>z.B. <code>android.support</code></html>
|
||||
preferences.cfg=CFG-Grafiken für Methoden generieren (im 'dot'-Format)
|
||||
preferences.raw_cfg=RAW CFG-Grafiken generieren
|
||||
#preferences.xposed_codegen_language=Xposed code generation language
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=Schrift ändern
|
||||
#preferences.smali_font=
|
||||
|
||||
@@ -203,6 +203,7 @@ preferences.excludedPackages.button=Edit
|
||||
preferences.excludedPackages.editDialog=<html>List of space separated package names that will not be decompiled or indexed (saves RAM)<br>e.g. <code>android.support</code></html>
|
||||
preferences.cfg=Generate methods CFG graphs (in 'dot' format)
|
||||
preferences.raw_cfg=Generate RAW CFG graphs
|
||||
preferences.xposed_codegen_language=Xposed code generation language
|
||||
preferences.integerFormat=Integer format
|
||||
preferences.font=Editor font
|
||||
preferences.smali_font=Monospaced font (Smali/Hex)
|
||||
|
||||
@@ -203,6 +203,7 @@ preferences.threads=Número de hilos a procesar
|
||||
#preferences.excludedPackages.editDialog=
|
||||
preferences.cfg=Generar methods CFG graphs (in 'dot' format)
|
||||
preferences.raw_cfg=Generate RAW CFG graphs
|
||||
#preferences.xposed_codegen_language=Xposed code generation language
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=Fuente del editor
|
||||
#preferences.smali_font=
|
||||
|
||||
@@ -203,6 +203,7 @@ preferences.excludedPackages.button=Edit
|
||||
preferences.excludedPackages.editDialog=<html>Daftar nama paket yang dipisahkan spasi yang tidak akan di deskompilasi atau diindeks (menghemat RAM)<br>contoh: <code>android.support</code></html>
|
||||
preferences.cfg=Hasilkan grafik CFG metode (dalam format 'dot')
|
||||
preferences.raw_cfg=Hasilkan grafik CFG mentah
|
||||
#preferences.xposed_codegen_language=Xposed code generation language
|
||||
preferences.integerFormat=Format bilangan bulat
|
||||
preferences.font=Font editor
|
||||
preferences.smali_font=Font monospasi (Smali/Hex)
|
||||
|
||||
@@ -203,6 +203,7 @@ preferences.excludedPackages.button=Edit
|
||||
preferences.excludedPackages.editDialog=<html>RAM 절약을 위해 디컴파일되거나 인덱싱하지 않을 패키지 이름 목록 (공백으로 항목 구분)<br>예: <code>android.support</code></html>
|
||||
preferences.cfg=메소드 CFG 그래프 생성 ('dot' 포맷)
|
||||
preferences.raw_cfg=RAW CFG 그래프 생성
|
||||
#preferences.xposed_codegen_language=Xposed code generation language
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=에디터 글씨체
|
||||
#preferences.smali_font=
|
||||
|
||||
@@ -203,6 +203,7 @@ preferences.excludedPackages.button=Editar
|
||||
preferences.excludedPackages.editDialog=<html>Lista espaço de pacotes que não vão ser descompilados ou indexados (economiza RAM)<br>ex: <code>android.support</code></html>
|
||||
preferences.cfg=Gera gráficos de métodos CFG no formato de pontos ('dot')
|
||||
preferences.raw_cfg=Gera gráficos CFG no formato RAW
|
||||
#preferences.xposed_codegen_language=Xposed code generation language
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=Fonte do editor
|
||||
#preferences.smali_font=
|
||||
|
||||
@@ -203,6 +203,7 @@ preferences.excludedPackages.button=Изменить
|
||||
preferences.excludedPackages.editDialog=<html>Список пакетов, которые не будут декомпилироваться и индексироваться (экономит ОЗУ)<br>например: <code>android.support</code><br>Разделитель - одинарный пробел</html>
|
||||
preferences.cfg=Методы генерации графиков CFG (в "dot" формате)
|
||||
preferences.raw_cfg=Генерировать необработанные графики CFG
|
||||
#preferences.xposed_codegen_language=Xposed code generation language
|
||||
#preferences.integerFormat=Integer format
|
||||
preferences.font=Шрифт редактора Java
|
||||
#preferences.smali_font=
|
||||
|
||||
@@ -203,6 +203,7 @@ preferences.excludedPackages.button=编辑
|
||||
preferences.excludedPackages.editDialog=<html>排除于反编译或索引的以空格分隔的包名列表(节省 RAM)<br>例如<code>android.support</code></html>
|
||||
preferences.cfg=生成方法的 CFG 图('.dot')
|
||||
preferences.raw_cfg=生成原始的 CFG 图
|
||||
#preferences.xposed_codegen_language=Xposed code generation language
|
||||
preferences.integerFormat=数值格式化
|
||||
preferences.font=编辑器字体
|
||||
preferences.smali_font=等宽字体 (Smali/Hex)
|
||||
|
||||
@@ -203,6 +203,7 @@ preferences.excludedPackages.button=編輯
|
||||
preferences.excludedPackages.editDialog=<html>排除於索引或反編譯外的套件列表 (以空格分隔) (節省 RAM) <br>例如 <code>android.support</code></html>
|
||||
preferences.cfg=產生方法 CFG 圖表 ('dot' 格式)
|
||||
preferences.raw_cfg=產生 RAW CFG 圖表
|
||||
#preferences.xposed_codegen_language=Xposed code generation language
|
||||
preferences.integerFormat=整數模式
|
||||
preferences.font=編輯器字型
|
||||
preferences.smali_font=等寬字型 (Smali/Hex)
|
||||
|
||||
Reference in New Issue
Block a user