Mercurial > hg > truffle
comparison src/share/vm/classfile/verifier.hpp @ 6646:c38f13903fdf
Merge with http://hg.openjdk.java.net/hsx/hsx25/hotspot/ just before the NPG (no perm gen) changeset
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 29 Oct 2012 21:10:04 +0100 |
parents | 4ee06e614636 |
children | da91efe96a93 |
comparison
equal
deleted
inserted
replaced
6590:dc5eec61daba | 6646:c38f13903fdf |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
86 #define CHECK_VERIFY(verifier) \ | 86 #define CHECK_VERIFY(verifier) \ |
87 CHECK); if ((verifier)->has_error()) return; (0 | 87 CHECK); if ((verifier)->has_error()) return; (0 |
88 #define CHECK_VERIFY_(verifier, result) \ | 88 #define CHECK_VERIFY_(verifier, result) \ |
89 CHECK_(result)); if ((verifier)->has_error()) return (result); (0 | 89 CHECK_(result)); if ((verifier)->has_error()) return (result); (0 |
90 | 90 |
91 class TypeOrigin VALUE_OBJ_CLASS_SPEC { | |
92 private: | |
93 typedef enum { | |
94 CF_LOCALS, // Comes from the current frame locals | |
95 CF_STACK, // Comes from the current frame expression stack | |
96 SM_LOCALS, // Comes from stackmap locals | |
97 SM_STACK, // Comes from stackmap expression stack | |
98 CONST_POOL, // Comes from the constant pool | |
99 SIG, // Comes from method signature | |
100 IMPLICIT, // Comes implicitly from code or context | |
101 BAD_INDEX, // No type, but the index is bad | |
102 FRAME_ONLY, // No type, context just contains the frame | |
103 NONE | |
104 } Origin; | |
105 | |
106 Origin _origin; | |
107 u2 _index; // local, stack, or constant pool index | |
108 StackMapFrame* _frame; // source frame if CF or SM | |
109 VerificationType _type; // The actual type | |
110 | |
111 TypeOrigin( | |
112 Origin origin, u2 index, StackMapFrame* frame, VerificationType type) | |
113 : _origin(origin), _index(index), _frame(frame), _type(type) {} | |
114 | |
115 public: | |
116 TypeOrigin() : _origin(NONE), _index(0), _frame(NULL) {} | |
117 | |
118 static TypeOrigin null(); | |
119 static TypeOrigin local(u2 index, StackMapFrame* frame); | |
120 static TypeOrigin stack(u2 index, StackMapFrame* frame); | |
121 static TypeOrigin sm_local(u2 index, StackMapFrame* frame); | |
122 static TypeOrigin sm_stack(u2 index, StackMapFrame* frame); | |
123 static TypeOrigin cp(u2 index, VerificationType vt); | |
124 static TypeOrigin signature(VerificationType vt); | |
125 static TypeOrigin bad_index(u2 index); | |
126 static TypeOrigin implicit(VerificationType t); | |
127 static TypeOrigin frame(StackMapFrame* frame); | |
128 | |
129 void reset_frame(); | |
130 void details(outputStream* ss) const; | |
131 void print_frame(outputStream* ss) const; | |
132 const StackMapFrame* frame() const { return _frame; } | |
133 bool is_valid() const { return _origin != NONE; } | |
134 u2 index() const { return _index; } | |
135 | |
136 #ifdef ASSERT | |
137 void print_on(outputStream* str) const; | |
138 #endif | |
139 }; | |
140 | |
141 class ErrorContext VALUE_OBJ_CLASS_SPEC { | |
142 private: | |
143 typedef enum { | |
144 INVALID_BYTECODE, // There was a problem with the bytecode | |
145 WRONG_TYPE, // Type value was not as expected | |
146 FLAGS_MISMATCH, // Frame flags are not assignable | |
147 BAD_CP_INDEX, // Invalid constant pool index | |
148 BAD_LOCAL_INDEX, // Invalid local index | |
149 LOCALS_SIZE_MISMATCH, // Frames have differing local counts | |
150 STACK_SIZE_MISMATCH, // Frames have different stack sizes | |
151 STACK_OVERFLOW, // Attempt to push onto a full expression stack | |
152 STACK_UNDERFLOW, // Attempt to pop and empty expression stack | |
153 MISSING_STACKMAP, // No stackmap for this location and there should be | |
154 BAD_STACKMAP, // Format error in stackmap | |
155 NO_FAULT, // No error | |
156 UNKNOWN | |
157 } FaultType; | |
158 | |
159 int _bci; | |
160 FaultType _fault; | |
161 TypeOrigin _type; | |
162 TypeOrigin _expected; | |
163 | |
164 ErrorContext(int bci, FaultType fault) : | |
165 _bci(bci), _fault(fault) {} | |
166 ErrorContext(int bci, FaultType fault, TypeOrigin type) : | |
167 _bci(bci), _fault(fault), _type(type) {} | |
168 ErrorContext(int bci, FaultType fault, TypeOrigin type, TypeOrigin exp) : | |
169 _bci(bci), _fault(fault), _type(type), _expected(exp) {} | |
170 | |
171 public: | |
172 ErrorContext() : _bci(-1), _fault(NO_FAULT) {} | |
173 | |
174 static ErrorContext bad_code(u2 bci) { | |
175 return ErrorContext(bci, INVALID_BYTECODE); | |
176 } | |
177 static ErrorContext bad_type(u2 bci, TypeOrigin type) { | |
178 return ErrorContext(bci, WRONG_TYPE, type); | |
179 } | |
180 static ErrorContext bad_type(u2 bci, TypeOrigin type, TypeOrigin exp) { | |
181 return ErrorContext(bci, WRONG_TYPE, type, exp); | |
182 } | |
183 static ErrorContext bad_flags(u2 bci, StackMapFrame* frame) { | |
184 return ErrorContext(bci, FLAGS_MISMATCH, TypeOrigin::frame(frame)); | |
185 } | |
186 static ErrorContext bad_flags(u2 bci, StackMapFrame* cur, StackMapFrame* sm) { | |
187 return ErrorContext(bci, FLAGS_MISMATCH, | |
188 TypeOrigin::frame(cur), TypeOrigin::frame(sm)); | |
189 } | |
190 static ErrorContext bad_cp_index(u2 bci, u2 index) { | |
191 return ErrorContext(bci, BAD_CP_INDEX, TypeOrigin::bad_index(index)); | |
192 } | |
193 static ErrorContext bad_local_index(u2 bci, u2 index) { | |
194 return ErrorContext(bci, BAD_LOCAL_INDEX, TypeOrigin::bad_index(index)); | |
195 } | |
196 static ErrorContext locals_size_mismatch( | |
197 u2 bci, StackMapFrame* frame0, StackMapFrame* frame1) { | |
198 return ErrorContext(bci, LOCALS_SIZE_MISMATCH, | |
199 TypeOrigin::frame(frame0), TypeOrigin::frame(frame1)); | |
200 } | |
201 static ErrorContext stack_size_mismatch( | |
202 u2 bci, StackMapFrame* frame0, StackMapFrame* frame1) { | |
203 return ErrorContext(bci, STACK_SIZE_MISMATCH, | |
204 TypeOrigin::frame(frame0), TypeOrigin::frame(frame1)); | |
205 } | |
206 static ErrorContext stack_overflow(u2 bci, StackMapFrame* frame) { | |
207 return ErrorContext(bci, STACK_OVERFLOW, TypeOrigin::frame(frame)); | |
208 } | |
209 static ErrorContext stack_underflow(u2 bci, StackMapFrame* frame) { | |
210 return ErrorContext(bci, STACK_UNDERFLOW, TypeOrigin::frame(frame)); | |
211 } | |
212 static ErrorContext missing_stackmap(u2 bci) { | |
213 return ErrorContext(bci, MISSING_STACKMAP); | |
214 } | |
215 static ErrorContext bad_stackmap(int index, StackMapFrame* frame) { | |
216 return ErrorContext(0, BAD_STACKMAP, TypeOrigin::frame(frame)); | |
217 } | |
218 | |
219 bool is_valid() const { return _fault != NO_FAULT; } | |
220 int bci() const { return _bci; } | |
221 | |
222 void reset_frames() { | |
223 _type.reset_frame(); | |
224 _expected.reset_frame(); | |
225 } | |
226 | |
227 void details(outputStream* ss, methodOop method) const; | |
228 | |
229 #ifdef ASSERT | |
230 void print_on(outputStream* str) const { | |
231 str->print("error_context(%d, %d,", _bci, _fault); | |
232 _type.print_on(str); | |
233 str->print(","); | |
234 _expected.print_on(str); | |
235 str->print(")"); | |
236 } | |
237 #endif | |
238 | |
239 private: | |
240 void location_details(outputStream* ss, methodOop method) const; | |
241 void reason_details(outputStream* ss) const; | |
242 void frame_details(outputStream* ss) const; | |
243 void bytecode_details(outputStream* ss, methodOop method) const; | |
244 void handler_details(outputStream* ss, methodOop method) const; | |
245 void stackmap_details(outputStream* ss, methodOop method) const; | |
246 }; | |
247 | |
91 // A new instance of this class is created for each class being verified | 248 // A new instance of this class is created for each class being verified |
92 class ClassVerifier : public StackObj { | 249 class ClassVerifier : public StackObj { |
93 private: | 250 private: |
94 Thread* _thread; | 251 Thread* _thread; |
252 GrowableArray<Symbol*>* _symbols; // keep a list of symbols created | |
253 | |
95 Symbol* _exception_type; | 254 Symbol* _exception_type; |
96 char* _message; | 255 char* _message; |
97 size_t _message_buffer_len; | 256 |
98 GrowableArray<Symbol*>* _symbols; // keep a list of symbols created | 257 ErrorContext _error_context; // contains information about an error |
99 | 258 |
100 void verify_method(methodHandle method, TRAPS); | 259 void verify_method(methodHandle method, TRAPS); |
101 char* generate_code_data(methodHandle m, u4 code_length, TRAPS); | 260 char* generate_code_data(methodHandle m, u4 code_length, TRAPS); |
102 void verify_exception_handler_table(u4 code_length, char* code_data, int& min, int& max, TRAPS); | 261 void verify_exception_handler_table(u4 code_length, char* code_data, |
262 int& min, int& max, TRAPS); | |
103 void verify_local_variable_table(u4 code_length, char* code_data, TRAPS); | 263 void verify_local_variable_table(u4 code_length, char* code_data, TRAPS); |
104 | 264 |
105 VerificationType cp_ref_index_to_type( | 265 VerificationType cp_ref_index_to_type( |
106 int index, constantPoolHandle cp, TRAPS) { | 266 int index, constantPoolHandle cp, TRAPS) { |
107 return cp_index_to_type(cp->klass_ref_index_at(index), cp, THREAD); | 267 return cp_index_to_type(cp->klass_ref_index_at(index), cp, THREAD); |
109 | 269 |
110 bool is_protected_access( | 270 bool is_protected_access( |
111 instanceKlassHandle this_class, klassOop target_class, | 271 instanceKlassHandle this_class, klassOop target_class, |
112 Symbol* field_name, Symbol* field_sig, bool is_method); | 272 Symbol* field_name, Symbol* field_sig, bool is_method); |
113 | 273 |
114 void verify_cp_index(constantPoolHandle cp, int index, TRAPS); | 274 void verify_cp_index(u2 bci, constantPoolHandle cp, int index, TRAPS); |
115 void verify_cp_type( | 275 void verify_cp_type(u2 bci, int index, constantPoolHandle cp, |
116 int index, constantPoolHandle cp, unsigned int types, TRAPS); | 276 unsigned int types, TRAPS); |
117 void verify_cp_class_type(int index, constantPoolHandle cp, TRAPS); | 277 void verify_cp_class_type(u2 bci, int index, constantPoolHandle cp, TRAPS); |
118 | 278 |
119 u2 verify_stackmap_table( | 279 u2 verify_stackmap_table( |
120 u2 stackmap_index, u2 bci, StackMapFrame* current_frame, | 280 u2 stackmap_index, u2 bci, StackMapFrame* current_frame, |
121 StackMapTable* stackmap_table, bool no_control_flow, TRAPS); | 281 StackMapTable* stackmap_table, bool no_control_flow, TRAPS); |
122 | 282 |
135 void verify_field_instructions( | 295 void verify_field_instructions( |
136 RawBytecodeStream* bcs, StackMapFrame* current_frame, | 296 RawBytecodeStream* bcs, StackMapFrame* current_frame, |
137 constantPoolHandle cp, TRAPS); | 297 constantPoolHandle cp, TRAPS); |
138 | 298 |
139 void verify_invoke_init( | 299 void verify_invoke_init( |
140 RawBytecodeStream* bcs, VerificationType ref_class_type, | 300 RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type, |
141 StackMapFrame* current_frame, u4 code_length, bool* this_uninit, | 301 StackMapFrame* current_frame, u4 code_length, bool* this_uninit, |
142 constantPoolHandle cp, TRAPS); | 302 constantPoolHandle cp, TRAPS); |
143 | 303 |
144 void verify_invoke_instructions( | 304 void verify_invoke_instructions( |
145 RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, | 305 RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, |
146 bool* this_uninit, VerificationType return_type, | 306 bool* this_uninit, VerificationType return_type, |
147 constantPoolHandle cp, TRAPS); | 307 constantPoolHandle cp, TRAPS); |
148 | 308 |
149 VerificationType get_newarray_type(u2 index, u2 bci, TRAPS); | 309 VerificationType get_newarray_type(u2 index, u2 bci, TRAPS); |
150 void verify_anewarray( | 310 void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp, |
151 u2 index, constantPoolHandle cp, StackMapFrame* current_frame, TRAPS); | 311 StackMapFrame* current_frame, TRAPS); |
152 void verify_return_value( | 312 void verify_return_value( |
153 VerificationType return_type, VerificationType type, u2 offset, TRAPS); | 313 VerificationType return_type, VerificationType type, u2 offset, |
314 StackMapFrame* current_frame, TRAPS); | |
154 | 315 |
155 void verify_iload (u2 index, StackMapFrame* current_frame, TRAPS); | 316 void verify_iload (u2 index, StackMapFrame* current_frame, TRAPS); |
156 void verify_lload (u2 index, StackMapFrame* current_frame, TRAPS); | 317 void verify_lload (u2 index, StackMapFrame* current_frame, TRAPS); |
157 void verify_fload (u2 index, StackMapFrame* current_frame, TRAPS); | 318 void verify_fload (u2 index, StackMapFrame* current_frame, TRAPS); |
158 void verify_dload (u2 index, StackMapFrame* current_frame, TRAPS); | 319 void verify_dload (u2 index, StackMapFrame* current_frame, TRAPS); |
187 BYTECODE_OFFSET = 1, | 348 BYTECODE_OFFSET = 1, |
188 NEW_OFFSET = 2 | 349 NEW_OFFSET = 2 |
189 }; | 350 }; |
190 | 351 |
191 // constructor | 352 // constructor |
192 ClassVerifier(instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS); | 353 ClassVerifier(instanceKlassHandle klass, TRAPS); |
193 | 354 |
194 // destructor | 355 // destructor |
195 ~ClassVerifier(); | 356 ~ClassVerifier(); |
196 | 357 |
197 Thread* thread() { return _thread; } | 358 Thread* thread() { return _thread; } |
205 void verify_class(TRAPS); | 366 void verify_class(TRAPS); |
206 | 367 |
207 // Return status modes | 368 // Return status modes |
208 Symbol* result() const { return _exception_type; } | 369 Symbol* result() const { return _exception_type; } |
209 bool has_error() const { return result() != NULL; } | 370 bool has_error() const { return result() != NULL; } |
371 char* exception_message() { | |
372 stringStream ss; | |
373 ss.print(_message); | |
374 _error_context.details(&ss, _method()); | |
375 return ss.as_string(); | |
376 } | |
210 | 377 |
211 // Called when verify or class format errors are encountered. | 378 // Called when verify or class format errors are encountered. |
212 // May throw an exception based upon the mode. | 379 // May throw an exception based upon the mode. |
213 void verify_error(u2 offset, const char* fmt, ...); | 380 void verify_error(ErrorContext ctx, const char* fmt, ...); |
214 void verify_error(const char* fmt, ...); | |
215 void class_format_error(const char* fmt, ...); | 381 void class_format_error(const char* fmt, ...); |
216 void format_error_message(const char* fmt, int offset, va_list args); | |
217 | 382 |
218 klassOop load_class(Symbol* name, TRAPS); | 383 klassOop load_class(Symbol* name, TRAPS); |
219 | 384 |
220 int change_sig_to_verificationType( | 385 int change_sig_to_verificationType( |
221 SignatureStream* sig_type, VerificationType* inference_type, TRAPS); | 386 SignatureStream* sig_type, VerificationType* inference_type, TRAPS); |
226 | 391 |
227 // Keep a list of temporary symbols created during verification because | 392 // Keep a list of temporary symbols created during verification because |
228 // their reference counts need to be decrememented when the verifier object | 393 // their reference counts need to be decrememented when the verifier object |
229 // goes out of scope. Since these symbols escape the scope in which they're | 394 // goes out of scope. Since these symbols escape the scope in which they're |
230 // created, we can't use a TempNewSymbol. | 395 // created, we can't use a TempNewSymbol. |
231 Symbol* create_temporary_symbol(const Symbol* s, int begin, int end, TRAPS); | 396 Symbol* create_temporary_symbol( |
397 const Symbol* s, int begin, int end, TRAPS); | |
232 Symbol* create_temporary_symbol(const char *s, int length, TRAPS); | 398 Symbol* create_temporary_symbol(const char *s, int length, TRAPS); |
233 | 399 |
234 static bool _verify_verbose; // for debugging | 400 TypeOrigin ref_ctx(const char* str, TRAPS); |
235 }; | 401 }; |
236 | 402 |
237 inline int ClassVerifier::change_sig_to_verificationType( | 403 inline int ClassVerifier::change_sig_to_verificationType( |
238 SignatureStream* sig_type, VerificationType* inference_type, TRAPS) { | 404 SignatureStream* sig_type, VerificationType* inference_type, TRAPS) { |
239 BasicType bt = sig_type->type(); | 405 BasicType bt = sig_type->type(); |