jcf-reader.c 15.1 KB
Newer Older
Anthony Green committed
1 2 3
/* This file read a Java(TM) .class file.
   It is not stand-alone:  It depends on tons of macros, and the
   intent is you #include this file after you've defined the macros.
4
   Copyright (C) 1996-2014 Free Software Foundation, Inc.
Anthony Green committed
5

6
This file is part of GCC.
Anthony Green committed
7

8
GCC is free software; you can redistribute it and/or modify
Anthony Green committed
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 3, or (at your option)
Anthony Green committed
11 12
any later version.

13
GCC is distributed in the hope that it will be useful,
Anthony Green committed
14 15 16 17 18
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
19 20
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  
Anthony Green committed
21 22 23 24 25

Java and all Java-based marks are trademarks or registered trademarks
of Sun Microsystems, Inc. in the United States and other countries.
The Free Software Foundation is independent of Sun Microsystems, Inc.  */

26
#include "ggc.h"
Anthony Green committed
27 28 29
#include "jcf.h"
#include "zipfile.h"

30
static int get_attribute (JCF *, int, jv_attr_type);
31 32 33 34
static int jcf_parse_preamble (JCF *);
static int jcf_parse_constant_pool (JCF *);
static void jcf_parse_class (JCF *);
static int jcf_parse_fields (JCF *);
35
static int jcf_parse_one_method (JCF *, int);
36 37
static int jcf_parse_methods (JCF *);
static int jcf_parse_final_attributes (JCF *);
38
static int jcf_parse_bootstrap_methods (JCF *, int) ATTRIBUTE_UNUSED;
Kaveh R. Ghazi committed
39
#ifdef NEED_PEEK_ATTRIBUTE
40
static int peek_attribute (JCF *, int, const char *, int);
Kaveh R. Ghazi committed
41 42
#endif
#ifdef NEED_SKIP_ATTRIBUTE
43
static void skip_attribute (JCF *, int);
Kaveh R. Ghazi committed
44
#endif
45

46 47 48 49 50
/* Go through all available attribute (ATTRIBUTE_NUMER) and try to
   identify PEEKED_NAME.  Return 1 if PEEKED_NAME was found, 0
   otherwise. JCF is restored to its initial position before
   returning.  */

Kaveh R. Ghazi committed
51
#ifdef NEED_PEEK_ATTRIBUTE	/* Not everyone uses this function */
52
static int
53 54
peek_attribute (JCF *jcf, int attribute_number, const char *peeked_name,
		int peeked_name_length)
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
{
  int to_return = 0;
  long absolute_offset = (long)JCF_TELL (jcf);
  int i;

  for (i = 0; !to_return && i < attribute_number; i++)
    {
      uint16 attribute_name = (JCF_FILL (jcf, 6), JCF_readu2 (jcf));
      uint32 attribute_length = JCF_readu4 (jcf);
      int name_length;
      const unsigned char *name_data; 

      JCF_FILL (jcf, (long) attribute_length);
      if (attribute_name <= 0 || attribute_name >= JPOOL_SIZE(jcf)
	  || JPOOL_TAG (jcf, attribute_name) != CONSTANT_Utf8)
	continue;

      name_length = JPOOL_UTF_LENGTH (jcf, attribute_name);
      name_data = JPOOL_UTF_DATA (jcf, attribute_name);

      if (name_length == peeked_name_length 
	  && ! memcmp (name_data, peeked_name, peeked_name_length)) 
	{
	  to_return = 1; 
	  break;
	}
      
      JCF_SKIP (jcf, attribute_length);
    }

  JCF_SEEK (jcf, absolute_offset);
  return to_return;
}
Kaveh R. Ghazi committed
88
#endif
89

Kaveh R. Ghazi committed
90
#ifdef NEED_SKIP_ATTRIBUTE	/* Not everyone uses this function */
91
static void
92
skip_attribute (JCF *jcf, int number_of_attribute)
93 94 95
{
  while (number_of_attribute--)
    {
96
      JCF_u4 N;
97 98
      JCF_FILL (jcf, 6);
      (void) JCF_readu2 (jcf);
99 100
      N = JCF_readu4 (jcf);
      JCF_SKIP (jcf, N);
101 102
    }
}
Kaveh R. Ghazi committed
103
#endif
104

105
static int
106 107
get_attribute (JCF *jcf, int index, 
	       jv_attr_type attr_type ATTRIBUTE_UNUSED)
Anthony Green committed
108 109 110 111 112
{
  uint16 attribute_name = (JCF_FILL (jcf, 6), JCF_readu2 (jcf));
  uint32 attribute_length = JCF_readu4 (jcf);
  uint32 start_pos = JCF_TELL(jcf);
  int name_length;
113
  const unsigned char *name_data;
114
  JCF_FILL (jcf, (long) attribute_length);
Anthony Green committed
115 116 117 118 119 120 121
  if (attribute_name <= 0 || attribute_name >= JPOOL_SIZE(jcf))
    return -2;
  if (JPOOL_TAG (jcf, attribute_name) != CONSTANT_Utf8)
    return -2;
  name_length = JPOOL_UTF_LENGTH (jcf, attribute_name);
  name_data = JPOOL_UTF_DATA (jcf, attribute_name);

122 123 124
#define MATCH_ATTRIBUTE(S) \
  (name_length == sizeof (S)-1 && memcmp (name_data, S, sizeof (S)-1) == 0)

Anthony Green committed
125 126 127 128 129 130 131 132
#ifdef IGNORE_ATTRIBUTE
   if (IGNORE_ATTRIBUTE (jcf, attribute_name, attribute_length))
     {
       JCF_SKIP (jcf, attribute_length);
     }
   else
#endif
#ifdef HANDLE_SOURCEFILE
133
  if (MATCH_ATTRIBUTE ("SourceFile"))
Anthony Green committed
134 135 136 137 138 139 140
    {
      uint16 sourcefile_index = JCF_readu2 (jcf);
      HANDLE_SOURCEFILE(sourcefile_index);
    }
  else
#endif
#ifdef HANDLE_CONSTANTVALUE
141
  if (MATCH_ATTRIBUTE ("ConstantValue"))
Anthony Green committed
142 143 144 145 146 147 148 149 150
    {
      uint16 constantvalue_index = JCF_readu2 (jcf);
      if (constantvalue_index <= 0 || constantvalue_index >= JPOOL_SIZE(jcf))
	return -2;
      HANDLE_CONSTANTVALUE(constantvalue_index);
    }
  else
#endif
#ifdef HANDLE_CODE_ATTRIBUTE
151
  if (MATCH_ATTRIBUTE ("Code"))
Anthony Green committed
152 153
    {
      uint16 j;
Kaveh R. Ghazi committed
154 155
      uint16 max_stack ATTRIBUTE_UNUSED = JCF_readu2 (jcf);
      uint16 max_locals ATTRIBUTE_UNUSED = JCF_readu2 (jcf);
Anthony Green committed
156 157 158 159 160 161 162 163 164
      uint32 code_length = JCF_readu4 (jcf);
      uint16 exception_table_length, attributes_count;
      if (code_length + 12 > attribute_length)
	return -1;
      HANDLE_CODE_ATTRIBUTE(max_stack, max_locals, code_length);
      JCF_SKIP (jcf, code_length);
      exception_table_length = JCF_readu2 (jcf);
      if (code_length + 8 * exception_table_length + 12 > attribute_length)
	return -1;
Per Bothner committed
165 166 167
#ifdef HANDLE_EXCEPTION_TABLE
      HANDLE_EXCEPTION_TABLE (jcf->read_ptr, exception_table_length);
#endif
Anthony Green committed
168 169 170 171
      JCF_SKIP (jcf, 2 * 4 * exception_table_length);
      attributes_count = JCF_readu2 (jcf);
      for (j = 0; j < attributes_count; j++)
	{
172
	  int code = get_attribute (jcf, index, JV_METHOD_ATTR);
Anthony Green committed
173 174 175 176 177 178 179
	  if (code != 0)
	    return code;
	}
    }
  else
#endif /* HANDLE_CODE_ATTRIBUTE */
#ifdef HANDLE_EXCEPTIONS_ATTRIBUTE
180
  if (MATCH_ATTRIBUTE ("Exceptions"))
Anthony Green committed
181 182 183 184 185 186 187
    {
      uint16 count = JCF_readu2 (jcf);
      HANDLE_EXCEPTIONS_ATTRIBUTE (count);
    }
  else
#endif
#ifdef HANDLE_LINENUMBERTABLE_ATTRIBUTE
188
  if (MATCH_ATTRIBUTE ("LineNumberTable"))
Anthony Green committed
189 190 191 192 193 194 195
    {
      uint16 count = JCF_readu2 (jcf);
      HANDLE_LINENUMBERTABLE_ATTRIBUTE (count);
    }
  else
#endif
#ifdef HANDLE_LOCALVARIABLETABLE_ATTRIBUTE
196
  if (MATCH_ATTRIBUTE ("LocalVariableTable"))
Anthony Green committed
197 198 199 200 201 202
    {
      uint16 count = JCF_readu2 (jcf);
      HANDLE_LOCALVARIABLETABLE_ATTRIBUTE (count);
    }
  else
#endif
203 204 205 206 207 208 209 210
#ifdef HANDLE_LOCALVARIABLETYPETABLE_ATTRIBUTE
  if (MATCH_ATTRIBUTE ("LocalVariableTypeTable"))
    {
      uint16 count = JCF_readu2 (jcf);
      HANDLE_LOCALVARIABLETYPETABLE_ATTRIBUTE (count);
    }
  else
#endif
211
#ifdef HANDLE_INNERCLASSES_ATTRIBUTE
212
  if (MATCH_ATTRIBUTE ("InnerClasses"))
213 214 215 216 217 218
    {
      uint16 count = JCF_readu2 (jcf);
      HANDLE_INNERCLASSES_ATTRIBUTE (count);
    }
  else
#endif
219
#ifdef HANDLE_SYNTHETIC_ATTRIBUTE
220
  if (MATCH_ATTRIBUTE ("Synthetic"))
221 222 223 224 225
    {
      HANDLE_SYNTHETIC_ATTRIBUTE ();
    }
  else
#endif
226 227 228 229 230 231 232
#ifdef HANDLE_GCJCOMPILED_ATTRIBUTE
  if (MATCH_ATTRIBUTE ("gnu.gcj.gcj-compiled"))
    {
      HANDLE_GCJCOMPILED_ATTRIBUTE ();
    }
  else
#endif
233 234 235 236 237 238 239
#ifdef HANDLE_DEPRECATED_ATTRIBUTE
  if (MATCH_ATTRIBUTE ("Deprecated"))
    {
      HANDLE_DEPRECATED_ATTRIBUTE ();
    }
  else
#endif
240 241 242 243 244 245 246
#ifdef HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE
  if (MATCH_ATTRIBUTE ("SourceDebugExtension")) /* JSR 45 */
    {
      HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE (attribute_length);
    }
  else
#endif
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
#ifdef HANDLE_ENCLOSINGMETHOD_ATTRIBUTE
  if (MATCH_ATTRIBUTE ("EnclosingMethod"))
    {
      HANDLE_ENCLOSINGMETHOD_ATTRIBUTE ();
    }
  else
#endif
#ifdef HANDLE_SIGNATURE_ATTRIBUTE
  if (MATCH_ATTRIBUTE ("Signature"))
    {
      HANDLE_SIGNATURE_ATTRIBUTE ();
    }
  else
#endif
#ifdef HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE
  if (MATCH_ATTRIBUTE ("RuntimeVisibleAnnotations"))
    {
      HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE ();
    }
  else
#endif
#ifdef HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE
  if (MATCH_ATTRIBUTE ("RuntimeInvisibleAnnotations"))
    {
      HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE ();
    }
  else
#endif
#ifdef HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE
  if (MATCH_ATTRIBUTE ("RuntimeVisibleParameterAnnotations"))
    {
      HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE ();
    }
  else
#endif
#ifdef HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE
  if (MATCH_ATTRIBUTE ("RuntimeInvisibleParameterAnnotations"))
    {
      HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE ();
    }
  else
#endif
#ifdef HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE
  if (MATCH_ATTRIBUTE ("AnnotationDefault"))
    {
      HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE ();
    }
  else
#endif
296 297 298 299 300 301 302 303 304
  if (MATCH_ATTRIBUTE ("BootstrapMethods"))
    {
#ifdef HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE
      HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE();
#else
      JCF_SKIP (jcf, attribute_length);
#endif
    }
   else
Anthony Green committed
305 306 307 308 309 310 311
    {
#ifdef PROCESS_OTHER_ATTRIBUTE
      PROCESS_OTHER_ATTRIBUTE(jcf, attribute_name, attribute_length);
#else
      JCF_SKIP (jcf, attribute_length);
#endif
    }
312
  if ((long) (start_pos + attribute_length) != JCF_TELL(jcf))
Anthony Green committed
313 314 315 316 317
    return -1;
  return 0;
}

/* Read and handle the pre-amble. */
318
static int
319
jcf_parse_preamble (JCF* jcf)
Anthony Green committed
320 321
{
  uint32 magic = (JCF_FILL (jcf, 8), JCF_readu4 (jcf));
322 323
  uint16 minor_version ATTRIBUTE_UNUSED = JCF_readu2 (jcf);
  uint16 major_version ATTRIBUTE_UNUSED = JCF_readu2 (jcf);
Anthony Green committed
324 325 326 327 328 329 330 331 332 333 334 335 336 337
#ifdef HANDLE_MAGIC
  HANDLE_MAGIC (magic, minor_version, major_version);
#endif
  if (magic != 0xcafebabe)
    return -1;
  else
    return 0;
}

/* Read and handle the constant pool.

   Return 0 if OK.
   Return -2 if a bad cross-reference (index of other constant) was seen.
*/
338
static int
339
jcf_parse_constant_pool (JCF* jcf)
Anthony Green committed
340 341 342
{
  int i, n;
  JPOOL_SIZE (jcf) = (JCF_FILL (jcf, 2), JCF_readu2 (jcf));
343
  jcf->cpool.tags = (uint8 *) ggc_alloc_atomic (JPOOL_SIZE (jcf));
344 345
  jcf->cpool.data = (cpool_entry *) ggc_internal_cleared_alloc
    (sizeof (jword) * JPOOL_SIZE (jcf));
Anthony Green committed
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
  jcf->cpool.tags[0] = 0;
#ifdef HANDLE_START_CONSTANT_POOL
  HANDLE_START_CONSTANT_POOL (JPOOL_SIZE (jcf));
#endif
  for (i = 1; i < (int) JPOOL_SIZE (jcf); i++)
    {
      int constant_kind;
       
      /* Make sure at least 9 bytes are available.  This is enough
	 for all fixed-sized constant pool entries (so we don't need many
	 more JCF_FILL calls below), but is is small enough that
	 we are guaranteed to not hit EOF (in a valid .class file). */
      JCF_FILL (jcf, 9);
      constant_kind = JCF_readu (jcf);
      jcf->cpool.tags[i] = constant_kind;
      switch (constant_kind)
	{
	case CONSTANT_String:
	case CONSTANT_Class:
365
	  jcf->cpool.data[i].w = JCF_readu2 (jcf);
Anthony Green committed
366 367 368 369 370
	  break;
	case CONSTANT_Fieldref:
	case CONSTANT_Methodref:
	case CONSTANT_InterfaceMethodref:
	case CONSTANT_NameAndType:
371 372
	  jcf->cpool.data[i].w = JCF_readu2 (jcf);
	  jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16;
Anthony Green committed
373 374 375
	  break;
	case CONSTANT_Integer:
	case CONSTANT_Float:
376
	  jcf->cpool.data[i].w = JCF_readu4 (jcf);
Anthony Green committed
377 378 379
	  break;
	case CONSTANT_Long:
	case CONSTANT_Double:
380
	  jcf->cpool.data[i].w = JCF_readu4 (jcf);
Anthony Green committed
381 382
	  i++; /* These take up two spots in the constant pool */
	  jcf->cpool.tags[i] = 0;
383
	  jcf->cpool.data[i].w = JCF_readu4 (jcf);
Anthony Green committed
384 385 386 387 388 389 390
	  break;
	case CONSTANT_Utf8:
	  n = JCF_readu2 (jcf);
	  JCF_FILL (jcf, n);
#ifdef HANDLE_CONSTANT_Utf8
	  HANDLE_CONSTANT_Utf8(jcf, i, n);
#else
391
	  jcf->cpool.data[i].w = JCF_TELL(jcf) - 2;
Anthony Green committed
392 393 394
	  JCF_SKIP (jcf, n);
#endif
	  break;
395 396 397 398 399 400 401 402 403 404 405
	case CONSTANT_MethodHandle:
	  jcf->cpool.data[i].w = JCF_readu (jcf);
	  jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16;
	  break;
	case CONSTANT_MethodType:
	  jcf->cpool.data[i].w = JCF_readu2 (jcf);
	  break;
	case CONSTANT_InvokeDynamic:
	  jcf->cpool.data[i].w = JCF_readu2 (jcf);
	  jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16;
	  break;
Anthony Green committed
406 407 408 409 410 411 412 413 414
	default:
	  return i;
	}
    }
  return 0;
}

/* Read various class flags and numbers. */

415
static void
416
jcf_parse_class (JCF* jcf)
Anthony Green committed
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
{
  int i;
  uint16 interfaces_count;
  JCF_FILL (jcf, 8);
  jcf->access_flags = JCF_readu2 (jcf);
  jcf->this_class = JCF_readu2 (jcf);
  jcf->super_class = JCF_readu2 (jcf);
  interfaces_count = JCF_readu2 (jcf);

#ifdef HANDLE_CLASS_INFO
  HANDLE_CLASS_INFO(jcf->access_flags, jcf->this_class, jcf->super_class, interfaces_count);
#endif

  JCF_FILL (jcf, 2 * interfaces_count);

  /* Read interfaces. */
  for (i = 0; i < interfaces_count; i++)
    {
Kaveh R. Ghazi committed
435
      uint16 index ATTRIBUTE_UNUSED = JCF_readu2 (jcf);
Anthony Green committed
436 437 438 439 440 441 442
#ifdef HANDLE_CLASS_INTERFACE
      HANDLE_CLASS_INTERFACE (index);
#endif
    }
}

/* Read fields. */
443
static int
444
jcf_parse_fields (JCF* jcf)
Anthony Green committed
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
{
  int i, j;
  uint16 fields_count;
  JCF_FILL (jcf, 2);
  fields_count = JCF_readu2 (jcf);

#ifdef HANDLE_START_FIELDS
  HANDLE_START_FIELDS (fields_count);
#endif
  for (i = 0; i < fields_count; i++)
    {
      uint16 access_flags = (JCF_FILL (jcf, 8), JCF_readu2 (jcf));
      uint16 name_index = JCF_readu2 (jcf);
      uint16 signature_index = JCF_readu2 (jcf);
      uint16 attribute_count = JCF_readu2 (jcf);
#ifdef HANDLE_START_FIELD
      HANDLE_START_FIELD (access_flags, name_index, signature_index,
462
			  attribute_count);
Anthony Green committed
463 464 465
#endif
      for (j = 0; j < attribute_count; j++)
	{
466
	  int code = get_attribute (jcf, i, JV_FIELD_ATTR);
Anthony Green committed
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
	  if (code != 0)
	    return code;
	}
#ifdef HANDLE_END_FIELD
      HANDLE_END_FIELD ();
#endif
    }
#ifdef HANDLE_END_FIELDS
  HANDLE_END_FIELDS ();
#endif
  return 0;
}

/* Read methods. */

482
static int
483
jcf_parse_one_method (JCF* jcf, int index)
Anthony Green committed
484 485 486 487 488 489 490 491 492 493 494
{
  int i;
  uint16 access_flags = (JCF_FILL (jcf, 8), JCF_readu2 (jcf));
  uint16 name_index = JCF_readu2 (jcf);
  uint16 signature_index = JCF_readu2 (jcf);
  uint16 attribute_count = JCF_readu2 (jcf);
#ifdef HANDLE_METHOD
  HANDLE_METHOD(access_flags, name_index, signature_index, attribute_count);
#endif
  for (i = 0; i < attribute_count; i++)
    {
495
      int code = get_attribute (jcf, index, JV_METHOD_ATTR);
Anthony Green committed
496 497 498
      if (code != 0)
	return code;
    }
499 500 501
#ifdef HANDLE_END_METHOD
  HANDLE_END_METHOD ();
#endif
Anthony Green committed
502 503 504
  return 0;
}

505
static int
506
jcf_parse_methods (JCF* jcf)
Anthony Green committed
507 508 509 510 511 512 513 514 515 516
{
  int i;
  uint16 methods_count;
  JCF_FILL (jcf, 2);
  methods_count = JCF_readu2 (jcf);
#ifdef HANDLE_START_METHODS
  HANDLE_START_METHODS (methods_count);
#endif
  for (i = 0; i < methods_count; i++)
    {
517
      int code = jcf_parse_one_method (jcf, i);
Anthony Green committed
518 519 520 521 522 523 524 525 526 527
      if (code != 0)
	return code;
    }
#ifdef HANDLE_END_METHODS
  HANDLE_END_METHODS ();
#endif
  return 0;
}

/* Read attributes. */
528
static int
529
jcf_parse_final_attributes (JCF *jcf)
Anthony Green committed
530 531 532 533 534 535 536 537
{
  int i;
  uint16 attributes_count = (JCF_FILL (jcf, 2), JCF_readu2 (jcf));
#ifdef START_FINAL_ATTRIBUTES
  START_FINAL_ATTRIBUTES (attributes_count)
#endif
  for (i = 0; i < attributes_count; i++)
    {
538
      int code = get_attribute (jcf, i, JV_CLASS_ATTR);
Anthony Green committed
539 540 541 542 543 544
      if (code != 0)
	return code;
    }
  return 0;
}

545 546 547 548 549 550 551 552 553 554
/* Read and handle the "BootstrapMethods" attribute.

   Return 0 if OK.
*/
static int
jcf_parse_bootstrap_methods (JCF* jcf, int attribute_length ATTRIBUTE_UNUSED)
{
  int i;
  uint16 num_methods = JCF_readu2 (jcf);
  jcf->bootstrap_methods.count = num_methods;
555
  jcf->bootstrap_methods.methods = ggc_vec_alloc<bootstrap_method> (num_methods);
556 557 558 559 560 561 562 563 564 565
#ifdef HANDLE_START_BOOTSTRAP_METHODS
  HANDLE_START_BOOTSTRAP_METHODS (jcf, num_methods);
#endif

  for (i = 0; i < num_methods; i++)
    {
      unsigned j;
      bootstrap_method *m = &jcf->bootstrap_methods.methods[i];
      m->method_ref = JCF_readu2 (jcf);
      m->num_arguments = JCF_readu2 (jcf);
566
      m->bootstrap_arguments = ggc_vec_alloc<unsigned> (m->num_arguments);
567 568 569 570 571 572 573 574 575 576
      for (j = 0; j < m->num_arguments; j++)
	m->bootstrap_arguments[j] = JCF_readu2 (jcf);
    }

#ifdef HANDLE_END_BOOTSTRAP_METHODS
  HANDLE_END_BOOTSTRAP_METHODS (num_methods);
#endif

  return 0;
}