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