-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathJaviumCore2.java
312 lines (288 loc) · 15 KB
/
JaviumCore2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class JaviumCore2 {
public static byte readU1(DataInputStream dis) {
try {
return dis.readByte();
} catch (Exception e) {
printError(e);
}
return -1; //TODO placeholder. Is there a better way to do this?
}
public static short readU2(DataInputStream dis) {
try {
return (short)dis.readUnsignedShort();
} catch (Exception e) {
printError(e);
}
return -1; //TODO placeholder. Is there a better way to do this?
}
public static int readU4(DataInputStream dis) {
try {
return dis.readInt();
} catch (Exception e) {
printError(e);
}
return -1; //TODO placeholder. Is there a better way to do this?
}
private static void printError(Exception e) {
System.err.printf("ERROR: {%s}\n", e);
System.exit(-1);
}
public abstract class ConstantPoolItem {
private byte tag;
byte getTag() {
return tag;
}
public String toString() {
return "Tag = " + tag + "\n";
}
}
public class ConstantPoolItemClass extends ConstantPoolItem {
private short name_index;
ConstantPoolItemClass(byte tag, short name_index) {
super.tag = tag;
this.name_index = name_index;
}
short getNameIndex() {
return name_index;
}
public String toString() {
return super.toString() + "\n"
+ "Name Index = " + name_index + "\n";
}
}
public class ConstantPoolItemFieldMethodInterface extends ConstantPoolItem {
private short class_index;
private short name_type_index;
ConstantPoolItemFieldMethodInterface(byte tag, short class_index, short name_type_index) {
super.tag = tag;
this.class_index = class_index;
this.name_type_index = name_type_index;
}
short getClassIndex() {
return class_index;
}
short getNameTypeIndex() {
return name_type_index;
}
public String toString() {
return super.toString() + "\n"
+ "Class Index = " + class_index + "\n"
+ "Name/Type Index = " + name_type_index + "\n";
}
}
private enum ConstantPoolInfo {
CONSTANT_CLASS (7),
CONSTANT_FIELD (9),
CONSTANT_METHOD (10),
CONSTANT_INTERFACE_METHOD (11),
CONSTANT_STRING (8),
CONSTANT_INTEGER (3),
CONSTANT_FLOAT (4),
CONSTANT_LONG (5),
CONSTANT_DOUBLE (6),
CONSTANT_NAME_AND_TYPE (12),
CONSTANT_UTF8 (1),
CONSTANT_METHOD_HANDLE (15),
CONSTANT_METHOD_TYPE (16),
CONSTANT_INVOKE_DYNAMIC (18);
Integer value;
ConstantPoolInfo (Integer value) {
this.value = value;
}
private Integer getValue() {
return this.value;
}
// Following 6 lines stolen from https://stackoverflow.com/a/65315398
private static final Map<Integer, ConstantPoolInfo> lookup =
Arrays.stream(ConstantPoolInfo.values()).collect(Collectors.toMap(ConstantPoolInfo::getValue, Function.identity()));
public static ConstantPoolInfo fromValue(int value) {
return lookup.get(value);
}
}
public static void main(String[] args) {
// Open .class file
String fileName = "./Main.class";
System.out.println("Parsing Class File: " + fileName);
try {
FileInputStream fis = new FileInputStream(fileName);
DataInputStream dis = new DataInputStream(fis);
// Read magic (u4)
String magic = Integer.toHexString(readU4(dis));
System.out.println(" Magic=" + magic);
// Read minor version (u2)
short minor_version = readU2(dis);
System.out.println(" Minor version=" + minor_version);
// Read major version (u2)
short major_version = readU2(dis);
System.out.println(" Major version=" + major_version);
// Read constant pool count (u2)
short constant_pool_count = readU2(dis);
System.out.println(" Constant pool count=" + constant_pool_count);
// Read constant pool
for (int i = 0; i < constant_pool_count -1; i++) {
// Read tag (u1)
byte tag = readU1(dis);
System.out.println(" Tag=" + tag + ", Value: " + ConstantPoolInfo.fromValue(tag));
// Read info
System.out.println(" Info=");
// if tag is CONSTANT_Class_info
if (tag == ConstantPoolInfo.CONSTANT_CLASS.getValue()) {
// Read name index (u2) -> constant_pool
short cp_name_index = readU2(dis);
System.out.println(" Name Index=" + cp_name_index + ", " + ConstantPoolInfo.fromValue(cp_name_index));
}
// else if tag is CONSTANT_Fieldref_info, CONSTANT_Methodref_info, CONSTANT InterfaceMethodref_info
else if(tag == ConstantPoolInfo.CONSTANT_FIELD.getValue() || tag == ConstantPoolInfo.CONSTANT_METHOD.getValue() || tag == ConstantPoolInfo.CONSTANT_INTERFACE_METHOD.getValue()) {
// Read class index (u2) -> constant_pool
short cp_class_index = readU2(dis);
System.out.println(" Class Index=" + cp_class_index + ", " + ConstantPoolInfo.fromValue(cp_class_index));
// Read name and type index (u2) -> constant_pool
short cp_name_and_type_index = readU2(dis);
System.out.println(" Name and Type Index=" + cp_name_and_type_index + ", " + ConstantPoolInfo.fromValue(cp_name_and_type_index));
}
// else if tag is CONSTANT_String_info
else if(tag == ConstantPoolInfo.CONSTANT_STRING.getValue()) {
// Read string_index (u2) -> constant_pool
short cp_string_index = readU2(dis);
System.out.println(" String Index=" + cp_string_index + ", " + ConstantPoolInfo.fromValue(cp_string_index));
}
// else if tag is CONSTANT_Integer_info, CONSTANT_Float_info
else if(tag == ConstantPoolInfo.CONSTANT_INTEGER.getValue() || tag == ConstantPoolInfo.CONSTANT_FLOAT.getValue()) {
// Read bytes (u4)
int cp_int = readU4(dis);
System.out.println(" Integer=" + cp_int);
}
// else if tag is CONSTANT_Long_info, CONSTANT_Double_info
else if(tag == ConstantPoolInfo.CONSTANT_LONG.getValue() || tag == ConstantPoolInfo.CONSTANT_DOUBLE.getValue()) {
// Read high bytes (u4)
int cp_high_bytes = readU4(dis);
// Read low bytes (u4)
int cp_low_bytes = readU4(dis);
long cp_long_double_value = ((long) cp_high_bytes << 32) + cp_low_bytes;
System.out.println(" Long/Double Value=" + cp_long_double_value);
}
// else if tag is CONSTANT_NameAndType_info
else if(tag == ConstantPoolInfo.CONSTANT_NAME_AND_TYPE.getValue()) {
// Read name index (u2) -> constant_pool
short cp_name_index = readU2(dis);
System.out.println(" Name Index=" + cp_name_index + ", " + ConstantPoolInfo.fromValue(cp_name_index));
// Read descriptor index (u2) -> constant_pool
short cp_descriptor_index = readU2(dis);
System.out.println(" Descriptor Index=" + cp_descriptor_index + ", " + ConstantPoolInfo.fromValue(cp_descriptor_index));
}
// else if tag is CONSTANT_Utf8_info
else if(tag == ConstantPoolInfo.CONSTANT_UTF8.getValue()) {
// Read length (u2)
short length = readU2(dis);
System.out.println(" Length=" + length);
// Read bytes[length] (u1[length])
byte[] value = dis.readNBytes(length);
String valueString = "";
for (int j = 0; j < value.length; j++) {
valueString += (char)value[j];
}
System.out.println(" Value=" + valueString);
}
// else if tag is CONSTANT_MethodHandle_info
else if(tag == ConstantPoolInfo.CONSTANT_METHOD_HANDLE.getValue()) {
// Read reference kind (u1)
byte kind = readU1(dis);
System.out.println(" RefKind= " + kind);
// Read reference index (u2) -> constant_pool
short refIndex = readU2(dis);
System.out.println(" RefIndex= " + refIndex + " (" + ConstantPoolInfo.fromValue(refIndex) + ")");
}
// else if tag is CONSTANT_MethodType_info
else if(tag == ConstantPoolInfo.CONSTANT_METHOD_TYPE.getValue()) {
// Read descriptor index (u2) -> constant_pool
short descIndex = readU2(dis);
System.out.println(" Desc Index= " + descIndex + " (" + ConstantPoolInfo.fromValue(descIndex) + ")");
}
// else if tag is CONSTANT_InvokeDynamic_info
// Read bootstrap method attr index (u2) -> attributes -> bootstrap_methods
// Read name and type index (u2) -> constant_pool
}
// Read access flags (u2)
// Read this class (u2)
// Read super class (u2)
// Read interface count (u2)
// Read interfaces (CONSTANT_Class_info[])
// Read tag (u1)
// Read name index (u2) -> constant_pool
// Read field count (u2)
// Read access flags (u2)
// Read name index (u2) -> constant_pool
// Read descriptor index (u2) -> constant_pool
// Read attribute count (u2)
// Read attributes
// Read fields
// Read method count (u2)
// Read methods
// Read attribute count (u2)
// Read attributes
// Read attribute name index (u2) -> constant_pool
// Read attribute length (u4)
// Read info
// if attribute length suggests attribute is ConstantValue_attribute
// info = Read constant value index (u2) -> constant_pool
// else if attribute length suggests attribute is Code_attribute
//info =
// Read max stack (u2)
// Read max locals (u2)
// Read code length (u4)
// Read code (u1[code length])
// Read exception table length (u2)
// Read exception table (contents[exception table length])
// Read start pc (u2) -> this -> code
// Read end pc (u2) -> this -> code
// Read handler pc (u2) -> this -> code
// Read catch type (u2) -> constant_pool
// Read attribute count (u2)
// Read attributes
// else if attribute length suggests attribute is StackMapTable_attribute
// Not going to implement yet
// else if attribute length suggests attribute is Exceptions_attribute
// Not going to implement yet
// else if attribute length suggests attribute is InnerClasses_attribute
// Not going to implement yet
// else if attribute length suggests attribute is EnclosingMethod_attribute
// Not going to implement yet
// else if attribute length suggests attribute is Synthetic_attribute
// Not going to implement yet
// else if attribute length suggests attribute is Signature_attribute
// Not going to implement yet
// else if attribute length suggests attribute is SourceFile_attribute
// Not going to implement yet
// else if attribute length suggests attribute is SourceDebugExtension_attribute
// Not going to implement yet
// else if attribute length suggests attribute is LineNumberTableAttribute
// Not going to implement yet
// else if attribute length suggests attribute is LocalVariableTable_attribute
// Not going to implement yet
// else if attribute length suggests attribute is LocalVariableTypeTable_attribute
// Not going to implement yet
// else if attribute length suggests attribute is Deprecated_attribute
// Not going to implement yet
// else if attribute length suggests attribute is RuntimeVisibleAnnotations_attribute
// Not going to implement yet
// else if attribute length suggests attribute is RuntimeInvisibleAnnotations_attribute
// Not going to implement yet
// else if attribute length suggests attribute is RuntimeVisibleParameterAnnotations_attribute
// Not going to implement yet
// else if attribute length suggests attribute is RuntimeInvisibleParameterAnnotations_attribute
// Not going to implement yet
// else if attribute length suggests attribute is AnnotationDefault_attribute
// Not going to implement yet
// else if attribute length suggests attribute is BootstrapMethods_attribute
// Not going to implement yet
} catch (Exception e) {
System.err.printf("ERROR: {%s}\n", e);
}
}
}