1 /* 2 * Copyright (c) 2007, 2018, 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 26 package com.sun.tools.javap; 27 28 import com.sun.tools.classfile.AccessFlags; 29 import com.sun.tools.classfile.AnnotationDefault_attribute; 30 import com.sun.tools.classfile.Attribute; 31 import com.sun.tools.classfile.Attributes; 32 import com.sun.tools.classfile.BootstrapMethods_attribute; 33 import com.sun.tools.classfile.CharacterRangeTable_attribute; 34 import com.sun.tools.classfile.CharacterRangeTable_attribute.Entry; 35 import com.sun.tools.classfile.Code_attribute; 36 import com.sun.tools.classfile.CompilationID_attribute; 37 import com.sun.tools.classfile.ConstantPool; 38 import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info; 39 import com.sun.tools.classfile.ConstantPoolException; 40 import com.sun.tools.classfile.ConstantValue_attribute; 41 import com.sun.tools.classfile.DefaultAttribute; 42 import com.sun.tools.classfile.Deprecated_attribute; 43 import com.sun.tools.classfile.EnclosingMethod_attribute; 44 import com.sun.tools.classfile.Exceptions_attribute; 45 import com.sun.tools.classfile.InnerClasses_attribute; 46 import com.sun.tools.classfile.InnerClasses_attribute.Info; 47 import com.sun.tools.classfile.LineNumberTable_attribute; 48 import com.sun.tools.classfile.LocalVariableTable_attribute; 49 import com.sun.tools.classfile.LocalVariableTypeTable_attribute; 50 import com.sun.tools.classfile.MethodParameters_attribute; 51 import com.sun.tools.classfile.Module_attribute; 52 import com.sun.tools.classfile.ModuleHashes_attribute; 53 import com.sun.tools.classfile.ModuleMainClass_attribute; 54 import com.sun.tools.classfile.ModulePackages_attribute; 55 import com.sun.tools.classfile.ModuleResolution_attribute; 56 import com.sun.tools.classfile.ModuleTarget_attribute; 57 import com.sun.tools.classfile.NestHost_attribute; 58 import com.sun.tools.classfile.NestMembers_attribute; 59 import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; 60 import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; 61 import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; 62 import com.sun.tools.classfile.RuntimeParameterAnnotations_attribute; 63 import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; 64 import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute; 65 import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; 66 import com.sun.tools.classfile.Signature_attribute; 67 import com.sun.tools.classfile.SourceDebugExtension_attribute; 68 import com.sun.tools.classfile.SourceFile_attribute; 69 import com.sun.tools.classfile.SourceID_attribute; 70 import com.sun.tools.classfile.StackMapTable_attribute; 71 import com.sun.tools.classfile.StackMap_attribute; 72 import com.sun.tools.classfile.Synthetic_attribute; 73 74 import static com.sun.tools.classfile.AccessFlags.*; 75 76 import com.sun.tools.javac.util.Assert; 77 import com.sun.tools.javac.util.StringUtils; 78 79 /* 80 * A writer for writing Attributes as text. 81 * 82 * <p><b>This is NOT part of any supported API. 83 * If you write code that depends on this, you do so at your own risk. 84 * This code and its internal interfaces are subject to change or 85 * deletion without notice.</b> 86 */ 87 public class AttributeWriter extends BasicWriter 88 implements Attribute.Visitor<Void,Void> 89 { instance(Context context)90 public static AttributeWriter instance(Context context) { 91 AttributeWriter instance = context.get(AttributeWriter.class); 92 if (instance == null) 93 instance = new AttributeWriter(context); 94 return instance; 95 } 96 AttributeWriter(Context context)97 protected AttributeWriter(Context context) { 98 super(context); 99 context.put(AttributeWriter.class, this); 100 annotationWriter = AnnotationWriter.instance(context); 101 codeWriter = CodeWriter.instance(context); 102 constantWriter = ConstantWriter.instance(context); 103 options = Options.instance(context); 104 } 105 write(Object owner, Attribute attr, ConstantPool constant_pool)106 public void write(Object owner, Attribute attr, ConstantPool constant_pool) { 107 if (attr != null) { 108 Assert.checkNonNull(constant_pool); 109 Assert.checkNonNull(owner); 110 this.constant_pool = constant_pool; 111 this.owner = owner; 112 attr.accept(this, null); 113 } 114 } 115 write(Object owner, Attributes attrs, ConstantPool constant_pool)116 public void write(Object owner, Attributes attrs, ConstantPool constant_pool) { 117 if (attrs != null) { 118 Assert.checkNonNull(constant_pool); 119 Assert.checkNonNull(owner); 120 this.constant_pool = constant_pool; 121 this.owner = owner; 122 for (Attribute attr: attrs) 123 attr.accept(this, null); 124 } 125 } 126 127 @Override visitDefault(DefaultAttribute attr, Void ignore)128 public Void visitDefault(DefaultAttribute attr, Void ignore) { 129 if (attr.reason != null) { 130 report(attr.reason); 131 } 132 byte[] data = attr.info; 133 int i = 0; 134 int j = 0; 135 print(" "); 136 try { 137 print(attr.getName(constant_pool)); 138 } catch (ConstantPoolException e) { 139 report(e); 140 print("attribute name = #" + attr.attribute_name_index); 141 } 142 print(": "); 143 println("length = 0x" + toHex(attr.info.length)); 144 145 print(" "); 146 147 while (i < data.length) { 148 print(toHex(data[i], 2)); 149 150 j++; 151 if (j == 16) { 152 println(); 153 print(" "); 154 j = 0; 155 } else { 156 print(" "); 157 } 158 i++; 159 } 160 println(); 161 return null; 162 } 163 164 @Override visitAnnotationDefault(AnnotationDefault_attribute attr, Void ignore)165 public Void visitAnnotationDefault(AnnotationDefault_attribute attr, Void ignore) { 166 println("AnnotationDefault:"); 167 indent(+1); 168 print("default_value: "); 169 annotationWriter.write(attr.default_value); 170 indent(-1); 171 println(); 172 return null; 173 } 174 175 @Override visitBootstrapMethods(BootstrapMethods_attribute attr, Void p)176 public Void visitBootstrapMethods(BootstrapMethods_attribute attr, Void p) { 177 println(Attribute.BootstrapMethods + ":"); 178 for (int i = 0; i < attr.bootstrap_method_specifiers.length ; i++) { 179 BootstrapMethods_attribute.BootstrapMethodSpecifier bsm = attr.bootstrap_method_specifiers[i]; 180 indent(+1); 181 print(i + ": #" + bsm.bootstrap_method_ref + " "); 182 println(constantWriter.stringValue(bsm.bootstrap_method_ref)); 183 indent(+1); 184 println("Method arguments:"); 185 indent(+1); 186 for (int j = 0; j < bsm.bootstrap_arguments.length; j++) { 187 print("#" + bsm.bootstrap_arguments[j] + " "); 188 println(constantWriter.stringValue(bsm.bootstrap_arguments[j])); 189 } 190 indent(-3); 191 } 192 return null; 193 } 194 195 @Override visitCharacterRangeTable(CharacterRangeTable_attribute attr, Void ignore)196 public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, Void ignore) { 197 println("CharacterRangeTable:"); 198 indent(+1); 199 for (Entry e : attr.character_range_table) { 200 print(String.format(" %2d, %2d, %6x, %6x, %4x", 201 e.start_pc, e.end_pc, 202 e.character_range_start, e.character_range_end, 203 e.flags)); 204 tab(); 205 print(String.format("// %2d, %2d, %4d:%02d, %4d:%02d", 206 e.start_pc, e.end_pc, 207 (e.character_range_start >> 10), (e.character_range_start & 0x3ff), 208 (e.character_range_end >> 10), (e.character_range_end & 0x3ff))); 209 if ((e.flags & CharacterRangeTable_attribute.CRT_STATEMENT) != 0) 210 print(", statement"); 211 if ((e.flags & CharacterRangeTable_attribute.CRT_BLOCK) != 0) 212 print(", block"); 213 if ((e.flags & CharacterRangeTable_attribute.CRT_ASSIGNMENT) != 0) 214 print(", assignment"); 215 if ((e.flags & CharacterRangeTable_attribute.CRT_FLOW_CONTROLLER) != 0) 216 print(", flow-controller"); 217 if ((e.flags & CharacterRangeTable_attribute.CRT_FLOW_TARGET) != 0) 218 print(", flow-target"); 219 if ((e.flags & CharacterRangeTable_attribute.CRT_INVOKE) != 0) 220 print(", invoke"); 221 if ((e.flags & CharacterRangeTable_attribute.CRT_CREATE) != 0) 222 print(", create"); 223 if ((e.flags & CharacterRangeTable_attribute.CRT_BRANCH_TRUE) != 0) 224 print(", branch-true"); 225 if ((e.flags & CharacterRangeTable_attribute.CRT_BRANCH_FALSE) != 0) 226 print(", branch-false"); 227 println(); 228 } 229 indent(-1); 230 return null; 231 } 232 233 @Override visitCode(Code_attribute attr, Void ignore)234 public Void visitCode(Code_attribute attr, Void ignore) { 235 codeWriter.write(attr, constant_pool); 236 return null; 237 } 238 239 @Override visitCompilationID(CompilationID_attribute attr, Void ignore)240 public Void visitCompilationID(CompilationID_attribute attr, Void ignore) { 241 constantWriter.write(attr.compilationID_index); 242 return null; 243 } 244 245 @Override visitConstantValue(ConstantValue_attribute attr, Void ignore)246 public Void visitConstantValue(ConstantValue_attribute attr, Void ignore) { 247 print("ConstantValue: "); 248 constantWriter.write(attr.constantvalue_index); 249 println(); 250 return null; 251 } 252 253 @Override visitDeprecated(Deprecated_attribute attr, Void ignore)254 public Void visitDeprecated(Deprecated_attribute attr, Void ignore) { 255 println("Deprecated: true"); 256 return null; 257 } 258 259 @Override visitEnclosingMethod(EnclosingMethod_attribute attr, Void ignore)260 public Void visitEnclosingMethod(EnclosingMethod_attribute attr, Void ignore) { 261 print("EnclosingMethod: #" + attr.class_index + ".#" + attr.method_index); 262 tab(); 263 print("// " + getJavaClassName(attr)); 264 if (attr.method_index != 0) 265 print("." + getMethodName(attr)); 266 println(); 267 return null; 268 } 269 getJavaClassName(EnclosingMethod_attribute a)270 private String getJavaClassName(EnclosingMethod_attribute a) { 271 try { 272 return getJavaName(a.getClassName(constant_pool)); 273 } catch (ConstantPoolException e) { 274 return report(e); 275 } 276 } 277 getMethodName(EnclosingMethod_attribute a)278 private String getMethodName(EnclosingMethod_attribute a) { 279 try { 280 return a.getMethodName(constant_pool); 281 } catch (ConstantPoolException e) { 282 return report(e); 283 } 284 } 285 286 @Override visitExceptions(Exceptions_attribute attr, Void ignore)287 public Void visitExceptions(Exceptions_attribute attr, Void ignore) { 288 println("Exceptions:"); 289 indent(+1); 290 print("throws "); 291 for (int i = 0; i < attr.number_of_exceptions; i++) { 292 if (i > 0) 293 print(", "); 294 print(getJavaException(attr, i)); 295 } 296 println(); 297 indent(-1); 298 return null; 299 } 300 getJavaException(Exceptions_attribute attr, int index)301 private String getJavaException(Exceptions_attribute attr, int index) { 302 try { 303 return getJavaName(attr.getException(index, constant_pool)); 304 } catch (ConstantPoolException e) { 305 return report(e); 306 } 307 } 308 309 310 @Override visitInnerClasses(InnerClasses_attribute attr, Void ignore)311 public Void visitInnerClasses(InnerClasses_attribute attr, Void ignore) { 312 boolean first = true; 313 for (Info info : attr.classes) { 314 //access 315 AccessFlags access_flags = info.inner_class_access_flags; 316 if (options.checkAccess(access_flags)) { 317 if (first) { 318 writeInnerClassHeader(); 319 first = false; 320 } 321 for (String name: access_flags.getInnerClassModifiers()) 322 print(name + " "); 323 if (info.inner_name_index != 0) { 324 print("#" + info.inner_name_index + "= "); 325 } 326 print("#" + info.inner_class_info_index); 327 if (info.outer_class_info_index != 0) { 328 print(" of #" + info.outer_class_info_index); 329 } 330 print(";"); 331 tab(); 332 print("// "); 333 if (info.inner_name_index != 0) { 334 print(getInnerName(constant_pool, info) + "="); 335 } 336 constantWriter.write(info.inner_class_info_index); 337 if (info.outer_class_info_index != 0) { 338 print(" of "); 339 constantWriter.write(info.outer_class_info_index); 340 } 341 println(); 342 } 343 } 344 if (!first) 345 indent(-1); 346 return null; 347 } 348 getInnerName(ConstantPool constant_pool, InnerClasses_attribute.Info info)349 String getInnerName(ConstantPool constant_pool, InnerClasses_attribute.Info info) { 350 try { 351 return info.getInnerName(constant_pool); 352 } catch (ConstantPoolException e) { 353 return report(e); 354 } 355 } 356 writeInnerClassHeader()357 private void writeInnerClassHeader() { 358 println("InnerClasses:"); 359 indent(+1); 360 } 361 362 @Override visitLineNumberTable(LineNumberTable_attribute attr, Void ignore)363 public Void visitLineNumberTable(LineNumberTable_attribute attr, Void ignore) { 364 println("LineNumberTable:"); 365 indent(+1); 366 for (LineNumberTable_attribute.Entry entry: attr.line_number_table) { 367 println("line " + entry.line_number + ": " + entry.start_pc); 368 } 369 indent(-1); 370 return null; 371 } 372 373 @Override visitLocalVariableTable(LocalVariableTable_attribute attr, Void ignore)374 public Void visitLocalVariableTable(LocalVariableTable_attribute attr, Void ignore) { 375 println("LocalVariableTable:"); 376 indent(+1); 377 println("Start Length Slot Name Signature"); 378 for (LocalVariableTable_attribute.Entry entry : attr.local_variable_table) { 379 println(String.format("%5d %7d %5d %5s %s", 380 entry.start_pc, entry.length, entry.index, 381 constantWriter.stringValue(entry.name_index), 382 constantWriter.stringValue(entry.descriptor_index))); 383 } 384 indent(-1); 385 return null; 386 } 387 388 @Override visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, Void ignore)389 public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, Void ignore) { 390 println("LocalVariableTypeTable:"); 391 indent(+1); 392 println("Start Length Slot Name Signature"); 393 for (LocalVariableTypeTable_attribute.Entry entry : attr.local_variable_table) { 394 println(String.format("%5d %7d %5d %5s %s", 395 entry.start_pc, entry.length, entry.index, 396 constantWriter.stringValue(entry.name_index), 397 constantWriter.stringValue(entry.signature_index))); 398 } 399 indent(-1); 400 return null; 401 } 402 403 @Override visitNestHost(NestHost_attribute attr, Void aVoid)404 public Void visitNestHost(NestHost_attribute attr, Void aVoid) { 405 print("NestHost: "); 406 constantWriter.write(attr.top_index); 407 println(); 408 return null; 409 } 410 getJavaClassName(ModuleMainClass_attribute a)411 private String getJavaClassName(ModuleMainClass_attribute a) { 412 try { 413 return getJavaName(a.getMainClassName(constant_pool)); 414 } catch (ConstantPoolException e) { 415 return report(e); 416 } 417 } 418 419 private static final String format = "%-31s%s"; 420 421 @Override visitMethodParameters(MethodParameters_attribute attr, Void ignore)422 public Void visitMethodParameters(MethodParameters_attribute attr, 423 Void ignore) { 424 final String header = String.format(format, "Name", "Flags"); 425 println("MethodParameters:"); 426 indent(+1); 427 println(header); 428 for (MethodParameters_attribute.Entry entry : 429 attr.method_parameter_table) { 430 String namestr = 431 entry.name_index != 0 ? 432 constantWriter.stringValue(entry.name_index) : "<no name>"; 433 String flagstr = 434 (0 != (entry.flags & ACC_FINAL) ? "final " : "") + 435 (0 != (entry.flags & ACC_MANDATED) ? "mandated " : "") + 436 (0 != (entry.flags & ACC_SYNTHETIC) ? "synthetic" : ""); 437 println(String.format(format, namestr, flagstr)); 438 } 439 indent(-1); 440 return null; 441 } 442 443 @Override visitModule(Module_attribute attr, Void ignore)444 public Void visitModule(Module_attribute attr, Void ignore) { 445 println("Module:"); 446 indent(+1); 447 448 print("#" + attr.module_name); 449 print(","); 450 print(String.format("%x", attr.module_flags)); 451 tab(); 452 print("// " + constantWriter.stringValue(attr.module_name)); 453 if ((attr.module_flags & Module_attribute.ACC_OPEN) != 0) 454 print(" ACC_OPEN"); 455 if ((attr.module_flags & Module_attribute.ACC_MANDATED) != 0) 456 print(" ACC_MANDATED"); 457 if ((attr.module_flags & Module_attribute.ACC_SYNTHETIC) != 0) 458 print(" ACC_SYNTHETIC"); 459 println(); 460 print("#" + attr.module_version_index); 461 if (attr.module_version_index != 0) { 462 tab(); 463 print("// " + constantWriter.stringValue(attr.module_version_index)); 464 } 465 println(); 466 467 printRequiresTable(attr); 468 printExportsTable(attr); 469 printOpensTable(attr); 470 printUsesTable(attr); 471 printProvidesTable(attr); 472 indent(-1); 473 return null; 474 } 475 printRequiresTable(Module_attribute attr)476 protected void printRequiresTable(Module_attribute attr) { 477 Module_attribute.RequiresEntry[] entries = attr.requires; 478 print(entries.length); 479 tab(); 480 println("// " + "requires"); 481 indent(+1); 482 for (Module_attribute.RequiresEntry e: entries) { 483 print("#" + e.requires_index + "," + String.format("%x", e.requires_flags)); 484 tab(); 485 print("// " + constantWriter.stringValue(e.requires_index)); 486 if ((e.requires_flags & Module_attribute.ACC_TRANSITIVE) != 0) 487 print(" ACC_TRANSITIVE"); 488 if ((e.requires_flags & Module_attribute.ACC_STATIC_PHASE) != 0) 489 print(" ACC_STATIC_PHASE"); 490 if ((e.requires_flags & Module_attribute.ACC_SYNTHETIC) != 0) 491 print(" ACC_SYNTHETIC"); 492 if ((e.requires_flags & Module_attribute.ACC_MANDATED) != 0) 493 print(" ACC_MANDATED"); 494 println(); 495 print("#" + e.requires_version_index); 496 if (e.requires_version_index != 0) { 497 tab(); 498 print("// " + constantWriter.stringValue(e.requires_version_index)); 499 } 500 println(); 501 } 502 indent(-1); 503 } 504 printExportsTable(Module_attribute attr)505 protected void printExportsTable(Module_attribute attr) { 506 Module_attribute.ExportsEntry[] entries = attr.exports; 507 print(entries.length); 508 tab(); 509 println("// exports"); 510 indent(+1); 511 for (Module_attribute.ExportsEntry e: entries) { 512 printExportOpenEntry(e.exports_index, e.exports_flags, e.exports_to_index); 513 } 514 indent(-1); 515 } 516 printOpensTable(Module_attribute attr)517 protected void printOpensTable(Module_attribute attr) { 518 Module_attribute.OpensEntry[] entries = attr.opens; 519 print(entries.length); 520 tab(); 521 println("// opens"); 522 indent(+1); 523 for (Module_attribute.OpensEntry e: entries) { 524 printExportOpenEntry(e.opens_index, e.opens_flags, e.opens_to_index); 525 } 526 indent(-1); 527 } 528 printExportOpenEntry(int index, int flags, int[] to_index)529 protected void printExportOpenEntry(int index, int flags, int[] to_index) { 530 print("#" + index + "," + String.format("%x", flags)); 531 tab(); 532 print("// "); 533 print(constantWriter.stringValue(index)); 534 if ((flags & Module_attribute.ACC_MANDATED) != 0) 535 print(" ACC_MANDATED"); 536 if ((flags & Module_attribute.ACC_SYNTHETIC) != 0) 537 print(" ACC_SYNTHETIC"); 538 if (to_index.length == 0) { 539 println(); 540 } else { 541 println(" to ... " + to_index.length); 542 indent(+1); 543 for (int to: to_index) { 544 print("#" + to); 545 tab(); 546 println("// ... to " + constantWriter.stringValue(to)); 547 } 548 indent(-1); 549 } 550 } 551 printUsesTable(Module_attribute attr)552 protected void printUsesTable(Module_attribute attr) { 553 int[] entries = attr.uses_index; 554 print(entries.length); 555 tab(); 556 println("// " + "uses"); 557 indent(+1); 558 for (int e: entries) { 559 print("#" + e); 560 tab(); 561 println("// " + constantWriter.stringValue(e)); 562 } 563 indent(-1); 564 } 565 printProvidesTable(Module_attribute attr)566 protected void printProvidesTable(Module_attribute attr) { 567 Module_attribute.ProvidesEntry[] entries = attr.provides; 568 print(entries.length); 569 tab(); 570 println("// " + "provides"); 571 indent(+1); 572 for (Module_attribute.ProvidesEntry e: entries) { 573 print("#" + e.provides_index); 574 tab(); 575 print("// "); 576 print(constantWriter.stringValue(e.provides_index)); 577 println(" with ... " + e.with_count); 578 indent(+1); 579 for (int with : e.with_index) { 580 print("#" + with); 581 tab(); 582 println("// ... with " + constantWriter.stringValue(with)); 583 } 584 indent(-1); 585 } 586 indent(-1); 587 } 588 589 @Override visitModuleHashes(ModuleHashes_attribute attr, Void ignore)590 public Void visitModuleHashes(ModuleHashes_attribute attr, Void ignore) { 591 println("ModuleHashes:"); 592 indent(+1); 593 print("algorithm: #" + attr.algorithm_index); 594 tab(); 595 println("// " + getAlgorithm(attr)); 596 print(attr.hashes_table_length); 597 tab(); 598 println("// hashes"); 599 for (ModuleHashes_attribute.Entry e : attr.hashes_table) { 600 print("#" + e.module_name_index); 601 tab(); 602 println("// " + getModuleName(e)); 603 println("hash_length: " + e.hash.length); 604 println("hash: [" + toHex(e.hash) + "]"); 605 } 606 indent(-1); 607 return null; 608 } 609 getAlgorithm(ModuleHashes_attribute attr)610 private String getAlgorithm(ModuleHashes_attribute attr) { 611 try { 612 return constant_pool.getUTF8Value(attr.algorithm_index); 613 } catch (ConstantPoolException e) { 614 return report(e); 615 } 616 } 617 getModuleName(ModuleHashes_attribute.Entry entry)618 private String getModuleName(ModuleHashes_attribute.Entry entry) { 619 try { 620 int utf8Index = constant_pool.getModuleInfo(entry.module_name_index).name_index; 621 return constant_pool.getUTF8Value(utf8Index); 622 } catch (ConstantPoolException e) { 623 return report(e); 624 } 625 } 626 627 @Override visitModuleMainClass(ModuleMainClass_attribute attr, Void ignore)628 public Void visitModuleMainClass(ModuleMainClass_attribute attr, Void ignore) { 629 print("ModuleMainClass: #" + attr.main_class_index); 630 tab(); 631 print("// " + getJavaClassName(attr)); 632 println(); 633 return null; 634 } 635 636 @Override visitModulePackages(ModulePackages_attribute attr, Void ignore)637 public Void visitModulePackages(ModulePackages_attribute attr, Void ignore) { 638 println("ModulePackages: "); 639 indent(+1); 640 for (int i = 0; i < attr.packages_count; i++) { 641 print("#" + attr.packages_index[i]); 642 tab(); 643 println("// " + getJavaPackage(attr, i)); 644 } 645 indent(-1); 646 return null; 647 } 648 getJavaPackage(ModulePackages_attribute attr, int index)649 private String getJavaPackage(ModulePackages_attribute attr, int index) { 650 try { 651 return getJavaName(attr.getPackage(index, constant_pool)); 652 } catch (ConstantPoolException e) { 653 return report(e); 654 } 655 } 656 657 @Override visitModuleResolution(ModuleResolution_attribute attr, Void ignore)658 public Void visitModuleResolution(ModuleResolution_attribute attr, Void ignore) { 659 println("ModuleResolution:"); 660 indent(+1); 661 print(String.format("%x", attr.resolution_flags)); 662 tab(); 663 print("// "); 664 int flags = attr.resolution_flags; 665 if ((flags & ModuleResolution_attribute.DO_NOT_RESOLVE_BY_DEFAULT) != 0) 666 print(" DO_NOT_RESOLVE_BY_DEFAULT"); 667 if ((flags & ModuleResolution_attribute.WARN_DEPRECATED) != 0) 668 print(" WARN_DEPRECATED"); 669 if ((flags & ModuleResolution_attribute.WARN_DEPRECATED_FOR_REMOVAL) != 0) 670 print(" WARN_DEPRECATED_FOR_REMOVAL"); 671 if ((flags & ModuleResolution_attribute.WARN_INCUBATING) != 0) 672 print(" WARN_INCUBATING"); 673 println(); 674 indent(-1); 675 return null; 676 } 677 678 @Override visitModuleTarget(ModuleTarget_attribute attr, Void ignore)679 public Void visitModuleTarget(ModuleTarget_attribute attr, Void ignore) { 680 println("ModuleTarget:"); 681 indent(+1); 682 print("target_platform: #" + attr.target_platform_index); 683 if (attr.target_platform_index != 0) { 684 tab(); 685 print("// " + getTargetPlatform(attr)); 686 } 687 println(); 688 indent(-1); 689 return null; 690 } 691 getTargetPlatform(ModuleTarget_attribute attr)692 private String getTargetPlatform(ModuleTarget_attribute attr) { 693 try { 694 return constant_pool.getUTF8Value(attr.target_platform_index); 695 } catch (ConstantPoolException e) { 696 return report(e); 697 } 698 } 699 700 @Override visitNestMembers(NestMembers_attribute attr, Void aVoid)701 public Void visitNestMembers(NestMembers_attribute attr, Void aVoid) { 702 println("NestMembers:"); 703 indent(+1); 704 try { 705 CONSTANT_Class_info[] children = attr.getChildren(constant_pool); 706 for (int i = 0; i < attr.members_indexes.length; i++) { 707 println(constantWriter.stringValue(children[i])); 708 } 709 indent(-1); 710 } catch (ConstantPoolException ex) { 711 throw new AssertionError(ex); 712 } 713 return null; 714 } 715 716 @Override visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, Void ignore)717 public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, Void ignore) { 718 println("RuntimeVisibleAnnotations:"); 719 indent(+1); 720 for (int i = 0; i < attr.annotations.length; i++) { 721 print(i + ": "); 722 annotationWriter.write(attr.annotations[i]); 723 println(); 724 } 725 indent(-1); 726 return null; 727 } 728 729 @Override visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, Void ignore)730 public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, Void ignore) { 731 println("RuntimeInvisibleAnnotations:"); 732 indent(+1); 733 for (int i = 0; i < attr.annotations.length; i++) { 734 print(i + ": "); 735 annotationWriter.write(attr.annotations[i]); 736 println(); 737 } 738 indent(-1); 739 return null; 740 } 741 742 @Override visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, Void ignore)743 public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, Void ignore) { 744 println("RuntimeVisibleTypeAnnotations:"); 745 indent(+1); 746 for (int i = 0; i < attr.annotations.length; i++) { 747 print(i + ": "); 748 annotationWriter.write(attr.annotations[i]); 749 println(); 750 } 751 indent(-1); 752 return null; 753 } 754 755 @Override visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, Void ignore)756 public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, Void ignore) { 757 println("RuntimeInvisibleTypeAnnotations:"); 758 indent(+1); 759 for (int i = 0; i < attr.annotations.length; i++) { 760 print(i + ": "); 761 annotationWriter.write(attr.annotations[i]); 762 println(); 763 } 764 indent(-1); 765 return null; 766 } 767 visitParameterAnnotations(String message, RuntimeParameterAnnotations_attribute attr)768 private void visitParameterAnnotations(String message, RuntimeParameterAnnotations_attribute attr) { 769 println(message); 770 indent(+1); 771 for (int param = 0; param < attr.parameter_annotations.length; param++) { 772 println("parameter " + param + ": "); 773 indent(+1); 774 for (int i = 0; i < attr.parameter_annotations[param].length; i++) { 775 print(i + ": "); 776 annotationWriter.write(attr.parameter_annotations[param][i]); 777 println(); 778 } 779 indent(-1); 780 } 781 indent(-1); 782 } 783 784 @Override visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore)785 public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) { 786 visitParameterAnnotations("RuntimeVisibleParameterAnnotations:", (RuntimeParameterAnnotations_attribute) attr); 787 return null; 788 } 789 790 @Override visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, Void ignore)791 public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, Void ignore) { 792 visitParameterAnnotations("RuntimeInvisibleParameterAnnotations:", (RuntimeParameterAnnotations_attribute) attr); 793 return null; 794 } 795 796 @Override visitSignature(Signature_attribute attr, Void ignore)797 public Void visitSignature(Signature_attribute attr, Void ignore) { 798 print("Signature: #" + attr.signature_index); 799 tab(); 800 println("// " + getSignature(attr)); 801 return null; 802 } 803 getSignature(Signature_attribute info)804 String getSignature(Signature_attribute info) { 805 try { 806 return info.getSignature(constant_pool); 807 } catch (ConstantPoolException e) { 808 return report(e); 809 } 810 } 811 812 @Override visitSourceDebugExtension(SourceDebugExtension_attribute attr, Void ignore)813 public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, Void ignore) { 814 println("SourceDebugExtension:"); 815 indent(+1); 816 for (String s: attr.getValue().split("[\r\n]+")) { 817 println(s); 818 } 819 indent(-1); 820 return null; 821 } 822 823 @Override visitSourceFile(SourceFile_attribute attr, Void ignore)824 public Void visitSourceFile(SourceFile_attribute attr, Void ignore) { 825 println("SourceFile: \"" + getSourceFile(attr) + "\""); 826 return null; 827 } 828 getSourceFile(SourceFile_attribute attr)829 private String getSourceFile(SourceFile_attribute attr) { 830 try { 831 return attr.getSourceFile(constant_pool); 832 } catch (ConstantPoolException e) { 833 return report(e); 834 } 835 } 836 837 @Override visitSourceID(SourceID_attribute attr, Void ignore)838 public Void visitSourceID(SourceID_attribute attr, Void ignore) { 839 constantWriter.write(attr.sourceID_index); 840 return null; 841 } 842 843 @Override visitStackMap(StackMap_attribute attr, Void ignore)844 public Void visitStackMap(StackMap_attribute attr, Void ignore) { 845 println("StackMap: number_of_entries = " + attr.number_of_entries); 846 indent(+1); 847 StackMapTableWriter w = new StackMapTableWriter(); 848 for (StackMapTable_attribute.stack_map_frame entry : attr.entries) { 849 w.write(entry); 850 } 851 indent(-1); 852 return null; 853 } 854 855 @Override visitStackMapTable(StackMapTable_attribute attr, Void ignore)856 public Void visitStackMapTable(StackMapTable_attribute attr, Void ignore) { 857 println("StackMapTable: number_of_entries = " + attr.number_of_entries); 858 indent(+1); 859 StackMapTableWriter w = new StackMapTableWriter(); 860 for (StackMapTable_attribute.stack_map_frame entry : attr.entries) { 861 w.write(entry); 862 } 863 indent(-1); 864 return null; 865 } 866 867 class StackMapTableWriter // also handles CLDC StackMap attributes 868 implements StackMapTable_attribute.stack_map_frame.Visitor<Void,Void> { write(StackMapTable_attribute.stack_map_frame frame)869 public void write(StackMapTable_attribute.stack_map_frame frame) { 870 frame.accept(this, null); 871 } 872 873 @Override visit_same_frame(StackMapTable_attribute.same_frame frame, Void p)874 public Void visit_same_frame(StackMapTable_attribute.same_frame frame, Void p) { 875 printHeader(frame, "/* same */"); 876 return null; 877 } 878 879 @Override visit_same_locals_1_stack_item_frame(StackMapTable_attribute.same_locals_1_stack_item_frame frame, Void p)880 public Void visit_same_locals_1_stack_item_frame(StackMapTable_attribute.same_locals_1_stack_item_frame frame, Void p) { 881 printHeader(frame, "/* same_locals_1_stack_item */"); 882 indent(+1); 883 printMap("stack", frame.stack); 884 indent(-1); 885 return null; 886 } 887 888 @Override visit_same_locals_1_stack_item_frame_extended(StackMapTable_attribute.same_locals_1_stack_item_frame_extended frame, Void p)889 public Void visit_same_locals_1_stack_item_frame_extended(StackMapTable_attribute.same_locals_1_stack_item_frame_extended frame, Void p) { 890 printHeader(frame, "/* same_locals_1_stack_item_frame_extended */"); 891 indent(+1); 892 println("offset_delta = " + frame.offset_delta); 893 printMap("stack", frame.stack); 894 indent(-1); 895 return null; 896 } 897 898 @Override visit_chop_frame(StackMapTable_attribute.chop_frame frame, Void p)899 public Void visit_chop_frame(StackMapTable_attribute.chop_frame frame, Void p) { 900 printHeader(frame, "/* chop */"); 901 indent(+1); 902 println("offset_delta = " + frame.offset_delta); 903 indent(-1); 904 return null; 905 } 906 907 @Override visit_same_frame_extended(StackMapTable_attribute.same_frame_extended frame, Void p)908 public Void visit_same_frame_extended(StackMapTable_attribute.same_frame_extended frame, Void p) { 909 printHeader(frame, "/* same_frame_extended */"); 910 indent(+1); 911 println("offset_delta = " + frame.offset_delta); 912 indent(-1); 913 return null; 914 } 915 916 @Override visit_append_frame(StackMapTable_attribute.append_frame frame, Void p)917 public Void visit_append_frame(StackMapTable_attribute.append_frame frame, Void p) { 918 printHeader(frame, "/* append */"); 919 indent(+1); 920 println("offset_delta = " + frame.offset_delta); 921 printMap("locals", frame.locals); 922 indent(-1); 923 return null; 924 } 925 926 @Override visit_full_frame(StackMapTable_attribute.full_frame frame, Void p)927 public Void visit_full_frame(StackMapTable_attribute.full_frame frame, Void p) { 928 if (frame instanceof StackMap_attribute.stack_map_frame) { 929 printHeader(frame, "offset = " + frame.offset_delta); 930 indent(+1); 931 } else { 932 printHeader(frame, "/* full_frame */"); 933 indent(+1); 934 println("offset_delta = " + frame.offset_delta); 935 } 936 printMap("locals", frame.locals); 937 printMap("stack", frame.stack); 938 indent(-1); 939 return null; 940 } 941 printHeader(StackMapTable_attribute.stack_map_frame frame, String extra)942 void printHeader(StackMapTable_attribute.stack_map_frame frame, String extra) { 943 print("frame_type = " + frame.frame_type + " "); 944 println(extra); 945 } 946 printMap(String name, StackMapTable_attribute.verification_type_info[] map)947 void printMap(String name, StackMapTable_attribute.verification_type_info[] map) { 948 print(name + " = ["); 949 for (int i = 0; i < map.length; i++) { 950 StackMapTable_attribute.verification_type_info info = map[i]; 951 int tag = info.tag; 952 switch (tag) { 953 case StackMapTable_attribute.verification_type_info.ITEM_Object: 954 print(" "); 955 constantWriter.write(((StackMapTable_attribute.Object_variable_info) info).cpool_index); 956 break; 957 case StackMapTable_attribute.verification_type_info.ITEM_Uninitialized: 958 print(" " + mapTypeName(tag)); 959 print(" " + ((StackMapTable_attribute.Uninitialized_variable_info) info).offset); 960 break; 961 default: 962 print(" " + mapTypeName(tag)); 963 } 964 print(i == (map.length - 1) ? " " : ","); 965 } 966 println("]"); 967 } 968 mapTypeName(int tag)969 String mapTypeName(int tag) { 970 switch (tag) { 971 case StackMapTable_attribute.verification_type_info.ITEM_Top: 972 return "top"; 973 974 case StackMapTable_attribute.verification_type_info.ITEM_Integer: 975 return "int"; 976 977 case StackMapTable_attribute.verification_type_info.ITEM_Float: 978 return "float"; 979 980 case StackMapTable_attribute.verification_type_info.ITEM_Long: 981 return "long"; 982 983 case StackMapTable_attribute.verification_type_info.ITEM_Double: 984 return "double"; 985 986 case StackMapTable_attribute.verification_type_info.ITEM_Null: 987 return "null"; 988 989 case StackMapTable_attribute.verification_type_info.ITEM_UninitializedThis: 990 return "this"; 991 992 case StackMapTable_attribute.verification_type_info.ITEM_Object: 993 return "CP"; 994 995 case StackMapTable_attribute.verification_type_info.ITEM_Uninitialized: 996 return "uninitialized"; 997 998 default: 999 report("unrecognized verification_type_info tag: " + tag); 1000 return "[tag:" + tag + "]"; 1001 } 1002 } 1003 } 1004 1005 @Override visitSynthetic(Synthetic_attribute attr, Void ignore)1006 public Void visitSynthetic(Synthetic_attribute attr, Void ignore) { 1007 println("Synthetic: true"); 1008 return null; 1009 } 1010 getJavaName(String name)1011 static String getJavaName(String name) { 1012 return name.replace('/', '.'); 1013 } 1014 toHex(byte b, int w)1015 String toHex(byte b, int w) { 1016 return toHex(b & 0xff, w); 1017 } 1018 toHex(int i)1019 static String toHex(int i) { 1020 return StringUtils.toUpperCase(Integer.toString(i, 16)); 1021 } 1022 toHex(int i, int w)1023 static String toHex(int i, int w) { 1024 String s = StringUtils.toUpperCase(Integer.toHexString(i)); 1025 while (s.length() < w) 1026 s = "0" + s; 1027 return StringUtils.toUpperCase(s); 1028 } 1029 toHex(byte[] ba)1030 static String toHex(byte[] ba) { 1031 StringBuilder sb = new StringBuilder(ba.length); 1032 for (byte b: ba) { 1033 sb.append(String.format("%02x", b & 0xff)); 1034 } 1035 return sb.toString(); 1036 } 1037 1038 private final AnnotationWriter annotationWriter; 1039 private final CodeWriter codeWriter; 1040 private final ConstantWriter constantWriter; 1041 private final Options options; 1042 1043 private ConstantPool constant_pool; 1044 private Object owner; 1045 } 1046