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