1 package com.sun.org.apache.bcel.internal.util; 2 3 56 57 import com.sun.org.apache.bcel.internal.classfile.*; 58 import java.io.*; 59 import java.util.BitSet ; 60 61 68 final class CodeHTML implements com.sun.org.apache.bcel.internal.Constants { 69 private String class_name; private Method[] methods; private PrintWriter file; private BitSet goto_set; 73 private ConstantPool constant_pool; 74 private ConstantHTML constant_html; 75 private static boolean wide=false; 76 77 CodeHTML(String dir, String class_name, 78 Method[] methods, ConstantPool constant_pool, 79 ConstantHTML constant_html) throws IOException 80 { 81 this.class_name = class_name; 82 this.methods = methods; 83 this.constant_pool = constant_pool; 84 this.constant_html = constant_html; 85 86 file = new PrintWriter(new FileOutputStream(dir + class_name + "_code.html")); 87 file.println("<HTML><BODY BGCOLOR=\"#C0C0C0\">"); 88 89 for(int i=0; i < methods.length; i++) 90 writeMethod(methods[i], i); 91 92 file.println("</BODY></HTML>"); 93 file.close(); 94 } 95 96 103 private final String codeToHTML(ByteSequence bytes, int method_number) 104 throws IOException 105 { 106 short opcode = (short)bytes.readUnsignedByte(); 107 StringBuffer buf; 108 String name, sig, signature; 109 int default_offset=0, low, high; 110 int index, class_index, vindex, constant; 111 int[] jump_table; 112 int no_pad_bytes=0, offset; 113 114 buf = new StringBuffer ("<TT>" + OPCODE_NAMES[opcode] + "</TT></TD><TD>"); 115 116 119 if((opcode == TABLESWITCH) || (opcode == LOOKUPSWITCH)) { 120 int remainder = bytes.getIndex() % 4; 121 no_pad_bytes = (remainder == 0)? 0 : 4 - remainder; 122 123 for(int i=0; i < no_pad_bytes; i++) 124 bytes.readByte(); 125 126 default_offset = bytes.readInt(); 128 } 129 130 switch(opcode) { 131 case TABLESWITCH: 132 low = bytes.readInt(); 133 high = bytes.readInt(); 134 135 offset = bytes.getIndex() - 12 - no_pad_bytes - 1; 136 default_offset += offset; 137 138 buf.append("<TABLE BORDER=1><TR>"); 139 140 jump_table = new int[high - low + 1]; 142 for(int i=0; i < jump_table.length; i++) { 143 jump_table[i] = offset + bytes.readInt(); 144 145 buf.append("<TH>" + (low + i) + "</TH>"); 146 } 147 buf.append("<TH>default</TH></TR>\n<TR>"); 148 149 for(int i=0; i < jump_table.length; i++) 151 buf.append("<TD><A HREF=\"#code" + method_number + "@" + 152 jump_table[i] + "\">" + jump_table[i] + "</A></TD>"); 153 buf.append("<TD><A HREF=\"#code" + method_number + "@" + 154 default_offset + "\">" + default_offset + "</A></TD></TR>\n</TABLE>\n"); 155 156 break; 157 158 160 case LOOKUPSWITCH: 161 int npairs = bytes.readInt(); 162 offset = bytes.getIndex() - 8 - no_pad_bytes - 1; 163 jump_table = new int[npairs]; 164 default_offset += offset; 165 166 buf.append("<TABLE BORDER=1><TR>"); 167 168 for(int i=0; i < npairs; i++) { 170 int match = bytes.readInt(); 171 172 jump_table[i] = offset + bytes.readInt(); 173 buf.append("<TH>" + match + "</TH>"); 174 } 175 buf.append("<TH>default</TH></TR>\n<TR>"); 176 177 for(int i=0; i < npairs; i++) 179 buf.append("<TD><A HREF=\"#code" + method_number + "@" + 180 jump_table[i] + "\">" + jump_table[i] + "</A></TD>"); 181 buf.append("<TD><A HREF=\"#code" + method_number + "@" + 182 default_offset + "\">" + default_offset + "</A></TD></TR>\n</TABLE>\n"); 183 break; 184 185 188 case GOTO: case IFEQ: case IFGE: case IFGT: 189 case IFLE: case IFLT: 190 case IFNE: case IFNONNULL: case IFNULL: case IF_ACMPEQ: 191 case IF_ACMPNE: case IF_ICMPEQ: case IF_ICMPGE: case IF_ICMPGT: 192 case IF_ICMPLE: case IF_ICMPLT: case IF_ICMPNE: case JSR: 193 194 index = (int)(bytes.getIndex() + bytes.readShort() - 1); 195 196 buf.append("<A HREF=\"#code" + method_number + "@" + index + "\">" + index + "</A>"); 197 break; 198 199 201 case GOTO_W: case JSR_W: 202 int windex = bytes.getIndex() + bytes.readInt() - 1; 203 buf.append("<A HREF=\"#code" + method_number + "@" + windex + "\">" + 204 windex + "</A>"); 205 break; 206 207 209 case ALOAD: case ASTORE: case DLOAD: case DSTORE: case FLOAD: 210 case FSTORE: case ILOAD: case ISTORE: case LLOAD: case LSTORE: 211 case RET: 212 if(wide) { 213 vindex = bytes.readShort(); 214 wide=false; } 216 else 217 vindex = bytes.readUnsignedByte(); 218 219 buf.append("%" + vindex); 220 break; 221 222 227 case WIDE: 228 wide = true; 229 buf.append("(wide)"); 230 break; 231 232 234 case NEWARRAY: 235 buf.append("<FONT COLOR=\"#00FF00\">" + TYPE_NAMES[bytes.readByte()] + "</FONT>"); 236 break; 237 238 240 case GETFIELD: case GETSTATIC: case PUTFIELD: case PUTSTATIC: 241 index = bytes.readShort(); 242 ConstantFieldref c1 = (ConstantFieldref)constant_pool.getConstant(index, CONSTANT_Fieldref); 243 244 class_index = c1.getClassIndex(); 245 name = constant_pool.getConstantString(class_index, CONSTANT_Class); 246 name = Utility.compactClassName(name, false); 247 248 index = c1.getNameAndTypeIndex(); 249 String field_name = constant_pool.constantToString(index, CONSTANT_NameAndType); 250 251 if(name.equals(class_name)) { buf.append("<A HREF=\"" + class_name + "_methods.html#field" + field_name + 253 "\" TARGET=Methods>" + field_name + "</A>\n"); 254 } 255 else 256 buf.append(constant_html.referenceConstant(class_index) + "." + field_name); 257 258 break; 259 260 262 case CHECKCAST: case INSTANCEOF: case NEW: 263 index = bytes.readShort(); 264 buf.append(constant_html.referenceConstant(index)); 265 break; 266 267 269 case INVOKESPECIAL: case INVOKESTATIC: case INVOKEVIRTUAL: case INVOKEINTERFACE: 270 int m_index = bytes.readShort(); 271 String str; 272 273 if(opcode == INVOKEINTERFACE) { int nargs = bytes.readUnsignedByte(); int reserved = bytes.readUnsignedByte(); 277 ConstantInterfaceMethodref c=(ConstantInterfaceMethodref)constant_pool.getConstant(m_index, CONSTANT_InterfaceMethodref); 278 279 class_index = c.getClassIndex(); 280 str = constant_pool.constantToString(c); 281 index = c.getNameAndTypeIndex(); 282 } 283 else { 284 ConstantMethodref c = (ConstantMethodref)constant_pool.getConstant(m_index, CONSTANT_Methodref); 285 class_index = c.getClassIndex(); 286 287 str = constant_pool.constantToString(c); 288 index = c.getNameAndTypeIndex(); 289 } 290 291 name = Class2HTML.referenceClass(class_index); 292 str = Class2HTML.toHTML(constant_pool.constantToString(constant_pool.getConstant(index, CONSTANT_NameAndType))); 293 294 ConstantNameAndType c2 = (ConstantNameAndType)constant_pool. 296 getConstant(index, CONSTANT_NameAndType); 297 signature = constant_pool.constantToString(c2.getSignatureIndex(), 298 CONSTANT_Utf8); 299 String [] args = Utility.methodSignatureArgumentTypes(signature, false); 300 String type = Utility.methodSignatureReturnType(signature, false); 301 302 buf.append(name + ".<A HREF=\"" + class_name + "_cp.html#cp" + m_index + 303 "\" TARGET=ConstantPool>" + str + "</A>" + "("); 304 305 for(int i=0; i < args.length; i++) { 307 buf.append(Class2HTML.referenceType(args[i])); 308 309 if(i < args.length - 1) 310 buf.append(", "); 311 } 312 buf.append("):" + Class2HTML.referenceType(type)); 314 315 break; 316 317 319 case LDC_W: case LDC2_W: 320 index = bytes.readShort(); 321 322 buf.append("<A HREF=\"" + class_name + "_cp.html#cp" + index + 323 "\" TARGET=\"ConstantPool\">" + 324 Class2HTML.toHTML(constant_pool.constantToString(index, 325 constant_pool. 326 getConstant(index).getTag()))+ 327 "</a>"); 328 break; 329 330 case LDC: 331 index = bytes.readUnsignedByte(); 332 buf.append("<A HREF=\"" + class_name + "_cp.html#cp" + index + 333 "\" TARGET=\"ConstantPool\">" + 334 Class2HTML.toHTML(constant_pool.constantToString(index, 335 constant_pool. 336 getConstant(index).getTag()))+ 337 "</a>"); 338 break; 339 340 342 case ANEWARRAY: 343 index = bytes.readShort(); 344 345 buf.append(constant_html.referenceConstant(index)); 346 break; 347 348 350 case MULTIANEWARRAY: 351 index = bytes.readShort(); 352 int dimensions = bytes.readByte(); 353 buf.append(constant_html.referenceConstant(index) + ":" + dimensions + "-dimensional"); 354 break; 355 356 358 case IINC: 359 if(wide) { 360 vindex = bytes.readShort(); 361 constant = bytes.readShort(); 362 wide = false; 363 } 364 else { 365 vindex = bytes.readUnsignedByte(); 366 constant = bytes.readByte(); 367 } 368 buf.append("%" + vindex + " " + constant); 369 break; 370 371 default: 372 if(NO_OF_OPERANDS[opcode] > 0) { 373 for(int i=0; i < TYPE_OF_OPERANDS[opcode].length; i++) { 374 switch(TYPE_OF_OPERANDS[opcode][i]) { 375 case T_BYTE: 376 buf.append(bytes.readUnsignedByte()); 377 break; 378 379 case T_SHORT: buf.append(bytes.readShort()); 381 break; 382 383 case T_INT: 384 buf.append(bytes.readInt()); 385 break; 386 387 default: System.err.println("Unreachable default case reached!"); 389 System.exit(-1); 390 } 391 buf.append(" "); 392 } 393 } 394 } 395 396 buf.append("</TD>"); 397 return buf.toString(); 398 } 399 400 404 private final void findGotos(ByteSequence bytes, Method method, Code code) 405 throws IOException 406 { 407 int index; 408 goto_set = new BitSet (bytes.available()); 409 int opcode; 410 411 414 415 if(code != null) { 416 CodeException[] ce = code.getExceptionTable(); 417 int len = ce.length; 418 419 for(int i=0; i < len; i++) { 420 goto_set.set(ce[i].getStartPC()); 421 goto_set.set(ce[i].getEndPC()); 422 goto_set.set(ce[i].getHandlerPC()); 423 } 424 425 Attribute[] attributes = code.getAttributes(); 427 for(int i=0; i < attributes.length; i++) { 428 if(attributes[i].getTag() == ATTR_LOCAL_VARIABLE_TABLE) { 429 LocalVariable[] vars = ((LocalVariableTable)attributes[i]).getLocalVariableTable(); 430 431 for(int j=0; j < vars.length; j++) { 432 int start = vars[j].getStartPC(); 433 int end = (int)(start + vars[j].getLength()); 434 goto_set.set(start); 435 goto_set.set(end); 436 } 437 break; 438 } 439 } 440 } 441 442 for(int i=0; bytes.available() > 0; i++) { 444 opcode = bytes.readUnsignedByte(); 445 switch(opcode) { 447 case TABLESWITCH: case LOOKUPSWITCH: 448 450 int remainder = bytes.getIndex() % 4; 451 int no_pad_bytes = (remainder == 0)? 0 : 4 - remainder; 452 int default_offset, offset; 453 454 for(int j=0; j < no_pad_bytes; j++) 455 bytes.readByte(); 456 457 default_offset = bytes.readInt(); 459 460 if(opcode == TABLESWITCH) { 461 int low = bytes.readInt(); 462 int high = bytes.readInt(); 463 464 offset = bytes.getIndex() - 12 - no_pad_bytes - 1; 465 default_offset += offset; 466 goto_set.set(default_offset); 467 468 for(int j=0; j < (high - low + 1); j++) { 469 index = offset + bytes.readInt(); 470 goto_set.set(index); 471 } 472 } 473 else { int npairs = bytes.readInt(); 475 476 offset = bytes.getIndex() - 8 - no_pad_bytes - 1; 477 default_offset += offset; 478 goto_set.set(default_offset); 479 480 for(int j=0; j < npairs; j++) { 481 int match = bytes.readInt(); 482 483 index = offset + bytes.readInt(); 484 goto_set.set(index); 485 } 486 } 487 break; 488 489 case GOTO: case IFEQ: case IFGE: case IFGT: 490 case IFLE: case IFLT: 491 case IFNE: case IFNONNULL: case IFNULL: case IF_ACMPEQ: 492 case IF_ACMPNE: case IF_ICMPEQ: case IF_ICMPGE: case IF_ICMPGT: 493 case IF_ICMPLE: case IF_ICMPLT: case IF_ICMPNE: case JSR: 494 index = bytes.getIndex() + bytes.readShort() - 1; 496 497 goto_set.set(index); 498 break; 499 500 case GOTO_W: case JSR_W: 501 index = bytes.getIndex() + bytes.readInt() - 1; 503 goto_set.set(index); 504 break; 505 506 default: 507 bytes.unreadByte(); 508 codeToHTML(bytes, 0); } 510 } 511 } 512 513 516 private void writeMethod(Method method, int method_number) 517 throws IOException 518 { 519 String signature = method.getSignature(); 521 String [] args = Utility.methodSignatureArgumentTypes(signature, false); 523 String type = Utility.methodSignatureReturnType(signature, false); 525 String name = method.getName(); 527 String html_name = Class2HTML.toHTML(name); 528 String access = Utility.accessToString(method.getAccessFlags()); 530 access = Utility.replace(access, " ", " "); 531 Attribute[] attributes= method.getAttributes(); 533 534 file.print("<P><B><FONT COLOR=\"#FF0000\">" + access + "</FONT> " + 535 "<A NAME=method" + method_number + ">" + Class2HTML.referenceType(type) + 536 "</A> <A HREF=\"" + class_name + "_methods.html#method" + method_number + 537 "\" TARGET=Methods>" + html_name + "</A>("); 538 539 for(int i=0; i < args.length; i++) { 540 file.print(Class2HTML.referenceType(args[i])); 541 if(i < args.length - 1) 542 file.print(", "); 543 } 544 545 file.println(")</B></P>"); 546 547 Code c=null; 548 byte[] code=null; 549 550 if(attributes.length > 0) { 551 file.print("<H4>Attributes</H4><UL>\n"); 552 for(int i=0; i < attributes.length; i++) { 553 byte tag = attributes[i].getTag(); 554 555 if(tag != ATTR_UNKNOWN) 556 file.print("<LI><A HREF=\"" + class_name + "_attributes.html#method" + method_number + "@" + i + 557 "\" TARGET=Attributes>" + ATTRIBUTE_NAMES[tag] + "</A></LI>\n"); 558 else 559 file.print("<LI>" + attributes[i] + "</LI>"); 560 561 if(tag == ATTR_CODE) { 562 c = (Code)attributes[i]; 563 Attribute[] attributes2 = c.getAttributes(); 564 code = c.getCode(); 565 566 file.print("<UL>"); 567 for(int j=0; j < attributes2.length; j++) { 568 tag = attributes2[j].getTag(); 569 file.print("<LI><A HREF=\"" + class_name + "_attributes.html#" + 570 "method" + method_number + "@" + i + "@" + j + "\" TARGET=Attributes>" + 571 ATTRIBUTE_NAMES[tag] + "</A></LI>\n"); 572 573 } 574 file.print("</UL>"); 575 } 576 } 577 file.println("</UL>"); 578 } 579 580 if(code != null) { 583 ByteSequence stream = new ByteSequence(code); 585 stream.mark(stream.available()); 586 findGotos(stream, method, c); 587 stream.reset(); 588 589 file.println("<TABLE BORDER=0><TR><TH ALIGN=LEFT>Byte<BR>offset</TH>" + 590 "<TH ALIGN=LEFT>Instruction</TH><TH ALIGN=LEFT>Argument</TH>"); 591 592 for(int i=0; stream.available() > 0; i++) { 593 int offset = stream.getIndex(); 594 String str = codeToHTML(stream, method_number); 595 String anchor = ""; 596 597 600 if(goto_set.get(offset)) 601 anchor = "<A NAME=code" + method_number + "@" + offset + "></A>"; 602 603 String anchor2; 604 if(stream.getIndex() == code.length) anchor2 = "<A NAME=code" + method_number + "@" + code.length + ">" + offset + "</A>"; 606 else 607 anchor2 = "" + offset; 608 609 file.println("<TR VALIGN=TOP><TD>" + anchor2 + "</TD><TD>" + anchor + str + "</TR>"); 610 } 611 612 file.println("<TR><TD> </A></TD></TR>"); 614 file.println("</TABLE>"); 615 } 616 617 } 618 } 619 | Popular Tags |