+
+ // When true, print debugging information about class loading.
+ bool verbose_class_flag;
+
+ // When true, enable the bytecode verifier and BC-ABI type verification.
+ bool verifyClasses = true;
+
+ // Thread stack size specified by the -Xss runtime argument.
+ size_t stack_size = 0;
+
+ // Start time of the VM
+ jlong startTime = 0;
+
+ // Arguments passed to the VM
+ JArray<jstring>* vmArgs;
+
+ // Currently loaded classes
+ jint loadedClasses = 0;
+
+ // Unloaded classes
+ jlong unloadedClasses = 0;
+}
+
+// We accept all non-standard options accepted by Sun's java command,
+// for compatibility with existing application launch scripts.
+static jint
+parse_x_arg (char* option_string)
+{
+ if (strlen (option_string) <= 0)
+ return -1;
+
+ if (! strcmp (option_string, "int"))
+ {
+ // FIXME: this should cause the vm to never load shared objects
+ }
+ else if (! strcmp (option_string, "mixed"))
+ {
+ // FIXME: allow interpreted and native code
+ }
+ else if (! strcmp (option_string, "batch"))
+ {
+ // FIXME: disable background JIT'ing
+ }
+ else if (! strcmp (option_string, "debug"))
+ {
+ remoteDebug = true;
+ }
+#ifdef INTERPRETER
+ else if (! strncmp (option_string, "runjdwp:", 8))
+ {
+ if (strlen (option_string) > 8)
+ jdwpOptions = &option_string[8];
+ else
+ {
+ fprintf (stderr,
+ "libgcj: argument required for JDWP options");
+ return -1;
+ }
+ }
+#endif // INTERPRETER
+ else if (! strncmp (option_string, "bootclasspath:", 14))
+ {
+ // FIXME: add a parse_bootclasspath_arg function
+ }
+ else if (! strncmp (option_string, "bootclasspath/a:", 16))
+ {
+ }
+ else if (! strncmp (option_string, "bootclasspath/p:", 16))
+ {
+ }
+ else if (! strcmp (option_string, "check:jni"))
+ {
+ // FIXME: enable strict JNI checking
+ }
+ else if (! strcmp (option_string, "future"))
+ {
+ // FIXME: enable strict class file format checks
+ }
+ else if (! strcmp (option_string, "noclassgc"))
+ {
+ // FIXME: disable garbage collection for classes
+ }
+ else if (! strcmp (option_string, "incgc"))
+ {
+ // FIXME: incremental garbage collection
+ }
+ else if (! strncmp (option_string, "loggc:", 6))
+ {
+ if (option_string[6] == '\0')
+ {
+ fprintf (stderr,
+ "libgcj: filename argument expected for loggc option\n");
+ return -1;
+ }
+ // FIXME: set gc logging filename
+ }
+ else if (! strncmp (option_string, "ms", 2))
+ {
+ // FIXME: ignore this option until PR 20699 is fixed.
+ // _Jv_SetInitialHeapSize (option_string + 2);
+ }
+ else if (! strncmp (option_string, "mx", 2))
+ _Jv_SetMaximumHeapSize (option_string + 2);
+ else if (! strcmp (option_string, "prof"))
+ {
+ // FIXME: enable profiling of program running in vm
+ }
+ else if (! strncmp (option_string, "runhprof:", 9))
+ {
+ // FIXME: enable specific type of vm profiling. add a
+ // parse_runhprof_arg function
+ }
+ else if (! strcmp (option_string, "rs"))
+ {
+ // FIXME: reduced system signal usage. disable thread dumps,
+ // only terminate in response to user-initiated calls,
+ // e.g. System.exit()
+ }
+ else if (! strncmp (option_string, "ss", 2))
+ {
+ _Jv_SetStackSize (option_string + 2);
+ }
+ else if (! strcmp (option_string, "X:+UseAltSigs"))
+ {
+ // FIXME: use signals other than SIGUSR1 and SIGUSR2
+ }
+ else if (! strcmp (option_string, "share:off"))
+ {
+ // FIXME: don't share class data
+ }
+ else if (! strcmp (option_string, "share:auto"))
+ {
+ // FIXME: share class data where possible
+ }
+ else if (! strcmp (option_string, "share:on"))
+ {
+ // FIXME: fail if impossible to share class data
+ }
+ else
+ {
+ // Unrecognized.
+ return -1;
+ }
+ return 0;
+}
+
+static jint
+parse_verbose_args (char* option_string,
+ bool ignore_unrecognized)
+{
+ size_t len = sizeof ("-verbose") - 1;
+
+ if (strlen (option_string) < len)
+ return -1;
+
+ if (option_string[len] == ':'
+ && option_string[len + 1] != '\0')
+ {
+ char* verbose_args = option_string + len + 1;
+
+ do
+ {
+ if (! strncmp (verbose_args,
+ "gc", sizeof ("gc") - 1))
+ {
+ if (verbose_args[sizeof ("gc") - 1] == '\0'
+ || verbose_args[sizeof ("gc") - 1] == ',')
+ {
+ // FIXME: we should add functions to boehm-gc that
+ // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and
+ // GC_print_back_height.
+ verbose_args += sizeof ("gc") - 1;
+ }
+ else
+ {
+ verbose_arg_err:
+ fprintf (stderr, "libgcj: unknown verbose option: %s\n",
+ option_string);
+ return -1;
+ }
+ }
+ else if (! strncmp (verbose_args,
+ "class",
+ sizeof ("class") - 1))
+ {
+ if (verbose_args[sizeof ("class") - 1] == '\0'
+ || verbose_args[sizeof ("class") - 1] == ',')
+ {
+ gcj::verbose_class_flag = true;
+ verbose_args += sizeof ("class") - 1;
+ }
+ else
+ goto verbose_arg_err;
+ }
+ else if (! strncmp (verbose_args, "jni",
+ sizeof ("jni") - 1))
+ {
+ if (verbose_args[sizeof ("jni") - 1] == '\0'
+ || verbose_args[sizeof ("jni") - 1] == ',')
+ {
+ // FIXME: enable JNI messages.
+ verbose_args += sizeof ("jni") - 1;
+ }
+ else
+ goto verbose_arg_err;
+ }
+ else if (ignore_unrecognized
+ && verbose_args[0] == 'X')
+ {
+ // ignore unrecognized non-standard verbose option
+ while (verbose_args[0] != '\0'
+ && verbose_args[0] != ',')
+ verbose_args++;
+ }
+ else if (verbose_args[0] == ',')
+ {
+ verbose_args++;
+ }
+ else
+ goto verbose_arg_err;
+
+ if (verbose_args[0] == ',')
+ verbose_args++;
+ }
+ while (verbose_args[0] != '\0');
+ }
+ else if (option_string[len] == 'g'
+ && option_string[len + 1] == 'c'
+ && option_string[len + 2] == '\0')
+ {
+ // FIXME: we should add functions to boehm-gc that
+ // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and
+ // GC_print_back_height.
+ return 0;
+ }
+ else if (option_string[len] == '\0')
+ {
+ gcj::verbose_class_flag = true;
+ return 0;
+ }
+ else
+ {
+ // unrecognized option beginning with -verbose
+ return -1;
+ }
+ return 0;
+}
+
+#ifdef INTERPRETER
+// 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 while loading agent library.\n");
+ return -1;
+ }
+
+ lt_dlhandle lib = lt_dlopenext (name);
+ if (!lib)
+ {
+ fprintf (stderr,
+ "libgcj: Error opening agent library.\n");
+ 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 library %s.\n",
+ name);
+ 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: Library %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;
+}
+#endif // INTERPRETER
+
+static jint
+parse_init_args (JvVMInitArgs* vm_args)
+{
+ // if _Jv_Compiler_Properties is non-NULL then it needs to be
+ // re-allocated dynamically.
+ if (_Jv_Compiler_Properties)
+ {
+ const char** props = _Jv_Compiler_Properties;
+ _Jv_Compiler_Properties = NULL;
+
+ for (int i = 0; props[i]; i++)
+ {
+ _Jv_Compiler_Properties = (const char**) _Jv_Realloc
+ (_Jv_Compiler_Properties,
+ (_Jv_Properties_Count + 1) * sizeof (const char*));
+ _Jv_Compiler_Properties[_Jv_Properties_Count++] = props[i];
+ }
+ }
+
+ if (vm_args == NULL)
+ return 0;
+
+ 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"))
+ {
+ // FIXME: we are required to recognize these, but for
+ // now we don't handle them in any way.
+ continue;
+ }
+ else if (! strncmp (option_string,
+ "-verbose", sizeof ("-verbose") - 1))
+ {
+ jint result = parse_verbose_args (option_string,
+ vm_args->ignoreUnrecognized);
+ if (result < 0)
+ return result;
+ }
+ else if (! strncmp (option_string, "-D", 2))
+ {
+ _Jv_Compiler_Properties = (const char**) _Jv_Realloc
+ (_Jv_Compiler_Properties,
+ (_Jv_Properties_Count + 1) * sizeof (char*));
+
+ _Jv_Compiler_Properties[_Jv_Properties_Count++] =
+ strdup (option_string + 2);
+
+ continue;
+ }
+#ifdef INTERPRETER
+ 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;
+ }
+
+ // These are optional arguments to pass to the agent library.
+ jvmti_agent_opts = strchr (strPtr, '=');
+
+ if (! strncmp (strPtr, "jdwp", 4))
+ {
+ // We want to run JDWP here so set the correct 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;
+ }
+
+ // Mark JVMTI active
+ JVMTI::enabled = true;
+ }
+
+ 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;
+ }
+
+ // These are optional arguments to pass to the agent library.
+ 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;
+ }
+
+ // Mark JVMTI active
+ JVMTI::enabled = true;
+ continue;
+ }
+#endif // INTERPRETER
+ else
+ {
+ int r = -1;
+ if (option_string[0] == '_')
+ r = parse_x_arg (option_string + 1);
+ else if (! strncmp (option_string, "-X", 2))
+ r = parse_x_arg (option_string + 2);
+
+ if (r == -1 && ! vm_args->ignoreUnrecognized)
+ {
+ fprintf (stderr, "libgcj: unknown option: %s\n", option_string);
+ return -1;
+ }
+ }
+ }
+ return 0;