1 /* 2 * Copyright (c) 2001, 2010, 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.java.util.jar.pack; 27 28 import com.sun.java.util.jar.pack.ConstantPool.ClassEntry; 29 import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry; 30 import com.sun.java.util.jar.pack.ConstantPool.Entry; 31 import com.sun.java.util.jar.pack.ConstantPool.Index; 32 import com.sun.java.util.jar.pack.ConstantPool.MemberEntry; 33 import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry; 34 import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry; 35 import com.sun.java.util.jar.pack.Package.Class; 36 import com.sun.java.util.jar.pack.Package.File; 37 import com.sun.java.util.jar.pack.Package.InnerClass; 38 import java.io.ByteArrayOutputStream; 39 import java.io.EOFException; 40 import java.io.PrintStream; 41 import java.io.FilterInputStream; 42 import java.io.BufferedInputStream; 43 import java.io.InputStream; 44 import java.io.IOException; 45 import java.util.ArrayList; 46 import java.util.Map; 47 import java.util.Arrays; 48 import java.util.Collection; 49 import java.util.Comparator; 50 import java.util.HashSet; 51 import java.util.HashMap; 52 import java.util.Iterator; 53 import java.util.List; 54 import java.util.ListIterator; 55 import java.util.Set; 56 import static com.sun.java.util.jar.pack.Constants.*; 57 58 /** 59 * Reader for a package file. 60 * 61 * @see PackageWriter 62 * @author John Rose 63 */ 64 class PackageReader extends BandStructure { 65 Package pkg; 66 byte[] bytes; 67 LimitedBuffer in; 68 69 PackageReader(Package pkg, InputStream in) throws IOException { 70 this.pkg = pkg; 71 this.in = new LimitedBuffer(in); 72 } 73 74 /** A buffered input stream which is careful not to 75 * read its underlying stream ahead of a given mark, 76 * called the 'readLimit'. This property declares 77 * the maximum number of characters that future reads 78 * can consume from the underlying stream. 79 */ 80 static 81 class LimitedBuffer extends BufferedInputStream { 82 long served; // total number of charburgers served 83 int servedPos; // ...as of this value of super.pos 84 long limit; // current declared limit 85 long buffered; 86 public boolean atLimit() { 87 boolean z = (getBytesServed() == limit); 88 assert(!z || limit == buffered); 89 return z; 90 } 91 public long getBytesServed() { 92 return served + (pos - servedPos); 93 } 94 public void setReadLimit(long newLimit) { 95 if (newLimit == -1) 96 limit = -1; 97 else 98 limit = getBytesServed() + newLimit; 99 } 100 public long getReadLimit() { 101 if (limit == -1) 102 return limit; 103 else 104 return limit - getBytesServed(); 105 } 106 public int read() throws IOException { 107 if (pos < count) { 108 // fast path 109 return buf[pos++] & 0xFF; 110 } 111 served += (pos - servedPos); 112 int ch = super.read(); 113 servedPos = pos; 114 if (ch >= 0) served += 1; 115 assert(served <= limit || limit == -1); 116 return ch; 117 } 118 public int read(byte b[], int off, int len) throws IOException { 119 served += (pos - servedPos); 120 int nr = super.read(b, off, len); 121 servedPos = pos; 122 if (nr >= 0) served += nr; 123 assert(served <= limit || limit == -1); 124 return nr; 125 } 126 public long skip(long n) throws IOException { 127 throw new RuntimeException("no skipping"); 128 } 129 LimitedBuffer(InputStream originalIn) { 130 super(null, 1<<14); 131 servedPos = pos; 132 super.in = new FilterInputStream(originalIn) { 133 public int read() throws IOException { 134 if (buffered == limit) 135 return -1; 136 ++buffered; 137 return super.read(); 138 } 139 public int read(byte b[], int off, int len) throws IOException { 140 if (buffered == limit) 141 return -1; 142 if (limit != -1) { 143 long remaining = limit - buffered; 144 if (len > remaining) 145 len = (int)remaining; 146 } 147 int nr = super.read(b, off, len); 148 if (nr >= 0) buffered += nr; 149 return nr; 150 } 151 }; 152 } 153 } 154 155 void read() throws IOException { 156 boolean ok = false; 157 try { 158 // pack200_archive: 159 // file_header 160 // *band_headers :BYTE1 161 // cp_bands 162 // attr_definition_bands 163 // ic_bands 164 // class_bands 165 // bc_bands 166 // file_bands 167 readFileHeader(); 168 readBandHeaders(); 169 readConstantPool(); // cp_bands 170 readAttrDefs(); 171 readInnerClasses(); 172 Class[] classes = readClasses(); 173 readByteCodes(); 174 readFiles(); // file_bands 175 assert(archiveSize1 == 0 || in.atLimit()); 176 assert(archiveSize1 == 0 || 177 in.getBytesServed() == archiveSize0+archiveSize1); 178 all_bands.doneDisbursing(); 179 180 // As a post-pass, build constant pools and inner classes. 181 for (int i = 0; i < classes.length; i++) { 182 reconstructClass(classes[i]); 183 } 184 185 ok = true; 186 } catch (Exception ee) { 187 Utils.log.warning("Error on input: "+ee, ee); 188 if (verbose > 0) 189 Utils.log.info("Stream offsets:"+ 190 " served="+in.getBytesServed()+ 191 " buffered="+in.buffered+ 192 " limit="+in.limit); 193 //if (verbose > 0) ee.printStackTrace(); 194 if (ee instanceof IOException) throw (IOException)ee; 195 if (ee instanceof RuntimeException) throw (RuntimeException)ee; 196 throw new Error("error unpacking", ee); 197 } 198 } 199 200 // Temporary count values, until band decoding gets rolling. 201 int[] tagCount = new int[CONSTANT_Limit]; 202 int numFiles; 203 int numAttrDefs; 204 int numInnerClasses; 205 int numClasses; 206 207 void readFileHeader() throws IOException { 208 // file_header: 209 // archive_magic archive_header 210 readArchiveMagic(); 211 readArchiveHeader(); 212 } 213 214 // Local routine used to parse fixed-format scalars 215 // in the file_header: 216 private int getMagicInt32() throws IOException { 217 int res = 0; 218 for (int i = 0; i < 4; i++) { 219 res <<= 8; 220 res |= (archive_magic.getByte() & 0xFF); 221 } 222 return res; 223 } 224 225 final static int MAGIC_BYTES = 4; 226 227 void readArchiveMagic() throws IOException { 228 229 // Read a minimum of bytes in the first gulp. 230 in.setReadLimit(MAGIC_BYTES + AH_LENGTH_MIN); 231 232 // archive_magic: 233 // #archive_magic_word :BYTE1[4] 234 archive_magic.expectLength(MAGIC_BYTES); 235 archive_magic.readFrom(in); 236 237 // read and check magic numbers: 238 pkg.magic = getMagicInt32(); 239 archive_magic.doneDisbursing(); 240 } 241 242 void readArchiveHeader() throws IOException { 243 // archive_header: 244 // #archive_minver :UNSIGNED5[1] 245 // #archive_majver :UNSIGNED5[1] 246 // #archive_options :UNSIGNED5[1] 247 // (archive_file_counts) ** (#have_file_headers) 248 // (archive_special_counts) ** (#have_special_formats) 249 // cp_counts 250 // class_counts 251 // 252 // archive_file_counts: 253 // #archive_size_hi :UNSIGNED5[1] 254 // #archive_size_lo :UNSIGNED5[1] 255 // #archive_next_count :UNSIGNED5[1] 256 // #archive_modtime :UNSIGNED5[1] 257 // #file_count :UNSIGNED5[1] 258 // 259 // class_counts: 260 // #ic_count :UNSIGNED5[1] 261 // #default_class_minver :UNSIGNED5[1] 262 // #default_class_majver :UNSIGNED5[1] 263 // #class_count :UNSIGNED5[1] 264 // 265 // archive_special_counts: 266 // #band_headers_size :UNSIGNED5[1] 267 // #attr_definition_count :UNSIGNED5[1] 268 // 269 assert(AH_LENGTH == 8+(ConstantPool.TAGS_IN_ORDER.length)+6); 270 archive_header_0.expectLength(AH_LENGTH_0); 271 archive_header_0.readFrom(in); 272 273 pkg.package_minver = archive_header_0.getInt(); 274 pkg.package_majver = archive_header_0.getInt(); 275 pkg.checkVersion(); 276 this.initPackageMajver(pkg.package_majver); 277 278 archiveOptions = archive_header_0.getInt(); 279 archive_header_0.doneDisbursing(); 280 281 // detect archive optional fields in archive header 282 boolean haveSpecial = testBit(archiveOptions, AO_HAVE_SPECIAL_FORMATS); 283 boolean haveFiles = testBit(archiveOptions, AO_HAVE_FILE_HEADERS); 284 boolean haveNumbers = testBit(archiveOptions, AO_HAVE_CP_NUMBERS); 285 initAttrIndexLimit(); 286 287 // now we are ready to use the data: 288 archive_header_S.expectLength(haveFiles? AH_LENGTH_S: 0); 289 archive_header_S.readFrom(in); 290 if (haveFiles) { 291 long sizeHi = archive_header_S.getInt(); 292 long sizeLo = archive_header_S.getInt(); 293 archiveSize1 = (sizeHi << 32) + ((sizeLo << 32) >>> 32); 294 // Set the limit, now, up to the file_bits. 295 in.setReadLimit(archiveSize1); // for debug only 296 } else { 297 archiveSize1 = 0; 298 in.setReadLimit(-1); // remove limitation 299 } 300 archive_header_S.doneDisbursing(); 301 archiveSize0 = in.getBytesServed(); 302 303 int remainingHeaders = AH_LENGTH - AH_LENGTH_0 - AH_LENGTH_S; 304 if (!haveFiles) remainingHeaders -= AH_FILE_HEADER_LEN-AH_LENGTH_S; 305 if (!haveSpecial) remainingHeaders -= AH_SPECIAL_FORMAT_LEN; 306 if (!haveNumbers) remainingHeaders -= AH_CP_NUMBER_LEN; 307 assert(remainingHeaders >= AH_LENGTH_MIN - AH_LENGTH_0); 308 archive_header_1.expectLength(remainingHeaders); 309 archive_header_1.readFrom(in); 310 311 if (haveFiles) { 312 archiveNextCount = archive_header_1.getInt(); 313 pkg.default_modtime = archive_header_1.getInt(); 314 numFiles = archive_header_1.getInt(); 315 } else { 316 archiveNextCount = 0; 317 numFiles = 0; 318 } 319 320 if (haveSpecial) { 321 band_headers.expectLength(archive_header_1.getInt()); 322 numAttrDefs = archive_header_1.getInt(); 323 } else { 324 band_headers.expectLength(0); 325 numAttrDefs = 0; 326 } 327 328 readConstantPoolCounts(haveNumbers); 329 330 numInnerClasses = archive_header_1.getInt(); 331 332 pkg.default_class_minver = (short) archive_header_1.getInt(); 333 pkg.default_class_majver = (short) archive_header_1.getInt(); 334 numClasses = archive_header_1.getInt(); 335 336 archive_header_1.doneDisbursing(); 337 338 // set some derived archive bits 339 if (testBit(archiveOptions, AO_DEFLATE_HINT)) { 340 pkg.default_options |= FO_DEFLATE_HINT; 341 } 342 } 343 344 void readBandHeaders() throws IOException { 345 band_headers.readFrom(in); 346 bandHeaderBytePos = 1; // Leave room to pushback the initial XB byte. 347 bandHeaderBytes = new byte[bandHeaderBytePos + band_headers.length()]; 348 for (int i = bandHeaderBytePos; i < bandHeaderBytes.length; i++) { 349 bandHeaderBytes[i] = (byte) band_headers.getByte(); 350 } 351 band_headers.doneDisbursing(); 352 } 353 354 void readConstantPoolCounts(boolean haveNumbers) throws IOException { 355 // size the constant pools: 356 for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) { 357 // cp_counts: 358 // #cp_Utf8_count :UNSIGNED5[1] 359 // (cp_number_counts) ** (#have_cp_numbers) 360 // #cp_String_count :UNSIGNED5[1] 361 // #cp_Class_count :UNSIGNED5[1] 362 // #cp_Signature_count :UNSIGNED5[1] 363 // #cp_Descr_count :UNSIGNED5[1] 364 // #cp_Field_count :UNSIGNED5[1] 365 // #cp_Method_count :UNSIGNED5[1] 366 // #cp_Imethod_count :UNSIGNED5[1] 367 // 368 // cp_number_counts: 369 // #cp_Int_count :UNSIGNED5[1] 370 // #cp_Float_count :UNSIGNED5[1] 371 // #cp_Long_count :UNSIGNED5[1] 372 // #cp_Double_count :UNSIGNED5[1] 373 // 374 byte tag = ConstantPool.TAGS_IN_ORDER[k]; 375 if (!haveNumbers) { 376 // These four counts are optional. 377 switch (tag) { 378 case CONSTANT_Integer: 379 case CONSTANT_Float: 380 case CONSTANT_Long: 381 case CONSTANT_Double: 382 continue; 383 } 384 } 385 tagCount[tag] = archive_header_1.getInt(); 386 } 387 } 388 389 protected Index getCPIndex(byte tag) { 390 return pkg.cp.getIndexByTag(tag); 391 } 392 Index initCPIndex(byte tag, Entry[] cpMap) { 393 if (verbose > 3) { 394 for (int i = 0; i < cpMap.length; i++) { 395 Utils.log.fine("cp.add "+cpMap[i]); 396 } 397 } 398 Index index = ConstantPool.makeIndex(ConstantPool.tagName(tag), cpMap); 399 if (verbose > 1) Utils.log.fine("Read "+index); 400 pkg.cp.initIndexByTag(tag, index); 401 return index; 402 } 403 404 void readConstantPool() throws IOException { 405 // cp_bands: 406 // cp_Utf8 407 // *cp_Int :UDELTA5 408 // *cp_Float :UDELTA5 409 // cp_Long 410 // cp_Double 411 // *cp_String :UDELTA5 (cp_Utf8) 412 // *cp_Class :UDELTA5 (cp_Utf8) 413 // cp_Signature 414 // cp_Descr 415 // cp_Field 416 // cp_Method 417 // cp_Imethod 418 419 if (verbose > 0) Utils.log.info("Reading CP"); 420 421 for (int k = 0; k < ConstantPool.TAGS_IN_ORDER.length; k++) { 422 byte tag = ConstantPool.TAGS_IN_ORDER[k]; 423 int len = tagCount[tag]; 424 425 Entry[] cpMap = new Entry[len]; 426 if (verbose > 0) 427 Utils.log.info("Reading "+cpMap.length+" "+ConstantPool.tagName(tag)+" entries..."); 428 429 switch (tag) { 430 case CONSTANT_Utf8: 431 readUtf8Bands(cpMap); 432 break; 433 case CONSTANT_Integer: 434 cp_Int.expectLength(cpMap.length); 435 cp_Int.readFrom(in); 436 for (int i = 0; i < cpMap.length; i++) { 437 int x = cp_Int.getInt(); // coding handles signs OK 438 cpMap[i] = ConstantPool.getLiteralEntry(x); 439 } 440 cp_Int.doneDisbursing(); 441 break; 442 case CONSTANT_Float: 443 cp_Float.expectLength(cpMap.length); 444 cp_Float.readFrom(in); 445 for (int i = 0; i < cpMap.length; i++) { 446 int x = cp_Float.getInt(); 447 float fx = Float.intBitsToFloat(x); 448 cpMap[i] = ConstantPool.getLiteralEntry(fx); 449 } 450 cp_Float.doneDisbursing(); 451 break; 452 case CONSTANT_Long: 453 // cp_Long: 454 // *cp_Long_hi :UDELTA5 455 // *cp_Long_lo :DELTA5 456 cp_Long_hi.expectLength(cpMap.length); 457 cp_Long_hi.readFrom(in); 458 cp_Long_lo.expectLength(cpMap.length); 459 cp_Long_lo.readFrom(in); 460 for (int i = 0; i < cpMap.length; i++) { 461 long hi = cp_Long_hi.getInt(); 462 long lo = cp_Long_lo.getInt(); 463 long x = (hi << 32) + ((lo << 32) >>> 32); 464 cpMap[i] = ConstantPool.getLiteralEntry(x); 465 } 466 cp_Long_hi.doneDisbursing(); 467 cp_Long_lo.doneDisbursing(); 468 break; 469 case CONSTANT_Double: 470 // cp_Double: 471 // *cp_Double_hi :UDELTA5 472 // *cp_Double_lo :DELTA5 473 cp_Double_hi.expectLength(cpMap.length); 474 cp_Double_hi.readFrom(in); 475 cp_Double_lo.expectLength(cpMap.length); 476 cp_Double_lo.readFrom(in); 477 for (int i = 0; i < cpMap.length; i++) { 478 long hi = cp_Double_hi.getInt(); 479 long lo = cp_Double_lo.getInt(); 480 long x = (hi << 32) + ((lo << 32) >>> 32); 481 double dx = Double.longBitsToDouble(x); 482 cpMap[i] = ConstantPool.getLiteralEntry(dx); 483 } 484 cp_Double_hi.doneDisbursing(); 485 cp_Double_lo.doneDisbursing(); 486 break; 487 case CONSTANT_String: 488 cp_String.expectLength(cpMap.length); 489 cp_String.readFrom(in); 490 cp_String.setIndex(getCPIndex(CONSTANT_Utf8)); 491 for (int i = 0; i < cpMap.length; i++) { 492 cpMap[i] = ConstantPool.getLiteralEntry(cp_String.getRef().stringValue()); 493 } 494 cp_String.doneDisbursing(); 495 break; 496 case CONSTANT_Class: 497 cp_Class.expectLength(cpMap.length); 498 cp_Class.readFrom(in); 499 cp_Class.setIndex(getCPIndex(CONSTANT_Utf8)); 500 for (int i = 0; i < cpMap.length; i++) { 501 cpMap[i] = ConstantPool.getClassEntry(cp_Class.getRef().stringValue()); 502 } 503 cp_Class.doneDisbursing(); 504 break; 505 case CONSTANT_Signature: 506 readSignatureBands(cpMap); 507 break; 508 case CONSTANT_NameandType: 509 // cp_Descr: 510 // *cp_Descr_type :DELTA5 (cp_Signature) 511 // *cp_Descr_name :UDELTA5 (cp_Utf8) 512 cp_Descr_name.expectLength(cpMap.length); 513 cp_Descr_name.readFrom(in); 514 cp_Descr_name.setIndex(getCPIndex(CONSTANT_Utf8)); 515 cp_Descr_type.expectLength(cpMap.length); 516 cp_Descr_type.readFrom(in); 517 cp_Descr_type.setIndex(getCPIndex(CONSTANT_Signature)); 518 for (int i = 0; i < cpMap.length; i++) { 519 Entry ref = cp_Descr_name.getRef(); 520 Entry ref2 = cp_Descr_type.getRef(); 521 cpMap[i] = ConstantPool.getDescriptorEntry((Utf8Entry)ref, 522 (SignatureEntry)ref2); 523 } 524 cp_Descr_name.doneDisbursing(); 525 cp_Descr_type.doneDisbursing(); 526 break; 527 case CONSTANT_Fieldref: 528 readMemberRefs(tag, cpMap, cp_Field_class, cp_Field_desc); 529 break; 530 case CONSTANT_Methodref: 531 readMemberRefs(tag, cpMap, cp_Method_class, cp_Method_desc); 532 break; 533 case CONSTANT_InterfaceMethodref: 534 readMemberRefs(tag, cpMap, cp_Imethod_class, cp_Imethod_desc); 535 break; 536 default: 537 assert(false); 538 } 539 540 Index index = initCPIndex(tag, cpMap); 541 542 if (optDumpBands) { 543 try (PrintStream ps = new PrintStream(getDumpStream(index, ".idx"))) { 544 printArrayTo(ps, index.cpMap, 0, index.cpMap.length); 545 } 546 } 547 } 548 549 cp_bands.doneDisbursing(); 550 551 setBandIndexes(); 552 } 553 554 void readUtf8Bands(Entry[] cpMap) throws IOException { 555 // cp_Utf8: 556 // *cp_Utf8_prefix :DELTA5 557 // *cp_Utf8_suffix :UNSIGNED5 558 // *cp_Utf8_chars :CHAR3 559 // *cp_Utf8_big_suffix :DELTA5 560 // (*cp_Utf8_big_chars :DELTA5) 561 // ** length(cp_Utf8_big_suffix) 562 int len = cpMap.length; 563 if (len == 0) 564 return; // nothing to read 565 566 // Bands have implicit leading zeroes, for the empty string: 567 final int SUFFIX_SKIP_1 = 1; 568 final int PREFIX_SKIP_2 = 2; 569 570 // First band: Read lengths of shared prefixes. 571 cp_Utf8_prefix.expectLength(Math.max(0, len - PREFIX_SKIP_2)); 572 cp_Utf8_prefix.readFrom(in); 573 574 // Second band: Read lengths of unshared suffixes: 575 cp_Utf8_suffix.expectLength(Math.max(0, len - SUFFIX_SKIP_1)); 576 cp_Utf8_suffix.readFrom(in); 577 578 char[][] suffixChars = new char[len][]; 579 int bigSuffixCount = 0; 580 581 // Third band: Read the char values in the unshared suffixes: 582 cp_Utf8_chars.expectLength(cp_Utf8_suffix.getIntTotal()); 583 cp_Utf8_chars.readFrom(in); 584 for (int i = 0; i < len; i++) { 585 int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt(); 586 if (suffix == 0 && i >= SUFFIX_SKIP_1) { 587 // chars are packed in cp_Utf8_big_chars 588 bigSuffixCount += 1; 589 continue; 590 } 591 suffixChars[i] = new char[suffix]; 592 for (int j = 0; j < suffix; j++) { 593 int ch = cp_Utf8_chars.getInt(); 594 assert(ch == (char)ch); 595 suffixChars[i][j] = (char)ch; 596 } 597 } 598 cp_Utf8_chars.doneDisbursing(); 599 600 // Fourth band: Go back and size the specially packed strings. 601 int maxChars = 0; 602 cp_Utf8_big_suffix.expectLength(bigSuffixCount); 603 cp_Utf8_big_suffix.readFrom(in); 604 cp_Utf8_suffix.resetForSecondPass(); 605 for (int i = 0; i < len; i++) { 606 int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt(); 607 int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt(); 608 if (suffix == 0 && i >= SUFFIX_SKIP_1) { 609 assert(suffixChars[i] == null); 610 suffix = cp_Utf8_big_suffix.getInt(); 611 } else { 612 assert(suffixChars[i] != null); 613 } 614 if (maxChars < prefix + suffix) 615 maxChars = prefix + suffix; 616 } 617 char[] buf = new char[maxChars]; 618 619 // Fifth band(s): Get the specially packed characters. 620 cp_Utf8_suffix.resetForSecondPass(); 621 cp_Utf8_big_suffix.resetForSecondPass(); 622 for (int i = 0; i < len; i++) { 623 if (i < SUFFIX_SKIP_1) continue; 624 int suffix = cp_Utf8_suffix.getInt(); 625 if (suffix != 0) continue; // already input 626 suffix = cp_Utf8_big_suffix.getInt(); 627 suffixChars[i] = new char[suffix]; 628 if (suffix == 0) { 629 // Do not bother to add an empty "(Utf8_big_0)" band. 630 continue; 631 } 632 IntBand packed = cp_Utf8_big_chars.newIntBand("(Utf8_big_"+i+")"); 633 packed.expectLength(suffix); 634 packed.readFrom(in); 635 for (int j = 0; j < suffix; j++) { 636 int ch = packed.getInt(); 637 assert(ch == (char)ch); 638 suffixChars[i][j] = (char)ch; 639 } 640 packed.doneDisbursing(); 641 } 642 cp_Utf8_big_chars.doneDisbursing(); 643 644 // Finally, sew together all the prefixes and suffixes. 645 cp_Utf8_prefix.resetForSecondPass(); 646 cp_Utf8_suffix.resetForSecondPass(); 647 cp_Utf8_big_suffix.resetForSecondPass(); 648 for (int i = 0; i < len; i++) { 649 int prefix = (i < PREFIX_SKIP_2)? 0: cp_Utf8_prefix.getInt(); 650 int suffix = (i < SUFFIX_SKIP_1)? 0: cp_Utf8_suffix.getInt(); 651 if (suffix == 0 && i >= SUFFIX_SKIP_1) 652 suffix = cp_Utf8_big_suffix.getInt(); 653 654 // by induction, the buffer is already filled with the prefix 655 System.arraycopy(suffixChars[i], 0, buf, prefix, suffix); 656 657 cpMap[i] = ConstantPool.getUtf8Entry(new String(buf, 0, prefix+suffix)); 658 } 659 660 cp_Utf8_prefix.doneDisbursing(); 661 cp_Utf8_suffix.doneDisbursing(); 662 cp_Utf8_big_suffix.doneDisbursing(); 663 } 664 665 Map<Utf8Entry, SignatureEntry> utf8Signatures; 666 667 void readSignatureBands(Entry[] cpMap) throws IOException { 668 // cp_Signature: 669 // *cp_Signature_form :DELTA5 (cp_Utf8) 670 // *cp_Signature_classes :UDELTA5 (cp_Class) 671 cp_Signature_form.expectLength(cpMap.length); 672 cp_Signature_form.readFrom(in); 673 cp_Signature_form.setIndex(getCPIndex(CONSTANT_Utf8)); 674 int[] numSigClasses = new int[cpMap.length]; 675 for (int i = 0; i < cpMap.length; i++) { 676 Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef(); 677 numSigClasses[i] = ConstantPool.countClassParts(formRef); 678 } 679 cp_Signature_form.resetForSecondPass(); 680 cp_Signature_classes.expectLength(getIntTotal(numSigClasses)); 681 cp_Signature_classes.readFrom(in); 682 cp_Signature_classes.setIndex(getCPIndex(CONSTANT_Class)); 683 utf8Signatures = new HashMap<>(); 684 for (int i = 0; i < cpMap.length; i++) { 685 Utf8Entry formRef = (Utf8Entry) cp_Signature_form.getRef(); 686 ClassEntry[] classRefs = new ClassEntry[numSigClasses[i]]; 687 for (int j = 0; j < classRefs.length; j++) { 688 classRefs[j] = (ClassEntry) cp_Signature_classes.getRef(); 689 } 690 SignatureEntry se = ConstantPool.getSignatureEntry(formRef, classRefs); 691 cpMap[i] = se; 692 utf8Signatures.put(se.asUtf8Entry(), se); 693 } 694 cp_Signature_form.doneDisbursing(); 695 cp_Signature_classes.doneDisbursing(); 696 } 697 698 void readMemberRefs(byte tag, Entry[] cpMap, CPRefBand cp_class, CPRefBand cp_desc) throws IOException { 699 // cp_Field: 700 // *cp_Field_class :DELTA5 (cp_Class) 701 // *cp_Field_desc :UDELTA5 (cp_Descr) 702 // cp_Method: 703 // *cp_Method_class :DELTA5 (cp_Class) 704 // *cp_Method_desc :UDELTA5 (cp_Descr) 705 // cp_Imethod: 706 // *cp_Imethod_class :DELTA5 (cp_Class) 707 // *cp_Imethod_desc :UDELTA5 (cp_Descr) 708 cp_class.expectLength(cpMap.length); 709 cp_class.readFrom(in); 710 cp_class.setIndex(getCPIndex(CONSTANT_Class)); 711 cp_desc.expectLength(cpMap.length); 712 cp_desc.readFrom(in); 713 cp_desc.setIndex(getCPIndex(CONSTANT_NameandType)); 714 for (int i = 0; i < cpMap.length; i++) { 715 ClassEntry mclass = (ClassEntry ) cp_class.getRef(); 716 DescriptorEntry mdescr = (DescriptorEntry) cp_desc.getRef(); 717 cpMap[i] = ConstantPool.getMemberEntry(tag, mclass, mdescr); 718 } 719 cp_class.doneDisbursing(); 720 cp_desc.doneDisbursing(); 721 } 722 723 void readFiles() throws IOException { 724 // file_bands: 725 // *file_name :UNSIGNED5 (cp_Utf8) 726 // *file_size_hi :UNSIGNED5 727 // *file_size_lo :UNSIGNED5 728 // *file_modtime :DELTA5 729 // *file_options :UNSIGNED5 730 // *file_bits :BYTE1 731 if (verbose > 0) 732 Utils.log.info(" ...building "+numFiles+" files..."); 733 file_name.expectLength(numFiles); 734 file_size_lo.expectLength(numFiles); 735 int options = archiveOptions; 736 boolean haveSizeHi = testBit(options, AO_HAVE_FILE_SIZE_HI); 737 boolean haveModtime = testBit(options, AO_HAVE_FILE_MODTIME); 738 boolean haveOptions = testBit(options, AO_HAVE_FILE_OPTIONS); 739 if (haveSizeHi) 740 file_size_hi.expectLength(numFiles); 741 if (haveModtime) 742 file_modtime.expectLength(numFiles); 743 if (haveOptions) 744 file_options.expectLength(numFiles); 745 746 file_name.readFrom(in); 747 file_size_hi.readFrom(in); 748 file_size_lo.readFrom(in); 749 file_modtime.readFrom(in); 750 file_options.readFrom(in); 751 file_bits.setInputStreamFrom(in); 752 753 Iterator nextClass = pkg.getClasses().iterator(); 754 755 // Compute file lengths before reading any file bits. 756 long totalFileLength = 0; 757 long[] fileLengths = new long[numFiles]; 758 for (int i = 0; i < numFiles; i++) { 759 long size = ((long)file_size_lo.getInt() << 32) >>> 32; 760 if (haveSizeHi) 761 size += (long)file_size_hi.getInt() << 32; 762 fileLengths[i] = size; 763 totalFileLength += size; 764 } 765 assert(in.getReadLimit() == -1 || in.getReadLimit() == totalFileLength); 766 767 byte[] buf = new byte[1<<16]; 768 for (int i = 0; i < numFiles; i++) { 769 // %%% Use a big temp file for file bits? 770 Utf8Entry name = (Utf8Entry) file_name.getRef(); 771 long size = fileLengths[i]; 772 File file = pkg.new File(name); 773 file.modtime = pkg.default_modtime; 774 file.options = pkg.default_options; 775 if (haveModtime) 776 file.modtime += file_modtime.getInt(); 777 if (haveOptions) 778 file.options |= file_options.getInt(); 779 if (verbose > 1) 780 Utils.log.fine("Reading "+size+" bytes of "+name.stringValue()); 781 long toRead = size; 782 while (toRead > 0) { 783 int nr = buf.length; 784 if (nr > toRead) nr = (int) toRead; 785 nr = file_bits.getInputStream().read(buf, 0, nr); 786 if (nr < 0) throw new EOFException(); 787 file.addBytes(buf, 0, nr); 788 toRead -= nr; 789 } 790 pkg.addFile(file); 791 if (file.isClassStub()) { 792 assert(file.getFileLength() == 0); 793 Class cls = (Class) nextClass.next(); 794 cls.initFile(file); 795 } 796 } 797 798 // Do the rest of the classes. 799 while (nextClass.hasNext()) { 800 Class cls = (Class) nextClass.next(); 801 cls.initFile(null); // implicitly initialize to a trivial one 802 cls.file.modtime = pkg.default_modtime; 803 } 804 805 file_name.doneDisbursing(); 806 file_size_hi.doneDisbursing(); 807 file_size_lo.doneDisbursing(); 808 file_modtime.doneDisbursing(); 809 file_options.doneDisbursing(); 810 file_bits.doneDisbursing(); 811 file_bands.doneDisbursing(); 812 813 if (archiveSize1 != 0 && !in.atLimit()) { 814 throw new RuntimeException("Predicted archive_size "+ 815 archiveSize1+" != "+ 816 (in.getBytesServed()-archiveSize0)); 817 } 818 } 819 820 void readAttrDefs() throws IOException { 821 // attr_definition_bands: 822 // *attr_definition_headers :BYTE1 823 // *attr_definition_name :UNSIGNED5 (cp_Utf8) 824 // *attr_definition_layout :UNSIGNED5 (cp_Utf8) 825 attr_definition_headers.expectLength(numAttrDefs); 826 attr_definition_name.expectLength(numAttrDefs); 827 attr_definition_layout.expectLength(numAttrDefs); 828 attr_definition_headers.readFrom(in); 829 attr_definition_name.readFrom(in); 830 attr_definition_layout.readFrom(in); 831 try (PrintStream dump = !optDumpBands ? null 832 : new PrintStream(getDumpStream(attr_definition_headers, ".def"))) 833 { 834 for (int i = 0; i < numAttrDefs; i++) { 835 int header = attr_definition_headers.getByte(); 836 Utf8Entry name = (Utf8Entry) attr_definition_name.getRef(); 837 Utf8Entry layout = (Utf8Entry) attr_definition_layout.getRef(); 838 int ctype = (header & ADH_CONTEXT_MASK); 839 int index = (header >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB; 840 Attribute.Layout def = new Attribute.Layout(ctype, 841 name.stringValue(), 842 layout.stringValue()); 843 // Check layout string for Java 6 extensions. 844 String pvLayout = def.layoutForPackageMajver(getPackageMajver()); 845 if (!pvLayout.equals(def.layout())) { 846 throw new IOException("Bad attribute layout in version 150 archive: "+def.layout()); 847 } 848 this.setAttributeLayoutIndex(def, index); 849 if (dump != null) dump.println(index+" "+def); 850 } 851 } // TODO TWR: this relies on new null treatment for TWR's close() 852 attr_definition_headers.doneDisbursing(); 853 attr_definition_name.doneDisbursing(); 854 attr_definition_layout.doneDisbursing(); 855 // Attribute layouts define bands, one per layout element. 856 // Create them now, all at once. 857 makeNewAttributeBands(); 858 attr_definition_bands.doneDisbursing(); 859 } 860 861 void readInnerClasses() throws IOException { 862 // ic_bands: 863 // *ic_this_class :UDELTA5 (cp_Class) 864 // *ic_flags :UNSIGNED5 865 // *ic_outer_class :DELTA5 (null or cp_Class) 866 // *ic_name :DELTA5 (null or cp_Utf8) 867 ic_this_class.expectLength(numInnerClasses); 868 ic_this_class.readFrom(in); 869 ic_flags.expectLength(numInnerClasses); 870 ic_flags.readFrom(in); 871 int longICCount = 0; 872 for (int i = 0; i < numInnerClasses; i++) { 873 int flags = ic_flags.getInt(); 874 boolean longForm = (flags & ACC_IC_LONG_FORM) != 0; 875 if (longForm) { 876 longICCount += 1; 877 } 878 } 879 ic_outer_class.expectLength(longICCount); 880 ic_outer_class.readFrom(in); 881 ic_name.expectLength(longICCount); 882 ic_name.readFrom(in); 883 ic_flags.resetForSecondPass(); 884 List<InnerClass> icList = new ArrayList<>(numInnerClasses); 885 for (int i = 0; i < numInnerClasses; i++) { 886 int flags = ic_flags.getInt(); 887 boolean longForm = (flags & ACC_IC_LONG_FORM) != 0; 888 flags &= ~ACC_IC_LONG_FORM; 889 ClassEntry thisClass = (ClassEntry) ic_this_class.getRef(); 890 ClassEntry outerClass; 891 Utf8Entry thisName; 892 if (longForm) { 893 outerClass = (ClassEntry) ic_outer_class.getRef(); 894 thisName = (Utf8Entry) ic_name.getRef(); 895 } else { 896 String n = thisClass.stringValue(); 897 String[] parse = Package.parseInnerClassName(n); 898 assert(parse != null); 899 String pkgOuter = parse[0]; 900 //String number = parse[1]; 901 String name = parse[2]; 902 if (pkgOuter == null) 903 outerClass = null; 904 else 905 outerClass = ConstantPool.getClassEntry(pkgOuter); 906 if (name == null) 907 thisName = null; 908 else 909 thisName = ConstantPool.getUtf8Entry(name); 910 } 911 InnerClass ic = 912 new InnerClass(thisClass, outerClass, thisName, flags); 913 assert(longForm || ic.predictable); 914 icList.add(ic); 915 } 916 ic_flags.doneDisbursing(); 917 ic_this_class.doneDisbursing(); 918 ic_outer_class.doneDisbursing(); 919 ic_name.doneDisbursing(); 920 pkg.setAllInnerClasses(icList); 921 ic_bands.doneDisbursing(); 922 } 923 924 void readLocalInnerClasses(Class cls) throws IOException { 925 int nc = class_InnerClasses_N.getInt(); 926 List<InnerClass> localICs = new ArrayList<>(nc); 927 for (int i = 0; i < nc; i++) { 928 ClassEntry thisClass = (ClassEntry) class_InnerClasses_RC.getRef(); 929 int flags = class_InnerClasses_F.getInt(); 930 if (flags == 0) { 931 // A zero flag means copy a global IC here. 932 InnerClass ic = pkg.getGlobalInnerClass(thisClass); 933 assert(ic != null); // must be a valid global IC reference 934 localICs.add(ic); 935 } else { 936 if (flags == ACC_IC_LONG_FORM) 937 flags = 0; // clear the marker bit 938 ClassEntry outer = (ClassEntry) class_InnerClasses_outer_RCN.getRef(); 939 Utf8Entry name = (Utf8Entry) class_InnerClasses_name_RUN.getRef(); 940 localICs.add(new InnerClass(thisClass, outer, name, flags)); 941 } 942 } 943 cls.setInnerClasses(localICs); 944 // cls.expandLocalICs may add more tuples to ics also, 945 // or may even delete tuples. 946 // We cannot do that now, because we do not know the 947 // full contents of the local constant pool yet. 948 } 949 950 static final int NO_FLAGS_YET = 0; // placeholder for later flag read-in 951 952 Class[] readClasses() throws IOException { 953 // class_bands: 954 // *class_this :DELTA5 (cp_Class) 955 // *class_super :DELTA5 (cp_Class) 956 // *class_interface_count :DELTA5 957 // *class_interface :DELTA5 (cp_Class) 958 // ...(member bands)... 959 // class_attr_bands 960 // code_bands 961 Class[] classes = new Class[numClasses]; 962 if (verbose > 0) 963 Utils.log.info(" ...building "+classes.length+" classes..."); 964 965 class_this.expectLength(numClasses); 966 class_super.expectLength(numClasses); 967 class_interface_count.expectLength(numClasses); 968 969 class_this.readFrom(in); 970 class_super.readFrom(in); 971 class_interface_count.readFrom(in); 972 class_interface.expectLength(class_interface_count.getIntTotal()); 973 class_interface.readFrom(in); 974 for (int i = 0; i < classes.length; i++) { 975 ClassEntry thisClass = (ClassEntry) class_this.getRef(); 976 ClassEntry superClass = (ClassEntry) class_super.getRef(); 977 ClassEntry[] interfaces = new ClassEntry[class_interface_count.getInt()]; 978 for (int j = 0; j < interfaces.length; j++) { 979 interfaces[j] = (ClassEntry) class_interface.getRef(); 980 } 981 // Packer encoded rare case of null superClass as thisClass: 982 if (superClass == thisClass) superClass = null; 983 Class cls = pkg.new Class(NO_FLAGS_YET, 984 thisClass, superClass, interfaces); 985 classes[i] = cls; 986 } 987 class_this.doneDisbursing(); 988 class_super.doneDisbursing(); 989 class_interface_count.doneDisbursing(); 990 class_interface.doneDisbursing(); 991 readMembers(classes); 992 countAndReadAttrs(ATTR_CONTEXT_CLASS, Arrays.asList(classes)); 993 pkg.trimToSize(); 994 readCodeHeaders(); 995 //code_bands.doneDisbursing(); // still need to read code attrs 996 //class_bands.doneDisbursing(); // still need to read code attrs 997 return classes; 998 } 999 1000 private int getOutputIndex(Entry e) { 1001 // Output CPs do not contain signatures. 1002 assert(e.tag != CONSTANT_Signature); 1003 int k = pkg.cp.untypedIndexOf(e); 1004 // In the output ordering, input signatures can serve 1005 // in place of Utf8s. 1006 if (k >= 0) 1007 return k; 1008 if (e.tag == CONSTANT_Utf8) { 1009 Entry se = (Entry) utf8Signatures.get(e); 1010 return pkg.cp.untypedIndexOf(se); 1011 } 1012 return -1; 1013 } 1014 1015 Comparator<Entry> entryOutputOrder = new Comparator<>() { 1016 public int compare(Entry e0, Entry e1) { 1017 int k0 = getOutputIndex(e0); 1018 int k1 = getOutputIndex(e1); 1019 if (k0 >= 0 && k1 >= 0) 1020 // If both have keys, use the keys. 1021 return k0 - k1; 1022 if (k0 == k1) 1023 // If neither have keys, use their native tags & spellings. 1024 return e0.compareTo(e1); 1025 // Otherwise, the guy with the key comes first. 1026 return (k0 >= 0)? 0-1: 1-0; 1027 } 1028 }; 1029 1030 void reconstructClass(Class cls) { 1031 if (verbose > 1) Utils.log.fine("reconstruct "+cls); 1032 1033 // check for local .ClassFile.version 1034 Attribute retroVersion = cls.getAttribute(attrClassFileVersion); 1035 if (retroVersion != null) { 1036 cls.removeAttribute(retroVersion); 1037 short[] minmajver = parseClassFileVersionAttr(retroVersion); 1038 cls.minver = minmajver[0]; 1039 cls.majver = minmajver[1]; 1040 } else { 1041 cls.minver = pkg.default_class_minver; 1042 cls.majver = pkg.default_class_majver; 1043 } 1044 1045 // Replace null SourceFile by "obvious" string. 1046 cls.expandSourceFile(); 1047 1048 // record the local cp: 1049 cls.setCPMap(reconstructLocalCPMap(cls)); 1050 } 1051 1052 Entry[] reconstructLocalCPMap(Class cls) { 1053 Set<Entry> ldcRefs = ldcRefMap.get(cls); 1054 Set<Entry> cpRefs = new HashSet<>(); 1055 1056 // look for constant pool entries: 1057 cls.visitRefs(VRM_CLASSIC, cpRefs); 1058 1059 // flesh out the local constant pool 1060 ConstantPool.completeReferencesIn(cpRefs, true); 1061 1062 // Now that we know all our local class references, 1063 // compute the InnerClasses attribute. 1064 int changed = cls.expandLocalICs(); 1065 1066 if (changed != 0) { 1067 if (changed > 0) { 1068 // Just visit the expanded InnerClasses attr. 1069 cls.visitInnerClassRefs(VRM_CLASSIC, cpRefs); 1070 } else { 1071 // Have to recompute from scratch, because of deletions. 1072 cpRefs.clear(); 1073 cls.visitRefs(VRM_CLASSIC, cpRefs); 1074 } 1075 1076 // flesh out the local constant pool, again 1077 ConstantPool.completeReferencesIn(cpRefs, true); 1078 } 1079 1080 // construct a local constant pool 1081 int numDoubles = 0; 1082 for (Entry e : cpRefs) { 1083 if (e.isDoubleWord()) numDoubles++; 1084 assert(e.tag != CONSTANT_Signature) : (e); 1085 } 1086 Entry[] cpMap = new Entry[1+numDoubles+cpRefs.size()]; 1087 int fillp = 1; 1088 1089 // Add all ldc operands first. 1090 if (ldcRefs != null) { 1091 assert(cpRefs.containsAll(ldcRefs)); 1092 for (Entry e : ldcRefs) { 1093 cpMap[fillp++] = e; 1094 } 1095 assert(fillp == 1+ldcRefs.size()); 1096 cpRefs.removeAll(ldcRefs); 1097 ldcRefs = null; // done with it 1098 } 1099 1100 // Next add all the two-byte references. 1101 Set<Entry> wideRefs = cpRefs; 1102 cpRefs = null; // do not use! 1103 int narrowLimit = fillp; 1104 for (Entry e : wideRefs) { 1105 cpMap[fillp++] = e; 1106 } 1107 assert(fillp == narrowLimit+wideRefs.size()); 1108 Arrays.sort(cpMap, 1, narrowLimit, entryOutputOrder); 1109 Arrays.sort(cpMap, narrowLimit, fillp, entryOutputOrder); 1110 1111 if (verbose > 3) { 1112 Utils.log.fine("CP of "+this+" {"); 1113 for (int i = 0; i < fillp; i++) { 1114 Entry e = cpMap[i]; 1115 Utils.log.fine(" "+((e==null)?-1:getOutputIndex(e)) 1116 +" : "+e); 1117 } 1118 Utils.log.fine("}"); 1119 } 1120 1121 // Now repack backwards, introducing null elements. 1122 int revp = cpMap.length; 1123 for (int i = fillp; --i >= 1; ) { 1124 Entry e = cpMap[i]; 1125 if (e.isDoubleWord()) 1126 cpMap[--revp] = null; 1127 cpMap[--revp] = e; 1128 } 1129 assert(revp == 1); // do not process the initial null 1130 1131 return cpMap; 1132 } 1133 1134 void readMembers(Class[] classes) throws IOException { 1135 // class_bands: 1136 // ... 1137 // *class_field_count :DELTA5 1138 // *class_method_count :DELTA5 1139 // 1140 // *field_descr :DELTA5 (cp_Descr) 1141 // field_attr_bands 1142 // 1143 // *method_descr :MDELTA5 (cp_Descr) 1144 // method_attr_bands 1145 // ... 1146 assert(classes.length == numClasses); 1147 class_field_count.expectLength(numClasses); 1148 class_method_count.expectLength(numClasses); 1149 class_field_count.readFrom(in); 1150 class_method_count.readFrom(in); 1151 1152 // Make a pre-pass over field and method counts to size the descrs: 1153 int totalNF = class_field_count.getIntTotal(); 1154 int totalNM = class_method_count.getIntTotal(); 1155 field_descr.expectLength(totalNF); 1156 method_descr.expectLength(totalNM); 1157 if (verbose > 1) Utils.log.fine("expecting #fields="+totalNF+" and #methods="+totalNM+" in #classes="+numClasses); 1158 1159 List<Class.Field> fields = new ArrayList<>(totalNF); 1160 field_descr.readFrom(in); 1161 for (int i = 0; i < classes.length; i++) { 1162 Class c = classes[i]; 1163 int nf = class_field_count.getInt(); 1164 for (int j = 0; j < nf; j++) { 1165 Class.Field f = c.new Field(NO_FLAGS_YET, (DescriptorEntry) 1166 field_descr.getRef()); 1167 fields.add(f); 1168 } 1169 } 1170 class_field_count.doneDisbursing(); 1171 field_descr.doneDisbursing(); 1172 countAndReadAttrs(ATTR_CONTEXT_FIELD, fields); 1173 fields = null; // release to GC 1174 1175 List<Class.Method> methods = new ArrayList<>(totalNM); 1176 method_descr.readFrom(in); 1177 for (int i = 0; i < classes.length; i++) { 1178 Class c = classes[i]; 1179 int nm = class_method_count.getInt(); 1180 for (int j = 0; j < nm; j++) { 1181 Class.Method m = c.new Method(NO_FLAGS_YET, (DescriptorEntry) 1182 method_descr.getRef()); 1183 methods.add(m); 1184 } 1185 } 1186 class_method_count.doneDisbursing(); 1187 method_descr.doneDisbursing(); 1188 countAndReadAttrs(ATTR_CONTEXT_METHOD, methods); 1189 1190 // Up to this point, Code attributes look like empty attributes. 1191 // Now we start to special-case them. The empty canonical Code 1192 // attributes stay in the method attribute lists, however. 1193 allCodes = buildCodeAttrs(methods); 1194 } 1195 1196 Code[] allCodes; 1197 List<Code> codesWithFlags; 1198 Map<Class, Set<Entry>> ldcRefMap = new HashMap<>(); 1199 1200 Code[] buildCodeAttrs(List<Class.Method> methods) { 1201 List<Code> codes = new ArrayList<>(methods.size()); 1202 for (Class.Method m : methods) { 1203 if (m.getAttribute(attrCodeEmpty) != null) { 1204 m.code = new Code(m); 1205 codes.add(m.code); 1206 } 1207 } 1208 Code[] a = new Code[codes.size()]; 1209 codes.toArray(a); 1210 return a; 1211 } 1212 1213 void readCodeHeaders() throws IOException { 1214 // code_bands: 1215 // *code_headers :BYTE1 1216 // 1217 // *code_max_stack :UNSIGNED5 1218 // *code_max_na_locals :UNSIGNED5 1219 // *code_handler_count :UNSIGNED5 1220 // ... 1221 // code_attr_bands 1222 boolean attrsOK = testBit(archiveOptions, AO_HAVE_ALL_CODE_FLAGS); 1223 code_headers.expectLength(allCodes.length); 1224 code_headers.readFrom(in); 1225 List<Code> longCodes = new ArrayList<>(allCodes.length / 10); 1226 for (int i = 0; i < allCodes.length; i++) { 1227 Code c = allCodes[i]; 1228 int sc = code_headers.getByte(); 1229 assert(sc == (sc & 0xFF)); 1230 if (verbose > 2) 1231 Utils.log.fine("codeHeader "+c+" = "+sc); 1232 if (sc == LONG_CODE_HEADER) { 1233 // We will read ms/ml/nh/flags from bands shortly. 1234 longCodes.add(c); 1235 continue; 1236 } 1237 // Short code header is the usual case: 1238 c.setMaxStack( shortCodeHeader_max_stack(sc) ); 1239 c.setMaxNALocals( shortCodeHeader_max_na_locals(sc) ); 1240 c.setHandlerCount( shortCodeHeader_handler_count(sc) ); 1241 assert(shortCodeHeader(c) == sc); 1242 } 1243 code_headers.doneDisbursing(); 1244 code_max_stack.expectLength(longCodes.size()); 1245 code_max_na_locals.expectLength(longCodes.size()); 1246 code_handler_count.expectLength(longCodes.size()); 1247 1248 // Do the long headers now. 1249 code_max_stack.readFrom(in); 1250 code_max_na_locals.readFrom(in); 1251 code_handler_count.readFrom(in); 1252 for (Code c : longCodes) { 1253 c.setMaxStack( code_max_stack.getInt() ); 1254 c.setMaxNALocals( code_max_na_locals.getInt() ); 1255 c.setHandlerCount( code_handler_count.getInt() ); 1256 } 1257 code_max_stack.doneDisbursing(); 1258 code_max_na_locals.doneDisbursing(); 1259 code_handler_count.doneDisbursing(); 1260 1261 readCodeHandlers(); 1262 1263 if (attrsOK) { 1264 // Code attributes are common (debug info not stripped). 1265 codesWithFlags = Arrays.asList(allCodes); 1266 } else { 1267 // Code attributes are very sparse (debug info is stripped). 1268 codesWithFlags = longCodes; 1269 } 1270 countAttrs(ATTR_CONTEXT_CODE, codesWithFlags); 1271 // do readAttrs later, after BCs are scanned 1272 } 1273 1274 void readCodeHandlers() throws IOException { 1275 // code_bands: 1276 // ... 1277 // *code_handler_start_P :BCI5 1278 // *code_handler_end_PO :BRANCH5 1279 // *code_handler_catch_PO :BRANCH5 1280 // *code_handler_class_RCN :UNSIGNED5 (null or cp_Class) 1281 // ... 1282 int nh = 0; 1283 for (int i = 0; i < allCodes.length; i++) { 1284 Code c = allCodes[i]; 1285 nh += c.getHandlerCount(); 1286 } 1287 1288 ValueBand[] code_handler_bands = { 1289 code_handler_start_P, 1290 code_handler_end_PO, 1291 code_handler_catch_PO, 1292 code_handler_class_RCN 1293 }; 1294 1295 for (int i = 0; i < code_handler_bands.length; i++) { 1296 code_handler_bands[i].expectLength(nh); 1297 code_handler_bands[i].readFrom(in); 1298 } 1299 1300 for (int i = 0; i < allCodes.length; i++) { 1301 Code c = allCodes[i]; 1302 for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) { 1303 c.handler_class[j] = code_handler_class_RCN.getRef(); 1304 // For now, just record the raw BCI codes. 1305 // We must wait until we have instruction boundaries. 1306 c.handler_start[j] = code_handler_start_P.getInt(); 1307 c.handler_end[j] = code_handler_end_PO.getInt(); 1308 c.handler_catch[j] = code_handler_catch_PO.getInt(); 1309 } 1310 } 1311 for (int i = 0; i < code_handler_bands.length; i++) { 1312 code_handler_bands[i].doneDisbursing(); 1313 } 1314 } 1315 1316 void fixupCodeHandlers() { 1317 // Actually decode (renumber) the BCIs now. 1318 for (int i = 0; i < allCodes.length; i++) { 1319 Code c = allCodes[i]; 1320 for (int j = 0, jmax = c.getHandlerCount(); j < jmax; j++) { 1321 int sum = c.handler_start[j]; 1322 c.handler_start[j] = c.decodeBCI(sum); 1323 sum += c.handler_end[j]; 1324 c.handler_end[j] = c.decodeBCI(sum); 1325 sum += c.handler_catch[j]; 1326 c.handler_catch[j] = c.decodeBCI(sum); 1327 } 1328 } 1329 } 1330 1331 // Generic routines for reading attributes of 1332 // classes, fields, methods, and codes. 1333 // The holders is a global list, already collected, 1334 // of attribute "customers". 1335 void countAndReadAttrs(int ctype, Collection holders) throws IOException { 1336 // class_attr_bands: 1337 // *class_flags :UNSIGNED5 1338 // *class_attr_count :UNSIGNED5 1339 // *class_attr_indexes :UNSIGNED5 1340 // *class_attr_calls :UNSIGNED5 1341 // *class_Signature_RS :UNSIGNED5 (cp_Signature) 1342 // class_metadata_bands 1343 // *class_SourceFile_RU :UNSIGNED5 (cp_Utf8) 1344 // *class_EnclosingMethod_RM :UNSIGNED5 (cp_Method) 1345 // ic_local_bands 1346 // *class_ClassFile_version_minor_H :UNSIGNED5 1347 // *class_ClassFile_version_major_H :UNSIGNED5 1348 // 1349 // field_attr_bands: 1350 // *field_flags :UNSIGNED5 1351 // *field_attr_count :UNSIGNED5 1352 // *field_attr_indexes :UNSIGNED5 1353 // *field_attr_calls :UNSIGNED5 1354 // *field_Signature_RS :UNSIGNED5 (cp_Signature) 1355 // field_metadata_bands 1356 // *field_ConstantValue_KQ :UNSIGNED5 (cp_Int, etc.; see note) 1357 // 1358 // method_attr_bands: 1359 // *method_flags :UNSIGNED5 1360 // *method_attr_count :UNSIGNED5 1361 // *method_attr_indexes :UNSIGNED5 1362 // *method_attr_calls :UNSIGNED5 1363 // *method_Signature_RS :UNSIGNED5 (cp_Signature) 1364 // method_metadata_bands 1365 // *method_Exceptions_N :UNSIGNED5 1366 // *method_Exceptions_RC :UNSIGNED5 (cp_Class) 1367 // 1368 // code_attr_bands: 1369 // *code_flags :UNSIGNED5 1370 // *code_attr_count :UNSIGNED5 1371 // *code_attr_indexes :UNSIGNED5 1372 // *code_attr_calls :UNSIGNED5 1373 // *code_LineNumberTable_N :UNSIGNED5 1374 // *code_LineNumberTable_bci_P :BCI5 1375 // *code_LineNumberTable_line :UNSIGNED5 1376 // *code_LocalVariableTable_N :UNSIGNED5 1377 // *code_LocalVariableTable_bci_P :BCI5 1378 // *code_LocalVariableTable_span_O :BRANCH5 1379 // *code_LocalVariableTable_name_RU :UNSIGNED5 (cp_Utf8) 1380 // *code_LocalVariableTable_type_RS :UNSIGNED5 (cp_Signature) 1381 // *code_LocalVariableTable_slot :UNSIGNED5 1382 1383 countAttrs(ctype, holders); 1384 readAttrs(ctype, holders); 1385 } 1386 1387 // Read flags and count the attributes that are to be placed 1388 // on the given holders. 1389 void countAttrs(int ctype, Collection holders) throws IOException { 1390 // Here, xxx stands for one of class, field, method, code. 1391 MultiBand xxx_attr_bands = attrBands[ctype]; 1392 long flagMask = attrFlagMask[ctype]; 1393 if (verbose > 1) { 1394 Utils.log.fine("scanning flags and attrs for "+Attribute.contextName(ctype)+"["+holders.size()+"]"); 1395 } 1396 1397 // Fetch the attribute layout definitions which govern the bands 1398 // we are about to read. 1399 List<Attribute.Layout> defList = attrDefs.get(ctype); 1400 Attribute.Layout[] defs = new Attribute.Layout[defList.size()]; 1401 defList.toArray(defs); 1402 IntBand xxx_flags_hi = getAttrBand(xxx_attr_bands, AB_FLAGS_HI); 1403 IntBand xxx_flags_lo = getAttrBand(xxx_attr_bands, AB_FLAGS_LO); 1404 IntBand xxx_attr_count = getAttrBand(xxx_attr_bands, AB_ATTR_COUNT); 1405 IntBand xxx_attr_indexes = getAttrBand(xxx_attr_bands, AB_ATTR_INDEXES); 1406 IntBand xxx_attr_calls = getAttrBand(xxx_attr_bands, AB_ATTR_CALLS); 1407 1408 // Count up the number of holders which have overflow attrs. 1409 int overflowMask = attrOverflowMask[ctype]; 1410 int overflowHolderCount = 0; 1411 boolean haveLongFlags = haveFlagsHi(ctype); 1412 xxx_flags_hi.expectLength(haveLongFlags? holders.size(): 0); 1413 xxx_flags_hi.readFrom(in); 1414 xxx_flags_lo.expectLength(holders.size()); 1415 xxx_flags_lo.readFrom(in); 1416 assert((flagMask & overflowMask) == overflowMask); 1417 for (Iterator i = holders.iterator(); i.hasNext(); ) { 1418 Attribute.Holder h = (Attribute.Holder) i.next(); 1419 int flags = xxx_flags_lo.getInt(); 1420 h.flags = flags; 1421 if ((flags & overflowMask) != 0) 1422 overflowHolderCount += 1; 1423 } 1424 1425 // For each holder with overflow attrs, read a count. 1426 xxx_attr_count.expectLength(overflowHolderCount); 1427 xxx_attr_count.readFrom(in); 1428 xxx_attr_indexes.expectLength(xxx_attr_count.getIntTotal()); 1429 xxx_attr_indexes.readFrom(in); 1430 1431 // Now it's time to check flag bits that indicate attributes. 1432 // We accumulate (a) a list of attribute types for each holder 1433 // (class/field/method/code), and also we accumulate (b) a total 1434 // count for each attribute type. 1435 int[] totalCounts = new int[defs.length]; 1436 for (Iterator i = holders.iterator(); i.hasNext(); ) { 1437 Attribute.Holder h = (Attribute.Holder) i.next(); 1438 assert(h.attributes == null); 1439 // System.out.println("flags="+h.flags+" using fm="+flagMask); 1440 long attrBits = ((h.flags & flagMask) << 32) >>> 32; 1441 // Clean up the flags now. 1442 h.flags -= (int)attrBits; // strip attr bits 1443 assert(h.flags == (char)h.flags); // 16 bits only now 1444 assert((ctype != ATTR_CONTEXT_CODE) || h.flags == 0); 1445 if (haveLongFlags) 1446 attrBits += (long)xxx_flags_hi.getInt() << 32; 1447 if (attrBits == 0) continue; // no attrs on this guy 1448 1449 int noa = 0; // number of overflow attrs 1450 long overflowBit = (attrBits & overflowMask); 1451 assert(overflowBit >= 0); 1452 attrBits -= overflowBit; 1453 if (overflowBit != 0) { 1454 noa = xxx_attr_count.getInt(); 1455 } 1456 1457 int nfa = 0; // number of flag attrs 1458 long bits = attrBits; 1459 for (int ai = 0; bits != 0; ai++) { 1460 if ((bits & (1L<<ai)) == 0) continue; 1461 bits -= (1L<<ai); 1462 nfa += 1; 1463 } 1464 List<Attribute> ha = new ArrayList<>(nfa + noa); 1465 h.attributes = ha; 1466 bits = attrBits; // iterate again 1467 for (int ai = 0; bits != 0; ai++) { 1468 if ((bits & (1L<<ai)) == 0) continue; 1469 bits -= (1L<<ai); 1470 totalCounts[ai] += 1; 1471 // This definition index is live in this holder. 1472 if (defs[ai] == null) badAttrIndex(ai, ctype); 1473 Attribute canonical = defs[ai].canonicalInstance(); 1474 ha.add(canonical); 1475 nfa -= 1; 1476 } 1477 assert(nfa == 0); 1478 for (; noa > 0; noa--) { 1479 int ai = xxx_attr_indexes.getInt(); 1480 totalCounts[ai] += 1; 1481 // This definition index is live in this holder. 1482 if (defs[ai] == null) badAttrIndex(ai, ctype); 1483 Attribute canonical = defs[ai].canonicalInstance(); 1484 ha.add(canonical); 1485 } 1486 } 1487 1488 xxx_flags_hi.doneDisbursing(); 1489 xxx_flags_lo.doneDisbursing(); 1490 xxx_attr_count.doneDisbursing(); 1491 xxx_attr_indexes.doneDisbursing(); 1492 1493 // Now each holder has a list of canonical attribute instances. 1494 // For layouts with no elements, we are done. However, for 1495 // layouts with bands, we must replace each canonical (empty) 1496 // instance with a value-bearing one, initialized from the 1497 // appropriate bands. 1498 1499 // Make a small pass to detect and read backward call counts. 1500 int callCounts = 0; 1501 for (boolean predef = true; ; predef = false) { 1502 for (int ai = 0; ai < defs.length; ai++) { 1503 Attribute.Layout def = defs[ai]; 1504 if (def == null) continue; // unused index 1505 if (predef != isPredefinedAttr(ctype, ai)) 1506 continue; // wrong pass 1507 int totalCount = totalCounts[ai]; 1508 if (totalCount == 0) 1509 continue; // irrelevant 1510 Attribute.Layout.Element[] cbles = def.getCallables(); 1511 for (int j = 0; j < cbles.length; j++) { 1512 assert(cbles[j].kind == Attribute.EK_CBLE); 1513 if (cbles[j].flagTest(Attribute.EF_BACK)) 1514 callCounts += 1; 1515 } 1516 } 1517 if (!predef) break; 1518 } 1519 xxx_attr_calls.expectLength(callCounts); 1520 xxx_attr_calls.readFrom(in); 1521 1522 // Finally, size all the attribute bands. 1523 for (boolean predef = true; ; predef = false) { 1524 for (int ai = 0; ai < defs.length; ai++) { 1525 Attribute.Layout def = defs[ai]; 1526 if (def == null) continue; // unused index 1527 if (predef != isPredefinedAttr(ctype, ai)) 1528 continue; // wrong pass 1529 int totalCount = totalCounts[ai]; 1530 Band[] ab = attrBandTable.get(def); 1531 if (def == attrInnerClassesEmpty) { 1532 // Special case. 1533 // Size the bands as if using the following layout: 1534 // [RCH TI[ (0)[] ()[RCNH RUNH] ]]. 1535 class_InnerClasses_N.expectLength(totalCount); 1536 class_InnerClasses_N.readFrom(in); 1537 int tupleCount = class_InnerClasses_N.getIntTotal(); 1538 class_InnerClasses_RC.expectLength(tupleCount); 1539 class_InnerClasses_RC.readFrom(in); 1540 class_InnerClasses_F.expectLength(tupleCount); 1541 class_InnerClasses_F.readFrom(in); 1542 // Drop remaining columns wherever flags are zero: 1543 tupleCount -= class_InnerClasses_F.getIntCount(0); 1544 class_InnerClasses_outer_RCN.expectLength(tupleCount); 1545 class_InnerClasses_outer_RCN.readFrom(in); 1546 class_InnerClasses_name_RUN.expectLength(tupleCount); 1547 class_InnerClasses_name_RUN.readFrom(in); 1548 } else if (totalCount == 0) { 1549 // Expect no elements at all. Skip quickly. 1550 for (int j = 0; j < ab.length; j++) { 1551 ab[j].doneWithUnusedBand(); 1552 } 1553 } else { 1554 // Read these bands in sequence. 1555 boolean hasCallables = def.hasCallables(); 1556 if (!hasCallables) { 1557 readAttrBands(def.elems, totalCount, new int[0], ab); 1558 } else { 1559 Attribute.Layout.Element[] cbles = def.getCallables(); 1560 // At first, record initial calls. 1561 // Later, forward calls may also accumulate here: 1562 int[] forwardCounts = new int[cbles.length]; 1563 forwardCounts[0] = totalCount; 1564 for (int j = 0; j < cbles.length; j++) { 1565 assert(cbles[j].kind == Attribute.EK_CBLE); 1566 int entryCount = forwardCounts[j]; 1567 forwardCounts[j] = -1; // No more, please! 1568 if (cbles[j].flagTest(Attribute.EF_BACK)) 1569 entryCount += xxx_attr_calls.getInt(); 1570 readAttrBands(cbles[j].body, entryCount, forwardCounts, ab); 1571 } 1572 } 1573 } 1574 } 1575 if (!predef) break; 1576 } 1577 xxx_attr_calls.doneDisbursing(); 1578 } 1579 1580 void badAttrIndex(int ai, int ctype) throws IOException { 1581 throw new IOException("Unknown attribute index "+ai+" for "+ 1582 ATTR_CONTEXT_NAME[ctype]+" attribute"); 1583 } 1584 1585 @SuppressWarnings("unchecked") 1586 void readAttrs(int ctype, Collection holders) throws IOException { 1587 // Decode band values into attributes. 1588 Set<Attribute.Layout> sawDefs = new HashSet<>(); 1589 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 1590 for (Iterator i = holders.iterator(); i.hasNext(); ) { 1591 final Attribute.Holder h = (Attribute.Holder) i.next(); 1592 if (h.attributes == null) continue; 1593 for (ListIterator<Attribute> j = h.attributes.listIterator(); j.hasNext(); ) { 1594 Attribute a = j.next(); 1595 Attribute.Layout def = a.layout(); 1596 if (def.bandCount == 0) { 1597 if (def == attrInnerClassesEmpty) { 1598 // Special logic to read this attr. 1599 readLocalInnerClasses((Class) h); 1600 continue; 1601 } 1602 // Canonical empty attr works fine (e.g., Synthetic). 1603 continue; 1604 } 1605 sawDefs.add(def); 1606 boolean isCV = (ctype == ATTR_CONTEXT_FIELD && def == attrConstantValue); 1607 if (isCV) setConstantValueIndex((Class.Field)h); 1608 if (verbose > 2) 1609 Utils.log.fine("read "+a+" in "+h); 1610 final Band[] ab = attrBandTable.get(def); 1611 // Read one attribute of type def from ab into a byte array. 1612 buf.reset(); 1613 Object fixups = a.unparse(new Attribute.ValueStream() { 1614 public int getInt(int bandIndex) { 1615 return ((IntBand) ab[bandIndex]).getInt(); 1616 } 1617 public Entry getRef(int bandIndex) { 1618 return ((CPRefBand) ab[bandIndex]).getRef(); 1619 } 1620 public int decodeBCI(int bciCode) { 1621 Code code = (Code) h; 1622 return code.decodeBCI(bciCode); 1623 } 1624 }, buf); 1625 // Replace the canonical attr with the one just read. 1626 j.set(a.addContent(buf.toByteArray(), fixups)); 1627 if (isCV) setConstantValueIndex(null); // clean up 1628 } 1629 } 1630 1631 // Mark the bands we just used as done disbursing. 1632 for (Attribute.Layout def : sawDefs) { 1633 if (def == null) continue; // unused index 1634 Band[] ab = attrBandTable.get(def); 1635 for (int j = 0; j < ab.length; j++) { 1636 ab[j].doneDisbursing(); 1637 } 1638 } 1639 1640 if (ctype == ATTR_CONTEXT_CLASS) { 1641 class_InnerClasses_N.doneDisbursing(); 1642 class_InnerClasses_RC.doneDisbursing(); 1643 class_InnerClasses_F.doneDisbursing(); 1644 class_InnerClasses_outer_RCN.doneDisbursing(); 1645 class_InnerClasses_name_RUN.doneDisbursing(); 1646 } 1647 1648 MultiBand xxx_attr_bands = attrBands[ctype]; 1649 for (int i = 0; i < xxx_attr_bands.size(); i++) { 1650 Band b = xxx_attr_bands.get(i); 1651 if (b instanceof MultiBand) 1652 b.doneDisbursing(); 1653 } 1654 xxx_attr_bands.doneDisbursing(); 1655 } 1656 1657 private 1658 void readAttrBands(Attribute.Layout.Element[] elems, 1659 int count, int[] forwardCounts, 1660 Band[] ab) 1661 throws IOException { 1662 for (int i = 0; i < elems.length; i++) { 1663 Attribute.Layout.Element e = elems[i]; 1664 Band eBand = null; 1665 if (e.hasBand()) { 1666 eBand = ab[e.bandIndex]; 1667 eBand.expectLength(count); 1668 eBand.readFrom(in); 1669 } 1670 switch (e.kind) { 1671 case Attribute.EK_REPL: 1672 // Recursive call. 1673 int repCount = ((IntBand)eBand).getIntTotal(); 1674 // Note: getIntTotal makes an extra pass over this band. 1675 readAttrBands(e.body, repCount, forwardCounts, ab); 1676 break; 1677 case Attribute.EK_UN: 1678 int remainingCount = count; 1679 for (int j = 0; j < e.body.length; j++) { 1680 int caseCount; 1681 if (j == e.body.length-1) { 1682 caseCount = remainingCount; 1683 } else { 1684 caseCount = 0; 1685 for (int j0 = j; 1686 (j == j0) 1687 || (j < e.body.length 1688 && e.body[j].flagTest(Attribute.EF_BACK)); 1689 j++) { 1690 caseCount += ((IntBand)eBand).getIntCount(e.body[j].value); 1691 } 1692 --j; // back up to last occurrence of this body 1693 } 1694 remainingCount -= caseCount; 1695 readAttrBands(e.body[j].body, caseCount, forwardCounts, ab); 1696 } 1697 assert(remainingCount == 0); 1698 break; 1699 case Attribute.EK_CALL: 1700 assert(e.body.length == 1); 1701 assert(e.body[0].kind == Attribute.EK_CBLE); 1702 if (!e.flagTest(Attribute.EF_BACK)) { 1703 // Backward calls are pre-counted, but forwards are not. 1704 // Push the present count forward. 1705 assert(forwardCounts[e.value] >= 0); 1706 forwardCounts[e.value] += count; 1707 } 1708 break; 1709 case Attribute.EK_CBLE: 1710 assert(false); 1711 break; 1712 } 1713 } 1714 } 1715 1716 void readByteCodes() throws IOException { 1717 // bc_bands: 1718 // *bc_codes :BYTE1 1719 // *bc_case_count :UNSIGNED5 1720 // *bc_case_value :DELTA5 1721 // *bc_byte :BYTE1 1722 // *bc_short :DELTA5 1723 // *bc_local :UNSIGNED5 1724 // *bc_label :BRANCH5 1725 // *bc_intref :DELTA5 (cp_Int) 1726 // *bc_floatref :DELTA5 (cp_Float) 1727 // *bc_longref :DELTA5 (cp_Long) 1728 // *bc_doubleref :DELTA5 (cp_Double) 1729 // *bc_stringref :DELTA5 (cp_String) 1730 // *bc_classref :UNSIGNED5 (current class or cp_Class) 1731 // *bc_fieldref :DELTA5 (cp_Field) 1732 // *bc_methodref :UNSIGNED5 (cp_Method) 1733 // *bc_imethodref :DELTA5 (cp_Imethod) 1734 // *bc_thisfield :UNSIGNED5 (cp_Field, only for current class) 1735 // *bc_superfield :UNSIGNED5 (cp_Field, only for current super) 1736 // *bc_thismethod :UNSIGNED5 (cp_Method, only for current class) 1737 // *bc_supermethod :UNSIGNED5 (cp_Method, only for current super) 1738 // *bc_initref :UNSIGNED5 (cp_Field, only for most recent new) 1739 // *bc_escref :UNSIGNED5 (cp_All) 1740 // *bc_escrefsize :UNSIGNED5 1741 // *bc_escsize :UNSIGNED5 1742 // *bc_escbyte :BYTE1 1743 bc_codes.elementCountForDebug = allCodes.length; 1744 bc_codes.setInputStreamFrom(in); 1745 readByteCodeOps(); // reads from bc_codes and bc_case_count 1746 bc_codes.doneDisbursing(); 1747 1748 // All the operand bands have now been sized. Read them all in turn. 1749 Band[] operand_bands = { 1750 bc_case_value, 1751 bc_byte, bc_short, 1752 bc_local, bc_label, 1753 bc_intref, bc_floatref, 1754 bc_longref, bc_doubleref, bc_stringref, 1755 bc_classref, bc_fieldref, 1756 bc_methodref, bc_imethodref, 1757 bc_thisfield, bc_superfield, 1758 bc_thismethod, bc_supermethod, 1759 bc_initref, 1760 bc_escref, bc_escrefsize, bc_escsize 1761 }; 1762 for (int i = 0; i < operand_bands.length; i++) { 1763 operand_bands[i].readFrom(in); 1764 } 1765 bc_escbyte.expectLength(bc_escsize.getIntTotal()); 1766 bc_escbyte.readFrom(in); 1767 1768 expandByteCodeOps(); 1769 1770 // Done fetching values from operand bands: 1771 bc_case_count.doneDisbursing(); 1772 for (int i = 0; i < operand_bands.length; i++) { 1773 operand_bands[i].doneDisbursing(); 1774 } 1775 bc_escbyte.doneDisbursing(); 1776 bc_bands.doneDisbursing(); 1777 1778 // We must delay the parsing of Code attributes until we 1779 // have a complete model of bytecodes, for BCI encodings. 1780 readAttrs(ATTR_CONTEXT_CODE, codesWithFlags); 1781 // Ditto for exception handlers in codes. 1782 fixupCodeHandlers(); 1783 // Now we can finish with class_bands; cf. readClasses(). 1784 code_bands.doneDisbursing(); 1785 class_bands.doneDisbursing(); 1786 } 1787 1788 private void readByteCodeOps() throws IOException { 1789 // scratch buffer for collecting code:: 1790 byte[] buf = new byte[1<<12]; 1791 // record of all switch opcodes (these are variable-length) 1792 List<Integer> allSwitchOps = new ArrayList<>(); 1793 for (int k = 0; k < allCodes.length; k++) { 1794 Code c = allCodes[k]; 1795 scanOneMethod: 1796 for (int i = 0; ; i++) { 1797 int bc = bc_codes.getByte(); 1798 if (i + 10 > buf.length) buf = realloc(buf); 1799 buf[i] = (byte)bc; 1800 boolean isWide = false; 1801 if (bc == _wide) { 1802 bc = bc_codes.getByte(); 1803 buf[++i] = (byte)bc; 1804 isWide = true; 1805 } 1806 assert(bc == (0xFF & bc)); 1807 // Adjust expectations of various band sizes. 1808 switch (bc) { 1809 case _tableswitch: 1810 case _lookupswitch: 1811 bc_case_count.expectMoreLength(1); 1812 allSwitchOps.add(bc); 1813 break; 1814 case _iinc: 1815 bc_local.expectMoreLength(1); 1816 if (isWide) 1817 bc_short.expectMoreLength(1); 1818 else 1819 bc_byte.expectMoreLength(1); 1820 break; 1821 case _sipush: 1822 bc_short.expectMoreLength(1); 1823 break; 1824 case _bipush: 1825 bc_byte.expectMoreLength(1); 1826 break; 1827 case _newarray: 1828 bc_byte.expectMoreLength(1); 1829 break; 1830 case _multianewarray: 1831 assert(getCPRefOpBand(bc) == bc_classref); 1832 bc_classref.expectMoreLength(1); 1833 bc_byte.expectMoreLength(1); 1834 break; 1835 case _ref_escape: 1836 bc_escrefsize.expectMoreLength(1); 1837 bc_escref.expectMoreLength(1); 1838 break; 1839 case _byte_escape: 1840 bc_escsize.expectMoreLength(1); 1841 // bc_escbyte will have to be counted too 1842 break; 1843 default: 1844 if (Instruction.isInvokeInitOp(bc)) { 1845 bc_initref.expectMoreLength(1); 1846 break; 1847 } 1848 if (Instruction.isSelfLinkerOp(bc)) { 1849 CPRefBand bc_which = selfOpRefBand(bc); 1850 bc_which.expectMoreLength(1); 1851 break; 1852 } 1853 if (Instruction.isBranchOp(bc)) { 1854 bc_label.expectMoreLength(1); 1855 break; 1856 } 1857 if (Instruction.isCPRefOp(bc)) { 1858 CPRefBand bc_which = getCPRefOpBand(bc); 1859 bc_which.expectMoreLength(1); 1860 assert(bc != _multianewarray); // handled elsewhere 1861 break; 1862 } 1863 if (Instruction.isLocalSlotOp(bc)) { 1864 bc_local.expectMoreLength(1); 1865 break; 1866 } 1867 break; 1868 case _end_marker: 1869 { 1870 // Transfer from buf to a more permanent place: 1871 c.bytes = realloc(buf, i); 1872 break scanOneMethod; 1873 } 1874 } 1875 } 1876 } 1877 1878 // To size instruction bands correctly, we need info on switches: 1879 bc_case_count.readFrom(in); 1880 for (Integer i : allSwitchOps) { 1881 int bc = i.intValue(); 1882 int caseCount = bc_case_count.getInt(); 1883 bc_label.expectMoreLength(1+caseCount); // default label + cases 1884 bc_case_value.expectMoreLength(bc == _tableswitch ? 1 : caseCount); 1885 } 1886 bc_case_count.resetForSecondPass(); 1887 } 1888 1889 private void expandByteCodeOps() throws IOException { 1890 // scratch buffer for collecting code: 1891 byte[] buf = new byte[1<<12]; 1892 // scratch buffer for collecting instruction boundaries: 1893 int[] insnMap = new int[1<<12]; 1894 // list of label carriers, for label decoding post-pass: 1895 int[] labels = new int[1<<10]; 1896 // scratch buffer for registering CP refs: 1897 Fixups fixupBuf = new Fixups(); 1898 1899 for (int k = 0; k < allCodes.length; k++) { 1900 Code code = allCodes[k]; 1901 byte[] codeOps = code.bytes; 1902 code.bytes = null; // just for now, while we accumulate bits 1903 1904 Class curClass = code.thisClass(); 1905 1906 Set<Entry> ldcRefSet = ldcRefMap.get(curClass); 1907 if (ldcRefSet == null) 1908 ldcRefMap.put(curClass, ldcRefSet = new HashSet<>()); 1909 1910 ClassEntry thisClass = curClass.thisClass; 1911 ClassEntry superClass = curClass.superClass; 1912 ClassEntry newClass = null; // class of last _new opcode 1913 1914 int pc = 0; // fill pointer in buf; actual bytecode PC 1915 int numInsns = 0; 1916 int numLabels = 0; 1917 boolean hasEscs = false; 1918 fixupBuf.clear(); 1919 for (int i = 0; i < codeOps.length; i++) { 1920 int bc = Instruction.getByte(codeOps, i); 1921 int curPC = pc; 1922 insnMap[numInsns++] = curPC; 1923 if (pc + 10 > buf.length) buf = realloc(buf); 1924 if (numInsns+10 > insnMap.length) insnMap = realloc(insnMap); 1925 if (numLabels+10 > labels.length) labels = realloc(labels); 1926 boolean isWide = false; 1927 if (bc == _wide) { 1928 buf[pc++] = (byte) bc; 1929 bc = Instruction.getByte(codeOps, ++i); 1930 isWide = true; 1931 } 1932 switch (bc) { 1933 case _tableswitch: // apc: (df, lo, hi, (hi-lo+1)*(label)) 1934 case _lookupswitch: // apc: (df, nc, nc*(case, label)) 1935 { 1936 int caseCount = bc_case_count.getInt(); 1937 while ((pc + 30 + caseCount*8) > buf.length) 1938 buf = realloc(buf); 1939 buf[pc++] = (byte) bc; 1940 //initialize apc, df, lo, hi bytes to reasonable bits: 1941 Arrays.fill(buf, pc, pc+30, (byte)0); 1942 Instruction.Switch isw = (Instruction.Switch) 1943 Instruction.at(buf, curPC); 1944 //isw.setDefaultLabel(getLabel(bc_label, code, curPC)); 1945 isw.setCaseCount(caseCount); 1946 if (bc == _tableswitch) { 1947 isw.setCaseValue(0, bc_case_value.getInt()); 1948 } else { 1949 for (int j = 0; j < caseCount; j++) { 1950 isw.setCaseValue(j, bc_case_value.getInt()); 1951 } 1952 } 1953 // Make our getLabel calls later. 1954 labels[numLabels++] = curPC; 1955 pc = isw.getNextPC(); 1956 continue; 1957 } 1958 case _iinc: 1959 { 1960 buf[pc++] = (byte) bc; 1961 int local = bc_local.getInt(); 1962 int delta; 1963 if (isWide) { 1964 delta = bc_short.getInt(); 1965 Instruction.setShort(buf, pc, local); pc += 2; 1966 Instruction.setShort(buf, pc, delta); pc += 2; 1967 } else { 1968 delta = (byte) bc_byte.getByte(); 1969 buf[pc++] = (byte)local; 1970 buf[pc++] = (byte)delta; 1971 } 1972 continue; 1973 } 1974 case _sipush: 1975 { 1976 int val = bc_short.getInt(); 1977 buf[pc++] = (byte) bc; 1978 Instruction.setShort(buf, pc, val); pc += 2; 1979 continue; 1980 } 1981 case _bipush: 1982 case _newarray: 1983 { 1984 int val = bc_byte.getByte(); 1985 buf[pc++] = (byte) bc; 1986 buf[pc++] = (byte) val; 1987 continue; 1988 } 1989 case _ref_escape: 1990 { 1991 // Note that insnMap has one entry for this. 1992 hasEscs = true; 1993 int size = bc_escrefsize.getInt(); 1994 Entry ref = bc_escref.getRef(); 1995 if (size == 1) ldcRefSet.add(ref); 1996 int fmt; 1997 switch (size) { 1998 case 1: fmt = Fixups.U1_FORMAT; break; 1999 case 2: fmt = Fixups.U2_FORMAT; break; 2000 default: assert(false); fmt = 0; 2001 } 2002 fixupBuf.add(pc, fmt, ref); 2003 buf[pc+0] = buf[pc+1] = 0; 2004 pc += size; 2005 } 2006 continue; 2007 case _byte_escape: 2008 { 2009 // Note that insnMap has one entry for all these bytes. 2010 hasEscs = true; 2011 int size = bc_escsize.getInt(); 2012 while ((pc + size) > buf.length) 2013 buf = realloc(buf); 2014 while (size-- > 0) { 2015 buf[pc++] = (byte) bc_escbyte.getByte(); 2016 } 2017 } 2018 continue; 2019 default: 2020 if (Instruction.isInvokeInitOp(bc)) { 2021 int idx = (bc - _invokeinit_op); 2022 int origBC = _invokespecial; 2023 ClassEntry classRef; 2024 switch (idx) { 2025 case _invokeinit_self_option: 2026 classRef = thisClass; break; 2027 case _invokeinit_super_option: 2028 classRef = superClass; break; 2029 default: 2030 assert(idx == _invokeinit_new_option); 2031 classRef = newClass; break; 2032 } 2033 buf[pc++] = (byte) origBC; 2034 int coding = bc_initref.getInt(); 2035 // Find the nth overloading of <init> in classRef. 2036 MemberEntry ref = pkg.cp.getOverloadingForIndex(CONSTANT_Methodref, classRef, "<init>", coding); 2037 fixupBuf.add(pc, Fixups.U2_FORMAT, ref); 2038 buf[pc+0] = buf[pc+1] = 0; 2039 pc += 2; 2040 assert(Instruction.opLength(origBC) == (pc - curPC)); 2041 continue; 2042 } 2043 if (Instruction.isSelfLinkerOp(bc)) { 2044 int idx = (bc - _self_linker_op); 2045 boolean isSuper = (idx >= _self_linker_super_flag); 2046 if (isSuper) idx -= _self_linker_super_flag; 2047 boolean isAload = (idx >= _self_linker_aload_flag); 2048 if (isAload) idx -= _self_linker_aload_flag; 2049 int origBC = _first_linker_op + idx; 2050 boolean isField = Instruction.isFieldOp(origBC); 2051 CPRefBand bc_which; 2052 ClassEntry which_cls = isSuper ? superClass : thisClass; 2053 Index which_ix; 2054 if (isField) { 2055 bc_which = isSuper ? bc_superfield : bc_thisfield; 2056 which_ix = pkg.cp.getMemberIndex(CONSTANT_Fieldref, which_cls); 2057 } else { 2058 bc_which = isSuper ? bc_supermethod : bc_thismethod; 2059 which_ix = pkg.cp.getMemberIndex(CONSTANT_Methodref, which_cls); 2060 } 2061 assert(bc_which == selfOpRefBand(bc)); 2062 MemberEntry ref = (MemberEntry) bc_which.getRef(which_ix); 2063 if (isAload) { 2064 buf[pc++] = (byte) _aload_0; 2065 curPC = pc; 2066 // Note: insnMap keeps the _aload_0 separate. 2067 insnMap[numInsns++] = curPC; 2068 } 2069 buf[pc++] = (byte) origBC; 2070 fixupBuf.add(pc, Fixups.U2_FORMAT, ref); 2071 buf[pc+0] = buf[pc+1] = 0; 2072 pc += 2; 2073 assert(Instruction.opLength(origBC) == (pc - curPC)); 2074 continue; 2075 } 2076 if (Instruction.isBranchOp(bc)) { 2077 buf[pc++] = (byte) bc; 2078 assert(!isWide); // no wide prefix for branches 2079 int nextPC = curPC + Instruction.opLength(bc); 2080 // Make our getLabel calls later. 2081 labels[numLabels++] = curPC; 2082 //Instruction.at(buf, curPC).setBranchLabel(getLabel(bc_label, code, curPC)); 2083 while (pc < nextPC) buf[pc++] = 0; 2084 continue; 2085 } 2086 if (Instruction.isCPRefOp(bc)) { 2087 CPRefBand bc_which = getCPRefOpBand(bc); 2088 Entry ref = bc_which.getRef(); 2089 if (ref == null) { 2090 if (bc_which == bc_classref) { 2091 // Shorthand for class self-references. 2092 ref = thisClass; 2093 } else { 2094 assert(false); 2095 } 2096 } 2097 int origBC = bc; 2098 int size = 2; 2099 switch (bc) { 2100 case _ildc: 2101 case _cldc: 2102 case _fldc: 2103 case _aldc: 2104 origBC = _ldc; 2105 size = 1; 2106 ldcRefSet.add(ref); 2107 break; 2108 case _ildc_w: 2109 case _cldc_w: 2110 case _fldc_w: 2111 case _aldc_w: 2112 origBC = _ldc_w; 2113 break; 2114 case _lldc2_w: 2115 case _dldc2_w: 2116 origBC = _ldc2_w; 2117 break; 2118 case _new: 2119 newClass = (ClassEntry) ref; 2120 break; 2121 } 2122 buf[pc++] = (byte) origBC; 2123 int fmt; 2124 switch (size) { 2125 case 1: fmt = Fixups.U1_FORMAT; break; 2126 case 2: fmt = Fixups.U2_FORMAT; break; 2127 default: assert(false); fmt = 0; 2128 } 2129 fixupBuf.add(pc, fmt, ref); 2130 buf[pc+0] = buf[pc+1] = 0; 2131 pc += size; 2132 if (origBC == _multianewarray) { 2133 // Copy the trailing byte also. 2134 int val = bc_byte.getByte(); 2135 buf[pc++] = (byte) val; 2136 } else if (origBC == _invokeinterface) { 2137 int argSize = ((MemberEntry)ref).descRef.typeRef.computeSize(true); 2138 buf[pc++] = (byte)( 1 + argSize ); 2139 buf[pc++] = 0; 2140 } 2141 assert(Instruction.opLength(origBC) == (pc - curPC)); 2142 continue; 2143 } 2144 if (Instruction.isLocalSlotOp(bc)) { 2145 buf[pc++] = (byte) bc; 2146 int local = bc_local.getInt(); 2147 if (isWide) { 2148 Instruction.setShort(buf, pc, local); 2149 pc += 2; 2150 if (bc == _iinc) { 2151 int iVal = bc_short.getInt(); 2152 Instruction.setShort(buf, pc, iVal); 2153 pc += 2; 2154 } 2155 } else { 2156 Instruction.setByte(buf, pc, local); 2157 pc += 1; 2158 if (bc == _iinc) { 2159 int iVal = bc_byte.getByte(); 2160 Instruction.setByte(buf, pc, iVal); 2161 pc += 1; 2162 } 2163 } 2164 assert(Instruction.opLength(bc) == (pc - curPC)); 2165 continue; 2166 } 2167 // Random bytecode. Just copy it. 2168 if (bc >= _bytecode_limit) 2169 Utils.log.warning("unrecognized bytescode "+bc 2170 +" "+Instruction.byteName(bc)); 2171 assert(bc < _bytecode_limit); 2172 buf[pc++] = (byte) bc; 2173 assert(Instruction.opLength(bc) == (pc - curPC)); 2174 continue; 2175 } 2176 } 2177 // now make a permanent copy of the bytecodes 2178 code.setBytes(realloc(buf, pc)); 2179 code.setInstructionMap(insnMap, numInsns); 2180 // fix up labels, now that code has its insnMap 2181 Instruction ibr = null; // temporary branch instruction 2182 for (int i = 0; i < numLabels; i++) { 2183 int curPC = labels[i]; 2184 // (Note: Passing ibr in allows reuse, a speed hack.) 2185 ibr = Instruction.at(code.bytes, curPC, ibr); 2186 if (ibr instanceof Instruction.Switch) { 2187 Instruction.Switch isw = (Instruction.Switch) ibr; 2188 isw.setDefaultLabel(getLabel(bc_label, code, curPC)); 2189 int caseCount = isw.getCaseCount(); 2190 for (int j = 0; j < caseCount; j++) { 2191 isw.setCaseLabel(j, getLabel(bc_label, code, curPC)); 2192 } 2193 } else { 2194 ibr.setBranchLabel(getLabel(bc_label, code, curPC)); 2195 } 2196 } 2197 if (fixupBuf.size() > 0) { 2198 if (verbose > 2) 2199 Utils.log.fine("Fixups in code: "+fixupBuf); 2200 code.addFixups(fixupBuf); 2201 } 2202 } 2203 } 2204 }