summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/bytecode/LocalVariableRenamer.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/cuchaz/enigma/bytecode/LocalVariableRenamer.java')
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/LocalVariableRenamer.java119
1 files changed, 119 insertions, 0 deletions
diff --git a/src/main/java/cuchaz/enigma/bytecode/LocalVariableRenamer.java b/src/main/java/cuchaz/enigma/bytecode/LocalVariableRenamer.java
new file mode 100644
index 0000000..d0ce107
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/bytecode/LocalVariableRenamer.java
@@ -0,0 +1,119 @@
1/*******************************************************************************
2 * Copyright (c) 2015 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Lesser General Public
5 * License v3.0 which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.html
7 * <p>
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.bytecode;
12
13import cuchaz.enigma.mapping.ArgumentEntry;
14import cuchaz.enigma.mapping.BehaviorEntry;
15import cuchaz.enigma.mapping.EntryFactory;
16import cuchaz.enigma.mapping.Translator;
17import javassist.CtBehavior;
18import javassist.CtClass;
19import javassist.bytecode.*;
20
21
22public class LocalVariableRenamer {
23
24 private Translator m_translator;
25
26 public LocalVariableRenamer(Translator translator) {
27 m_translator = translator;
28 }
29
30 public void rename(CtClass c) {
31 for (CtBehavior behavior : c.getDeclaredBehaviors()) {
32
33 // if there's a local variable table, just rename everything to v1, v2, v3, ... for now
34 CodeAttribute codeAttribute = behavior.getMethodInfo().getCodeAttribute();
35 if (codeAttribute == null) {
36 continue;
37 }
38
39 BehaviorEntry behaviorEntry = EntryFactory.getBehaviorEntry(behavior);
40 ConstPool constants = c.getClassFile().getConstPool();
41
42 LocalVariableAttribute table = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
43 if (table != null) {
44 renameLVT(behaviorEntry, constants, table);
45 }
46
47 LocalVariableTypeAttribute typeTable = (LocalVariableTypeAttribute) codeAttribute.getAttribute(LocalVariableAttribute.typeTag);
48 if (typeTable != null) {
49 renameLVTT(typeTable, table);
50 }
51 }
52 }
53
54 // DEBUG
55 @SuppressWarnings("unused")
56 private void dumpTable(LocalVariableAttribute table) {
57 for (int i = 0; i < table.tableLength(); i++) {
58 System.out.println(String.format("\t%d (%d): %s %s",
59 i, table.index(i), table.variableName(i), table.descriptor(i)
60 ));
61 }
62 }
63
64 private void renameLVT(BehaviorEntry behaviorEntry, ConstPool constants, LocalVariableAttribute table) {
65
66 // skip empty tables
67 if (table.tableLength() <= 0) {
68 return;
69 }
70
71 // where do we start counting variables?
72 int starti = 0;
73 if (table.variableName(0).equals("this")) {
74 // skip the "this" variable
75 starti = 1;
76 }
77
78 // rename method arguments first
79 int numArgs = 0;
80 if (behaviorEntry.getSignature() != null) {
81 numArgs = behaviorEntry.getSignature().getArgumentTypes().size();
82 for (int i = starti; i < starti + numArgs && i < table.tableLength(); i++) {
83 int argi = i - starti;
84 String argName = m_translator.translate(new ArgumentEntry(behaviorEntry, argi, ""));
85 if (argName == null) {
86 argName = "a" + (argi + 1);
87 }
88 renameVariable(table, i, constants.addUtf8Info(argName));
89 }
90 }
91
92 // then rename the rest of the args, if any
93 for (int i = starti + numArgs; i < table.tableLength(); i++) {
94 int firstIndex = table.index(starti + numArgs);
95 renameVariable(table, i, constants.addUtf8Info("v" + (table.index(i) - firstIndex + 1)));
96 }
97 }
98
99 private void renameLVTT(LocalVariableTypeAttribute typeTable, LocalVariableAttribute table) {
100 // rename args to the same names as in the LVT
101 for (int i = 0; i < typeTable.tableLength(); i++) {
102 renameVariable(typeTable, i, getNameIndex(table, typeTable.index(i)));
103 }
104 }
105
106 private void renameVariable(LocalVariableAttribute table, int i, int stringId) {
107 // based off of LocalVariableAttribute.nameIndex()
108 ByteArray.write16bit(stringId, table.get(), i * 10 + 6);
109 }
110
111 private int getNameIndex(LocalVariableAttribute table, int index) {
112 for (int i = 0; i < table.tableLength(); i++) {
113 if (table.index(i) == index) {
114 return table.nameIndex(i);
115 }
116 }
117 return 0;
118 }
119}