From: <jik...@li...> - 2011-06-28 09:39:50
|
details: http://jikesrvm.hg.sourceforge.net/hgweb/jikesrvm/soc2011/rev/52b9daea3a2b changeset: 10394:52b9daea3a2b user: James Bornholt <u48...@an...> date: Tue Jun 28 19:39:35 2011 +1000 description: Load agents using -agentlib, using dlopen's search path behaviour diffstat: rvm/src/org/jikesrvm/runtime/jvmti/JVMTI.java | 56 +++++++++++++++++++++++++--- rvm/src/org/jikesrvm/runtime/jvmti/JVMTIAgent.java | 9 +++- test-agents/onload/onload.c | 1 + 3 files changed, 57 insertions(+), 9 deletions(-) diffs (135 lines): diff -r 56afb3a1235c -r 52b9daea3a2b rvm/src/org/jikesrvm/runtime/jvmti/JVMTI.java --- a/rvm/src/org/jikesrvm/runtime/jvmti/JVMTI.java Tue Jun 28 16:17:34 2011 +1000 +++ b/rvm/src/org/jikesrvm/runtime/jvmti/JVMTI.java Tue Jun 28 19:39:35 2011 +1000 @@ -29,6 +29,25 @@ new ImmutableEntryHashMapRVM<String, JVMTIAgent>(); /** + * Expand a library name into a filename that can be provided + * to dlopen. + * + * @param agentLib the library name + * @return the filename of the relevant shared library + */ + private static String mapLibraryName(String agentLib) { + String libSuffix; + if (VM.BuildForLinux || VM.BuildForSolaris) { + libSuffix = ".so"; + } else if (VM.BuildForOsx) { + libSuffix = ".jnilib"; + } else { + libSuffix = ".a"; + } + return "lib" + agentLib + libSuffix; + } + + /** * Initialise all the agents given on the command line. If a library cannot * be loaded or its Agent_OnLoad gives an error, we will call VM.sysFail, * so this will only return successfully if no errors occur. @@ -37,18 +56,20 @@ * @param agentPaths An array containing alternating lib paths and options */ public static void init(String[] agentLibs, String[] agentPaths) { -// for (int i = 0; i < agentLibs.length; i+=2) { -// VM.sysWriteln("agentlib: " + agentLibs[i] + ", opts " + agentLibs[i+1]); -// } -// for (int i = 0; i < agentPaths.length; i+=2) { -// VM.sysWriteln("agentpath: " + agentPaths[i] + ", opts " + agentPaths[i+1]); -// } for (int i = 0; i < agentPaths.length; i+=2) { if ( !JVMTI.loadAgentPath(agentPaths[i], agentPaths[i+1]) ) { VM.sysWriteln("Agent " + agentPaths[i] + " does not exist."); VM.sysExit(VM.EXIT_STATUS_BOGUS_COMMAND_LINE_ARG); } } + + // agentlib args are handled in a platform-specific manner. In particular, + // the spec expects us to expand the provided name to the platform-specific + // name (libfoo.so/libfoo.so/libfoo.a/libfoo.dll/etc), and then let the + // platform try to load that (through dlopen in this case). + for (int i = 0; i < agentLibs.length; i+=2) { + JVMTI.loadAgentLib(agentLibs[i], agentLibs[i+1]); + } } /** @@ -58,6 +79,7 @@ * callback. * * @param agentPath the absolute path to the shared library to load + * @param options the options from the command line argument * @return true if the load was successful */ public static boolean loadAgentPath(String agentPath, String options) { @@ -71,4 +93,26 @@ return false; // fail; file does not exist } } + + /** + * Load a new JVMTI agent using a library name - this corresponds + * to the command line argument -agentlib:<path>. + * The initialiser for JVMTIAgent will also fire the agent's onload + * callback. If the library cannot be found by the platform's dlopen, + * an UnsatisfiedLinkError will be thrown. + * + * Unlike loadAgentPath, we cannot stat the filename here because + * the paths to be checked for the library are platform-specific + * (as implemented by libc). + * + * @param agentLib the name of the shared library to load + * @param options the options from the command line argument + */ + public static void loadAgentLib(String agentLib, String options) { + String agentLibName = mapLibraryName(agentLib); + JVMTIAgent ag = agents.get(agentLibName); + if (ag != null) return; // already loaded + + agents.put(agentLibName, new JVMTIAgent(agentLibName, options)); + } } diff -r 56afb3a1235c -r 52b9daea3a2b rvm/src/org/jikesrvm/runtime/jvmti/JVMTIAgent.java --- a/rvm/src/org/jikesrvm/runtime/jvmti/JVMTIAgent.java Tue Jun 28 16:17:34 2011 +1000 +++ b/rvm/src/org/jikesrvm/runtime/jvmti/JVMTIAgent.java Tue Jun 28 19:39:35 2011 +1000 @@ -60,7 +60,7 @@ /** * Load an agent and maintain it in this object. - * @param agentPath the full path to the agent shared library + * @param agentPath the path to the agent shared library */ protected JVMTIAgent(String agentPath, String options) { // Convert file name from unicode to filesystem character set. @@ -85,7 +85,9 @@ if (agentHandle.isZero()) { VM.sysWriteln("error loading agent: " + agentPath); - throw new UnsatisfiedLinkError(); + // Causes a freeze + //throw new UnsatisfiedLinkError(); + VM.sysExit(VM.EXIT_STATUS_BOGUS_COMMAND_LINE_ARG); } agentName = agentPath; @@ -111,7 +113,8 @@ if (!agentOnLoad.isZero()) { int res = runAgent_OnLoad(agentOnLoad, options); if ( res != 0 ) { - VM.sysFail("JVMTI agent " + agentName + " returned error " + res + " from Agent_OnLoad; we cannot proceed."); + VM.sysWriteln("JVMTI agent " + agentName + " returned error " + res + " from Agent_OnLoad; we cannot proceed."); + VM.sysExit(VM.EXIT_STATUS_JNI_TROUBLE); } } } diff -r 56afb3a1235c -r 52b9daea3a2b test-agents/onload/onload.c --- a/test-agents/onload/onload.c Tue Jun 28 16:17:34 2011 +1000 +++ b/test-agents/onload/onload.c Tue Jun 28 19:39:35 2011 +1000 @@ -20,6 +20,7 @@ ret = (*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION); if ( ret != JNI_OK ) { fprintf(stderr, "ERROR: couldn't create JVMTI environment (%d)\n", ret); + return -1; } else { fprintf(stdout, "JVMTI agent loaded successfully.\n"); |