26 #include "classfile/symbolTable.hpp"
27 #include "interpreter/bytecodeStream.hpp"
28 #include "oops/fieldStreams.hpp"
29 #include "prims/jvmtiClassFileReconstituter.hpp"
30 #include "runtime/signature.hpp"
31 #ifdef TARGET_ARCH_x86
32 # include "bytes_x86.hpp"
33 #endif
34 #ifdef TARGET_ARCH_sparc
35 # include "bytes_sparc.hpp"
36 #endif
37 #ifdef TARGET_ARCH_zero
38 # include "bytes_zero.hpp"
39 #endif
40 #ifdef TARGET_ARCH_arm
41 # include "bytes_arm.hpp"
42 #endif
43 #ifdef TARGET_ARCH_ppc
44 # include "bytes_ppc.hpp"
45 #endif
46 // FIXME: add Deprecated, LVTT attributes
47 // FIXME: fix Synthetic attribute
48 // FIXME: per Serguei, add error return handling for constantPoolOopDesc::copy_cpool_bytes()
49
50
51 // Write the field information portion of ClassFile structure
52 // JVMSpec| u2 fields_count;
53 // JVMSpec| field_info fields[fields_count];
54 void JvmtiClassFileReconstituter::write_field_infos() {
55 HandleMark hm(thread());
56 objArrayHandle fields_anno(thread(), ikh()->fields_annotations());
57
58 // Compute the real number of Java fields
59 int java_fields = ikh()->java_fields_count();
60
61 write_u2(java_fields);
62 for (JavaFieldStream fs(ikh()); !fs.done(); fs.next()) {
63 AccessFlags access_flags = fs.access_flags();
64 int name_index = fs.name_index();
65 int signature_index = fs.signature_index();
66 int initial_value_index = fs.initval_index();
120 // JVMSpec| u2 attribute_name_index;
121 // JVMSpec| u4 attribute_length;
122 // JVMSpec| u2 max_stack;
123 // JVMSpec| u2 max_locals;
124 // JVMSpec| u4 code_length;
125 // JVMSpec| u1 code[code_length];
126 // JVMSpec| u2 exception_table_length;
127 // JVMSpec| { u2 start_pc;
128 // JVMSpec| u2 end_pc;
129 // JVMSpec| u2 handler_pc;
130 // JVMSpec| u2 catch_type;
131 // JVMSpec| } exception_table[exception_table_length];
132 // JVMSpec| u2 attributes_count;
133 // JVMSpec| attribute_info attributes[attributes_count];
134 // JVMSpec| }
135 void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) {
136 constMethodHandle const_method(thread(), method->constMethod());
137 u2 line_num_cnt = 0;
138 int stackmap_len = 0;
139 int local_variable_table_length = 0;
140
141 // compute number and length of attributes
142 int attr_count = 0;
143 int attr_size = 0;
144 if (const_method->has_linenumber_table()) {
145 line_num_cnt = line_number_table_entries(method);
146 if (line_num_cnt != 0) {
147 ++attr_count;
148 // Compute the complete size of the line number table attribute:
149 // LineNumberTable_attribute {
150 // u2 attribute_name_index;
151 // u4 attribute_length;
152 // u2 line_number_table_length;
153 // { u2 start_pc;
154 // u2 line_number;
155 // } line_number_table[line_number_table_length];
156 // }
157 attr_size += 2 + 4 + 2 + line_num_cnt * (2 + 2);
158 }
159 }
160 if (method->has_stackmap_table()) {
161 stackmap_len = method->stackmap_data()->length();
162 if (stackmap_len != 0) {
163 ++attr_count;
164 // Compute the size of the stack map table attribute (VM stores raw):
165 // StackMapTable_attribute {
166 // u2 attribute_name_index;
167 // u4 attribute_length;
168 // u2 number_of_entries;
169 // stack_map_frame_entries[number_of_entries];
170 // }
171 attr_size += 2 + 4 + stackmap_len;
172 }
173 }
174 if (method->has_localvariable_table()) {
175 local_variable_table_length = method->localvariable_table_length();
176 ++attr_count;
177 if (local_variable_table_length != 0) {
178 // Compute the size of the local variable table attribute (VM stores raw):
179 // LocalVariableTable_attribute {
180 // u2 attribute_name_index;
181 // u4 attribute_length;
182 // u2 local_variable_table_length;
183 // {
184 // u2 start_pc;
185 // u2 length;
186 // u2 name_index;
187 // u2 descriptor_index;
188 // u2 index;
189 // }
190 attr_size += 2 + 4 + 2 + local_variable_table_length * (2 + 2 + 2 + 2 + 2);
191 }
192 }
193
194 ExceptionTable exception_table(method());
195 int exception_table_length = exception_table.length();
196 int code_size = const_method->code_size();
197 int size =
198 2+2+4 + // max_stack, max_locals, code_length
199 code_size + // code
200 2 + // exception_table_length
201 (2+2+2+2) * exception_table_length + // exception_table
202 2 + // attributes_count
203 attr_size; // attributes
204
205 write_attribute_name_index("Code");
206 write_u4(size);
207 write_u2(method->max_stack());
208 write_u2(method->max_locals());
209 write_u4(code_size);
210 copy_bytecodes(method, (unsigned char*)writeable_address(code_size));
211 write_u2(exception_table_length);
212 for (int index = 0; index < exception_table_length; index++) {
213 write_u2(exception_table.start_pc(index));
214 write_u2(exception_table.end_pc(index));
215 write_u2(exception_table.handler_pc(index));
216 write_u2(exception_table.catch_type_index(index));
217 }
218 write_u2(attr_count);
219 if (line_num_cnt != 0) {
220 write_line_number_table_attribute(method, line_num_cnt);
221 }
222 if (stackmap_len != 0) {
223 write_stackmap_table_attribute(method, stackmap_len);
224 }
225 if (local_variable_table_length != 0) {
226 write_local_variable_table_attribute(method, local_variable_table_length);
227 }
228 }
229
230 // Write Exceptions attribute
231 // JVMSpec| Exceptions_attribute {
232 // JVMSpec| u2 attribute_name_index;
233 // JVMSpec| u4 attribute_length;
234 // JVMSpec| u2 number_of_exceptions;
235 // JVMSpec| u2 exception_index_table[number_of_exceptions];
236 // JVMSpec| }
237 void JvmtiClassFileReconstituter::write_exceptions_attribute(constMethodHandle const_method) {
238 CheckedExceptionElement* checked_exceptions = const_method->checked_exceptions_start();
239 int checked_exceptions_length = const_method->checked_exceptions_length();
240 int size =
241 2 + // number_of_exceptions
242 2 * checked_exceptions_length; // exception_index_table
243
244 write_attribute_name_index("Exceptions");
245 write_u4(size);
246 write_u2(checked_exceptions_length);
247 for (int index = 0; index < checked_exceptions_length; index++) {
372 // JVMSpec| u4 attribute_length;
373 // JVMSpec| u2 line_number_table_length;
374 // JVMSpec| { u2 start_pc;
375 // JVMSpec| u2 line_number;
376 // JVMSpec| } line_number_table[line_number_table_length];
377 // JVMSpec| }
378 void JvmtiClassFileReconstituter::write_line_number_table_attribute(methodHandle method,
379 u2 num_entries) {
380
381 write_attribute_name_index("LineNumberTable");
382 write_u4(2 + num_entries * (2 + 2));
383 write_u2(num_entries);
384
385 CompressedLineNumberReadStream stream(method->compressed_linenumber_table());
386 while (stream.read_pair()) {
387 write_u2(stream.bci());
388 write_u2(stream.line());
389 }
390 }
391
392 // Write LineNumberTable attribute
393 // JVMSpec| LocalVariableTable_attribute {
394 // JVMSpec| u2 attribute_name_index;
395 // JVMSpec| u4 attribute_length;
396 // JVMSpec| u2 local_variable_table_length;
397 // JVMSpec| { u2 start_pc;
398 // JVMSpec| u2 length;
399 // JVMSpec| u2 name_index;
400 // JVMSpec| u2 descriptor_index;
401 // JVMSpec| u2 index;
402 // JVMSpec| } local_variable_table[local_variable_table_length];
403 // JVMSpec| }
404 void JvmtiClassFileReconstituter::write_local_variable_table_attribute(methodHandle method, u2 num_entries) {
405 write_attribute_name_index("LocalVariableTable");
406 write_u4(2 + num_entries * (2 + 2 + 2 + 2 + 2));
407 write_u2(num_entries);
408
409 assert(method->localvariable_table_length() == num_entries, "just checking");
410
411 LocalVariableTableElement *elem = method->localvariable_table_start();
412 for (int j=0; j<method->localvariable_table_length(); j++) {
413 write_u2(elem->start_bci);
414 write_u2(elem->length);
415 write_u2(elem->name_cp_index);
416 write_u2(elem->descriptor_cp_index);
417 write_u2(elem->slot);
418 elem++;
419 }
420 }
421
422 // Write stack map table attribute
423 // JSR-202| StackMapTable_attribute {
424 // JSR-202| u2 attribute_name_index;
425 // JSR-202| u4 attribute_length;
426 // JSR-202| u2 number_of_entries;
427 // JSR-202| stack_map_frame_entries[number_of_entries];
428 // JSR-202| }
429 void JvmtiClassFileReconstituter::write_stackmap_table_attribute(methodHandle method,
430 int stackmap_len) {
431
432 write_attribute_name_index("StackMapTable");
433 write_u4(stackmap_len);
434 memcpy(
435 writeable_address(stackmap_len),
436 (void*)(method->stackmap_data()->byte_at_addr(0)),
437 stackmap_len);
438 }
439
440 // Write one method_info structure
441 // JVMSpec| method_info {
|
26 #include "classfile/symbolTable.hpp"
27 #include "interpreter/bytecodeStream.hpp"
28 #include "oops/fieldStreams.hpp"
29 #include "prims/jvmtiClassFileReconstituter.hpp"
30 #include "runtime/signature.hpp"
31 #ifdef TARGET_ARCH_x86
32 # include "bytes_x86.hpp"
33 #endif
34 #ifdef TARGET_ARCH_sparc
35 # include "bytes_sparc.hpp"
36 #endif
37 #ifdef TARGET_ARCH_zero
38 # include "bytes_zero.hpp"
39 #endif
40 #ifdef TARGET_ARCH_arm
41 # include "bytes_arm.hpp"
42 #endif
43 #ifdef TARGET_ARCH_ppc
44 # include "bytes_ppc.hpp"
45 #endif
46 // FIXME: add Deprecated attribute
47 // FIXME: fix Synthetic attribute
48 // FIXME: per Serguei, add error return handling for constantPoolOopDesc::copy_cpool_bytes()
49
50
51 // Write the field information portion of ClassFile structure
52 // JVMSpec| u2 fields_count;
53 // JVMSpec| field_info fields[fields_count];
54 void JvmtiClassFileReconstituter::write_field_infos() {
55 HandleMark hm(thread());
56 objArrayHandle fields_anno(thread(), ikh()->fields_annotations());
57
58 // Compute the real number of Java fields
59 int java_fields = ikh()->java_fields_count();
60
61 write_u2(java_fields);
62 for (JavaFieldStream fs(ikh()); !fs.done(); fs.next()) {
63 AccessFlags access_flags = fs.access_flags();
64 int name_index = fs.name_index();
65 int signature_index = fs.signature_index();
66 int initial_value_index = fs.initval_index();
120 // JVMSpec| u2 attribute_name_index;
121 // JVMSpec| u4 attribute_length;
122 // JVMSpec| u2 max_stack;
123 // JVMSpec| u2 max_locals;
124 // JVMSpec| u4 code_length;
125 // JVMSpec| u1 code[code_length];
126 // JVMSpec| u2 exception_table_length;
127 // JVMSpec| { u2 start_pc;
128 // JVMSpec| u2 end_pc;
129 // JVMSpec| u2 handler_pc;
130 // JVMSpec| u2 catch_type;
131 // JVMSpec| } exception_table[exception_table_length];
132 // JVMSpec| u2 attributes_count;
133 // JVMSpec| attribute_info attributes[attributes_count];
134 // JVMSpec| }
135 void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) {
136 constMethodHandle const_method(thread(), method->constMethod());
137 u2 line_num_cnt = 0;
138 int stackmap_len = 0;
139 int local_variable_table_length = 0;
140 int local_variable_type_table_length = 0;
141
142 // compute number and length of attributes
143 int attr_count = 0;
144 int attr_size = 0;
145 if (const_method->has_linenumber_table()) {
146 line_num_cnt = line_number_table_entries(method);
147 if (line_num_cnt != 0) {
148 ++attr_count;
149 // Compute the complete size of the line number table attribute:
150 // LineNumberTable_attribute {
151 // u2 attribute_name_index;
152 // u4 attribute_length;
153 // u2 line_number_table_length;
154 // { u2 start_pc;
155 // u2 line_number;
156 // } line_number_table[line_number_table_length];
157 // }
158 attr_size += 2 + 4 + 2 + line_num_cnt * (2 + 2);
159 }
160 }
161 if (method->has_stackmap_table()) {
162 stackmap_len = method->stackmap_data()->length();
163 if (stackmap_len != 0) {
164 ++attr_count;
165 // Compute the size of the stack map table attribute (VM stores raw):
166 // StackMapTable_attribute {
167 // u2 attribute_name_index;
168 // u4 attribute_length;
169 // u2 number_of_entries;
170 // stack_map_frame_entries[number_of_entries];
171 // }
172 attr_size += 2 + 4 + stackmap_len;
173 }
174 }
175 if (method->has_localvariable_table()) {
176 local_variable_table_length = method->localvariable_table_length();
177 if (local_variable_table_length != 0) {
178 ++attr_count;
179 // Compute the size of the local variable table attribute (VM stores raw):
180 // LocalVariableTable_attribute {
181 // u2 attribute_name_index;
182 // u4 attribute_length;
183 // u2 local_variable_table_length;
184 // {
185 // u2 start_pc;
186 // u2 length;
187 // u2 name_index;
188 // u2 descriptor_index;
189 // u2 index;
190 // }
191 attr_size += 2 + 4 + 2 + local_variable_table_length * (2 + 2 + 2 + 2 + 2);
192
193 // Local variables with generic signatures must have LVTT entries
194 LocalVariableTableElement *elem = method->localvariable_table_start();
195 for (int idx = 0; idx < local_variable_table_length; idx++) {
196 if (elem[idx].signature_cp_index > 0) {
197 local_variable_type_table_length++;
198 }
199 }
200 }
201
202 if (local_variable_type_table_length != 0) {
203 ++attr_count;
204 // Compute the size of the local variable type table attribute (VM stores raw):
205 // LocalVariableTypeTable_attribute {
206 // u2 attribute_name_index;
207 // u4 attribute_length;
208 // u2 local_variable_type_table_length;
209 // {
210 // u2 start_pc;
211 // u2 length;
212 // u2 name_index;
213 // u2 signature_index;
214 // u2 index;
215 // }
216 attr_size += 2 + 4 + 2 + local_variable_type_table_length * (2 + 2 + 2 + 2 + 2);
217 }
218 }
219
220 ExceptionTable exception_table(method());
221 int exception_table_length = exception_table.length();
222 int code_size = const_method->code_size();
223 int size =
224 2+2+4 + // max_stack, max_locals, code_length
225 code_size + // code
226 2 + // exception_table_length
227 (2+2+2+2) * exception_table_length + // exception_table
228 2 + // attributes_count
229 attr_size; // attributes
230
231 write_attribute_name_index("Code");
232 write_u4(size);
233 write_u2(method->max_stack());
234 write_u2(method->max_locals());
235 write_u4(code_size);
236 copy_bytecodes(method, (unsigned char*)writeable_address(code_size));
237 write_u2(exception_table_length);
238 for (int index = 0; index < exception_table_length; index++) {
239 write_u2(exception_table.start_pc(index));
240 write_u2(exception_table.end_pc(index));
241 write_u2(exception_table.handler_pc(index));
242 write_u2(exception_table.catch_type_index(index));
243 }
244 write_u2(attr_count);
245 if (line_num_cnt != 0) {
246 write_line_number_table_attribute(method, line_num_cnt);
247 }
248 if (stackmap_len != 0) {
249 write_stackmap_table_attribute(method, stackmap_len);
250 }
251 if (local_variable_table_length != 0) {
252 write_local_variable_table_attribute(method, local_variable_table_length);
253 }
254 if (local_variable_type_table_length != 0) {
255 write_local_variable_type_table_attribute(method, local_variable_type_table_length);
256 }
257 }
258
259 // Write Exceptions attribute
260 // JVMSpec| Exceptions_attribute {
261 // JVMSpec| u2 attribute_name_index;
262 // JVMSpec| u4 attribute_length;
263 // JVMSpec| u2 number_of_exceptions;
264 // JVMSpec| u2 exception_index_table[number_of_exceptions];
265 // JVMSpec| }
266 void JvmtiClassFileReconstituter::write_exceptions_attribute(constMethodHandle const_method) {
267 CheckedExceptionElement* checked_exceptions = const_method->checked_exceptions_start();
268 int checked_exceptions_length = const_method->checked_exceptions_length();
269 int size =
270 2 + // number_of_exceptions
271 2 * checked_exceptions_length; // exception_index_table
272
273 write_attribute_name_index("Exceptions");
274 write_u4(size);
275 write_u2(checked_exceptions_length);
276 for (int index = 0; index < checked_exceptions_length; index++) {
401 // JVMSpec| u4 attribute_length;
402 // JVMSpec| u2 line_number_table_length;
403 // JVMSpec| { u2 start_pc;
404 // JVMSpec| u2 line_number;
405 // JVMSpec| } line_number_table[line_number_table_length];
406 // JVMSpec| }
407 void JvmtiClassFileReconstituter::write_line_number_table_attribute(methodHandle method,
408 u2 num_entries) {
409
410 write_attribute_name_index("LineNumberTable");
411 write_u4(2 + num_entries * (2 + 2));
412 write_u2(num_entries);
413
414 CompressedLineNumberReadStream stream(method->compressed_linenumber_table());
415 while (stream.read_pair()) {
416 write_u2(stream.bci());
417 write_u2(stream.line());
418 }
419 }
420
421 // Write LocalVariableTable attribute
422 // JVMSpec| LocalVariableTable_attribute {
423 // JVMSpec| u2 attribute_name_index;
424 // JVMSpec| u4 attribute_length;
425 // JVMSpec| u2 local_variable_table_length;
426 // JVMSpec| { u2 start_pc;
427 // JVMSpec| u2 length;
428 // JVMSpec| u2 name_index;
429 // JVMSpec| u2 descriptor_index;
430 // JVMSpec| u2 index;
431 // JVMSpec| } local_variable_table[local_variable_table_length];
432 // JVMSpec| }
433 void JvmtiClassFileReconstituter::write_local_variable_table_attribute(methodHandle method, u2 num_entries) {
434 write_attribute_name_index("LocalVariableTable");
435 write_u4(2 + num_entries * (2 + 2 + 2 + 2 + 2));
436 write_u2(num_entries);
437
438 assert(method->localvariable_table_length() == num_entries, "just checking");
439
440 LocalVariableTableElement *elem = method->localvariable_table_start();
441 for (int j=0; j<method->localvariable_table_length(); j++) {
442 write_u2(elem->start_bci);
443 write_u2(elem->length);
444 write_u2(elem->name_cp_index);
445 write_u2(elem->descriptor_cp_index);
446 write_u2(elem->slot);
447 elem++;
448 }
449 }
450
451 // Write LocalVariableTypeTable attribute
452 // JVMSpec| LocalVariableTypeTable_attribute {
453 // JVMSpec| u2 attribute_name_index;
454 // JVMSpec| u4 attribute_length;
455 // JVMSpec| u2 local_variable_type_table_length;
456 // JVMSpec| { u2 start_pc;
457 // JVMSpec| u2 length;
458 // JVMSpec| u2 name_index;
459 // JVMSpec| u2 signature_index;
460 // JVMSpec| u2 index;
461 // JVMSpec| } local_variable_type_table[local_variable_type_table_length];
462 // JVMSpec| }
463 void JvmtiClassFileReconstituter::write_local_variable_type_table_attribute(methodHandle method, u2 num_entries) {
464 write_attribute_name_index("LocalVariableTypeTable");
465 write_u4(2 + num_entries * (2 + 2 + 2 + 2 + 2));
466 write_u2(num_entries);
467
468 LocalVariableTableElement *elem = method->localvariable_table_start();
469 for (int j=0; j<method->localvariable_table_length(); j++) {
470 if (elem->signature_cp_index > 0) {
471 // Local variable has a generic signature - write LVTT attribute entry
472 write_u2(elem->start_bci);
473 write_u2(elem->length);
474 write_u2(elem->name_cp_index);
475 write_u2(elem->signature_cp_index);
476 write_u2(elem->slot);
477 num_entries--;
478 }
479 elem++;
480 }
481 assert(num_entries == 0, "just checking");
482 }
483
484 // Write stack map table attribute
485 // JSR-202| StackMapTable_attribute {
486 // JSR-202| u2 attribute_name_index;
487 // JSR-202| u4 attribute_length;
488 // JSR-202| u2 number_of_entries;
489 // JSR-202| stack_map_frame_entries[number_of_entries];
490 // JSR-202| }
491 void JvmtiClassFileReconstituter::write_stackmap_table_attribute(methodHandle method,
492 int stackmap_len) {
493
494 write_attribute_name_index("StackMapTable");
495 write_u4(stackmap_len);
496 memcpy(
497 writeable_address(stackmap_len),
498 (void*)(method->stackmap_data()->byte_at_addr(0)),
499 stackmap_len);
500 }
501
502 // Write one method_info structure
503 // JVMSpec| method_info {
|