Mon, 14 Jan 2013 11:01:39 -0500
8006005: Fix constant pool index validation and alignment trap for method parameter reflection
Summary: This patch addresses an alignment trap due to the storage format of method parameters data in constMethod. It also adds code to validate constant pool indexes for method parameters data.
Reviewed-by: jrose, dholmes
Contributed-by: eric.mccorkle@oracle.com
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 */
25 #ifndef SHARE_VM_OOPS_CONSTMETHODOOP_HPP
26 #define SHARE_VM_OOPS_CONSTMETHODOOP_HPP
28 #include "oops/oop.hpp"
30 // An ConstMethod* represents portions of a Java method which
31 // do not vary.
32 //
33 // Memory layout (each line represents a word). Note that most
34 // applications load thousands of methods, so keeping the size of this
35 // structure small has a big impact on footprint.
36 //
37 // |------------------------------------------------------|
38 // | header |
39 // | klass |
40 // |------------------------------------------------------|
41 // | fingerprint 1 |
42 // | fingerprint 2 |
43 // | constants (oop) |
44 // | stackmap_data (oop) |
45 // | constMethod_size |
46 // | interp_kind | flags | code_size |
47 // | name index | signature index |
48 // | method_idnum | max_stack |
49 // | max_locals | size_of_parameters |
50 // |------------------------------------------------------|
51 // | |
52 // | byte codes |
53 // | |
54 // |------------------------------------------------------|
55 // | compressed linenumber table |
56 // | (see class CompressedLineNumberReadStream) |
57 // | (note that length is unknown until decompressed) |
58 // | (access flags bit tells whether table is present) |
59 // | (indexed from start of ConstMethod*) |
60 // | (elements not necessarily sorted!) |
61 // |------------------------------------------------------|
62 // | localvariable table elements + length (length last) |
63 // | (length is u2, elements are 6-tuples of u2) |
64 // | (see class LocalVariableTableElement) |
65 // | (access flags bit tells whether table is present) |
66 // | (indexed from end of ConstMethod*) |
67 // |------------------------------------------------------|
68 // | exception table + length (length last) |
69 // | (length is u2, elements are 4-tuples of u2) |
70 // | (see class ExceptionTableElement) |
71 // | (access flags bit tells whether table is present) |
72 // | (indexed from end of ConstMethod*) |
73 // |------------------------------------------------------|
74 // | checked exceptions elements + length (length last) |
75 // | (length is u2, elements are u2) |
76 // | (see class CheckedExceptionElement) |
77 // | (access flags bit tells whether table is present) |
78 // | (indexed from end of ConstMethod*) |
79 // |------------------------------------------------------|
80 // | method parameters elements + length (length last) |
81 // | (length is u2, elements are u2, u4 structures) |
82 // | (see class MethodParametersElement) |
83 // | (access flags bit tells whether table is present) |
84 // | (indexed from end of ConstMethod*) |
85 // |------------------------------------------------------|
86 // | generic signature index (u2) |
87 // | (indexed from start of constMethodOop) |
88 // |------------------------------------------------------|
89 //
90 // IMPORTANT: If anything gets added here, there need to be changes to
91 // ensure that ServicabilityAgent doesn't get broken as a result!
94 // Utitily class decribing elements in checked exceptions table inlined in Method*.
95 class CheckedExceptionElement VALUE_OBJ_CLASS_SPEC {
96 public:
97 u2 class_cp_index;
98 };
101 // Utitily class decribing elements in local variable table inlined in Method*.
102 class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC {
103 public:
104 u2 start_bci;
105 u2 length;
106 u2 name_cp_index;
107 u2 descriptor_cp_index;
108 u2 signature_cp_index;
109 u2 slot;
110 };
112 // Utitily class describing elements in exception table
113 class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
114 public:
115 u2 start_pc;
116 u2 end_pc;
117 u2 handler_pc;
118 u2 catch_type_index;
119 };
121 // Utility class describing elements in method parameters
122 class MethodParametersElement VALUE_OBJ_CLASS_SPEC {
123 public:
124 u2 name_cp_index;
125 // This has to happen, otherwise it will cause SIGBUS from a
126 // misaligned u4 on some architectures (ie SPARC)
127 // because MethodParametersElements are only aligned mod 2
128 // within the ConstMethod container u2 flags_hi;
129 u2 flags_hi;
130 u2 flags_lo;
131 };
134 class ConstMethod : public MetaspaceObj {
135 friend class VMStructs;
137 public:
138 typedef enum { NORMAL, OVERPASS } MethodType;
140 private:
141 enum {
142 _has_linenumber_table = 1,
143 _has_checked_exceptions = 2,
144 _has_localvariable_table = 4,
145 _has_exception_table = 8,
146 _has_generic_signature = 16,
147 _has_method_parameters = 32,
148 _is_overpass = 64
149 };
151 // Bit vector of signature
152 // Callers interpret 0=not initialized yet and
153 // -1=too many args to fix, must parse the slow way.
154 // The real initial value is special to account for nonatomicity of 64 bit
155 // loads and stores. This value may updated and read without a lock by
156 // multiple threads, so is volatile.
157 volatile uint64_t _fingerprint;
159 ConstantPool* _constants; // Constant pool
161 // Raw stackmap data for the method
162 Array<u1>* _stackmap_data;
164 int _constMethod_size;
165 jbyte _interpreter_kind;
166 jbyte _flags;
168 // Size of Java bytecodes allocated immediately after Method*.
169 u2 _code_size;
170 u2 _name_index; // Method name (index in constant pool)
171 u2 _signature_index; // Method signature (index in constant pool)
172 u2 _method_idnum; // unique identification number for the method within the class
173 // initially corresponds to the index into the methods array.
174 // but this may change with redefinition
175 u2 _max_stack; // Maximum number of entries on the expression stack
176 u2 _max_locals; // Number of local variables used by this method
177 u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words
179 // Constructor
180 ConstMethod(int byte_code_size,
181 int compressed_line_number_size,
182 int localvariable_table_length,
183 int exception_table_length,
184 int checked_exceptions_length,
185 int method_parameters_length,
186 u2 generic_signature_index,
187 MethodType is_overpass,
188 int size);
189 public:
191 static ConstMethod* allocate(ClassLoaderData* loader_data,
192 int byte_code_size,
193 int compressed_line_number_size,
194 int localvariable_table_length,
195 int exception_table_length,
196 int checked_exceptions_length,
197 int method_parameters_length,
198 u2 generic_signature_index,
199 MethodType mt,
200 TRAPS);
202 bool is_constMethod() const { return true; }
204 // Inlined tables
205 void set_inlined_tables_length(u2 generic_signature_index,
206 int checked_exceptions_len,
207 int compressed_line_number_size,
208 int localvariable_table_len,
209 int exception_table_len,
210 int method_parameters_length);
212 bool has_generic_signature() const
213 { return (_flags & _has_generic_signature) != 0; }
215 bool has_linenumber_table() const
216 { return (_flags & _has_linenumber_table) != 0; }
218 bool has_checked_exceptions() const
219 { return (_flags & _has_checked_exceptions) != 0; }
221 bool has_localvariable_table() const
222 { return (_flags & _has_localvariable_table) != 0; }
224 bool has_exception_handler() const
225 { return (_flags & _has_exception_table) != 0; }
227 bool has_method_parameters() const
228 { return (_flags & _has_method_parameters) != 0; }
230 MethodType method_type() const {
231 return ((_flags & _is_overpass) == 0) ? NORMAL : OVERPASS;
232 }
234 void set_method_type(MethodType mt) {
235 if (mt == NORMAL) {
236 _flags &= ~(_is_overpass);
237 } else {
238 _flags |= _is_overpass;
239 }
240 }
243 void set_interpreter_kind(int kind) { _interpreter_kind = kind; }
244 int interpreter_kind(void) const { return _interpreter_kind; }
246 // constant pool
247 ConstantPool* constants() const { return _constants; }
248 void set_constants(ConstantPool* c) { _constants = c; }
250 Method* method() const;
252 // stackmap table data
253 Array<u1>* stackmap_data() const { return _stackmap_data; }
254 void set_stackmap_data(Array<u1>* sd) { _stackmap_data = sd; }
255 bool has_stackmap_table() const { return _stackmap_data != NULL; }
257 void init_fingerprint() {
258 const uint64_t initval = CONST64(0x8000000000000000);
259 _fingerprint = initval;
260 }
262 uint64_t fingerprint() const {
263 // Since reads aren't atomic for 64 bits, if any of the high or low order
264 // word is the initial value, return 0. See init_fingerprint for initval.
265 uint high_fp = (uint)(_fingerprint >> 32);
266 if ((int) _fingerprint == 0 || high_fp == 0x80000000) {
267 return 0L;
268 } else {
269 return _fingerprint;
270 }
271 }
273 uint64_t set_fingerprint(uint64_t new_fingerprint) {
274 #ifdef ASSERT
275 // Assert only valid if complete/valid 64 bit _fingerprint value is read.
276 uint64_t oldfp = fingerprint();
277 #endif // ASSERT
278 _fingerprint = new_fingerprint;
279 assert(oldfp == 0L || new_fingerprint == oldfp,
280 "fingerprint cannot change");
281 assert(((new_fingerprint >> 32) != 0x80000000) && (int)new_fingerprint !=0,
282 "fingerprint should call init to set initial value");
283 return new_fingerprint;
284 }
286 // name
287 int name_index() const { return _name_index; }
288 void set_name_index(int index) { _name_index = index; }
290 // signature
291 int signature_index() const { return _signature_index; }
292 void set_signature_index(int index) { _signature_index = index; }
294 // generics support
295 int generic_signature_index() const {
296 if (has_generic_signature()) {
297 return *generic_signature_index_addr();
298 } else {
299 return 0;
300 }
301 }
302 void set_generic_signature_index(u2 index) {
303 assert(has_generic_signature(), "");
304 u2* addr = generic_signature_index_addr();
305 *addr = index;
306 }
308 // Sizing
309 static int header_size() {
310 return sizeof(ConstMethod)/HeapWordSize;
311 }
313 // Size needed
314 static int size(int code_size, int compressed_line_number_size,
315 int local_variable_table_length,
316 int exception_table_length,
317 int checked_exceptions_length,
318 int method_parameters_length,
319 u2 generic_signature_index);
321 int size() const { return _constMethod_size;}
322 void set_constMethod_size(int size) { _constMethod_size = size; }
324 // code size
325 int code_size() const { return _code_size; }
326 void set_code_size(int size) {
327 assert(max_method_code_size < (1 << 16),
328 "u2 is too small to hold method code size in general");
329 assert(0 <= size && size <= max_method_code_size, "invalid code size");
330 _code_size = size;
331 }
333 // linenumber table - note that length is unknown until decompression,
334 // see class CompressedLineNumberReadStream.
335 u_char* compressed_linenumber_table() const; // not preserved by gc
336 u2* generic_signature_index_addr() const;
337 u2* checked_exceptions_length_addr() const;
338 u2* localvariable_table_length_addr() const;
339 u2* exception_table_length_addr() const;
340 u2* method_parameters_length_addr() const;
342 // checked exceptions
343 int checked_exceptions_length() const;
344 CheckedExceptionElement* checked_exceptions_start() const;
346 // localvariable table
347 int localvariable_table_length() const;
348 LocalVariableTableElement* localvariable_table_start() const;
350 // exception table
351 int exception_table_length() const;
352 ExceptionTableElement* exception_table_start() const;
354 // method parameters table
355 int method_parameters_length() const;
356 MethodParametersElement* method_parameters_start() const;
358 // byte codes
359 void set_code(address code) {
360 if (code_size() > 0) {
361 memcpy(code_base(), code, code_size());
362 }
363 }
364 address code_base() const { return (address) (this+1); }
365 address code_end() const { return code_base() + code_size(); }
366 bool contains(address bcp) const { return code_base() <= bcp
367 && bcp < code_end(); }
368 // Offset to bytecodes
369 static ByteSize codes_offset()
370 { return in_ByteSize(sizeof(ConstMethod)); }
372 static ByteSize constants_offset()
373 { return byte_offset_of(ConstMethod, _constants); }
375 static ByteSize max_stack_offset()
376 { return byte_offset_of(ConstMethod, _max_stack); }
377 static ByteSize size_of_locals_offset()
378 { return byte_offset_of(ConstMethod, _max_locals); }
379 static ByteSize size_of_parameters_offset()
380 { return byte_offset_of(ConstMethod, _size_of_parameters); }
383 // Unique id for the method
384 static const u2 MAX_IDNUM;
385 static const u2 UNSET_IDNUM;
386 u2 method_idnum() const { return _method_idnum; }
387 void set_method_idnum(u2 idnum) { _method_idnum = idnum; }
389 // max stack
390 int max_stack() const { return _max_stack; }
391 void set_max_stack(int size) { _max_stack = size; }
393 // max locals
394 int max_locals() const { return _max_locals; }
395 void set_max_locals(int size) { _max_locals = size; }
397 // size of parameters
398 int size_of_parameters() const { return _size_of_parameters; }
399 void set_size_of_parameters(int size) { _size_of_parameters = size; }
401 // Deallocation for RedefineClasses
402 void deallocate_contents(ClassLoaderData* loader_data);
403 bool is_klass() const { return false; }
404 DEBUG_ONLY(bool on_stack() { return false; })
406 private:
407 // Since the size of the compressed line number table is unknown, the
408 // offsets of the other variable sized sections are computed backwards
409 // from the end of the ConstMethod*.
411 // First byte after ConstMethod*
412 address constMethod_end() const
413 { return (address)((oop*)this + _constMethod_size); }
415 // Last short in ConstMethod*
416 u2* last_u2_element() const
417 { return (u2*)constMethod_end() - 1; }
419 public:
420 // Printing
421 void print_on (outputStream* st) const;
422 void print_value_on(outputStream* st) const;
424 const char* internal_name() const { return "{constMethod}"; }
426 // Verify
427 void verify_on(outputStream* st);
428 };
430 #endif // SHARE_VM_OOPS_CONSTMETHODOOP_HPP