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