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