Commit 13a8d9ff authored by Lubomir Bulej's avatar Lubomir Bulej
Browse files

Extract configuration from dislagent.c

parent 84cf2d0b
......@@ -131,7 +131,7 @@ AGENT_GENSRCS := bytecode.c codeflags.h
AGENT_SOURCES := \
bytecode.c common.c jvmtiutil.c connection.c \
connpool.c msgchannel.c network.c classparser.c \
dislagent.c sessions.c strutil.c
dislagent.c sessions.c strutil.c config.c
AGENT_OBJECTS = $(addprefix $(BUILD_DIR)/,$(AGENT_SOURCES:%.c=%.o))
AGENT_SRCDEPS = $(addprefix $(BUILD_DIR)/,$(AGENT_SOURCES:%.c=%.d))
......
#include "config.h"
#include <string.h>
#include <jvmti.h>
#include "debug.h"
#include "strutil.h"
#include "jvmtiutil.h"
// ****************************************************************************
// AGENT CONFIG
// ****************************************************************************
#define DISL_SERVER_HOST "disl.server.host"
#define DISL_SERVER_HOST_DEFAULT "localhost"
#define DISL_SERVER_PORT "disl.server.port"
#define DISL_SERVER_PORT_DEFAULT "11217"
// Required argument (no default value).
#define DISL_INSTRUMENTATION "disl.instrumentation"
#define DISL_INSTRUMENTATION_SEPARATOR ","
#define DISL_BYPASS "disl.bypass"
#define DISL_BYPASS_DEFAULT "dynamic"
#define DISL_SPLIT_METHODS "disl.splitmethods"
#define DISL_SPLIT_METHODS_DEFAULT true
#define DISL_CATCH_EXCEPTIONS "disl.excepthandler"
#define DISL_CATCH_EXCEPTIONS_DEFAULT false
#define DISL_FORCE_SUPERCLASS "disl.forcesuperclass"
#define DISL_FORCE_SUPERCLASS_DEFAULT false
#define DISL_FORCE_INTERFACES "disl.forceinterfaces"
#define DISL_FORCE_INTERFACES_DEFAULT false
#define DISL_DEBUG "debug"
#define DISL_DEBUG_DEFAULT false
//
void
config_parse_system_properties (
struct config * restrict config, jvmtiEnv * jvmti
) {
//
// Get bypass mode configuration
//
char * bypass = jvmti_get_system_property_string (
jvmti, DISL_BYPASS, DISL_BYPASS_DEFAULT
);
static const char * values [] = { "disabled", "bootstrap", "dynamic" };
int bypass_index = strarray_index (values, sizeof_array (values), bypass);
check_error (bypass_index < 0, "invalid bypass mode: %s", bypass);
config->bypass_mode = bypass_index;
free (bypass);
//
// Get the names of instrumentation JAR files from a list of JAR files
// separated by commas (colons are a problem on Windows, semicolons are a
// problem in Unix/MacOS shells, comma should work just fine).
//
char * jar_file_list = jvmti_get_system_property_string (
jvmti, DISL_INSTRUMENTATION, NULL
);
check_error (jar_file_list == NULL, "disl.instrumentation property must be set");
config->jar_paths = strsplit (
jar_file_list, DISL_INSTRUMENTATION_SEPARATOR, &config->jar_count
);
//
// Get boolean values from system properties
//
config->split_methods = jvmti_get_system_property_bool (
jvmti, DISL_SPLIT_METHODS, DISL_SPLIT_METHODS_DEFAULT
);
config->catch_exceptions = jvmti_get_system_property_bool (
jvmti, DISL_CATCH_EXCEPTIONS, DISL_CATCH_EXCEPTIONS_DEFAULT
);
config->force_superclass = jvmti_get_system_property_bool (
jvmti, DISL_FORCE_SUPERCLASS, DISL_FORCE_SUPERCLASS_DEFAULT
);
config->force_interfaces = jvmti_get_system_property_bool (
jvmti, DISL_FORCE_INTERFACES, DISL_FORCE_INTERFACES_DEFAULT
);
config->debug = jvmti_get_system_property_bool (
jvmti, DISL_DEBUG, DISL_DEBUG_DEFAULT
);
//
// Configuration summary. Current thread does not exist yet.
//
rdexec {
rdaprefix ("bypass mode: %s\n", values [bypass_index]);
rdaprefix ("split methods: %d\n", config->split_methods);
rdaprefix ("catch exceptions: %d\n", config->catch_exceptions);
rdaprefix ("force superclass: %d\n", config->force_superclass);
rdaprefix ("force interfaces: %d\n", config->force_interfaces);
rdaprefix ("runtime debug: %d\n", config->debug);
rdaprefix ("instrumentation jars: %zu\n", config->jar_count);
for (size_t i = 0; i < config->jar_count; i++) {
rdaprefix ("\t%s\n", config->jar_paths [i]);
}
}
}
void
config_parse_agent_options (
struct config * restrict config, const char * options
) {
//
// Assign default host name and port and bail out
// if there are no agent options.
//
if (options == NULL) {
config->server_host = strdup (DISL_SERVER_HOST_DEFAULT);
config->server_port = strdup (DISL_SERVER_PORT_DEFAULT);
return;
}
//
// Parse the host name and port of the remote server.
// Look for port specification first, then take the prefix
// before ':' as the host name.
//
char * host_start = strdup (options);
char * port_start = strchr (host_start, ':');
if (port_start != NULL) {
//
// Split the option string at the port delimiter (':')
// using an end-of-string character ('\0') and copy
// the port.
//
port_start [0] = '\0';
port_start++;
config->server_port = strdup (port_start);
}
config->server_host = strdup (host_start);
}
......@@ -6,11 +6,16 @@
#ifndef _CONFIG_H
#define _CONFIG_H
#include "common.h"
#define _POSIX_C_SOURCE 200809L
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <jvmti.h>
/**
* The instrumentation bypass mode.
* NOTE: The ordering of the modes is important!
......@@ -67,4 +72,15 @@ struct config {
bool debug;
};
//
void config_parse_agent_options (
struct config * restrict config, const char * options
);
void config_parse_system_properties (
struct config * restrict config, jvmtiEnv * jvmti
);
#endif // _CONFIG_H
......@@ -31,38 +31,7 @@
#error AGENT_NAME macro has to be defined
#endif
// ****************************************************************************
// AGENT CONFIG
// ****************************************************************************
#define DISL_SERVER_HOST "disl.server.host"
#define DISL_SERVER_HOST_DEFAULT "localhost"
// Required argument, no default value.
#define DISL_INSTRUMENTATION "disl.instrumentation"
#define LIST_SEPARATOR ":"
#define DISL_SERVER_PORT "disl.server.port"
#define DISL_SERVER_PORT_DEFAULT "11217"
#define DISL_BYPASS "disl.bypass"
#define DISL_BYPASS_DEFAULT "dynamic"
#define DISL_SPLIT_METHODS "disl.splitmethods"
#define DISL_SPLIT_METHODS_DEFAULT true
#define DISL_CATCH_EXCEPTIONS "disl.excepthandler"
#define DISL_CATCH_EXCEPTIONS_DEFAULT false
#define DISL_FORCE_SUPERCLASS "disl.forcesuperclass"
#define DISL_FORCE_SUPERCLASS_DEFAULT false
#define DISL_FORCE_INTERFACES "disl.forceinterfaces"
#define DISL_FORCE_INTERFACES_DEFAULT false
#define DISL_DEBUG "debug"
#define DISL_DEBUG_DEFAULT false
//
/**
* Flags representing code options, derived from the values generated from Java.
......@@ -582,122 +551,6 @@ jvmti_callback_vm_death (jvmtiEnv * jvmti, JNIEnv * jni) {
// AGENT ENTRY POINT: ON LOAD
// ****************************************************************************
/**
* Parse the instrumentation jar list in format "jar:jar2:...:jarN" to agent_config struct.
*
* @param list The list of jar files separated by :
* @param config
*/
static void
__parse_instrumentations (char * list, struct config * config) {
size_t jar_count;
const char ** jar_paths = strsplit (list, LIST_SEPARATOR, &jar_count);
config->jar_count = jar_count;
config->jar_paths = jar_paths;
}
static void
__configure_from_properties (jvmtiEnv * jvmti, struct config * config) {
//
// Get bypass mode configuration
//
char * bypass = jvmti_get_system_property_string (
jvmti, DISL_BYPASS, DISL_BYPASS_DEFAULT
);
static const char * values [] = { "disabled", "bootstrap", "dynamic" };
int bypass_index = strarray_index (values, sizeof_array (values), bypass);
check_error (bypass_index < 0, "invalid bypass mode, check " DISL_BYPASS);
config->bypass_mode = bypass_index;
free (bypass);
//
// Get instrumentation list
//
char * instrumentation = jvmti_get_system_property_string (
jvmti, DISL_INSTRUMENTATION, NULL
);
assert (instrumentation != NULL);
__parse_instrumentations (instrumentation, config);
//
// Get boolean values from system properties
//
config->split_methods = jvmti_get_system_property_bool (
jvmti, DISL_SPLIT_METHODS, DISL_SPLIT_METHODS_DEFAULT
);
config->catch_exceptions = jvmti_get_system_property_bool (
jvmti, DISL_CATCH_EXCEPTIONS, DISL_CATCH_EXCEPTIONS_DEFAULT
);
config->force_superclass = jvmti_get_system_property_bool (
jvmti, DISL_FORCE_SUPERCLASS, DISL_FORCE_SUPERCLASS_DEFAULT
);
config->force_interfaces = jvmti_get_system_property_bool (
jvmti, DISL_FORCE_INTERFACES, DISL_FORCE_INTERFACES_DEFAULT
);
config->debug = jvmti_get_system_property_bool (
jvmti, DISL_DEBUG, DISL_DEBUG_DEFAULT
);
//
// Configuration summary. Current thread does not exist yet.
//
rdexec {
rdaprefix ("bypass mode: %s\n", values [bypass_index]);
rdaprefix ("split methods: %d\n", config->split_methods);
rdaprefix ("catch exceptions: %d\n", config->catch_exceptions);
rdaprefix ("force superclass: %d\n", config->force_superclass);
rdaprefix ("force interfaces: %d\n", config->force_interfaces);
rdaprefix ("runtime debug: %d\n", config->debug);
rdaprefix ("instrumentation jars: %zu\n", config->jar_count);
for (size_t i = 0; i < config->jar_count; i++) {
rdaprefix ("\t%s\n", config->jar_paths[i]);
}
}
}
static void
__configure_from_options (const char * options, struct config * config) {
//
// Assign default host name and port and bail out
// if there are no agent options.
//
if (options == NULL) {
config->server_host = strdup (DISL_SERVER_HOST_DEFAULT);
config->server_port = strdup (DISL_SERVER_PORT_DEFAULT);
return;
}
//
// Parse the host name and port of the remote server.
// Look for port specification first, then take the prefix
// before ':' as the host name.
//
char * host_start = strdup (options);
char * port_start = strchr (host_start, ':');
if (port_start != NULL) {
//
// Split the option string at the port delimiter (':')
// using an end-of-string character ('\0') and copy
// the port.
//
port_start [0] = '\0';
port_start++;
config->server_port = strdup (port_start);
}
config->server_host = strdup (host_start);
}
static jvmtiEnv *
__get_jvmti (JavaVM * jvm) {
jvmtiEnv * jvmti = NULL;
......@@ -787,10 +640,11 @@ Agent_OnLoad (JavaVM * jvm, char * options, void * UNUSED (reserved)) {
__jvmti_enable_events (jvmti, events, sizeof_array (events));
// Configure agent and init globals.
__configure_from_options (options, &agent_config);
__configure_from_properties (jvmti, &agent_config);
//
// Configure and initialize the agent.
//
config_parse_agent_options (&agent_config, options);
config_parse_system_properties (&agent_config, jvmti);
jvm_is_started = false;
jvm_is_initialized = false;
......
......@@ -10,10 +10,10 @@ The agent accepts several options, that can alter his behaviour:
### DiSL module options
Those options are used to setup the behaviour of remote instrumentation client.
Note that all of this settings takes an effect, only when `disl.allow` option
Note that all of this settings takes an effect, only when `disl.enable` option
is turned on.
* `disl.allow=(true|false)` - allow the agent to act as the remote instrumentation agent,
* `disl.enable=(true|false)` - allow the agent to act as the remote instrumentation agent,
when this option is passed, the option `disl.instrumentation` is also
required. Default value is false.
......@@ -41,11 +41,13 @@ is turned on.
Those options are used to setup the behaviour of remote analysis agent.
* `svm-agent.shadow.host`
* `shvm.enable=(true|false)`
* `svm-agent.shadow.port`
* `shvm.server.host`
* `svm-agent.debug`
* `shvm.server.port`
* `shvm.debug`
## How is this done?
......
......@@ -84,7 +84,7 @@
#define ERROR_STD 10002
#define ERROR_JVMTI 10003
#define AGENT_NAME "svm-agent"
#define AGENT_NAME "shvm-agent"
//
......
......@@ -9,42 +9,82 @@
#include "strutil.h"
// ****************************************************************************
// SHVM AGENT CONFIG
// ****************************************************************************
#define SHVM_ENABLE "shvm.enable"
#define SHVM_ENABLE_DEFAULT false
#define SHVM_SERVER_HOST "shvm.server.host"
#define SHVM_SERVER_HOST_DEFAULT "localhost"
#define SHVM_SERVER_PORT "shvm.server.port"
#define SHVM_SERVER_PORT_DEFAULT "11218"
#define SHVM_DEBUG "shvm.debug"
#define SHVM_DEBUG_DEFAULT false
// ****************************************************************************
// DiSL AGENT CONFIG
// ****************************************************************************
#define DISL_ENABLE "disl.enable"
#define DISL_ENABLE_DEFAULT false
#define DISL_SERVER_HOST "disl.server.host"
#define DISL_SERVER_HOST_DEFAULT "localhost"
#define DISL_SERVER_PORT "disl.server.port"
#define DISL_SERVER_PORT_DEFAULT "11217"
// Required argument (no default value).
#define DISL_INSTRUMENTATION "disl.instrumentation"
#define DISL_INSTRUMENTATION_SEPARATOR ","
#define DISL_BYPASS "disl.bypass"
#define DISL_BYPASS_DEFAULT "dynamic"
#define DISL_SPLIT_METHODS "disl.splitmethods"
#define DISL_SPLIT_METHODS_DEFAULT true
#define DISL_CATCH_EXCEPTIONS "disl.excepthandler"
#define DISL_CATCH_EXCEPTIONS_DEFAULT false
#define DISL_FORCE_SUPERCLASS "disl.forcesuperclass"
#define DISL_FORCE_SUPERCLASS_DEFAULT false
#define DISL_FORCE_INTERFACES "disl.forceinterfaces"
#define DISL_FORCE_INTERFACES_DEFAULT false
#define DISL_DEBUG "disl.debug"
#define DISL_DEBUG_DEFAULT false
/*
* Agent configuration.
*/
static struct config agent_config;
/**
* Parse the instrumentation jar list in format "jar:jar2:...:jarN" to agent_config struct.
*
* @param list The list of jar files separated by :
* @param config
*/
static void
__parse_instrumentations (char * list, struct config * config) {
size_t jar_count;
const char ** jar_paths = strsplit (list, LIST_SEPARATOR, &jar_count);
config->jar_count = jar_count;
config->jar_paths = jar_paths;
}
static void
__configure_from_properties (jvmtiEnv * jvmti, struct config * config) {
//
// Get boolean values from system properties
//
config->shvm_debug = jvmti_get_system_property_bool (
jvmti, PROP_DEBUG, CONF_DEBUG_DEFAULT
config->shvm_functionality = jvmti_get_system_property_bool (
jvmti, SHVM_ENABLE, SHVM_ENABLE_DEFAULT
);
config->shvm_functionality = jvmti_get_system_property_bool (
jvmti, SHVM_FUNCTIONALITY, SHVM_FUNCTIONALITY_DEFAULT
config->shvm_debug = jvmti_get_system_property_bool (
jvmti, SHVM_DEBUG, SHVM_DEBUG_DEFAULT
);
//
config->disl_functionality = jvmti_get_system_property_bool (
jvmti, DISL_FUNCTIONALITY, DISL_FUNCTIONALITY_DEFAULT
jvmti, DISL_ENABLE, DISL_ENABLE_DEFAULT
);
config->disl_host = jvmti_get_system_property_string (
......@@ -90,20 +130,24 @@ __configure_from_properties (jvmtiEnv * jvmti, struct config * config) {
free (bypass);
//
// Get instrumentation list
// Get the names of instrumentation JAR files from a list of JAR files
// separated by commas (colons are a problem on Windows, semicolons are a
// problem in Unix/MacOS shells, comma should work just fine).
//
if (config->disl_functionality) {
char * instrumentation = jvmti_get_system_property_string (
jvmti, DISL_INSTRUMENTATION, NULL
char * jar_file_list = jvmti_get_system_property_string (
jvmti, DISL_INSTRUMENTATION, NULL
);
check_error (
instrumentation == NULL,
"Instrumentation agent enabled, but no instrumentation specified. "
jar_file_list == NULL,
"Instrumentation enabled, but no instrumentation jars specified. "
"Please check the use of the -D" DISL_INSTRUMENTATION " property."
);
__parse_instrumentations (instrumentation, config);
config->jar_paths = strsplit (
jar_file_list, DISL_INSTRUMENTATION_SEPARATOR, &config->jar_count
);
}
}
......@@ -115,8 +159,8 @@ __configure_from_options (const char * options, struct config * config) {
// if there are no agent options.
//
if (options == NULL) {
config->shadow_host = strdup (CONF_SHADOW_HOST_DEFAULT);
config->shadow_port = strdup (CONF_SHADOW_PORT_DEFAULT);
config->shadow_host = strdup (SHVM_SERVER_HOST_DEFAULT);
config->shadow_port = strdup (SHVM_SERVER_PORT_DEFAULT);
return;
}
......@@ -151,16 +195,26 @@ config_init (jvmtiEnv * jvmti, const char * options) {
check_error (
!agent_config.shvm_functionality && !agent_config.disl_functionality,
"At least one of instrumentation/analysis functions must be enabled. "
"Check the -D" DISL_FUNCTIONALITY " and -D" SHVM_FUNCTIONALITY " properties."
"Check the -D" DISL_ENABLE " and -D" SHVM_ENABLE " properties."
);
//
// Configuration summary.
//
rdexec {
rdaprefix ("host: %s\n", agent_config.shadow_host);
rdaprefix ("port: %s\n", agent_config.shadow_port);
rdaprefix ("debug: %d\n", agent_config.shvm_debug);
rdaprefix ("shvm host: %s\n", agent_config.shadow_host);
rdaprefix ("shvm port: %s\n", agent_config.shadow_port);
rdaprefix ("shvm debug: %d\n", agent_config.shvm_debug);
rdaprefix ("disl bypass mode: %d\n", agent_config.bypass_mode);
rdaprefix ("disl split methods: %d\n", agent_config.split_methods);
rdaprefix ("disl catch exceptions: %d\n", agent_config.catch_exceptions);
rdaprefix ("disl force superclass: %d\n", agent_config.force_superclass);
rdaprefix ("disl force interfaces: %d\n", agent_config.force_interfaces);
rdaprefix ("disl debug: %d\n", agent_config.disl_debug);
rdaprefix ("disl instrumentation jars: %zu\n", agent_config.jar_count);
for (size_t i = 0; i < agent_config.jar_count; i++) {
rdaprefix ("\t%s\n", agent_config.jar_paths [i]);
}
}
return &agent_config;
......
......@@ -16,60 +16,6 @@
#include <jvmti.h>
// ****************************************************************************
// SHVM AGENT CONFIG
// ****************************************************************************
#define SHVM_FUNCTIONALITY "svm-agent.allow"
#define SHVM_FUNCTIONALITY_DEFAULT false
#define PROP_SHADOW_HOST "svm-agent.shadow.host"
#define CONF_SHADOW_HOST_DEFAULT "localhost"
#define PROP_SHADOW_PORT "svm-agent.shadow.port"
#define CONF_SHADOW_PORT_DEFAULT "11218"
#define PROP_DEBUG "svm-agent.debug"
#define CONF_DEBUG_DEFAULT false
// ****************************************************************************
// DiSL AGENT CONFIG
// ****************************************************************************
#define DISL_FUNCTIONALITY "disl.allow"
#define DISL_FUNCTIONALITY_DEFAULT false
#define DISL_SERVER_HOST "disl.server.host"
#define DISL_SERVER_HOST_DEFAULT "localhost"
#define DISL_SERVER_PORT "disl.server.port"
#define DISL_SERVER_PORT_DEFAULT "11217"
// Required argument
// No default value.
#define DISL_INSTRUMENTATION "disl.instrumentation"