]>
Commit | Line | Data |
---|---|---|
e04a16fb AG |
1 | /* This file read a Java(TM) .class file. |
2 | It is not stand-alone: It depends on tons of macros, and the | |
3 | intent is you #include this file after you've defined the macros. | |
23a5b65a | 4 | Copyright (C) 1996-2014 Free Software Foundation, Inc. |
e04a16fb | 5 | |
f309ff0a | 6 | This file is part of GCC. |
e04a16fb | 7 | |
f309ff0a | 8 | GCC is free software; you can redistribute it and/or modify |
e04a16fb | 9 | it under the terms of the GNU General Public License as published by |
8328d52a | 10 | the Free Software Foundation; either version 3, or (at your option) |
e04a16fb AG |
11 | any later version. |
12 | ||
f309ff0a | 13 | GCC is distributed in the hope that it will be useful, |
e04a16fb AG |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
8328d52a NC |
19 | along with GCC; see the file COPYING3. If not see |
20 | <http://www.gnu.org/licenses/>. | |
e04a16fb AG |
21 | |
22 | Java and all Java-based marks are trademarks or registered trademarks | |
23 | of Sun Microsystems, Inc. in the United States and other countries. | |
24 | The Free Software Foundation is independent of Sun Microsystems, Inc. */ | |
25 | ||
f67cc87d | 26 | #include "ggc.h" |
e04a16fb AG |
27 | #include "jcf.h" |
28 | #include "zipfile.h" | |
29 | ||
97b8365c | 30 | static int get_attribute (JCF *, int, jv_attr_type); |
d2097937 KG |
31 | static int jcf_parse_preamble (JCF *); |
32 | static int jcf_parse_constant_pool (JCF *); | |
33 | static void jcf_parse_class (JCF *); | |
34 | static int jcf_parse_fields (JCF *); | |
97b8365c | 35 | static int jcf_parse_one_method (JCF *, int); |
d2097937 KG |
36 | static int jcf_parse_methods (JCF *); |
37 | static int jcf_parse_final_attributes (JCF *); | |
e9184c9e | 38 | static int jcf_parse_bootstrap_methods (JCF *, int) ATTRIBUTE_UNUSED; |
80393943 | 39 | #ifdef NEED_PEEK_ATTRIBUTE |
d2097937 | 40 | static int peek_attribute (JCF *, int, const char *, int); |
80393943 KG |
41 | #endif |
42 | #ifdef NEED_SKIP_ATTRIBUTE | |
d2097937 | 43 | static void skip_attribute (JCF *, int); |
80393943 | 44 | #endif |
c8e7d2e6 | 45 | |
f0f3a777 APB |
46 | /* Go through all available attribute (ATTRIBUTE_NUMER) and try to |
47 | identify PEEKED_NAME. Return 1 if PEEKED_NAME was found, 0 | |
48 | otherwise. JCF is restored to its initial position before | |
49 | returning. */ | |
50 | ||
80393943 | 51 | #ifdef NEED_PEEK_ATTRIBUTE /* Not everyone uses this function */ |
f0f3a777 | 52 | static int |
0a2f0c54 KG |
53 | peek_attribute (JCF *jcf, int attribute_number, const char *peeked_name, |
54 | int peeked_name_length) | |
f0f3a777 APB |
55 | { |
56 | int to_return = 0; | |
57 | long absolute_offset = (long)JCF_TELL (jcf); | |
58 | int i; | |
59 | ||
60 | for (i = 0; !to_return && i < attribute_number; i++) | |
61 | { | |
62 | uint16 attribute_name = (JCF_FILL (jcf, 6), JCF_readu2 (jcf)); | |
63 | uint32 attribute_length = JCF_readu4 (jcf); | |
64 | int name_length; | |
65 | const unsigned char *name_data; | |
66 | ||
67 | JCF_FILL (jcf, (long) attribute_length); | |
68 | if (attribute_name <= 0 || attribute_name >= JPOOL_SIZE(jcf) | |
69 | || JPOOL_TAG (jcf, attribute_name) != CONSTANT_Utf8) | |
70 | continue; | |
71 | ||
72 | name_length = JPOOL_UTF_LENGTH (jcf, attribute_name); | |
73 | name_data = JPOOL_UTF_DATA (jcf, attribute_name); | |
74 | ||
75 | if (name_length == peeked_name_length | |
76 | && ! memcmp (name_data, peeked_name, peeked_name_length)) | |
77 | { | |
78 | to_return = 1; | |
79 | break; | |
80 | } | |
81 | ||
82 | JCF_SKIP (jcf, attribute_length); | |
83 | } | |
84 | ||
85 | JCF_SEEK (jcf, absolute_offset); | |
86 | return to_return; | |
87 | } | |
80393943 | 88 | #endif |
f0f3a777 | 89 | |
80393943 | 90 | #ifdef NEED_SKIP_ATTRIBUTE /* Not everyone uses this function */ |
f0f3a777 | 91 | static void |
0a2f0c54 | 92 | skip_attribute (JCF *jcf, int number_of_attribute) |
f0f3a777 APB |
93 | { |
94 | while (number_of_attribute--) | |
95 | { | |
b4bbc8b7 | 96 | JCF_u4 N; |
f0f3a777 APB |
97 | JCF_FILL (jcf, 6); |
98 | (void) JCF_readu2 (jcf); | |
b4bbc8b7 DN |
99 | N = JCF_readu4 (jcf); |
100 | JCF_SKIP (jcf, N); | |
f0f3a777 APB |
101 | } |
102 | } | |
80393943 | 103 | #endif |
f0f3a777 | 104 | |
c8e7d2e6 | 105 | static int |
97b8365c TT |
106 | get_attribute (JCF *jcf, int index, |
107 | jv_attr_type attr_type ATTRIBUTE_UNUSED) | |
e04a16fb AG |
108 | { |
109 | uint16 attribute_name = (JCF_FILL (jcf, 6), JCF_readu2 (jcf)); | |
110 | uint32 attribute_length = JCF_readu4 (jcf); | |
111 | uint32 start_pos = JCF_TELL(jcf); | |
112 | int name_length; | |
c8e7d2e6 | 113 | const unsigned char *name_data; |
b4b63e32 | 114 | JCF_FILL (jcf, (long) attribute_length); |
e04a16fb AG |
115 | if (attribute_name <= 0 || attribute_name >= JPOOL_SIZE(jcf)) |
116 | return -2; | |
117 | if (JPOOL_TAG (jcf, attribute_name) != CONSTANT_Utf8) | |
118 | return -2; | |
119 | name_length = JPOOL_UTF_LENGTH (jcf, attribute_name); | |
120 | name_data = JPOOL_UTF_DATA (jcf, attribute_name); | |
121 | ||
b124f72e APB |
122 | #define MATCH_ATTRIBUTE(S) \ |
123 | (name_length == sizeof (S)-1 && memcmp (name_data, S, sizeof (S)-1) == 0) | |
124 | ||
e04a16fb AG |
125 | #ifdef IGNORE_ATTRIBUTE |
126 | if (IGNORE_ATTRIBUTE (jcf, attribute_name, attribute_length)) | |
127 | { | |
128 | JCF_SKIP (jcf, attribute_length); | |
129 | } | |
130 | else | |
131 | #endif | |
132 | #ifdef HANDLE_SOURCEFILE | |
b124f72e | 133 | if (MATCH_ATTRIBUTE ("SourceFile")) |
e04a16fb AG |
134 | { |
135 | uint16 sourcefile_index = JCF_readu2 (jcf); | |
136 | HANDLE_SOURCEFILE(sourcefile_index); | |
137 | } | |
138 | else | |
139 | #endif | |
140 | #ifdef HANDLE_CONSTANTVALUE | |
b124f72e | 141 | if (MATCH_ATTRIBUTE ("ConstantValue")) |
e04a16fb AG |
142 | { |
143 | uint16 constantvalue_index = JCF_readu2 (jcf); | |
144 | if (constantvalue_index <= 0 || constantvalue_index >= JPOOL_SIZE(jcf)) | |
145 | return -2; | |
146 | HANDLE_CONSTANTVALUE(constantvalue_index); | |
147 | } | |
148 | else | |
149 | #endif | |
150 | #ifdef HANDLE_CODE_ATTRIBUTE | |
b124f72e | 151 | if (MATCH_ATTRIBUTE ("Code")) |
e04a16fb AG |
152 | { |
153 | uint16 j; | |
7e21fe59 KG |
154 | uint16 max_stack ATTRIBUTE_UNUSED = JCF_readu2 (jcf); |
155 | uint16 max_locals ATTRIBUTE_UNUSED = JCF_readu2 (jcf); | |
e04a16fb AG |
156 | uint32 code_length = JCF_readu4 (jcf); |
157 | uint16 exception_table_length, attributes_count; | |
158 | if (code_length + 12 > attribute_length) | |
159 | return -1; | |
160 | HANDLE_CODE_ATTRIBUTE(max_stack, max_locals, code_length); | |
161 | JCF_SKIP (jcf, code_length); | |
162 | exception_table_length = JCF_readu2 (jcf); | |
163 | if (code_length + 8 * exception_table_length + 12 > attribute_length) | |
164 | return -1; | |
8376a32e PB |
165 | #ifdef HANDLE_EXCEPTION_TABLE |
166 | HANDLE_EXCEPTION_TABLE (jcf->read_ptr, exception_table_length); | |
167 | #endif | |
e04a16fb AG |
168 | JCF_SKIP (jcf, 2 * 4 * exception_table_length); |
169 | attributes_count = JCF_readu2 (jcf); | |
170 | for (j = 0; j < attributes_count; j++) | |
171 | { | |
97b8365c | 172 | int code = get_attribute (jcf, index, JV_METHOD_ATTR); |
e04a16fb AG |
173 | if (code != 0) |
174 | return code; | |
175 | } | |
176 | } | |
177 | else | |
178 | #endif /* HANDLE_CODE_ATTRIBUTE */ | |
179 | #ifdef HANDLE_EXCEPTIONS_ATTRIBUTE | |
b124f72e | 180 | if (MATCH_ATTRIBUTE ("Exceptions")) |
e04a16fb AG |
181 | { |
182 | uint16 count = JCF_readu2 (jcf); | |
183 | HANDLE_EXCEPTIONS_ATTRIBUTE (count); | |
184 | } | |
185 | else | |
186 | #endif | |
187 | #ifdef HANDLE_LINENUMBERTABLE_ATTRIBUTE | |
b124f72e | 188 | if (MATCH_ATTRIBUTE ("LineNumberTable")) |
e04a16fb AG |
189 | { |
190 | uint16 count = JCF_readu2 (jcf); | |
191 | HANDLE_LINENUMBERTABLE_ATTRIBUTE (count); | |
192 | } | |
193 | else | |
194 | #endif | |
195 | #ifdef HANDLE_LOCALVARIABLETABLE_ATTRIBUTE | |
b124f72e | 196 | if (MATCH_ATTRIBUTE ("LocalVariableTable")) |
e04a16fb AG |
197 | { |
198 | uint16 count = JCF_readu2 (jcf); | |
199 | HANDLE_LOCALVARIABLETABLE_ATTRIBUTE (count); | |
200 | } | |
201 | else | |
c2952b01 | 202 | #endif |
97b8365c TT |
203 | #ifdef HANDLE_LOCALVARIABLETYPETABLE_ATTRIBUTE |
204 | if (MATCH_ATTRIBUTE ("LocalVariableTypeTable")) | |
205 | { | |
206 | uint16 count = JCF_readu2 (jcf); | |
207 | HANDLE_LOCALVARIABLETYPETABLE_ATTRIBUTE (count); | |
208 | } | |
209 | else | |
210 | #endif | |
c2952b01 | 211 | #ifdef HANDLE_INNERCLASSES_ATTRIBUTE |
b124f72e | 212 | if (MATCH_ATTRIBUTE ("InnerClasses")) |
c2952b01 APB |
213 | { |
214 | uint16 count = JCF_readu2 (jcf); | |
215 | HANDLE_INNERCLASSES_ATTRIBUTE (count); | |
216 | } | |
217 | else | |
493d561d APB |
218 | #endif |
219 | #ifdef HANDLE_SYNTHETIC_ATTRIBUTE | |
b124f72e | 220 | if (MATCH_ATTRIBUTE ("Synthetic")) |
493d561d APB |
221 | { |
222 | HANDLE_SYNTHETIC_ATTRIBUTE (); | |
223 | } | |
224 | else | |
b124f72e APB |
225 | #endif |
226 | #ifdef HANDLE_GCJCOMPILED_ATTRIBUTE | |
227 | if (MATCH_ATTRIBUTE ("gnu.gcj.gcj-compiled")) | |
228 | { | |
229 | HANDLE_GCJCOMPILED_ATTRIBUTE (); | |
230 | } | |
231 | else | |
f94ae540 TT |
232 | #endif |
233 | #ifdef HANDLE_DEPRECATED_ATTRIBUTE | |
234 | if (MATCH_ATTRIBUTE ("Deprecated")) | |
235 | { | |
236 | HANDLE_DEPRECATED_ATTRIBUTE (); | |
237 | } | |
238 | else | |
837491bc PB |
239 | #endif |
240 | #ifdef HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE | |
241 | if (MATCH_ATTRIBUTE ("SourceDebugExtension")) /* JSR 45 */ | |
242 | { | |
243 | HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE (attribute_length); | |
244 | } | |
245 | else | |
97b8365c TT |
246 | #endif |
247 | #ifdef HANDLE_ENCLOSINGMETHOD_ATTRIBUTE | |
248 | if (MATCH_ATTRIBUTE ("EnclosingMethod")) | |
249 | { | |
250 | HANDLE_ENCLOSINGMETHOD_ATTRIBUTE (); | |
251 | } | |
252 | else | |
253 | #endif | |
254 | #ifdef HANDLE_SIGNATURE_ATTRIBUTE | |
255 | if (MATCH_ATTRIBUTE ("Signature")) | |
256 | { | |
257 | HANDLE_SIGNATURE_ATTRIBUTE (); | |
258 | } | |
259 | else | |
260 | #endif | |
261 | #ifdef HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE | |
262 | if (MATCH_ATTRIBUTE ("RuntimeVisibleAnnotations")) | |
263 | { | |
264 | HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE (); | |
265 | } | |
266 | else | |
267 | #endif | |
268 | #ifdef HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE | |
269 | if (MATCH_ATTRIBUTE ("RuntimeInvisibleAnnotations")) | |
270 | { | |
271 | HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE (); | |
272 | } | |
273 | else | |
274 | #endif | |
275 | #ifdef HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE | |
276 | if (MATCH_ATTRIBUTE ("RuntimeVisibleParameterAnnotations")) | |
277 | { | |
278 | HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE (); | |
279 | } | |
280 | else | |
281 | #endif | |
282 | #ifdef HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE | |
283 | if (MATCH_ATTRIBUTE ("RuntimeInvisibleParameterAnnotations")) | |
284 | { | |
285 | HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE (); | |
286 | } | |
287 | else | |
288 | #endif | |
289 | #ifdef HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE | |
290 | if (MATCH_ATTRIBUTE ("AnnotationDefault")) | |
291 | { | |
292 | HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE (); | |
293 | } | |
294 | else | |
e04a16fb | 295 | #endif |
cca4dd59 AH |
296 | if (MATCH_ATTRIBUTE ("BootstrapMethods")) |
297 | { | |
298 | #ifdef HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE | |
299 | HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE(); | |
300 | #else | |
301 | JCF_SKIP (jcf, attribute_length); | |
302 | #endif | |
303 | } | |
304 | else | |
e04a16fb AG |
305 | { |
306 | #ifdef PROCESS_OTHER_ATTRIBUTE | |
307 | PROCESS_OTHER_ATTRIBUTE(jcf, attribute_name, attribute_length); | |
308 | #else | |
309 | JCF_SKIP (jcf, attribute_length); | |
310 | #endif | |
311 | } | |
b4b63e32 | 312 | if ((long) (start_pos + attribute_length) != JCF_TELL(jcf)) |
e04a16fb AG |
313 | return -1; |
314 | return 0; | |
315 | } | |
316 | ||
317 | /* Read and handle the pre-amble. */ | |
c8e7d2e6 | 318 | static int |
6ff2fe39 | 319 | jcf_parse_preamble (JCF* jcf) |
e04a16fb AG |
320 | { |
321 | uint32 magic = (JCF_FILL (jcf, 8), JCF_readu4 (jcf)); | |
8e1f2d4c KG |
322 | uint16 minor_version ATTRIBUTE_UNUSED = JCF_readu2 (jcf); |
323 | uint16 major_version ATTRIBUTE_UNUSED = JCF_readu2 (jcf); | |
e04a16fb AG |
324 | #ifdef HANDLE_MAGIC |
325 | HANDLE_MAGIC (magic, minor_version, major_version); | |
326 | #endif | |
327 | if (magic != 0xcafebabe) | |
328 | return -1; | |
329 | else | |
330 | return 0; | |
331 | } | |
332 | ||
333 | /* Read and handle the constant pool. | |
334 | ||
335 | Return 0 if OK. | |
336 | Return -2 if a bad cross-reference (index of other constant) was seen. | |
337 | */ | |
c8e7d2e6 | 338 | static int |
6ff2fe39 | 339 | jcf_parse_constant_pool (JCF* jcf) |
e04a16fb AG |
340 | { |
341 | int i, n; | |
342 | JPOOL_SIZE (jcf) = (JCF_FILL (jcf, 2), JCF_readu2 (jcf)); | |
a9429e29 | 343 | jcf->cpool.tags = (uint8 *) ggc_alloc_atomic (JPOOL_SIZE (jcf)); |
766090c2 TS |
344 | jcf->cpool.data = (cpool_entry *) ggc_internal_cleared_alloc |
345 | (sizeof (jword) * JPOOL_SIZE (jcf)); | |
e04a16fb AG |
346 | jcf->cpool.tags[0] = 0; |
347 | #ifdef HANDLE_START_CONSTANT_POOL | |
348 | HANDLE_START_CONSTANT_POOL (JPOOL_SIZE (jcf)); | |
349 | #endif | |
350 | for (i = 1; i < (int) JPOOL_SIZE (jcf); i++) | |
351 | { | |
352 | int constant_kind; | |
353 | ||
354 | /* Make sure at least 9 bytes are available. This is enough | |
355 | for all fixed-sized constant pool entries (so we don't need many | |
356 | more JCF_FILL calls below), but is is small enough that | |
357 | we are guaranteed to not hit EOF (in a valid .class file). */ | |
358 | JCF_FILL (jcf, 9); | |
359 | constant_kind = JCF_readu (jcf); | |
360 | jcf->cpool.tags[i] = constant_kind; | |
361 | switch (constant_kind) | |
362 | { | |
363 | case CONSTANT_String: | |
364 | case CONSTANT_Class: | |
17211ab5 | 365 | jcf->cpool.data[i].w = JCF_readu2 (jcf); |
e04a16fb AG |
366 | break; |
367 | case CONSTANT_Fieldref: | |
368 | case CONSTANT_Methodref: | |
369 | case CONSTANT_InterfaceMethodref: | |
370 | case CONSTANT_NameAndType: | |
17211ab5 GK |
371 | jcf->cpool.data[i].w = JCF_readu2 (jcf); |
372 | jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16; | |
e04a16fb AG |
373 | break; |
374 | case CONSTANT_Integer: | |
375 | case CONSTANT_Float: | |
17211ab5 | 376 | jcf->cpool.data[i].w = JCF_readu4 (jcf); |
e04a16fb AG |
377 | break; |
378 | case CONSTANT_Long: | |
379 | case CONSTANT_Double: | |
17211ab5 | 380 | jcf->cpool.data[i].w = JCF_readu4 (jcf); |
e04a16fb AG |
381 | i++; /* These take up two spots in the constant pool */ |
382 | jcf->cpool.tags[i] = 0; | |
17211ab5 | 383 | jcf->cpool.data[i].w = JCF_readu4 (jcf); |
e04a16fb AG |
384 | break; |
385 | case CONSTANT_Utf8: | |
386 | n = JCF_readu2 (jcf); | |
387 | JCF_FILL (jcf, n); | |
388 | #ifdef HANDLE_CONSTANT_Utf8 | |
389 | HANDLE_CONSTANT_Utf8(jcf, i, n); | |
390 | #else | |
17211ab5 | 391 | jcf->cpool.data[i].w = JCF_TELL(jcf) - 2; |
e04a16fb AG |
392 | JCF_SKIP (jcf, n); |
393 | #endif | |
394 | break; | |
cca4dd59 AH |
395 | case CONSTANT_MethodHandle: |
396 | jcf->cpool.data[i].w = JCF_readu (jcf); | |
397 | jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16; | |
398 | break; | |
399 | case CONSTANT_MethodType: | |
400 | jcf->cpool.data[i].w = JCF_readu2 (jcf); | |
401 | break; | |
402 | case CONSTANT_InvokeDynamic: | |
403 | jcf->cpool.data[i].w = JCF_readu2 (jcf); | |
404 | jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16; | |
405 | break; | |
e04a16fb AG |
406 | default: |
407 | return i; | |
408 | } | |
409 | } | |
410 | return 0; | |
411 | } | |
412 | ||
413 | /* Read various class flags and numbers. */ | |
414 | ||
c8e7d2e6 | 415 | static void |
6ff2fe39 | 416 | jcf_parse_class (JCF* jcf) |
e04a16fb AG |
417 | { |
418 | int i; | |
419 | uint16 interfaces_count; | |
420 | JCF_FILL (jcf, 8); | |
421 | jcf->access_flags = JCF_readu2 (jcf); | |
422 | jcf->this_class = JCF_readu2 (jcf); | |
423 | jcf->super_class = JCF_readu2 (jcf); | |
424 | interfaces_count = JCF_readu2 (jcf); | |
425 | ||
426 | #ifdef HANDLE_CLASS_INFO | |
427 | HANDLE_CLASS_INFO(jcf->access_flags, jcf->this_class, jcf->super_class, interfaces_count); | |
428 | #endif | |
429 | ||
430 | JCF_FILL (jcf, 2 * interfaces_count); | |
431 | ||
432 | /* Read interfaces. */ | |
433 | for (i = 0; i < interfaces_count; i++) | |
434 | { | |
7e21fe59 | 435 | uint16 index ATTRIBUTE_UNUSED = JCF_readu2 (jcf); |
e04a16fb AG |
436 | #ifdef HANDLE_CLASS_INTERFACE |
437 | HANDLE_CLASS_INTERFACE (index); | |
438 | #endif | |
439 | } | |
440 | } | |
441 | ||
442 | /* Read fields. */ | |
c8e7d2e6 | 443 | static int |
6ff2fe39 | 444 | jcf_parse_fields (JCF* jcf) |
e04a16fb AG |
445 | { |
446 | int i, j; | |
447 | uint16 fields_count; | |
448 | JCF_FILL (jcf, 2); | |
449 | fields_count = JCF_readu2 (jcf); | |
450 | ||
451 | #ifdef HANDLE_START_FIELDS | |
452 | HANDLE_START_FIELDS (fields_count); | |
453 | #endif | |
454 | for (i = 0; i < fields_count; i++) | |
455 | { | |
456 | uint16 access_flags = (JCF_FILL (jcf, 8), JCF_readu2 (jcf)); | |
457 | uint16 name_index = JCF_readu2 (jcf); | |
458 | uint16 signature_index = JCF_readu2 (jcf); | |
459 | uint16 attribute_count = JCF_readu2 (jcf); | |
460 | #ifdef HANDLE_START_FIELD | |
461 | HANDLE_START_FIELD (access_flags, name_index, signature_index, | |
b124f72e | 462 | attribute_count); |
e04a16fb AG |
463 | #endif |
464 | for (j = 0; j < attribute_count; j++) | |
465 | { | |
97b8365c | 466 | int code = get_attribute (jcf, i, JV_FIELD_ATTR); |
e04a16fb AG |
467 | if (code != 0) |
468 | return code; | |
469 | } | |
470 | #ifdef HANDLE_END_FIELD | |
471 | HANDLE_END_FIELD (); | |
472 | #endif | |
473 | } | |
474 | #ifdef HANDLE_END_FIELDS | |
475 | HANDLE_END_FIELDS (); | |
476 | #endif | |
477 | return 0; | |
478 | } | |
479 | ||
480 | /* Read methods. */ | |
481 | ||
c8e7d2e6 | 482 | static int |
97b8365c | 483 | jcf_parse_one_method (JCF* jcf, int index) |
e04a16fb AG |
484 | { |
485 | int i; | |
486 | uint16 access_flags = (JCF_FILL (jcf, 8), JCF_readu2 (jcf)); | |
487 | uint16 name_index = JCF_readu2 (jcf); | |
488 | uint16 signature_index = JCF_readu2 (jcf); | |
489 | uint16 attribute_count = JCF_readu2 (jcf); | |
490 | #ifdef HANDLE_METHOD | |
491 | HANDLE_METHOD(access_flags, name_index, signature_index, attribute_count); | |
492 | #endif | |
493 | for (i = 0; i < attribute_count; i++) | |
494 | { | |
97b8365c | 495 | int code = get_attribute (jcf, index, JV_METHOD_ATTR); |
e04a16fb AG |
496 | if (code != 0) |
497 | return code; | |
498 | } | |
92c068d1 TT |
499 | #ifdef HANDLE_END_METHOD |
500 | HANDLE_END_METHOD (); | |
501 | #endif | |
e04a16fb AG |
502 | return 0; |
503 | } | |
504 | ||
c8e7d2e6 | 505 | static int |
6ff2fe39 | 506 | jcf_parse_methods (JCF* jcf) |
e04a16fb AG |
507 | { |
508 | int i; | |
509 | uint16 methods_count; | |
510 | JCF_FILL (jcf, 2); | |
511 | methods_count = JCF_readu2 (jcf); | |
512 | #ifdef HANDLE_START_METHODS | |
513 | HANDLE_START_METHODS (methods_count); | |
514 | #endif | |
515 | for (i = 0; i < methods_count; i++) | |
516 | { | |
97b8365c | 517 | int code = jcf_parse_one_method (jcf, i); |
e04a16fb AG |
518 | if (code != 0) |
519 | return code; | |
520 | } | |
521 | #ifdef HANDLE_END_METHODS | |
522 | HANDLE_END_METHODS (); | |
523 | #endif | |
524 | return 0; | |
525 | } | |
526 | ||
527 | /* Read attributes. */ | |
c8e7d2e6 | 528 | static int |
6ff2fe39 | 529 | jcf_parse_final_attributes (JCF *jcf) |
e04a16fb AG |
530 | { |
531 | int i; | |
532 | uint16 attributes_count = (JCF_FILL (jcf, 2), JCF_readu2 (jcf)); | |
533 | #ifdef START_FINAL_ATTRIBUTES | |
534 | START_FINAL_ATTRIBUTES (attributes_count) | |
535 | #endif | |
536 | for (i = 0; i < attributes_count; i++) | |
537 | { | |
97b8365c | 538 | int code = get_attribute (jcf, i, JV_CLASS_ATTR); |
e04a16fb AG |
539 | if (code != 0) |
540 | return code; | |
541 | } | |
542 | return 0; | |
543 | } | |
544 | ||
cca4dd59 AH |
545 | /* Read and handle the "BootstrapMethods" attribute. |
546 | ||
547 | Return 0 if OK. | |
548 | */ | |
549 | static int | |
550 | jcf_parse_bootstrap_methods (JCF* jcf, int attribute_length ATTRIBUTE_UNUSED) | |
551 | { | |
552 | int i; | |
553 | uint16 num_methods = JCF_readu2 (jcf); | |
554 | jcf->bootstrap_methods.count = num_methods; | |
766090c2 | 555 | jcf->bootstrap_methods.methods = ggc_vec_alloc<bootstrap_method> (num_methods); |
cca4dd59 AH |
556 | #ifdef HANDLE_START_BOOTSTRAP_METHODS |
557 | HANDLE_START_BOOTSTRAP_METHODS (jcf, num_methods); | |
558 | #endif | |
559 | ||
560 | for (i = 0; i < num_methods; i++) | |
561 | { | |
562 | unsigned j; | |
563 | bootstrap_method *m = &jcf->bootstrap_methods.methods[i]; | |
564 | m->method_ref = JCF_readu2 (jcf); | |
565 | m->num_arguments = JCF_readu2 (jcf); | |
766090c2 | 566 | m->bootstrap_arguments = ggc_vec_alloc<unsigned> (m->num_arguments); |
cca4dd59 AH |
567 | for (j = 0; j < m->num_arguments; j++) |
568 | m->bootstrap_arguments[j] = JCF_readu2 (jcf); | |
569 | } | |
570 | ||
571 | #ifdef HANDLE_END_BOOTSTRAP_METHODS | |
572 | HANDLE_END_BOOTSTRAP_METHODS (num_methods); | |
573 | #endif | |
574 | ||
575 | return 0; | |
576 | } |