Skip to content

Commit 78da22c

Browse files
committed
New optional --lvt argument, possible values STRIP and FERNFLOWER. STRIP will remove the LocalVariableTable {Emulating the old MC versions where it was removed} and FERNFLOWER will rename any 'snowman' LV's to Fermflower 'var'+index names.
1 parent a58bdd3 commit 78da22c

6 files changed

Lines changed: 211 additions & 22 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package de.oceanlabs.mcp.mcinjector;
2+
3+
public enum LVTNaming
4+
{
5+
STRIP,
6+
FERNFLOWER
7+
}

src/main/java/de/oceanlabs/mcp/mcinjector/MCInjector.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ public class MCInjector
1313
{
1414
private final static Logger log = Logger.getLogger("MCInjector");
1515
public static final String VERSION = "MCInjector v3.2 by Searge, LexManos, Fesh0r";
16-
16+
1717
public static void main(String[] args) throws Exception
1818
{
19-
19+
2020
OptionParser parser = new OptionParser();
2121
parser.accepts("help").forHelp();
2222
parser.accepts("version").forHelp();
@@ -29,6 +29,7 @@ public static void main(String[] args) throws Exception
2929
parser.accepts("jsonIn").withRequiredArg();
3030
parser.accepts("applyMarkers");
3131
parser.accepts("generateParams");
32+
parser.accepts("lvt").withRequiredArg().ofType(LVTNaming.class).defaultsTo(LVTNaming.STRIP);
3233

3334
try
3435
{
@@ -54,10 +55,11 @@ else if (options.has("version"))
5455
int index = (Integer)options.valueOf("index");
5556
boolean applyM = options.has("applyMarkers");
5657
boolean genArgs = options.has("generateParams");
57-
58+
LVTNaming naming = (LVTNaming)options.valueOf("lvt");
59+
5860
MCInjector.log.setUseParentHandlers(false);
5961
MCInjector.log.setLevel(Level.ALL);
60-
62+
6163
if (log != null)
6264
{
6365
FileHandler filehandler = new FileHandler(log);
@@ -69,13 +71,13 @@ else if (options.has("version"))
6971
public void publish(LogRecord record)
7072
{
7173
System.out.println(String.format(record.getMessage(), record.getParameters()));
72-
74+
7375
}
7476
@Override public void flush() {}
7577
@Override public void close() throws SecurityException {}
7678
});
7779
}
78-
80+
7981
log(MCInjector.VERSION);
8082
log("Input: " + jarIn);
8183
log("Output: " + jarOut);
@@ -86,10 +88,11 @@ public void publish(LogRecord record)
8688
log("Json: " + jsonIn);
8789
log("ApplyMarker: " + applyM);
8890
log("GenArgs: " + genArgs);
89-
91+
log("LVT: " + naming);
92+
9093
try
9194
{
92-
MCInjectorImpl.process(jarIn, jarOut, mapIn, log, mapOut, index, jsonIn, applyM, genArgs);
95+
MCInjectorImpl.process(jarIn, jarOut, mapIn, log, mapOut, index, jsonIn, applyM, genArgs, naming);
9396
}
9497
catch (Exception e)
9598
{

src/main/java/de/oceanlabs/mcp/mcinjector/MCInjectorImpl.java

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.io.OutputStream;
1313
import java.io.Reader;
1414
import java.io.Writer;
15+
import java.lang.reflect.Field;
1516
import java.util.ArrayList;
1617
import java.util.Collections;
1718
import java.util.Enumeration;
@@ -31,7 +32,9 @@
3132
import org.objectweb.asm.ClassReader;
3233
import org.objectweb.asm.ClassVisitor;
3334
import org.objectweb.asm.ClassWriter;
35+
import org.objectweb.asm.MethodVisitor;
3436
import org.objectweb.asm.tree.ClassNode;
37+
import org.objectweb.asm.tree.MethodNode;
3538

3639
import com.google.gson.*;
3740

@@ -41,6 +44,8 @@
4144
import de.oceanlabs.mcp.mcinjector.adaptors.ApplyMarker;
4245
import de.oceanlabs.mcp.mcinjector.adaptors.GenerateMap;
4346
import de.oceanlabs.mcp.mcinjector.adaptors.JsonAttribute;
47+
import de.oceanlabs.mcp.mcinjector.adaptors.LVTFernflower;
48+
import de.oceanlabs.mcp.mcinjector.adaptors.LVTStrip;
4449
import de.oceanlabs.mcp.mcinjector.adaptors.ReadMarker;
4550

4651
public class MCInjectorImpl
@@ -73,24 +78,31 @@ public synchronized Enumeration keys()
7378
private boolean applyMarkers = false;
7479
public final InheratanceMap inheratance;
7580
public boolean genParams = false;
81+
public LVTNaming naming = LVTNaming.STRIP;
7682

7783
public static void process(String inFile, String outFile, String mapFile, String logFile, String outMapFile, int index, String classJson, boolean applyMarkers)
7884
throws IOException
7985
{
8086
process(inFile, outFile, mapFile, logFile, outMapFile, index, classJson, applyMarkers, false);
8187
}
88+
public static void process(String inFile, String outFile, String mapFile, String logFile, String outMapFile, int index, String classJson, boolean applyMarkers, boolean genParams)
89+
throws IOException
90+
{
91+
process(inFile, outFile, mapFile, logFile, outMapFile, index, classJson, applyMarkers, false, LVTNaming.STRIP);
92+
}
8293

8394
public static void process(
8495
String inFile, String outFile, String mapFile, String logFile,
8596
String outMapFile, int index, String classJson,
86-
boolean applyMarkers, boolean genParams)
97+
boolean applyMarkers, boolean genParams, LVTNaming naming)
8798
throws IOException
8899
{
89100
MCInjectorImpl mci = new MCInjectorImpl(index, outMapFile != null);
90101
mci.loadJson(classJson);
91102
mci.loadMap(mapFile);
92103
mci.applyMarkers = applyMarkers;
93104
mci.genParams = genParams;
105+
mci.naming = naming;
94106

95107
mci.processJar(inFile, outFile);
96108

@@ -600,7 +612,14 @@ public byte[] processClass(byte[] cls, boolean readOnly)
600612
}
601613
else
602614
{
603-
ca = new ApplyMap(cn, this);
615+
ca = new ApplyMap(ca, this);
616+
617+
switch (naming)
618+
{
619+
case STRIP: ca = new LVTStrip (ca, this); break;
620+
case FERNFLOWER: ca = new LVTFernflower(ca, this); break;
621+
}
622+
604623
ca = new JsonAttribute(ca, this);
605624

606625
if (applyMarkers)
@@ -624,4 +643,27 @@ public byte[] processClass(byte[] cls, boolean readOnly)
624643
return writer.toByteArray();
625644
}
626645

627-
}
646+
private static Field field_mv;
647+
public static MethodNode getMethodNode(MethodVisitor mv)
648+
{
649+
try
650+
{
651+
if (field_mv == null)
652+
{
653+
field_mv = MethodVisitor.class.getDeclaredField("mv");
654+
field_mv.setAccessible(true);
655+
}
656+
MethodVisitor tmp = mv;
657+
while (!(tmp instanceof MethodNode) && tmp != null)
658+
tmp = (MethodVisitor)field_mv.get(tmp);
659+
return (MethodNode)tmp;
660+
}
661+
catch (Exception e)
662+
{
663+
if (e instanceof RuntimeException)
664+
throw (RuntimeException)e;
665+
throw new RuntimeException(e);
666+
667+
}
668+
}
669+
}

src/main/java/de/oceanlabs/mcp/mcinjector/adaptors/ApplyMap.java

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
import java.util.ArrayList;
44
import java.util.Arrays;
5+
import java.util.Collections;
6+
import java.util.Comparator;
7+
import java.util.HashMap;
58
import java.util.List;
9+
import java.util.Map;
610
import java.util.logging.Level;
711
import java.util.logging.Logger;
812

@@ -11,7 +15,6 @@
1115
import org.objectweb.asm.Opcodes;
1216
import org.objectweb.asm.Type;
1317
import org.objectweb.asm.tree.AbstractInsnNode;
14-
import org.objectweb.asm.tree.ClassNode;
1518
import org.objectweb.asm.tree.LabelNode;
1619
import org.objectweb.asm.tree.LocalVariableNode;
1720
import org.objectweb.asm.tree.MethodNode;
@@ -24,13 +27,11 @@ public class ApplyMap extends ClassVisitor
2427
private static final Logger log = Logger.getLogger("MCInjector");
2528
private MCInjectorImpl mci;
2629
String className;
27-
private ClassNode cn;
2830

29-
public ApplyMap(ClassNode cn, MCInjectorImpl mci)
31+
public ApplyMap(ClassVisitor cn, MCInjectorImpl mci)
3032
{
3133
super(Opcodes.ASM5, cn);
3234
this.mci = mci;
33-
this.cn = cn;
3435
}
3536

3637
@Override
@@ -52,7 +53,7 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si
5253

5354
if (!mci.generate) log.log(Level.FINER, " Name: " + name + " Desc: " + desc + " Sig: " + signature);
5455

55-
String clsSig = this.className + "." + name + desc;
56+
final String clsSig = this.className + "." + name + desc;
5657

5758
exceptions = processExceptions(clsSig, exceptions);
5859

@@ -62,9 +63,16 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si
6263
return super.visitMethod(access, name, desc, signature, exceptions);
6364
}
6465

65-
MethodNode mn = (MethodNode)cn.visitMethod(access, name, desc, signature, exceptions);
66-
mn = processLVT(className, clsSig, mn);
67-
return mn;
66+
MethodNode mn = (MethodNode)cv.visitMethod(access, name, desc, signature, exceptions);
67+
return new MethodVisitor(api, mn)
68+
{
69+
@Override
70+
public void visitEnd()
71+
{
72+
super.visitEnd();
73+
processLVT(className, clsSig, MCInjectorImpl.getMethodNode(mv));
74+
}
75+
};
6876
}
6977

7078
private String[] processExceptions(String clsSig, String[] exceptions)
@@ -143,25 +151,57 @@ else if (tmp.getType() != AbstractInsnNode.LABEL)
143151
LabelNode start = (LabelNode)mn.instructions.getFirst();
144152
LabelNode end = (LabelNode)mn.instructions.getLast();
145153

146-
mn.localVariables = new ArrayList<LocalVariableNode>();
154+
Map<Integer, LocalVariableNode> lvt = new HashMap<Integer, LocalVariableNode>();
155+
if (mn.localVariables != null)
156+
{
157+
for (LocalVariableNode lvn : mn.localVariables)
158+
{
159+
if (lvt.containsKey(lvn.index))
160+
{
161+
log.info(" DUPLICATE LVT INDEX: " + lvn.index);
162+
}
163+
lvt.put(lvn.index, lvn);
164+
}
165+
}
147166

148167
for (int x = 0, y = x; x < params.size(); x++, y++)
149168
{
150169
String arg = params.get(x);
151170
String desc = types.get(x).getDescriptor();
171+
LocalVariableNode lvn = lvt.get(y);
152172

153173
if (arg.equals(""))
154174
{
155175
log.fine(" Skipping argument " + x + " (" + y + ") -> " + desc);
156176
}
157177
else
158178
{
159-
log.fine(" Naming argument " + x + " (" + y + ") -> " + arg + " " + desc);
160-
mn.localVariables.add(new LocalVariableNode(arg, desc, null, start, end, y));
179+
if (lvn != null)
180+
{
181+
log.fine(" ReNaming argument " + x + " (" + y + "): " + lvn.name + " -> " + arg);
182+
lvn.name = arg;
183+
}
184+
else
185+
{
186+
log.fine(" Naming argument " + x + " (" + y + ") -> " + arg + " " + desc);
187+
lvt.put(y, new LocalVariableNode(arg, desc, null, start, end, y));
188+
}
161189
}
162190

163191
if (desc.equals("J") || desc.equals("D")) y++;
164192
}
193+
194+
mn.localVariables = new ArrayList<LocalVariableNode>();
195+
mn.localVariables.addAll(lvt.values());
196+
Collections.sort(mn.localVariables, new Comparator<LocalVariableNode>()
197+
{
198+
@Override
199+
public int compare(LocalVariableNode o1, LocalVariableNode o2)
200+
{
201+
return (o1.index < o2.index ? -1 : (o1.index == o2.index ? 0 : 1));
202+
}
203+
});
204+
165205
return mn;
166206
}
167207
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package de.oceanlabs.mcp.mcinjector.adaptors;
2+
3+
import java.util.logging.Logger;
4+
5+
import org.objectweb.asm.ClassVisitor;
6+
import org.objectweb.asm.MethodVisitor;
7+
import org.objectweb.asm.Opcodes;
8+
import org.objectweb.asm.tree.LocalVariableNode;
9+
import org.objectweb.asm.tree.MethodNode;
10+
11+
import de.oceanlabs.mcp.mcinjector.MCInjectorImpl;
12+
13+
public class LVTFernflower extends ClassVisitor
14+
{
15+
private static final Logger log = Logger.getLogger("MCInjector");
16+
//private MCInjectorImpl mci;
17+
String className;
18+
19+
public LVTFernflower(ClassVisitor cn, MCInjectorImpl mci)
20+
{
21+
super(Opcodes.ASM5, cn);
22+
//this.mci = mci;
23+
}
24+
25+
@Override
26+
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
27+
{
28+
this.className = name;
29+
super.visit(version, access, name, signature, superName, interfaces);
30+
}
31+
32+
@Override
33+
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
34+
{
35+
return new MethodVisitor(api, cv.visitMethod(access, name, desc, signature, exceptions))
36+
{
37+
@Override
38+
public void visitEnd()
39+
{
40+
super.visitEnd();
41+
MethodNode mn = MCInjectorImpl.getMethodNode(mv);
42+
if (mn.localVariables != null && mn.localVariables.size() > 0)
43+
{
44+
for (LocalVariableNode lvn : mn.localVariables)
45+
{
46+
if (0x2603 != lvn.name.charAt(0)) // Snowmen, added in 1.8.2? rename them to FF names
47+
continue;
48+
log.info(" Renaming LVT: " + lvn.index + " " + lvn.name + " " +lvn.desc + " -> " + "var" + lvn.index);
49+
lvn.name = "var" + lvn.index;
50+
}
51+
}
52+
}
53+
};
54+
}
55+
}

0 commit comments

Comments
 (0)