Mercurial > hg > graal-compiler
comparison src/os/solaris/vm/dtraceJSDT_solaris.cpp @ 116:018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
Summary: Initial checkin of JSDT code
Reviewed-by: acorn, sbohne
author | kamg |
---|---|
date | Thu, 17 Apr 2008 22:18:15 -0400 |
parents | |
children | d1605aabd0a1 |
comparison
equal
deleted
inserted
replaced
115:e7a91a357527 | 116:018d5b58dd4f |
---|---|
1 /* | |
2 * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_dtraceJSDT_solaris.cpp.incl" | |
27 | |
28 #ifdef HAVE_DTRACE_H | |
29 | |
30 #include <sys/types.h> | |
31 #include <sys/stat.h> | |
32 #include <fcntl.h> | |
33 #include <unistd.h> | |
34 #include <dtrace.h> | |
35 | |
36 static const char* devname = "/dev/dtrace/helper"; | |
37 static const char* olddevname = "/devices/pseudo/dtrace@0:helper"; | |
38 | |
39 static const char* string_sig = "uintptr_t"; | |
40 static const char* int_sig = "long"; | |
41 static const char* long_sig = "long long"; | |
42 | |
43 static void printDOFHelper(dof_helper_t* helper); | |
44 | |
45 static int dofhelper_open() { | |
46 int fd; | |
47 if ((fd = open64(devname, O_RDWR)) < 0) { | |
48 // Optimize next calls | |
49 devname = olddevname; | |
50 if ((fd = open64(devname, O_RDWR)) < 0) { | |
51 return -1; | |
52 } | |
53 } | |
54 return fd; | |
55 } | |
56 | |
57 static jint dof_register(jstring module, uint8_t* dof, void* modaddr) { | |
58 int probe; | |
59 dof_helper_t dh; | |
60 int fd; | |
61 | |
62 memset(&dh, 0, sizeof(dh)); | |
63 | |
64 char* module_name = java_lang_String::as_utf8_string( | |
65 JNIHandles::resolve_non_null(module)); | |
66 jio_snprintf(dh.dofhp_mod, sizeof(dh.dofhp_mod), "%s", module_name); | |
67 dh.dofhp_dof = (uint64_t)dof; | |
68 dh.dofhp_addr = (uint64_t)modaddr; | |
69 | |
70 fd = dofhelper_open(); | |
71 if (fd < 0) | |
72 return -1; | |
73 probe = ioctl(fd, DTRACEHIOC_ADDDOF, &dh); | |
74 close(fd); | |
75 if (PrintDTraceDOF) { | |
76 printDOFHelper(&dh); | |
77 tty->print_cr("DOF helper id = %d", probe); | |
78 } | |
79 return probe; | |
80 } | |
81 | |
82 int DTraceJSDT::pd_activate( | |
83 void* moduleBaseAddress, jstring module, | |
84 jint providers_count, JVM_DTraceProvider* providers) { | |
85 | |
86 // We need sections: | |
87 // (1) STRTAB | |
88 // ( | |
89 // (2) PROVIDER | |
90 // (3) PROBES | |
91 // (4) PROBOFFS | |
92 // (5) PROBARGS | |
93 // ) * Number of Providers | |
94 | |
95 // Type of sections we create | |
96 enum { | |
97 STRTAB = 0, | |
98 PROVIDERS = 1, | |
99 PROBES = 2, | |
100 PROBE_OFFSETS = 3, | |
101 ARG_OFFSETS = 4, | |
102 NUM_SECTIONS = 5 | |
103 }; | |
104 | |
105 static int alignment_for[NUM_SECTIONS] = { 1, 4, 8, 4, 1 }; | |
106 | |
107 ResourceMark rm; | |
108 | |
109 uint32_t num_sections = 1 + 4 * providers_count; | |
110 uint32_t offset = sizeof(dof_hdr_t) + (num_sections * sizeof(dof_sec_t)); | |
111 uint32_t* secoffs = NEW_RESOURCE_ARRAY(uint32_t, num_sections); | |
112 uint32_t* secsize = NEW_RESOURCE_ARRAY(uint32_t, num_sections); | |
113 | |
114 // Store offsets of all strings here in such order: | |
115 // zero-string (always 0) | |
116 // provider1-name | |
117 // probe1-function | |
118 // probe1-name | |
119 // arg-1 | |
120 // arg-2 | |
121 // ... | |
122 // probe2-function | |
123 // probe2-name | |
124 // arg-1 | |
125 // arg-2 | |
126 // provider2-name | |
127 // ... | |
128 | |
129 uint32_t strcount = 0; | |
130 // Count the number of strings we'll need | |
131 for(int prvc = 0; prvc < providers_count; ++prvc) { | |
132 JVM_DTraceProvider* provider = &providers[prvc]; | |
133 // Provider name | |
134 ++strcount; | |
135 for(int prbc = 0; prbc < provider->probe_count; ++prbc) { | |
136 JVM_DTraceProbe* p = &(provider->probes[prbc]); | |
137 symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); | |
138 // function + name + one per argument | |
139 strcount += 2 + ArgumentCount(sig).size(); | |
140 } | |
141 } | |
142 | |
143 // Create place for string offsets | |
144 uint32_t* stroffs = NEW_RESOURCE_ARRAY(uint32_t, strcount + 1); | |
145 uint32_t string_index = 0; | |
146 uint32_t curstr = 0; | |
147 | |
148 // First we need an empty string: "" | |
149 stroffs[curstr++] = string_index; | |
150 string_index += strlen("") + 1; | |
151 | |
152 for(int prvc = 0; prvc < providers_count; ++prvc) { | |
153 JVM_DTraceProvider* provider = &providers[prvc]; | |
154 char* provider_name = java_lang_String::as_utf8_string( | |
155 JNIHandles::resolve_non_null(provider->name)); | |
156 stroffs[curstr++] = string_index; | |
157 string_index += strlen(provider_name) + 1; | |
158 | |
159 // All probes | |
160 for(int prbc = 0; prbc < provider->probe_count; ++prbc) { | |
161 JVM_DTraceProbe* p = &(provider->probes[prbc]); | |
162 | |
163 char* function = java_lang_String::as_utf8_string( | |
164 JNIHandles::resolve_non_null(p->function)); | |
165 stroffs[curstr++] = string_index; | |
166 string_index += strlen(function) + 1; | |
167 | |
168 char* name = java_lang_String::as_utf8_string( | |
169 JNIHandles::resolve_non_null(p->name)); | |
170 stroffs[curstr++] = string_index; | |
171 string_index += strlen(name) + 1; | |
172 | |
173 symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); | |
174 SignatureStream ss(sig); | |
175 for ( ; !ss.at_return_type(); ss.next()) { | |
176 BasicType bt = ss.type(); | |
177 const char* t = NULL; | |
178 if (bt == T_OBJECT && | |
179 ss.as_symbol_or_null() == vmSymbols::java_lang_String()) { | |
180 t = string_sig; | |
181 } else if (bt == T_LONG) { | |
182 t = long_sig; | |
183 } else { | |
184 t = int_sig; | |
185 } | |
186 stroffs[curstr++] = string_index; | |
187 string_index += strlen(t) + 1; | |
188 } | |
189 } | |
190 } | |
191 secoffs[STRTAB] = offset; | |
192 secsize[STRTAB] = string_index; | |
193 offset += string_index; | |
194 | |
195 // Calculate the size of the rest | |
196 for(int prvc = 0; prvc < providers_count; ++prvc) { | |
197 JVM_DTraceProvider* provider = &providers[prvc]; | |
198 size_t provider_sec = PROVIDERS + prvc * 4; | |
199 size_t probe_sec = PROBES + prvc * 4; | |
200 size_t probeoffs_sec = PROBE_OFFSETS + prvc * 4; | |
201 size_t argoffs_sec = ARG_OFFSETS + prvc * 4; | |
202 | |
203 // Allocate space for the provider data struction | |
204 secoffs[provider_sec] = align_size_up(offset, alignment_for[PROVIDERS]); | |
205 secsize[provider_sec] = sizeof(dof_provider_t); | |
206 offset = secoffs[provider_sec] + secsize[provider_sec]; | |
207 | |
208 // Allocate space for all the probes | |
209 secoffs[probe_sec] = align_size_up(offset, alignment_for[PROBES]); | |
210 secsize[probe_sec] = sizeof(dof_probe_t) * provider->probe_count; | |
211 offset = secoffs[probe_sec] + secsize[probe_sec]; | |
212 | |
213 // Allocate space for the probe offsets | |
214 secoffs[probeoffs_sec] = align_size_up(offset, alignment_for[PROBE_OFFSETS]); | |
215 secsize[probeoffs_sec] = sizeof(uint32_t) * provider->probe_count; | |
216 offset = secoffs[probeoffs_sec] + secsize[probeoffs_sec]; | |
217 | |
218 // We need number of arguments argoffs | |
219 uint32_t argscount = 0; | |
220 for(int prbc = 0; prbc < provider->probe_count; ++prbc) { | |
221 JVM_DTraceProbe* p = &(provider->probes[prbc]); | |
222 symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); | |
223 argscount += ArgumentCount(sig).size(); | |
224 } | |
225 secoffs[argoffs_sec] = align_size_up(offset, alignment_for[ARG_OFFSETS]); | |
226 secsize[argoffs_sec] = sizeof(uint8_t) * argscount; | |
227 offset = secoffs[argoffs_sec] + secsize[argoffs_sec]; | |
228 } | |
229 | |
230 uint32_t size = offset; | |
231 | |
232 uint8_t* dof = NEW_RESOURCE_ARRAY(uint8_t, size); | |
233 if (!dof) { | |
234 return -1; | |
235 } | |
236 memset((void*)dof, 0, size); | |
237 | |
238 // Fill memory with proper values | |
239 dof_hdr_t* hdr = (dof_hdr_t*)dof; | |
240 hdr->dofh_ident[DOF_ID_MAG0] = DOF_MAG_MAG0; | |
241 hdr->dofh_ident[DOF_ID_MAG1] = DOF_MAG_MAG1; | |
242 hdr->dofh_ident[DOF_ID_MAG2] = DOF_MAG_MAG2; | |
243 hdr->dofh_ident[DOF_ID_MAG3] = DOF_MAG_MAG3; | |
244 hdr->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_NATIVE; // No variants | |
245 hdr->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE; // No variants | |
246 hdr->dofh_ident[DOF_ID_VERSION] = DOF_VERSION_1; // No variants | |
247 hdr->dofh_ident[DOF_ID_DIFVERS] = DIF_VERSION_2; // No variants | |
248 // all other fields of ident to zero | |
249 | |
250 hdr->dofh_flags = 0; | |
251 hdr->dofh_hdrsize = sizeof(dof_hdr_t); | |
252 hdr->dofh_secsize = sizeof(dof_sec_t); | |
253 hdr->dofh_secnum = num_sections; | |
254 hdr->dofh_secoff = sizeof(dof_hdr_t); | |
255 hdr->dofh_loadsz = size; | |
256 hdr->dofh_filesz = size; | |
257 | |
258 // First section: STRTAB | |
259 dof_sec_t* sec = (dof_sec_t*)(dof + sizeof(dof_hdr_t)); | |
260 sec->dofs_type = DOF_SECT_STRTAB; | |
261 sec->dofs_align = alignment_for[STRTAB]; | |
262 sec->dofs_flags = DOF_SECF_LOAD; | |
263 sec->dofs_entsize = 0; | |
264 sec->dofs_offset = secoffs[STRTAB]; | |
265 sec->dofs_size = secsize[STRTAB]; | |
266 // Make data for this section | |
267 char* str = (char*)(dof + sec->dofs_offset); | |
268 | |
269 *str = 0; str += 1; // "" | |
270 | |
271 // Run through all strings again | |
272 for(int prvc = 0; prvc < providers_count; ++prvc) { | |
273 JVM_DTraceProvider* provider = &providers[prvc]; | |
274 char* provider_name = java_lang_String::as_utf8_string( | |
275 JNIHandles::resolve_non_null(provider->name)); | |
276 strcpy(str, provider_name); | |
277 str += strlen(provider_name) + 1; | |
278 | |
279 // All probes | |
280 for(int prbc = 0; prbc < provider->probe_count; ++prbc) { | |
281 JVM_DTraceProbe* p = &(provider->probes[prbc]); | |
282 | |
283 char* function = java_lang_String::as_utf8_string( | |
284 JNIHandles::resolve_non_null(p->function)); | |
285 strcpy(str, function); | |
286 str += strlen(str) + 1; | |
287 | |
288 char* name = java_lang_String::as_utf8_string( | |
289 JNIHandles::resolve_non_null(p->name)); | |
290 strcpy(str, name); | |
291 str += strlen(name) + 1; | |
292 | |
293 symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); | |
294 SignatureStream ss(sig); | |
295 for ( ; !ss.at_return_type(); ss.next()) { | |
296 BasicType bt = ss.type(); | |
297 const char* t; | |
298 if (bt == T_OBJECT && | |
299 ss.as_symbol_or_null() == vmSymbols::java_lang_String()) { | |
300 t = string_sig; | |
301 } else if (bt == T_LONG) { | |
302 t = long_sig; | |
303 } else { | |
304 t = int_sig; | |
305 } | |
306 strcpy(str, t); | |
307 str += strlen(t) + 1; | |
308 } | |
309 } | |
310 } | |
311 | |
312 curstr = 1; | |
313 for(int prvc = 0; prvc < providers_count; ++prvc) { | |
314 JVM_DTraceProvider* provider = &providers[prvc]; | |
315 size_t provider_sec = PROVIDERS + prvc * 4; | |
316 size_t probe_sec = PROBES + prvc * 4; | |
317 size_t probeoffs_sec = PROBE_OFFSETS + prvc * 4; | |
318 size_t argoffs_sec = ARG_OFFSETS + prvc * 4; | |
319 | |
320 // PROVIDER /////////////////////////////////////////////////////////////// | |
321 // Section header | |
322 sec = (dof_sec_t*) | |
323 (dof + sizeof(dof_hdr_t) + sizeof(dof_sec_t) * provider_sec); | |
324 sec->dofs_type = DOF_SECT_PROVIDER; | |
325 sec->dofs_align = alignment_for[PROVIDERS]; | |
326 sec->dofs_flags = DOF_SECF_LOAD; | |
327 sec->dofs_entsize = 0; | |
328 sec->dofs_offset = secoffs[provider_sec]; | |
329 sec->dofs_size = secsize[provider_sec]; | |
330 // Make provider decriiption | |
331 dof_provider_t* prv = (dof_provider_t*)(dof + sec->dofs_offset); | |
332 prv->dofpv_strtab = STRTAB; | |
333 prv->dofpv_probes = probe_sec; | |
334 prv->dofpv_prargs = argoffs_sec; | |
335 prv->dofpv_proffs = probeoffs_sec; | |
336 prv->dofpv_name = stroffs[curstr++]; // Index in string table | |
337 prv->dofpv_provattr = DOF_ATTR( | |
338 provider->providerAttributes.nameStability, | |
339 provider->providerAttributes.dataStability, | |
340 provider->providerAttributes.dependencyClass); | |
341 prv->dofpv_modattr = DOF_ATTR( | |
342 provider->moduleAttributes.nameStability, | |
343 provider->moduleAttributes.dataStability, | |
344 provider->moduleAttributes.dependencyClass); | |
345 prv->dofpv_funcattr = DOF_ATTR( | |
346 provider->functionAttributes.nameStability, | |
347 provider->functionAttributes.dataStability, | |
348 provider->functionAttributes.dependencyClass); | |
349 prv->dofpv_nameattr = DOF_ATTR( | |
350 provider->nameAttributes.nameStability, | |
351 provider->nameAttributes.dataStability, | |
352 provider->nameAttributes.dependencyClass); | |
353 prv->dofpv_argsattr = DOF_ATTR( | |
354 provider->argsAttributes.nameStability, | |
355 provider->argsAttributes.dataStability, | |
356 provider->argsAttributes.dependencyClass); | |
357 | |
358 // PROBES ///////////////////////////////////////////////////////////////// | |
359 // Section header | |
360 sec = (dof_sec_t*) | |
361 (dof + sizeof(dof_hdr_t) + sizeof(dof_sec_t) * probe_sec); | |
362 sec->dofs_type = DOF_SECT_PROBES; | |
363 sec->dofs_align = alignment_for[PROBES]; | |
364 sec->dofs_flags = DOF_SECF_LOAD; | |
365 sec->dofs_entsize = sizeof(dof_probe_t); | |
366 sec->dofs_offset = secoffs[probe_sec]; | |
367 sec->dofs_size = secsize[probe_sec]; | |
368 // Make probes descriptions | |
369 uint32_t argsoffs = 0; | |
370 for(int prbc = 0; prbc < provider->probe_count; ++prbc) { | |
371 JVM_DTraceProbe* probe = &(provider->probes[prbc]); | |
372 methodOop m = JNIHandles::resolve_jmethod_id(probe->method); | |
373 int arg_count = ArgumentCount(m->signature()).size(); | |
374 assert(m->code() != NULL, "must have an nmethod"); | |
375 | |
376 dof_probe_t* prb = | |
377 (dof_probe_t*)(dof + sec->dofs_offset + prbc * sizeof(dof_probe_t)); | |
378 | |
379 prb->dofpr_addr = (uint64_t)m->code()->entry_point(); | |
380 prb->dofpr_func = stroffs[curstr++]; // Index in string table | |
381 prb->dofpr_name = stroffs[curstr++]; // Index in string table | |
382 prb->dofpr_nargv = stroffs[curstr ]; // Index in string table | |
383 // We spent siglen strings here | |
384 curstr += arg_count; | |
385 prb->dofpr_xargv = prb->dofpr_nargv; // Same bunch of strings | |
386 prb->dofpr_argidx = argsoffs; | |
387 prb->dofpr_offidx = prbc; | |
388 prb->dofpr_nargc = arg_count; | |
389 prb->dofpr_xargc = arg_count; | |
390 prb->dofpr_noffs = 1; // Number of offsets | |
391 // Next bunch of offsets | |
392 argsoffs += arg_count; | |
393 } | |
394 | |
395 // PROFFS ///////////////////////////////////////////////////////////////// | |
396 // Section header | |
397 sec = (dof_sec_t*) | |
398 (dof + sizeof(dof_hdr_t) + sizeof(dof_sec_t) * probeoffs_sec); | |
399 sec->dofs_type = DOF_SECT_PROFFS; | |
400 sec->dofs_align = alignment_for[PROBE_OFFSETS]; | |
401 sec->dofs_flags = DOF_SECF_LOAD; | |
402 sec->dofs_entsize = sizeof(uint32_t); | |
403 sec->dofs_offset = secoffs[probeoffs_sec]; | |
404 sec->dofs_size = secsize[probeoffs_sec]; | |
405 // Make offsets | |
406 for (int prbc = 0; prbc < provider->probe_count; ++prbc) { | |
407 uint32_t* pof = | |
408 (uint32_t*)(dof + sec->dofs_offset + sizeof(uint32_t) * prbc); | |
409 JVM_DTraceProbe* probe = &(provider->probes[prbc]); | |
410 methodOop m = JNIHandles::resolve_jmethod_id(probe->method); | |
411 *pof = m->code()->trap_offset(); | |
412 } | |
413 | |
414 // PRARGS ///////////////////////////////////////////////////////////////// | |
415 // Section header | |
416 sec = (dof_sec_t*) | |
417 (dof + sizeof(dof_hdr_t) + sizeof(dof_sec_t) * argoffs_sec); | |
418 sec->dofs_type = DOF_SECT_PRARGS; | |
419 sec->dofs_align = alignment_for[ARG_OFFSETS]; | |
420 sec->dofs_flags = DOF_SECF_LOAD; | |
421 sec->dofs_entsize = sizeof(uint8_t); | |
422 sec->dofs_offset = secoffs[argoffs_sec]; | |
423 sec->dofs_size = secsize[argoffs_sec]; | |
424 // Make arguments | |
425 uint8_t* par = (uint8_t*)(dof + sec->dofs_offset); | |
426 for (int prbc = 0; prbc < provider->probe_count; ++prbc) { | |
427 JVM_DTraceProbe* p = &(provider->probes[prbc]); | |
428 symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); | |
429 uint8_t count = (uint8_t)ArgumentCount(sig).size(); | |
430 for (uint8_t i = 0; i < count; ++i) { | |
431 *par++ = i; | |
432 } | |
433 } | |
434 } | |
435 | |
436 // Register module | |
437 return dof_register(module, dof, moduleBaseAddress); | |
438 } | |
439 | |
440 | |
441 void DTraceJSDT::pd_dispose(int handle) { | |
442 int fd; | |
443 if (handle == -1) { | |
444 return; | |
445 } | |
446 fd = dofhelper_open(); | |
447 if (fd < 0) | |
448 return; | |
449 ioctl(fd, DTRACEHIOC_REMOVE, handle); | |
450 close(fd); | |
451 } | |
452 | |
453 jboolean DTraceJSDT::pd_is_supported() { | |
454 int fd = dofhelper_open(); | |
455 if (fd < 0) { | |
456 return false; | |
457 } | |
458 close(fd); | |
459 return true; | |
460 } | |
461 | |
462 static const char* dofSecTypeFor(uint32_t type) { | |
463 switch (type) { | |
464 case 0: return "DOF_SECT_NONE"; | |
465 case 1: return "DOF_SECT_COMMENTS"; | |
466 case 2: return "DOF_SECT_SOURCE"; | |
467 case 3: return "DOF_SECT_ECBDESC"; | |
468 case 4: return "DOF_SECT_PROBEDESC"; | |
469 case 5: return "DOF_SECT_ACTDESC"; | |
470 case 6: return "DOF_SECT_DIFOHDR"; | |
471 case 7: return "DOF_SECT_DIF"; | |
472 case 8: return "DOF_SECT_STRTAB"; | |
473 case 9: return "DOF_SECT_VARTAB"; | |
474 case 10: return "DOF_SECT_RELTAB"; | |
475 case 11: return "DOF_SECT_TYPETAB"; | |
476 case 12: return "DOF_SECT_URELHDR"; | |
477 case 13: return "DOF_SECT_KRELHDR"; | |
478 case 14: return "DOF_SECT_OPTDESC"; | |
479 case 15: return "DOF_SECT_PROVIDER"; | |
480 case 16: return "DOF_SECT_PROBES"; | |
481 case 17: return "DOF_SECT_PRARGS"; | |
482 case 18: return "DOF_SECT_PROFFS"; | |
483 case 19: return "DOF_SECT_INTTAB"; | |
484 case 20: return "DOF_SECT_UTSNAME"; | |
485 case 21: return "DOF_SECT_XLTAB"; | |
486 case 22: return "DOF_SECT_XLMEMBERS"; | |
487 case 23: return "DOF_SECT_XLIMPORT"; | |
488 case 24: return "DOF_SECT_XLEXPORT"; | |
489 case 25: return "DOF_SECT_PREXPORT"; | |
490 case 26: return "DOF_SECT_PRENOFFS"; | |
491 default: return "<unknown>"; | |
492 } | |
493 } | |
494 | |
495 static void printDOFStringTabSec(void* dof, dof_sec_t* sec) { | |
496 size_t tab = sec->dofs_offset; | |
497 size_t limit = sec->dofs_size; | |
498 tty->print_cr("// String Table:"); | |
499 for (size_t idx = 0; idx < limit; /*empty*/) { | |
500 char* str = ((char*)dof) + tab + idx; | |
501 tty->print_cr("// [0x%x + 0x%x] '%s'", tab, idx, str); | |
502 idx += strlen(str) + 1; | |
503 } | |
504 } | |
505 | |
506 static void printDOFProviderSec(void* dof, dof_sec_t* sec) { | |
507 dof_provider_t* prov = (dof_provider_t*)((char*)dof + sec->dofs_offset); | |
508 tty->print_cr("// dof_provider_t {"); | |
509 tty->print_cr("// dofpv_strtab = %d", prov->dofpv_strtab); | |
510 tty->print_cr("// dofpv_probes = %d", prov->dofpv_probes); | |
511 tty->print_cr("// dofpv_prargs = %d", prov->dofpv_prargs); | |
512 tty->print_cr("// dofpv_proffs = %d", prov->dofpv_proffs); | |
513 tty->print_cr("// dofpv_name = 0x%x", prov->dofpv_name); | |
514 tty->print_cr("// dofpv_provattr = 0x%08x", prov->dofpv_provattr); | |
515 tty->print_cr("// dofpv_modattr = 0x%08x", prov->dofpv_modattr); | |
516 tty->print_cr("// dofpv_funcattr = 0x%08x", prov->dofpv_funcattr); | |
517 tty->print_cr("// dofpv_nameattr = 0x%08x", prov->dofpv_nameattr); | |
518 tty->print_cr("// dofpv_argsattr = 0x%08x", prov->dofpv_argsattr); | |
519 tty->print_cr("// }"); | |
520 } | |
521 | |
522 static void printDOFProbesSec(void* dof, dof_sec_t* sec) { | |
523 size_t idx = sec->dofs_offset; | |
524 size_t limit = idx + sec->dofs_size; | |
525 for (size_t idx = sec->dofs_offset; idx < limit; idx += sec->dofs_entsize) { | |
526 dof_probe_t* prb = (dof_probe_t*)((char*)dof + idx); | |
527 tty->print_cr("// dof_probe_t {"); | |
528 tty->print_cr("// dofpr_addr = 0x%016llx", prb->dofpr_addr); | |
529 tty->print_cr("// dofpr_func = 0x%x", prb->dofpr_func); | |
530 tty->print_cr("// dofpr_name = 0x%x", prb->dofpr_name); | |
531 tty->print_cr("// dofpr_nargv = 0x%x", prb->dofpr_nargv); | |
532 tty->print_cr("// dofpr_xargv = 0x%x", prb->dofpr_xargv); | |
533 tty->print_cr("// dofpr_argidx = 0x%x", prb->dofpr_argidx); | |
534 tty->print_cr("// dofpr_offidx = 0x%x", prb->dofpr_offidx); | |
535 tty->print_cr("// dofpr_nargc = %d", prb->dofpr_nargc); | |
536 tty->print_cr("// dofpr_xargc = %d", prb->dofpr_xargc); | |
537 tty->print_cr("// dofpr_noffs = %d", prb->dofpr_noffs); | |
538 tty->print_cr("// }"); | |
539 } | |
540 } | |
541 | |
542 static void printDOFOffsetsSec(void* dof, dof_sec_t* sec) { | |
543 size_t tab = sec->dofs_offset; | |
544 size_t limit = sec->dofs_size; | |
545 tty->print_cr("// Offsets:"); | |
546 for (size_t idx = 0; idx < limit; idx += sec->dofs_entsize) { | |
547 uint32_t* off = (uint32_t*)((char*)dof + tab + idx); | |
548 tty->print_cr("// [0x%x + 0x%x]: %d", tab, idx, *off); | |
549 } | |
550 } | |
551 | |
552 static void printDOFArgsSec(void* dof, dof_sec_t* sec) { | |
553 size_t tab = sec->dofs_offset; | |
554 size_t limit = sec->dofs_size; | |
555 tty->print_cr("// Arguments:"); | |
556 for (size_t idx = 0; idx < limit; idx += sec->dofs_entsize) { | |
557 uint8_t* arg = (uint8_t*)((char*)dof + tab + idx); | |
558 tty->print_cr("// [0x%x + 0x%x]: %d", tab, idx, *arg); | |
559 } | |
560 } | |
561 | |
562 static void printDOFSection(void* dof, dof_sec_t* sec) { | |
563 tty->print_cr("// dof_sec_t {"); | |
564 tty->print_cr("// dofs_type = 0x%x /* %s */", | |
565 sec->dofs_type, dofSecTypeFor(sec->dofs_type)); | |
566 tty->print_cr("// dofs_align = %d", sec->dofs_align); | |
567 tty->print_cr("// dofs_flags = 0x%x", sec->dofs_flags); | |
568 tty->print_cr("// dofs_entsize = %d", sec->dofs_entsize); | |
569 tty->print_cr("// dofs_offset = 0x%llx", sec->dofs_offset); | |
570 tty->print_cr("// dofs_size = %lld", sec->dofs_size); | |
571 tty->print_cr("// }"); | |
572 switch (sec->dofs_type) { | |
573 case DOF_SECT_STRTAB: printDOFStringTabSec(dof, sec); break; | |
574 case DOF_SECT_PROVIDER: printDOFProviderSec(dof, sec); break; | |
575 case DOF_SECT_PROBES: printDOFProbesSec(dof, sec); break; | |
576 case DOF_SECT_PROFFS: printDOFOffsetsSec(dof, sec); break; | |
577 case DOF_SECT_PRARGS: printDOFArgsSec(dof, sec); break; | |
578 default: tty->print_cr("// <section type not recognized>"); | |
579 } | |
580 } | |
581 | |
582 static void printDOFHeader(dof_hdr_t* hdr) { | |
583 tty->print_cr("// dof_hdr_t {"); | |
584 tty->print_cr("// dofh_ident[DOF_ID_MAG0] = 0x%x", | |
585 hdr->dofh_ident[DOF_ID_MAG0]); | |
586 tty->print_cr("// dofh_ident[DOF_ID_MAG1] = 0x%x", | |
587 hdr->dofh_ident[DOF_ID_MAG1]); | |
588 tty->print_cr("// dofh_ident[DOF_ID_MAG2] = 0x%x", | |
589 hdr->dofh_ident[DOF_ID_MAG2]); | |
590 tty->print_cr("// dofh_ident[DOF_ID_MAG3] = 0x%x", | |
591 hdr->dofh_ident[DOF_ID_MAG3]); | |
592 tty->print_cr("// dofh_ident[DOF_ID_MODEL] = 0x%x", | |
593 hdr->dofh_ident[DOF_ID_MODEL]); | |
594 tty->print_cr("// dofh_ident[DOF_ID_ENCODING] = 0x%x", | |
595 hdr->dofh_ident[DOF_ID_ENCODING]); | |
596 tty->print_cr("// dofh_ident[DOF_ID_VERSION] = 0x%x", | |
597 hdr->dofh_ident[DOF_ID_VERSION]); | |
598 tty->print_cr("// dofh_ident[DOF_ID_DIFVERS] = 0x%x", | |
599 hdr->dofh_ident[DOF_ID_DIFVERS]); | |
600 tty->print_cr("// dofh_flags = 0x%x", hdr->dofh_flags); | |
601 tty->print_cr("// dofh_hdrsize = %d", hdr->dofh_hdrsize); | |
602 tty->print_cr("// dofh_secsize = %d", hdr->dofh_secsize); | |
603 tty->print_cr("// dofh_secnum = %d", hdr->dofh_secnum); | |
604 tty->print_cr("// dofh_secoff = %lld", hdr->dofh_secoff); | |
605 tty->print_cr("// dofh_loadsz = %lld", hdr->dofh_loadsz); | |
606 tty->print_cr("// dofh_filesz = %lld", hdr->dofh_filesz); | |
607 tty->print_cr("// }"); | |
608 } | |
609 | |
610 static void printDOF(void* dof) { | |
611 dof_hdr_t* hdr = (dof_hdr_t*)dof; | |
612 printDOFHeader(hdr); | |
613 for (int i = 0; i < hdr->dofh_secnum; ++i) { | |
614 dof_sec_t* sec = | |
615 (dof_sec_t*)((char*)dof + sizeof(dof_hdr_t) + i * sizeof(dof_sec_t)); | |
616 tty->print_cr("// [Section #%d]", i); | |
617 printDOFSection(dof, sec); | |
618 } | |
619 } | |
620 | |
621 /** | |
622 * This prints out hex data in a 'windbg' or 'xxd' form, where each line is: | |
623 * <hex-address>: 8 * <hex-halfword> <ascii translation> | |
624 * example: | |
625 * 0000000: 7f44 4f46 0102 0102 0000 0000 0000 0000 .DOF............ | |
626 * 0000010: 0000 0000 0000 0040 0000 0020 0000 0005 .......@... .... | |
627 * 0000020: 0000 0000 0000 0040 0000 0000 0000 015d .......@.......] | |
628 * ... | |
629 */ | |
630 static void printDOFRawData(void* dof) { | |
631 size_t size = ((dof_hdr_t*)dof)->dofh_loadsz; | |
632 size_t limit = (size + 16) / 16 * 16; | |
633 for (size_t i = 0; i < limit; ++i) { | |
634 if (i % 16 == 0) { | |
635 tty->print("%07x:", i); | |
636 } | |
637 if (i % 2 == 0) { | |
638 tty->print(" "); | |
639 } | |
640 if (i < size) { | |
641 tty->print("%02x", ((unsigned char*)dof)[i]); | |
642 } else { | |
643 tty->print(" "); | |
644 } | |
645 if ((i + 1) % 16 == 0) { | |
646 tty->print(" "); | |
647 for (size_t j = 0; j < 16; ++j) { | |
648 size_t idx = i + j - 15; | |
649 char c = ((char*)dof)[idx]; | |
650 if (idx < size) { | |
651 tty->print("%c", c >= 32 && c <= 126 ? c : '.'); | |
652 } | |
653 } | |
654 tty->print_cr(""); | |
655 } | |
656 } | |
657 tty->print_cr(""); | |
658 } | |
659 | |
660 static void printDOFHelper(dof_helper_t* helper) { | |
661 tty->print_cr("// dof_helper_t {"); | |
662 tty->print_cr("// dofhp_mod = \"%s\"", helper->dofhp_mod); | |
663 tty->print_cr("// dofhp_addr = 0x%016llx", helper->dofhp_addr); | |
664 tty->print_cr("// dofhp_dof = 0x%016llx", helper->dofhp_dof); | |
665 printDOF((void*)helper->dofhp_dof); | |
666 tty->print_cr("// }"); | |
667 printDOFRawData((void*)helper->dofhp_dof); | |
668 } | |
669 | |
670 #else // ndef HAVE_DTRACE_H | |
671 | |
672 // Get here if we're not building on at least Solaris 10 | |
673 int DTraceJSDT::pd_activate( | |
674 void* baseAddress, jstring module, | |
675 jint provider_count, JVM_DTraceProvider* providers) { | |
676 return -1; | |
677 } | |
678 | |
679 void DTraceJSDT::pd_dispose(int handle) { | |
680 } | |
681 | |
682 jboolean DTraceJSDT::pd_is_supported() { | |
683 return false; | |
684 } | |
685 #endif |