| 1 | /* |
| 2 | * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. Oracle designates this |
| 8 | * particular file as subject to the "Classpath" exception as provided |
| 9 | * by Oracle in the LICENSE file that accompanied this code. |
| 10 | * |
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 14 | * version 2 for more details (a copy is included in the LICENSE file that |
| 15 | * accompanied this code). |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License version |
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20 | * |
| 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| 22 | * or visit www.oracle.com if you need additional information or have any |
| 23 | * questions. |
| 24 | */ |
| 25 | // Global Structures |
| 26 | struct jar; |
| 27 | struct gunzip; |
| 28 | struct band; |
| 29 | struct cpool; |
| 30 | struct entry; |
| 31 | struct cpindex; |
| 32 | struct inner_class; |
| 33 | struct value_stream; |
| 34 | |
| 35 | struct cpindex { |
| 36 | uint len; |
| 37 | entry* base1; // base of primary index |
| 38 | entry** base2; // base of secondary index |
| 39 | byte ixTag; // type of entries (!= CONSTANT_None), plus 64 if sub-index |
| 40 | enum { SUB_TAG = 64 }; |
| 41 | |
| 42 | entry* get(uint i); |
| 43 | |
| 44 | void init(int len_, entry* base1_, int ixTag_) { |
| 45 | len = len_; |
| 46 | base1 = base1_; |
| 47 | base2 = null; |
| 48 | ixTag = ixTag_; |
| 49 | } |
| 50 | void init(int len_, entry** base2_, int ixTag_) { |
| 51 | len = len_; |
| 52 | base1 = null; |
| 53 | base2 = base2_; |
| 54 | ixTag = ixTag_; |
| 55 | } |
| 56 | }; |
| 57 | |
| 58 | struct cpool { |
| 59 | uint nentries; |
| 60 | entry* entries; |
| 61 | entry* ; |
| 62 | uint maxentries; // total allocated size of entries |
| 63 | |
| 64 | // Position and size of each homogeneous subrange: |
| 65 | int tag_count[CONSTANT_Limit]; |
| 66 | int tag_base[CONSTANT_Limit]; |
| 67 | cpindex tag_index[CONSTANT_Limit]; |
| 68 | ptrlist [CONSTANT_Limit]; |
| 69 | |
| 70 | int tag_group_count[CONSTANT_GroupLimit - CONSTANT_GroupFirst]; |
| 71 | cpindex tag_group_index[CONSTANT_GroupLimit - CONSTANT_GroupFirst]; |
| 72 | |
| 73 | cpindex* member_indexes; // indexed by 2*CONSTANT_Class.inord |
| 74 | cpindex* getFieldIndex(entry* classRef); |
| 75 | cpindex* getMethodIndex(entry* classRef); |
| 76 | |
| 77 | inner_class** ic_index; |
| 78 | inner_class** ic_child_index; |
| 79 | inner_class* getIC(entry* inner); |
| 80 | inner_class* getFirstChildIC(entry* outer); |
| 81 | inner_class* getNextChildIC(inner_class* child); |
| 82 | |
| 83 | int outputIndexLimit; // index limit after renumbering |
| 84 | ptrlist outputEntries; // list of entry* needing output idx assigned |
| 85 | ptrlist requested_bsms; // which bsms need output? |
| 86 | |
| 87 | entry** hashTab; |
| 88 | uint hashTabLength; |
| 89 | entry*& hashTabRef(byte tag, bytes& b); |
| 90 | entry* ensureUtf8(bytes& b); |
| 91 | entry* ensureClass(bytes& b); |
| 92 | |
| 93 | // Well-known Utf8 symbols. |
| 94 | enum { |
| 95 | #define SNAME(n,s) s_##s, |
| 96 | ALL_ATTR_DO(SNAME) |
| 97 | #undef SNAME |
| 98 | s_lt_init_gt, // <init> |
| 99 | s_LIMIT |
| 100 | }; |
| 101 | entry* sym[s_LIMIT]; |
| 102 | |
| 103 | // read counts from hdr, allocate main arrays |
| 104 | void init(unpacker* u, int counts[CONSTANT_Limit]); |
| 105 | |
| 106 | // pointer to outer unpacker, for error checks etc. |
| 107 | unpacker* u; |
| 108 | |
| 109 | int getCount(byte tag) { |
| 110 | if ((uint)tag >= CONSTANT_GroupFirst) { |
| 111 | assert((uint)tag < CONSTANT_GroupLimit); |
| 112 | return tag_group_count[(uint)tag - CONSTANT_GroupFirst]; |
| 113 | } else { |
| 114 | assert((uint)tag < CONSTANT_Limit); |
| 115 | return tag_count[(uint)tag]; |
| 116 | } |
| 117 | } |
| 118 | cpindex* getIndex(byte tag) { |
| 119 | if ((uint)tag >= CONSTANT_GroupFirst) { |
| 120 | assert((uint)tag < CONSTANT_GroupLimit); |
| 121 | return &tag_group_index[(uint)tag - CONSTANT_GroupFirst]; |
| 122 | } else { |
| 123 | assert((uint)tag < CONSTANT_Limit); |
| 124 | return &tag_index[(uint)tag]; |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | cpindex* getKQIndex(); // uses cur_descr |
| 129 | |
| 130 | void expandSignatures(); |
| 131 | void initGroupIndexes(); |
| 132 | void initMemberIndexes(); |
| 133 | int initLoadableValues(entry** loadable_entries); |
| 134 | |
| 135 | void computeOutputOrder(); |
| 136 | void computeOutputIndexes(); |
| 137 | void resetOutputIndexes(); |
| 138 | |
| 139 | // error handling |
| 140 | inline void abort(const char* msg); |
| 141 | inline bool aborting(); |
| 142 | }; |
| 143 | |
| 144 | /* |
| 145 | * The unpacker provides the entry points to the unpack engine, |
| 146 | * as well as maintains the state of the engine. |
| 147 | */ |
| 148 | struct unpacker { |
| 149 | // One element of the resulting JAR. |
| 150 | struct file { |
| 151 | const char* name; |
| 152 | julong size; |
| 153 | int modtime; |
| 154 | int options; |
| 155 | bytes data[2]; |
| 156 | // Note: If Sum(data[*].len) < size, |
| 157 | // remaining bytes must be read directly from the input stream. |
| 158 | bool deflate_hint() { return ((options & FO_DEFLATE_HINT) != 0); } |
| 159 | }; |
| 160 | |
| 161 | // back pointer to NativeUnpacker obj and Java environment |
| 162 | void* jniobj; |
| 163 | void* jnienv; |
| 164 | |
| 165 | // global pointer to self, if not running under JNI (not multi-thread safe) |
| 166 | static unpacker* non_mt_current; |
| 167 | |
| 168 | // if running Unix-style, here are the inputs and outputs |
| 169 | FILE* infileptr; // buffered |
| 170 | int infileno; // unbuffered |
| 171 | bytes inbytes; // direct |
| 172 | gunzip* gzin; // gunzip filter, if any |
| 173 | jar* jarout; // output JAR file |
| 174 | |
| 175 | #ifndef PRODUCT |
| 176 | int nowrite; |
| 177 | int skipfiles; |
| 178 | int verbose_bands; |
| 179 | #endif |
| 180 | |
| 181 | // pointer to self, for U_NEW macro |
| 182 | unpacker* u; |
| 183 | |
| 184 | // private abort message string, allocated to PATH_MAX*2 |
| 185 | const char* abort_message; |
| 186 | ptrlist mallocs; // list of guys to free when we are all done |
| 187 | ptrlist tmallocs; // list of guys to free on next client request |
| 188 | fillbytes smallbuf; // supplies small alloc requests |
| 189 | fillbytes tsmallbuf; // supplies temporary small alloc requests |
| 190 | |
| 191 | // option management members |
| 192 | int verbose; // verbose level, 0 means no output |
| 193 | bool strip_compile; |
| 194 | bool strip_debug; |
| 195 | bool strip_jcov; |
| 196 | bool remove_packfile; |
| 197 | int deflate_hint_or_zero; // ==0 means not set, otherwise -1 or 1 |
| 198 | int modification_time_or_zero; |
| 199 | |
| 200 | FILE* errstrm; |
| 201 | const char* errstrm_name; |
| 202 | |
| 203 | const char* log_file; |
| 204 | |
| 205 | // input stream |
| 206 | fillbytes input; // the whole block (size is predicted, has slop too) |
| 207 | bool live_input; // is the data in this block live? |
| 208 | bool free_input; // must the input buffer be freed? |
| 209 | byte* rp; // read pointer (< rplimit <= input.limit()) |
| 210 | byte* rplimit; // how much of the input block has been read? |
| 211 | julong bytes_read; |
| 212 | size_t unsized_bytes_read; |
| 213 | |
| 214 | // callback to read at least one byte, up to available input |
| 215 | typedef jlong (*read_input_fn_t)(unpacker* self, void* buf, jlong minlen, jlong maxlen); |
| 216 | read_input_fn_t read_input_fn; |
| 217 | |
| 218 | // archive header fields |
| 219 | int magic, minver, majver; |
| 220 | size_t archive_size; |
| 221 | int archive_next_count, archive_options, archive_modtime; |
| 222 | int band_headers_size; |
| 223 | int file_count, attr_definition_count, ic_count, class_count; |
| 224 | int default_class_minver, default_class_majver; |
| 225 | int default_file_options, suppress_file_options; // not header fields |
| 226 | int default_archive_modtime, default_file_modtime; // not header fields |
| 227 | int code_count; // not a header field |
| 228 | int files_remaining; // not a header field |
| 229 | |
| 230 | // engine state |
| 231 | band* all_bands; // indexed by band_number |
| 232 | byte* meta_rp; // read-pointer into (copy of) band_headers |
| 233 | cpool cp; // all constant pool information |
| 234 | inner_class* ics; // InnerClasses |
| 235 | |
| 236 | // output stream |
| 237 | bytes output; // output block (either classfile head or tail) |
| 238 | byte* wp; // write pointer (< wplimit == output.limit()) |
| 239 | byte* wpbase; // write pointer starting address (<= wp) |
| 240 | byte* wplimit; // how much of the output block has been written? |
| 241 | |
| 242 | // output state |
| 243 | file cur_file; |
| 244 | entry* cur_class; // CONSTANT_Class entry |
| 245 | entry* cur_super; // CONSTANT_Class entry or null |
| 246 | entry* cur_descr; // CONSTANT_NameandType entry |
| 247 | int cur_descr_flags; // flags corresponding to cur_descr |
| 248 | int cur_class_minver, cur_class_majver; |
| 249 | bool cur_class_has_local_ics; |
| 250 | int cur_class_local_bsm_count; |
| 251 | fillbytes cur_classfile_head; |
| 252 | fillbytes cur_classfile_tail; |
| 253 | int files_written; // also tells which file we're working on |
| 254 | int classes_written; // also tells which class we're working on |
| 255 | julong bytes_written; |
| 256 | intlist bcimap; |
| 257 | fillbytes class_fixup_type; |
| 258 | intlist class_fixup_offset; |
| 259 | ptrlist class_fixup_ref; |
| 260 | fillbytes code_fixup_type; // which format of branch operand? |
| 261 | intlist code_fixup_offset; // location of operand needing fixup |
| 262 | intlist code_fixup_source; // encoded ID of branch insn |
| 263 | ptrlist requested_ics; // which ics need output? |
| 264 | |
| 265 | // stats pertaining to multiple segments (updated on reset) |
| 266 | julong bytes_read_before_reset; |
| 267 | julong bytes_written_before_reset; |
| 268 | int files_written_before_reset; |
| 269 | int classes_written_before_reset; |
| 270 | int segments_read_before_reset; |
| 271 | |
| 272 | // attribute state |
| 273 | struct layout_definition { |
| 274 | uint idx; // index (0..31...) which identifies this layout |
| 275 | const char* name; // name of layout |
| 276 | entry* nameEntry; |
| 277 | const char* layout; // string of layout (not yet parsed) |
| 278 | band** elems; // array of top-level layout elems (or callables) |
| 279 | |
| 280 | bool hasCallables() { return layout[0] == '['; } |
| 281 | band** bands() { assert(elems != null); return elems; } |
| 282 | }; |
| 283 | struct attr_definitions { |
| 284 | unpacker* u; // pointer to self, for U_NEW macro |
| 285 | int xxx_flags_hi_bn;// locator for flags, count, indexes, calls bands |
| 286 | int attrc; // ATTR_CONTEXT_CLASS, etc. |
| 287 | uint flag_limit; // 32 or 63, depending on archive_options bit |
| 288 | julong predef; // mask of built-in definitions |
| 289 | julong redef; // mask of local flag definitions or redefinitions |
| 290 | ptrlist layouts; // local (compressor-defined) defs, in index order |
| 291 | int flag_count[X_ATTR_LIMIT_FLAGS_HI]; |
| 292 | intlist overflow_count; |
| 293 | ptrlist strip_names; // what attribute names are being stripped? |
| 294 | ptrlist band_stack; // Temp., used during layout parsing. |
| 295 | ptrlist calls_to_link; // (ditto) |
| 296 | int bands_made; // (ditto) |
| 297 | |
| 298 | void free() { |
| 299 | layouts.free(); |
| 300 | overflow_count.free(); |
| 301 | strip_names.free(); |
| 302 | band_stack.free(); |
| 303 | calls_to_link.free(); |
| 304 | } |
| 305 | |
| 306 | // Locate the five fixed bands. |
| 307 | band& xxx_flags_hi(); |
| 308 | band& xxx_flags_lo(); |
| 309 | band& xxx_attr_count(); |
| 310 | band& xxx_attr_indexes(); |
| 311 | band& xxx_attr_calls(); |
| 312 | band& fixed_band(int e_class_xxx); |
| 313 | |
| 314 | // Register a new layout, and make bands for it. |
| 315 | layout_definition* defineLayout(int idx, const char* name, const char* layout); |
| 316 | layout_definition* defineLayout(int idx, entry* nameEntry, const char* layout); |
| 317 | band** buildBands(layout_definition* lo); |
| 318 | |
| 319 | // Parse a layout string or part of one, recursively if necessary. |
| 320 | const char* parseLayout(const char* lp, band** &res, int curCble); |
| 321 | const char* parseNumeral(const char* lp, int &res); |
| 322 | const char* parseIntLayout(const char* lp, band* &res, byte le_kind, |
| 323 | bool can_be_signed = false); |
| 324 | band** popBody(int band_stack_base); // pops a body off band_stack |
| 325 | |
| 326 | // Read data into the bands of the idx-th layout. |
| 327 | void readBandData(int idx); // parse layout, make bands, read data |
| 328 | void readBandData(band** body, uint count); // recursive helper |
| 329 | |
| 330 | layout_definition* getLayout(uint idx) { |
| 331 | if (idx >= (uint)layouts.length()) return null; |
| 332 | return (layout_definition*) layouts.get(idx); |
| 333 | } |
| 334 | |
| 335 | void setHaveLongFlags(bool z) { |
| 336 | assert(flag_limit == 0); // not set up yet |
| 337 | flag_limit = (z? X_ATTR_LIMIT_FLAGS_HI: X_ATTR_LIMIT_NO_FLAGS_HI); |
| 338 | } |
| 339 | bool haveLongFlags() { |
| 340 | assert(flag_limit == X_ATTR_LIMIT_NO_FLAGS_HI || |
| 341 | flag_limit == X_ATTR_LIMIT_FLAGS_HI); |
| 342 | return flag_limit == X_ATTR_LIMIT_FLAGS_HI; |
| 343 | } |
| 344 | |
| 345 | // Return flag_count if idx is predef and not redef, else zero. |
| 346 | int predefCount(uint idx); |
| 347 | |
| 348 | bool isRedefined(uint idx) { |
| 349 | if (idx >= flag_limit) return false; |
| 350 | return (bool)((redef >> idx) & 1); |
| 351 | } |
| 352 | bool isPredefined(uint idx) { |
| 353 | if (idx >= flag_limit) return false; |
| 354 | return (bool)(((predef & ~redef) >> idx) & 1); |
| 355 | } |
| 356 | julong flagIndexMask() { |
| 357 | return (predef | redef); |
| 358 | } |
| 359 | bool isIndex(uint idx) { |
| 360 | assert(flag_limit != 0); // must be set up already |
| 361 | if (idx < flag_limit) |
| 362 | return (bool)(((predef | redef) >> idx) & 1); |
| 363 | else |
| 364 | return (idx - flag_limit < (uint)overflow_count.length()); |
| 365 | } |
| 366 | int& getCount(uint idx) { |
| 367 | assert(isIndex(idx)); |
| 368 | if (idx < flag_limit) |
| 369 | return flag_count[idx]; |
| 370 | else |
| 371 | return overflow_count.get(idx - flag_limit); |
| 372 | } |
| 373 | bool aborting() { return u->aborting(); } |
| 374 | void abort(const char* msg) { u->abort(msg); } |
| 375 | }; |
| 376 | |
| 377 | attr_definitions attr_defs[ATTR_CONTEXT_LIMIT]; |
| 378 | |
| 379 | // Initialization |
| 380 | void init(read_input_fn_t input_fn = null); |
| 381 | // Resets to a known sane state |
| 382 | void reset(); |
| 383 | // Deallocates all storage. |
| 384 | void free(); |
| 385 | // Deallocates temporary storage (volatile after next client call). |
| 386 | void free_temps() { tsmallbuf.init(); tmallocs.freeAll(); } |
| 387 | |
| 388 | // Option management methods |
| 389 | bool set_option(const char* option, const char* value); |
| 390 | const char* get_option(const char* option); |
| 391 | |
| 392 | void dump_options(); |
| 393 | |
| 394 | // Fetching input. |
| 395 | bool ensure_input(jlong more); |
| 396 | byte* input_scan() { return rp; } |
| 397 | size_t input_remaining() { return rplimit - rp; } |
| 398 | size_t input_consumed() { return rp - input.base(); } |
| 399 | |
| 400 | // Entry points to the unpack engine |
| 401 | static int run(int argc, char **argv); // Unix-style entry point. |
| 402 | void check_options(); |
| 403 | void start(void* packptr = null, size_t len = 0); |
| 404 | void redirect_stdio(); |
| 405 | void write_file_to_jar(file* f); |
| 406 | void finish(); |
| 407 | |
| 408 | // Public post unpack methods |
| 409 | int get_files_remaining() { return files_remaining; } |
| 410 | int get_segments_remaining() { return archive_next_count; } |
| 411 | file* get_next_file(); // returns null on last file |
| 412 | |
| 413 | // General purpose methods |
| 414 | void* alloc(size_t size) { return alloc_heap(size, true); } |
| 415 | void* temp_alloc(size_t size) { return alloc_heap(size, true, true); } |
| 416 | void* alloc_heap(size_t size, bool smallOK = false, bool temp = false); |
| 417 | void saveTo(bytes& b, const char* str) { saveTo(b, (byte*)str, strlen(str)); } |
| 418 | void saveTo(bytes& b, bytes& data) { saveTo(b, data.ptr, data.len); } |
| 419 | void saveTo(bytes& b, byte* ptr, size_t len); //{ b.ptr = U_NEW...} |
| 420 | const char* saveStr(const char* str) { bytes buf; saveTo(buf, str); return buf.strval(); } |
| 421 | const char* saveIntStr(int num) { char buf[30]; sprintf(buf, "%d" , num); return saveStr(buf); } |
| 422 | #ifndef PRODUCT |
| 423 | int printcr_if_verbose(int level, const char* fmt,...); |
| 424 | #endif |
| 425 | const char* get_abort_message(); |
| 426 | void abort(const char* s = null); |
| 427 | bool aborting() { return abort_message != null; } |
| 428 | static unpacker* current(); // find current instance |
| 429 | void checkLegacy(const char* name); |
| 430 | // Output management |
| 431 | void set_output(fillbytes* which) { |
| 432 | assert(wp == null); |
| 433 | which->ensureSize(1 << 12); // covers the average classfile |
| 434 | wpbase = which->base(); |
| 435 | wp = which->limit(); |
| 436 | wplimit = which->end(); |
| 437 | } |
| 438 | fillbytes* close_output(fillbytes* which = null); // inverse of set_output |
| 439 | |
| 440 | // These take an implicit parameter of wp/wplimit, and resize as necessary: |
| 441 | byte* put_space(size_t len); // allocates space at wp, returns pointer |
| 442 | size_t put_empty(size_t s) { byte* p = put_space(s); return p - wpbase; } |
| 443 | void ensure_put_space(size_t len); |
| 444 | void put_bytes(bytes& b) { b.writeTo(put_space(b.len)); } |
| 445 | void putu1(int n) { putu1_at(put_space(1), n); } |
| 446 | void putu1_fast(int n) { putu1_at(wp++, n); } |
| 447 | void putu2(int n); // { putu2_at(put_space(2), n); } |
| 448 | void putu4(int n); // { putu4_at(put_space(4), n); } |
| 449 | void putu8(jlong n); // { putu8_at(put_space(8), n); } |
| 450 | void putref(entry* e); // { putu2_at(put_space(2), putref_index(e, 2)); } |
| 451 | void putu1ref(entry* e); // { putu1_at(put_space(1), putref_index(e, 1)); } |
| 452 | int putref_index(entry* e, int size); // size in [1..2] |
| 453 | void put_label(int curIP, int size); // size in {2,4} |
| 454 | void putlayout(band** body); |
| 455 | void put_stackmap_type(); |
| 456 | |
| 457 | size_t wpoffset() { return (size_t)(wp - wpbase); } // (unvariant across overflow) |
| 458 | byte* wp_at(size_t offset) { return wpbase + offset; } |
| 459 | uint to_bci(uint bii); |
| 460 | void (int& max_stack, |
| 461 | int& max_na_locals, |
| 462 | int& handler_count, |
| 463 | int& cflags); |
| 464 | band* ref_band_for_self_op(int bc, bool& isAloadVar, int& origBCVar); |
| 465 | band* ref_band_for_op(int bc); |
| 466 | |
| 467 | // Definitions of standard classfile int formats: |
| 468 | static void putu1_at(byte* wp, int n) { assert(n == (n & 0xFF)); wp[0] = n; } |
| 469 | static void putu2_at(byte* wp, int n); |
| 470 | static void putu4_at(byte* wp, int n); |
| 471 | static void putu8_at(byte* wp, jlong n); |
| 472 | |
| 473 | // Private stuff |
| 474 | void reset_cur_classfile(); |
| 475 | void write_classfile_tail(); |
| 476 | void write_classfile_head(); |
| 477 | void write_code(); |
| 478 | void write_bc_ops(); |
| 479 | void write_members(int num, int attrc); // attrc=ATTR_CONTEXT_FIELD/METHOD |
| 480 | int write_attrs(int attrc, julong indexBits); |
| 481 | int write_ics(int naOffset, int na); |
| 482 | int write_bsms(int naOffset, int na); |
| 483 | |
| 484 | // The readers |
| 485 | void read_bands(); |
| 486 | void (); |
| 487 | void read_cp(); |
| 488 | void read_cp_counts(value_stream& hdr); |
| 489 | void read_attr_defs(); |
| 490 | void read_ics(); |
| 491 | void read_attrs(int attrc, int obj_count); |
| 492 | void read_classes(); |
| 493 | void (); |
| 494 | void read_bcs(); |
| 495 | void read_bc_ops(); |
| 496 | void read_files(); |
| 497 | void read_Utf8_values(entry* cpMap, int len); |
| 498 | void read_single_words(band& cp_band, entry* cpMap, int len); |
| 499 | void read_double_words(band& cp_bands, entry* cpMap, int len); |
| 500 | void read_single_refs(band& cp_band, byte refTag, entry* cpMap, int len); |
| 501 | void read_double_refs(band& cp_band, byte ref1Tag, byte ref2Tag, entry* cpMap, int len); |
| 502 | void read_signature_values(entry* cpMap, int len); |
| 503 | void read_method_handle(entry* cpMap, int len); |
| 504 | void read_method_type(entry* cpMap, int len); |
| 505 | void read_bootstrap_methods(entry* cpMap, int len); |
| 506 | }; |
| 507 | |
| 508 | inline void cpool::abort(const char* msg) { u->abort(msg); } |
| 509 | inline bool cpool::aborting() { return u->aborting(); } |
| 510 | |