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