1 /*
  2  * Copyright (c) 2003, 2021, 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 "classfile/javaClasses.inline.hpp"
 27 #include "jvmtifiles/jvmtiEnv.hpp"
 28 #include "logging/log.hpp"
 29 #include "logging/logConfiguration.hpp"
 30 #include "memory/resourceArea.hpp"
 31 #include "prims/jvmtiTrace.hpp"
 32 #include "runtime/thread.inline.hpp"
 33 
 34 //
 35 // class JvmtiTrace
 36 //
 37 // Support for JVMTI tracing code
 38 //
 39 // ------------
 40 // Usage:
 41 //    -XX:TraceJVMTI=DESC,DESC,DESC
 42 //
 43 //    DESC is   DOMAIN ACTION KIND
 44 //
 45 //    DOMAIN is function name
 46 //              event name
 47 //              "all" (all functions and events)
 48 //              "func" (all functions except boring)
 49 //              "allfunc" (all functions)
 50 //              "event" (all events)
 51 //              "ec" (event controller)
 52 //
 53 //    ACTION is "+" (add)
 54 //              "-" (remove)
 55 //
 56 //    KIND is
 57 //     for func
 58 //              "i" (input params)
 59 //              "e" (error returns)
 60 //              "o" (output)
 61 //     for event
 62 //              "t" (event triggered aka posted)
 63 //              "s" (event sent)
 64 //
 65 // Example:
 66 //            -XX:TraceJVMTI=ec+,GetCallerFrame+ie,Breakpoint+s
 67 
 68 #ifdef JVMTI_TRACE
 69 
 70 bool JvmtiTrace::_initialized = false;
 71 bool JvmtiTrace::_on = false;
 72 bool JvmtiTrace::_trace_event_controller = false;
 73 
 74 void JvmtiTrace::initialize() {
 75   if (_initialized) {
 76     return;
 77   }
 78   SafeResourceMark rm;
 79 
 80   const char *very_end;
 81   const char *curr;
 82   if (TraceJVMTI != NULL) {
 83     curr = TraceJVMTI;
 84   } else {
 85     curr = "";  // hack in fixed tracing here
 86   }
 87 
 88   // Enable UL for JVMTI tracing
 89   if (strlen(curr) > 0) {
 90     if (!log_is_enabled(Trace, jvmti)) {
 91       log_warning(arguments)("-XX:+TraceJVMTI specified, "
 92          "but no log output configured for the 'jvmti' tag on Trace level. "
 93          "Defaulting to -Xlog:jvmti=trace");
 94       LogConfiguration::configure_stdout(LogLevel::Trace, true, LOG_TAGS(jvmti));
 95     }
 96   }
 97 
 98   very_end = curr + strlen(curr);
 99   while (curr < very_end) {
100     const char *curr_end = strchr(curr, ',');
101     if (curr_end == NULL) {
102       curr_end = very_end;
103     }
104     const char *op_pos = strchr(curr, '+');
105     const char *minus_pos = strchr(curr, '-');
106     if (minus_pos != NULL && (minus_pos < op_pos || op_pos == NULL)) {
107       op_pos = minus_pos;
108     }
109     char op;
110     const char *flags = op_pos + 1;
111     const char *flags_end = curr_end;
112     if (op_pos == NULL || op_pos > curr_end) {
113       flags = "ies";
114       flags_end = flags + strlen(flags);
115       op_pos = curr_end;
116       op = '+';
117     } else {
118       op = *op_pos;
119     }
120     jbyte bits = 0;
121     for (; flags < flags_end; ++flags) {
122       switch (*flags) {
123       case 'i':
124         bits |= SHOW_IN;
125         break;
126       case 'I':
127         bits |= SHOW_IN_DETAIL;
128         break;
129       case 'e':
130         bits |= SHOW_ERROR;
131         break;
132       case 'o':
133         bits |= SHOW_OUT;
134         break;
135       case 'O':
136         bits |= SHOW_OUT_DETAIL;
137         break;
138       case 't':
139         bits |= SHOW_EVENT_TRIGGER;
140         break;
141       case 's':
142         bits |= SHOW_EVENT_SENT;
143         break;
144       default:
145         log_warning(jvmti)("Invalid trace flag '%c'", *flags);
146         break;
147       }
148     }
149     const int FUNC = 1;
150     const int EXCLUDE  = 2;
151     const int ALL_FUNC = 4;
152     const int EVENT = 8;
153     const int ALL_EVENT = 16;
154     int domain = 0;
155     size_t len = op_pos - curr;
156     if (op_pos == curr) {
157       domain = ALL_FUNC | FUNC | ALL_EVENT | EVENT | EXCLUDE;
158     } else if (len==3 && strncmp(curr, "all", 3)==0) {
159       domain = ALL_FUNC | FUNC | ALL_EVENT | EVENT;
160     } else if (len==7 && strncmp(curr, "allfunc", 7)==0) {
161       domain = ALL_FUNC | FUNC;
162     } else if (len==4 && strncmp(curr, "func", 4)==0) {
163       domain = ALL_FUNC | FUNC | EXCLUDE;
164     } else if (len==8 && strncmp(curr, "allevent", 8)==0) {
165       domain = ALL_EVENT | EVENT;
166     } else if (len==5 && strncmp(curr, "event", 5)==0) {
167       domain = ALL_EVENT | EVENT;
168     } else if (len==2 && strncmp(curr, "ec", 2)==0) {
169       _trace_event_controller = true;
170       log_trace(jvmti)("Tracing the event controller");
171     } else {
172       domain = FUNC | EVENT;  // go searching
173     }
174 
175     int exclude_index = 0;
176     if (domain & FUNC) {
177       if (domain & ALL_FUNC) {
178         if (domain & EXCLUDE) {
179           log_trace(jvmti)("Tracing all significant functions");
180         } else {
181           log_trace(jvmti)("Tracing all functions");
182         }
183       }
184       for (int i = 0; i <= _max_function_index; ++i) {
185         if (domain & EXCLUDE && i == _exclude_functions[exclude_index]) {
186           ++exclude_index;
187         } else {
188           bool do_op = false;
189           if (domain & ALL_FUNC) {
190             do_op = true;
191           } else {
192             const char *fname = function_name(i);
193             if (fname != NULL) {
194               size_t fnlen = strlen(fname);
195               if (len==fnlen && strncmp(curr, fname, fnlen)==0) {
196                 log_trace(jvmti)("Tracing the function: %s", fname);
197                 do_op = true;
198               }
199             }
200           }
201           if (do_op) {
202             if (op == '+') {
203               _trace_flags[i] |= bits;
204             } else {
205               _trace_flags[i] &= ~bits;
206             }
207             _on = true;
208           }
209         }
210       }
211     }
212     if (domain & EVENT) {
213       if (domain & ALL_EVENT) {
214         log_trace(jvmti)("Tracing all events");
215       }
216       for (int i = 0; i <= _max_event_index; ++i) {
217         bool do_op = false;
218         if (domain & ALL_EVENT) {
219           do_op = true;
220         } else {
221           const char *ename = event_name(i);
222           if (ename != NULL) {
223             size_t evtlen = strlen(ename);
224             if (len==evtlen && strncmp(curr, ename, evtlen)==0) {
225               log_trace(jvmti)("Tracing the event: %s", ename);
226               do_op = true;
227             }
228           }
229         }
230         if (do_op) {
231           if (op == '+') {
232             _event_trace_flags[i] |= bits;
233           } else {
234             _event_trace_flags[i] &= ~bits;
235           }
236           _on = true;
237         }
238       }
239     }
240     if (!_on && (domain & (FUNC|EVENT))) {
241       log_warning(jvmti)("Trace domain not found");
242     }
243     curr = curr_end + 1;
244   }
245   _initialized = true;
246 }
247 
248 
249 void JvmtiTrace::shutdown() {
250   int i;
251   _on = false;
252   _trace_event_controller = false;
253   for (i = 0; i <= _max_function_index; ++i) {
254     _trace_flags[i] = 0;
255   }
256   for (i = 0; i <= _max_event_index; ++i) {
257     _event_trace_flags[i] = 0;
258   }
259 }
260 
261 
262 const char* JvmtiTrace::enum_name(const char** names, const jint* values, jint value) {
263   for (int index = 0; names[index] != 0; ++index) {
264     if (values[index] == value) {
265       return names[index];
266     }
267   }
268   return "*INVALID-ENUM-VALUE*";
269 }
270 
271 
272 // return a valid string no matter what state the thread is in
273 const char *JvmtiTrace::safe_get_thread_name(Thread *thread) {
274   if (thread == NULL) {
275     return "NULL";
276   }
277   if (!thread->is_Java_thread()) {
278     return thread->name();
279   }
280   oop threadObj = JavaThread::cast(thread)->threadObj();
281   if (threadObj == NULL) {
282     return "NULL";
283   }
284   oop name = java_lang_Thread::name(threadObj);
285   if (name == NULL) {
286     return "<NOT FILLED IN>";
287   }
288   return java_lang_String::as_utf8_string(name);
289 }
290 
291 
292 // return the name of the current thread
293 const char *JvmtiTrace::safe_get_current_thread_name() {
294   if (JvmtiEnv::is_vm_live()) {
295     return JvmtiTrace::safe_get_thread_name(Thread::current_or_null());
296   } else {
297     return "VM not live";
298   }
299 }
300 
301 // return a valid string no matter what the state of k_mirror
302 const char * JvmtiTrace::get_class_name(oop k_mirror) {
303   if (java_lang_Class::is_primitive(k_mirror)) {
304     return "primitive";
305   }
306   Klass* k_oop = java_lang_Class::as_Klass(k_mirror);
307   if (k_oop == NULL) {
308     return "INVALID";
309   }
310   return k_oop->external_name();
311 }
312 
313 #endif /*JVMTI_TRACE */