diff options
| author | Petr Mrázek <peterix@gmail.com> | 2016-04-10 15:53:05 +0200 |
|---|---|---|
| committer | Petr Mrázek <peterix@gmail.com> | 2016-05-01 00:00:14 +0200 |
| commit | b6d455a02bd338e9dc0faa09d4d8177ecd8d569a (patch) | |
| tree | 41982bca1ede50049f2f8c7109dd18edeefde6d0 /libraries/pack200/src | |
| parent | 47e37635f50c09b4f9a9ee7699e3120bab3e4088 (diff) | |
| download | PrismLauncher-b6d455a02bd338e9dc0faa09d4d8177ecd8d569a.tar.gz PrismLauncher-b6d455a02bd338e9dc0faa09d4d8177ecd8d569a.tar.bz2 PrismLauncher-b6d455a02bd338e9dc0faa09d4d8177ecd8d569a.zip | |
NOISSUE reorganize and document libraries
Diffstat (limited to 'libraries/pack200/src')
| -rw-r--r-- | libraries/pack200/src/bands.cpp | 423 | ||||
| -rw-r--r-- | libraries/pack200/src/bands.h | 489 | ||||
| -rw-r--r-- | libraries/pack200/src/bytes.cpp | 217 | ||||
| -rw-r--r-- | libraries/pack200/src/bytes.h | 286 | ||||
| -rw-r--r-- | libraries/pack200/src/coding.cpp | 1044 | ||||
| -rw-r--r-- | libraries/pack200/src/coding.h | 247 | ||||
| -rw-r--r-- | libraries/pack200/src/constants.h | 442 | ||||
| -rw-r--r-- | libraries/pack200/src/defines.h | 65 | ||||
| -rw-r--r-- | libraries/pack200/src/unpack.cpp | 4793 | ||||
| -rw-r--r-- | libraries/pack200/src/unpack.h | 547 | ||||
| -rw-r--r-- | libraries/pack200/src/unpack200.cpp | 162 | ||||
| -rw-r--r-- | libraries/pack200/src/utils.cpp | 71 | ||||
| -rw-r--r-- | libraries/pack200/src/utils.h | 53 | ||||
| -rw-r--r-- | libraries/pack200/src/zip.cpp | 589 | ||||
| -rw-r--r-- | libraries/pack200/src/zip.h | 110 |
15 files changed, 9538 insertions, 0 deletions
diff --git a/libraries/pack200/src/bands.cpp b/libraries/pack200/src/bands.cpp new file mode 100644 index 00000000..1608d838 --- /dev/null +++ b/libraries/pack200/src/bands.cpp @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// -*- C++ -*- +// Small program for unpacking specially compressed Java packages. +// John R. Rose + +#include <sys/types.h> + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> +#include <assert.h> +#include <stdint.h> + +#include "defines.h" +#include "bytes.h" +#include "utils.h" +#include "coding.h" +#include "bands.h" + +#include "constants.h" +#include "unpack.h" + +void band::readData(int expectedLength) +{ + assert(expectedLength >= 0); + assert(vs[0].cmk == cmk_ERROR); + if (expectedLength != 0) + { + assert(length == 0); + length = expectedLength; + } + if (length == 0) + { + assert((rplimit = cm.vs0.rp = u->rp) != nullptr); + return; + } + assert(length > 0); + + bool is_BYTE1 = (defc->spec == BYTE1_spec); + + if (is_BYTE1) + { + // No possibility of coding change. Sizing is exact. + u->ensure_input(length); + } + else + { + // Make a conservatively generous estimate of band size in bytes. + // Assume B == 5 everywhere. + // Assume awkward pop with all {U} values (2*5 per value) + int64_t generous = (int64_t)length * (B_MAX * 3 + 1) + C_SLOP; + u->ensure_input(generous); + } + + // Read one value to see what it might be. + int XB = _meta_default; + if (!is_BYTE1) + { + // must be a variable-length coding + assert(defc->B() > 1 && defc->L() > 0); + + value_stream xvs; + coding *valc = defc; + if (valc->D() != 0) + { + valc = coding::findBySpec(defc->B(), defc->H(), defc->S()); + assert(!valc->isMalloc); + } + xvs.init(u->rp, u->rplimit, valc); + int X = xvs.getInt(); + if (valc->S() != 0) + { + assert(valc->min <= -256); + XB = -1 - X; + } + else + { + int L = valc->L(); + assert(valc->max >= L + 255); + XB = X - L; + } + if (0 <= XB && XB < 256) + { + // Skip over the escape value. + u->rp = xvs.rp; + } + else + { + // No, it's still default. + XB = _meta_default; + } + } + + if (XB <= _meta_canon_max) + { + byte XB_byte = (byte)XB; + byte *XB_ptr = &XB_byte; + cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, nullptr); + } + else + { + assert(u->meta_rp != nullptr); + // Scribble the initial byte onto the band. + byte *save_meta_rp = --u->meta_rp; + byte save_meta_xb = (*save_meta_rp); + (*save_meta_rp) = (byte)XB; + cm.init(u->rp, u->rplimit, u->meta_rp, 0, defc, length, nullptr); + (*save_meta_rp) = save_meta_xb; // put it back, just to be tidy + } + rplimit = u->rp; + + rewind(); +} + +void band::setIndex(cpindex *ix_) +{ + assert(ix_ == nullptr || ixTag == ix_->ixTag); + ix = ix_; +} +void band::setIndexByTag(byte tag) +{ + setIndex(u->cp.getIndex(tag)); +} + +entry *band::getRefCommon(cpindex *ix_, bool nullOKwithCaller) +{ + assert(ix_->ixTag == ixTag || + (ixTag == CONSTANT_Literal && ix_->ixTag >= CONSTANT_Integer && + ix_->ixTag <= CONSTANT_String)); + int n = vs[0].getInt() - nullOK; + // Note: band-local nullOK means nullptr encodes as 0. + // But nullOKwithCaller means caller is willing to tolerate a nullptr. + entry *ref = ix_->get(n); + if (ref == nullptr && !(nullOKwithCaller && n == -1)) + unpack_abort(n == -1 ? "nullptr ref" : "bad ref"); + return ref; +} + +int64_t band::getLong(band &lo_band, bool have_hi) +{ + band &hi_band = (*this); + assert(lo_band.bn == hi_band.bn + 1); + uint32_t lo = lo_band.getInt(); + if (!have_hi) + { + assert(hi_band.length == 0); + return makeLong(0, lo); + } + uint32_t hi = hi_band.getInt(); + return makeLong(hi, lo); +} + +int band::getIntTotal() +{ + if (length == 0) + return 0; + if (total_memo > 0) + return total_memo - 1; + int total = getInt(); + // overflow checks require that none of the addends are <0, + // and that the partial sums never overflow (wrap negative) + if (total < 0) + { + unpack_abort("overflow detected"); + } + for (int k = length - 1; k > 0; k--) + { + int prev_total = total; + total += vs[0].getInt(); + if (total < prev_total) + { + unpack_abort("overflow detected"); + } + } + rewind(); + total_memo = total + 1; + return total; +} + +int band::getIntCount(int tag) +{ + if (length == 0) + return 0; + if (tag >= HIST0_MIN && tag <= HIST0_MAX) + { + if (hist0 == nullptr) + { + // Lazily calculate an approximate histogram. + hist0 = U_NEW(int, (HIST0_MAX - HIST0_MIN) + 1); + for (int k = length; k > 0; k--) + { + int x = vs[0].getInt(); + if (x >= HIST0_MIN && x <= HIST0_MAX) + hist0[x - HIST0_MIN] += 1; + } + rewind(); + } + return hist0[tag - HIST0_MIN]; + } + int total = 0; + for (int k = length; k > 0; k--) + { + total += (vs[0].getInt() == tag) ? 1 : 0; + } + rewind(); + return total; +} + +#define INDEX_INIT(tag, nullOK, subindex) ((tag) + (subindex) * SUBINDEX_BIT + (nullOK) * 256) + +#define INDEX(tag) INDEX_INIT(tag, 0, 0) +#define NULL_OR_INDEX(tag) INDEX_INIT(tag, 1, 0) +#define SUB_INDEX(tag) INDEX_INIT(tag, 0, 1) +#define NO_INDEX 0 + +struct band_init +{ + int defc; + int index; +}; + +#define BAND_INIT(name, cspec, ix) \ + { \ + cspec, ix \ + } + +const band_init all_band_inits[] = + { + // BAND_INIT(archive_magic, BYTE1_spec, 0), + // BAND_INIT(archive_header, UNSIGNED5_spec, 0), + // BAND_INIT(band_headers, BYTE1_spec, 0), + BAND_INIT(cp_Utf8_prefix, DELTA5_spec, 0), BAND_INIT(cp_Utf8_suffix, UNSIGNED5_spec, 0), + BAND_INIT(cp_Utf8_chars, CHAR3_spec, 0), BAND_INIT(cp_Utf8_big_suffix, DELTA5_spec, 0), + BAND_INIT(cp_Utf8_big_chars, DELTA5_spec, 0), BAND_INIT(cp_Int, UDELTA5_spec, 0), + BAND_INIT(cp_Float, UDELTA5_spec, 0), BAND_INIT(cp_Long_hi, UDELTA5_spec, 0), + BAND_INIT(cp_Long_lo, DELTA5_spec, 0), BAND_INIT(cp_Double_hi, UDELTA5_spec, 0), + BAND_INIT(cp_Double_lo, DELTA5_spec, 0), + BAND_INIT(cp_String, UDELTA5_spec, INDEX(CONSTANT_Utf8)), + BAND_INIT(cp_Class, UDELTA5_spec, INDEX(CONSTANT_Utf8)), + BAND_INIT(cp_Signature_form, DELTA5_spec, INDEX(CONSTANT_Utf8)), + BAND_INIT(cp_Signature_classes, UDELTA5_spec, INDEX(CONSTANT_Class)), + BAND_INIT(cp_Descr_name, DELTA5_spec, INDEX(CONSTANT_Utf8)), + BAND_INIT(cp_Descr_type, UDELTA5_spec, INDEX(CONSTANT_Signature)), + BAND_INIT(cp_Field_class, DELTA5_spec, INDEX(CONSTANT_Class)), + BAND_INIT(cp_Field_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)), + BAND_INIT(cp_Method_class, DELTA5_spec, INDEX(CONSTANT_Class)), + BAND_INIT(cp_Method_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)), + BAND_INIT(cp_Imethod_class, DELTA5_spec, INDEX(CONSTANT_Class)), + BAND_INIT(cp_Imethod_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)), + BAND_INIT(attr_definition_headers, BYTE1_spec, 0), + BAND_INIT(attr_definition_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)), + BAND_INIT(attr_definition_layout, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)), + BAND_INIT(ic_this_class, UDELTA5_spec, INDEX(CONSTANT_Class)), + BAND_INIT(ic_flags, UNSIGNED5_spec, 0), + BAND_INIT(ic_outer_class, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Class)), + BAND_INIT(ic_name, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Utf8)), + BAND_INIT(class_this, DELTA5_spec, INDEX(CONSTANT_Class)), + BAND_INIT(class_super, DELTA5_spec, INDEX(CONSTANT_Class)), + BAND_INIT(class_interface_count, DELTA5_spec, 0), + BAND_INIT(class_interface, DELTA5_spec, INDEX(CONSTANT_Class)), + BAND_INIT(class_field_count, DELTA5_spec, 0), + BAND_INIT(class_method_count, DELTA5_spec, 0), + BAND_INIT(field_descr, DELTA5_spec, INDEX(CONSTANT_NameandType)), + BAND_INIT(field_flags_hi, UNSIGNED5_spec, 0), + BAND_INIT(field_flags_lo, UNSIGNED5_spec, 0), + BAND_INIT(field_attr_count, UNSIGNED5_spec, 0), + BAND_INIT(field_attr_indexes, UNSIGNED5_spec, 0), + BAND_INIT(field_attr_calls, UNSIGNED5_spec, 0), + BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_Literal)), + BAND_INIT(field_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)), + BAND_INIT(field_metadata_bands, -1, -1), BAND_INIT(field_attr_bands, -1, -1), + BAND_INIT(method_descr, MDELTA5_spec, INDEX(CONSTANT_NameandType)), + BAND_INIT(method_flags_hi, UNSIGNED5_spec, 0), + BAND_INIT(method_flags_lo, UNSIGNED5_spec, 0), + BAND_INIT(method_attr_count, UNSIGNED5_spec, 0), + BAND_INIT(method_attr_indexes, UNSIGNED5_spec, 0), + BAND_INIT(method_attr_calls, UNSIGNED5_spec, 0), + BAND_INIT(method_Exceptions_N, UNSIGNED5_spec, 0), + BAND_INIT(method_Exceptions_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)), + BAND_INIT(method_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)), + BAND_INIT(method_metadata_bands, -1, -1), BAND_INIT(method_attr_bands, -1, -1), + BAND_INIT(class_flags_hi, UNSIGNED5_spec, 0), + BAND_INIT(class_flags_lo, UNSIGNED5_spec, 0), + BAND_INIT(class_attr_count, UNSIGNED5_spec, 0), + BAND_INIT(class_attr_indexes, UNSIGNED5_spec, 0), + BAND_INIT(class_attr_calls, UNSIGNED5_spec, 0), + BAND_INIT(class_SourceFile_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)), + BAND_INIT(class_EnclosingMethod_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)), + BAND_INIT(class_EnclosingMethod_RDN, UNSIGNED5_spec, + NULL_OR_INDEX(CONSTANT_NameandType)), + BAND_INIT(class_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)), + BAND_INIT(class_metadata_bands, -1, -1), + BAND_INIT(class_InnerClasses_N, UNSIGNED5_spec, 0), + BAND_INIT(class_InnerClasses_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)), + BAND_INIT(class_InnerClasses_F, UNSIGNED5_spec, 0), + BAND_INIT(class_InnerClasses_outer_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)), + BAND_INIT(class_InnerClasses_name_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)), + BAND_INIT(class_ClassFile_version_minor_H, UNSIGNED5_spec, 0), + BAND_INIT(class_ClassFile_version_major_H, UNSIGNED5_spec, 0), + BAND_INIT(class_attr_bands, -1, -1), BAND_INIT(code_headers, BYTE1_spec, 0), + BAND_INIT(code_max_stack, UNSIGNED5_spec, 0), + BAND_INIT(code_max_na_locals, UNSIGNED5_spec, 0), + BAND_INIT(code_handler_count, UNSIGNED5_spec, 0), + BAND_INIT(code_handler_start_P, BCI5_spec, 0), + BAND_INIT(code_handler_end_PO, BRANCH5_spec, 0), + BAND_INIT(code_handler_catch_PO, BRANCH5_spec, 0), + BAND_INIT(code_handler_class_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)), + BAND_INIT(code_flags_hi, UNSIGNED5_spec, 0), + BAND_INIT(code_flags_lo, UNSIGNED5_spec, 0), + BAND_INIT(code_attr_count, UNSIGNED5_spec, 0), + BAND_INIT(code_attr_indexes, UNSIGNED5_spec, 0), + BAND_INIT(code_attr_calls, UNSIGNED5_spec, 0), + BAND_INIT(code_StackMapTable_N, UNSIGNED5_spec, 0), + BAND_INIT(code_StackMapTable_frame_T, BYTE1_spec, 0), + BAND_INIT(code_StackMapTable_local_N, UNSIGNED5_spec, 0), + BAND_INIT(code_StackMapTable_stack_N, UNSIGNED5_spec, 0), + BAND_INIT(code_StackMapTable_offset, UNSIGNED5_spec, 0), + BAND_INIT(code_StackMapTable_T, BYTE1_spec, 0), + BAND_INIT(code_StackMapTable_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)), + BAND_INIT(code_StackMapTable_P, BCI5_spec, 0), + BAND_INIT(code_LineNumberTable_N, UNSIGNED5_spec, 0), + BAND_INIT(code_LineNumberTable_bci_P, BCI5_spec, 0), + BAND_INIT(code_LineNumberTable_line, UNSIGNED5_spec, 0), + BAND_INIT(code_LocalVariableTable_N, UNSIGNED5_spec, 0), + BAND_INIT(code_LocalVariableTable_bci_P, BCI5_spec, 0), + BAND_INIT(code_LocalVariableTable_span_O, BRANCH5_spec, 0), + BAND_INIT(code_LocalVariableTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)), + BAND_INIT(code_LocalVariableTable_type_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)), + BAND_INIT(code_LocalVariableTable_slot, UNSIGNED5_spec, 0), + BAND_INIT(code_LocalVariableTypeTable_N, UNSIGNED5_spec, 0), + BAND_INIT(code_LocalVariableTypeTable_bci_P, BCI5_spec, 0), + BAND_INIT(code_LocalVariableTypeTable_span_O, BRANCH5_spec, 0), + BAND_INIT(code_LocalVariableTypeTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)), + BAND_INIT(code_LocalVariableTypeTable_type_RS, UNSIGNED5_spec, + INDEX(CONSTANT_Signature)), + BAND_INIT(code_LocalVariableTypeTable_slot, UNSIGNED5_spec, 0), + BAND_INIT(code_attr_bands, -1, -1), BAND_INIT(bc_codes, BYTE1_spec, 0), + BAND_INIT(bc_case_count, UNSIGNED5_spec, 0), BAND_INIT(bc_case_value, DELTA5_spec, 0), + BAND_INIT(bc_byte, BYTE1_spec, 0), BAND_INIT(bc_short, DELTA5_spec, 0), + BAND_INIT(bc_local, UNSIGNED5_spec, 0), BAND_INIT(bc_label, BRANCH5_spec, 0), + BAND_INIT(bc_intref, DELTA5_spec, INDEX(CONSTANT_Integer)), + BAND_INIT(bc_floatref, DELTA5_spec, INDEX(CONSTANT_Float)), + BAND_INIT(bc_longref, DELTA5_spec, INDEX(CONSTANT_Long)), + BAND_INIT(bc_doubleref, DELTA5_spec, INDEX(CONSTANT_Double)), + BAND_INIT(bc_stringref, DELTA5_spec, INDEX(CONSTANT_String)), + BAND_INIT(bc_classref, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)), + BAND_INIT(bc_fieldref, DELTA5_spec, INDEX(CONSTANT_Fieldref)), + BAND_INIT(bc_methodref, UNSIGNED5_spec, INDEX(CONSTANT_Methodref)), + BAND_INIT(bc_imethodref, DELTA5_spec, INDEX(CONSTANT_InterfaceMethodref)), + BAND_INIT(bc_thisfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)), + BAND_INIT(bc_superfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)), + BAND_INIT(bc_thismethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)), + BAND_INIT(bc_supermethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)), + BAND_INIT(bc_initref, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)), + BAND_INIT(bc_escref, UNSIGNED5_spec, INDEX(CONSTANT_All)), + BAND_INIT(bc_escrefsize, UNSIGNED5_spec, 0), BAND_INIT(bc_escsize, UNSIGNED5_spec, 0), + BAND_INIT(bc_escbyte, BYTE1_spec, 0), + BAND_INIT(file_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)), + BAND_INIT(file_size_hi, UNSIGNED5_spec, 0), BAND_INIT(file_size_lo, UNSIGNED5_spec, 0), + BAND_INIT(file_modtime, DELTA5_spec, 0), BAND_INIT(file_options, UNSIGNED5_spec, 0), + // BAND_INIT(file_bits, BYTE1_spec, 0), + {0, 0}}; + +band *band::makeBands(unpacker *u) +{ + band *tmp_all_bands = U_NEW(band, BAND_LIMIT); + for (int i = 0; i < BAND_LIMIT; i++) + { + assert((byte *)&all_band_inits[i + 1] < + (byte *)all_band_inits + sizeof(all_band_inits)); + const band_init &bi = all_band_inits[i]; + band &b = tmp_all_bands[i]; + coding *defc = coding::findBySpec(bi.defc); + assert((defc == nullptr) == (bi.defc == -1)); // no garbage, please + assert(defc == nullptr || !defc->isMalloc); + b.init(u, i, defc); + if (bi.index > 0) + { + b.nullOK = ((bi.index >> 8) & 1); + b.ixTag = (bi.index & 0xFF); + } + } + return tmp_all_bands; +} + +void band::initIndexes(unpacker *u) +{ + band *tmp_all_bands = u->all_bands; + for (int i = 0; i < BAND_LIMIT; i++) + { + band *scan = &tmp_all_bands[i]; + uint32_t tag = scan->ixTag; // Cf. #define INDEX(tag) above + if (tag != 0 && tag != CONSTANT_Literal && (tag & SUBINDEX_BIT) == 0) + { + scan->setIndex(u->cp.getIndex(tag)); + } + } +} diff --git a/libraries/pack200/src/bands.h b/libraries/pack200/src/bands.h new file mode 100644 index 00000000..a56cd7d5 --- /dev/null +++ b/libraries/pack200/src/bands.h @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// -*- C++ -*- +struct entry; +struct cpindex; +struct unpacker; + +struct band +{ + int bn; // band_number of this band + coding *defc; // default coding method + cpindex *ix; // CP entry mapping, if CPRefBand + byte ixTag; // 0 or 1; nullptr is coded as (nullOK?0:-1) + byte nullOK; // 0 or 1; nullptr is coded as (nullOK?0:-1) + int length; // expected # values + unpacker *u; // back pointer + + value_stream vs[2]; // source of values + coding_method cm; // method used for initial state of vs[0] + byte *rplimit; // end of band (encoded, transmitted) + + int total_memo; // cached value of getIntTotal, or -1 + int *hist0; // approximate. histogram + enum + { + HIST0_MIN = 0, + HIST0_MAX = 255 + }; // catches the usual cases + + // properties for attribute layout elements: + byte le_kind; // EK_XXX + byte le_bci; // 0,EK_BCI,EK_BCD,EK_BCO + byte le_back; // ==EF_BACK + byte le_len; // 0,1,2,4 (size in classfile), or call addr + band **le_body; // body of repl, union, call (nullptr-terminated) +// Note: EK_CASE elements use hist0 to record union tags. +#define le_casetags hist0 + + band &nextBand() + { + return this[1]; + } + band &prevBand() + { + return this[-1]; + } + + void init(unpacker *u_, int bn_, coding *defc_) + { + u = u_; + cm.u = u_; + bn = bn_; + defc = defc_; + } + void init(unpacker *u_, int bn_, int defcSpec) + { + init(u_, bn_, coding::findBySpec(defcSpec)); + } + void initRef(int ixTag_ = 0, bool nullOK_ = false) + { + ixTag = ixTag_; + nullOK = nullOK_; + setIndexByTag(ixTag); + } + + void expectMoreLength(int l) + { + assert(length >= 0); // able to accept a length + assert((int)l >= 0); // no overflow + assert(rplimit == nullptr); // readData not yet called + length += l; + assert(length >= l); // no overflow + } + + void setIndex(cpindex *ix_); + void setIndexByTag(byte tag); + + // Parse the band and its meta-coding header. + void readData(int expectedLength = 0); + + // Reset the band for another pass (Cf. Java Band.resetForSecondPass.) + void rewind() + { + cm.reset(&vs[0]); + } + + byte *&curRP() + { + return vs[0].rp; + } + byte *minRP() + { + return cm.vs0.rp; + } + byte *maxRP() + { + return rplimit; + } + size_t size() + { + return maxRP() - minRP(); + } + + int getByte() + { + assert(ix == nullptr); + return vs[0].getByte(); + } + int getInt() + { + assert(ix == nullptr); + return vs[0].getInt(); + } + entry *getRefN() + { + assert(ix != nullptr); + return getRefCommon(ix, true); + } + entry *getRef() + { + assert(ix != nullptr); + return getRefCommon(ix, false); + } + entry *getRefUsing(cpindex *ix2) + { + assert(ix == nullptr); + return getRefCommon(ix2, true); + } + entry *getRefCommon(cpindex *ix, bool nullOK); + int64_t getLong(band &lo_band, bool have_hi); + + static int64_t makeLong(uint32_t hi, uint32_t lo) + { + return ((uint64_t)hi << 32) + (((uint64_t)lo << 32) >> 32); + } + + int getIntTotal(); + int getIntCount(int tag); + + static band *makeBands(unpacker *u); + static void initIndexes(unpacker *u); +}; + +extern band all_bands[]; + +#define BAND_LOCAL /* \ + band* band_temp = all_bands; \ + band* all_bands = band_temp */ + +// Band schema: +enum band_number +{ + // e_archive_magic, + // e_archive_header, + // e_band_headers, + + // constant pool contents + e_cp_Utf8_prefix, + e_cp_Utf8_suffix, + e_cp_Utf8_chars, + e_cp_Utf8_big_suffix, + e_cp_Utf8_big_chars, + e_cp_Int, + e_cp_Float, + e_cp_Long_hi, + e_cp_Long_lo, + e_cp_Double_hi, + e_cp_Double_lo, + e_cp_String, + e_cp_Class, + e_cp_Signature_form, + e_cp_Signature_classes, + e_cp_Descr_name, + e_cp_Descr_type, + e_cp_Field_class, + e_cp_Field_desc, + e_cp_Method_class, + e_cp_Method_desc, + e_cp_Imethod_class, + e_cp_Imethod_desc, + + // bands which define transmission of attributes + e_attr_definition_headers, + e_attr_definition_name, + e_attr_definition_layout, + + // band for hardwired InnerClasses attribute (shared across the package) + e_ic_this_class, + e_ic_flags, + // These bands contain data only where flags sets ACC_IC_LONG_FORM: + e_ic_outer_class, + e_ic_name, + + // bands for carrying class schema information: + e_class_this, + e_class_super, + e_class_interface_count, + e_class_interface, + + // bands for class members + e_class_field_count, + e_class_method_count, + e_field_descr, + e_field_flags_hi, + e_field_flags_lo, + e_field_attr_count, + e_field_attr_indexes, + e_field_attr_calls, + e_field_ConstantValue_KQ, + e_field_Signature_RS, + e_field_metadata_bands, + e_field_attr_bands, + e_method_descr, + e_method_flags_hi, + e_method_flags_lo, + e_method_attr_count, + e_method_attr_indexes, + e_method_attr_calls, + e_method_Exceptions_N, + e_method_Exceptions_RC, + e_method_Signature_RS, + e_method_metadata_bands, + e_method_attr_bands, + e_class_flags_hi, + e_class_flags_lo, + e_class_attr_count, + e_class_attr_indexes, + e_class_attr_calls, + e_class_SourceFile_RUN, + e_class_EnclosingMethod_RC, + e_class_EnclosingMethod_RDN, + e_class_Signature_RS, + e_class_metadata_bands, + e_class_InnerClasses_N, + e_class_InnerClasses_RC, + e_class_InnerClasses_F, + e_class_InnerClasses_outer_RCN, + e_class_InnerClasses_name_RUN, + e_class_ClassFile_version_minor_H, + e_class_ClassFile_version_major_H, + e_class_attr_bands, + e_code_headers, + e_code_max_stack, + e_code_max_na_locals, + e_code_handler_count, + e_code_handler_start_P, + e_code_handler_end_PO, + e_code_handler_catch_PO, + e_code_handler_class_RCN, + + // code attributes + e_code_flags_hi, + e_code_flags_lo, + e_code_attr_count, + e_code_attr_indexes, + e_code_attr_calls, + e_code_StackMapTable_N, + e_code_StackMapTable_frame_T, + e_code_StackMapTable_local_N, + e_code_StackMapTable_stack_N, + e_code_StackMapTable_offset, + e_code_StackMapTable_T, + e_code_StackMapTable_RC, + e_code_StackMapTable_P, + e_code_LineNumberTable_N, + e_code_LineNumberTable_bci_P, + e_code_LineNumberTable_line, + e_code_LocalVariableTable_N, + e_code_LocalVariableTable_bci_P, + e_code_LocalVariableTable_span_O, + e_code_LocalVariableTable_name_RU, + e_code_LocalVariableTable_type_RS, + e_code_LocalVariableTable_slot, + e_code_LocalVariableTypeTable_N, + e_code_LocalVariableTypeTable_bci_P, + e_code_LocalVariableTypeTable_span_O, + e_code_LocalVariableTypeTable_name_RU, + e_code_LocalVariableTypeTable_type_RS, + e_code_LocalVariableTypeTable_slot, + e_code_attr_bands, + + // bands for bytecodes + e_bc_codes, + // remaining bands provide typed opcode fields required by the bc_codes + e_bc_case_count, + e_bc_case_value, + e_bc_byte, + e_bc_short, + e_bc_local, + e_bc_label, + + // ldc* operands: + e_bc_intref, + e_bc_floatref, + e_bc_longref, + e_bc_doubleref, + e_bc_stringref, + e_bc_classref, + e_bc_fieldref, + e_bc_methodref, + e_bc_imethodref, + + // _self_linker_op family + e_bc_thisfield, + e_bc_superfield, + e_bc_thismethod, + e_bc_supermethod, + + // bc_invokeinit family: + e_bc_initref, + + // bytecode escape sequences + e_bc_escref, + e_bc_escrefsize, + e_bc_escsize, + e_bc_escbyte, + + // file attributes and contents + e_file_name, + e_file_size_hi, + e_file_size_lo, + e_file_modtime, + e_file_options, + // e_file_bits, // handled specially as an appendix + BAND_LIMIT +}; + +// Symbolic names for bands, as if in a giant global struct: +//#define archive_magic all_bands[e_archive_magic] +//#define archive_header all_bands[e_archive_header] +//#define band_headers all_bands[e_band_headers] +#define cp_Utf8_prefix all_bands[e_cp_Utf8_prefix] +#define cp_Utf8_suffix all_bands[e_cp_Utf8_suffix] +#define cp_Utf8_chars all_bands[e_cp_Utf8_chars] +#define cp_Utf8_big_suffix all_bands[e_cp_Utf8_big_suffix] +#define cp_Utf8_big_chars all_bands[e_cp_Utf8_big_chars] +#define cp_Int all_bands[e_cp_Int] +#define cp_Float all_bands[e_cp_Float] +#define cp_Long_hi all_bands[e_cp_Long_hi] +#define cp_Long_lo all_bands[e_cp_Long_lo] +#define cp_Double_hi all_bands[e_cp_Double_hi] +#define cp_Double_lo all_bands[e_cp_Double_lo] +#define cp_String all_bands[e_cp_String] +#define cp_Class all_bands[e_cp_Class] +#define cp_Signature_form all_bands[e_cp_Signature_form] +#define cp_Signature_classes all_bands[e_cp_Signature_classes] +#define cp_Descr_name all_bands[e_cp_Descr_name] +#define cp_Descr_type all_bands[e_cp_Descr_type] +#define cp_Field_class all_bands[e_cp_Field_class] +#define cp_Field_desc all_bands[e_cp_Field_desc] +#define cp_Method_class all_bands[e_cp_Method_class] +#define cp_Method_desc all_bands[e_cp_Method_desc] +#define cp_Imethod_class all_bands[e_cp_Imethod_class] +#define cp_Imethod_desc all_bands[e_cp_Imethod_desc] +#define attr_definition_headers all_bands[e_attr_definition_headers] +#define attr_definition_name all_bands[e_attr_definition_name] +#define attr_definition_layout all_bands[e_attr_definition_layout] +#define ic_this_class all_bands[e_ic_this_class] +#define ic_flags all_bands[e_ic_flags] +#define ic_outer_class all_bands[e_ic_outer_class] +#define ic_name all_bands[e_ic_name] +#define class_this all_bands[e_class_this] +#define class_super all_bands[e_class_super] +#define class_interface_count all_bands[e_class_interface_count] +#define class_interface all_bands[e_class_interface] +#define class_field_count all_bands[e_class_field_count] +#define class_method_count all_bands[e_class_method_count] +#define field_descr all_bands[e_field_descr] +#define field_flags_hi all_bands[e_field_flags_hi] +#define field_flags_lo all_bands[e_field_flags_lo] +#define field_attr_count all_bands[e_field_attr_count] +#define field_attr_indexes all_bands[e_field_attr_indexes] +#define field_ConstantValue_KQ all_bands[e_field_ConstantValue_KQ] +#define field_Signature_RS all_bands[e_field_Signature_RS] +#define field_attr_bands all_bands[e_field_attr_bands] +#define method_descr all_bands[e_method_descr] +#define method_flags_hi all_bands[e_method_flags_hi] +#define method_flags_lo all_bands[e_method_flags_lo] +#define method_attr_count all_bands[e_method_attr_count] +#define method_attr_indexes all_bands[e_method_attr_indexes] +#define method_Exceptions_N all_bands[e_method_Exceptions_N] +#define method_Exceptions_RC all_bands[e_method_Exceptions_RC] +#define method_Signature_RS all_bands[e_method_Signature_RS] +#define method_attr_bands all_bands[e_method_attr_bands] +#define class_flags_hi all_bands[e_class_flags_hi] +#define class_flags_lo all_bands[e_class_flags_lo] +#define class_attr_count all_bands[e_class_attr_count] +#define class_attr_indexes all_bands[e_class_attr_indexes] +#define class_SourceFile_RUN all_bands[e_class_SourceFile_RUN] +#define class_EnclosingMethod_RC all_bands[e_class_EnclosingMethod_RC] +#define class_EnclosingMethod_RDN all_bands[e_class_EnclosingMethod_RDN] +#define class_Signature_RS all_bands[e_class_Signature_RS] +#define class_InnerClasses_N all_bands[e_class_InnerClasses_N] +#define class_InnerClasses_RC all_bands[e_class_InnerClasses_RC] +#define class_InnerClasses_F all_bands[e_class_InnerClasses_F] +#define class_InnerClasses_outer_RCN all_bands[e_class_InnerClasses_outer_RCN] +#define class_InnerClasses_name_RUN all_bands[e_class_InnerClasses_name_RUN] +#define class_ClassFile_version_minor_H all_bands[e_class_ClassFile_version_minor_H] +#define class_ClassFile_version_major_H all_bands[e_class_ClassFile_version_major_H] +#define class_attr_bands all_bands[e_class_attr_bands] +#define code_headers all_bands[e_code_headers] +#define code_max_stack all_bands[e_code_max_stack] +#define code_max_na_locals all_bands[e_code_max_na_locals] +#define code_handler_count all_bands[e_code_handler_count] +#define code_handler_start_P all_bands[e_code_handler_start_P] +#define code_handler_end_PO all_bands[e_code_handler_end_PO] +#define code_handler_catch_PO all_bands[e_code_handler_catch_PO] +#define code_handler_class_RCN all_bands[e_code_handler_class_RCN] +#define code_flags_hi all_bands[e_code_flags_hi] +#define code_flags_lo all_bands[e_code_flags_lo] +#define code_attr_count all_bands[e_code_attr_count] +#define code_attr_indexes all_bands[e_code_attr_indexes] +#define code_StackMapTable_N all_bands[e_code_StackMapTable_N] +#define code_StackMapTable_frame_T all_bands[e_code_StackMapTable_frame_T] +#define code_StackMapTable_local_N all_bands[e_code_StackMapTable_local_N] +#define code_StackMapTable_stack_N all_bands[e_code_StackMapTable_stack_N] +#define code_StackMapTable_offset all_bands[e_code_StackMapTable_offset] +#define code_StackMapTable_T all_bands[e_code_StackMapTable_T] +#define code_StackMapTable_RC all_bands[e_code_StackMapTable_RC] +#define code_StackMapTable_P all_bands[e_code_StackMapTable_P] +#define code_LineNumberTable_N all_bands[e_code_LineNumberTable_N] +#define code_LineNumberTable_bci_P all_bands[e_code_LineNumberTable_bci_P] +#define code_LineNumberTable_line all_bands[e_code_LineNumberTable_line] +#define code_LocalVariableTable_N all_bands[e_code_LocalVariableTable_N] +#define code_LocalVariableTable_bci_P all_bands[e_code_LocalVariableTable_bci_P] +#define code_LocalVariableTable_span_O all_bands[e_code_LocalVariableTable_span_O] +#define code_LocalVariableTable_name_RU all_bands[e_code_LocalVariableTable_name_RU] +#define code_LocalVariableTable_type_RS all_bands[e_code_LocalVariableTable_type_RS] +#define code_LocalVariableTable_slot all_bands[e_code_LocalVariableTable_slot] +#define code_LocalVariableTypeTable_N all_bands[e_code_LocalVariableTypeTable_N] +#define code_LocalVariableTypeTable_bci_P all_bands[e_code_LocalVariableTypeTable_bci_P] +#define code_LocalVariableTypeTable_span_O all_bands[e_code_LocalVariableTypeTable_span_O] +#define code_LocalVariableTypeTable_name_RU all_bands[e_code_LocalVariableTypeTable_name_RU] +#define code_LocalVariableTypeTable_type_RS all_bands[e_code_LocalVariableTypeTable_type_RS] +#define code_LocalVariableTypeTable_slot all_bands[e_code_LocalVariableTypeTable_slot] +#define code_attr_bands all_bands[e_code_attr_bands] +#define bc_codes all_bands[e_bc_codes] +#define bc_case_count all_bands[e_bc_case_count] +#define bc_case_value all_bands[e_bc_case_val |
