unpack.h revision 494
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * This code is free software; you can redistribute it and/or modify it
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * under the terms of the GNU General Public License version 2 only, as
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * published by the Free Software Foundation. Sun designates this
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * particular file as subject to the "Classpath" exception as provided
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * by Sun in the LICENSE file that accompanied this code.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * This code is distributed in the hope that it will be useful, but WITHOUT
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * version 2 for more details (a copy is included in the LICENSE file that
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * accompanied this code).
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * You should have received a copy of the GNU General Public License version
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * 2 along with this work; if not, write to the Free Software Foundation,
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * CA 95054 USA or visit www.sun.com if you need additional information or
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * have any questions.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift// Global Structures
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift byte ixTag; // type of entries (!= CONSTANT_None), plus 64 if sub-index
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void init(int len_, entry* base1_, int ixTag_) {
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void init(int len_, entry** base2_, int ixTag_) {
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift uint maxentries; // total allocated size of entries
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Position and size of each homogeneous subrange:
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift cpindex* member_indexes; // indexed by 2*CONSTANT_Class.inord
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift inner_class* getNextChildIC(inner_class* child);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift int outputIndexLimit; // index limit after renumbering
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift ptrlist outputEntries; // list of entry* needing output idx assigned
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Well-known Utf8 symbols.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // read counts from hdr, allocate main arrays
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void init(unpacker* u, int counts[NUM_COUNTS]);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // pointer to outer unpacker, for error checks etc.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // error handling
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift inline bool aborting();
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * The unpacker provides the entry points to the unpack engine,
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift * as well as maintains the state of the engine.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // One element of the resulting JAR.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Note: If Sum(data[*].len) < size,
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // remaining bytes must be read directly from the input stream.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift bool deflate_hint() { return ((options & FO_DEFLATE_HINT) != 0); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // back pointer to NativeUnpacker obj and Java environment
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // global pointer to self, if not running under JNI (not multi-thread safe)
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // if running Unix-style, here are the inputs and outputs
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // pointer to self, for U_NEW macro
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // private abort message string, allocated to PATH_MAX*2
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift ptrlist mallocs; // list of guys to free when we are all done
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift ptrlist tmallocs; // list of guys to free on next client request
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift fillbytes smallbuf; // supplies small alloc requests
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift fillbytes tsmallbuf; // supplies temporary small alloc requests
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift // option management members
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift int verbose; // verbose level, 0 means no output
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift int deflate_hint_or_zero; // ==0 means not set, otherwise -1 or 1
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // input stream
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift fillbytes input; // the whole block (size is predicted, has slop too)
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift bool live_input; // is the data in this block live?
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift bool free_input; // must the input buffer be freed?
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift byte* rp; // read pointer (< rplimit <= input.limit())
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift byte* rplimit; // how much of the input block has been read?
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // callback to read at least one byte, up to available input
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift typedef jlong (*read_input_fn_t)(unpacker* self, void* buf, jlong minlen, jlong maxlen);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // archive header fields
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift int archive_next_count, archive_options, archive_modtime;
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift int file_count, attr_definition_count, ic_count, class_count;
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift int default_class_minver, default_class_majver;
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift int default_file_options, suppress_file_options; // not header fields
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift int default_archive_modtime, default_file_modtime; // not header fields
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // engine state
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift byte* meta_rp; // read-pointer into (copy of) band_headers
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // output stream
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift bytes output; // output block (either classfile head or tail)
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift byte* wp; // write pointer (< wplimit == output.limit())
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift byte* wpbase; // write pointer starting address (<= wp)
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift byte* wplimit; // how much of the output block has been written?
91940c5122d22be4fd20bc41db2ffc4a9ba4ce59matthew_swift // output state
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift entry* cur_super; // CONSTANT_Class entry or null
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift entry* cur_descr; // CONSTANT_NameandType entry
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift int cur_descr_flags; // flags corresponding to cur_descr
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift int files_written; // also tells which file we're working on
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift int classes_written; // also tells which class we're working on
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift fillbytes code_fixup_type; // which format of branch operand?
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift intlist code_fixup_offset; // location of operand needing fixup
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift intlist code_fixup_source; // encoded ID of branch insn
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift ptrlist requested_ics; // which ics need output?
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // stats pertaining to multiple segments (updated on reset)
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // attribute state
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift uint idx; // index (0..31...) which identifies this layout
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift const char* layout; // string of layout (not yet parsed)
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift band** elems; // array of top-level layout elems (or callables)
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift bool hasCallables() { return layout[0] == '['; }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift band** bands() { assert(elems != null); return elems; }
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift unpacker* u; // pointer to self, for U_NEW macro
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift int xxx_flags_hi_bn;// locator for flags, count, indexes, calls bands
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift uint flag_limit; // 32 or 63, depending on archive_options bit
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift julong predef; // mask of built-in definitions
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift julong redef; // mask of local flag definitions or redefinitions
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift ptrlist layouts; // local (compressor-defined) defs, in index order
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift ptrlist strip_names; // what attribute names are being stripped?
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift ptrlist band_stack; // Temp., used during layout parsing.
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift // Locate the five fixed bands.
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift // Register a new layout, and make bands for it.
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift layout_definition* defineLayout(int idx, const char* name, const char* layout);
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift layout_definition* defineLayout(int idx, entry* nameEntry, const char* layout);
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift // Parse a layout string or part of one, recursively if necessary.
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift const char* parseLayout(const char* lp, band** &res, int curCble);
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift const char* parseNumeral(const char* lp, int &res);
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift const char* parseIntLayout(const char* lp, band* &res, byte le_kind,
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift band** popBody(int band_stack_base); // pops a body off band_stack
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift // Read data into the bands of the idx-th layout.
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift void readBandData(int idx); // parse layout, make bands, read data
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift void readBandData(band** body, uint count); // recursive helper
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift if (idx >= (uint)layouts.length()) return null;
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift flag_limit = (z? X_ATTR_LIMIT_FLAGS_HI: X_ATTR_LIMIT_NO_FLAGS_HI);
408b8eb145348cb8f251a8abfec96e7e4e80f630matthew_swift assert(flag_limit == X_ATTR_LIMIT_NO_FLAGS_HI ||
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Return flag_count if idx is predef and not redef, else zero.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift return (bool)(((predef & ~redef) >> idx) & 1);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift assert(flag_limit != 0); // must be set up already
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift return (idx - flag_limit < (uint)overflow_count.length());
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void abort(const char* msg) { u->abort(msg); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift attr_definitions attr_defs[ATTR_CONTEXT_LIMIT];
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Initialization
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Resets to a known sane state
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Deallocates all storage.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Deallocates temporary storage (volatile after next client call).
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void free_temps() { tsmallbuf.init(); tmallocs.freeAll(); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Option management methods
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift bool set_option(const char* option, const char* value);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Fetching input.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift size_t input_remaining() { return rplimit - rp; }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift size_t input_consumed() { return rp - input.base(); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Entry points to the unpack engine
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift static int run(int argc, char **argv); // Unix-style entry point.
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void start(void* packptr = null, size_t len = 0);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Public post unpack methods
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift int get_files_remaining() { return files_remaining; }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift int get_segments_remaining() { return archive_next_count; }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift file* get_next_file(); // returns null on last file
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // General purpose methods
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void* alloc(size_t size) { return alloc_heap(size, true); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void* temp_alloc(size_t size) { return alloc_heap(size, true, true); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void* alloc_heap(size_t size, bool smallOK = false, bool temp = false);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void saveTo(bytes& b, const char* str) { saveTo(b, (byte*)str, strlen(str)); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void saveTo(bytes& b, bytes& data) { saveTo(b, data.ptr, data.len); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void saveTo(bytes& b, byte* ptr, size_t len); //{ b.ptr = U_NEW...}
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift const char* saveStr(const char* str) { bytes buf; saveTo(buf, str); return buf.strval(); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift const char* saveIntStr(int num) { char buf[30]; sprintf(buf, "%d", num); return saveStr(buf); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift int printcr_if_verbose(int level, const char* fmt,...);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift bool aborting() { return abort_message != null; }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift static unpacker* current(); // find current instance
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Output management
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift which->ensureSize(1 << 12); // covers the average classfile
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift fillbytes* close_output(fillbytes* which = null); // inverse of set_output
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // These take an implicit parameter of wp/wplimit, and resize as necessary:
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift byte* put_space(size_t len); // allocates space at wp, returns pointer
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift size_t put_empty(size_t s) { byte* p = put_space(s); return p - wpbase; }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void put_bytes(bytes& b) { b.writeTo(put_space(b.len)); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void putu1(int n) { putu1_at(put_space(1), n); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void putu2(int n); // { putu2_at(put_space(2), n); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void putu4(int n); // { putu4_at(put_space(4), n); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void putu8(jlong n); // { putu8_at(put_space(8), n); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void putref(entry* e); // { putu2_at(put_space(2), putref_index(e, 2)); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void putu1ref(entry* e); // { putu1_at(put_space(1), putref_index(e, 1)); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift int putref_index(entry* e, int size); // size in [1..2]
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void put_label(int curIP, int size); // size in {2,4}
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift size_t wpoffset() { return (size_t)(wp - wpbase); } // (unvariant across overflow)
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift byte* wp_at(size_t offset) { return wpbase + offset; }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift band* ref_band_for_self_op(int bc, bool& isAloadVar, int& origBCVar);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Definitions of standard classfile int formats:
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift static void putu1_at(byte* wp, int n) { assert(n == (n & 0xFF)); wp[0] = n; }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // Private stuff
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void write_members(int num, int attrc); // attrc=ATTR_CONTEXT_FIELD/METHOD
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift // The readers
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void read_single_words(band& cp_band, entry* cpMap, int len);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void read_double_words(band& cp_bands, entry* cpMap, int len);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void read_single_refs(band& cp_band, byte refTag, entry* cpMap, int len);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void read_double_refs(band& cp_band, byte ref1Tag, byte ref2Tag, entry* cpMap, int len);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swift void read_signature_values(entry* cpMap, int len);
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swiftinline void cpool::abort(const char* msg) { u->abort(msg); }
bb8874d71cdd8e5288297b9727703437c6dfcfedmatthew_swiftinline bool cpool::aborting() { return u->aborting(); }