Skip to content

Commit 265cb1b

Browse files
committed
Preliminary work for maple-ir integration
1 parent 9c37183 commit 265cb1b

File tree

145 files changed

+293
-43229
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

145 files changed

+293
-43229
lines changed

mapleir/src/ILDecompiler.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import club.bytecode.the.jda.FileContainer;
2+
import club.bytecode.the.jda.decompilers.JDADecompiler;
3+
import org.mapleir.ir.cfg.ControlFlowGraph;
4+
import org.mapleir.ir.printer.ClassPrinter;
5+
import org.mapleir.ir.printer.FieldNodePrinter;
6+
import org.mapleir.ir.printer.MethodNodePrinter;
7+
import org.mapleir.propertyframework.api.IPropertyDictionary;
8+
import org.mapleir.propertyframework.util.PropertyHelper;
9+
import org.mapleir.stdlib.util.TabbedStringWriter;
10+
import org.objectweb.asm.tree.ClassNode;
11+
import org.objectweb.asm.tree.MethodNode;
12+
13+
public class ILDecompiler extends JDADecompiler {
14+
@Override
15+
public String decompileClassNode(FileContainer container, ClassNode cn) {
16+
TabbedStringWriter sw = new TabbedStringWriter();
17+
sw.setTabString(" ");
18+
IPropertyDictionary settings = PropertyHelper.createDictionary();
19+
// settings.put(new BooleanProperty(ASMPrinter.PROP_ACCESS_FLAG_SAFE, true));
20+
ClassPrinter cp = new ClassPrinter(sw, settings,
21+
new FieldNodePrinter(sw, settings),
22+
new MethodNodePrinter(sw, settings) {
23+
@Override
24+
protected ControlFlowGraph getCfg(MethodNode mn) {
25+
return MaplePlugin.cxt.getIRCache().getFor(mn);
26+
}
27+
28+
});
29+
cp.print(cn);
30+
return sw.toString();
31+
}
32+
33+
@Override
34+
public void decompileToZip(String zipName) {
35+
36+
}
37+
38+
@Override
39+
public String getName() {
40+
return "MapleIL";
41+
}
42+
}

mapleir/src/IRDecompiler.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import club.bytecode.the.jda.decompilers.bytecode.*;
2+
import org.mapleir.ir.cfg.ControlFlowGraph;
3+
import org.objectweb.asm.tree.ClassNode;
4+
import org.objectweb.asm.tree.MethodNode;
5+
6+
import java.util.ArrayList;
7+
import java.util.Arrays;
8+
import java.util.Iterator;
9+
10+
public class IRDecompiler extends BytecodeDecompiler {
11+
@Override
12+
protected MethodNodeDecompiler getMethodNodeDecompiler(PrefixedStringBuilder sb, ClassNode cn, Iterator<MethodNode> it) {
13+
return new IRMethodDecompiler(this, sb, it.next(), cn);
14+
}
15+
16+
@Override
17+
public void decompileToZip(String zipName) {
18+
}
19+
20+
@Override
21+
public String getName() {
22+
return "MapleIR";
23+
}
24+
}
25+
26+
class IRMethodDecompiler extends MethodNodeDecompiler {
27+
public IRMethodDecompiler(BytecodeDecompiler parent, PrefixedStringBuilder sb, MethodNode mn, ClassNode cn) {
28+
super(parent, sb, mn, cn);
29+
}
30+
31+
@Override
32+
protected InstructionPrinter getInstructionPrinter(MethodNode m, TypeAndName[] args) {
33+
return new IRInstructionPrinter(this, m, args);
34+
}
35+
}
36+
37+
class IRInstructionPrinter extends InstructionPrinter {
38+
public IRInstructionPrinter(MethodNodeDecompiler parent, MethodNode m, TypeAndName[] args) {
39+
super(parent, m, args);
40+
}
41+
42+
@Override
43+
public ArrayList<String> createPrint() {
44+
ControlFlowGraph cfg = MaplePlugin.cfgs.get(mNode);
45+
String result = cfg.toString();
46+
return new ArrayList<>(Arrays.asList(result.split("\n")));
47+
}
48+
}

mapleir/src/MaplePlugin.java

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import club.bytecode.the.jda.FileContainer;
2+
import club.bytecode.the.jda.api.JDAPlugin;
3+
import club.bytecode.the.jda.decompilers.Decompilers;
4+
import club.bytecode.the.jda.decompilers.JDADecompiler;
5+
import org.mapleir.DefaultInvocationResolver;
6+
import org.mapleir.app.client.SimpleApplicationContext;
7+
import org.mapleir.app.service.ApplicationClassSource;
8+
import org.mapleir.app.service.InstalledRuntimeClassSource;
9+
import org.mapleir.app.service.LibraryClassSource;
10+
import org.mapleir.context.AnalysisContext;
11+
import org.mapleir.context.BasicAnalysisContext;
12+
import org.mapleir.context.IRCache;
13+
import org.mapleir.deob.IPass;
14+
import org.mapleir.deob.PassGroup;
15+
import org.mapleir.deob.interproc.IRCallTracer;
16+
import org.mapleir.deob.passes.ConstantExpressionReorderPass;
17+
import org.mapleir.deob.util.RenamingHeuristic;
18+
import org.mapleir.ir.algorithms.BoissinotDestructor;
19+
import org.mapleir.ir.algorithms.ControlFlowGraphDumper;
20+
import org.mapleir.ir.cfg.ControlFlowGraph;
21+
import org.mapleir.ir.cfg.builder.ControlFlowGraphBuilder;
22+
import org.objectweb.asm.tree.ClassNode;
23+
import org.objectweb.asm.tree.MethodNode;
24+
import org.topdank.byteengineer.commons.data.JarInfo;
25+
import org.topdank.byteio.in.SingleJarDownloader;
26+
27+
import java.io.File;
28+
import java.io.IOException;
29+
import java.util.ArrayList;
30+
import java.util.HashMap;
31+
import java.util.Map;
32+
33+
public class MaplePlugin implements JDAPlugin {
34+
public static Map<MethodNode, ControlFlowGraph> cfgs;
35+
public static AnalysisContext cxt;
36+
public static JDADecompiler MAPLEIR = new IRDecompiler();
37+
public static JDADecompiler MAPLEIL = new ILDecompiler();
38+
39+
public MaplePlugin() {
40+
Decompilers.BY_NAME.put("MapleIR", MAPLEIR);
41+
Decompilers.BY_NAME.put("MapleIL", MAPLEIL);
42+
System.out.println("MapleIR plugin loaded");
43+
}
44+
45+
public static void main(String[] args) {
46+
new MaplePlugin();
47+
}
48+
49+
@Override
50+
public int onGUILoad() {
51+
cfgs = new HashMap<>();
52+
return 0;
53+
}
54+
55+
@Override
56+
public int onExit() {
57+
return 0;
58+
}
59+
60+
private static LibraryClassSource rt(ApplicationClassSource app, File rtjar) throws IOException {
61+
System.out.println("Loading rt.jar from " + rtjar.getAbsolutePath());
62+
SingleJarDownloader<ClassNode> dl = new SingleJarDownloader<>(new JarInfo(rtjar));
63+
dl.download();
64+
65+
return new LibraryClassSource(app, dl.getJarContents().getClassContents());
66+
}
67+
68+
@Override
69+
public int onAddFile(FileContainer fileContainer) {
70+
//ManagementFactory.getRuntimeMXBean().getBootClassPath()
71+
File rtjar = new File("C:\\Program Files\\Java\\jdk1.8.0_131\\jre\\lib\\rt.jar");
72+
// Load input jar
73+
ApplicationClassSource app = new ApplicationClassSource(fileContainer.name, fileContainer.getClasses());
74+
// app.addLibraries(new InstalledRuntimeClassSource(app));
75+
try {
76+
app.addLibraries(rt(app, rtjar), new InstalledRuntimeClassSource(app));
77+
} catch (IOException e) {
78+
e.printStackTrace();
79+
return 1;
80+
}
81+
System.out.println("Initialising context.");
82+
83+
cxt = new BasicAnalysisContext.BasicContextBuilder()
84+
.setApplication(app)
85+
.setInvocationResolver(new DefaultInvocationResolver(app))
86+
.setCache(new IRCache(ControlFlowGraphBuilder::build))
87+
.setApplicationContext(new SimpleApplicationContext(app))
88+
.build();
89+
90+
System.out.println("Expanding callgraph and generating cfgs.");
91+
92+
IRCallTracer tracer = new IRCallTracer(cxt);
93+
for(ClassNode cn : app.iterate()) {
94+
System.out.println(cn);
95+
for(MethodNode m : cn.methods) {
96+
System.out.println(m);
97+
try {
98+
tracer.trace(m);
99+
}catch(Exception e){e.printStackTrace();}
100+
}
101+
}
102+
103+
// for(ClassNode cn : app.iterate()) {
104+
// TabbedStringWriter sw = new TabbedStringWriter();
105+
// sw.setTabString(" ");
106+
// IPropertyDictionary settings = PropertyHelper.createDictionary();
107+
// // settings.put(new BooleanProperty(ASMPrinter.PROP_ACCESS_FLAG_SAFE, true));
108+
// ClassPrinter cp = new ClassPrinter(sw, settings,
109+
// new FieldNodePrinter(sw, settings),
110+
// new MethodNodePrinter(sw, settings) {
111+
// @Override
112+
// protected ControlFlowGraph getCfg(MethodNode mn) {
113+
// return cxt.getIRCache().getFor(mn);
114+
// }
115+
//
116+
// });
117+
// cp.print(cn);
118+
// System.out.println(sw.toString());
119+
// }
120+
121+
System.out.println("...generated " + cxt.getIRCache().size() + " cfgs.\nPreparing to transform.");
122+
123+
// do passes
124+
PassGroup masterGroup = new PassGroup("MasterController");
125+
for(IPass p : getTransformationPasses()) {
126+
masterGroup.add(p);
127+
}
128+
run(cxt, masterGroup);
129+
130+
// for(MethodNode m : cxt.getIRCache().getActiveMethods()) {
131+
// if(m.instructions.size() > 100 && m.instructions.size() < 500) {
132+
// System.out.println(cxt.getIRCache().get(m));
133+
// }
134+
// }
135+
136+
System.out.println("Retranslating SSA IR to standard flavour.");
137+
for(Map.Entry<MethodNode, ControlFlowGraph> e : cxt.getIRCache().entrySet()) {
138+
try {
139+
MethodNode mn = e.getKey();
140+
ControlFlowGraph cfg = e.getValue();
141+
142+
BoissinotDestructor.leaveSSA(cfg);
143+
cfg.getLocals().realloc(cfg);
144+
(new ControlFlowGraphDumper(cfg, mn)).dump();
145+
cfgs.put(mn, cfg);
146+
}catch(Exception e3){e3.printStackTrace();}
147+
}
148+
149+
System.out.println("Rewriting jar.");
150+
// dumpJar(app, dl, masterGroup, "out/osb5.jar");
151+
152+
System.out.println("Finished.");
153+
154+
return 0;
155+
}
156+
157+
private static void run(AnalysisContext cxt, PassGroup group) {
158+
group.accept(cxt, null, new ArrayList<>());
159+
}
160+
161+
private static IPass[] getTransformationPasses() {
162+
RenamingHeuristic heuristic = RenamingHeuristic.RENAME_ALL;
163+
return new IPass[] {
164+
// new ConcreteStaticInvocationPass(),
165+
// new ClassRenamerPass(heuristic),
166+
// new MethodRenamerPass(heuristic),
167+
// new FieldRenamerPass(),
168+
// new CallgraphPruningPass(),
169+
170+
// new PassGroup("Interprocedural Optimisations")
171+
// .add(new ConstantParameterPass())
172+
// new LiftConstructorCallsPass(),
173+
// new DemoteRangesPass(),
174+
175+
new ConstantExpressionReorderPass(),
176+
// new FieldRSADecryptionPass(),
177+
// new ConstantParameterPass(),
178+
// new ConstantExpressionEvaluatorPass(),
179+
// new DeadCodeEliminationPass()
180+
181+
};
182+
}
183+
}

src/main/java/club/bytecode/the/jda/JDA.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package club.bytecode.the.jda;
22

33
import club.bytecode.the.jda.api.ExceptionUI;
4-
import club.bytecode.the.jda.api.Plugin;
4+
import club.bytecode.the.jda.api.JDAPlugin;
55
import club.bytecode.the.jda.api.PluginLoader;
66
import club.bytecode.the.jda.gui.MainViewerGUI;
77
import club.bytecode.the.jda.gui.fileviewer.BytecodeFoldParser;
@@ -47,7 +47,7 @@ public class JDA {
4747
private static List<String> recentFiles = new ArrayList<>();
4848
public static String lastDirectory = "";
4949
public static List<Process> createdProcesses = new ArrayList<>();
50-
public static List<Plugin> plugins = new ArrayList<>();
50+
public static List<JDAPlugin> plugins = new ArrayList<>();
5151

5252
/**
5353
* Main startup
@@ -94,7 +94,7 @@ else if (!pluginsDir.isDirectory())
9494
System.out.println("Skipping non-jar " + pluginFile.getName());
9595
continue;
9696
}
97-
Plugin pluginInstance = PluginLoader.tryLoadPlugin(pluginFile);
97+
JDAPlugin pluginInstance = PluginLoader.tryLoadPlugin(pluginFile);
9898
if (pluginInstance != null)
9999
plugins.add(pluginInstance);
100100
}
@@ -105,7 +105,7 @@ public static void onGUILoad() {
105105
atmf.putMapping(BytecodeTokenizer.SYNTAX_STYLE_BYTECODE, BytecodeTokenizer.class.getName());
106106
FoldParserManager.get().addFoldParserMapping(BytecodeTokenizer.SYNTAX_STYLE_BYTECODE, new BytecodeFoldParser());
107107

108-
plugins.forEach(Plugin::onGUILoad);
108+
plugins.forEach(JDAPlugin::onGUILoad);
109109
}
110110

111111
// todo: rewrite
@@ -138,7 +138,7 @@ public static void boot(String[] args) {
138138
}
139139

140140
private static void onExit() {
141-
plugins.forEach(Plugin::onExit);
141+
plugins.forEach(JDAPlugin::onExit);
142142

143143
for (Process proc : createdProcesses)
144144
proc.destroy();
@@ -329,6 +329,13 @@ public static FileContainer loadClassfile(File fileToOpen, String fn) {
329329

330330
public static void addFile(FileContainer fc) {
331331
JDA.files.add(fc);
332+
for (String cc : fc.getFiles().keySet()) {
333+
try {
334+
fc.add(fc.loadClass(cc));
335+
}catch(Exception e){
336+
e.printStackTrace();
337+
}
338+
}
332339
plugins.forEach((plugin -> plugin.onAddFile(fc)));
333340
}
334341

src/main/java/club/bytecode/the/jda/api/Plugin.java renamed to src/main/java/club/bytecode/the/jda/api/JDAPlugin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import club.bytecode.the.jda.FileContainer;
44

5-
public interface Plugin {
5+
public interface JDAPlugin {
66
int onGUILoad();
77

88
int onExit();

src/main/java/club/bytecode/the/jda/api/PluginLoader.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import java.net.URLClassLoader;
99

1010
public class PluginLoader {
11-
public static Plugin tryLoadPlugin(File pluginFile) throws MalformedURLException {
11+
public static JDAPlugin tryLoadPlugin(File pluginFile) throws MalformedURLException {
1212
String pluginFileName = pluginFile.getName();
1313
try {
1414
ClassLoader loader = new URLClassLoader(new URL[] { pluginFile.toURI().toURL() }) {
@@ -32,7 +32,7 @@ public URL getResource(String name) {
3232
return null;
3333
}
3434

35-
Class<? extends Plugin> clazz = Class.forName(mainClass, true, loader).asSubclass(Plugin.class);
35+
Class<? extends JDAPlugin> clazz = Class.forName(mainClass, true, loader).asSubclass(JDAPlugin.class);
3636
return clazz.getConstructor().newInstance();
3737
} catch (ReflectiveOperationException e) {
3838
System.err.println("Failed to load plugin " + pluginFileName);

src/main/java/club/bytecode/the/jda/decompilers/Decompilers.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import java.util.Map;
99

1010
public class Decompilers {
11-
static final Map<String, JDADecompiler> BY_NAME = new LinkedHashMap<>();
11+
public static final Map<String, JDADecompiler> BY_NAME = new LinkedHashMap<>();
1212

1313
public final static JDADecompiler PROCYON = new ProcyonDecompiler();
1414
public final static JDADecompiler CFR = new CFRDecompiler();

0 commit comments

Comments
 (0)