1 /*
2  * Copyright (c) 2016, 2018, 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 "jvm.h"
27 #include "classfile/classFileParser.hpp"
28 #include "classfile/classFileStream.hpp"
29 #include "classfile/javaClasses.inline.hpp"
30 #include "classfile/moduleEntry.hpp"
31 #include "classfile/modules.hpp"
32 #include "classfile/stackMapTable.hpp"
33 #include "classfile/verificationType.hpp"
34 #include "interpreter/bytecodes.hpp"
35 #include "jfr/instrumentation/jfrEventClassTransformer.hpp"
36 #include "jfr/jfr.hpp"
37 #include "jfr/jni/jfrJavaSupport.hpp"
38 #include "jfr/jni/jfrUpcalls.hpp"
39 #include "jfr/support/jfrEventClass.hpp"
40 #include "jfr/utilities/jfrBigEndian.hpp"
41 #include "jfr/writers/jfrBigEndianWriter.hpp"
42 #include "logging/log.hpp"
43 #include "memory/allocation.inline.hpp"
44 #include "memory/resourceArea.hpp"
45 #include "oops/array.hpp"
46 #include "oops/instanceKlass.hpp"
47 #include "oops/method.hpp"
48 #include "prims/jvmtiRedefineClasses.hpp"
49 #include "runtime/handles.inline.hpp"
50 #include "runtime/os.hpp"
51 #include "runtime/thread.inline.hpp"
52 #include "utilities/exceptions.hpp"
53 #include "utilities/globalDefinitions.hpp"
54 #include "utilities/macros.hpp"
55 
56 static const u2 number_of_new_methods = 5;
57 static const u2 number_of_new_fields = 3;
58 static const int extra_stream_bytes = 0x280;
59 static const u2 invalid_cp_index = 0;
60 
61 static const char* utf8_constants[] = {
62   "Code",         // 0
63   "J",            // 1
64   "commit",       // 2
65   "eventHandler", // 3
66   "duration",     // 4
67   "begin",        // 5
68   "()V",          // 6
69   "isEnabled",    // 7
70   "()Z",          // 8
71   "end",          // 9
72   "shouldCommit", // 10
73   "startTime",    // 11 // LAST_REQUIRED_UTF8
74   "Ljdk/jfr/internal/handlers/EventHandler;", // 12
75   "Ljava/lang/Object;", // 13
76   "<clinit>",     // 14
77   "jdk/jfr/FlightRecorder", // 15
78   "register",     // 16
79   "(Ljava/lang/Class;)V", // 17
80   "StackMapTable", // 18
81   "Exceptions", // 19
82   "LineNumberTable", // 20
83   "LocalVariableTable", // 21
84   "LocalVariableTypeTable", // 22
85   "RuntimeVisibleAnnotation", // 23
86 };
87 
88 enum utf8_req_symbols {
89   UTF8_REQ_Code,
90   UTF8_REQ_J_FIELD_DESC,
91   UTF8_REQ_commit,
92   UTF8_REQ_eventHandler,
93   UTF8_REQ_duration,
94   UTF8_REQ_begin,
95   UTF8_REQ_EMPTY_VOID_METHOD_DESC,
96   UTF8_REQ_isEnabled,
97   UTF8_REQ_EMPTY_BOOLEAN_METHOD_DESC,
98   UTF8_REQ_end,
99   UTF8_REQ_shouldCommit,
100   UTF8_REQ_startTime,
101   NOF_UTF8_REQ_SYMBOLS
102 };
103 
104 enum utf8_opt_symbols {
105   UTF8_OPT_eventHandler_FIELD_DESC = NOF_UTF8_REQ_SYMBOLS,
106   UTF8_OPT_LjavaLangObject,
107   UTF8_OPT_clinit,
108   UTF8_OPT_FlightRecorder,
109   UTF8_OPT_register,
110   UTF8_OPT_CLASS_VOID_METHOD_DESC,
111   UTF8_OPT_StackMapTable,
112   UTF8_OPT_Exceptions,
113   UTF8_OPT_LineNumberTable,
114   UTF8_OPT_LocalVariableTable,
115   UTF8_OPT_LocalVariableTypeTable,
116   UTF8_OPT_RuntimeVisibleAnnotation,
117   NOF_UTF8_SYMBOLS
118 };
119 
120 static u1 empty_void_method_code_attribute[] = {
121   0x0,
122   0x0,
123   0x0,
124   0xd, // attribute len
125   0x0,
126   0x0, // max stack
127   0x0,
128   0x1, // max locals
129   0x0,
130   0x0,
131   0x0,
132   0x1, // code length
133   Bytecodes::_return,
134   0x0,
135   0x0, // ex table len
136   0x0,
137   0x0  // attributes_count
138 };
139 
140 static u1 boolean_method_code_attribute[] = {
141   0x0,
142   0x0,
143   0x0,
144   0xe,
145   0x0,
146   0x1, // max stack
147   0x0,
148   0x1, // max locals
149   0x0,
150   0x0,
151   0x0,
152   0x2,
153   Bytecodes::_iconst_0,
154   Bytecodes::_ireturn,
155   0x0,
156   0x0, // ex table len
157   0x0,
158   0x0, // attributes_count
159 };
160 
161 // annotation processing support
162 
163 enum {  // initial annotation layout
164   atype_off = 0,      // utf8 such as 'Ljava/lang/annotation/Retention;'
165   count_off = 2,      // u2   such as 1 (one value)
166   member_off = 4,     // utf8 such as 'value'
167   tag_off = 6,        // u1   such as 'c' (type) or 'e' (enum)
168   e_tag_val = 'e',
169   e_type_off = 7,   // utf8 such as 'Ljava/lang/annotation/RetentionPolicy;'
170   e_con_off = 9,    // utf8 payload, such as 'SOURCE', 'CLASS', 'RUNTIME'
171   e_size = 11,     // end of 'e' annotation
172   c_tag_val = 'c',    // payload is type
173   c_con_off = 7,    // utf8 payload, such as 'I'
174   c_size = 9,       // end of 'c' annotation
175   s_tag_val = 's',    // payload is String
176   s_con_off = 7,    // utf8 payload, such as 'Ljava/lang/String;'
177   s_size = 9,
178   min_size = 6        // smallest possible size (zero members)
179 };
180 
181 static int skip_annotation_value(const address, int, int); // fwd decl
182 
183 // Skip an annotation.  Return >=limit if there is any problem.
next_annotation_index(const address buffer,int limit,int index)184 static int next_annotation_index(const address buffer, int limit, int index) {
185   assert(buffer != NULL, "invariant");
186   index += 2;  // skip atype
187   if ((index += 2) >= limit) {
188     return limit;
189   }
190   int nof_members = JfrBigEndian::read<u2>(buffer + index - 2);
191   while (--nof_members >= 0 && index < limit) {
192     index += 2; // skip member
193     index = skip_annotation_value(buffer, limit, index);
194   }
195   return index;
196 }
197 
198 // Skip an annotation value.  Return >=limit if there is any problem.
skip_annotation_value(const address buffer,int limit,int index)199 static int skip_annotation_value(const address buffer, int limit, int index) {
200   assert(buffer != NULL, "invariant");
201   // value := switch (tag:u1) {
202   //   case B, C, I, S, Z, D, F, J, c: con:u2;
203   //   case e: e_class:u2 e_name:u2;
204   //   case s: s_con:u2;
205   //   case [: do(nval:u2) {value};
206   //   case @: annotation;
207   //   case s: s_con:u2;
208   // }
209   if ((index += 1) >= limit) {
210     return limit;
211   }
212   const u1 tag = buffer[index - 1];
213   switch (tag) {
214     case 'B':
215     case 'C':
216     case 'I':
217     case 'S':
218     case 'Z':
219     case 'D':
220     case 'F':
221     case 'J':
222     case 'c':
223     case 's':
224       index += 2;  // skip con or s_con
225       break;
226     case 'e':
227       index += 4;  // skip e_class, e_name
228       break;
229     case '[':
230       {
231         if ((index += 2) >= limit) {
232           return limit;
233         }
234         int nof_values = JfrBigEndian::read<u2>(buffer + index - 2);
235         while (--nof_values >= 0 && index < limit) {
236           index = skip_annotation_value(buffer, limit, index);
237         }
238       }
239       break;
240     case '@':
241       index = next_annotation_index(buffer, limit, index);
242       break;
243     default:
244       return limit;  //  bad tag byte
245   }
246   return index;
247 }
248 
249 static const u2 number_of_elements_offset = (u2)2;
250 static const u2 element_name_offset = (u2)(number_of_elements_offset + 2);
251 static const u2 element_name_size = (u2)2;
252 static const u2 value_type_relative_offset = (u2)2;
253 static const u2 value_relative_offset = (u2)(value_type_relative_offset + 1);
254 
255 // see JVMS - 4.7.16. The RuntimeVisibleAnnotations Attribute
256 
257 class AnnotationElementIterator : public StackObj {
258  private:
259   const InstanceKlass* _ik;
260   const address _buffer;
261   const u2 _limit; // length of annotation
262   mutable u2 _current; // element
263   mutable u2 _next; // element
value_index() const264   u2 value_index() const {
265     return JfrBigEndian::read<u2>(_buffer + _current + value_relative_offset);
266   }
267 
268  public:
AnnotationElementIterator(const InstanceKlass * ik,address buffer,u2 limit)269   AnnotationElementIterator(const InstanceKlass* ik, address buffer, u2 limit) : _ik(ik),
270                                                                                  _buffer(buffer),
271                                                                                  _limit(limit),
272                                                                                  _current(element_name_offset),
273                                                                                  _next(element_name_offset) {
274     assert(_buffer != NULL, "invariant");
275     assert(_next == element_name_offset, "invariant");
276     assert(_current == element_name_offset, "invariant");
277   }
278 
has_next() const279   bool has_next() const {
280     return _next < _limit;
281   }
282 
move_to_next() const283   void move_to_next() const {
284     assert(has_next(), "invariant");
285     _current = _next;
286     if (_next < _limit) {
287       _next = skip_annotation_value(_buffer, _limit, _next + element_name_size);
288     }
289     assert(_next <= _limit, "invariant");
290     assert(_current <= _limit, "invariant");
291   }
292 
number_of_elements() const293   u2 number_of_elements() const {
294     return JfrBigEndian::read<u2>(_buffer + number_of_elements_offset);
295   }
296 
name() const297   const Symbol* name() const {
298     assert(_current < _next, "invariant");
299     return _ik->constants()->symbol_at(JfrBigEndian::read<u2>(_buffer + _current));
300   }
301 
value_type() const302   char value_type() const {
303     return JfrBigEndian::read<u1>(_buffer + _current + value_type_relative_offset);
304   }
305 
read_int() const306   jint read_int() const {
307     return _ik->constants()->int_at(value_index());
308   }
309 
read_bool() const310   bool read_bool() const {
311     return read_int() != 0;
312   }
313 };
314 
315 class AnnotationIterator : public StackObj {
316  private:
317   const InstanceKlass* _ik;
318   // ensure _limit field is declared before _buffer
319   u2 _limit; // length of annotations array
320   const address _buffer;
321   mutable u2 _current; // annotation
322   mutable u2 _next; // annotation
323 
324  public:
AnnotationIterator(const InstanceKlass * ik,AnnotationArray * ar)325   AnnotationIterator(const InstanceKlass* ik, AnnotationArray* ar) : _ik(ik),
326                                                                      _limit(ar != NULL ? ar->length() : 0),
327                                                                      _buffer(_limit > 2 ? ar->adr_at(2) : NULL),
328                                                                      _current(0),
329                                                                      _next(0) {
330     if (_buffer != NULL) {
331       _limit -= 2; // subtract sizeof(u2) number of annotations field
332     }
333   }
has_next() const334   bool has_next() const {
335     return _next < _limit;
336   }
337 
move_to_next() const338   void move_to_next() const {
339     assert(has_next(), "invariant");
340     _current = _next;
341     if (_next < _limit) {
342       _next = next_annotation_index(_buffer, _limit, _next);
343     }
344     assert(_next <= _limit, "invariant");
345     assert(_current <= _limit, "invariant");
346   }
elements() const347   const AnnotationElementIterator elements() const {
348     assert(_current < _next, "invariant");
349     return AnnotationElementIterator(_ik, _buffer + _current, _next - _current);
350   }
type() const351   const Symbol* type() const {
352     assert(_buffer != NULL, "invariant");
353     assert(_current < _limit, "invariant");
354     return _ik->constants()->symbol_at(JfrBigEndian::read<u2>(_buffer + _current));
355   }
356 };
357 
358 static unsigned int unused_hash = 0;
359 static const char value_name[] = "value";
has_annotation(const InstanceKlass * ik,const Symbol * annotation_type,bool & value)360 static bool has_annotation(const InstanceKlass* ik, const Symbol* annotation_type, bool& value) {
361   assert(annotation_type != NULL, "invariant");
362   AnnotationArray* class_annotations = ik->class_annotations();
363   if (class_annotations == NULL) {
364     return false;
365   }
366 
367   const AnnotationIterator annotation_iterator(ik, class_annotations);
368   while (annotation_iterator.has_next()) {
369     annotation_iterator.move_to_next();
370     if (annotation_iterator.type() == annotation_type) {
371       // target annotation found
372       static const Symbol* value_symbol =
373         SymbolTable::lookup_only(value_name, sizeof value_name - 1, unused_hash);
374       assert(value_symbol != NULL, "invariant");
375       const AnnotationElementIterator element_iterator = annotation_iterator.elements();
376       while (element_iterator.has_next()) {
377         element_iterator.move_to_next();
378         if (value_symbol == element_iterator.name()) {
379           // "value" element
380           assert('Z' == element_iterator.value_type(), "invariant");
381           value = element_iterator.read_bool();
382           return true;
383         }
384       }
385     }
386   }
387   return false;
388 }
389 
390 // Evaluate to the value of the first found Symbol* annotation type.
391 // Searching moves upwards in the klass hierarchy in order to support
392 // inherited annotations in addition to the ability to override.
annotation_value(const InstanceKlass * ik,const Symbol * annotation_type,bool & value)393 static bool annotation_value(const InstanceKlass* ik, const Symbol* annotation_type, bool& value) {
394   assert(ik != NULL, "invariant");
395   assert(annotation_type != NULL, "invariant");
396   assert(JdkJfrEvent::is_a(ik), "invariant");
397   if (has_annotation(ik, annotation_type, value)) {
398     return true;
399   }
400   InstanceKlass* const super = InstanceKlass::cast(ik->super());
401   return super != NULL && JdkJfrEvent::is_a(super) ? annotation_value(super, annotation_type, value) : false;
402 }
403 
404 static const char jdk_jfr_module_name[] = "jdk.jfr";
405 
java_base_can_read_jdk_jfr()406 static bool java_base_can_read_jdk_jfr() {
407   static bool can_read = false;
408   if (can_read) {
409     return true;
410   }
411   static Symbol* jdk_jfr_module_symbol = NULL;
412   if (jdk_jfr_module_symbol == NULL) {
413     jdk_jfr_module_symbol = SymbolTable::lookup_only(jdk_jfr_module_name, sizeof jdk_jfr_module_name - 1, unused_hash);
414     if (jdk_jfr_module_symbol == NULL) {
415       return false;
416     }
417   }
418   assert(jdk_jfr_module_symbol != NULL, "invariant");
419   ModuleEntryTable* const table = Modules::get_module_entry_table(Handle());
420   assert(table != NULL, "invariant");
421   const ModuleEntry* const java_base_module = table->javabase_moduleEntry();
422   if (java_base_module == NULL) {
423     return false;
424   }
425   assert(java_base_module != NULL, "invariant");
426   ModuleEntry* const jdk_jfr_module = table->lookup_only(jdk_jfr_module_symbol);
427   if (jdk_jfr_module == NULL) {
428     return false;
429   }
430   assert(jdk_jfr_module != NULL, "invariant");
431   if (java_base_module->can_read(jdk_jfr_module)) {
432     can_read = true;
433   }
434   return can_read;
435 }
436 
437 static const char registered_constant[] = "Ljdk/jfr/Registered;";
438 
439 // Evaluate to the value of the first found "Ljdk/jfr/Registered;" annotation.
440 // Searching moves upwards in the klass hierarchy in order to support
441 // inherited annotations in addition to the ability to override.
should_register_klass(const InstanceKlass * ik,bool & untypedEventHandler)442 static bool should_register_klass(const InstanceKlass* ik, bool& untypedEventHandler) {
443   assert(ik != NULL, "invariant");
444   assert(JdkJfrEvent::is_a(ik), "invariant");
445   assert(!untypedEventHandler, "invariant");
446   static const Symbol* registered_symbol = NULL;
447   if (registered_symbol == NULL) {
448     registered_symbol = SymbolTable::lookup_only(registered_constant, sizeof registered_constant - 1, unused_hash);
449     if (registered_symbol == NULL) {
450       untypedEventHandler = true;
451       return false;
452     }
453   }
454   assert(registered_symbol != NULL, "invariant");
455   bool value = false; // to be set by annotation_value
456   untypedEventHandler = !(annotation_value(ik, registered_symbol, value) || java_base_can_read_jdk_jfr());
457   return value;
458 }
459 
460 /*
461  * Map an utf8 constant back to its CONSTANT_UTF8_INFO
462  */
utf8_info_index(const InstanceKlass * ik,const Symbol * const target,TRAPS)463 static u2 utf8_info_index(const InstanceKlass* ik, const Symbol* const target, TRAPS) {
464   assert(target != NULL, "invariant");
465   const ConstantPool* cp = ik->constants();
466   const int cp_len = cp->length();
467   for (u2 index = 1; index < cp_len; ++index) {
468     const constantTag tag = cp->tag_at(index);
469     if (tag.is_utf8()) {
470       const Symbol* const utf8_sym = cp->symbol_at(index);
471       assert(utf8_sym != NULL, "invariant");
472       if (utf8_sym == target) {
473         return index;
474       }
475     }
476   }
477   // not in constant pool
478   return invalid_cp_index;
479 }
480 
481 #ifdef ASSERT
is_index_within_range(u2 index,u2 orig_cp_len,u2 new_cp_entries_len)482 static bool is_index_within_range(u2 index, u2 orig_cp_len, u2 new_cp_entries_len) {
483   return index > 0 && index < orig_cp_len + new_cp_entries_len;
484 }
485 #endif
486 
add_utf8_info(JfrBigEndianWriter & writer,const char * utf8_constant,u2 orig_cp_len,u2 & new_cp_entries_len)487 static u2 add_utf8_info(JfrBigEndianWriter& writer, const char* utf8_constant, u2 orig_cp_len, u2& new_cp_entries_len) {
488   assert(utf8_constant != NULL, "invariant");
489   writer.write<u1>(JVM_CONSTANT_Utf8);
490   writer.write_utf8_u2_len(utf8_constant);
491   assert(writer.is_valid(), "invariant");
492   // return index for the added utf8 info
493   return orig_cp_len + new_cp_entries_len++;
494 }
495 
add_method_ref_info(JfrBigEndianWriter & writer,u2 cls_name_index,u2 method_index,u2 desc_index,u2 orig_cp_len,u2 & number_of_new_constants,TRAPS)496 static u2 add_method_ref_info(JfrBigEndianWriter& writer,
497                               u2 cls_name_index,
498                               u2 method_index,
499                               u2 desc_index,
500                               u2 orig_cp_len,
501                               u2& number_of_new_constants,
502                               TRAPS) {
503   assert(cls_name_index != invalid_cp_index, "invariant");
504   assert(method_index != invalid_cp_index, "invariant");
505   assert(desc_index != invalid_cp_index, "invariant");
506   assert(is_index_within_range(cls_name_index, orig_cp_len, number_of_new_constants), "invariant");
507   assert(is_index_within_range(method_index, orig_cp_len, number_of_new_constants), "invariant");
508   assert(is_index_within_range(desc_index, orig_cp_len, number_of_new_constants), "invariant");
509   writer.write<u1>(JVM_CONSTANT_Class);
510   writer.write<u2>(cls_name_index);
511   const u2 cls_entry_index = orig_cp_len + number_of_new_constants;
512   ++number_of_new_constants;
513   writer.write<u1>(JVM_CONSTANT_NameAndType);
514   writer.write<u2>(method_index);
515   writer.write<u2>(desc_index);
516   const u2 nat_entry_index = orig_cp_len + number_of_new_constants;
517   ++number_of_new_constants;
518   writer.write<u1>(JVM_CONSTANT_Methodref);
519   writer.write<u2>(cls_entry_index);
520   writer.write<u2>(nat_entry_index);
521   // post-increment number_of_new_constants
522   // value returned is the index to the added method_ref
523   return orig_cp_len + number_of_new_constants++;
524 }
525 
add_flr_register_method_constants(JfrBigEndianWriter & writer,const u2 * utf8_indexes,u2 orig_cp_len,u2 & number_of_new_constants,TRAPS)526 static u2 add_flr_register_method_constants(JfrBigEndianWriter& writer,
527                                             const u2* utf8_indexes,
528                                             u2 orig_cp_len,
529                                             u2& number_of_new_constants,
530                                             TRAPS) {
531   assert(utf8_indexes != NULL, "invariant");
532   return add_method_ref_info(writer,
533                              utf8_indexes[UTF8_OPT_FlightRecorder],
534                              utf8_indexes[UTF8_OPT_register],
535                              utf8_indexes[UTF8_OPT_CLASS_VOID_METHOD_DESC],
536                              orig_cp_len,
537                              number_of_new_constants,
538                              THREAD);
539 }
540 
541 /*
542  * field_info {
543  *   u2             access_flags;
544  *   u2             name_index;
545  *   u2             descriptor_index;
546  *   u2             attributes_count;
547  *   attribute_info attributes[attributes_count];
548  * }
549  */
add_field_info(JfrBigEndianWriter & writer,u2 name_index,u2 desc_index,bool is_static=false)550 static jlong add_field_info(JfrBigEndianWriter& writer, u2 name_index, u2 desc_index, bool is_static = false) {
551   assert(name_index != invalid_cp_index, "invariant");
552   assert(desc_index != invalid_cp_index, "invariant");
553   DEBUG_ONLY(const jlong start_offset = writer.current_offset();)
554   writer.write<u2>(JVM_ACC_SYNTHETIC | JVM_ACC_PRIVATE | (is_static ? JVM_ACC_STATIC : JVM_ACC_TRANSIENT)); // flags
555   writer.write(name_index);
556   writer.write(desc_index);
557   writer.write((u2)0x0); // attributes_count
558   assert(writer.is_valid(), "invariant");
559   DEBUG_ONLY(assert(start_offset + 8 == writer.current_offset(), "invariant");)
560   return writer.current_offset();
561 }
562 
add_field_infos(JfrBigEndianWriter & writer,const u2 * utf8_indexes,bool untypedEventHandler)563 static u2 add_field_infos(JfrBigEndianWriter& writer, const u2* utf8_indexes, bool untypedEventHandler) {
564   assert(utf8_indexes != NULL, "invariant");
565   add_field_info(writer,
566                  utf8_indexes[UTF8_REQ_eventHandler],
567                  untypedEventHandler ? utf8_indexes[UTF8_OPT_LjavaLangObject] : utf8_indexes[UTF8_OPT_eventHandler_FIELD_DESC],
568                  true); // static
569 
570   add_field_info(writer,
571                  utf8_indexes[UTF8_REQ_startTime],
572                  utf8_indexes[UTF8_REQ_J_FIELD_DESC]);
573 
574   add_field_info(writer,
575                  utf8_indexes[UTF8_REQ_duration],
576                  utf8_indexes[UTF8_REQ_J_FIELD_DESC]);
577 
578   return number_of_new_fields;
579 }
580 
581 /*
582  * method_info {
583  *  u2             access_flags;
584  *  u2             name_index;
585  *  u2             descriptor_index;
586  *  u2             attributes_count;
587  *  attribute_info attributes[attributes_count];
588  * }
589  *
590  * Code_attribute {
591  *   u2 attribute_name_index;
592  *   u4 attribute_length;
593  *   u2 max_stack;
594  *   u2 max_locals;
595  *   u4 code_length;
596  *   u1 code[code_length];
597  *   u2 exception_table_length;
598  *   {   u2 start_pc;
599  *       u2 end_pc;
600  *       u2 handler_pc;
601  *       u2 catch_type;
602  *   } exception_table[exception_table_length];
603  *   u2 attributes_count;
604  *   attribute_info attributes[attributes_count];
605  * }
606  */
607 
add_method_info(JfrBigEndianWriter & writer,u2 name_index,u2 desc_index,u2 code_index,const u1 * const code,const size_t code_len)608 static jlong add_method_info(JfrBigEndianWriter& writer,
609                              u2 name_index,
610                              u2 desc_index,
611                              u2 code_index,
612                              const u1* const code,
613                              const size_t code_len) {
614   assert(name_index > 0, "invariant");
615   assert(desc_index > 0, "invariant");
616   assert(code_index > 0, "invariant");
617   DEBUG_ONLY(const jlong start_offset = writer.current_offset();)
618   writer.write<u2>(JVM_ACC_SYNTHETIC | JVM_ACC_PUBLIC); // flags
619   writer.write(name_index);
620   writer.write(desc_index);
621   writer.write<u2>(0x1); // attributes_count ; 1 for "Code" attribute
622   assert(writer.is_valid(), "invariant");
623   DEBUG_ONLY(assert(start_offset + 8 == writer.current_offset(), "invariant");)
624   // Code attribute
625   writer.write(code_index); // "Code"
626   writer.bytes(code, code_len);
627   DEBUG_ONLY(assert((start_offset + 8 + 2 + (jlong)code_len) == writer.current_offset(), "invariant");)
628   return writer.current_offset();
629 }
630 
631 /*
632  * On return, the passed stream will be positioned
633  * just after the constant pool section in the classfile
634  * and the cp length is returned.
635  *
636  * Stream should come in at the start position.
637  */
position_stream_after_cp(const ClassFileStream * stream)638 static u2 position_stream_after_cp(const ClassFileStream* stream) {
639   assert(stream != NULL, "invariant");
640   assert(stream->current_offset() == 0, "invariant");
641   stream->skip_u4_fast(2);  // 8 bytes skipped
642   const u2 cp_len = stream->get_u2_fast();
643   assert(cp_len > 0, "invariant");
644   // now spin the stream position to just after the constant pool
645   for (u2 index = 1; index < cp_len; ++index) {
646     const u1 tag = stream->get_u1_fast(); // cp tag
647     switch (tag) {
648       case JVM_CONSTANT_Class:
649       case JVM_CONSTANT_String: {
650         stream->skip_u2_fast(1); // skip 2 bytes
651         continue;
652       }
653       case JVM_CONSTANT_Fieldref:
654       case JVM_CONSTANT_Methodref:
655       case JVM_CONSTANT_InterfaceMethodref:
656       case JVM_CONSTANT_Integer:
657       case JVM_CONSTANT_Float:
658       case JVM_CONSTANT_NameAndType:
659       case JVM_CONSTANT_InvokeDynamic: {
660         stream->skip_u4_fast(1); // skip 4 bytes
661         continue;
662       }
663       case JVM_CONSTANT_Long:
664       case JVM_CONSTANT_Double: {
665         stream->skip_u4_fast(2); // skip 8 bytes
666         // Skip entry following eigth-byte constant, see JVM book p. 98
667         ++index;
668         continue;
669       }
670       case JVM_CONSTANT_Utf8: {
671         u2 utf8_length = stream->get_u2_fast();
672         stream->skip_u1_fast(utf8_length); // skip 2 + len bytes
673         continue;
674       }
675       case JVM_CONSTANT_MethodHandle:
676       case JVM_CONSTANT_MethodType: {
677         if (tag == JVM_CONSTANT_MethodHandle) {
678           stream->skip_u1_fast(1);
679           stream->skip_u2_fast(1); // skip 3 bytes
680         }
681         else if (tag == JVM_CONSTANT_MethodType) {
682           stream->skip_u2_fast(1); // skip 3 bytes
683         }
684       }
685       continue;
686       default:
687         assert(false, "error in skip logic!");
688         break;
689     } // end switch(tag)
690   }
691   return cp_len;
692 }
693 
694 /*
695 * On return, the passed stream will be positioned
696 * just after the fields section in the classfile
697 * and the number of fields will be returned.
698 *
699 * Stream should come in positioned just before fields_count
700 */
position_stream_after_fields(const ClassFileStream * stream)701 static u2 position_stream_after_fields(const ClassFileStream* stream) {
702   assert(stream != NULL, "invariant");
703   assert(stream->current_offset() > 0, "invariant");
704   // fields len
705   const u2 orig_fields_len = stream->get_u2_fast();
706   // fields
707   for (u2 i = 0; i < orig_fields_len; ++i) {
708     stream->skip_u2_fast(3);
709     const u2 attrib_info_len = stream->get_u2_fast();
710     for (u2 j = 0; j < attrib_info_len; ++j) {
711       stream->skip_u2_fast(1);
712       const u4 attrib_len = stream->get_u4_fast();
713       stream->skip_u1_fast(attrib_len);
714     }
715   }
716   return orig_fields_len;
717 }
718 
719 /*
720 * On return, the passed stream will be positioned
721 * just after the methods section in the classfile
722 * and the number of methods will be returned.
723 *
724 * Stream should come in positioned just before methods_count
725 */
position_stream_after_methods(JfrBigEndianWriter & writer,const ClassFileStream * stream,const u2 * utf8_indexes,bool register_klass,const Method * clinit_method,u4 & orig_method_len_offset)726 static u2 position_stream_after_methods(JfrBigEndianWriter& writer,
727                                         const ClassFileStream* stream,
728                                         const u2* utf8_indexes,
729                                         bool register_klass,
730                                         const Method* clinit_method,
731                                         u4& orig_method_len_offset) {
732   assert(stream != NULL, "invariant");
733   assert(stream->current_offset() > 0, "invariant");
734   assert(utf8_indexes != NULL, "invariant");
735   // We will come back to this location when we
736   // know how many methods there will be.
737   writer.reserve(sizeof(u2));
738   const u2 orig_methods_len = stream->get_u2_fast();
739   // Move copy position past original method_count
740   // in order to not copy the original count
741   orig_method_len_offset += sizeof(u2);
742   for (u2 i = 0; i < orig_methods_len; ++i) {
743     const u4 method_offset = stream->current_offset();
744     stream->skip_u2_fast(1); // Access Flags
745     const u2 name_index = stream->get_u2_fast(); // Name index
746     stream->skip_u2_fast(1); // Descriptor index
747     const u2 attributes_count = stream->get_u2_fast();
748     for (u2 j = 0; j < attributes_count; ++j) {
749       stream->skip_u2_fast(1);
750       const u4 attrib_len = stream->get_u4_fast();
751       stream->skip_u1_fast(attrib_len);
752     }
753     if (clinit_method != NULL && name_index == clinit_method->name_index()) {
754       // The method just parsed is an existing <clinit> method.
755       // If the class has the @Registered(false) annotation, i.e. marking a class
756       // for opting out from automatic registration, then we do not need to do anything.
757       if (!register_klass) {
758         continue;
759       }
760       // Automatic registration with the jfr system is acccomplished
761       // by pre-pending code to the <clinit> method of the class.
762       // We will need to re-create a new <clinit> in a later step.
763       // For now, ensure that this method is excluded from the methods
764       // being copied.
765       writer.bytes(stream->buffer() + orig_method_len_offset,
766                    method_offset - orig_method_len_offset);
767       assert(writer.is_valid(), "invariant");
768 
769       // Update copy position to skip copy of <clinit> method
770       orig_method_len_offset = stream->current_offset();
771     }
772   }
773   return orig_methods_len;
774 }
775 
add_method_infos(JfrBigEndianWriter & writer,const u2 * utf8_indexes)776 static u2 add_method_infos(JfrBigEndianWriter& writer, const u2* utf8_indexes) {
777   assert(utf8_indexes != NULL, "invariant");
778   add_method_info(writer,
779                   utf8_indexes[UTF8_REQ_begin],
780                   utf8_indexes[UTF8_REQ_EMPTY_VOID_METHOD_DESC],
781                   utf8_indexes[UTF8_REQ_Code],
782                   empty_void_method_code_attribute,
783                   sizeof(empty_void_method_code_attribute));
784 
785   assert(writer.is_valid(), "invariant");
786 
787   add_method_info(writer,
788                   utf8_indexes[UTF8_REQ_end],
789                   utf8_indexes[UTF8_REQ_EMPTY_VOID_METHOD_DESC],
790                   utf8_indexes[UTF8_REQ_Code],
791                   empty_void_method_code_attribute,
792                   sizeof(empty_void_method_code_attribute));
793 
794   assert(writer.is_valid(), "invariant");
795 
796   add_method_info(writer,
797                   utf8_indexes[UTF8_REQ_commit],
798                   utf8_indexes[UTF8_REQ_EMPTY_VOID_METHOD_DESC],
799                   utf8_indexes[UTF8_REQ_Code],
800                   empty_void_method_code_attribute,
801                   sizeof(empty_void_method_code_attribute));
802 
803   assert(writer.is_valid(), "invariant");
804 
805   add_method_info(writer,
806                   utf8_indexes[UTF8_REQ_isEnabled],
807                   utf8_indexes[UTF8_REQ_EMPTY_BOOLEAN_METHOD_DESC],
808                   utf8_indexes[UTF8_REQ_Code],
809                   boolean_method_code_attribute,
810                   sizeof(boolean_method_code_attribute));
811 
812   assert(writer.is_valid(), "invariant");
813 
814   add_method_info(writer,
815                   utf8_indexes[UTF8_REQ_shouldCommit],
816                   utf8_indexes[UTF8_REQ_EMPTY_BOOLEAN_METHOD_DESC],
817                   utf8_indexes[UTF8_REQ_Code],
818                   boolean_method_code_attribute,
819                   sizeof(boolean_method_code_attribute));
820   assert(writer.is_valid(), "invariant");
821   return number_of_new_methods;
822 }
823 
adjust_exception_table(JfrBigEndianWriter & writer,u2 bci_adjustment_offset,const Method * method,TRAPS)824 static void adjust_exception_table(JfrBigEndianWriter& writer, u2 bci_adjustment_offset, const Method* method, TRAPS) {
825   const u2 ex_table_length = method != NULL ? (u2)method->exception_table_length() : 0;
826   writer.write<u2>(ex_table_length); // Exception table length
827   if (ex_table_length > 0) {
828     assert(method != NULL, "invariant");
829     const ExceptionTableElement* const ex_elements = method->exception_table_start();
830     for (int i = 0; i < ex_table_length; ++i) {
831       assert(ex_elements != NULL, "invariant");
832       writer.write<u2>(ex_elements[i].start_pc + bci_adjustment_offset);
833       writer.write<u2>(ex_elements[i].end_pc + bci_adjustment_offset);
834       writer.write<u2>(ex_elements[i].handler_pc + bci_adjustment_offset);
835       writer.write<u2>(ex_elements[i].catch_type_index); // no adjustment
836     }
837   }
838 }
839 
840 enum StackMapFrameTypes {
841   SAME_FRAME_BEGIN = 0,
842   SAME_FRAME_END = 63,
843   SAME_LOCALS_1_STACK_ITEM_FRAME_BEGIN = 64,
844   SAME_LOCALS_1_STACK_ITEM_FRAME_END = 127,
845   SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247,
846   CHOP_FRAME_BEGIN = 248,
847   CHOP_FRAME_END = 250,
848   SAME_FRAME_EXTENDED = 251,
849   APPEND_FRAME_BEGIN = 252,
850   APPEND_FRAME_END = 254,
851   FULL_FRAME = 255
852 };
853 
adjust_stack_map(JfrBigEndianWriter & writer,Array<u1> * stack_map,const u2 * utf8_indexes,u2 bci_adjustment_offset,TRAPS)854 static void adjust_stack_map(JfrBigEndianWriter& writer,
855                              Array<u1>* stack_map,
856                              const u2* utf8_indexes,
857                              u2 bci_adjustment_offset,
858                              TRAPS) {
859   assert(stack_map != NULL, "invariant");
860   assert(utf8_indexes != NULL, "invariant");
861   writer.write<u2>(utf8_indexes[UTF8_OPT_StackMapTable]);
862   const jlong stack_map_attrib_len_offset = writer.current_offset();
863   writer.reserve(sizeof(u4));
864   StackMapStream stream(stack_map);
865   const u2 stack_map_entries = stream.get_u2(THREAD);
866   // number of entries
867   writer.write<u2>(stack_map_entries); // new stack map entry added
868   const u1 frame_type = stream.get_u1(THREAD);
869   // SAME_FRAME and SAME_LOCALS_1_STACK_ITEM_FRAME encode
870   // their offset_delta into the actual frame type itself.
871   // If such a frame type is the first frame, then we transform
872   // it to a SAME_FRAME_EXTENDED or a SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED frame.
873   // This is done in order to not overflow frame types accidentally
874   // when adjusting the offset_delta. In changing the frame types,
875   // we can work with an explicit u2 offset_delta field (like the other frame types)
876   if (frame_type <= SAME_FRAME_END) {
877     writer.write<u1>(SAME_FRAME_EXTENDED);
878     writer.write<u2>(frame_type + bci_adjustment_offset);
879   } else if (frame_type >= SAME_LOCALS_1_STACK_ITEM_FRAME_BEGIN &&
880              frame_type <= SAME_LOCALS_1_STACK_ITEM_FRAME_END) {
881     writer.write<u1>(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED);
882     writer.write<u2>((frame_type - SAME_LOCALS_1_STACK_ITEM_FRAME_BEGIN) + bci_adjustment_offset);
883   } else if (frame_type >= SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
884       // SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED to FULL_FRAME
885       // has a u2 offset_delta field
886       writer.write<u1>(frame_type);
887       writer.write<u2>(stream.get_u2(THREAD) + bci_adjustment_offset);
888   } else {
889     assert(false, "stackMapFrame type is invalid");
890   }
891 
892   while (!stream.at_end()) {
893     writer.write<u1>(stream.get_u1(THREAD));
894   }
895 
896   u4 stack_map_attrib_len = writer.current_offset() - stack_map_attrib_len_offset;
897   // the stack_map_table_attributes_length value is exclusive
898   stack_map_attrib_len -= sizeof(u4);
899   writer.write_at_offset(stack_map_attrib_len, stack_map_attrib_len_offset);
900 }
901 
adjust_line_number_table(JfrBigEndianWriter & writer,const u2 * utf8_indexes,u4 bci_adjustement_offset,const Method * method,TRAPS)902 static void adjust_line_number_table(JfrBigEndianWriter& writer,
903                                      const u2* utf8_indexes,
904                                      u4 bci_adjustement_offset,
905                                      const Method* method,
906                                      TRAPS) {
907   assert(utf8_indexes != NULL, "invariant");
908   assert(method != NULL, "invariant");
909   assert(method->has_linenumber_table(), "invariant");
910   writer.write(utf8_indexes[UTF8_OPT_LineNumberTable]);
911   const jlong lnt_attributes_length_offset = writer.current_offset();
912   writer.reserve(sizeof(u4));
913   const jlong lnt_attributes_entries_offset = writer.current_offset();
914   writer.reserve(sizeof(u2));
915   u1* lnt = method->compressed_linenumber_table();
916   CompressedLineNumberReadStream lnt_stream(lnt);
917   u2 line_number_table_entries = 0;
918   while (lnt_stream.read_pair()) {
919     ++line_number_table_entries;
920     const u2 bci = (u2)lnt_stream.bci();
921     writer.write<u2>(bci + (u2)bci_adjustement_offset);
922     writer.write<u2>((u2)lnt_stream.line());
923   }
924   writer.write_at_offset(line_number_table_entries, lnt_attributes_entries_offset);
925   u4 lnt_table_attributes_len = writer.current_offset() - lnt_attributes_length_offset;
926   // the line_number_table_attributes_length value is exclusive
927   lnt_table_attributes_len -= sizeof(u4);
928   writer.write_at_offset(lnt_table_attributes_len, lnt_attributes_length_offset);
929 }
930 
931 // returns the number of lvtt entries
adjust_local_variable_table(JfrBigEndianWriter & writer,const u2 * utf8_indexes,u2 bci_adjustment_offset,const Method * method,TRAPS)932 static u2 adjust_local_variable_table(JfrBigEndianWriter& writer,
933                                       const u2* utf8_indexes,
934                                       u2 bci_adjustment_offset,
935                                       const Method* method,
936                                       TRAPS) {
937   assert(utf8_indexes != NULL, "invariant");
938   assert(method != NULL, "invariant");
939   assert(method->has_localvariable_table(), "invariant");
940   writer.write<u2>(utf8_indexes[UTF8_OPT_LocalVariableTable]);
941   const jlong lvt_attributes_length_offset = writer.current_offset();
942   writer.reserve(sizeof(u4));
943   const int lvt_len = method->localvariable_table_length();
944   writer.write<u2>((u2)lvt_len);
945   const LocalVariableTableElement* table = method->localvariable_table_start();
946   assert(table != NULL, "invariant");
947   u2 num_lvtt_entries = 0;
948   for (int i = 0; i < lvt_len; ++i) {
949     writer.write<u2>(table[i].start_bci + bci_adjustment_offset);
950     writer.write<u2>(table[i].length);
951     writer.write<u2>(table[i].name_cp_index);
952     writer.write<u2>(table[i].descriptor_cp_index);
953     writer.write<u2>(table[i].slot);
954     if (table[i].signature_cp_index > 0) {
955       ++num_lvtt_entries;
956     }
957   }
958   u4 lvt_table_attributes_len = writer.current_offset() - lvt_attributes_length_offset;
959   // the lvt_table_attributes_length value is exclusive
960   lvt_table_attributes_len -= sizeof(u4);
961   writer.write_at_offset(lvt_table_attributes_len, lvt_attributes_length_offset);
962   return num_lvtt_entries;
963 }
964 
adjust_local_variable_type_table(JfrBigEndianWriter & writer,const u2 * utf8_indexes,u2 bci_adjustment_offset,u2 num_lvtt_entries,const Method * method,TRAPS)965 static void adjust_local_variable_type_table(JfrBigEndianWriter& writer,
966                                             const u2* utf8_indexes,
967                                             u2 bci_adjustment_offset,
968                                             u2 num_lvtt_entries,
969                                             const Method* method,
970                                             TRAPS) {
971   assert(num_lvtt_entries > 0, "invariant");
972   writer.write<u2>(utf8_indexes[UTF8_OPT_LocalVariableTypeTable]);
973   const jlong lvtt_attributes_length_offset = writer.current_offset();
974   writer.reserve(sizeof(u4));
975   writer.write<u2>(num_lvtt_entries);
976   const LocalVariableTableElement* table = method->localvariable_table_start();
977   assert(table != NULL, "invariant");
978   const int lvt_len = method->localvariable_table_length();
979   for (int i = 0; i < lvt_len; ++i) {
980     if (table[i].signature_cp_index > 0) {
981       writer.write<u2>(table[i].start_bci + bci_adjustment_offset);
982       writer.write<u2>(table[i].length);
983       writer.write<u2>(table[i].name_cp_index);
984       writer.write<u2>(table[i].signature_cp_index);
985       writer.write<u2>(table[i].slot);
986     }
987   }
988   u4 lvtt_table_attributes_len = writer.current_offset() - lvtt_attributes_length_offset;
989   // the lvtt_table_attributes_length value is exclusive
990   lvtt_table_attributes_len -= sizeof(u4);
991   writer.write_at_offset(lvtt_table_attributes_len, lvtt_attributes_length_offset);
992 }
993 
adjust_code_attributes(JfrBigEndianWriter & writer,const u2 * utf8_indexes,u2 bci_adjustment_offset,const Method * clinit_method,TRAPS)994 static void adjust_code_attributes(JfrBigEndianWriter& writer,
995                                    const u2* utf8_indexes,
996                                    u2 bci_adjustment_offset,
997                                    const Method* clinit_method,
998                                    TRAPS) {
999   // "Code" attributes
1000   assert(utf8_indexes != NULL, "invariant");
1001   const jlong code_attributes_offset = writer.current_offset();
1002   writer.reserve(sizeof(u2));
1003   u2 number_of_code_attributes = 0;
1004   if (clinit_method != NULL) {
1005     Array<u1>* stack_map = clinit_method->stackmap_data();
1006     if (stack_map != NULL) {
1007       ++number_of_code_attributes;
1008       adjust_stack_map(writer, stack_map, utf8_indexes, bci_adjustment_offset, THREAD);
1009       assert(writer.is_valid(), "invariant");
1010     }
1011     if (clinit_method != NULL && clinit_method->has_linenumber_table()) {
1012       ++number_of_code_attributes;
1013       adjust_line_number_table(writer, utf8_indexes, bci_adjustment_offset, clinit_method, THREAD);
1014       assert(writer.is_valid(), "invariant");
1015     }
1016     if (clinit_method != NULL && clinit_method->has_localvariable_table()) {
1017       ++number_of_code_attributes;
1018       const u2 num_of_lvtt_entries = adjust_local_variable_table(writer, utf8_indexes, bci_adjustment_offset, clinit_method, THREAD);
1019       assert(writer.is_valid(), "invariant");
1020       if (num_of_lvtt_entries > 0) {
1021         ++number_of_code_attributes;
1022         adjust_local_variable_type_table(writer, utf8_indexes, bci_adjustment_offset, num_of_lvtt_entries, clinit_method, THREAD);
1023         assert(writer.is_valid(), "invariant");
1024       }
1025     }
1026   }
1027 
1028   // Store the number of code_attributes
1029   writer.write_at_offset(number_of_code_attributes, code_attributes_offset);
1030 }
1031 
insert_clinit_method(const InstanceKlass * ik,const ClassFileParser & parser,JfrBigEndianWriter & writer,u2 orig_constant_pool_len,const u2 * utf8_indexes,const u2 register_method_ref_index,const Method * clinit_method,TRAPS)1032 static jlong insert_clinit_method(const InstanceKlass* ik,
1033                                   const ClassFileParser& parser,
1034                                   JfrBigEndianWriter& writer,
1035                                   u2 orig_constant_pool_len,
1036                                   const u2* utf8_indexes,
1037                                   const u2 register_method_ref_index,
1038                                   const Method* clinit_method,
1039                                   TRAPS) {
1040   assert(utf8_indexes != NULL, "invariant");
1041   // The injected code length is always this value.
1042   // This is to ensure that padding can be done
1043   // where needed and to simplify size calculations.
1044   static const u2 injected_code_length = 8;
1045   const u2 name_index = utf8_indexes[UTF8_OPT_clinit];
1046   assert(name_index != invalid_cp_index, "invariant");
1047   const u2 desc_index = utf8_indexes[UTF8_REQ_EMPTY_VOID_METHOD_DESC];
1048   const u2 max_stack = MAX2(clinit_method != NULL ? clinit_method->verifier_max_stack() : 1, 1);
1049   const u2 max_locals = MAX2(clinit_method != NULL ? clinit_method->max_locals() : 0, 0);
1050   const u2 orig_bytecodes_length = clinit_method != NULL ? (u2)clinit_method->code_size() : 0;
1051   const address orig_bytecodes = clinit_method != NULL ? clinit_method->code_base() : NULL;
1052   const u2 new_code_length = injected_code_length + orig_bytecodes_length;
1053   DEBUG_ONLY(const jlong start_offset = writer.current_offset();)
1054   writer.write<u2>(JVM_ACC_STATIC); // flags
1055   writer.write<u2>(name_index);
1056   writer.write<u2>(desc_index);
1057   writer.write<u2>((u2)0x1); // attributes_count // "Code"
1058   assert(writer.is_valid(), "invariant");
1059   DEBUG_ONLY(assert(start_offset + 8 == writer.current_offset(), "invariant");)
1060   // "Code" attribute
1061   writer.write<u2>(utf8_indexes[UTF8_REQ_Code]); // "Code"
1062   const jlong code_attribute_length_offset = writer.current_offset();
1063   writer.reserve(sizeof(u4));
1064   writer.write<u2>(max_stack); // max stack
1065   writer.write<u2>(max_locals); // max locals
1066   writer.write<u4>((u4)new_code_length); // code length
1067 
1068   /* BEGIN CLINIT CODE */
1069 
1070   // Note the use of ldc_w here instead of ldc.
1071   // This is to handle all values of "this_class_index"
1072   writer.write<u1>((u1)Bytecodes::_ldc_w);
1073   writer.write<u2>((u2)parser.this_class_index()); // load constant "this class"
1074   writer.write<u1>((u1)Bytecodes::_invokestatic);
1075   // invoke "FlightRecorder.register(Ljava/lang/Class;")
1076   writer.write<u2>(register_method_ref_index);
1077   if (clinit_method == NULL) {
1078     writer.write<u1>((u1)Bytecodes::_nop);
1079     writer.write<u1>((u1)Bytecodes::_return);
1080   } else {
1081     // If we are pre-pending to original code,
1082     // do padding to minimize disruption to the original.
1083     // It might have dependencies on 4-byte boundaries
1084     // i.e. lookupswitch and tableswitch instructions
1085     writer.write<u1>((u1)Bytecodes::_nop);
1086     writer.write<u1>((u1)Bytecodes::_nop);
1087     // insert original clinit code
1088     writer.bytes(orig_bytecodes, orig_bytecodes_length);
1089   }
1090 
1091   /* END CLINIT CODE */
1092 
1093   assert(writer.is_valid(), "invariant");
1094   adjust_exception_table(writer, injected_code_length, clinit_method, THREAD);
1095   assert(writer.is_valid(), "invariant");
1096   adjust_code_attributes(writer, utf8_indexes, injected_code_length, clinit_method, THREAD);
1097   assert(writer.is_valid(), "invariant");
1098   u4 code_attribute_len = writer.current_offset() - code_attribute_length_offset;
1099   // the code_attribute_length value is exclusive
1100   code_attribute_len -= sizeof(u4);
1101   writer.write_at_offset(code_attribute_len, code_attribute_length_offset);
1102   return writer.current_offset();
1103 }
1104 
1105 // Caller needs ResourceMark
create_new_bytes_for_event_klass(const InstanceKlass * ik,const ClassFileParser & parser,TRAPS)1106 static ClassFileStream* create_new_bytes_for_event_klass(const InstanceKlass* ik, const ClassFileParser& parser, TRAPS) {
1107   DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
1108   static const u2 public_final_flag_mask = JVM_ACC_PUBLIC | JVM_ACC_FINAL;
1109   const ClassFileStream* const orig_stream = parser.clone_stream();
1110   const int orig_stream_length = orig_stream->length();
1111   // allocate an identically sized buffer
1112   u1* const new_buffer = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, u1, orig_stream_length);
1113   if (new_buffer == NULL) {
1114     return NULL;
1115   }
1116   assert(new_buffer != NULL, "invariant");
1117   // memcpy the entire [B
1118   memcpy(new_buffer, orig_stream->buffer(), orig_stream_length);
1119   const u2 orig_cp_len = position_stream_after_cp(orig_stream);
1120   assert(orig_cp_len > 0, "invariant");
1121   assert(orig_stream->current_offset() > 0, "invariant");
1122   orig_stream->skip_u2_fast(3); // access_flags, this_class_index, super_class_index
1123   const u2 iface_len = orig_stream->get_u2_fast();
1124   orig_stream->skip_u2_fast(iface_len);
1125   // fields len
1126   const u2 orig_fields_len = orig_stream->get_u2_fast();
1127   // fields
1128   for (u2 i = 0; i < orig_fields_len; ++i) {
1129     orig_stream->skip_u2_fast(3);
1130     const u2 attrib_info_len = orig_stream->get_u2_fast();
1131     for (u2 j = 0; j < attrib_info_len; ++j) {
1132       orig_stream->skip_u2_fast(1);
1133       const u4 attrib_len = orig_stream->get_u4_fast();
1134       orig_stream->skip_u1_fast(attrib_len);
1135     }
1136   }
1137   // methods
1138   const u2 orig_methods_len = orig_stream->get_u2_fast();
1139   for (u2 i = 0; i < orig_methods_len; ++i) {
1140     const u4 access_flag_offset = orig_stream->current_offset();
1141     const u2 flags = orig_stream->get_u2_fast();
1142     // Rewrite JVM_ACC_FINAL -> JVM_ACC_PUBLIC
1143     if (public_final_flag_mask == flags) {
1144       JfrBigEndianWriter accessflagsrewriter(new_buffer + access_flag_offset, sizeof(u2));
1145       accessflagsrewriter.write<u2>(JVM_ACC_PUBLIC);
1146       assert(accessflagsrewriter.is_valid(), "invariant");
1147     }
1148     orig_stream->skip_u2_fast(2);
1149     const u2 attributes_count = orig_stream->get_u2_fast();
1150     for (u2 j = 0; j < attributes_count; ++j) {
1151       orig_stream->skip_u2_fast(1);
1152       const u4 attrib_len = orig_stream->get_u4_fast();
1153       orig_stream->skip_u1_fast(attrib_len);
1154     }
1155   }
1156   return new ClassFileStream(new_buffer, orig_stream_length, NULL, ClassFileStream::verify);
1157 }
1158 
1159 // Attempt to locate an existing UTF8_INFO mapping the utf8_constant.
1160 // If no UTF8_INFO exists, add (append) a new one to the constant pool.
find_or_add_utf8_info(JfrBigEndianWriter & writer,const InstanceKlass * ik,const char * const utf8_constant,u2 orig_cp_len,u2 & added_cp_entries,TRAPS)1161 static u2 find_or_add_utf8_info(JfrBigEndianWriter& writer,
1162                                 const InstanceKlass* ik,
1163                                 const char* const utf8_constant,
1164                                 u2 orig_cp_len,
1165                                 u2& added_cp_entries,
1166                                 TRAPS) {
1167   assert(utf8_constant != NULL, "invariant");
1168   TempNewSymbol utf8_sym = SymbolTable::new_symbol(utf8_constant, THREAD);
1169   // lookup existing
1170   const int utf8_orig_idx = utf8_info_index(ik, utf8_sym, THREAD);
1171   if (utf8_orig_idx != invalid_cp_index) {
1172     // existing constant pool entry found
1173     return utf8_orig_idx;
1174   }
1175   // no existing match, need to add a new utf8 cp entry
1176   assert(invalid_cp_index == utf8_orig_idx, "invariant");
1177   // add / append new
1178   return add_utf8_info(writer, utf8_constant, orig_cp_len, added_cp_entries);
1179 }
1180 
1181 /*
1182  * This routine will resolve the required utf8_constants array
1183  * to their constant pool indexes (mapping to their UTF8_INFO's)
1184  * Only if a constant is actually needed and does not already exist
1185  * will it be added.
1186  *
1187  * The passed in indexes array will be populated with the resolved indexes.
1188  * The number of newly added constant pool entries is returned.
1189  */
resolve_utf8_indexes(JfrBigEndianWriter & writer,const InstanceKlass * ik,u2 * const utf8_indexes,u2 orig_cp_len,const Method * clinit_method,bool register_klass,bool untypedEventHandler,TRAPS)1190 static u2 resolve_utf8_indexes(JfrBigEndianWriter& writer,
1191                                const InstanceKlass* ik,
1192                                u2* const utf8_indexes,
1193                                u2 orig_cp_len,
1194                                const Method* clinit_method,
1195                                bool register_klass,
1196                                bool untypedEventHandler,
1197                                TRAPS) {
1198   assert(utf8_indexes != NULL, "invariant");
1199   u2 added_cp_entries = 0;
1200   // resolve all required symbols
1201   for (u2 index = 0; index < NOF_UTF8_REQ_SYMBOLS; ++index) {
1202     utf8_indexes[index] = find_or_add_utf8_info(writer, ik, utf8_constants[index], orig_cp_len, added_cp_entries, THREAD);
1203   }
1204 
1205   // resolve optional constants
1206   utf8_indexes[UTF8_OPT_eventHandler_FIELD_DESC] = untypedEventHandler ? invalid_cp_index :
1207     find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_eventHandler_FIELD_DESC], orig_cp_len, added_cp_entries, THREAD);
1208 
1209   utf8_indexes[UTF8_OPT_LjavaLangObject] = untypedEventHandler ?
1210     find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_LjavaLangObject], orig_cp_len, added_cp_entries, THREAD) : invalid_cp_index;
1211 
1212   if (register_klass) {
1213     utf8_indexes[UTF8_OPT_clinit] =
1214       find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_clinit], orig_cp_len, added_cp_entries, THREAD);
1215     utf8_indexes[UTF8_OPT_FlightRecorder] =
1216       find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_FlightRecorder], orig_cp_len, added_cp_entries, THREAD);
1217     utf8_indexes[UTF8_OPT_register] =
1218       find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_register], orig_cp_len, added_cp_entries, THREAD);
1219     utf8_indexes[UTF8_OPT_CLASS_VOID_METHOD_DESC] =
1220       find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_CLASS_VOID_METHOD_DESC], orig_cp_len, added_cp_entries, THREAD);
1221   } else {
1222     utf8_indexes[UTF8_OPT_clinit] = invalid_cp_index;
1223     utf8_indexes[UTF8_OPT_FlightRecorder] = invalid_cp_index;
1224     utf8_indexes[UTF8_OPT_register] = invalid_cp_index;
1225     utf8_indexes[UTF8_OPT_CLASS_VOID_METHOD_DESC] = invalid_cp_index;
1226   }
1227 
1228   if (clinit_method != NULL && clinit_method->has_stackmap_table()) {
1229     utf8_indexes[UTF8_OPT_StackMapTable] =
1230       find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_StackMapTable], orig_cp_len, added_cp_entries, THREAD);
1231   } else {
1232     utf8_indexes[UTF8_OPT_StackMapTable] = invalid_cp_index;
1233   }
1234 
1235   if (clinit_method != NULL && clinit_method->has_linenumber_table()) {
1236     utf8_indexes[UTF8_OPT_LineNumberTable] =
1237       find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_LineNumberTable], orig_cp_len, added_cp_entries, THREAD);
1238   } else {
1239     utf8_indexes[UTF8_OPT_LineNumberTable] = invalid_cp_index;
1240   }
1241 
1242   if (clinit_method != NULL && clinit_method->has_localvariable_table()) {
1243     utf8_indexes[UTF8_OPT_LocalVariableTable] =
1244       find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_LocalVariableTable], orig_cp_len, added_cp_entries, THREAD);
1245     utf8_indexes[UTF8_OPT_LocalVariableTypeTable] =
1246       find_or_add_utf8_info(writer, ik, utf8_constants[UTF8_OPT_LocalVariableTypeTable], orig_cp_len, added_cp_entries, THREAD);
1247   } else {
1248     utf8_indexes[UTF8_OPT_LocalVariableTable] = invalid_cp_index;
1249     utf8_indexes[UTF8_OPT_LocalVariableTypeTable] = invalid_cp_index;
1250   }
1251 
1252   return added_cp_entries;
1253 }
1254 
new_bytes_for_lazy_instrumentation(const InstanceKlass * ik,const ClassFileParser & parser,jint & size_of_new_bytes,TRAPS)1255 static u1* new_bytes_for_lazy_instrumentation(const InstanceKlass* ik,
1256                                               const ClassFileParser& parser,
1257                                               jint& size_of_new_bytes,
1258                                               TRAPS) {
1259   assert(ik != NULL, "invariant");
1260   // If the class already has a clinit method
1261   // we need to take that into account
1262   const Method* clinit_method = ik->class_initializer();
1263   bool untypedEventHandler = false;
1264   const bool register_klass = should_register_klass(ik, untypedEventHandler);
1265   const ClassFileStream* const orig_stream = parser.clone_stream();
1266   const int orig_stream_size = orig_stream->length();
1267   assert(orig_stream->current_offset() == 0, "invariant");
1268   const u2 orig_cp_len = position_stream_after_cp(orig_stream);
1269   assert(orig_cp_len > 0, "invariant");
1270   assert(orig_stream->current_offset() > 0, "invariant");
1271   // Dimension and allocate a working byte buffer
1272   // to be used in building up a modified class [B.
1273   const jint new_buffer_size = extra_stream_bytes + orig_stream_size;
1274   u1* const new_buffer = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, u1, new_buffer_size);
1275   if (new_buffer == NULL) {
1276     log_error(jfr, system) ("Thread local allocation (native) for " SIZE_FORMAT
1277       " bytes failed in JfrClassAdapter::on_klass_creation", (size_t)new_buffer_size);
1278     return NULL;
1279   }
1280   assert(new_buffer != NULL, "invariant");
1281   // [B wrapped in a big endian writer
1282   JfrBigEndianWriter writer(new_buffer, new_buffer_size);
1283   assert(writer.current_offset() == 0, "invariant");
1284   const u4 orig_access_flag_offset = orig_stream->current_offset();
1285   // Copy original stream from the beginning up to AccessFlags
1286   // This means the original constant pool contents are copied unmodified
1287   writer.bytes(orig_stream->buffer(), orig_access_flag_offset);
1288   assert(writer.is_valid(), "invariant");
1289   assert(writer.current_offset() == (intptr_t)orig_access_flag_offset, "invariant"); // same positions
1290   // Our writer now sits just after the last original constant pool entry.
1291   // I.e. we are in a good position to append new constant pool entries
1292   // This array will contain the resolved indexes
1293   // in order to reference UTF8_INFO's needed
1294   u2 utf8_indexes[NOF_UTF8_SYMBOLS];
1295   // Resolve_utf8_indexes will be conservative in attempting to
1296   // locate an existing UTF8_INFO; it will only append constants
1297   // that is absolutely required
1298   u2 number_of_new_constants =
1299     resolve_utf8_indexes(writer, ik, utf8_indexes, orig_cp_len, clinit_method, register_klass, untypedEventHandler, THREAD);
1300   // UTF8_INFO entries now added to the constant pool
1301   // In order to invoke a method we would need additional
1302   // constants, JVM_CONSTANT_Class, JVM_CONSTANT_NameAndType
1303   // and JVM_CONSTANT_Methodref.
1304   const u2 flr_register_method_ref_index =
1305     register_klass ?
1306       add_flr_register_method_constants(writer,
1307                                         utf8_indexes,
1308                                         orig_cp_len,
1309                                         number_of_new_constants,
1310                                         THREAD) :  invalid_cp_index;
1311 
1312   // New constant pool entries added and all UTF8_INFO indexes resolved
1313   // Now update the class file constant_pool_count with an updated count
1314   writer.write_at_offset<u2>(orig_cp_len + number_of_new_constants, 8);
1315   assert(writer.is_valid(), "invariant");
1316   orig_stream->skip_u2_fast(3); // access_flags, this_class_index, super_class_index
1317   const u2 iface_len = orig_stream->get_u2_fast(); // interfaces
1318   orig_stream->skip_u2_fast(iface_len);
1319   const u4 orig_fields_len_offset = orig_stream->current_offset();
1320   // Copy from AccessFlags up to and including interfaces
1321   writer.bytes(orig_stream->buffer() + orig_access_flag_offset,
1322                orig_fields_len_offset - orig_access_flag_offset);
1323   assert(writer.is_valid(), "invariant");
1324   const jlong new_fields_len_offset = writer.current_offset();
1325   const u2 orig_fields_len = position_stream_after_fields(orig_stream);
1326   u4 orig_method_len_offset = orig_stream->current_offset();
1327   // Copy up to and including fields
1328   writer.bytes(orig_stream->buffer() + orig_fields_len_offset, orig_method_len_offset - orig_fields_len_offset);
1329   assert(writer.is_valid(), "invariant");
1330   // We are sitting just after the original number of field_infos
1331   // so this is a position where we can add (append) new field_infos
1332   const u2 number_of_new_fields = add_field_infos(writer, utf8_indexes, untypedEventHandler);
1333   assert(writer.is_valid(), "invariant");
1334   const jlong new_method_len_offset = writer.current_offset();
1335   // Additional field_infos added, update classfile fields_count
1336   writer.write_at_offset<u2>(orig_fields_len + number_of_new_fields, new_fields_len_offset);
1337   assert(writer.is_valid(), "invariant");
1338   // Our current location is now at classfile methods_count
1339   const u2 orig_methods_len = position_stream_after_methods(writer,
1340                                                             orig_stream,
1341                                                             utf8_indexes,
1342                                                             register_klass,
1343                                                             clinit_method,
1344                                                             orig_method_len_offset);
1345   const u4 orig_attributes_count_offset = orig_stream->current_offset();
1346   // Copy existing methods
1347   writer.bytes(orig_stream->buffer() + orig_method_len_offset, orig_attributes_count_offset - orig_method_len_offset);
1348   assert(writer.is_valid(), "invariant");
1349   // We are sitting just after the original number of method_infos
1350   // so this is a position where we can add (append) new method_infos
1351   u2 number_of_new_methods = add_method_infos(writer, utf8_indexes);
1352 
1353   // We have just added the new methods.
1354   //
1355   // What about the state of <clinit>?
1356   // We would need to do:
1357   // 1. Nothing (@Registered(false) annotation)
1358   // 2. Build up a new <clinit> - and if the original class already contains a <clinit>,
1359   //                              merging will be neccessary.
1360   //
1361   if (register_klass) {
1362     insert_clinit_method(ik, parser, writer, orig_cp_len, utf8_indexes, flr_register_method_ref_index, clinit_method, THREAD);
1363   }
1364   number_of_new_methods += clinit_method != NULL ? 0 : register_klass ? 1 : 0;
1365   // Update classfile methods_count
1366   writer.write_at_offset<u2>(orig_methods_len + number_of_new_methods, new_method_len_offset);
1367   assert(writer.is_valid(), "invariant");
1368   // Copy last remaining bytes
1369   writer.bytes(orig_stream->buffer() + orig_attributes_count_offset, orig_stream_size - orig_attributes_count_offset);
1370   assert(writer.is_valid(), "invariant");
1371   assert(writer.current_offset() > orig_stream->length(), "invariant");
1372   size_of_new_bytes = (jint)writer.current_offset();
1373   return new_buffer;
1374 }
1375 
log_pending_exception(oop throwable)1376 static void log_pending_exception(oop throwable) {
1377   assert(throwable != NULL, "invariant");
1378   oop msg = java_lang_Throwable::message(throwable);
1379   if (msg != NULL) {
1380     char* text = java_lang_String::as_utf8_string(msg);
1381     if (text != NULL) {
1382       log_error(jfr, system) ("%s", text);
1383     }
1384   }
1385 }
1386 
should_force_instrumentation()1387 static bool should_force_instrumentation() {
1388   return !JfrOptionSet::allow_event_retransforms() || JfrEventClassTransformer::is_force_instrumentation();
1389 }
1390 
create_new_bytes_for_subklass(const InstanceKlass * ik,const ClassFileParser & parser,Thread * t)1391 static ClassFileStream* create_new_bytes_for_subklass(const InstanceKlass* ik, const ClassFileParser& parser, Thread* t) {
1392   assert(JdkJfrEvent::is_a(ik), "invariant");
1393   DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(t));
1394   jint size_of_new_bytes = 0;
1395   const u1* new_bytes = new_bytes_for_lazy_instrumentation(ik, parser, size_of_new_bytes, t);
1396   if (new_bytes == NULL) {
1397     return NULL;
1398   }
1399   assert(new_bytes != NULL, "invariant");
1400   assert(size_of_new_bytes > 0, "invariant");
1401 
1402   bool force_instrumentation = should_force_instrumentation();
1403   if (Jfr::is_recording() || force_instrumentation) {
1404     jint size_instrumented_data = 0;
1405     unsigned char* instrumented_data = NULL;
1406     const jclass super = (jclass)JNIHandles::make_local(ik->super()->java_mirror());
1407     JfrUpcalls::new_bytes_eager_instrumentation(TRACE_ID(ik),
1408                                                 force_instrumentation,
1409                                                 super,
1410                                                 size_of_new_bytes,
1411                                                 new_bytes,
1412                                                 &size_instrumented_data,
1413                                                 &instrumented_data,
1414                                                 t);
1415     if (t->has_pending_exception()) {
1416       log_pending_exception(t->pending_exception());
1417       t->clear_pending_exception();
1418       return NULL;
1419     }
1420     assert(instrumented_data != NULL, "invariant");
1421     assert(size_instrumented_data > 0, "invariant");
1422     return new ClassFileStream(instrumented_data, size_instrumented_data, NULL, ClassFileStream::verify);
1423   }
1424   return new ClassFileStream(new_bytes, size_of_new_bytes, NULL, ClassFileStream::verify);
1425 }
1426 
cache_bytes(InstanceKlass * ik,ClassFileStream * new_stream,InstanceKlass * new_ik,TRAPS)1427 static bool cache_bytes(InstanceKlass* ik, ClassFileStream* new_stream, InstanceKlass* new_ik, TRAPS) {
1428   assert(ik != NULL, "invariant");
1429   assert(new_ik != NULL, "invariant");
1430   assert(new_ik->name() != NULL, "invariant");
1431   assert(new_stream != NULL, "invariant");
1432   assert(!HAS_PENDING_EXCEPTION, "invariant");
1433   static const bool can_retransform = JfrOptionSet::allow_retransforms();
1434   if (!can_retransform) {
1435     return true;
1436   }
1437   const jint stream_len = new_stream->length();
1438   JvmtiCachedClassFileData* p =
1439     (JvmtiCachedClassFileData*)NEW_C_HEAP_ARRAY_RETURN_NULL(u1, offset_of(JvmtiCachedClassFileData, data) + stream_len, mtInternal);
1440   if (p == NULL) {
1441     log_error(jfr, system)("Allocation using C_HEAP_ARRAY for " SIZE_FORMAT
1442       " bytes failed in JfrClassAdapter::on_klass_creation", (size_t)offset_of(JvmtiCachedClassFileData, data) + stream_len);
1443     return false;
1444   }
1445   p->length = stream_len;
1446   memcpy(p->data, new_stream->buffer(), stream_len);
1447   new_ik->set_cached_class_file(p);
1448   JvmtiCachedClassFileData* const cached_class_data = ik->get_cached_class_file();
1449   if (cached_class_data != NULL) {
1450     os::free(cached_class_data);
1451     ik->set_cached_class_file(NULL);
1452   }
1453   return true;
1454 }
1455 
create_new_instance_klass(InstanceKlass * ik,ClassFileStream * stream,TRAPS)1456 static InstanceKlass* create_new_instance_klass(InstanceKlass* ik, ClassFileStream* stream, TRAPS) {
1457   assert(stream != NULL, "invariant");
1458   ResourceMark rm(THREAD);
1459   ClassLoaderData* const cld = ik->class_loader_data();
1460   Handle pd(THREAD, ik->protection_domain());
1461   Symbol* const class_name = ik->name();
1462   const char* const klass_name = class_name != NULL ? class_name->as_C_string() : "";
1463   ClassFileParser new_parser(stream,
1464                              class_name,
1465                              cld,
1466                              pd,
1467                              NULL, // host klass
1468                              NULL, // cp_patches
1469                              ClassFileParser::INTERNAL, // internal visibility
1470                              THREAD);
1471   if (HAS_PENDING_EXCEPTION) {
1472     log_pending_exception(PENDING_EXCEPTION);
1473     CLEAR_PENDING_EXCEPTION;
1474     return NULL;
1475   }
1476   InstanceKlass* const new_ik = new_parser.create_instance_klass(false, THREAD);
1477   if (HAS_PENDING_EXCEPTION) {
1478     log_pending_exception(PENDING_EXCEPTION);
1479     CLEAR_PENDING_EXCEPTION;
1480     return NULL;
1481   }
1482   assert(new_ik != NULL, "invariant");
1483   assert(new_ik->name() != NULL, "invariant");
1484   assert(strncmp(ik->name()->as_C_string(), new_ik->name()->as_C_string(), strlen(ik->name()->as_C_string())) == 0, "invariant");
1485   return cache_bytes(ik, stream, new_ik, THREAD) ? new_ik : NULL;
1486 }
1487 
rewrite_klass_pointer(InstanceKlass * & ik,InstanceKlass * new_ik,ClassFileParser & parser,TRAPS)1488 static void rewrite_klass_pointer(InstanceKlass*& ik, InstanceKlass* new_ik, ClassFileParser& parser, TRAPS) {
1489   assert(ik != NULL, "invariant");
1490   assert(new_ik != NULL, "invariant");
1491   assert(new_ik->name() != NULL, "invariant");
1492   assert(JdkJfrEvent::is(new_ik) || JdkJfrEvent::is_subklass(new_ik), "invariant");
1493   assert(!HAS_PENDING_EXCEPTION, "invariant");
1494   // assign original InstanceKlass* back onto "its" parser object for proper destruction
1495   parser.set_klass_to_deallocate(ik);
1496   // now rewrite original pointer to newly created InstanceKlass
1497   ik = new_ik;
1498 }
1499 
1500 // During retransform/redefine, copy the Method specific trace flags
1501 // from the previous ik ("the original klass") to the new ik ("the scratch_klass").
1502 // The open code for retransform/redefine does not know about these.
1503 // In doing this migration here, we ensure the new Methods (defined in scratch klass)
1504 // will carry over trace tags from the old Methods being replaced,
1505 // ensuring flag/tag continuity while being transparent to open code.
copy_method_trace_flags(const InstanceKlass * the_original_klass,const InstanceKlass * the_scratch_klass)1506 static void copy_method_trace_flags(const InstanceKlass* the_original_klass, const InstanceKlass* the_scratch_klass) {
1507   assert(the_original_klass != NULL, "invariant");
1508   assert(the_scratch_klass != NULL, "invariant");
1509   assert(the_original_klass->name() == the_scratch_klass->name(), "invariant");
1510   const Array<Method*>* old_methods = the_original_klass->methods();
1511   const Array<Method*>* new_methods = the_scratch_klass->methods();
1512   const bool equal_array_length = old_methods->length() == new_methods->length();
1513   // The Method array has the property of being sorted.
1514   // If they are the same length, there is a one-to-one mapping.
1515   // If they are unequal, there was a method added (currently only
1516   // private static methods allowed to be added), use lookup.
1517   for (int i = 0; i < old_methods->length(); ++i) {
1518     const Method* const old_method = old_methods->at(i);
1519     Method* const new_method = equal_array_length ? new_methods->at(i) :
1520       the_scratch_klass->find_method(old_method->name(), old_method->signature());
1521     assert(new_method != NULL, "invariant");
1522     assert(new_method->name() == old_method->name(), "invariant");
1523     assert(new_method->signature() == old_method->signature(), "invariant");
1524     *new_method->trace_flags_addr() = old_method->trace_flags();
1525     assert(new_method->trace_flags() == old_method->trace_flags(), "invariant");
1526   }
1527 }
1528 
is_retransforming(const InstanceKlass * ik,TRAPS)1529 static bool is_retransforming(const InstanceKlass* ik, TRAPS) {
1530   assert(ik != NULL, "invariant");
1531   assert(JdkJfrEvent::is_a(ik), "invariant");
1532   Symbol* const name = ik->name();
1533   assert(name != NULL, "invariant");
1534   Handle class_loader(THREAD, ik->class_loader());
1535   Handle protection_domain(THREAD, ik->protection_domain());
1536   // nota bene: use lock-free dictionary lookup
1537   const InstanceKlass* prev_ik = (const InstanceKlass*)SystemDictionary::find(name, class_loader, protection_domain, THREAD);
1538   if (prev_ik == NULL) {
1539     return false;
1540   }
1541   // an existing ik implies a retransform/redefine
1542   assert(prev_ik != NULL, "invariant");
1543   assert(JdkJfrEvent::is_a(prev_ik), "invariant");
1544   copy_method_trace_flags(prev_ik, ik);
1545   return true;
1546 }
1547 
1548 // target for JFR_ON_KLASS_CREATION hook
on_klass_creation(InstanceKlass * & ik,ClassFileParser & parser,TRAPS)1549 void JfrEventClassTransformer::on_klass_creation(InstanceKlass*& ik, ClassFileParser& parser, TRAPS) {
1550   assert(ik != NULL, "invariant");
1551   if (JdkJfrEvent::is(ik)) {
1552     ResourceMark rm(THREAD);
1553     HandleMark hm(THREAD);
1554     ClassFileStream* new_stream = create_new_bytes_for_event_klass(ik, parser, THREAD);
1555     if (new_stream == NULL) {
1556       log_error(jfr, system)("JfrClassAdapter: unable to create ClassFileStream");
1557       return;
1558     }
1559     assert(new_stream != NULL, "invariant");
1560     InstanceKlass* new_ik = create_new_instance_klass(ik, new_stream, THREAD);
1561     if (new_ik == NULL) {
1562       log_error(jfr, system)("JfrClassAdapter: unable to create InstanceKlass");
1563       return;
1564     }
1565     assert(new_ik != NULL, "invariant");
1566     // We now need to explicitly tag the replaced klass as the jdk.jfr.Event klass
1567     assert(!JdkJfrEvent::is(new_ik), "invariant");
1568     JdkJfrEvent::tag_as(new_ik);
1569     assert(JdkJfrEvent::is(new_ik), "invariant");
1570     rewrite_klass_pointer(ik, new_ik, parser, THREAD);
1571     return;
1572   }
1573   assert(JdkJfrEvent::is_subklass(ik), "invariant");
1574   if (is_retransforming(ik, THREAD)) {
1575     // not the initial klass load
1576     return;
1577   }
1578   if (ik->is_abstract()) {
1579     // abstract classes are not instrumented
1580     return;
1581   }
1582   ResourceMark rm(THREAD);
1583   HandleMark hm(THREAD);
1584   ClassFileStream* const new_stream = create_new_bytes_for_subklass(ik, parser, THREAD);
1585   if (NULL == new_stream) {
1586     log_error(jfr, system)("JfrClassAdapter: unable to create ClassFileStream");
1587     return;
1588   }
1589   assert(new_stream != NULL, "invariant");
1590   InstanceKlass* new_ik = create_new_instance_klass(ik, new_stream, THREAD);
1591   if (new_ik == NULL) {
1592     log_error(jfr, system)("JfrClassAdapter: unable to create InstanceKlass");
1593     return;
1594   }
1595   assert(new_ik != NULL, "invariant");
1596   // would have been tagged already as a subklass during the normal process of traceid assignment
1597   assert(JdkJfrEvent::is_subklass(new_ik), "invariant");
1598   traceid id = ik->trace_id();
1599   ik->set_trace_id(0);
1600   new_ik->set_trace_id(id);
1601   rewrite_klass_pointer(ik, new_ik, parser, THREAD);
1602 }
1603 
1604 static bool _force_instrumentation = false;
set_force_instrumentation(bool force_instrumentation)1605 void JfrEventClassTransformer::set_force_instrumentation(bool force_instrumentation) {
1606   _force_instrumentation = force_instrumentation;
1607 }
1608 
is_force_instrumentation()1609 bool JfrEventClassTransformer::is_force_instrumentation() {
1610   return _force_instrumentation;
1611 }
1612