Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java
38867 views
1
/*
2
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
26
27
import com.sun.tools.classfile.AccessFlags;
28
import com.sun.tools.classfile.Annotation;
29
import com.sun.tools.classfile.Annotation.*;
30
import com.sun.tools.classfile.AnnotationDefault_attribute;
31
import com.sun.tools.classfile.Attribute;
32
import com.sun.tools.classfile.Attributes;
33
import com.sun.tools.classfile.BootstrapMethods_attribute;
34
import com.sun.tools.classfile.CharacterRangeTable_attribute;
35
import com.sun.tools.classfile.ClassFile;
36
import com.sun.tools.classfile.Code_attribute;
37
import com.sun.tools.classfile.CompilationID_attribute;
38
import com.sun.tools.classfile.ConstantPool;
39
import com.sun.tools.classfile.ConstantPool.*;
40
import com.sun.tools.classfile.ConstantPoolException;
41
import com.sun.tools.classfile.ConstantValue_attribute;
42
import com.sun.tools.classfile.DefaultAttribute;
43
import com.sun.tools.classfile.Deprecated_attribute;
44
import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
45
import com.sun.tools.classfile.EnclosingMethod_attribute;
46
import com.sun.tools.classfile.Exceptions_attribute;
47
import com.sun.tools.classfile.Field;
48
import com.sun.tools.classfile.InnerClasses_attribute;
49
import com.sun.tools.classfile.InnerClasses_attribute.Info;
50
import com.sun.tools.classfile.Instruction;
51
import com.sun.tools.classfile.Instruction.TypeKind;
52
import com.sun.tools.classfile.LineNumberTable_attribute;
53
import com.sun.tools.classfile.LocalVariableTable_attribute;
54
import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
55
import com.sun.tools.classfile.Method;
56
import com.sun.tools.classfile.MethodParameters_attribute;
57
import com.sun.tools.classfile.Opcode;
58
import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
59
import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
60
import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
61
import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
62
import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute;
63
import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute;
64
import com.sun.tools.classfile.Signature_attribute;
65
import com.sun.tools.classfile.SourceDebugExtension_attribute;
66
import com.sun.tools.classfile.SourceFile_attribute;
67
import com.sun.tools.classfile.SourceID_attribute;
68
import com.sun.tools.classfile.StackMapTable_attribute;
69
import com.sun.tools.classfile.StackMapTable_attribute.*;
70
import com.sun.tools.classfile.StackMap_attribute;
71
import com.sun.tools.classfile.Synthetic_attribute;
72
import com.sun.tools.classfile.TypeAnnotation;
73
import com.sun.tools.classfile.TypeAnnotation.Position;
74
import static com.sun.tools.classfile.TypeAnnotation.TargetType.THROWS;
75
import java.util.*;
76
import java.io.*;
77
import java.util.jar.JarEntry;
78
import java.util.jar.JarFile;
79
import xmlkit.XMLKit.Element;
80
81
/*
82
* @author jrose, ksrini
83
*/
84
public class ClassReader {
85
86
private static final CommandLineParser CLP = new CommandLineParser(""
87
+ "-source: +> = \n"
88
+ "-dest: +> = \n"
89
+ "-encoding: +> = \n"
90
+ "-jcov $ \n -nojcov !-jcov \n"
91
+ "-verbose $ \n -noverbose !-verbose \n"
92
+ "-keepPath $ \n -nokeepPath !-keepPath \n"
93
+ "-keepCP $ \n -nokeepCP !-keepCP \n"
94
+ "-keepOrder $ \n -nokeepOrder !-keepOrder \n"
95
+ "-continue $ \n -nocontinue !-continue \n"
96
+ "-@ >-@ . \n"
97
+ "- +? \n"
98
+ "\n");
99
100
101
// Protected state for representing the class file.
102
protected Element cfile; // <ClassFile ...>
103
protected Element cpool; // <ConstantPool ...>
104
protected Element klass; // <Class ...>
105
protected List<String> thePool; // stringified flattened Constant Pool
106
107
public static void main(String[] ava) throws IOException {
108
ArrayList<String> av = new ArrayList<>(Arrays.asList(ava));
109
HashMap<String, String> props = new HashMap<>();
110
props.put("-encoding:", "UTF8"); // default
111
props.put("-keepOrder", null); // CLI default
112
props.put("-pretty", "1"); // CLI default
113
props.put("-continue", "1"); // CLI default
114
CLP.parse(av, props);
115
//System.out.println(props+" ++ "+av);
116
File source = asFile(props.get("-source:"));
117
File dest = asFile(props.get("-dest:"));
118
String encoding = props.get("-encoding:");
119
boolean contError = props.containsKey("-continue");
120
ClassReader options = new ClassReader();
121
options.copyOptionsFrom(props);
122
/*
123
if (dest == null && av.size() > 1) {
124
dest = File.createTempFile("TestOut", ".dir", new File("."));
125
dest.delete();
126
if (!dest.mkdir())
127
throw new RuntimeException("Cannot create "+dest);
128
System.out.println("Writing results to "+dest);
129
}
130
*/
131
if (av.isEmpty()) {
132
av.add(""); //to enter this loop
133
}
134
boolean readList = false;
135
for (String a : av) {
136
if (readList) {
137
readList = false;
138
InputStream fin;
139
if (a.equals("-")) {
140
fin = System.in;
141
} else {
142
fin = new FileInputStream(a);
143
}
144
145
BufferedReader files = makeReader(fin, encoding);
146
for (String file; (file = files.readLine()) != null;) {
147
doFile(file, source, dest, options, encoding, contError);
148
}
149
if (fin != System.in) {
150
fin.close();
151
}
152
} else if (a.equals("-@")) {
153
readList = true;
154
} else if (a.startsWith("-")) {
155
throw new RuntimeException("Bad flag argument: " + a);
156
} else if (source.getName().endsWith(".jar")) {
157
doJar(a, source, dest, options, encoding, contError);
158
} else {
159
doFile(a, source, dest, options, encoding, contError);
160
}
161
}
162
}
163
164
private static File asFile(String str) {
165
return (str == null) ? null : new File(str);
166
}
167
168
private static void doFile(String a,
169
File source, File dest,
170
ClassReader options, String encoding,
171
boolean contError) throws IOException {
172
if (!contError) {
173
doFile(a, source, dest, options, encoding);
174
} else {
175
try {
176
doFile(a, source, dest, options, encoding);
177
} catch (Exception ee) {
178
System.out.println("Error processing " + source + ": " + ee);
179
ee.printStackTrace();
180
}
181
}
182
}
183
184
private static void doJar(String a, File source, File dest,
185
ClassReader options, String encoding,
186
Boolean contError) throws IOException {
187
try {
188
JarFile jf = new JarFile(source);
189
for (JarEntry je : Collections.list(jf.entries())) {
190
String name = je.getName();
191
if (!name.endsWith(".class")) {
192
continue;
193
}
194
try {
195
doStream(name, jf.getInputStream(je), dest, options, encoding);
196
} catch (Exception e) {
197
if (contError) {
198
System.out.println("Error processing " + source + ": " + e);
199
e.printStackTrace();
200
continue;
201
}
202
}
203
}
204
} catch (IOException ioe) {
205
throw ioe;
206
}
207
}
208
209
private static void doStream(String a, InputStream in, File dest,
210
ClassReader options, String encoding) throws IOException {
211
212
File f = new File(a);
213
ClassReader cr = new ClassReader(options);
214
Element e;
215
if (options.verbose) {
216
System.out.println("Reading " + f);
217
}
218
e = cr.readFrom(in);
219
220
OutputStream out;
221
if (dest == null) {
222
out = System.out;
223
} else {
224
File outf = new File(dest, f.isAbsolute() ? f.getName() : f.getPath());
225
String outName = outf.getName();
226
File outSubdir = outf.getParentFile();
227
outSubdir.mkdirs();
228
int extPos = outName.lastIndexOf('.');
229
if (extPos > 0) {
230
outf = new File(outSubdir, outName.substring(0, extPos) + ".xml");
231
}
232
out = new FileOutputStream(outf);
233
}
234
235
Writer outw = makeWriter(out, encoding);
236
if (options.pretty || !options.keepOrder) {
237
e.writePrettyTo(outw);
238
} else {
239
e.writeTo(outw);
240
}
241
if (out == System.out) {
242
outw.write("\n");
243
outw.flush();
244
} else {
245
outw.close();
246
}
247
}
248
249
private static void doFile(String a,
250
File source, File dest,
251
ClassReader options, String encoding) throws IOException {
252
File inf = new File(source, a);
253
if (dest != null && options.verbose) {
254
System.out.println("Reading " + inf);
255
}
256
257
BufferedInputStream in = new BufferedInputStream(new FileInputStream(inf));
258
259
doStream(a, in, dest, options, encoding);
260
261
}
262
263
public static BufferedReader makeReader(InputStream in,
264
String encoding) throws IOException {
265
Reader inw;
266
in = new BufferedInputStream(in); // add buffering
267
if (encoding == null) {
268
inw = new InputStreamReader(in);
269
} else {
270
inw = new InputStreamReader(in, encoding);
271
}
272
return new BufferedReader(inw); // add buffering
273
}
274
275
public static Writer makeWriter(OutputStream out,
276
String encoding) throws IOException {
277
Writer outw;
278
if (encoding == null) {
279
outw = new OutputStreamWriter(out);
280
} else {
281
outw = new OutputStreamWriter(out, encoding);
282
}
283
return new BufferedWriter(outw); // add buffering
284
}
285
286
public Element result() {
287
return cfile;
288
}
289
290
protected InputStream in;
291
protected ByteArrayOutputStream buf = new ByteArrayOutputStream(1024);
292
// input options
293
public boolean pretty = false;
294
public boolean verbose = false;
295
public boolean keepPath = false;
296
public boolean keepCP = false;
297
public boolean keepBytes = false;
298
public boolean parseBytes = true;
299
public boolean resolveRefs = true;
300
public boolean keepOrder = true;
301
public boolean keepSizes = false;
302
303
public ClassReader() {
304
cfile = new Element("ClassFile");
305
}
306
307
public ClassReader(ClassReader options) {
308
this();
309
copyOptionsFrom(options);
310
}
311
312
public void copyOptionsFrom(ClassReader options) {
313
pretty = options.pretty;
314
verbose = options.verbose;
315
keepPath = options.keepPath;
316
keepCP = options.keepCP;
317
keepOrder = options.keepOrder;
318
}
319
320
public void copyOptionsFrom(Map<String, String> options) {
321
if (options.containsKey("-pretty")) {
322
pretty = (options.get("-pretty") != null);
323
}
324
if (options.containsKey("-verbose")) {
325
verbose = (options.get("-verbose") != null);
326
}
327
if (options.containsKey("-keepPath")) {
328
keepPath = (options.get("-keepPath") != null);
329
}
330
if (options.containsKey("-keepCP")) {
331
keepCP = (options.get("-keepCP") != null);
332
}
333
if (options.containsKey("-keepOrder")) {
334
keepOrder = (options.get("-keepOrder") != null);
335
}
336
}
337
338
protected String getCpString(int i) {
339
return thePool.get(i);
340
}
341
342
public Element readFrom(InputStream in) throws IOException {
343
try {
344
this.in = in;
345
ClassFile c = ClassFile.read(in);
346
// read the file header
347
if (c.magic != 0xCAFEBABE) {
348
throw new RuntimeException("bad magic number " +
349
Integer.toHexString(c.magic));
350
}
351
cfile.setAttr("magic", "" + c.magic);
352
int minver = c.minor_version;
353
int majver = c.major_version;
354
cfile.setAttr("minver", "" + minver);
355
cfile.setAttr("majver", "" + majver);
356
readCP(c);
357
readClass(c);
358
return result();
359
} catch (InvalidDescriptor | ConstantPoolException ex) {
360
throw new IOException("Fatal error", ex);
361
}
362
}
363
364
public Element readFrom(File file) throws IOException {
365
try (InputStream strm = new FileInputStream(file)) {
366
Element e = readFrom(new BufferedInputStream(strm));
367
if (keepPath) {
368
e.setAttr("path", file.toString());
369
}
370
return e;
371
}
372
}
373
374
private void readClass(ClassFile c) throws IOException,
375
ConstantPoolException,
376
InvalidDescriptor {
377
klass = new Element("Class");
378
cfile.add(klass);
379
String thisk = c.getName();
380
381
klass.setAttr("name", thisk);
382
383
AccessFlags af = new AccessFlags(c.access_flags.flags);
384
klass.setAttr("flags", flagString(af, klass));
385
if (!"java/lang/Object".equals(thisk)) {
386
klass.setAttr("super", c.getSuperclassName());
387
}
388
for (int i : c.interfaces) {
389
klass.add(new Element("Interface", "name", getCpString(i)));
390
}
391
readFields(c, klass);
392
readMethods(c, klass);
393
readAttributesFor(c, c.attributes, klass);
394
klass.trimToSize();
395
}
396
397
private void readFields(ClassFile c, Element klass) throws IOException {
398
int len = c.fields.length;
399
Element fields = new Element(len);
400
for (Field f : c.fields) {
401
Element field = new Element("Field");
402
field.setAttr("name", getCpString(f.name_index));
403
field.setAttr("type", getCpString(f.descriptor.index));
404
field.setAttr("flags", flagString(f.access_flags.flags, field));
405
readAttributesFor(c, f.attributes, field);
406
407
field.trimToSize();
408
fields.add(field);
409
}
410
if (!keepOrder) {
411
fields.sort();
412
}
413
klass.addAll(fields);
414
}
415
416
417
private void readMethods(ClassFile c, Element klass) throws IOException {
418
int len = c.methods.length;
419
Element methods = new Element(len);
420
for (Method m : c.methods) {
421
Element member = new Element("Method");
422
member.setAttr("name", getCpString(m.name_index));
423
member.setAttr("type", getCpString(m.descriptor.index));
424
member.setAttr("flags", flagString(m.access_flags.flags, member));
425
readAttributesFor(c, m.attributes, member);
426
427
member.trimToSize();
428
methods.add(member);
429
}
430
if (!keepOrder) {
431
methods.sort();
432
}
433
klass.addAll(methods);
434
}
435
436
private AccessFlags.Kind getKind(Element e) {
437
switch(e.getName()) {
438
case "Class":
439
return AccessFlags.Kind.Class;
440
case "InnerClass":
441
return AccessFlags.Kind.InnerClass;
442
case "Field":
443
return AccessFlags.Kind.Field ;
444
case "Method":
445
return AccessFlags.Kind.Method;
446
default: throw new RuntimeException("should not reach here");
447
}
448
}
449
450
protected String flagString(int flags, Element holder) {
451
return flagString(new AccessFlags(flags), holder);
452
}
453
protected String flagString(AccessFlags af, Element holder) {
454
return flagString(af, holder.getName());
455
}
456
protected String flagString(int flags, String kind) {
457
return flagString(new AccessFlags(flags), kind);
458
}
459
protected String flagString(AccessFlags af, String kind) {
460
Set<String> mods = null;
461
switch (kind) {
462
case "Class":
463
mods = af.getClassFlags();
464
break;
465
case "InnerClass":
466
mods = af.getInnerClassFlags();
467
break;
468
case "Field":
469
mods = af.getFieldFlags();
470
break;
471
case "Method":
472
mods = af.getMethodFlags();
473
break;
474
default:
475
throw new RuntimeException("should not reach here");
476
}
477
StringBuilder sb = new StringBuilder();
478
for (String x : mods) {
479
sb.append(x.substring(x.indexOf('_') + 1).toLowerCase()).append(" ");
480
}
481
return sb.toString().trim();
482
}
483
484
485
protected void readAttributesFor(ClassFile c, Attributes attrs, Element x) {
486
Element container = new Element();
487
AttributeVisitor av = new AttributeVisitor(this, c);
488
for (Attribute a : attrs) {
489
av.visit(a, container);
490
}
491
if (!keepOrder) {
492
container.sort();
493
}
494
x.addAll(container);
495
}
496
497
private int fileSize = 0;
498
private HashMap<String, int[]> attrSizes = new HashMap<>();
499
500
private void attachTo(Element x, Object aval0) {
501
if (aval0 == null) {
502
return;
503
}
504
if (!(aval0 instanceof Element)) {
505
x.add(aval0);
506
return;
507
}
508
Element aval = (Element) aval0;
509
if (!aval.isAnonymous()) {
510
x.add(aval);
511
return;
512
}
513
for (int imax = aval.attrSize(), i = 0; i < imax; i++) {
514
//%%
515
attachAttrTo(x, aval.getAttrName(i), aval.getAttr(i));
516
}
517
x.addAll(aval);
518
}
519
520
private void attachAttrTo(Element x, String aname, String aval) {
521
String aval0 = x.getAttr(aname);
522
if (aval0 != null) {
523
aval = aval0 + " " + aval;
524
}
525
x.setAttr(aname, aval);
526
}
527
528
private void readCP(ClassFile c) throws IOException {
529
cpool = new Element("ConstantPool", c.constant_pool.size());
530
ConstantPoolVisitor cpv = new ConstantPoolVisitor(cpool, c,
531
c.constant_pool.size());
532
for (int i = 1 ; i < c.constant_pool.size() ; i++) {
533
try {
534
cpv.visit(c.constant_pool.get(i), i);
535
} catch (InvalidIndex ex) {
536
// can happen periodically when accessing doubles etc. ignore it
537
// ex.printStackTrace();
538
}
539
}
540
thePool = cpv.getPoolList();
541
if (verbose) {
542
for (int i = 0; i < thePool.size(); i++) {
543
System.out.println("[" + i + "]: " + thePool.get(i));
544
}
545
}
546
if (keepCP) {
547
cfile.add(cpool);
548
}
549
}
550
}
551
552
class ConstantPoolVisitor implements ConstantPool.Visitor<String, Integer> {
553
final List<String> slist;
554
final Element xpool;
555
final ClassFile cf;
556
final ConstantPool cfpool;
557
final List<String> bsmlist;
558
559
560
public ConstantPoolVisitor(Element xpool, ClassFile cf, int size) {
561
slist = new ArrayList<>(size);
562
for (int i = 0 ; i < size; i++) {
563
slist.add(null);
564
}
565
this.xpool = xpool;
566
this.cf = cf;
567
this.cfpool = cf.constant_pool;
568
bsmlist = readBSM();
569
}
570
571
public List<String> getPoolList() {
572
return Collections.unmodifiableList(slist);
573
}
574
575
public List<String> getBSMList() {
576
return Collections.unmodifiableList(bsmlist);
577
}
578
579
public String visit(CPInfo c, int index) {
580
return c.accept(this, index);
581
}
582
583
private List<String> readBSM() {
584
BootstrapMethods_attribute bsmAttr =
585
(BootstrapMethods_attribute) cf.getAttribute(Attribute.BootstrapMethods);
586
if (bsmAttr != null) {
587
List<String> out =
588
new ArrayList<>(bsmAttr.bootstrap_method_specifiers.length);
589
for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsms :
590
bsmAttr.bootstrap_method_specifiers) {
591
int index = bsms.bootstrap_method_ref;
592
try {
593
String value = slist.get(index);
594
String bsmStr = value;
595
if (value == null) {
596
value = visit(cfpool.get(index), index);
597
slist.set(index, value);
598
}
599
bsmStr = value;
600
for (int idx : bsms.bootstrap_arguments) {
601
value = slist.get(idx);
602
if (value == null) {
603
value = visit(cfpool.get(idx), idx);
604
slist.set(idx, value);
605
}
606
bsmStr = bsmStr.concat("," + value);
607
}
608
out.add(bsmStr);
609
} catch (InvalidIndex ex) {
610
ex.printStackTrace();
611
}
612
}
613
return out;
614
}
615
return new ArrayList<>(0);
616
}
617
618
@Override
619
public String visitClass(CONSTANT_Class_info c, Integer p) {
620
String value = slist.get(p);
621
if (value == null) {
622
try {
623
value = visit(cfpool.get(c.name_index), c.name_index);
624
slist.set(p, value);
625
xpool.add(new Element("CONSTANT_Class",
626
new String[]{"id", p.toString()},
627
value));
628
} catch (ConstantPoolException ex) {
629
ex.printStackTrace();
630
}
631
}
632
return value;
633
}
634
635
@Override
636
public String visitDouble(CONSTANT_Double_info c, Integer p) {
637
String value = slist.get(p);
638
if (value == null) {
639
value = Double.toString(c.value);
640
slist.set(p, value);
641
xpool.add(new Element("CONSTANT_Double",
642
new String[]{"id", p.toString()},
643
value));
644
}
645
return value;
646
}
647
648
@Override
649
public String visitFieldref(CONSTANT_Fieldref_info c, Integer p) {
650
String value = slist.get(p);
651
if (value == null) {
652
try {
653
value = visit(cfpool.get(c.class_index), c.class_index);
654
value = value.concat(" " + visit(cfpool.get(c.name_and_type_index),
655
c.name_and_type_index));
656
slist.set(p, value);
657
xpool.add(new Element("CONSTANT_Fieldref",
658
new String[]{"id", p.toString()},
659
value));
660
} catch (ConstantPoolException ex) {
661
ex.printStackTrace();
662
}
663
}
664
return value;
665
}
666
667
@Override
668
public String visitFloat(CONSTANT_Float_info c, Integer p) {
669
String value = slist.get(p);
670
if (value == null) {
671
value = Float.toString(c.value);
672
slist.set(p, value);
673
xpool.add(new Element("CONSTANT_Float",
674
new String[]{"id", p.toString()},
675
value));
676
}
677
return value;
678
}
679
680
@Override
681
public String visitInteger(CONSTANT_Integer_info cnstnt, Integer p) {
682
String value = slist.get(p);
683
if (value == null) {
684
value = Integer.toString(cnstnt.value);
685
slist.set(p, value);
686
xpool.add(new Element("CONSTANT_Integer",
687
new String[]{"id", p.toString()},
688
value));
689
}
690
return value;
691
}
692
693
@Override
694
public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info c,
695
Integer p) {
696
String value = slist.get(p);
697
if (value == null) {
698
try {
699
value = visit(cfpool.get(c.class_index), c.class_index);
700
value = value.concat(" " +
701
visit(cfpool.get(c.name_and_type_index),
702
c.name_and_type_index));
703
slist.set(p, value);
704
xpool.add(new Element("CONSTANT_InterfaceMethodref",
705
new String[]{"id", p.toString()},
706
value));
707
708
} catch (ConstantPoolException ex) {
709
ex.printStackTrace();
710
}
711
}
712
return value;
713
}
714
715
@Override
716
public String visitInvokeDynamic(CONSTANT_InvokeDynamic_info c, Integer p) {
717
String value = slist.get(p);
718
if (value == null) {
719
try {
720
value = bsmlist.get(c.bootstrap_method_attr_index) + " "
721
+ visit(cfpool.get(c.name_and_type_index), c.name_and_type_index);
722
slist.set(p, value);
723
xpool.add(new Element("CONSTANT_InvokeDynamic",
724
new String[]{"id", p.toString()},
725
value));
726
727
} catch (ConstantPoolException ex) {
728
ex.printStackTrace();
729
}
730
}
731
return value;
732
}
733
734
@Override
735
public String visitLong(CONSTANT_Long_info c, Integer p) {
736
String value = slist.get(p);
737
if (value == null) {
738
value = Long.toString(c.value);
739
slist.set(p, value);
740
xpool.add(new Element("CONSTANT_Long",
741
new String[]{"id", p.toString()},
742
value));
743
}
744
return value;
745
}
746
747
@Override
748
public String visitNameAndType(CONSTANT_NameAndType_info c, Integer p) {
749
String value = slist.get(p);
750
if (value == null) {
751
try {
752
value = visit(cfpool.get(c.name_index), c.name_index);
753
value = value.concat(" " +
754
visit(cfpool.get(c.type_index), c.type_index));
755
slist.set(p, value);
756
xpool.add(new Element("CONSTANT_NameAndType",
757
new String[]{"id", p.toString()},
758
value));
759
} catch (InvalidIndex ex) {
760
ex.printStackTrace();
761
}
762
}
763
return value;
764
}
765
766
@Override
767
public String visitMethodref(CONSTANT_Methodref_info c, Integer p) {
768
String value = slist.get(p);
769
if (value == null) {
770
try {
771
value = visit(cfpool.get(c.class_index), c.class_index);
772
value = value.concat(" " +
773
visit(cfpool.get(c.name_and_type_index),
774
c.name_and_type_index));
775
slist.set(p, value);
776
xpool.add(new Element("CONSTANT_Methodref",
777
new String[]{"id", p.toString()},
778
value));
779
780
} catch (ConstantPoolException ex) {
781
ex.printStackTrace();
782
}
783
}
784
return value;
785
}
786
787
@Override
788
public String visitMethodHandle(CONSTANT_MethodHandle_info c, Integer p) {
789
String value = slist.get(p);
790
if (value == null) {
791
try {
792
value = c.reference_kind.name();
793
value = value.concat(" "
794
+ visit(cfpool.get(c.reference_index), c.reference_index));
795
slist.set(p, value);
796
xpool.add(new Element("CONSTANT_MethodHandle",
797
new String[]{"id", p.toString()},
798
value));
799
800
} catch (ConstantPoolException ex) {
801
ex.printStackTrace();
802
}
803
}
804
return value;
805
}
806
807
@Override
808
public String visitMethodType(CONSTANT_MethodType_info c, Integer p) {
809
String value = slist.get(p);
810
if (value == null) {
811
try {
812
value = visit(cfpool.get(c.descriptor_index), c.descriptor_index);
813
slist.set(p, value);
814
xpool.add(new Element("CONSTANT_MethodType",
815
new String[]{"id", p.toString()},
816
value));
817
} catch (ConstantPoolException ex) {
818
ex.printStackTrace();
819
}
820
}
821
return value;
822
}
823
824
@Override
825
public String visitString(CONSTANT_String_info c, Integer p) {
826
try {
827
828
String value = slist.get(p);
829
if (value == null) {
830
value = c.getString();
831
slist.set(p, value);
832
xpool.add(new Element("CONSTANT_String",
833
new String[]{"id", p.toString()},
834
value));
835
}
836
return value;
837
} catch (ConstantPoolException ex) {
838
throw new RuntimeException("Fatal error", ex);
839
}
840
}
841
842
@Override
843
public String visitUtf8(CONSTANT_Utf8_info cnstnt, Integer p) {
844
String value = slist.get(p);
845
if (value == null) {
846
value = cnstnt.value;
847
slist.set(p, value);
848
xpool.add(new Element("CONSTANT_Utf8",
849
new String[]{"id", p.toString()},
850
value));
851
}
852
return value;
853
854
}
855
}
856
857
858
class AttributeVisitor implements Attribute.Visitor<Element, Element> {
859
final ClassFile cf;
860
final ClassReader x;
861
final AnnotationsElementVisitor aev;
862
final InstructionVisitor iv;
863
864
public AttributeVisitor(ClassReader x, ClassFile cf) {
865
this.x = x;
866
this.cf = cf;
867
iv = new InstructionVisitor(x, cf);
868
aev = new AnnotationsElementVisitor(x, cf);
869
}
870
871
public void visit(Attribute a, Element parent) {
872
a.accept(this, parent);
873
}
874
875
@Override
876
public Element visitBootstrapMethods(BootstrapMethods_attribute bm, Element p) {
877
Element e = new Element(x.getCpString(bm.attribute_name_index));
878
for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsm : bm.bootstrap_method_specifiers) {
879
Element be = new Element("BootstrapMethodSpecifier");
880
be.setAttr("ref", x.getCpString(bsm.bootstrap_method_ref));
881
if (bsm.bootstrap_arguments.length > 0) {
882
Element bme = new Element("MethodArguments");
883
for (int index : bsm.bootstrap_arguments) {
884
bme.add(x.getCpString(index));
885
}
886
bme.trimToSize();
887
be.add(bme);
888
}
889
be.trimToSize();
890
e.add(be);
891
}
892
e.trimToSize();
893
if (!x.keepOrder) {
894
e.sort();
895
}
896
p.add(e);
897
return null;
898
}
899
900
@Override
901
public Element visitDefault(DefaultAttribute da, Element p) {
902
Element e = new Element(x.getCpString(da.attribute_name_index));
903
StringBuilder sb = new StringBuilder();
904
for (byte x : da.info) {
905
sb.append("0x").append(Integer.toHexString(x)).append(" ");
906
}
907
e.setAttr("bytes", sb.toString().trim());
908
e.trimToSize();
909
p.add(e);
910
return null;
911
}
912
913
@Override
914
public Element visitAnnotationDefault(AnnotationDefault_attribute ad, Element p) {
915
Element e = new Element(x.getCpString(ad.attribute_name_index));
916
e.setAttr("tag", "" + ad.default_value.tag);
917
Element child = aev.visit(ad.default_value, e);
918
if (child != null) {
919
e.add(child);
920
}
921
e.trimToSize();
922
p.add(e);
923
return null;
924
}
925
926
@Override
927
public Element visitCharacterRangeTable(CharacterRangeTable_attribute crt,
928
Element p) {
929
Element e = new Element(x.getCpString(crt.attribute_name_index));
930
for (CharacterRangeTable_attribute.Entry ce : crt.character_range_table) {
931
e.setAttr("start_pc", "" + ce.start_pc);
932
e.setAttr("end_pc", "" + ce.end_pc);
933
e.setAttr("range_start", "" + ce.character_range_start);
934
e.setAttr("range_end", "" + ce.character_range_end);
935
e.setAttr("flags", x.flagString(ce.flags, "Method"));
936
}
937
e.trimToSize();
938
p.add(e);
939
return null;
940
}
941
942
private Element instructions(Element code, Code_attribute c) {
943
Element ielement = new Element("Instructions");
944
for (Instruction ins : c.getInstructions()) {
945
ielement.add(iv.visit(ins));
946
}
947
ielement.trimToSize();
948
return ielement;
949
}
950
951
@Override
952
public Element visitCode(Code_attribute c, Element p) {
953
Element e = null;
954
955
e = new Element(x.getCpString(c.attribute_name_index),
956
"stack", "" + c.max_stack,
957
"local", "" + c.max_locals);
958
959
e.add(instructions(e, c));
960
961
for (Code_attribute.Exception_data edata : c.exception_table) {
962
e.add(new Element("Handler",
963
"start", "" + edata.start_pc,
964
"end", "" + edata.end_pc,
965
"catch", "" + edata.handler_pc,
966
"class", x.getCpString(edata.catch_type)));
967
968
}
969
this.x.readAttributesFor(cf, c.attributes, e);
970
e.trimToSize();
971
p.add(e);
972
return null;
973
}
974
975
@Override
976
public Element visitCompilationID(CompilationID_attribute cid, Element p) {
977
Element e = new Element(x.getCpString(cid.attribute_name_index),
978
x.getCpString(cid.compilationID_index));
979
p.add(e);
980
return null;
981
}
982
983
@Override
984
public Element visitConstantValue(ConstantValue_attribute cv, Element p) {
985
Element e = new Element(x.getCpString(cv.attribute_name_index));
986
e.add(x.getCpString(cv.constantvalue_index));
987
p.add(e);
988
return null;
989
}
990
991
@Override
992
public Element visitDeprecated(Deprecated_attribute d, Element p) {
993
Element e = new Element(x.getCpString(d.attribute_name_index));
994
p.add(e);
995
return null;
996
}
997
998
@Override
999
public Element visitEnclosingMethod(EnclosingMethod_attribute em, Element p) {
1000
Element e = new Element(x.getCpString(em.attribute_name_index));
1001
e.setAttr("class", x.getCpString(em.class_index));
1002
e.setAttr("desc", x.getCpString(em.method_index));
1003
e.trimToSize();
1004
p.add(e);
1005
return null;
1006
}
1007
1008
@Override
1009
public Element visitExceptions(Exceptions_attribute e, Element p) {
1010
Element ee = new Element(x.getCpString(e.attribute_name_index));
1011
for (int idx : e.exception_index_table) {
1012
Element n = new Element("Item");
1013
n.setAttr("class", x.getCpString(idx));
1014
ee.add(n);
1015
}
1016
ee.trimToSize();
1017
p.add(ee);
1018
return null;
1019
}
1020
1021
@Override
1022
public Element visitInnerClasses(InnerClasses_attribute ic, Element p) {
1023
for (Info info : ic.classes) {
1024
Element e = new Element(x.getCpString(ic.attribute_name_index));
1025
e.setAttr("class", x.getCpString(info.inner_class_info_index));
1026
e.setAttr("outer", x.getCpString(info.outer_class_info_index));
1027
e.setAttr("name", x.getCpString(info.inner_name_index));
1028
e.setAttr("flags", x.flagString(info.inner_class_access_flags,
1029
"InnerClass"));
1030
e.trimToSize();
1031
p.add(e);
1032
}
1033
return null;
1034
}
1035
1036
@Override
1037
public Element visitLineNumberTable(LineNumberTable_attribute lnt, Element p) {
1038
String name = x.getCpString(lnt.attribute_name_index);
1039
for (LineNumberTable_attribute.Entry e : lnt.line_number_table) {
1040
Element l = new Element(name);
1041
l.setAttr("bci", "" + e.start_pc);
1042
l.setAttr("line", "" + e.line_number);
1043
l.trimToSize();
1044
p.add(l);
1045
}
1046
return null; // already added to parent
1047
}
1048
1049
@Override
1050
public Element visitLocalVariableTable(LocalVariableTable_attribute lvt,
1051
Element p) {
1052
String name = x.getCpString(lvt.attribute_name_index);
1053
for (LocalVariableTable_attribute.Entry e : lvt.local_variable_table) {
1054
Element l = new Element(name);
1055
l.setAttr("bci", "" + e.start_pc);
1056
l.setAttr("span", "" + e.length);
1057
l.setAttr("name", x.getCpString(e.name_index));
1058
l.setAttr("type", x.getCpString(e.descriptor_index));
1059
l.setAttr("slot", "" + e.index);
1060
l.trimToSize();
1061
p.add(l);
1062
}
1063
return null; // already added to parent
1064
}
1065
1066
@Override
1067
public Element visitLocalVariableTypeTable(LocalVariableTypeTable_attribute lvtt,
1068
Element p) {
1069
String name = x.getCpString(lvtt.attribute_name_index);
1070
for (LocalVariableTypeTable_attribute.Entry e : lvtt.local_variable_table) {
1071
Element l = new Element(name);
1072
l.setAttr("bci", "" + e.start_pc);
1073
l.setAttr("span", "" + e.length);
1074
l.setAttr("name", x.getCpString(e.name_index));
1075
l.setAttr("type", x.getCpString(e.signature_index));
1076
l.setAttr("slot", "" + e.index);
1077
l.trimToSize();
1078
p.add(l);
1079
}
1080
return null; // already added to parent
1081
}
1082
1083
@Override
1084
public Element visitMethodParameters(MethodParameters_attribute mp, Element p) {
1085
String name = x.getCpString(mp.attribute_name_index);
1086
for (MethodParameters_attribute.Entry e : mp.method_parameter_table) {
1087
Element l = new Element(name);
1088
l.setAttr("name", x.getCpString(e.name_index));
1089
l.setAttr("flag", "" + e.flags);
1090
l.trimToSize();
1091
p.add(l);
1092
}
1093
return null; // already added to parent
1094
}
1095
private void parseAnnotation(Annotation anno, Element p) {
1096
Element ea = new Element("Annotation");
1097
ea.setAttr("name", "" + x.getCpString(anno.type_index));
1098
for (Annotation.element_value_pair evp : anno.element_value_pairs) {
1099
Element evpe = new Element("Element");
1100
evpe.setAttr("tag", "" + evp.value.tag);
1101
evpe.setAttr("value", x.getCpString(evp.element_name_index));
1102
Element child = aev.visit(evp.value, evpe);
1103
if (child != null) {
1104
evpe.add(child);
1105
}
1106
ea.add(evpe);
1107
}
1108
ea.trimToSize();
1109
p.add(ea);
1110
}
1111
1112
private void parseAnnotations(Annotation[] ra, Element p) {
1113
for (Annotation anno : ra) {
1114
parseAnnotation(anno, p);
1115
}
1116
}
1117
1118
@Override
1119
public Element visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute rva,
1120
Element p) {
1121
Element e = new Element(x.getCpString(rva.attribute_name_index));
1122
parseAnnotations(rva.annotations, e);
1123
e.trimToSize();
1124
p.add(e);
1125
return null;
1126
}
1127
1128
@Override
1129
public Element visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute ria,
1130
Element p) {
1131
Element e = new Element(x.getCpString(ria.attribute_name_index));
1132
parseAnnotations(ria.annotations, e);
1133
e.trimToSize();
1134
p.add(e);
1135
return null;
1136
}
1137
1138
@Override
1139
public Element visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute rvpa,
1140
Element p) {
1141
Element e = new Element(x.getCpString(rvpa.attribute_name_index));
1142
for (Annotation[] pa : rvpa.parameter_annotations) {
1143
parseAnnotations(pa, e);
1144
}
1145
p.add(e);
1146
return null;
1147
}
1148
1149
@Override
1150
public Element visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute ripa,
1151
Element p) {
1152
Element e = new Element(x.getCpString(ripa.attribute_name_index));
1153
for (Annotation[] pa : ripa.parameter_annotations) {
1154
parseAnnotations(pa, e);
1155
}
1156
p.add(e);
1157
return null;
1158
}
1159
1160
private void parsePosition(Position ap, Element p) {
1161
Element te = new Element();
1162
switch (ap.type) {
1163
case CLASS_TYPE_PARAMETER: // 0x00
1164
te.setName("CLASS_TYPE_PARAMETER");
1165
te.setAttr("idx", "" + ap.parameter_index);
1166
break;
1167
case METHOD_TYPE_PARAMETER: // 0x01
1168
te.setName("METHOD_TYPE_PARAMETER");
1169
te.setAttr("idx", "" + ap.parameter_index);
1170
break;
1171
case CLASS_EXTENDS: // 0x10
1172
te.setName("CLASS_EXTENDS");
1173
te.setAttr("idx", "" + ap.type_index);
1174
break;
1175
case CLASS_TYPE_PARAMETER_BOUND: // 0x11
1176
te.setName("CLASS_TYPE_PARAMETER_BOUND");
1177
te.setAttr("idx1", "" + ap.parameter_index);
1178
te.setAttr("idx2", "" + ap.bound_index);
1179
break;
1180
case METHOD_TYPE_PARAMETER_BOUND: // 0x12
1181
te.setName("METHOD_TYPE_PARAMETER_BOUND");
1182
te.setAttr("idx1", "" + ap.parameter_index);
1183
te.setAttr("idx2", "" + ap.bound_index);
1184
break;
1185
case FIELD: // 0x13
1186
te.setName("FIELD");
1187
break;
1188
case METHOD_RETURN: // 0x14
1189
te.setName("METHOD_RETURN");
1190
break;
1191
case METHOD_RECEIVER: // 0x15
1192
te.setName("METHOD_RECEIVER");
1193
break;
1194
case METHOD_FORMAL_PARAMETER: // 0x16
1195
te.setName("METHOD_FORMAL_PARAMETER");
1196
te.setAttr("idx", "" + ap.parameter_index);
1197
break;
1198
case THROWS: // 0x17
1199
te.setName("THROWS");
1200
te.setAttr("idx", "" + ap.type_index);
1201
break;
1202
case LOCAL_VARIABLE: // 0x40
1203
te.setName("LOCAL_VARIABLE");
1204
for (int i = 0; i < ap.lvarIndex.length; i++) {
1205
te.setAttr("lvar_idx_" + i, "" + ap.lvarIndex[i]);
1206
te.setAttr("lvar_len_" + i, "" + ap.lvarLength[i]);
1207
te.setAttr("lvar_off_" + i, "" + ap.lvarOffset[i]);
1208
}
1209
break;
1210
case RESOURCE_VARIABLE: // 0x41
1211
te.setName("RESOURCE_VARIABLE");
1212
for (int i = 0; i < ap.lvarIndex.length ; i++) {
1213
te.setAttr("lvar_idx_" + i, "" + ap.lvarIndex[i]);
1214
te.setAttr("lvar_len_" + i, "" + ap.lvarLength[i]);
1215
te.setAttr("lvar_off_" + i, "" + ap.lvarOffset[i]);
1216
}
1217
break;
1218
case EXCEPTION_PARAMETER: // 0x42
1219
te.setName("EXCEPTION_PARAMETER");
1220
te.setAttr("idx", "" + ap.exception_index);
1221
break;
1222
case INSTANCEOF: // 0x43
1223
te.setName("INSTANCE_OF");
1224
te.setAttr("off", "" + ap.offset);
1225
break;
1226
case NEW: // 0x44
1227
te.setName("NEW");
1228
te.setAttr("off", "" + ap.offset);
1229
break;
1230
case CONSTRUCTOR_REFERENCE: // 0x45
1231
te.setName("CONSTRUCTOR_REFERENCE_RECEIVER");
1232
te.setAttr("off", "" + ap.offset);
1233
break;
1234
case METHOD_REFERENCE: // 0x46
1235
te.setName("METHOD_REFERENCE_RECEIVER");
1236
te.setAttr("off", "" + ap.offset);
1237
break;
1238
case CAST: // 0x47
1239
te.setName("CAST");
1240
te.setAttr("off", "" + ap.offset);
1241
te.setAttr("idx", "" + ap.type_index);
1242
break;
1243
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT: // 0x48
1244
te.setName("CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT");
1245
te.setAttr("off", "" + ap.offset);
1246
te.setAttr("idx", "" + ap.type_index);
1247
break;
1248
case METHOD_INVOCATION_TYPE_ARGUMENT: // 0x49
1249
te.setName("METHOD_INVOCATION_TYPE_ARGUMENT");
1250
te.setAttr("off", "" + ap.offset);
1251
te.setAttr("idx", "" + ap.type_index);
1252
break;
1253
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: // 0x4A
1254
te.setName("CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT");
1255
te.setAttr("off", "" + ap.offset);
1256
te.setAttr("idx", "" + ap.type_index);
1257
break;
1258
case METHOD_REFERENCE_TYPE_ARGUMENT: // 0x4B
1259
te.setName("METHOD_REFERENCE_TYPE_ARGUMENT");
1260
te.setAttr("off", "" + ap.offset);
1261
te.setAttr("idx", "" + ap.type_index);
1262
break;
1263
default:
1264
throw new RuntimeException("not implemented");
1265
}
1266
te.trimToSize();
1267
p.add(te);
1268
}
1269
private void parseTypeAnnotations(TypeAnnotation pa, Element p) {
1270
Element pta = new Element("RuntimeVisibleTypeAnnotation");
1271
p.add(pta);
1272
Position pos = pa.position;
1273
parsePosition(pos, pta);
1274
parseAnnotation(pa.annotation, pta);
1275
}
1276
1277
@Override
1278
public Element visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute rvta, Element p) {
1279
Element e = new Element(x.getCpString(rvta.attribute_name_index));
1280
for (TypeAnnotation pa : rvta.annotations) {
1281
parseTypeAnnotations(pa, e);
1282
}
1283
e.sort();
1284
p.add(e);
1285
return null;
1286
}
1287
1288
@Override
1289
public Element visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute rita, Element p) {
1290
Element e = new Element(x.getCpString(rita.attribute_name_index));
1291
for (TypeAnnotation pa : rita.annotations) {
1292
parseTypeAnnotations(pa, e);
1293
}
1294
e.sort();
1295
p.add(e);
1296
return null;
1297
}
1298
1299
@Override
1300
public Element visitSignature(Signature_attribute s, Element p) {
1301
String aname = x.getCpString(s.attribute_name_index);
1302
String sname = x.getCpString(s.signature_index);
1303
Element se = new Element(aname);
1304
se.add(sname);
1305
se.trimToSize();
1306
p.add(se);
1307
return null;
1308
}
1309
1310
@Override
1311
public Element visitSourceDebugExtension(SourceDebugExtension_attribute sde,
1312
Element p) {
1313
String aname = x.getCpString(sde.attribute_name_index);
1314
Element se = new Element(aname);
1315
se.setAttr("val", sde.getValue());
1316
se.trimToSize();
1317
p.add(se);
1318
return null;
1319
}
1320
1321
@Override
1322
public Element visitSourceFile(SourceFile_attribute sf, Element p) {
1323
String aname = x.getCpString(sf.attribute_name_index);
1324
String sname = x.getCpString(sf.sourcefile_index);
1325
Element se = new Element(aname);
1326
se.add(sname);
1327
se.trimToSize();
1328
p.add(se);
1329
return null;
1330
}
1331
1332
@Override
1333
public Element visitSourceID(SourceID_attribute sid, Element p) {
1334
Element e = new Element(x.getCpString(sid.attribute_name_index));
1335
e.add(x.getCpString(sid.sourceID_index));
1336
e.trimToSize();
1337
p.add(e);
1338
return null;
1339
}
1340
1341
@Override
1342
public Element visitStackMap(StackMap_attribute sm, Element p) {
1343
throw new UnsupportedOperationException("Not supported yet.");
1344
}
1345
1346
@Override
1347
public Element visitStackMapTable(StackMapTable_attribute smt, Element p) {
1348
Element stackmap = new Element(x.getCpString(smt.attribute_name_index));
1349
for (StackMapTable_attribute.stack_map_frame f : smt.entries) {
1350
StackMapVisitor smv = new StackMapVisitor(x, cf, stackmap);
1351
stackmap.add(smv.visit(f));
1352
}
1353
stackmap.trimToSize();
1354
p.add(stackmap);
1355
return null;
1356
}
1357
1358
@Override
1359
public Element visitSynthetic(Synthetic_attribute s, Element p) {
1360
Element e = new Element(x.getCpString(s.attribute_name_index));
1361
e.trimToSize();
1362
p.add(e);
1363
return null;
1364
}
1365
}
1366
1367
class StackMapVisitor implements StackMapTable_attribute.stack_map_frame.Visitor<Element, Void> {
1368
1369
final ClassFile cf;
1370
final ClassReader x;
1371
final Element parent;
1372
1373
public StackMapVisitor(ClassReader x, ClassFile cf, Element parent) {
1374
this.x = x;
1375
this.cf = cf;
1376
this.parent = parent;
1377
}
1378
1379
public Element visit(StackMapTable_attribute.stack_map_frame frame) {
1380
return frame.accept(this, null);
1381
}
1382
1383
@Override
1384
public Element visit_same_frame(same_frame sm_frm, Void p) {
1385
Element e = new Element("SameFrame");
1386
e.setAttr("tag", "" + sm_frm.frame_type);
1387
return e;
1388
}
1389
1390
@Override
1391
public Element visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame s, Void p) {
1392
Element e = new Element("SameLocals1StackItemFrame");
1393
e.setAttr("tag", "" + s.frame_type);
1394
e.addAll(getVerificationTypeInfo("Stack", s.stack));
1395
e.trimToSize();
1396
return e;
1397
}
1398
1399
@Override
1400
public Element visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended s, Void p) {
1401
Element e = new Element("SameLocals1StackItemFrameExtended");
1402
e.setAttr("tag", "" + s.frame_type);
1403
e.addAll(getVerificationTypeInfo("Stack", s.stack));
1404
e.trimToSize();
1405
return e;
1406
}
1407
1408
@Override
1409
public Element visit_chop_frame(chop_frame c, Void p) {
1410
Element e = new Element("Chop" + (251 - c.frame_type));
1411
e.setAttr("tag", "" + c.frame_type);
1412
e.setAttr("offset", "" + c.offset_delta);
1413
return e;
1414
}
1415
1416
@Override
1417
public Element visit_same_frame_extended(same_frame_extended s, Void p) {
1418
Element e = new Element("SameFrameExtended");
1419
e.setAttr("tag", "" + s.frame_type);
1420
e.setAttr("offset", "" + s.offset_delta);
1421
return e;
1422
}
1423
1424
@Override
1425
public Element visit_append_frame(append_frame a, Void p) {
1426
Element e = new Element("AppendFrame" + (a.frame_type - 251));
1427
e.setAttr("tag", "" + a.frame_type);
1428
e.addAll(getVerificationTypeInfo("Local", a.locals));
1429
e.trimToSize();
1430
return e;
1431
}
1432
1433
@Override
1434
public Element visit_full_frame(full_frame fl_frm, Void p) {
1435
Element e = new Element("FullFrame");
1436
e.setAttr("tag", "" + fl_frm.frame_type);
1437
e.addAll(getVerificationTypeInfo("Local", fl_frm.locals));
1438
e.trimToSize();
1439
return e;
1440
}
1441
1442
private Element getVerificationTypeInfo(String kind,
1443
StackMapTable_attribute.verification_type_info velems[]) {
1444
Element container = new Element(velems.length);
1445
for (StackMapTable_attribute.verification_type_info v : velems) {
1446
Element ve = null;
1447
int offset = 0;
1448
int index = 0;
1449
switch (v.tag) {
1450
case StackMapTable_attribute.verification_type_info.ITEM_Top:
1451
ve = new Element("ITEM_Top");
1452
break;
1453
case StackMapTable_attribute.verification_type_info.ITEM_Integer:
1454
ve = new Element("ITEM_Integer");
1455
break;
1456
case StackMapTable_attribute.verification_type_info.ITEM_Float:
1457
ve = new Element("ITEM_Float");
1458
break;
1459
case StackMapTable_attribute.verification_type_info.ITEM_Long:
1460
ve = new Element("ITEM_Long");
1461
break;
1462
case StackMapTable_attribute.verification_type_info.ITEM_Double:
1463
ve = new Element("ITEM_Double");
1464
break;
1465
case StackMapTable_attribute.verification_type_info.ITEM_Null:
1466
ve = new Element("ITEM_Null");
1467
break;
1468
case StackMapTable_attribute.verification_type_info.ITEM_Uninitialized:
1469
ve = new Element("ITEM_Uninitialized");
1470
offset = ((StackMapTable_attribute.Uninitialized_variable_info) v).offset;
1471
ve.setAttr("offset", "" + offset);
1472
break;
1473
case StackMapTable_attribute.verification_type_info.ITEM_UninitializedThis:
1474
ve = new Element("ITEM_UnitializedtThis");
1475
break;
1476
case StackMapTable_attribute.verification_type_info.ITEM_Object:
1477
ve = new Element("ITEM_Object");
1478
index = ((StackMapTable_attribute.Object_variable_info) v).cpool_index;
1479
ve.setAttr("class", x.getCpString(index));
1480
break;
1481
default:
1482
ve = new Element("Unknown");
1483
}
1484
Element kindE = new Element(kind);
1485
kindE.setAttr("tag", "" + v.tag);
1486
container.add(kindE);
1487
kindE.add(ve);
1488
}
1489
container.trimToSize();
1490
return container;
1491
}
1492
}
1493
1494
class InstructionVisitor implements Instruction.KindVisitor<Element, Void> {
1495
1496
final ClassReader x;
1497
final ClassFile cf;
1498
1499
public InstructionVisitor(ClassReader x, ClassFile cf) {
1500
this.x = x;
1501
this.cf = cf;
1502
}
1503
1504
public Element visit(Instruction i) {
1505
Element ie = i.accept(this, null);
1506
ie.trimToSize();
1507
return ie;
1508
}
1509
1510
@Override
1511
public Element visitNoOperands(Instruction i, Void p) {
1512
Opcode o = i.getOpcode();
1513
Element e = new Element(i.getMnemonic());
1514
if (o.opcode > 0xab && o.opcode <= 0xb1) {
1515
e.setAttr("pc", "" + i.getPC());
1516
}
1517
return e;
1518
}
1519
1520
@Override
1521
public Element visitArrayType(Instruction i, TypeKind tk, Void p) {
1522
Element ie = new Element(i.getMnemonic());
1523
ie.setAttr("num", "" + tk.value);
1524
ie.setAttr("val", tk.name);
1525
return ie;
1526
}
1527
1528
@Override
1529
public Element visitBranch(Instruction i, int i1, Void p) {
1530
Element ie = new Element(i.getMnemonic());
1531
ie.setAttr("lab", "" + (i.getPC() + i1));
1532
return ie;
1533
}
1534
1535
@Override
1536
public Element visitConstantPoolRef(Instruction i, int i1, Void p) {
1537
Element ie = new Element(i.getMnemonic());
1538
ie.setAttr("ref", x.getCpString(i1));
1539
return ie;
1540
}
1541
1542
@Override
1543
public Element visitConstantPoolRefAndValue(Instruction i, int i1, int i2, Void p) {
1544
// workaround for a potential bug in classfile
1545
Element ie = new Element(i.getMnemonic());
1546
if (i.getOpcode().equals(Opcode.IINC_W)) {
1547
ie.setAttr("loc", "" + i1);
1548
ie.setAttr("num", "" + i2);
1549
} else {
1550
ie.setAttr("ref", x.getCpString(i1));
1551
ie.setAttr("val", "" + i2);
1552
}
1553
return ie;
1554
}
1555
1556
@Override
1557
public Element visitLocal(Instruction i, int i1, Void p) {
1558
Element ie = new Element(i.getMnemonic());
1559
ie.setAttr("loc", "" + i1);
1560
return ie;
1561
}
1562
1563
@Override
1564
public Element visitLocalAndValue(Instruction i, int i1, int i2, Void p) {
1565
Element ie = new Element(i.getMnemonic());
1566
ie.setAttr("loc", "" + i1);
1567
ie.setAttr("num", "" + i2);
1568
return ie;
1569
}
1570
1571
@Override
1572
public Element visitLookupSwitch(Instruction i, int i1, int i2, int[] ints,
1573
int[] ints1, Void p) {
1574
Element ie = new Element(i.getMnemonic());
1575
int pc = i.getPC();
1576
ie.setAttr("lab", "" + (pc + i1));
1577
for (int k = 0 ; k < i2 ; k++) {
1578
Element c = new Element("Case");
1579
c.setAttr("num", "" + (ints[k]));
1580
c.setAttr("lab", "" + (pc + ints1[k]));
1581
c.trimToSize();
1582
ie.add(c);
1583
}
1584
return ie;
1585
}
1586
1587
@Override
1588
public Element visitTableSwitch(Instruction i, int i1, int i2, int i3,
1589
int[] ints, Void p) {
1590
Element ie = new Element(i.getMnemonic());
1591
int pc = i.getPC();
1592
ie.setAttr("lab", "" + (pc + i1));
1593
for (int k : ints) {
1594
Element c = new Element("Case");
1595
c.setAttr("num", "" + (k + i2));
1596
c.setAttr("lab", "" + (pc + k));
1597
c.trimToSize();
1598
ie.add(c);
1599
}
1600
return ie;
1601
}
1602
1603
@Override
1604
public Element visitValue(Instruction i, int i1, Void p) {
1605
Element ie = new Element(i.getMnemonic());
1606
ie.setAttr("num", "" + i1);
1607
return ie;
1608
}
1609
1610
@Override
1611
public Element visitUnknown(Instruction i, Void p) {
1612
Element e = new Element(i.getMnemonic());
1613
e.setAttr("pc", "" + i.getPC());
1614
e.setAttr("opcode", "" + i.getOpcode().opcode);
1615
return e;
1616
}
1617
}
1618
1619
class AnnotationsElementVisitor implements Annotation.element_value.Visitor<Element, Element> {
1620
final ClassReader x;
1621
final ClassFile cf;
1622
1623
public AnnotationsElementVisitor(ClassReader x, ClassFile cf) {
1624
this.x = x;
1625
this.cf = cf;
1626
}
1627
1628
public Element visit(Annotation.element_value v, Element p) {
1629
return v.accept(this, p);
1630
}
1631
1632
@Override
1633
public Element visitPrimitive(Primitive_element_value e, Element p) {
1634
Element el = new Element("String");
1635
el.setAttr("val", x.getCpString(e.const_value_index));
1636
el.trimToSize();
1637
return el;
1638
}
1639
1640
@Override
1641
public Element visitEnum(Enum_element_value e, Element p) {
1642
Element el = new Element("Enum");
1643
el.setAttr("name", x.getCpString(e.const_name_index));
1644
el.setAttr("type", x.getCpString(e.type_name_index));
1645
el.trimToSize();
1646
return el;
1647
}
1648
1649
@Override
1650
public Element visitClass(Class_element_value c, Element p) {
1651
Element el = new Element("Class");
1652
el.setAttr("name", x.getCpString(c.class_info_index));
1653
el.trimToSize();
1654
return el;
1655
}
1656
1657
@Override
1658
public Element visitAnnotation(Annotation_element_value a, Element p) {
1659
Element el = new Element("Annotation");
1660
Annotation anno = a.annotation_value;
1661
for (Annotation.element_value_pair evp : anno.element_value_pairs) {
1662
Element child = visit(evp.value, el);
1663
if (child != null) {
1664
el.add(child);
1665
}
1666
}
1667
el.trimToSize();
1668
return el;
1669
}
1670
1671
@Override
1672
public Element visitArray(Array_element_value a, Element p) {
1673
Element el = new Element("Array");
1674
for (Annotation.element_value v : a.values) {
1675
Element child = visit(v, el);
1676
if (child != null) {
1677
el.add(child);
1678
}
1679
}
1680
el.trimToSize();
1681
return el;
1682
}
1683
}
1684
1685