stackMapTable.cpp revision 1472:c18cbe5936b8
1/* 2 * Copyright (c) 2003, 2006, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25# include "incls/_precompiled.incl" 26# include "incls/_stackMapTable.cpp.incl" 27 28StackMapTable::StackMapTable(StackMapReader* reader, StackMapFrame* init_frame, 29 u2 max_locals, u2 max_stack, 30 char* code_data, int code_len, TRAPS) { 31 _code_length = code_len; 32 _frame_count = reader->get_frame_count(); 33 if (_frame_count > 0) { 34 _frame_array = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, 35 StackMapFrame*, _frame_count); 36 StackMapFrame* pre_frame = init_frame; 37 for (int32_t i = 0; i < _frame_count; i++) { 38 StackMapFrame* frame = reader->next( 39 pre_frame, i == 0, max_locals, max_stack, 40 CHECK_VERIFY(pre_frame->verifier())); 41 _frame_array[i] = frame; 42 int offset = frame->offset(); 43 if (offset >= code_len || code_data[offset] == 0) { 44 frame->verifier()->verify_error("StackMapTable error: bad offset"); 45 return; 46 } 47 pre_frame = frame; 48 } 49 } 50 reader->check_end(CHECK); 51} 52 53// This method is only called by method in StackMapTable. 54int StackMapTable::get_index_from_offset(int32_t offset) const { 55 int i = 0; 56 for (; i < _frame_count; i++) { 57 if (_frame_array[i]->offset() == offset) { 58 return i; 59 } 60 } 61 return i; // frame with offset doesn't exist in the array 62} 63 64bool StackMapTable::match_stackmap( 65 StackMapFrame* frame, int32_t target, 66 bool match, bool update, TRAPS) const { 67 int index = get_index_from_offset(target); 68 69 return match_stackmap( 70 frame, target, index, match, 71 update, CHECK_VERIFY_(frame->verifier(), false)); 72} 73 74// Match and/or update current_frame to the frame in stackmap table with 75// specified offset and frame index. Return true if the two frames match. 76// 77// The values of match and update are: _match__update_ 78// 79// checking a branch target/exception handler: true false 80// linear bytecode verification following an 81// unconditional branch: false true 82// linear bytecode verification not following an 83// unconditional branch: true true 84bool StackMapTable::match_stackmap( 85 StackMapFrame* frame, int32_t target, int32_t frame_index, 86 bool match, bool update, TRAPS) const { 87 if (frame_index < 0 || frame_index >= _frame_count) { 88 frame->verifier()->verify_error(frame->offset(), 89 "Expecting a stackmap frame at branch target %d", target); 90 return false; 91 } 92 93 bool result = true; 94 StackMapFrame *stackmap_frame = _frame_array[frame_index]; 95 if (match) { 96 // Has direct control flow from last instruction, need to match the two 97 // frames. 98 result = frame->is_assignable_to( 99 stackmap_frame, CHECK_VERIFY_(frame->verifier(), false)); 100 } 101 if (update) { 102 // Use the frame in stackmap table as current frame 103 int lsize = stackmap_frame->locals_size(); 104 int ssize = stackmap_frame->stack_size(); 105 if (frame->locals_size() > lsize || frame->stack_size() > ssize) { 106 // Make sure unused type array items are all _bogus_type. 107 frame->reset(); 108 } 109 frame->set_locals_size(lsize); 110 frame->copy_locals(stackmap_frame); 111 frame->set_stack_size(ssize); 112 frame->copy_stack(stackmap_frame); 113 frame->set_flags(stackmap_frame->flags()); 114 } 115 return result; 116} 117 118void StackMapTable::check_jump_target( 119 StackMapFrame* frame, int32_t target, TRAPS) const { 120 bool match = match_stackmap( 121 frame, target, true, false, CHECK_VERIFY(frame->verifier())); 122 if (!match || (target < 0 || target >= _code_length)) { 123 frame->verifier()->verify_error(frame->offset(), 124 "Inconsistent stackmap frames at branch target %d", target); 125 return; 126 } 127 // check if uninitialized objects exist on backward branches 128 check_new_object(frame, target, CHECK_VERIFY(frame->verifier())); 129} 130 131void StackMapTable::check_new_object( 132 const StackMapFrame* frame, int32_t target, TRAPS) const { 133 if (frame->offset() > target && frame->has_new_object()) { 134 frame->verifier()->verify_error(frame->offset(), 135 "Uninitialized object exists on backward branch %d", target); 136 return; 137 } 138} 139 140#ifndef PRODUCT 141 142void StackMapTable::print() const { 143 tty->print_cr("StackMapTable: frame_count = %d", _frame_count); 144 tty->print_cr("table = { "); 145 for (int32_t i = 0; i < _frame_count; i++) { 146 _frame_array[i]->print(); 147 } 148 tty->print_cr(" }"); 149} 150 151#endif 152 153int32_t StackMapReader::chop( 154 VerificationType* locals, int32_t length, int32_t chops) { 155 int32_t pos = length - 1; 156 for (int32_t i=0; i<chops; i++) { 157 if (locals[pos].is_category2_2nd()) { 158 pos -= 2; 159 } else { 160 pos --; 161 } 162 if (pos<0 && i<(chops-1)) return -1; 163 } 164 return pos+1; 165} 166 167VerificationType StackMapReader::parse_verification_type(u1* flags, TRAPS) { 168 u1 tag = _stream->get_u1(THREAD); 169 if (tag < (u1)ITEM_UninitializedThis) { 170 return VerificationType::from_tag(tag); 171 } 172 if (tag == ITEM_Object) { 173 u2 class_index = _stream->get_u2(THREAD); 174 int nconstants = _cp->length(); 175 if ((class_index <= 0 || class_index >= nconstants) || 176 (!_cp->tag_at(class_index).is_klass() && 177 !_cp->tag_at(class_index).is_unresolved_klass())) { 178 _stream->stackmap_format_error("bad class index", THREAD); 179 return VerificationType::bogus_type(); 180 } 181 return VerificationType::reference_type( 182 symbolHandle(THREAD, _cp->klass_name_at(class_index))); 183 } 184 if (tag == ITEM_UninitializedThis) { 185 if (flags != NULL) { 186 *flags |= FLAG_THIS_UNINIT; 187 } 188 return VerificationType::uninitialized_this_type(); 189 } 190 if (tag == ITEM_Uninitialized) { 191 u2 offset = _stream->get_u2(THREAD); 192 if (offset >= _code_length || 193 _code_data[offset] != ClassVerifier::NEW_OFFSET) { 194 ResourceMark rm(THREAD); 195 _verifier->class_format_error( 196 "StackMapTable format error: bad offset for Uninitialized"); 197 return VerificationType::bogus_type(); 198 } 199 return VerificationType::uninitialized_type(offset); 200 } 201 _stream->stackmap_format_error("bad verification type", THREAD); 202 return VerificationType::bogus_type(); 203} 204 205StackMapFrame* StackMapReader::next( 206 StackMapFrame* pre_frame, bool first, u2 max_locals, u2 max_stack, TRAPS) { 207 StackMapFrame* frame; 208 int offset; 209 VerificationType* locals = NULL; 210 u1 frame_type = _stream->get_u1(THREAD); 211 if (frame_type < 64) { 212 // same_frame 213 if (first) { 214 offset = frame_type; 215 // Can't share the locals array since that is updated by the verifier. 216 if (pre_frame->locals_size() > 0) { 217 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 218 THREAD, VerificationType, pre_frame->locals_size()); 219 } 220 } else { 221 offset = pre_frame->offset() + frame_type + 1; 222 locals = pre_frame->locals(); 223 } 224 frame = new StackMapFrame( 225 offset, pre_frame->flags(), pre_frame->locals_size(), 0, 226 max_locals, max_stack, locals, NULL, _verifier); 227 if (first && locals != NULL) { 228 frame->copy_locals(pre_frame); 229 } 230 return frame; 231 } 232 if (frame_type < 128) { 233 // same_locals_1_stack_item_frame 234 if (first) { 235 offset = frame_type - 64; 236 // Can't share the locals array since that is updated by the verifier. 237 if (pre_frame->locals_size() > 0) { 238 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 239 THREAD, VerificationType, pre_frame->locals_size()); 240 } 241 } else { 242 offset = pre_frame->offset() + frame_type - 63; 243 locals = pre_frame->locals(); 244 } 245 VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD( 246 THREAD, VerificationType, 2); 247 u2 stack_size = 1; 248 stack[0] = parse_verification_type(NULL, CHECK_VERIFY_(_verifier, NULL)); 249 if (stack[0].is_category2()) { 250 stack[1] = stack[0].to_category2_2nd(); 251 stack_size = 2; 252 } 253 check_verification_type_array_size( 254 stack_size, max_stack, CHECK_VERIFY_(_verifier, NULL)); 255 frame = new StackMapFrame( 256 offset, pre_frame->flags(), pre_frame->locals_size(), stack_size, 257 max_locals, max_stack, locals, stack, _verifier); 258 if (first && locals != NULL) { 259 frame->copy_locals(pre_frame); 260 } 261 return frame; 262 } 263 264 u2 offset_delta = _stream->get_u2(THREAD); 265 266 if (frame_type < SAME_LOCALS_1_STACK_ITEM_EXTENDED) { 267 // reserved frame types 268 _stream->stackmap_format_error( 269 "reserved frame type", CHECK_VERIFY_(_verifier, NULL)); 270 } 271 272 if (frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { 273 // same_locals_1_stack_item_frame_extended 274 if (first) { 275 offset = offset_delta; 276 // Can't share the locals array since that is updated by the verifier. 277 if (pre_frame->locals_size() > 0) { 278 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 279 THREAD, VerificationType, pre_frame->locals_size()); 280 } 281 } else { 282 offset = pre_frame->offset() + offset_delta + 1; 283 locals = pre_frame->locals(); 284 } 285 VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD( 286 THREAD, VerificationType, 2); 287 u2 stack_size = 1; 288 stack[0] = parse_verification_type(NULL, CHECK_VERIFY_(_verifier, NULL)); 289 if (stack[0].is_category2()) { 290 stack[1] = stack[0].to_category2_2nd(); 291 stack_size = 2; 292 } 293 check_verification_type_array_size( 294 stack_size, max_stack, CHECK_VERIFY_(_verifier, NULL)); 295 frame = new StackMapFrame( 296 offset, pre_frame->flags(), pre_frame->locals_size(), stack_size, 297 max_locals, max_stack, locals, stack, _verifier); 298 if (first && locals != NULL) { 299 frame->copy_locals(pre_frame); 300 } 301 return frame; 302 } 303 304 if (frame_type <= SAME_EXTENDED) { 305 // chop_frame or same_frame_extended 306 locals = pre_frame->locals(); 307 int length = pre_frame->locals_size(); 308 int chops = SAME_EXTENDED - frame_type; 309 int new_length = length; 310 u1 flags = pre_frame->flags(); 311 if (chops != 0) { 312 new_length = chop(locals, length, chops); 313 check_verification_type_array_size( 314 new_length, max_locals, CHECK_VERIFY_(_verifier, NULL)); 315 // Recompute flags since uninitializedThis could have been chopped. 316 flags = 0; 317 for (int i=0; i<new_length; i++) { 318 if (locals[i].is_uninitialized_this()) { 319 flags |= FLAG_THIS_UNINIT; 320 break; 321 } 322 } 323 } 324 if (first) { 325 offset = offset_delta; 326 // Can't share the locals array since that is updated by the verifier. 327 if (new_length > 0) { 328 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 329 THREAD, VerificationType, new_length); 330 } else { 331 locals = NULL; 332 } 333 } else { 334 offset = pre_frame->offset() + offset_delta + 1; 335 } 336 frame = new StackMapFrame( 337 offset, flags, new_length, 0, max_locals, max_stack, 338 locals, NULL, _verifier); 339 if (first && locals != NULL) { 340 frame->copy_locals(pre_frame); 341 } 342 return frame; 343 } else if (frame_type < SAME_EXTENDED + 4) { 344 // append_frame 345 int appends = frame_type - SAME_EXTENDED; 346 int real_length = pre_frame->locals_size(); 347 int new_length = real_length + appends*2; 348 locals = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, VerificationType, new_length); 349 VerificationType* pre_locals = pre_frame->locals(); 350 int i; 351 for (i=0; i<pre_frame->locals_size(); i++) { 352 locals[i] = pre_locals[i]; 353 } 354 u1 flags = pre_frame->flags(); 355 for (i=0; i<appends; i++) { 356 locals[real_length] = parse_verification_type(&flags, THREAD); 357 if (locals[real_length].is_category2()) { 358 locals[real_length + 1] = locals[real_length].to_category2_2nd(); 359 ++real_length; 360 } 361 ++real_length; 362 } 363 check_verification_type_array_size( 364 real_length, max_locals, CHECK_VERIFY_(_verifier, NULL)); 365 if (first) { 366 offset = offset_delta; 367 } else { 368 offset = pre_frame->offset() + offset_delta + 1; 369 } 370 frame = new StackMapFrame( 371 offset, flags, real_length, 0, max_locals, 372 max_stack, locals, NULL, _verifier); 373 return frame; 374 } 375 if (frame_type == FULL) { 376 // full_frame 377 u1 flags = 0; 378 u2 locals_size = _stream->get_u2(THREAD); 379 int real_locals_size = 0; 380 if (locals_size > 0) { 381 locals = NEW_RESOURCE_ARRAY_IN_THREAD( 382 THREAD, VerificationType, locals_size*2); 383 } 384 int i; 385 for (i=0; i<locals_size; i++) { 386 locals[real_locals_size] = parse_verification_type(&flags, THREAD); 387 if (locals[real_locals_size].is_category2()) { 388 locals[real_locals_size + 1] = 389 locals[real_locals_size].to_category2_2nd(); 390 ++real_locals_size; 391 } 392 ++real_locals_size; 393 } 394 check_verification_type_array_size( 395 real_locals_size, max_locals, CHECK_VERIFY_(_verifier, NULL)); 396 u2 stack_size = _stream->get_u2(THREAD); 397 int real_stack_size = 0; 398 VerificationType* stack = NULL; 399 if (stack_size > 0) { 400 stack = NEW_RESOURCE_ARRAY_IN_THREAD( 401 THREAD, VerificationType, stack_size*2); 402 } 403 for (i=0; i<stack_size; i++) { 404 stack[real_stack_size] = parse_verification_type(NULL, THREAD); 405 if (stack[real_stack_size].is_category2()) { 406 stack[real_stack_size + 1] = stack[real_stack_size].to_category2_2nd(); 407 ++real_stack_size; 408 } 409 ++real_stack_size; 410 } 411 check_verification_type_array_size( 412 real_stack_size, max_stack, CHECK_VERIFY_(_verifier, NULL)); 413 if (first) { 414 offset = offset_delta; 415 } else { 416 offset = pre_frame->offset() + offset_delta + 1; 417 } 418 frame = new StackMapFrame( 419 offset, flags, real_locals_size, real_stack_size, 420 max_locals, max_stack, locals, stack, _verifier); 421 return frame; 422 } 423 424 _stream->stackmap_format_error( 425 "reserved frame type", CHECK_VERIFY_(pre_frame->verifier(), NULL)); 426 return NULL; 427} 428