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