1 /* src/vmcore/stackmap.c - class attribute StackMapTable
3 Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31 #include "mm/memory.h"
33 #include "vm/exceptions.h"
35 #include "vmcore/class.h"
36 #include "vmcore/method.h"
37 #include "vmcore/options.h"
38 #include "vmcore/stackmap.h"
39 #include "vmcore/statistics.h"
40 #include "vmcore/suck.h"
43 /* stackmap_get_verification_type_info *****************************************
45 union verification_type_info {
47 Integer_variable_info;
52 UninitializedThis_variable_info;
54 Uninitialized_variable_info;
58 u1 tag = ITEM_Top; // 0
61 Integer_variable_info {
62 u1 tag = ITEM_Integer; // 1
66 u1 tag = ITEM_Float; // 2
70 u1 tag = ITEM_Long; // 4
73 Double_variable_info {
74 u1 tag = ITEM_Double; // 3
78 u1 tag = ITEM_Null; // 5
81 UninitializedThis_variable_info {
82 u1 tag = ITEM_UninitializedThis; // 6
85 Object_variable_info {
86 u1 tag = ITEM_Object; // 7
90 Uninitialized_variable_info {
91 u1 tag = ITEM_Uninitialized; // 8
95 *******************************************************************************/
97 static bool stackmap_get_verification_type_info(classbuffer *cb, verification_type_info_t *verification_type_info)
99 /* get verification type */
101 if (!suck_check_classbuffer_size(cb, 1))
104 verification_type_info->tag = suck_u1(cb);
106 /* process the tag */
108 switch (verification_type_info->tag) {
115 case ITEM_UninitializedThis:
119 /* get constant pool index */
121 if (!suck_check_classbuffer_size(cb, 2))
124 verification_type_info->Object_variable_info.cpool_index = suck_u2(cb);
127 case ITEM_Uninitialized:
130 if (!suck_check_classbuffer_size(cb, 2))
133 verification_type_info->Uninitialized_variable_info.offset = suck_u2(cb);
141 /* stackmap_get_same_locals_1_stack_item_frame *********************************
143 same_locals_1_stack_item_frame {
144 u1 frame_type = SAME_LOCALS_1_STACK_ITEM; // 64-127
145 verification_type_info stack[1];
148 *******************************************************************************/
150 static bool stackmap_get_same_locals_1_stack_item_frame(classbuffer *cb, stack_map_frame_t *stack_map_frame)
152 same_locals_1_stack_item_frame_t *same_locals_1_stack_item_frame;
154 /* for convenience */
156 same_locals_1_stack_item_frame =
157 &(stack_map_frame->same_locals_1_stack_item_frame);
159 if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame->stack[0])))
166 /* stackmap_get_same_locals_1_stack_item_frame_extended ************************
168 same_locals_1_stack_item_frame_extended {
169 u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; // 247
171 verification_type_info stack[1];
174 *******************************************************************************/
176 static bool stackmap_get_same_locals_1_stack_item_frame_extended(classbuffer *cb, stack_map_frame_t *stack_map_frame)
178 same_locals_1_stack_item_frame_extended_t *same_locals_1_stack_item_frame_extended;
180 /* for convenience */
182 same_locals_1_stack_item_frame_extended =
183 &(stack_map_frame->same_locals_1_stack_item_frame_extended);
185 /* check buffer size */
187 if (!suck_check_classbuffer_size(cb, 2))
190 /* get offset delta */
192 same_locals_1_stack_item_frame_extended->offset_delta = suck_u2(cb);
196 if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame_extended->stack[0])))
203 /* stackmap_get_chop_frame *****************************************************
206 u1 frame_type = CHOP_FRAME; // 248-250
210 *******************************************************************************/
212 static bool stackmap_get_chop_frame(classbuffer *cb,
213 stack_map_frame_t *stack_map_frame)
215 chop_frame_t *chop_frame;
217 /* for convenience */
219 chop_frame = &(stack_map_frame->chop_frame);
221 /* check buffer size */
223 if (!suck_check_classbuffer_size(cb, 2))
226 /* get offset delta */
228 chop_frame->offset_delta = suck_u2(cb);
234 /* stackmap_get_same_frame_extended ********************************************
236 same_frame_extended {
237 u1 frame_type = SAME_FRAME_EXTENDED; // 251
241 *******************************************************************************/
243 static bool stackmap_get_same_frame_extended(classbuffer *cb,
244 stack_map_frame_t *stack_map_frame)
246 same_frame_extended_t *same_frame_extended;
248 /* for convenience */
250 same_frame_extended = &(stack_map_frame->same_frame_extended);
252 /* check buffer size */
254 if (!suck_check_classbuffer_size(cb, 2))
257 /* get offset delta */
259 same_frame_extended->offset_delta = suck_u2(cb);
265 /* stackmap_get_append_frame ***************************************************
268 u1 frame_type = APPEND_FRAME; // 252-254
270 verification_type_info locals[frame_Type - 251];
273 *******************************************************************************/
275 static bool stackmap_get_append_frame(classbuffer *cb,
276 stack_map_frame_t *stack_map_frame)
278 append_frame_t *append_frame;
282 /* for convenience */
284 append_frame = &(stack_map_frame->append_frame);
286 /* check buffer size */
288 if (!suck_check_classbuffer_size(cb, 2))
291 /* get offset delta */
293 append_frame->offset_delta = suck_u2(cb);
295 /* allocate locals array */
297 number_of_locals = append_frame->frame_type - 251;
299 append_frame->locals = DMNEW(verification_type_info_t, number_of_locals);
301 /* process all locals */
303 for (i = 0; i < number_of_locals; i++)
304 if (!stackmap_get_verification_type_info(cb, &(append_frame->locals[i])))
311 /* stackmap_get_full_frame *****************************************************
314 u1 frame_type = FULL_FRAME;
317 verification_type_info locals[number_of_locals];
318 u2 number_of_stack_items;
319 verification_type_info stack[number_of_stack_items];
322 *******************************************************************************/
324 static bool stackmap_get_full_frame(classbuffer *cb,
325 stack_map_frame_t *stack_map_frame)
327 full_frame_t *full_frame;
330 /* for convenience */
332 full_frame = &(stack_map_frame->full_frame);
334 /* check buffer size */
336 if (!suck_check_classbuffer_size(cb, 2 + 2))
339 /* get offset delta */
341 stack_map_frame->full_frame.offset_delta = suck_u2(cb);
343 /* get number of locals */
345 full_frame->number_of_locals = suck_u2(cb);
347 /* allocate locals array */
350 DMNEW(verification_type_info_t, full_frame->number_of_locals);
352 /* process all locals */
354 for (i = 0; i < full_frame->number_of_locals; i++)
355 if (!stackmap_get_verification_type_info(cb, &(full_frame->locals[i])))
358 /* get number of stack items */
360 if (!suck_check_classbuffer_size(cb, 2))
363 full_frame->number_of_stack_items = suck_u2(cb);
365 /* allocate stack array */
368 DMNEW(verification_type_info_t, full_frame->number_of_stack_items);
370 /* process all stack items */
372 for (i = 0; i < full_frame->number_of_stack_items; i++)
373 if (!stackmap_get_verification_type_info(cb, &(full_frame->stack[i])))
380 /* stackmap_load_attribute_stackmaptable ***************************************
383 u2 attribute_name_index;
385 u2 number_of_entries;
386 stack_map_frame entries[number_of_entries];
389 union stack_map_frame {
391 same_locals_1_stack_item_frame;
392 same_locals_1_stack_item_frame_extended;
400 u1 frame_type = SAME; // 0-63
403 *******************************************************************************/
405 bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m)
408 stack_map_t *stack_map;
416 /* allocate stack map structure */
418 stack_map = DNEW(stack_map_t);
420 STATISTICS(size_stack_map += sizeof(stack_map_t));
422 /* check buffer size */
424 if (!suck_check_classbuffer_size(cb, 4 + 2))
427 /* attribute_length */
429 stack_map->attribute_length = suck_u4(cb);
431 if (!suck_check_classbuffer_size(cb, stack_map->attribute_length))
434 /* get number of entries */
436 stack_map->number_of_entries = suck_u2(cb);
438 /* process all entries */
440 stack_map->entries = DMNEW(stack_map_frame_t, stack_map->number_of_entries);
442 for (i = 0; i < stack_map->number_of_entries; i++) {
443 /* get the frame type */
445 frame_type = suck_u1(cb);
447 stack_map->entries[i].frame_type = frame_type;
451 if (frame_type <= FRAME_TYPE_SAME) {
454 else if (frame_type <= FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM) {
455 /* same_locals_1_stack_item_frame */
457 if (!stackmap_get_same_locals_1_stack_item_frame(cb, &(stack_map->entries[i])))
460 else if (frame_type <= FRAME_TYPE_RESERVED) {
463 exceptions_throw_classformaterror(c, "reserved frame type");
466 else if (frame_type == FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
467 /* same_locals_1_stack_item_frame_extended */
469 if (!stackmap_get_same_locals_1_stack_item_frame_extended(cb, &(stack_map->entries[i])))
472 else if (frame_type <= FRAME_TYPE_CHOP) {
475 if (!stackmap_get_chop_frame(cb, &(stack_map->entries[i])))
478 else if (frame_type == FRAME_TYPE_SAME_FRAME_EXTENDED) {
479 /* same_frame_extended */
481 if (!stackmap_get_same_frame_extended(cb, &(stack_map->entries[i])))
484 else if (frame_type <= FRAME_TYPE_APPEND) {
487 if (!stackmap_get_append_frame(cb, &(stack_map->entries[i])))
490 else if (frame_type == FRAME_TYPE_FULL_FRAME) {
493 if (!stackmap_get_full_frame(cb, &(stack_map->entries[i])))
498 /* store stack map in method structure */
501 /* currently not used */
503 m->stack_map = stack_map;
511 * These are local overrides for various environment variables in Emacs.
512 * Please do not remove this and leave it at the end of the file, where
513 * Emacs will automagically detect them.
514 * ---------------------------------------------------------------------
517 * indent-tabs-mode: t
521 * vim:noexpandtab:sw=4:ts=4: