|
| 1 | +package the.bytecode.club.jda.decompilers; |
| 2 | + |
| 3 | +import com.strobel.assembler.InputTypeLoader; |
| 4 | +import com.strobel.assembler.metadata.*; |
| 5 | +import com.strobel.decompiler.DecompilationOptions; |
| 6 | +import com.strobel.decompiler.DecompilerSettings; |
| 7 | +import com.strobel.decompiler.PlainTextOutput; |
| 8 | +import org.objectweb.asm.tree.ClassNode; |
| 9 | +import the.bytecode.club.jda.JDA; |
| 10 | +import the.bytecode.club.jda.settings.DecompilerSettings.SettingsEntry; |
| 11 | + |
| 12 | +import java.io.*; |
| 13 | +import java.util.*; |
| 14 | + |
| 15 | +/** |
| 16 | + * Procyon Java Decompiler Wrapper |
| 17 | + * |
| 18 | + * @author Konloch |
| 19 | + * @author DeathMarine |
| 20 | + */ |
| 21 | + |
| 22 | +public final class ProcyonDecompiler extends Decompiler { |
| 23 | + |
| 24 | + public ProcyonDecompiler() { |
| 25 | + // output modes: Bytecode AST, raw bytecode, Java |
| 26 | + settings.registerSetting(new SettingsEntry("ci", "Use wildcard imports", false)); |
| 27 | + settings.registerSetting(new SettingsEntry("dl", "Show LVT comments", false)); |
| 28 | + settings.registerSetting(new SettingsEntry("disable-foreach", "Disable 'for each'", false)); |
| 29 | + settings.registerSetting(new SettingsEntry("eml", "Eager method loading", false)); |
| 30 | + settings.registerSetting(new SettingsEntry("ent", "Exclude nested types", false)); |
| 31 | + settings.registerSetting(new SettingsEntry("ei", "Explicit type arguments", false)); |
| 32 | + settings.registerSetting(new SettingsEntry("fsb", "Flatten switch blocks", false)); |
| 33 | + settings.registerSetting(new SettingsEntry("mv", "Merge variables aggressively", false)); |
| 34 | + settings.registerSetting(new SettingsEntry("ec", "Retain redundant casts", false)); |
| 35 | + settings.registerSetting(new SettingsEntry("ps", "Retain pointless switches", false)); |
| 36 | + settings.registerSetting(new SettingsEntry("ss", "Show synthetic members", true)); |
| 37 | + settings.registerSetting(new SettingsEntry("sm", "Simplify member references", false)); |
| 38 | + settings.registerSetting(new SettingsEntry("sl", "Stretch lines to match LVT", false)); |
| 39 | + settings.registerSetting(new SettingsEntry("unicode", "Do not escape non-ASCII characters", false)); |
| 40 | +// settings.registerSetting(new SettingsEntry("u", "Unoptimized AST", false)); |
| 41 | + } |
| 42 | + |
| 43 | + @Override |
| 44 | + public String getName() { |
| 45 | + return "Procyon"; |
| 46 | + } |
| 47 | + |
| 48 | + public DecompilerSettings getDecompilerSettings() { |
| 49 | + System.out.println(settings.getEntry("Do not escape non-ASCII characters").getBool()); |
| 50 | + DecompilerSettings procyonSettings = new DecompilerSettings(); |
| 51 | + procyonSettings.setFlattenSwitchBlocks(settings.getEntry("Flatten switch blocks").getBool()); |
| 52 | + procyonSettings.setForceExplicitImports(!settings.getEntry("Use wildcard imports").getBool()); |
| 53 | + procyonSettings.setForceExplicitTypeArguments(settings.getEntry("Explicit type arguments").getBool()); |
| 54 | + procyonSettings.setRetainRedundantCasts(settings.getEntry("Retain redundant casts").getBool()); |
| 55 | + procyonSettings.setShowSyntheticMembers(settings.getEntry("Show synthetic members").getBool()); |
| 56 | + procyonSettings.setExcludeNestedTypes(settings.getEntry("Exclude nested types").getBool()); |
| 57 | +// procyonSettings.setOutputDirectory(options.getOutputDirectory()); |
| 58 | + procyonSettings.setIncludeLineNumbersInBytecode(settings.getEntry("Show LVT comments").getBool()); |
| 59 | + procyonSettings.setRetainPointlessSwitches(settings.getEntry("Retain pointless switches").getBool()); |
| 60 | + procyonSettings.setUnicodeOutputEnabled(settings.getEntry("Do not escape non-ASCII characters").getBool()); |
| 61 | + procyonSettings.setMergeVariables(settings.getEntry("Merge variables aggressively").getBool()); |
| 62 | + procyonSettings.setShowDebugLineNumbers(settings.getEntry("Show LVT comments").getBool()); |
| 63 | + procyonSettings.setSimplifyMemberReferences(settings.getEntry("Simplify member references").getBool()); |
| 64 | + procyonSettings.setDisableForEachTransforms(settings.getEntry("Disable 'for each'").getBool()); |
| 65 | + procyonSettings.setTypeLoader(new InputTypeLoader()); |
| 66 | +// procyonSettings.setLanguage(Languages.bytecode()); |
| 67 | +// procyonSettings.setLanguage(settings.getEntry("Unoptimized AST").getBool() ? Languages.bytecodeAstUnoptimized() : Languages.bytecodeAst()); |
| 68 | + return procyonSettings; |
| 69 | + } |
| 70 | + |
| 71 | + @Override |
| 72 | + public String decompileClassNode(String containerName, final ClassNode cn) { |
| 73 | + try { |
| 74 | + byte[] bytes = JDA.getClassBytes(containerName, cn); |
| 75 | + final Map<String, byte[]> loadedClasses = JDA.getLoadedBytes(); |
| 76 | + MetadataSystem metadataSystem = new MetadataSystem(new ITypeLoader() { |
| 77 | + private InputTypeLoader backLoader = new InputTypeLoader(); |
| 78 | + |
| 79 | + @Override |
| 80 | + public boolean tryLoadType(String s, Buffer buffer) { |
| 81 | + if (s.equals(cn.name)) { |
| 82 | + buffer.putByteArray(bytes, 0, bytes.length); |
| 83 | + buffer.position(0); |
| 84 | + return true; |
| 85 | + } else { |
| 86 | + byte[] toUse = loadedClasses.get(s + ".class"); |
| 87 | + if (toUse != null) { |
| 88 | + buffer.putByteArray(toUse, 0, toUse.length); |
| 89 | + buffer.position(0); |
| 90 | + return true; |
| 91 | + } else { |
| 92 | + return backLoader.tryLoadType(s, buffer); |
| 93 | + } |
| 94 | + } |
| 95 | + } |
| 96 | + }); |
| 97 | + TypeReference type = metadataSystem.lookupType(cn.name); |
| 98 | + DecompilationOptions decompilationOptions = new DecompilationOptions(); |
| 99 | + DecompilerSettings settings = getDecompilerSettings(); |
| 100 | + decompilationOptions.setSettings(settings); |
| 101 | + decompilationOptions.setFullDecompilation(true); |
| 102 | + TypeDefinition resolvedType; |
| 103 | + if (type == null || ((resolvedType = type.resolve()) == null)) { |
| 104 | + throw new Exception("Unable to resolve type."); |
| 105 | + } |
| 106 | + StringWriter stringwriter = new StringWriter(); |
| 107 | + settings.getLanguage().decompileType(resolvedType, new PlainTextOutput(stringwriter), decompilationOptions); |
| 108 | + String decompiledSource = stringwriter.toString(); |
| 109 | + return decompiledSource; |
| 110 | + } catch (Throwable e) { |
| 111 | + return parseException(e); |
| 112 | + } |
| 113 | + } |
| 114 | + |
| 115 | + @Override |
| 116 | + public void decompileToZip(String zipName) { |
| 117 | + // todo: rewrite |
| 118 | + } |
| 119 | +} |
| 120 | + |
0 commit comments