1 /*
2 * Copyright (c) 2003, 2011, 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 *
29 #include "oops/oop.inline.hpp"
30 #include "runtime/fieldType.hpp"
31 #include "runtime/handles.inline.hpp"
32
33 StackMapTable::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("StackMapTable error: bad offset");
50 return;
51 }
52 pre_frame = frame;
53 }
54 }
55 reader->check_end(CHECK);
56 }
57
58 // This method is only called by method in StackMapTable.
59 int StackMapTable::get_index_from_offset(int32_t offset) const {
60 int i = 0;
61 for (; i < _frame_count; i++) {
62 if (_frame_array[i]->offset() == offset) {
63 return i;
64 }
65 }
66 return i; // frame with offset doesn't exist in the array
67 }
68
69 bool StackMapTable::match_stackmap(
70 StackMapFrame* frame, int32_t target,
71 bool match, bool update, bool handler, TRAPS) const {
72 int index = get_index_from_offset(target);
73
74 return match_stackmap(
75 frame, target, index, match,
76 update, handler, CHECK_VERIFY_(frame->verifier(), false));
77 }
78
79 // Match and/or update current_frame to the frame in stackmap table with
80 // specified offset and frame index. Return true if the two frames match.
81 // handler is true if the frame in stackmap_table is for an exception handler.
82 //
83 // The values of match and update are: _match__update__handler
84 //
85 // checking a branch target: true false false
86 // checking an exception handler: true false true
87 // linear bytecode verification following an
88 // unconditional branch: false true false
89 // linear bytecode verification not following an
90 // unconditional branch: true true false
91 bool StackMapTable::match_stackmap(
92 StackMapFrame* frame, int32_t target, int32_t frame_index,
93 bool match, bool update, bool handler, TRAPS) const {
94 if (frame_index < 0 || frame_index >= _frame_count) {
95 frame->verifier()->verify_error(frame->offset(),
96 "Expecting a stackmap frame at branch target %d", target);
97 return false;
98 }
99
100 bool result = true;
101 StackMapFrame *stackmap_frame = _frame_array[frame_index];
102 if (match) {
103 // Has direct control flow from last instruction, need to match the two
104 // frames.
105 result = frame->is_assignable_to(
106 stackmap_frame, handler,
107 CHECK_VERIFY_(frame->verifier(), false));
108 }
109 if (update) {
110 // Use the frame in stackmap table as current frame
111 int lsize = stackmap_frame->locals_size();
112 int ssize = stackmap_frame->stack_size();
113 if (frame->locals_size() > lsize || frame->stack_size() > ssize) {
114 // Make sure unused type array items are all _bogus_type.
115 frame->reset();
116 }
117 frame->set_locals_size(lsize);
118 frame->copy_locals(stackmap_frame);
119 frame->set_stack_size(ssize);
120 frame->copy_stack(stackmap_frame);
121 frame->set_flags(stackmap_frame->flags());
122 }
123 return result;
124 }
125
126 void StackMapTable::check_jump_target(
127 StackMapFrame* frame, int32_t target, TRAPS) const {
128 bool match = match_stackmap(
129 frame, target, true, false, false, CHECK_VERIFY(frame->verifier()));
130 if (!match || (target < 0 || target >= _code_length)) {
131 frame->verifier()->verify_error(frame->offset(),
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
139 void 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(frame->offset(),
143 "Uninitialized object exists on backward branch %d", target);
144 return;
145 }
146 }
147
148 #ifndef PRODUCT
149
150 void StackMapTable::print() const {
151 tty->print_cr("StackMapTable: frame_count = %d", _frame_count);
152 tty->print_cr("table = { ");
153 for (int32_t i = 0; i < _frame_count; i++) {
154 _frame_array[i]->print();
155 }
156 tty->print_cr(" }");
157 }
158
159 #endif
160
161 int32_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
176 VerificationType 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);
|
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 *
29 #include "oops/oop.inline.hpp"
30 #include "runtime/fieldType.hpp"
31 #include "runtime/handles.inline.hpp"
32
33 StackMapTable::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.
61 int 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
71 bool StackMapTable::match_stackmap(
72 StackMapFrame* frame, int32_t target,
73 bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const {
74 int index = get_index_from_offset(target);
75 return match_stackmap(frame, target, index, match, update, handler, 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 // handler is true if the frame in stackmap_table is for an exception handler.
81 //
82 // The values of match and update are: _match__update__handler
83 //
84 // checking a branch target: true false false
85 // checking an exception handler: true false true
86 // linear bytecode verification following an
87 // unconditional branch: false true false
88 // linear bytecode verification not following an
89 // unconditional branch: true true false
90 bool StackMapTable::match_stackmap(
91 StackMapFrame* frame, int32_t target, int32_t frame_index,
92 bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const {
93 if (frame_index < 0 || frame_index >= _frame_count) {
94 *ctx = ErrorContext::missing_stackmap(frame->offset());
95 frame->verifier()->verify_error(
96 *ctx, "Expecting a stackmap frame at branch target %d", target);
97 return false;
98 }
99
100 StackMapFrame *stackmap_frame = _frame_array[frame_index];
101 bool result = true;
102 if (match) {
103 // Has direct control flow from last instruction, need to match the two
104 // frames.
105 result = frame->is_assignable_to(stackmap_frame, 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
125 void 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, 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
139 void 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
149 void 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
161 int32_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
176 VerificationType 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);
|