Compression algo dependencies, still need hackery...

This commit is contained in:
Petr Mrázek
2013-09-26 02:58:09 +02:00
parent af234f3502
commit 2c8dc0b855
52 changed files with 17769 additions and 40 deletions

View File

@ -0,0 +1,451 @@
/*
* 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 "defines.h"
#include "bytes.h"
#include "utils.h"
#include "coding.h"
#include "bands.h"
#include "constants.h"
#include "unpack.h"
inline void band::abort(const char *msg)
{
u->abort(msg);
}
inline bool band::aborting()
{
return u->aborting();
}
void band::readData(int expectedLength)
{
CHECK;
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)
jlong generous = (jlong)length * (B_MAX * 3 + 1) + C_SLOP;
u->ensure_input(generous);
}
// Read one value to see what it might be.
int XB = _meta_default;
int cp1 = 0, cp2 = 0;
if (!is_BYTE1)
{
// must be a variable-length coding
assert(defc->B() > 1 && defc->L() > 0);
// must have already read from previous band:
assert(bn >= BAND_LIMIT || bn <= 0 || bn == e_cp_Utf8_big_chars ||
endsWith(name, "_lo") // preceded by _hi conditional band
||
bn == e_file_options // preceded by conditional band
||
u->rp == u->all_bands[bn - 1].maxRP() || u->all_bands[bn - 1].defc == nullptr);
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);
CHECK;
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;
cp1 = 1;
}
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);
CHECK;
}
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)
{
CHECK_0;
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))
abort(n == -1 ? "nullptr ref" : "bad ref");
return ref;
}
jlong band::getLong(band &lo_band, bool have_hi)
{
band &hi_band = (*this);
assert(lo_band.bn == hi_band.bn + 1);
uint lo = lo_band.getInt();
if (!have_hi)
{
assert(hi_band.length == 0);
return makeLong(0, lo);
}
uint hi = hi_band.getInt();
return makeLong(hi, lo);
}
int band::getIntTotal()
{
CHECK_0;
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)
{
abort("overflow detected");
return 0;
}
for (int k = length - 1; k > 0; k--)
{
int prev_total = total;
total += vs[0].getInt();
if (total < prev_total)
{
abort("overflow detected");
return 0;
}
}
rewind();
total_memo = total + 1;
return total;
}
int band::getIntCount(int tag)
{
CHECK_0;
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);
CHECK_0;
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}};
#define NUM_BAND_INITS (sizeof(all_band_inits) / sizeof(all_band_inits[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);
assert(bi.bn == i); // band array consistent w/ band enum
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];
uint tag = scan->ixTag; // Cf. #define INDEX(tag) above
if (tag != 0 && tag != CONSTANT_Literal && (tag & SUBINDEX_BIT) == 0)
{
scan->setIndex(u->cp.getIndex(tag));
}
}
}

492
depends/pack200/src/bands.h Normal file
View File

@ -0,0 +1,492 @@
/*
* 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);
jlong getLong(band &lo_band, bool have_hi);
static jlong makeLong(uint hi, uint lo)
{
return ((julong)hi << 32) + (((julong)lo << 32) >> 32);
}
int getIntTotal();
int getIntCount(int tag);
static band *makeBands(unpacker *u);
static void initIndexes(unpacker *u);
void abort(const char *msg = nullptr); //{ u->abort(msg); }
bool aborting(); //{ return u->aborting(); }
};
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_value]
#define bc_byte all_bands[e_bc_byte]
#define bc_short all_bands[e_bc_short]
#define bc_local all_bands[e_bc_local]
#define bc_label all_bands[e_bc_label]
#define bc_intref all_bands[e_bc_intref]
#define bc_floatref all_bands[e_bc_floatref]
#define bc_longref all_bands[e_bc_longref]
#define bc_doubleref all_bands[e_bc_doubleref]
#define bc_stringref all_bands[e_bc_stringref]
#define bc_classref all_bands[e_bc_classref]
#define bc_fieldref all_bands[e_bc_fieldref]
#define bc_methodref all_bands[e_bc_methodref]
#define bc_imethodref all_bands[e_bc_imethodref]
#define bc_thisfield all_bands[e_bc_thisfield]
#define bc_superfield all_bands[e_bc_superfield]
#define bc_thismethod all_bands[e_bc_thismethod]
#define bc_supermethod all_bands[e_bc_supermethod]
#define bc_initref all_bands[e_bc_initref]
#define bc_escref all_bands[e_bc_escref]
#define bc_escrefsize all_bands[e_bc_escrefsize]
#define bc_escsize all_bands[e_bc_escsize]
#define bc_escbyte all_bands[e_bc_escbyte]
#define file_name all_bands[e_file_name]
#define file_size_hi all_bands[e_file_size_hi]
#define file_size_lo all_bands[e_file_size_lo]
#define file_modtime all_bands[e_file_modtime]
#define file_options all_bands[e_file_options]

View File

@ -0,0 +1,217 @@
/*
* Copyright (c) 2001, 2010, 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "defines.h"
#include "bytes.h"
#include "utils.h"
static byte dummy[1 << 10];
bool bytes::inBounds(const void *p)
{
return p >= ptr && p < limit();
}
void bytes::malloc(size_t len_)
{
len = len_;
ptr = NEW(byte, add_size(len_, 1)); // add trailing zero byte always
if (ptr == nullptr)
{
// set ptr to some victim memory, to ease escape
set(dummy, sizeof(dummy) - 1);
unpack_abort(ERROR_ENOMEM);
}
}
void bytes::realloc(size_t len_)
{
if (len == len_)
return; // nothing to do
if (ptr == dummy)
return; // escaping from an error
if (ptr == nullptr)
{
malloc(len_);
return;
}
byte *oldptr = ptr;
ptr = (len_ >= PSIZE_MAX) ? nullptr : (byte *)::realloc(ptr, add_size(len_, 1));
if (ptr != nullptr)
{
if (len < len_)
memset(ptr + len, 0, len_ - len);
ptr[len_] = 0;
len = len_;
}
else
{
ptr = oldptr; // ease our escape
unpack_abort(ERROR_ENOMEM);
}
}
void bytes::free()
{
if (ptr == dummy)
return; // escaping from an error
if (ptr != nullptr)
{
::free(ptr);
}
len = 0;
ptr = 0;
}
int bytes::indexOf(byte c)
{
byte *p = (byte *)memchr(ptr, c, len);
return (p == 0) ? -1 : (int)(p - ptr);
}
byte *bytes::writeTo(byte *bp)
{
memcpy(bp, ptr, len);
return bp + len;
}
int bytes::compareTo(bytes &other)
{
size_t l1 = len;
size_t l2 = other.len;
int cmp = memcmp(ptr, other.ptr, (l1 < l2) ? l1 : l2);
if (cmp != 0)
return cmp;
return (l1 < l2) ? -1 : (l1 > l2) ? 1 : 0;
}
void bytes::saveFrom(const void *ptr_, size_t len_)
{
malloc(len_);
// Save as much as possible. (Helps unpacker::abort.)
if (len_ > len)
{
assert(ptr == dummy); // error recovery
len_ = len;
}
copyFrom(ptr_, len_);
}
//#TODO: Need to fix for exception handling
void bytes::copyFrom(const void *ptr_, size_t len_, size_t offset)
{
assert(len_ == 0 || inBounds(ptr + offset));
assert(len_ == 0 || inBounds(ptr + offset + len_ - 1));
memcpy(ptr + offset, ptr_, len_);
}
// Make sure there are 'o' bytes beyond the fill pointer,
// advance the fill pointer, and return the old fill pointer.
byte *fillbytes::grow(size_t s)
{
size_t nlen = add_size(b.len, s);
if (nlen <= allocated)
{
b.len = nlen;
return limit() - s;
}
size_t maxlen = nlen;
if (maxlen < 128)
maxlen = 128;
if (maxlen < allocated * 2)
maxlen = allocated * 2;
if (allocated == 0)
{
// Initial buffer was not malloced. Do not reallocate it.
bytes old = b;
b.malloc(maxlen);
if (b.len == maxlen)
old.writeTo(b.ptr);
}
else
{
b.realloc(maxlen);
}
allocated = b.len;
if (allocated != maxlen)
{
assert(unpack_aborting());
b.len = nlen - s; // back up
return dummy; // scribble during error recov.
}
// after realloc, recompute pointers
b.len = nlen;
assert(b.len <= allocated);
return limit() - s;
}
void fillbytes::ensureSize(size_t s)
{
if (allocated >= s)
return;
size_t len0 = b.len;
grow(s - size());
b.len = len0; // put it back
}
int ptrlist::indexOf(const void *x)
{
int len = length();
for (int i = 0; i < len; i++)
{
if (get(i) == x)
return i;
}
return -1;
}
void ptrlist::freeAll()
{
int len = length();
for (int i = 0; i < len; i++)
{
void *p = (void *)get(i);
if (p != nullptr)
{
::free(p);
}
}
free();
}
int intlist::indexOf(int x)
{
int len = length();
for (int i = 0; i < len; i++)
{
if (get(i) == x)
return i;
}
return -1;
}

284
depends/pack200/src/bytes.h Normal file
View File

@ -0,0 +1,284 @@
/*
* Copyright (c) 2001, 2008, 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.
*/
struct bytes
{
int8_t *ptr;
size_t len;
int8_t *limit()
{
return ptr + len;
}
void set(int8_t *ptr_, size_t len_)
{
ptr = ptr_;
len = len_;
}
void set(const char *str)
{
ptr = (int8_t *)str;
len = strlen(str);
}
bool inBounds(const void *p); // p in [ptr, limit)
void malloc(size_t len_);
void realloc(size_t len_);
void free();
void copyFrom(const void *ptr_, size_t len_, size_t offset = 0);
void saveFrom(const void *ptr_, size_t len_);
void saveFrom(const char *str)
{
saveFrom(str, strlen(str));
}
void copyFrom(bytes &other, size_t offset = 0)
{
copyFrom(other.ptr, other.len, offset);
}
void saveFrom(bytes &other)
{
saveFrom(other.ptr, other.len);
}
void clear(int fill_byte = 0)
{
memset(ptr, fill_byte, len);
}
int8_t *writeTo(int8_t *bp);
bool equals(bytes &other)
{
return 0 == compareTo(other);
}
int compareTo(bytes &other);
bool contains(int8_t c)
{
return indexOf(c) >= 0;
}
int indexOf(int8_t c);
// substrings:
static bytes of(int8_t *ptr, size_t len)
{
bytes res;
res.set(ptr, len);
return res;
}
bytes slice(size_t beg, size_t end)
{
bytes res;
res.ptr = ptr + beg;
res.len = end - beg;
assert(res.len == 0 || inBounds(res.ptr) && inBounds(res.limit() - 1));
return res;
}
// building C strings inside byte buffers:
bytes &strcat(const char *str)
{
::strcat((char *)ptr, str);
return *this;
}
bytes &strcat(bytes &other)
{
::strncat((char *)ptr, (char *)other.ptr, other.len);
return *this;
}
char *strval()
{
assert(strlen((char *)ptr) == len);
return (char *)ptr;
}
};
#define BYTES_OF(var) (bytes::of((int8_t *)&(var), sizeof(var)))
struct fillbytes
{
bytes b;
size_t allocated;
int8_t *base()
{
return b.ptr;
}
size_t size()
{
return b.len;
}
int8_t *limit()
{
return b.limit();
} // logical limit
void setLimit(int8_t *lp)
{
assert(isAllocated(lp));
b.len = lp - b.ptr;
}
int8_t *end()
{
return b.ptr + allocated;
} // physical limit
int8_t *loc(size_t o)
{
assert(o < b.len);
return b.ptr + o;
}
void init()
{
allocated = 0;
b.set(nullptr, 0);
}
void init(size_t s)
{
init();
ensureSize(s);
}
void free()
{
if (allocated != 0)
b.free();
allocated = 0;
}
void empty()
{
b.len = 0;
}
int8_t *grow(size_t s); // grow so that limit() += s
int getByte(uint i)
{
return *loc(i) & 0xFF;
}
void addByte(int8_t x)
{
*grow(1) = x;
}
void ensureSize(size_t s); // make sure allocated >= s
void trimToSize()
{
if (allocated > size())
b.realloc(allocated = size());
}
bool canAppend(size_t s)
{
return allocated > b.len + s;
}
bool isAllocated(int8_t *p)
{
return p >= base() && p <= end();
} // asserts
void set(bytes &src)
{
set(src.ptr, src.len);
}
void set(int8_t *ptr, size_t len)
{
b.set(ptr, len);
allocated = 0; // mark as not reallocatable
}
// block operations on resizing byte buffer:
fillbytes &append(const void *ptr_, size_t len_)
{
memcpy(grow(len_), ptr_, len_);
return (*this);
}
fillbytes &append(bytes &other)
{
return append(other.ptr, other.len);
}
fillbytes &append(const char *str)
{
return append(str, strlen(str));
}
};
struct ptrlist : fillbytes
{
typedef const void *cvptr;
int length()
{
return (int)(size() / sizeof(cvptr));
}
cvptr *base()
{
return (cvptr *)fillbytes::base();
}
cvptr &get(int i)
{
return *(cvptr *)loc(i * sizeof(cvptr));
}
cvptr *limit()
{
return (cvptr *)fillbytes::limit();
}
void add(cvptr x)
{
*(cvptr *)grow(sizeof(x)) = x;
}
void popTo(int l)
{
assert(l <= length());
b.len = l * sizeof(cvptr);
}
int indexOf(cvptr x);
bool contains(cvptr x)
{
return indexOf(x) >= 0;
}
void freeAll(); // frees every ptr on the list, plus the list itself
};
// Use a macro rather than mess with subtle mismatches
// between member and non-member function pointers.
#define PTRLIST_QSORT(ptrls, fn) ::qsort((ptrls).base(), (ptrls).length(), sizeof(void *), fn)
struct intlist : fillbytes
{
int length()
{
return (int)(size() / sizeof(int));
}
int *base()
{
return (int *)fillbytes::base();
}
int &get(int i)
{
return *(int *)loc(i * sizeof(int));
}
int *limit()
{
return (int *)fillbytes::limit();
}
void add(int x)
{
*(int *)grow(sizeof(x)) = x;
}
void popTo(int l)
{
assert(l <= length());
b.len = l * sizeof(int);
}
int indexOf(int x);
bool contains(int x)
{
return indexOf(x) >= 0;
}
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,270 @@
/*
* Copyright (c) 2002, 2008, 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.
*/
struct unpacker;
#define INT_MAX_VALUE ((int)0x7FFFFFFF)
#define INT_MIN_VALUE ((int)0x80000000)
#define CODING_SPEC(B, H, S, D) ((B) << 20 | (H) << 8 | (S) << 4 | (D) << 0)
#define CODING_B(x) ((x) >> 20 & 0xF)
#define CODING_H(x) ((x) >> 8 & 0xFFF)
#define CODING_S(x) ((x) >> 4 & 0xF)
#define CODING_D(x) ((x) >> 0 & 0xF)
#define CODING_INIT(B, H, S, D) \
{ \
CODING_SPEC(B, H, S, D), 0, 0, 0, 0, 0, 0, 0, 0 \
}
// For debugging purposes, some compilers do not like this and will complain.
// #define long do_not_use_C_long_types_use_jlong_or_int
// Use of the type "long" is problematic, do not use it.
struct coding
{
int spec; // B,H,S,D
// Handy values derived from the spec:
int B()
{
return CODING_B(spec);
}
int H()
{
return CODING_H(spec);
}
int S()
{
return CODING_S(spec);
}
int D()
{
return CODING_D(spec);
}
int L()
{
return 256 - CODING_H(spec);
}
int min, max;
int umin, umax;
char isSigned, isSubrange, isFullRange, isMalloc;
coding *init(); // returns self or nullptr if error
coding *initFrom(int spec_)
{
assert(this->spec == 0);
this->spec = spec_;
return init();
}
static coding *findBySpec(int spec);
static coding *findBySpec(int B, int H, int S = 0, int D = 0);
static coding *findByIndex(int irregularCodingIndex);
static uint parse(byte *&rp, int B, int H);
static uint parse_lgH(byte *&rp, int B, int H, int lgH);
static void parseMultiple(byte *&rp, int N, byte *limit, int B, int H);
uint parse(byte *&rp)
{
return parse(rp, CODING_B(spec), CODING_H(spec));
}
void parseMultiple(byte *&rp, int N, byte *limit)
{
parseMultiple(rp, N, limit, CODING_B(spec), CODING_H(spec));
}
bool canRepresent(int x)
{
return (x >= min && x <= max);
}
bool canRepresentUnsigned(int x)
{
return (x >= umin && x <= umax);
}
int sumInUnsignedRange(int x, int y);
int readFrom(byte *&rpVar, int *dbase);
void readArrayFrom(byte *&rpVar, int *dbase, int length, int *values);
void skipArrayFrom(byte *&rpVar, int length)
{
readArrayFrom(rpVar, (int *)NULL, length, (int *)NULL);
}
void free(); // free self if isMalloc
// error handling
static void abort(const char *msg = nullptr)
{
unpack_abort(msg);
}
};
enum coding_method_kind
{
cmk_ERROR,
cmk_BHS,
cmk_BHS0,
cmk_BHS1,
cmk_BHSD1,
cmk_BHS1D1full, // isFullRange
cmk_BHS1D1sub, // isSubRange
// special cases hand-optimized (~50% of all decoded values)
cmk_BYTE1, //(1,256) 6%
cmk_CHAR3, //(3,128) 7%
cmk_UNSIGNED5, //(5,64) 13%
cmk_DELTA5, //(5,64,1,1) 5%
cmk_BCI5, //(5,4) 18%
cmk_BRANCH5, //(5,4,2) 4%
// cmk_UNSIGNED5H16, //(5,16) 5%
// cmk_UNSIGNED2H4, //(2,4) 6%
// cmk_DELTA4H8, //(4,8,1,1) 10%
// cmk_DELTA3H16, //(3,16,1,1) 9%
cmk_BHS_LIMIT,
cmk_pop,
cmk_pop_BHS0,
cmk_pop_BYTE1,
cmk_pop_LIMIT,
cmk_LIMIT
};
enum
{
BYTE1_spec = CODING_SPEC(1, 256, 0, 0),
CHAR3_spec = CODING_SPEC(3, 128, 0, 0),
UNSIGNED4_spec = CODING_SPEC(4, 256, 0, 0),
UNSIGNED5_spec = CODING_SPEC(5, 64, 0, 0),
SIGNED5_spec = CODING_SPEC(5, 64, 1, 0),
DELTA5_spec = CODING_SPEC(5, 64, 1, 1),
UDELTA5_spec = CODING_SPEC(5, 64, 0, 1),
MDELTA5_spec = CODING_SPEC(5, 64, 2, 1),
BCI5_spec = CODING_SPEC(5, 4, 0, 0),
BRANCH5_spec = CODING_SPEC(5, 4, 2, 0)
};
enum
{
B_MAX = 5,
C_SLOP = B_MAX * 10
};
struct coding_method;
// iterator under the control of a meta-coding
struct value_stream
{
// current coding of values or values
coding c; // B,H,S,D,etc.
coding_method_kind cmk; // type of decoding needed
byte *rp; // read pointer
byte *rplimit; // final value of read pointer
int sum; // partial sum of all values so far (D=1 only)
coding_method *cm; // coding method that defines this stream
void init(byte *band_rp, byte *band_limit, coding *defc);
void init(byte *band_rp, byte *band_limit, int spec)
{
init(band_rp, band_limit, coding::findBySpec(spec));
}
void setCoding(coding *c);
void setCoding(int spec)
{
setCoding(coding::findBySpec(spec));
}
// Parse and decode a single value.
int getInt();
// Parse and decode a single byte, with no error checks.
int getByte()
{
assert(cmk == cmk_BYTE1);
assert(rp < rplimit);
return *rp++ & 0xFF;
}
// Used only for asserts.
bool hasValue();
void done()
{
assert(!hasValue());
}
// Sometimes a value stream has an auxiliary (but there are never two).
value_stream *helper()
{
assert(hasHelper());
return this + 1;
}
bool hasHelper();
// error handling
// inline void abort(const char* msg);
// inline void aborting();
};
struct coding_method
{
value_stream vs0; // initial state snapshot (vs.meta==this)
coding_method *next; // what to do when we run out of bytes
// these fields are used for pop codes only:
int *fValues; // favored value array
int fVlength; // maximum favored value token
coding_method *uValues; // unfavored value stream
// pointer to outer unpacker, for error checks etc.
unpacker *u;
// Initialize a value stream.
void reset(value_stream *state);
// Parse a band header, size a band, and initialize for further action.
// band_rp advances (but not past band_limit), and meta_rp advances.
// The mode gives context, such as "inside a pop".
// The defc and N are the incoming parameters to a meta-coding.
// The value sink is used to collect output values, when desired.
void init(byte *&band_rp, byte *band_limit, byte *&meta_rp, int mode, coding *defc, int N,
intlist *valueSink);
// error handling
void abort(const char *msg)
{
unpack_abort(msg, u);
}
bool aborting()
{
return unpack_aborting(u);
}
};
// inline void value_stream::abort(const char* msg) { cm->abort(msg); }
// inline void value_stream::aborting() { cm->aborting(); }

View File

@ -0,0 +1,442 @@
/*
* Copyright (c) 2001, 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.
*/
/*
Java Class Version numbers history
1.0 to 1.3.X 45,3
1.4 to 1.4.X 46,0
1.5 to 1.5.X 49,0
1.6 to 1.5.x 50,0 NOTE Assumed for now
*/
// classfile constants
#define JAVA_MAGIC 0xCAFEBABE
#define JAVA_MIN_MAJOR_VERSION 45
#define JAVA_MIN_MINOR_VERSION 3
#define JAVA5_MAX_MAJOR_VERSION 49
#define JAVA5_MAX_MINOR_VERSION 0
// NOTE: Assume for now
#define JAVA6_MAX_MAJOR_VERSION 50
#define JAVA6_MAX_MINOR_VERSION 0
// package file constants
#define JAVA_PACKAGE_MAGIC 0xCAFED00D
#define JAVA5_PACKAGE_MAJOR_VERSION 150
#define JAVA5_PACKAGE_MINOR_VERSION 7
#define JAVA6_PACKAGE_MAJOR_VERSION 160
#define JAVA6_PACKAGE_MINOR_VERSION 1
// magic number for gzip streams (for processing pack200-gzip data)
#define GZIP_MAGIC 0x1F8B0800
#define GZIP_MAGIC_MASK 0xFFFFFF00 // last byte is variable "flg" field
enum
{
CONSTANT_None,
CONSTANT_Utf8,
CONSTANT_unused2, /* unused, was Unicode */
CONSTANT_Integer,
CONSTANT_Float,
CONSTANT_Long,
CONSTANT_Double,
CONSTANT_Class,
CONSTANT_String,
CONSTANT_Fieldref,
CONSTANT_Methodref,
CONSTANT_InterfaceMethodref,
CONSTANT_NameandType,
CONSTANT_Signature = 13,
CONSTANT_All = 14,
CONSTANT_Limit = 15,
CONSTANT_NONE = 0,
CONSTANT_Literal = 20, // pseudo-tag for debugging
CONSTANT_Member = 21, // pseudo-tag for debugging
SUBINDEX_BIT = 64, // combined with CONSTANT_xxx for ixTag
ACC_STATIC = 0x0008,
ACC_IC_LONG_FORM = (1 << 16), // for ic_flags
CLASS_ATTR_SourceFile = 17,
CLASS_ATTR_EnclosingMethod = 18,
CLASS_ATTR_InnerClasses = 23,
CLASS_ATTR_ClassFile_version = 24,
FIELD_ATTR_ConstantValue = 17,
METHOD_ATTR_Code = 17,
METHOD_ATTR_Exceptions = 18,
METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23,
METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24,
METHOD_ATTR_AnnotationDefault = 25,
CODE_ATTR_StackMapTable = 0,
CODE_ATTR_LineNumberTable = 1,
CODE_ATTR_LocalVariableTable = 2,
CODE_ATTR_LocalVariableTypeTable = 3,
// X_ATTR_Synthetic = 12, // ACC_SYNTHETIC; not predefined
X_ATTR_Signature = 19,
X_ATTR_Deprecated = 20,
X_ATTR_RuntimeVisibleAnnotations = 21,
X_ATTR_RuntimeInvisibleAnnotations = 22,
X_ATTR_OVERFLOW = 16,
X_ATTR_LIMIT_NO_FLAGS_HI = 32,
X_ATTR_LIMIT_FLAGS_HI = 63,
#define O_ATTR_DO(F) \
F(X_ATTR_OVERFLOW, 01) \
/*(end)*/
#define X_ATTR_DO(F) \
O_ATTR_DO(F) F(X_ATTR_Signature, Signature) F(X_ATTR_Deprecated, Deprecated) \
F(X_ATTR_RuntimeVisibleAnnotations, RuntimeVisibleAnnotations) \
F(X_ATTR_RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations) \
/*F(X_ATTR_Synthetic,Synthetic)*/ \
/*(end)*/
#define CLASS_ATTR_DO(F) \
F(CLASS_ATTR_SourceFile, SourceFile) F(CLASS_ATTR_InnerClasses, InnerClasses) \
F(CLASS_ATTR_EnclosingMethod, EnclosingMethod) F(CLASS_ATTR_ClassFile_version, 02) \
/*(end)*/
#define FIELD_ATTR_DO(F) \
F(FIELD_ATTR_ConstantValue, ConstantValue) \
/*(end)*/
#define METHOD_ATTR_DO(F) \
F(METHOD_ATTR_Code, Code) F(METHOD_ATTR_Exceptions, Exceptions) \
F(METHOD_ATTR_RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations) \
F(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, \
RuntimeInvisibleParameterAnnotations) \
F(METHOD_ATTR_AnnotationDefault, AnnotationDefault) \
/*(end)*/
#define CODE_ATTR_DO(F) \
F(CODE_ATTR_StackMapTable, StackMapTable) F(CODE_ATTR_LineNumberTable, LineNumberTable) \
F(CODE_ATTR_LocalVariableTable, LocalVariableTable) \
F(CODE_ATTR_LocalVariableTypeTable, LocalVariableTypeTable) \
/*(end)*/
#define ALL_ATTR_DO(F) \
X_ATTR_DO(F) CLASS_ATTR_DO(F) FIELD_ATTR_DO(F) METHOD_ATTR_DO(F) CODE_ATTR_DO(F) \
/*(end)*/
// attribute "context types"
ATTR_CONTEXT_CLASS = 0,
ATTR_CONTEXT_FIELD = 1,
ATTR_CONTEXT_METHOD = 2,
ATTR_CONTEXT_CODE = 3,
ATTR_CONTEXT_LIMIT = 4,
// constants for parsed layouts (stored in band::le_kind)
EK_NONE = 0, // not a layout element
EK_INT = 'I', // B H I SH etc., also FH etc.
EK_BCI = 'P', // PH etc.
EK_BCID = 'Q', // POH etc.
EK_BCO = 'O', // OH etc.
EK_REPL = 'N', // NH[...] etc.
EK_REF = 'R', // RUH, RUNH, KQH, etc.
EK_UN = 'T', // TB(...)[...] etc.
EK_CASE = 'K', // (...)[...] etc.
EK_CALL = '(', // (0), (1), etc.
EK_CBLE = '[', // [...][...] etc.
NO_BAND_INDEX = -1,
// File option bits, from LSB in ascending bit position.
FO_DEFLATE_HINT = 1 << 0,
FO_IS_CLASS_STUB = 1 << 1,
// Archive option bits, from LSB in ascending bit position:
AO_HAVE_SPECIAL_FORMATS = 1 << 0,
AO_HAVE_CP_NUMBERS = 1 << 1,
AO_HAVE_ALL_CODE_FLAGS = 1 << 2,
AO_3_UNUSED_MBZ = 1 << 3,
AO_HAVE_FILE_HEADERS = 1 << 4,
AO_DEFLATE_HINT = 1 << 5,
AO_HAVE_FILE_MODTIME = 1 << 6,
AO_HAVE_FILE_OPTIONS = 1 << 7,
AO_HAVE_FILE_SIZE_HI = 1 << 8,
AO_HAVE_CLASS_FLAGS_HI = 1 << 9,
AO_HAVE_FIELD_FLAGS_HI = 1 << 10,
AO_HAVE_METHOD_FLAGS_HI = 1 << 11,
AO_HAVE_CODE_FLAGS_HI = 1 << 12,
#define ARCHIVE_BIT_DO(F) \
F(AO_HAVE_SPECIAL_FORMATS) F(AO_HAVE_CP_NUMBERS) F(AO_HAVE_ALL_CODE_FLAGS) \
/*F(AO_3_UNUSED_MBZ)*/ \
F(AO_HAVE_FILE_HEADERS) F(AO_DEFLATE_HINT) F(AO_HAVE_FILE_MODTIME) \
F(AO_HAVE_FILE_OPTIONS) F(AO_HAVE_FILE_SIZE_HI) F(AO_HAVE_CLASS_FLAGS_HI) \
F(AO_HAVE_FIELD_FLAGS_HI) F(AO_HAVE_METHOD_FLAGS_HI) F(AO_HAVE_CODE_FLAGS_HI) \
/*(end)*/
// Constants for decoding attribute definition header bytes.
ADH_CONTEXT_MASK = 0x3, // (hdr & ADH_CONTEXT_MASK)
ADH_BIT_SHIFT = 0x2, // (hdr >> ADH_BIT_SHIFT)
ADH_BIT_IS_LSB = 1, // (hdr >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB
#define ADH_BYTE(context, index) ((((index) + ADH_BIT_IS_LSB) << ADH_BIT_SHIFT) + (context))
#define ADH_BYTE_CONTEXT(adhb) ((adhb) & ADH_CONTEXT_MASK)
#define ADH_BYTE_INDEX(adhb) (((adhb) >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB)
NO_MODTIME = 0, // nullptr modtime value
// meta-coding
_meta_default = 0,
_meta_canon_min = 1,
_meta_canon_max = 115,
_meta_arb = 116,
_meta_run = 117,
_meta_pop = 141,
_meta_limit = 189,
_meta_error = 255,
_xxx_1_end
};
// Bytecodes.
enum
{
bc_nop = 0, // 0x00
bc_aconst_null = 1, // 0x01
bc_iconst_m1 = 2, // 0x02
bc_iconst_0 = 3, // 0x03
bc_iconst_1 = 4, // 0x04
bc_iconst_2 = 5, // 0x05
bc_iconst_3 = 6, // 0x06
bc_iconst_4 = 7, // 0x07
bc_iconst_5 = 8, // 0x08
bc_lconst_0 = 9, // 0x09
bc_lconst_1 = 10, // 0x0a
bc_fconst_0 = 11, // 0x0b
bc_fconst_1 = 12, // 0x0c
bc_fconst_2 = 13, // 0x0d
bc_dconst_0 = 14, // 0x0e
bc_dconst_1 = 15, // 0x0f
bc_bipush = 16, // 0x10
bc_sipush = 17, // 0x11
bc_ldc = 18, // 0x12
bc_ldc_w = 19, // 0x13
bc_ldc2_w = 20, // 0x14
bc_iload = 21, // 0x15
bc_lload = 22, // 0x16
bc_fload = 23, // 0x17
bc_dload = 24, // 0x18
bc_aload = 25, // 0x19
bc_iload_0 = 26, // 0x1a
bc_iload_1 = 27, // 0x1b
bc_iload_2 = 28, // 0x1c
bc_iload_3 = 29, // 0x1d
bc_lload_0 = 30, // 0x1e
bc_lload_1 = 31, // 0x1f
bc_lload_2 = 32, // 0x20
bc_lload_3 = 33, // 0x21
bc_fload_0 = 34, // 0x22
bc_fload_1 = 35, // 0x23
bc_fload_2 = 36, // 0x24
bc_fload_3 = 37, // 0x25
bc_dload_0 = 38, // 0x26
bc_dload_1 = 39, // 0x27
bc_dload_2 = 40, // 0x28
bc_dload_3 = 41, // 0x29
bc_aload_0 = 42, // 0x2a
bc_aload_1 = 43, // 0x2b
bc_aload_2 = 44, // 0x2c
bc_aload_3 = 45, // 0x2d
bc_iaload = 46, // 0x2e
bc_laload = 47, // 0x2f
bc_faload = 48, // 0x30
bc_daload = 49, // 0x31
bc_aaload = 50, // 0x32
bc_baload = 51, // 0x33
bc_caload = 52, // 0x34
bc_saload = 53, // 0x35
bc_istore = 54, // 0x36
bc_lstore = 55, // 0x37
bc_fstore = 56, // 0x38
bc_dstore = 57, // 0x39
bc_astore = 58, // 0x3a
bc_istore_0 = 59, // 0x3b
bc_istore_1 = 60, // 0x3c
bc_istore_2 = 61, // 0x3d
bc_istore_3 = 62, // 0x3e
bc_lstore_0 = 63, // 0x3f
bc_lstore_1 = 64, // 0x40
bc_lstore_2 = 65, // 0x41
bc_lstore_3 = 66, // 0x42
bc_fstore_0 = 67, // 0x43
bc_fstore_1 = 68, // 0x44
bc_fstore_2 = 69, // 0x45
bc_fstore_3 = 70, // 0x46
bc_dstore_0 = 71, // 0x47
bc_dstore_1 = 72, // 0x48
bc_dstore_2 = 73, // 0x49
bc_dstore_3 = 74, // 0x4a
bc_astore_0 = 75, // 0x4b
bc_astore_1 = 76, // 0x4c
bc_astore_2 = 77, // 0x4d
bc_astore_3 = 78, // 0x4e
bc_iastore = 79, // 0x4f
bc_lastore = 80, // 0x50
bc_fastore = 81, // 0x51
bc_dastore = 82, // 0x52
bc_aastore = 83, // 0x53
bc_bastore = 84, // 0x54
bc_castore = 85, // 0x55
bc_sastore = 86, // 0x56
bc_pop = 87, // 0x57
bc_pop2 = 88, // 0x58
bc_dup = 89, // 0x59
bc_dup_x1 = 90, // 0x5a
bc_dup_x2 = 91, // 0x5b
bc_dup2 = 92, // 0x5c
bc_dup2_x1 = 93, // 0x5d
bc_dup2_x2 = 94, // 0x5e
bc_swap = 95, // 0x5f
bc_iadd = 96, // 0x60
bc_ladd = 97, // 0x61
bc_fadd = 98, // 0x62
bc_dadd = 99, // 0x63
bc_isub = 100, // 0x64
bc_lsub = 101, // 0x65
bc_fsub = 102, // 0x66
bc_dsub = 103, // 0x67
bc_imul = 104, // 0x68
bc_lmul = 105, // 0x69
bc_fmul = 106, // 0x6a
bc_dmul = 107, // 0x6b
bc_idiv = 108, // 0x6c
bc_ldiv = 109, // 0x6d
bc_fdiv = 110, // 0x6e
bc_ddiv = 111, // 0x6f
bc_irem = 112, // 0x70
bc_lrem = 113, // 0x71
bc_frem = 114, // 0x72
bc_drem = 115, // 0x73
bc_ineg = 116, // 0x74
bc_lneg = 117, // 0x75
bc_fneg = 118, // 0x76
bc_dneg = 119, // 0x77
bc_ishl = 120, // 0x78
bc_lshl = 121, // 0x79
bc_ishr = 122, // 0x7a
bc_lshr = 123, // 0x7b
bc_iushr = 124, // 0x7c
bc_lushr = 125, // 0x7d
bc_iand = 126, // 0x7e
bc_land = 127, // 0x7f
bc_ior = 128, // 0x80
bc_lor = 129, // 0x81
bc_ixor = 130, // 0x82
bc_lxor = 131, // 0x83
bc_iinc = 132, // 0x84
bc_i2l = 133, // 0x85
bc_i2f = 134, // 0x86
bc_i2d = 135, // 0x87
bc_l2i = 136, // 0x88
bc_l2f = 137, // 0x89
bc_l2d = 138, // 0x8a
bc_f2i = 139, // 0x8b
bc_f2l = 140, // 0x8c
bc_f2d = 141, // 0x8d
bc_d2i = 142, // 0x8e
bc_d2l = 143, // 0x8f
bc_d2f = 144, // 0x90
bc_i2b = 145, // 0x91
bc_i2c = 146, // 0x92
bc_i2s = 147, // 0x93
bc_lcmp = 148, // 0x94
bc_fcmpl = 149, // 0x95
bc_fcmpg = 150, // 0x96
bc_dcmpl = 151, // 0x97
bc_dcmpg = 152, // 0x98
bc_ifeq = 153, // 0x99
bc_ifne = 154, // 0x9a
bc_iflt = 155, // 0x9b
bc_ifge = 156, // 0x9c
bc_ifgt = 157, // 0x9d
bc_ifle = 158, // 0x9e
bc_if_icmpeq = 159, // 0x9f
bc_if_icmpne = 160, // 0xa0
bc_if_icmplt = 161, // 0xa1
bc_if_icmpge = 162, // 0xa2
bc_if_icmpgt = 163, // 0xa3
bc_if_icmple = 164, // 0xa4
bc_if_acmpeq = 165, // 0xa5
bc_if_acmpne = 166, // 0xa6
bc_goto = 167, // 0xa7
bc_jsr = 168, // 0xa8
bc_ret = 169, // 0xa9
bc_tableswitch = 170, // 0xaa
bc_lookupswitch = 171, // 0xab
bc_ireturn = 172, // 0xac
bc_lreturn = 173, // 0xad
bc_freturn = 174, // 0xae
bc_dreturn = 175, // 0xaf
bc_areturn = 176, // 0xb0
bc_return = 177, // 0xb1
bc_getstatic = 178, // 0xb2
bc_putstatic = 179, // 0xb3
bc_getfield = 180, // 0xb4
bc_putfield = 181, // 0xb5
bc_invokevirtual = 182, // 0xb6
bc_invokespecial = 183, // 0xb7
bc_invokestatic = 184, // 0xb8
bc_invokeinterface = 185, // 0xb9
bc_xxxunusedxxx = 186, // 0xba
bc_new = 187, // 0xbb
bc_newarray = 188, // 0xbc
bc_anewarray = 189, // 0xbd
bc_arraylength = 190, // 0xbe
bc_athrow = 191, // 0xbf
bc_checkcast = 192, // 0xc0
bc_instanceof = 193, // 0xc1
bc_monitorenter = 194, // 0xc2
bc_monitorexit = 195, // 0xc3
bc_wide = 196, // 0xc4
bc_multianewarray = 197, // 0xc5
bc_ifnull = 198, // 0xc6
bc_ifnonnull = 199, // 0xc7
bc_goto_w = 200, // 0xc8
bc_jsr_w = 201, // 0xc9
bc_bytecode_limit = 202 // 0xca
};
enum
{
bc_end_marker = 255,
bc_byte_escape = 254,
bc_ref_escape = 253,
_first_linker_op = bc_getstatic,
_last_linker_op = bc_invokestatic,
_num_linker_ops = (_last_linker_op - _first_linker_op) + 1,
_self_linker_op = bc_bytecode_limit,
_self_linker_aload_flag = 1 * _num_linker_ops,
_self_linker_super_flag = 2 * _num_linker_ops,
_self_linker_limit = _self_linker_op + 4 * _num_linker_ops,
_invokeinit_op = _self_linker_limit,
_invokeinit_self_option = 0,
_invokeinit_super_option = 1,
_invokeinit_new_option = 2,
_invokeinit_limit = _invokeinit_op + 3,
_xldc_op = _invokeinit_limit,
bc_aldc = bc_ldc,
bc_cldc = _xldc_op + 0,
bc_ildc = _xldc_op + 1,
bc_fldc = _xldc_op + 2,
bc_aldc_w = bc_ldc_w,
bc_cldc_w = _xldc_op + 3,
bc_ildc_w = _xldc_op + 4,
bc_fldc_w = _xldc_op + 5,
bc_lldc2_w = bc_ldc2_w,
bc_dldc2_w = _xldc_op + 6,
_xldc_limit = _xldc_op + 7,
_xxx_3_end
};

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2001, 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.
*/
// random definitions
#ifdef _MSC_VER
#include <windows.h>
#include <winuser.h>
#else
#include <unistd.h>
#endif
#ifndef FULL
#define FULL 1 /* Adds <500 bytes to the zipped final product. */
#endif
#if FULL // define this if you want debugging and/or compile-time attributes
#define IF_FULL(x) x
#else
#define IF_FULL(x) /*x*/
#endif
// Error messages that we have
#define ERROR_ENOMEM "Native allocation failed"
#define ERROR_FORMAT "Corrupted pack file"
#define ERROR_RESOURCE "Cannot extract resource file"
#define ERROR_OVERFLOW "Internal buffer overflow"
#define ERROR_INTERNAL "Internal error"
#define LOGFILE_STDOUT "-"
#define LOGFILE_STDERR ""
#define lengthof(array) (sizeof(array) / sizeof(array[0]))
#define NEW(T, n) (T *) must_malloc((int)(scale_size(n, sizeof(T))))
#define U_NEW(T, n) (T *) u->alloc(scale_size(n, sizeof(T)))
#define T_NEW(T, n) (T *) u->temp_alloc(scale_size(n, sizeof(T)))
// bytes and byte arrays
typedef unsigned int uint;
#ifdef _MSC_VER
typedef LONGLONG jlong;
typedef DWORDLONG julong;
#define MKDIR(dir) mkdir(dir)
#define getpid() _getpid()
#define PATH_MAX MAX_PATH
#define dup2(a, b) _dup2(a, b)
#define strcasecmp(s1, s2) _stricmp(s1, s2)
#define tempname _tempname
#define sleep Sleep
#else
typedef signed char byte;
#ifdef _LP64
typedef long jlong;
typedef long unsigned julong;
#else
typedef long long jlong;
typedef long long unsigned julong;
#endif
#define MKDIR(dir) mkdir(dir, 0777);
#endif
/* Must cast to void *, then size_t, then int. */
#define ptrlowbits(x) ((int)(size_t)(void *)(x))
/* Back and forth from jlong to pointer */
#define ptr2jlong(x) ((jlong)(size_t)(void *)(x))
#define jlong2ptr(x) ((void *)(size_t)(x))
// Keys used by Java:
#define UNPACK_DEFLATE_HINT "unpack.deflate.hint"
#define COM_PREFIX "com.sun.java.util.jar.pack."
#define UNPACK_MODIFICATION_TIME COM_PREFIX "unpack.modification.time"
#define DEBUG_VERBOSE COM_PREFIX "verbose"
#define ZIP_ARCHIVE_MARKER_COMMENT "PACK200"
// The following are not known to the Java classes:
#define UNPACK_REMOVE_PACKFILE COM_PREFIX "unpack.remove.packfile"
// Called from unpacker layers
#define _CHECK_DO(t, x) \
{ \
if (t) \
{ \
x; \
} \
}
#define CHECK _CHECK_DO(aborting(), return)
#define CHECK_(y) _CHECK_DO(aborting(), return y)
#define CHECK_0 _CHECK_DO(aborting(), return 0)
#define CHECK_NULL(p) _CHECK_DO((p) == nullptr, return)
#define CHECK_NULL_(y, p) _CHECK_DO((p) == nullptr, return y)
#define CHECK_NULL_0(p) _CHECK_DO((p) == nullptr, return 0)
#define CHECK_COUNT(t) \
if (t < 0) \
{ \
abort("bad value count"); \
} \
CHECK
#define STR_TRUE "true"
#define STR_FALSE "false"
#define STR_TF(x) ((x) ? STR_TRUE : STR_FALSE)
#define BOOL_TF(x) (((x) != nullptr &&strcmp((x), STR_TRUE) == 0) ? true : false)
#define DEFAULT_ARCHIVE_MODTIME 1060000000 // Aug 04, 2003 5:26 PM PDT

View File

@ -0,0 +1,489 @@
/*
* Copyright (c) 2003, 2008, 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.
*/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <assert.h>
#include <limits.h>
#include <time.h>
#include "defines.h"
#include "bytes.h"
#include "utils.h"
#include "coding.h"
#include "bands.h"
#include "constants.h"
#include "zip.h"
#include "unpack.h"
int main(int argc, char **argv)
{
return unpacker::run(argc, argv);
}
unpacker *unpacker::non_mt_current = nullptr;
unpacker *unpacker::current()
{
return non_mt_current;
}
static void set_current_unpacker(unpacker *u)
{
unpacker::non_mt_current = u;
}
// Callback for fetching data, Unix style.
static jlong read_input_via_stdio(unpacker *u, void *buf, jlong minlen, jlong maxlen)
{
assert(minlen <= maxlen); // don't talk nonsense
jlong numread = 0;
char *bufptr = (char *)buf;
while (numread < minlen)
{
// read available input, up to buf.length or maxlen
int readlen = (1 << 16);
if (readlen > (maxlen - numread))
readlen = (int)(maxlen - numread);
int nr = 0;
if (u->infileptr != nullptr)
{
nr = (int)fread(bufptr, 1, readlen, u->infileptr);
}
else
{
#ifndef WIN32
// we prefer unbuffered inputs
nr = (int)read(u->infileno, bufptr, readlen);
#else
nr = (int)fread(bufptr, 1, readlen, stdin);
#endif
}
if (nr <= 0)
{
if (errno != EINTR)
break;
nr = 0;
}
numread += nr;
bufptr += nr;
assert(numread <= maxlen);
}
// fprintf(u->errstrm, "readInputFn(%d,%d) => %d\n",
// (int)minlen, (int)maxlen, (int)numread);
return numread;
}
enum
{
EOF_MAGIC = 0,
BAD_MAGIC = -1
};
static int read_magic(unpacker *u, char peek[], int peeklen)
{
assert(peeklen == 4); // magic numbers are always 4 bytes
jlong nr = (u->read_input_fn)(u, peek, peeklen, peeklen);
if (nr != peeklen)
{
return (nr == 0) ? EOF_MAGIC : BAD_MAGIC;
}
int magic = 0;
for (int i = 0; i < peeklen; i++)
{
magic <<= 8;
magic += peek[i] & 0xFF;
}
return magic;
}
static void setup_gzin(unpacker *u)
{
gunzip *gzin = NEW(gunzip, 1);
gzin->init(u);
}
static const char *nbasename(const char *progname)
{
const char *slash = strrchr(progname, '/');
if (slash != nullptr)
progname = ++slash;
return progname;
}
static const char *usage_lines[] = {
"Usage: %s [-opt... | --option=value]... x.pack[.gz] y.jar\n", "\n", "Unpacking Options\n",
" -H{h}, --deflate-hint={h} override transmitted deflate hint: true, false, or keep "
"(default)\n",
" -r, --remove-pack-file remove input file after unpacking\n",
" -v, --verbose increase program verbosity\n",
" -q, --quiet set verbosity to lowest level\n",
" -l{F}, --log-file={F} output to the given log file, or '-' for standard output "
"(default)\n",
" -?, -h, --help print this message\n",
" -J{X} Java VM argument (ignored)\n", nullptr};
static void usage(unpacker *u, const char *progname, bool full = false)
{
// WinMain does not set argv[0] to the progrname
progname = (progname != nullptr) ? nbasename(progname) : "unpack200";
for (int i = 0; usage_lines[i] != nullptr; i++)
{
fprintf(stderr, usage_lines[i], progname);
if (!full)
{
fprintf(stderr, "(For more information, run %s --help .)\n", progname);
break;
}
}
}
// argument parsing
static char **init_args(int argc, char **argv, int &envargc)
{
const char *env = getenv("UNPACK200_FLAGS");
ptrlist envargs;
envargs.init();
if (env != nullptr)
{
char *buf = (char *)strdup(env);
const char *delim = "\n\t ";
for (char *p = strtok(buf, delim); p != nullptr; p = strtok(nullptr, delim))
{
envargs.add(p);
}
}
// allocate extra margin at both head and tail
char **argp = NEW(char *, envargs.length() + argc + 1);
char **argp0 = argp;
int i;
for (i = 0; i < envargs.length(); i++)
{
*argp++ = (char *)envargs.get(i);
}
for (i = 1; i < argc; i++)
{
// note: skip argv[0] (program name)
*argp++ = (char *)strdup(argv[i]); // make a scratch copy
}
*argp = nullptr; // sentinel
envargc = envargs.length(); // report this count to next_arg
envargs.free();
return argp0;
}
static int strpcmp(const char *str, const char *pfx)
{
return strncmp(str, pfx, strlen(pfx));
}
static const char flag_opts[] = "vqrVh?";
static const char string_opts[] = "HlJ";
static int next_arg(char **&argp)
{
char *arg = *argp;
if (arg == nullptr || arg[0] != '-')
{ // end of option list
return 0;
}
// printf("opt: %s\n", arg);
char ach = arg[1];
if (ach == '\0')
{
// ++argp; // do not pop this arg
return 0; // bare "-" is stdin/stdout
}
else if (arg[1] == '-')
{ // --foo option
static const char *keys[] = {"Hdeflate-hint=", "vverbose", "qquiet",
"rremove-pack-file", "llog-file=", "Vversion",
"hhelp", nullptr};
if (arg[2] == '\0')
{ // end of option list
++argp; // pop the "--"
return 0;
}
for (int i = 0; keys[i] != nullptr; i++)
{
const char *key = keys[i];
char kch = *key++;
if (strchr(key, '=') == nullptr)
{
if (!strcmp(arg + 2, key))
{
++argp; // pop option arg
return kch;
}
}
else
{
if (!strpcmp(arg + 2, key))
{
*argp += 2 + strlen(key); // remove "--"+key from arg
return kch;
}
}
}
}
else if (strchr(flag_opts, ach) != nullptr)
{ // plain option
if (arg[2] == '\0')
{
++argp;
}
else
{
// in-place edit of "-vxyz" to "-xyz"
arg += 1; // skip original '-'
arg[0] = '-';
*argp = arg;
}
// printf(" key => %c\n", ach);
return ach;
}
else if (strchr(string_opts, ach) != nullptr)
{ // argument-bearing option
if (arg[2] == '\0')
{
if (argp[1] == nullptr)
return -1; // no next arg
++argp; // leave the argument in place
}
else
{
// in-place edit of "-Hxyz" to "xyz"
arg += 2; // skip original '-H'
*argp = arg;
}
// printf(" key => %c\n", ach);
return ach;
}
return -1; // bad argument
}
static const char sccsver[] = "1.30, 07/05/05";
// Usage: unpackage input.pack output.jar
int unpacker::run(int argc, char **argv)
{
unpacker u;
u.init(read_input_via_stdio);
set_current_unpacker(&u);
jar jarout;
jarout.init(&u);
int envargc = 0;
char **argbuf = init_args(argc, argv, envargc);
char **arg0 = argbuf + envargc;
char **argp = argbuf;
int verbose = 0;
char *logfile = nullptr;
for (;;)
{
const char *arg = (*argp == nullptr) ? "" : u.saveStr(*argp);
bool isenvarg = (argp < arg0);
int ach = next_arg(argp);
bool hasoptarg = (ach != 0 && strchr(string_opts, ach) != nullptr);
if (ach == 0 && argp >= arg0)
break;
if (isenvarg && argp == arg0 && hasoptarg)
ach = 0; // don't pull from cmdline
switch (ach)
{
case 'H':
u.set_option(UNPACK_DEFLATE_HINT, *argp++);
break;
case 'v':
++verbose;
break;
case 'q':
verbose = 0;
break;
case 'r':
u.set_option(UNPACK_REMOVE_PACKFILE, "1");
break;
case 'l':
logfile = *argp++;
break;
case 'J':
argp += 1;
break; // skip ignored -Jxxx parameter
case 'h':
case '?':
usage(&u, argv[0], true);
exit(1);
default:
const char *inenv = isenvarg ? " in ${UNPACK200_FLAGS}" : "";
if (hasoptarg)
fprintf(stderr, "Missing option string%s: %s\n", inenv, arg);
else
fprintf(stderr, "Unrecognized argument%s: %s\n", inenv, arg);
usage(&u, argv[0]);
exit(2);
}
}
if (verbose != 0)
{
u.set_option(DEBUG_VERBOSE, u.saveIntStr(verbose));
}
const char *source_file = *argp++;
const char *destination_file = *argp++;
if (source_file == nullptr || destination_file == nullptr || *argp != nullptr)
{
usage(&u, argv[0]);
exit(2);
}
if (verbose != 0)
{
fprintf(stderr, "Unpacking from %s to %s\n", source_file, destination_file);
}
bool &remove_source = u.remove_packfile;
if (strcmp(source_file, "-") == 0)
{
remove_source = false;
u.infileno = fileno(stdin);
}
else
{
u.infileptr = fopen(source_file, "rb");
if (u.infileptr == nullptr)
{
fprintf(stderr, "Error: Could not open input file: %s\n", source_file);
exit(3); // Called only from the native standalone unpacker
}
}
if (strcmp(destination_file, "-") == 0)
{
jarout.jarfp = stdout;
}
else
{
jarout.openJarFile(destination_file);
assert(jarout.jarfp != nullptr);
}
if (verbose != 0)
u.dump_options();
char peek[4];
int magic;
// check for GZIP input
magic = read_magic(&u, peek, (int)sizeof(peek));
if ((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC)
{
// Oops; must slap an input filter on this data.
setup_gzin(&u);
u.gzin->start(magic);
if (!u.aborting())
{
u.start();
}
}
else
{
u.start(peek, sizeof(peek));
}
// Note: The checks to u.aborting() are necessary to gracefully
// terminate processing when the first segment throws an error.
for (;;)
{
if (u.aborting())
break;
// Each trip through this loop unpacks one segment
// and then resets the unpacker.
for (unpacker::file *filep; (filep = u.get_next_file()) != nullptr;)
{
if (u.aborting())
break;
u.write_file_to_jar(filep);
}
if (u.aborting())
break;
// Peek ahead for more data.
magic = read_magic(&u, peek, (int)sizeof(peek));
if (magic != (int)JAVA_PACKAGE_MAGIC)
{
if (magic != EOF_MAGIC)
u.abort("garbage after end of pack archive");
break; // all done
}
// Release all storage from parsing the old segment.
u.reset();
// Restart, beginning with the peek-ahead.
u.start(peek, sizeof(peek));
}
int status = 0;
if (u.aborting())
{
fprintf(stderr, "Error: %s\n", u.get_abort_message());
status = 1;
}
if (u.infileptr != nullptr)
{
fclose(u.infileptr);
u.infileptr = nullptr;
}
if (!u.aborting() && remove_source)
remove(source_file);
if (verbose != 0)
{
fprintf(stderr, "unpacker completed with status=%d\n", status);
}
u.finish();
u.free(); // tidy up malloc blocks
set_current_unpacker(nullptr); // clean up global pointer
return status;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,585 @@
/*
* Copyright (c) 2002, 2008, 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.
*/
// Global Structures
struct jar;
struct gunzip;
struct band;
struct cpool;
struct entry;
struct cpindex;
struct inner_class;
struct value_stream;
struct cpindex
{
uint len;
entry *base1; // base of primary index
entry **base2; // base of secondary index
byte ixTag; // type of entries (!= CONSTANT_None), plus 64 if sub-index
enum
{
SUB_TAG = 64
};
entry *get(uint i);
void init(int len_, entry *base1_, int ixTag_)
{
len = len_;
base1 = base1_;
base2 = nullptr;
ixTag = ixTag_;
}
void init(int len_, entry **base2_, int ixTag_)
{
len = len_;
base1 = nullptr;
base2 = base2_;
ixTag = ixTag_;
}
};
struct cpool
{
uint nentries;
entry *entries;
entry *first_extra_entry;
uint maxentries; // total allocated size of entries
// Position and size of each homogeneous subrange:
int tag_count[CONSTANT_Limit];
int tag_base[CONSTANT_Limit];
cpindex tag_index[CONSTANT_Limit];
ptrlist tag_extras[CONSTANT_Limit];
cpindex *member_indexes; // indexed by 2*CONSTANT_Class.inord
cpindex *getFieldIndex(entry *classRef);
cpindex *getMethodIndex(entry *classRef);
inner_class **ic_index;
inner_class **ic_child_index;
inner_class *getIC(entry *inner);
inner_class *getFirstChildIC(entry *outer);
inner_class *getNextChildIC(inner_class *child);
int outputIndexLimit; // index limit after renumbering
ptrlist outputEntries; // list of entry* needing output idx assigned
entry **hashTab;
uint hashTabLength;
entry *&hashTabRef(byte tag, bytes &b);
entry *ensureUtf8(bytes &b);
entry *ensureClass(bytes &b);
// Well-known Utf8 symbols.
enum
{
#define SNAME(n, s) s_##s,
ALL_ATTR_DO(SNAME)
#undef SNAME
s_lt_init_gt, // <init>
s_LIMIT
};
entry *sym[s_LIMIT];
// read counts from hdr, allocate main arrays
enum
{
NUM_COUNTS = 12
};
void init(unpacker *u, int counts[NUM_COUNTS]);
// pointer to outer unpacker, for error checks etc.
unpacker *u;
int getCount(byte tag)
{
assert((uint)tag < CONSTANT_Limit);
return tag_count[tag];
}
cpindex *getIndex(byte tag)
{
assert((uint)tag < CONSTANT_Limit);
return &tag_index[tag];
}
cpindex *getKQIndex(); // uses cur_descr
void expandSignatures();
void initMemberIndexes();
void computeOutputOrder();
void computeOutputIndexes();
void resetOutputIndexes();
// error handling
inline void abort(const char *msg);
inline bool aborting();
};
/*
* The unpacker provides the entry points to the unpack engine,
* as well as maintains the state of the engine.
*/
struct unpacker
{
// One element of the resulting JAR.
struct file
{
const char *name;
julong size;
int modtime;
int options;
bytes data[2];
// Note: If Sum(data[*].len) < size,
// remaining bytes must be read directly from the input stream.
bool deflate_hint()
{
return ((options & FO_DEFLATE_HINT) != 0);
}
};
// global pointer to self, if not running under JNI (not multi-thread safe)
static unpacker *non_mt_current;
// if running Unix-style, here are the inputs and outputs
FILE *infileptr; // buffered
int infileno; // unbuffered
bytes inbytes; // direct
gunzip *gzin; // gunzip filter, if any
jar *jarout; // output JAR file
// pointer to self, for U_NEW macro
unpacker *u;
// private abort message string, allocated to PATH_MAX*2
const char *abort_message;
ptrlist mallocs; // list of guys to free when we are all done
ptrlist tmallocs; // list of guys to free on next client request
fillbytes smallbuf; // supplies small alloc requests
fillbytes tsmallbuf; // supplies temporary small alloc requests
// option management members
int verbose; // verbose level, 0 means no output
bool strip_compile;
bool strip_debug;
bool strip_jcov;
bool remove_packfile;
int deflate_hint_or_zero; // ==0 means not set, otherwise -1 or 1
int modification_time_or_zero;
// input stream
fillbytes input; // the whole block (size is predicted, has slop too)
bool live_input; // is the data in this block live?
bool free_input; // must the input buffer be freed?
byte *rp; // read pointer (< rplimit <= input.limit())
byte *rplimit; // how much of the input block has been read?
julong bytes_read;
int unsized_bytes_read;
// callback to read at least one byte, up to available input
typedef jlong (*read_input_fn_t)(unpacker *self, void *buf, jlong minlen, jlong maxlen);
read_input_fn_t read_input_fn;
// archive header fields
int magic, minver, majver;
size_t archive_size;
int archive_next_count, archive_options, archive_modtime;
int band_headers_size;
int file_count, attr_definition_count, ic_count, class_count;
int default_class_minver, default_class_majver;
int default_file_options, suppress_file_options; // not header fields
int default_archive_modtime, default_file_modtime; // not header fields
int code_count; // not a header field
int files_remaining; // not a header field
// engine state
band *all_bands; // indexed by band_number
byte *meta_rp; // read-pointer into (copy of) band_headers
cpool cp; // all constant pool information
inner_class *ics; // InnerClasses
// output stream
bytes output; // output block (either classfile head or tail)
byte *wp; // write pointer (< wplimit == output.limit())
byte *wpbase; // write pointer starting address (<= wp)
byte *wplimit; // how much of the output block has been written?
// output state
file cur_file;
entry *cur_class; // CONSTANT_Class entry
entry *cur_super; // CONSTANT_Class entry or nullptr
entry *cur_descr; // CONSTANT_NameandType entry
int cur_descr_flags; // flags corresponding to cur_descr
int cur_class_minver, cur_class_majver;
bool cur_class_has_local_ics;
fillbytes cur_classfile_head;
fillbytes cur_classfile_tail;
int files_written; // also tells which file we're working on
int classes_written; // also tells which class we're working on
julong bytes_written;
intlist bcimap;
fillbytes class_fixup_type;
intlist class_fixup_offset;
ptrlist class_fixup_ref;
fillbytes code_fixup_type; // which format of branch operand?
intlist code_fixup_offset; // location of operand needing fixup
intlist code_fixup_source; // encoded ID of branch insn
ptrlist requested_ics; // which ics need output?
// stats pertaining to multiple segments (updated on reset)
julong bytes_read_before_reset;
julong bytes_written_before_reset;
int files_written_before_reset;
int classes_written_before_reset;
int segments_read_before_reset;
// attribute state
struct layout_definition
{
uint idx; // index (0..31...) which identifies this layout
const char *name; // name of layout
entry *nameEntry;
const char *layout; // string of layout (not yet parsed)
band **elems; // array of top-level layout elems (or callables)
bool hasCallables()
{
return layout[0] == '[';
}
band **bands()
{
assert(elems != nullptr);
return elems;
}
};
struct attr_definitions
{
unpacker *u; // pointer to self, for U_NEW macro
int xxx_flags_hi_bn; // locator for flags, count, indexes, calls bands
int attrc; // ATTR_CONTEXT_CLASS, etc.
uint flag_limit; // 32 or 63, depending on archive_options bit
julong predef; // mask of built-in definitions
julong redef; // mask of local flag definitions or redefinitions
ptrlist layouts; // local (compressor-defined) defs, in index order
int flag_count[X_ATTR_LIMIT_FLAGS_HI];
intlist overflow_count;
ptrlist strip_names; // what attribute names are being stripped?
ptrlist band_stack; // Temp., used during layout parsing.
ptrlist calls_to_link; // (ditto)
int bands_made; // (ditto)
void free()
{
layouts.free();
overflow_count.free();
strip_names.free();
band_stack.free();
calls_to_link.free();
}
// Locate the five fixed bands.
band &xxx_flags_hi();
band &xxx_flags_lo();
band &xxx_attr_count();
band &xxx_attr_indexes();
band &xxx_attr_calls();
band &fixed_band(int e_class_xxx);
// Register a new layout, and make bands for it.
layout_definition *defineLayout(int idx, const char *name, const char *layout);
layout_definition *defineLayout(int idx, entry *nameEntry, const char *layout);
band **buildBands(layout_definition *lo);
// Parse a layout string or part of one, recursively if necessary.
const char *parseLayout(const char *lp, band **&res, int curCble);
const char *parseNumeral(const char *lp, int &res);
const char *parseIntLayout(const char *lp, band *&res, byte le_kind,
bool can_be_signed = false);
band **popBody(int band_stack_base); // pops a body off band_stack
// Read data into the bands of the idx-th layout.
void readBandData(int idx); // parse layout, make bands, read data
void readBandData(band **body, uint count); // recursive helper
layout_definition *getLayout(uint idx)
{
if (idx >= (uint)layouts.length())
return nullptr;
return (layout_definition *)layouts.get(idx);
}
void setHaveLongFlags(bool z)
{
assert(flag_limit == 0); // not set up yet
flag_limit = (z ? X_ATTR_LIMIT_FLAGS_HI : X_ATTR_LIMIT_NO_FLAGS_HI);
}
bool haveLongFlags()
{
assert(flag_limit == X_ATTR_LIMIT_NO_FLAGS_HI ||
flag_limit == X_ATTR_LIMIT_FLAGS_HI);
return flag_limit == X_ATTR_LIMIT_FLAGS_HI;
}
// Return flag_count if idx is predef and not redef, else zero.
int predefCount(uint idx);
bool isRedefined(uint idx)
{
if (idx >= flag_limit)
return false;
return (bool)((redef >> idx) & 1);
}
bool isPredefined(uint idx)
{
if (idx >= flag_limit)
return false;
return (bool)(((predef & ~redef) >> idx) & 1);
}
julong flagIndexMask()
{
return (predef | redef);
}
bool isIndex(uint idx)
{
assert(flag_limit != 0); // must be set up already
if (idx < flag_limit)
return (bool)(((predef | redef) >> idx) & 1);
else
return (idx - flag_limit < (uint)overflow_count.length());
}
int &getCount(uint idx)
{
assert(isIndex(idx));
if (idx < flag_limit)
return flag_count[idx];
else
return overflow_count.get(idx - flag_limit);
}
bool aborting()
{
return u->aborting();
}
void abort(const char *msg)
{
u->abort(msg);
}
};
attr_definitions attr_defs[ATTR_CONTEXT_LIMIT];
// Initialization
void init(read_input_fn_t input_fn = nullptr);
// Resets to a known sane state
void reset();
// Deallocates all storage.
void free();
// Deallocates temporary storage (volatile after next client call).
void free_temps()
{
tsmallbuf.init();
tmallocs.freeAll();
}
// Option management methods
bool set_option(const char *option, const char *value);
const char *get_option(const char *option);
void dump_options();
// Fetching input.
bool ensure_input(jlong more);
byte *input_scan()
{
return rp;
}
size_t input_remaining()
{
return rplimit - rp;
}
size_t input_consumed()
{
return rp - input.base();
}
// Entry points to the unpack engine
static int run(int argc, char **argv); // Unix-style entry point.
void check_options();
void start(void *packptr = nullptr, size_t len = 0);
void write_file_to_jar(file *f);
void finish();
// Public post unpack methods
int get_files_remaining()
{
return files_remaining;
}
int get_segments_remaining()
{
return archive_next_count;
}
file *get_next_file(); // returns nullptr on last file
// General purpose methods
void *alloc(size_t size)
{
return alloc_heap(size, true);
}
void *temp_alloc(size_t size)
{
return alloc_heap(size, true, true);
}
void *alloc_heap(size_t size, bool smallOK = false, bool temp = false);
void saveTo(bytes &b, const char *str)
{
saveTo(b, (byte *)str, strlen(str));
}
void saveTo(bytes &b, bytes &data)
{
saveTo(b, data.ptr, data.len);
}
void saveTo(bytes &b, byte *ptr, size_t len); //{ b.ptr = U_NEW...}
const char *saveStr(const char *str)
{
bytes buf;
saveTo(buf, str);
return buf.strval();
}
const char *saveIntStr(int num)
{
char buf[30];
sprintf(buf, "%d", num);
return saveStr(buf);
}
const char *get_abort_message();
void abort(const char *s = nullptr);
bool aborting()
{
return abort_message != nullptr;
}
static unpacker *current(); // find current instance
// Output management
void set_output(fillbytes *which)
{
assert(wp == nullptr);
which->ensureSize(1 << 12); // covers the average classfile
wpbase = which->base();
wp = which->limit();
wplimit = which->end();
}
fillbytes *close_output(fillbytes *which = nullptr); // inverse of set_output
// These take an implicit parameter of wp/wplimit, and resize as necessary:
byte *put_space(size_t len); // allocates space at wp, returns pointer
size_t put_empty(size_t s)
{
byte *p = put_space(s);
return p - wpbase;
}
void ensure_put_space(size_t len);
void put_bytes(bytes &b)
{
b.writeTo(put_space(b.len));
}
void putu1(int n)
{
putu1_at(put_space(1), n);
}
void putu1_fast(int n)
{
putu1_at(wp++, n);
}
void putu2(int n); // { putu2_at(put_space(2), n); }
void putu4(int n); // { putu4_at(put_space(4), n); }
void putu8(jlong n); // { putu8_at(put_space(8), n); }
void putref(entry *e); // { putu2_at(put_space(2), putref_index(e, 2)); }
void putu1ref(entry *e); // { putu1_at(put_space(1), putref_index(e, 1)); }
int putref_index(entry *e, int size); // size in [1..2]
void put_label(int curIP, int size); // size in {2,4}
void putlayout(band **body);
void put_stackmap_type();
size_t wpoffset()
{
return (size_t)(wp - wpbase);
} // (unvariant across overflow)
byte *wp_at(size_t offset)
{
return wpbase + offset;
}
uint to_bci(uint bii);
void get_code_header(int &max_stack, int &max_na_locals, int &handler_count, int &cflags);
band *ref_band_for_self_op(int bc, bool &isAloadVar, int &origBCVar);
band *ref_band_for_op(int bc);
// Definitions of standard classfile int formats:
static void putu1_at(byte *wp, int n)
{
assert(n == (n & 0xFF));
wp[0] = n;
}
static void putu2_at(byte *wp, int n);
static void putu4_at(byte *wp, int n);
static void putu8_at(byte *wp, jlong n);
// Private stuff
void reset_cur_classfile();
void write_classfile_tail();
void write_classfile_head();
void write_code();
void write_bc_ops();
void write_members(int num, int attrc); // attrc=ATTR_CONTEXT_FIELD/METHOD
int write_attrs(int attrc, julong indexBits);
// The readers
void read_bands();
void read_file_header();
void read_cp();
void read_cp_counts(value_stream &hdr);
void read_attr_defs();
void read_ics();
void read_attrs(int attrc, int obj_count);
void read_classes();
void read_code_headers();
void read_bcs();
void read_bc_ops();
void read_files();
void read_Utf8_values(entry *cpMap, int len);
void read_single_words(band &cp_band, entry *cpMap, int len);
void read_double_words(band &cp_bands, entry *cpMap, int len);
void read_single_refs(band &cp_band, byte refTag, entry *cpMap, int len);
void read_double_refs(band &cp_band, byte ref1Tag, byte ref2Tag, entry *cpMap, int len);
void read_signature_values(entry *cpMap, int len);
};
inline void cpool::abort(const char *msg)
{
u->abort(msg);
}
inline bool cpool::aborting()
{
return u->aborting();
}

View File

@ -0,0 +1,91 @@
/*
* Copyright (c) 2001, 2008, 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.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
#include <sys/stat.h>
#ifdef _MSC_VER
#include <direct.h>
#include <io.h>
#include <process.h>
#else
#include <unistd.h>
#endif
#include "constants.h"
#include "defines.h"
#include "bytes.h"
#include "utils.h"
#include "unpack.h"
void *must_malloc(size_t size)
{
size_t msize = size;
void *ptr = (msize > PSIZE_MAX) ? nullptr : malloc(msize);
if (ptr != nullptr)
{
memset(ptr, 0, size);
}
else
{
unpack_abort(ERROR_ENOMEM);
}
return ptr;
}
void unpack_abort(const char *msg, unpacker *u)
{
if (msg == nullptr)
msg = "corrupt pack file or internal error";
if (u == nullptr)
u = unpacker::current();
if (u == nullptr)
{
fprintf(stderr, "Error: unpacker: %s\n", msg);
::abort();
return;
}
u->abort(msg);
}
bool unpack_aborting(unpacker *u)
{
if (u == nullptr)
u = unpacker::current();
if (u == nullptr)
{
fprintf(stderr, "Error: unpacker: no current instance\n");
::abort();
return true;
}
return u->aborting();
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2001, 2008, 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.
*/
// Definitions of our util functions
void *must_malloc(size_t size);
// overflow management
#define OVERFLOW ((size_t) - 1)
#define PSIZE_MAX (OVERFLOW / 2) /* normal size limit */
inline size_t scale_size(size_t size, size_t scale)
{
return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
}
inline size_t add_size(size_t size1, size_t size2)
{
return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX) ? OVERFLOW : size1 + size2;
}
inline size_t add_size(size_t size1, size_t size2, int size3)
{
return add_size(add_size(size1, size2), size3);
}
// These may be expensive, because they have to go via Java TSD,
// if the optional u argument is missing.
struct unpacker;
extern void unpack_abort(const char *msg, unpacker *u = nullptr);
extern bool unpack_aborting(unpacker *u = nullptr);

610
depends/pack200/src/zip.cpp Normal file
View File

@ -0,0 +1,610 @@
/*
* Copyright (c) 2001, 2008, 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.
*/
/**
* Note: Lifted from uncrunch.c from jdk sources
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>
#include <assert.h>
#ifndef _MSC_VER
#include <strings.h>
#endif
#include "defines.h"
#include "bytes.h"
#include "utils.h"
#include "constants.h"
#include "unpack.h"
#include "zip.h"
#ifdef NO_ZLIB
inline bool jar::deflate_bytes(bytes &head, bytes &tail)
{
return false;
}
inline uint jar::get_crc32(uint c, uchar *ptr, uint len)
{
return 0;
}
#define Z_NULL NULL
#else // Have ZLIB
#include <zlib.h>
inline uint jar::get_crc32(uint c, uchar *ptr, uint len)
{
return crc32(c, ptr, len);
}
#endif // End of ZLIB
#ifdef sparc
#define SWAP_BYTES(a) ((((a) << 8) & 0xff00) | 0x00ff) & (((a) >> 8) | 0xff00)
#else
#define SWAP_BYTES(a) (a)
#endif
#define GET_INT_LO(a) SWAP_BYTES(a & 0xFFFF)
#define GET_INT_HI(a) SWAP_BYTES((a >> 16) & 0xFFFF);
void jar::init(unpacker *u_)
{
BYTES_OF(*this).clear();
u = u_;
u->jarout = this;
}
// Write data to the ZIP output stream.
void jar::write_data(void *buff, int len)
{
while (len > 0)
{
int rc = (int)fwrite(buff, 1, len, jarfp);
if (rc <= 0)
{
fprintf(stderr, "Error: write on output file failed err=%d\n", errno);
exit(1); // Called only from the native standalone unpacker
}
output_file_offset += rc;
buff = ((char *)buff) + rc;
len -= rc;
}
}
void jar::add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
uint32_t crc)
{
uint fname_length = (uint)strlen(fname);
ushort header[23];
if (modtime == 0)
modtime = default_modtime;
uint32_t dostime = get_dostime(modtime);
header[0] = (ushort)SWAP_BYTES(0x4B50);
header[1] = (ushort)SWAP_BYTES(0x0201);
header[2] = (ushort)SWAP_BYTES(0xA);
// required version
header[3] = (ushort)SWAP_BYTES(0xA);
// flags 02 = maximum sub-compression flag
header[4] = (store) ? 0x0 : SWAP_BYTES(0x2);
// Compression method 8=deflate.
header[5] = (store) ? 0x0 : SWAP_BYTES(0x08);
// Last modified date and time.
header[6] = (ushort)GET_INT_LO(dostime);
header[7] = (ushort)GET_INT_HI(dostime);
// CRC
header[8] = (ushort)GET_INT_LO(crc);
header[9] = (ushort)GET_INT_HI(crc);
// Compressed length:
header[10] = (ushort)GET_INT_LO(clen);
header[11] = (ushort)GET_INT_HI(clen);
// Uncompressed length.
header[12] = (ushort)GET_INT_LO(len);
header[13] = (ushort)GET_INT_HI(len);
// Filename length
header[14] = (ushort)SWAP_BYTES(fname_length);
// So called "extra field" length.
header[15] = 0;
// So called "comment" length.
header[16] = 0;
// Disk number start
header[17] = 0;
// File flags => binary
header[18] = 0;
// More file flags
header[19] = 0;
header[20] = 0;
// Offset within ZIP file.
header[21] = (ushort)GET_INT_LO(output_file_offset);
header[22] = (ushort)GET_INT_HI(output_file_offset);
// Copy the whole thing into the central directory.
central_directory.append(header, sizeof(header));
// Copy the fname to the header.
central_directory.append(fname, fname_length);
central_directory_count++;
}
void jar::write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
uint crc)
{
uint fname_length = (uint)strlen(fname);
ushort header[15];
if (modtime == 0)
modtime = default_modtime;
uint32_t dostime = get_dostime(modtime);
// ZIP LOC magic.
header[0] = (ushort)SWAP_BYTES(0x4B50);
header[1] = (ushort)SWAP_BYTES(0x0403);
// Version
header[2] = (ushort)SWAP_BYTES(0xA);
// flags 02 = maximum sub-compression flag
header[3] = (store) ? 0x0 : SWAP_BYTES(0x2);
// Compression method = deflate
header[4] = (store) ? 0x0 : SWAP_BYTES(0x08);
// Last modified date and time.
header[5] = (ushort)GET_INT_LO(dostime);
header[6] = (ushort)GET_INT_HI(dostime);
// CRC
header[7] = (ushort)GET_INT_LO(crc);
header[8] = (ushort)GET_INT_HI(crc);
// Compressed length:
header[9] = (ushort)GET_INT_LO(clen);
header[10] = (ushort)GET_INT_HI(clen);
// Uncompressed length.
header[11] = (ushort)GET_INT_LO(len);
header[12] = (ushort)GET_INT_HI(len);
// Filename length
header[13] = (ushort)SWAP_BYTES(fname_length);
// So called "extra field" length.
header[14] = 0;
// Write the LOC header to the output file.
write_data(header, (int)sizeof(header));
// Copy the fname to the header.
write_data((char *)fname, (int)fname_length);
}
static const char marker_comment[] = ZIP_ARCHIVE_MARKER_COMMENT;
void jar::write_central_directory()
{
bytes mc;
mc.set(marker_comment);
ushort header[11];
// Create the End of Central Directory structure.
header[0] = (ushort)SWAP_BYTES(0x4B50);
header[1] = (ushort)SWAP_BYTES(0x0605);
// disk numbers
header[2] = 0;
header[3] = 0;
// Number of entries in central directory.
header[4] = (ushort)SWAP_BYTES(central_directory_count);
header[5] = (ushort)SWAP_BYTES(central_directory_count);
// Size of the central directory}
header[6] = (ushort)GET_INT_LO((int)central_directory.size());
header[7] = (ushort)GET_INT_HI((int)central_directory.size());
// Offset of central directory within disk.
header[8] = (ushort)GET_INT_LO(output_file_offset);
header[9] = (ushort)GET_INT_HI(output_file_offset);
// zipfile comment length;
header[10] = (ushort)SWAP_BYTES((int)mc.len);
// Write the central directory.
write_data(central_directory.b);
// Write the End of Central Directory structure.
write_data(header, (int)sizeof(header));
// Write the comment.
write_data(mc);
}
// Public API
// Open a Jar file and initialize.
void jar::openJarFile(const char *fname)
{
if (!jarfp)
{
jarfp = fopen(fname, "wb");
if (!jarfp)
{
fprintf(stderr, "Error: Could not open jar file: %s\n", fname);
exit(3); // Called only from the native standalone unpacker
}
}
}
// Add a ZIP entry and copy the file data
void jar::addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
bytes &tail)
{
int len = (int)(head.len + tail.len);
int clen = 0;
uint crc = get_crc32(0, Z_NULL, 0);
if (head.len != 0)
crc = get_crc32(crc, (uchar *)head.ptr, (uint)head.len);
if (tail.len != 0)
crc = get_crc32(crc, (uchar *)tail.ptr, (uint)tail.len);
bool deflate = (deflate_hint && len > 0);
if (deflate)
{
if (deflate_bytes(head, tail) == false)
{
deflate = false;
}
}
clen = (int)((deflate) ? deflated.size() : len);
add_to_jar_directory(fname, !deflate, modtime, len, clen, crc);
write_jar_header(fname, !deflate, modtime, len, clen, crc);
if (deflate)
{
write_data(deflated.b);
}
else
{
write_data(head);
write_data(tail);
}
}
// Add a ZIP entry for a directory name no data
void jar::addDirectoryToJarFile(const char *dir_name)
{
bool store = true;
add_to_jar_directory((const char *)dir_name, store, default_modtime, 0, 0, 0);
write_jar_header((const char *)dir_name, store, default_modtime, 0, 0, 0);
}
// Write out the central directory and close the jar file.
void jar::closeJarFile(bool central)
{
if (jarfp)
{
fflush(jarfp);
if (central)
write_central_directory();
fflush(jarfp);
fclose(jarfp);
}
reset();
}
/* Convert the date y/n/d and time h:m:s to a four byte DOS date and
* time (date in high two bytes, time in low two bytes allowing magnitude
* comparison).
*/
inline uint32_t jar::dostime(int y, int n, int d, int h, int m, int s)
{
return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0)
: (((uint32_t)y - 1980) << 25) | ((uint32_t)n << 21) | ((uint32_t)d << 16) |
((uint32_t)h << 11) | ((uint32_t)m << 5) | ((uint32_t)s >> 1);
}
#ifdef _REENTRANT // solaris
extern "C" struct tm *gmtime_r(const time_t *, struct tm *);
#else
#define gmtime_r(t, s) gmtime(t)
#endif
/*
* Return the Unix time in DOS format
*/
uint32_t jar::get_dostime(int modtime)
{
// see defines.h
if (modtime != 0 && modtime == modtime_cache)
return dostime_cache;
if (modtime != 0 && default_modtime == 0)
default_modtime = modtime; // catch a reasonable default
time_t t = modtime;
struct tm sbuf;
(void)memset((void *)&sbuf, 0, sizeof(sbuf));
struct tm *s = gmtime_r(&t, &sbuf);
modtime_cache = modtime;
dostime_cache =
dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday, s->tm_hour, s->tm_min, s->tm_sec);
// printf("modtime %d => %d\n", modtime_cache, dostime_cache);
return dostime_cache;
}
/* Returns true on success, and will set the clen to the compressed
length, the caller should verify if true and clen less than the
input data
*/
bool jar::deflate_bytes(bytes &head, bytes &tail)
{
int len = (int)(head.len + tail.len);
z_stream zs;
BYTES_OF(zs).clear();
// NOTE: the window size should always be -MAX_WBITS normally -15.
// unzip/zipup.c and java/Deflater.c
int error =
deflateInit2(&zs, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
if (error != Z_OK)
{
/*
switch (error)
{
case Z_MEM_ERROR:
PRINTCR((2, "Error: deflate error : Out of memory \n"));
break;
case Z_STREAM_ERROR:
PRINTCR((2, "Error: deflate error : Invalid compression level \n"));
break;
case Z_VERSION_ERROR:
PRINTCR((2, "Error: deflate error : Invalid version\n"));
break;
default:
PRINTCR((2, "Error: Internal deflate error error = %d\n", error));
}
*/
return false;
}
deflated.empty();
zs.next_out = (uchar *)deflated.grow(len + (len / 2));
zs.avail_out = (int)deflated.size();
zs.next_in = (uchar *)head.ptr;
zs.avail_in = (int)head.len;
bytes *first = &head;
bytes *last = &tail;
if (last->len == 0)
{
first = nullptr;
last = &head;
}
else if (first->len == 0)
{
first = nullptr;
}
if (first != nullptr && error == Z_OK)
{
zs.next_in = (uchar *)first->ptr;
zs.avail_in = (int)first->len;
error = deflate(&zs, Z_NO_FLUSH);
}
if (error == Z_OK)
{
zs.next_in = (uchar *)last->ptr;
zs.avail_in = (int)last->len;
error = deflate(&zs, Z_FINISH);
}
if (error == Z_STREAM_END)
{
if (len > (int)zs.total_out)
{
deflated.b.len = zs.total_out;
deflateEnd(&zs);
return true;
}
deflateEnd(&zs);
return false;
}
deflateEnd(&zs);
return false;
}
// Callback for fetching data from a GZIP input stream
static jlong read_input_via_gzip(unpacker *u, void *buf, jlong minlen, jlong maxlen)
{
assert(minlen <= maxlen); // don't talk nonsense
jlong numread = 0;
char *bufptr = (char *)buf;
char *inbuf = u->gzin->inbuf;
size_t inbuflen = sizeof(u->gzin->inbuf);
unpacker::read_input_fn_t read_gzin_fn = (unpacker::read_input_fn_t)u->gzin->read_input_fn;
z_stream &zs = *(z_stream *)u->gzin->zstream;
while (numread < minlen)
{
int readlen = (1 << 16); // pretty arbitrary
if (readlen > (maxlen - numread))
readlen = (int)(maxlen - numread);
zs.next_out = (uchar *)bufptr;
zs.avail_out = readlen;
if (zs.avail_in == 0)
{
zs.avail_in = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
zs.next_in = (uchar *)inbuf;
}
int error = inflate(&zs, Z_NO_FLUSH);
if (error != Z_OK && error != Z_STREAM_END)
{
u->abort("error inflating input");
break;
}
int nr = readlen - zs.avail_out;
numread += nr;
bufptr += nr;
assert(numread <= maxlen);
if (error == Z_STREAM_END)
{
enum
{
TRAILER_LEN = 8
};
// skip 8-byte trailer
if (zs.avail_in >= TRAILER_LEN)
{
zs.avail_in -= TRAILER_LEN;
}
else
{
// Bug: 5023768,we read past the TRAILER_LEN to see if there is
// any extraneous data, as we dont support concatenated .gz
// files just yet.
int extra = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
zs.avail_in += extra - TRAILER_LEN;
}
// %%% should check final CRC and length here
// %%% should check for concatenated *.gz files here
if (zs.avail_in > 0)
u->abort("garbage after end of deflated input stream");
// pop this filter off:
u->gzin->free();
break;
}
}
// fprintf(u->errstrm, "readInputFn(%d,%d) => %d (gunzip)\n",
// (int)minlen, (int)maxlen, (int)numread);
return numread;
}
void gunzip::init(unpacker *u_)
{
BYTES_OF(*this).clear();
u = u_;
assert(u->gzin == nullptr); // once only, please
read_input_fn = (void *)u->read_input_fn;
zstream = NEW(z_stream, 1);
u->gzin = this;
u->read_input_fn = read_input_via_gzip;
}
void gunzip::start(int magic)
{
assert((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC);
int gz_flg = (magic & 0xFF); // keep "flg", discard other 3 bytes
enum
{
FHCRC = (1 << 1),
FEXTRA = (1 << 2),
FNAME = (1 << 3),
FCOMMENT = (1 << 4)
};
char gz_mtime[4];
char gz_xfl[1];
char gz_os[1];
char gz_extra_len[2];
char gz_hcrc[2];
char gz_ignore;
// do not save extra, name, comment
read_fixed_field(gz_mtime, sizeof(gz_mtime));
read_fixed_field(gz_xfl, sizeof(gz_xfl));
read_fixed_field(gz_os, sizeof(gz_os));
if (gz_flg & FEXTRA)
{
read_fixed_field(gz_extra_len, sizeof(gz_extra_len));
int extra_len = gz_extra_len[0] & 0xFF;
extra_len += (gz_extra_len[1] & 0xFF) << 8;
for (; extra_len > 0; extra_len--)
{
read_fixed_field(&gz_ignore, 1);
}
}
int null_terms = 0;
if (gz_flg & FNAME)
null_terms++;
if (gz_flg & FCOMMENT)
null_terms++;
for (; null_terms; null_terms--)
{
for (;;)
{
gz_ignore = 0;
read_fixed_field(&gz_ignore, 1);
if (gz_ignore == 0)
break;
}
}
if (gz_flg & FHCRC)
read_fixed_field(gz_hcrc, sizeof(gz_hcrc));
if (aborting())
return;
// now the input stream is ready to read into the inflater
int error = inflateInit2((z_stream *)zstream, -MAX_WBITS);
if (error != Z_OK)
{
abort("cannot create input");
return;
}
}
void gunzip::free()
{
assert(u->gzin == this);
u->gzin = nullptr;
u->read_input_fn = (unpacker::read_input_fn_t) this->read_input_fn;
inflateEnd((z_stream *)zstream);
::free(zstream);
zstream = nullptr;
::free(this);
}
void gunzip::read_fixed_field(char *buf, size_t buflen)
{
if (aborting())
return;
jlong nr = ((unpacker::read_input_fn_t)read_input_fn)(u, buf, buflen, buflen);
if ((size_t)nr != buflen)
u->abort("short stream header");
}

130
depends/pack200/src/zip.h Normal file
View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2001, 2008, 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.
*/
#include <stdint.h>
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned char uchar;
struct unpacker;
struct jar
{
// JAR file writer
FILE *jarfp;
int default_modtime;
// Used by unix2dostime:
int modtime_cache;
uint32_t dostime_cache;
// Private members
fillbytes central_directory;
ushort central_directory_count;
uint output_file_offset;
fillbytes deflated; // temporary buffer
// pointer to outer unpacker, for error checks etc.
unpacker *u;
// Public Methods
void openJarFile(const char *fname);
void addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
bytes &tail);
void addDirectoryToJarFile(const char *dir_name);
void closeJarFile(bool central);
void init(unpacker *u_);
void free()
{
central_directory.free();
deflated.free();
}
void reset()
{
free();
init(u);
}
// Private Methods
void write_data(void *ptr, int len);
void write_data(bytes &b)
{
write_data(b.ptr, (int)b.len);
}
void add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
uint32_t crc);
void write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
unsigned int crc);
void write_central_directory();
uint32_t dostime(int y, int n, int d, int h, int m, int s);
uint32_t get_dostime(int modtime);
// The definitions of these depend on the NO_ZLIB option:
bool deflate_bytes(bytes &head, bytes &tail);
static uint get_crc32(uint c, unsigned char *ptr, uint len);
// error handling
void abort(const char *msg)
{
unpack_abort(msg, u);
}
bool aborting()
{
return unpack_aborting(u);
}
};
struct gunzip
{
// optional gzip input stream control block
// pointer to outer unpacker, for error checks etc.
unpacker *u;
void *read_input_fn; // underlying byte stream
void *zstream; // inflater state
char inbuf[1 << 14]; // input buffer
void init(unpacker *u_); // pushes new value on u->read_input_fn
void free();
void start(int magic);
// private stuff
void read_fixed_field(char *buf, size_t buflen);
// error handling
void abort(const char *msg)
{
unpack_abort(msg, u);
}
bool aborting()
{
return unpack_aborting(u);
}
};