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