This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA] JVMTI Agent Loading


Tom Tromey wrote:
"Kyle" == Kyle Galloway <kgallowa@redhat.com> writes:

Kyle> The reason for this is that if the library is a C library, it will Kyle> have unmangled names, but if the library is a C++ library the names Kyle> will be mangled.

Yeah, but the declaration of Agent_OnLoad and Agent_OnUnload is
wrapped in 'extern "C"'... so I'd assume this case can't happen.
I think your right, I could swear I've seen a mangled AgentOnLoad before, but I can't reproduce it so I whacked the mangled check.
Kyle> Is it better to have sizeof("-agentlib:") - 1 to be more clear about
Kyle> what's happening or sizeof(agentlib) because it avoids the subtraction?

The first one I think. Don't worry about the subtraction, the
compiler will fold this to a constant.
I think I have all the changes made now, but I've attached a revised patch here in case there are any other issues before I check this in.

- Kyle
Index: libjava/gij.cc
===================================================================
--- libjava/gij.cc	(revision 123426)
+++ libjava/gij.cc	(working copy)
@@ -121,11 +121,11 @@
         continue;
       else if (! strcmp (arg, "-jrockit"))
         continue;
-      // Ignore JVM Tool Interface options
+      // JVM Tool Interface options
       else if (! strncmp (arg, "-agentlib:", sizeof ("-agentlib:") - 1))
-        continue;
+        add_option (vm_args, arg, NULL);
       else if (! strncmp (arg, "-agentpath:", sizeof ("-agentpath:") - 1))
-        continue;
+        add_option (vm_args, arg, NULL);
       else if (! strcmp (arg, "-classpath") || ! strcmp (arg, "-cp"))
         {
           if (i >= argc - 1)
Index: libjava/prims.cc
===================================================================
--- libjava/prims.cc	(revision 123426)
+++ libjava/prims.cc	(working copy)
@@ -108,6 +108,16 @@
 static char defaultJdwpOptions[] = "";
 static char *jdwpOptions = defaultJdwpOptions;
 
+// Typedefs for JVMTI agent functions
+typedef jint jvmti_agent_onload_func (JavaVM *vm, char *options,
+                                      void *reserved);
+typedef jint jvmti_agent_onunload_func (JavaVM *vm);
+
+// JVMTI agent functions
+static jvmti_agent_onload_func *jvmti_agentonload = NULL;
+static jvmti_agent_onunload_func *jvmti_agentonunload = NULL;
+static char *jvmti_agent_opts;
+
 // Argument support.
 int
 _Jv_GetNbArgs (void)
@@ -1358,7 +1368,65 @@
   return 0;
 }
 
+// This function loads the agent functions for JVMTI from the library indicated
+// by name.  It returns a negative value on failure, the value of which
+// indicates where ltdl failed, it also prints an error message.
 static jint
+load_jvmti_agent (const char *name)
+{
+#ifdef USE_LTDL
+  if (lt_dlinit ())
+    {
+      fprintf (stderr, 
+              "libgcj: Error in ltdl init loading agent library\nlibgcj: %s\n",
+               (char *) lt_dlerror ());
+      return -1;
+    }
+ 
+  lt_dlhandle lib = lt_dlopenext (name);
+  if (!lib)
+    {
+      fprintf (stderr, 
+               "libgcj: Error opening agent library\nlibgcj: %s\n",
+               (char *) lt_dlerror ());
+      return -2;
+    }
+
+  if (lib)
+    {
+      jvmti_agentonload 
+        = (jvmti_agent_onload_func *) lt_dlsym (lib, "Agent_OnLoad");
+ 
+      if (!jvmti_agentonload)
+        {
+          fprintf (stderr, 
+                   "libgcj: Error finding agent function in %s\nlibgcj: %s\n",
+                   name, (char *) lt_dlerror ());
+          lt_dlclose (lib);
+          lib = NULL;
+          return -4;
+        }
+      else
+        {
+          jvmti_agentonunload
+            = (jvmti_agent_onunload_func *) lt_dlsym (lib, "Agent_OnUnload");
+	   
+          return 0;
+        }
+    }
+  else
+    {
+      fprintf (stderr, "libgcj: %s not found in library path\n", name);
+      return -3;
+    }
+
+#endif /* USE_LTDL */
+
+// If LTDL cannot be used, return an error code indicating this
+return -99;
+}
+
+static jint
 parse_init_args (JvVMInitArgs* vm_args)
 {
   // if _Jv_Compiler_Properties is non-NULL then it needs to be
@@ -1383,6 +1451,7 @@
   for (int i = 0; i < vm_args->nOptions; ++i)
     {
       char* option_string = vm_args->options[i].optionString;
+      
       if (! strcmp (option_string, "vfprintf")
 	  || ! strcmp (option_string, "exit")
 	  || ! strcmp (option_string, "abort"))
@@ -1410,6 +1479,95 @@
 
 	  continue;
 	}
+      else if (! strncmp (option_string, "-agentlib", sizeof ("-agentlib") - 1))
+	{
+          char *strPtr;
+	                                              
+          if (strlen(option_string) > (sizeof ("-agentlib:") - 1))
+            strPtr = &option_string[sizeof ("-agentlib:") - 1];
+          else
+            {
+              fprintf (stderr,
+                "libgcj: Malformed agentlib argument %s: expected lib name\n",
+                option_string);
+              return -1;
+            }
+
+          // This is optional
+          jvmti_agent_opts = strchr (strPtr, '=');
+   
+          if (! strncmp (strPtr, "jdwp", 4))
+            {    	
+              // We want to run JDWP here so set the variables
+              remoteDebug = true;
+              jdwpOptions = ++jvmti_agent_opts;
+            }
+          else
+            {
+              jint nameLength;
+   
+              if (jvmti_agent_opts == NULL)
+                nameLength = strlen (strPtr);
+              else
+                {
+                  nameLength = jvmti_agent_opts - strPtr;
+                  jvmti_agent_opts++;
+                }
+               
+              char lib_name[nameLength + 3 + 1];
+              strcpy (lib_name, "lib");
+              strncat (lib_name, strPtr, nameLength);
+      
+              jint result = load_jvmti_agent (lib_name);
+      
+              if (result < 0)
+	        {
+	          return -1;
+	        }
+            }
+    
+          continue;
+	}
+      else if (! strncmp (option_string, "-agentpath:", 
+                          sizeof ("-agentpath:") - 1))
+	{
+          char *strPtr;
+	                                              
+          if (strlen(option_string) > 10)
+            strPtr = &option_string[10];
+          else
+            {
+              fprintf (stderr,
+                "libgcj: Malformed agentlib argument %s: expected lib path\n",
+                option_string);
+              return -1;
+            }
+		
+          // This is optional
+          jvmti_agent_opts = strchr (strPtr, '=');
+    
+          jint nameLength;
+   
+          if (jvmti_agent_opts == NULL)
+            nameLength = strlen (strPtr);
+          else
+            {
+              nameLength = jvmti_agent_opts - strPtr;
+              jvmti_agent_opts++;
+            }
+    
+          char lib_name[nameLength + 3 + 1];
+          strcpy (lib_name, "lib");
+          strncat (lib_name, strPtr, nameLength);
+          jint result = load_jvmti_agent (strPtr);
+
+          if (result < 0)
+            {
+              return -1;
+            }
+	
+          continue;
+	}
       else if (vm_args->ignoreUnrecognized)
         {
           if (option_string[0] == '_')
@@ -1570,6 +1728,10 @@
 	main_thread = new MainThread (JvNewStringUTF (name),
 				      arg_vec, is_jar);
       _Jv_AttachCurrentThread (main_thread);
+      
+      //start JVMTI if an agent function has been found
+      if (jvmti_agentonload)
+        (*jvmti_agentonload) (_Jv_GetJavaVM (), jvmti_agent_opts, NULL);
 
       // Start JDWP
       if (remoteDebug)
@@ -1609,6 +1770,10 @@
       JNIEnv *jni_env = _Jv_GetCurrentJNIEnv ();
       _Jv_JVMTI_PostEvent (JVMTI_EVENT_VM_DEATH, thread, jni_env);
     }
+    
+   // Run JVMTI AgentOnUnload if it exists and an agent is loaded
+  if (jvmti_agentonunload)
+    (*jvmti_agentonunload) (_Jv_GetJavaVM ());
 
   // If we got here then something went wrong, as MainThread is not
   // supposed to terminate.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]