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