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