7200297: agent code does not handle multiple boot library path elements correctly
Summary: When bug 6819213 was fixed it enabled sun.boot.library.path property to contain multiple paths. Code in agents does not handle multiple paths when attempting to find dependent shared libs.
Reviewed-by: dholmes, sspitsyn, dsamersoff
Contributed-by: Bill Pittore <bill.pittore@oracle.com>
--- a/jdk/src/share/back/debugInit.c Sun Dec 02 16:37:31 2012 +0000
+++ b/jdk/src/share/back/debugInit.c Sun Dec 02 19:16:56 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,7 @@
#include "debugLoop.h"
#include "bag.h"
#include "invoker.h"
+#include "sys.h"
/* How the options get to OnLoad: */
#define XDEBUG "-Xdebug"
@@ -201,6 +202,8 @@
jint jvmtiCompileTimeMajorVersion;
jint jvmtiCompileTimeMinorVersion;
jint jvmtiCompileTimeMicroVersion;
+ char *boot_path = NULL;
+ char npt_lib[MAXPATHLEN];
/* See if it's already loaded */
if ( gdata!=NULL && gdata->isLoaded==JNI_TRUE ) {
@@ -227,18 +230,6 @@
vmInitialized = JNI_FALSE;
gdata->vmDead = JNI_FALSE;
- /* Npt and Utf function init */
- NPT_INITIALIZE(&(gdata->npt), NPT_VERSION, NULL);
- if (gdata->npt == NULL) {
- ERROR_MESSAGE(("JDWP: unable to initialize NPT library"));
- return JNI_ERR;
- }
- gdata->npt->utf = (gdata->npt->utfInitialize)(NULL);
- if (gdata->npt->utf == NULL) {
- ERROR_MESSAGE(("JDWP: UTF function initialization failed"));
- return JNI_ERR;
- }
-
/* Get the JVMTI Env, IMPORTANT: Do this first! For jvmtiAllocate(). */
error = JVM_FUNC_PTR(vm,GetEnv)
(vm, (void **)&(gdata->jvmti), JVMTI_VERSION_1);
@@ -277,6 +268,24 @@
forceExit(1); /* Kill entire process, no core dump wanted */
}
+ JVMTI_FUNC_PTR(gdata->jvmti, GetSystemProperty)
+ (gdata->jvmti, (const char *)"sun.boot.library.path",
+ &boot_path);
+
+ dbgsysBuildLibName(npt_lib, sizeof(npt_lib), boot_path, NPT_LIBNAME);
+ /* Npt and Utf function init */
+ NPT_INITIALIZE(npt_lib, &(gdata->npt), NPT_VERSION, NULL);
+ jvmtiDeallocate(boot_path);
+ if (gdata->npt == NULL) {
+ ERROR_MESSAGE(("JDWP: unable to initialize NPT library"));
+ return JNI_ERR;
+ }
+ gdata->npt->utf = (gdata->npt->utfInitialize)(NULL);
+ if (gdata->npt->utf == NULL) {
+ ERROR_MESSAGE(("JDWP: UTF function initialization failed"));
+ return JNI_ERR;
+ }
+
/* Parse input options */
if (!parseOptions(options)) {
/* No message necessary, should have been printed out already */
--- a/jdk/src/share/back/error_messages.c Sun Dec 02 16:37:31 2012 +0000
+++ b/jdk/src/share/back/error_messages.c Sun Dec 02 19:16:56 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -70,8 +70,13 @@
len = (int)strlen((char*)utf8buf);
/* Convert to platform encoding (ignore errors, dangerous area) */
- (void)(gdata->npt->utf8ToPlatform)(gdata->npt->utf,
- utf8buf, len, pbuf, MAX_MESSAGE_LEN);
+ if (gdata->npt != NULL) {
+ (void)(gdata->npt->utf8ToPlatform)(gdata->npt->utf,
+ utf8buf, len, pbuf, MAX_MESSAGE_LEN);
+ } else {
+ /* May be called before NPT is initialized so don't fault */
+ strncpy(pbuf, (char*)utf8buf, len);
+ }
(void)fprintf(fp, "%s%s%s", prefix, pbuf, suffix);
}
--- a/jdk/src/share/back/transport.c Sun Dec 02 16:37:31 2012 +0000
+++ b/jdk/src/share/back/transport.c Sun Dec 02 19:16:56 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -144,7 +144,9 @@
/* First, look in sun.boot.library.path. This should find the standard
* dt_socket and dt_shmem transport libraries, or any library
* that was delivered with the J2SE.
- * Note: Java property sun.boot.library.path contains a single directory.
+ * Note: Since 6819213 fixed, Java property sun.boot.library.path can
+ * contain multiple paths. Dll_dir is the first entry and
+ * -Dsun.boot.library.path entries are appended.
*/
libdir = gdata->property_sun_boot_library_path;
if (libdir == NULL) {
--- a/jdk/src/share/demo/jvmti/hprof/hprof.h Sun Dec 02 16:37:31 2012 +0000
+++ b/jdk/src/share/demo/jvmti/hprof/hprof.h Sun Dec 02 19:16:56 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -65,6 +65,7 @@
#include "jni.h"
#include "jvmti.h"
#include "classfile_constants.h"
+#include "jvm_md.h"
#ifndef SKIP_NPT
#include "npt.h" /* To get NptEnv for doing character conversions */
--- a/jdk/src/share/demo/jvmti/hprof/hprof_init.c Sun Dec 02 16:37:31 2012 +0000
+++ b/jdk/src/share/demo/jvmti/hprof/hprof_init.c Sun Dec 02 19:16:56 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -1899,6 +1899,7 @@
*/
getSystemProperty("sun.boot.library.path", &boot_path);
md_build_library_name(lname, FILENAME_MAX, boot_path, name);
+ jvmtiDeallocate(boot_path);
handle = md_load_library(lname, err_buf, (int)sizeof(err_buf));
if ( handle == NULL ) {
/* This may be necessary on Windows. */
@@ -1941,6 +1942,9 @@
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{
+ char *boot_path = NULL;
+ char npt_lib[JVM_MAXPATHLEN];
+
/* See if it's already loaded */
if ( gdata!=NULL && gdata->isLoaded==JNI_TRUE ) {
HPROF_ERROR(JNI_TRUE, "Cannot load this JVM TI agent twice, check your java command line for duplicate hprof options.");
@@ -1957,9 +1961,15 @@
gdata->jvm = vm;
+ /* Get the JVMTI environment */
+ getJvmti();
+
#ifndef SKIP_NPT
+ getSystemProperty("sun.boot.library.path", &boot_path);
/* Load in NPT library for character conversions */
- NPT_INITIALIZE(&(gdata->npt), NPT_VERSION, NULL);
+ md_build_library_name(npt_lib, sizeof(npt_lib), boot_path, NPT_LIBNAME);
+ jvmtiDeallocate(boot_path);
+ NPT_INITIALIZE(npt_lib, &(gdata->npt), NPT_VERSION, NULL);
if ( gdata->npt == NULL ) {
HPROF_ERROR(JNI_TRUE, "Cannot load npt library");
}
@@ -1969,9 +1979,6 @@
}
#endif
- /* Get the JVMTI environment */
- getJvmti();
-
/* Lock needed to protect debug_malloc() code, which is not MT safe */
#ifdef DEBUG
gdata->debug_malloc_lock = createRawMonitor("HPROF debug_malloc lock");
--- a/jdk/src/solaris/back/linker_md.c Sun Dec 02 16:37:31 2012 +0000
+++ b/jdk/src/solaris/back/linker_md.c Sun Dec 02 19:16:56 2012 -0500
@@ -54,6 +54,32 @@
#define LIB_SUFFIX "so"
#endif
+static void dll_build_name(char* buffer, size_t buflen,
+ const char* pname, const char* fname) {
+ // Based on os_solaris.cpp
+
+ char *path_sep = PATH_SEPARATOR;
+ char *pathname = (char *)pname;
+ while (strlen(pathname) > 0) {
+ char *p = strchr(pathname, *path_sep);
+ if (p == NULL) {
+ p = pathname + strlen(pathname);
+ }
+ /* check for NULL path */
+ if (p == pathname) {
+ continue;
+ }
+ (void)snprintf(buffer, buflen, "%.*s/lib%s." LIB_SUFFIX, (p - pathname),
+ pathname, fname);
+
+ if (access(buffer, F_OK) == 0) {
+ break;
+ }
+ pathname = p + 1;
+ *buffer = '\0';
+ }
+}
+
/*
* create a string for the JNI native function name by adding the
* appropriate decorations.
@@ -76,16 +102,16 @@
{
const int pnamelen = pname ? strlen(pname) : 0;
+ *holder = '\0';
/* Quietly truncate on buffer overflow. Should be an error. */
if (pnamelen + (int)strlen(fname) + 10 > holderlen) {
- *holder = '\0';
return;
}
if (pnamelen == 0) {
(void)snprintf(holder, holderlen, "lib%s." LIB_SUFFIX, fname);
} else {
- (void)snprintf(holder, holderlen, "%s/lib%s." LIB_SUFFIX, pname, fname);
+ dll_build_name(holder, holderlen, pname, fname);
}
}
--- a/jdk/src/solaris/demo/jvmti/hprof/hprof_md.c Sun Dec 02 16:37:31 2012 +0000
+++ b/jdk/src/solaris/demo/jvmti/hprof/hprof_md.c Sun Dec 02 19:16:56 2012 -0500
@@ -380,6 +380,31 @@
return ntohl(l);
}
+static void dll_build_name(char* buffer, size_t buflen,
+ const char* pname, const char* fname) {
+ // Loosely based on os_solaris.cpp
+
+ char *pathname = (char *)pname;
+ while (strlen(pathname) > 0) {
+ char *p = strchr(pathname, ':');
+ if (p == NULL) {
+ p = pathname + strlen(pathname);
+ }
+ /* check for NULL path */
+ if (p == pathname) {
+ continue;
+ }
+ (void)snprintf(buffer, buflen, "%.*s/lib%s" JNI_LIB_SUFFIX,
+ (p - pathname), pathname, fname);
+
+ if (access(buffer, F_OK) == 0) {
+ break;
+ }
+ pathname = p + 1;
+ *buffer = '\0';
+ }
+}
+
/* Create the actual fill filename for a dynamic library. */
void
md_build_library_name(char *holder, int holderlen, char *pname, char *fname)
@@ -389,9 +414,9 @@
/* Length of options directory location. */
pnamelen = pname ? strlen(pname) : 0;
+ *holder = '\0';
/* Quietly truncate on buffer overflow. Should be an error. */
if (pnamelen + (int)strlen(fname) + 10 > holderlen) {
- *holder = '\0';
return;
}
@@ -399,7 +424,7 @@
if (pnamelen == 0) {
(void)snprintf(holder, holderlen, "lib%s" JNI_LIB_SUFFIX, fname);
} else {
- (void)snprintf(holder, holderlen, "%s/lib%s" JNI_LIB_SUFFIX, pname, fname);
+ dll_build_name(holder, holderlen, pname, fname);
}
}
--- a/jdk/src/solaris/npt/npt_md.h Sun Dec 02 16:37:31 2012 +0000
+++ b/jdk/src/solaris/npt/npt_md.h Sun Dec 02 19:16:56 2012 -0500
@@ -36,14 +36,14 @@
#define NPT_LIBNAME "npt"
-#define NPT_INITIALIZE(pnpt,version,options) \
+#define NPT_INITIALIZE(path,pnpt,version,options) \
{ \
void *_handle; \
void *_sym; \
\
if ( (pnpt) == NULL ) NPT_ERROR("NptEnv* is NULL"); \
*(pnpt) = NULL; \
- _handle = dlopen(JNI_LIB_NAME(NPT_LIBNAME), RTLD_LAZY); \
+ _handle = dlopen(path, RTLD_LAZY); \
if ( _handle == NULL ) NPT_ERROR("Cannot open library"); \
_sym = dlsym(_handle, "nptInitialize"); \
if ( _sym == NULL ) NPT_ERROR("Cannot find nptInitialize"); \
--- a/jdk/src/windows/back/linker_md.c Sun Dec 02 16:37:31 2012 +0000
+++ b/jdk/src/windows/back/linker_md.c Sun Dec 02 19:16:56 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,11 +32,42 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
+#include <io.h>
#include "sys.h"
#include "path_md.h"
+static void dll_build_name(char* buffer, size_t buflen,
+ const char* pname, const char* fname) {
+ // Based on os_windows.cpp
+
+ char *path_sep = PATH_SEPARATOR;
+ char *pathname = (char *)pname;
+ while (strlen(pathname) > 0) {
+ char *p = strchr(pathname, *path_sep);
+ if (p == NULL) {
+ p = pathname + strlen(pathname);
+ }
+ /* check for NULL path */
+ if (p == pathname) {
+ continue;
+ }
+ if (*(p-1) == ':' || *(p-1) == '\\') {
+ (void)_snprintf(buffer, buflen, "%.*s%s.dll", (p - pathname),
+ pathname, fname);
+ } else {
+ (void)_snprintf(buffer, buflen, "%.*s\\%s.dll", (p - pathname),
+ pathname, fname);
+ }
+ if (_access(buffer, 0) == 0) {
+ break;
+ }
+ pathname = p + 1;
+ *buffer = '\0';
+ }
+}
+
/*
* From system_md.c v1.54
*/
@@ -80,20 +111,17 @@
dbgsysBuildLibName(char *holder, int holderlen, char *pname, char *fname)
{
const int pnamelen = pname ? (int)strlen(pname) : 0;
- const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0;
+ *holder = '\0';
/* Quietly truncates on buffer overflow. Should be an error. */
if (pnamelen + (int)strlen(fname) + 10 > holderlen) {
- *holder = '\0';
return;
}
if (pnamelen == 0) {
sprintf(holder, "%s.dll", fname);
- } else if (c == ':' || c == '\\') {
- sprintf(holder, "%s%s.dll", pname, fname);
} else {
- sprintf(holder, "%s\\%s.dll", pname, fname);
+ dll_build_name(holder, holderlen, pname, fname);
}
}
--- a/jdk/src/windows/demo/jvmti/hprof/hprof_md.c Sun Dec 02 16:37:31 2012 +0000
+++ b/jdk/src/windows/demo/jvmti/hprof/hprof_md.c Sun Dec 02 19:16:56 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -367,28 +367,53 @@
return 0;
}
+static void dll_build_name(char* buffer, size_t buflen,
+ const char* pname, const char* fname) {
+ // Loosley based on os_windows.cpp
+
+ char *pathname = (char *)pname;
+ while (strlen(pathname) > 0) {
+ char *p = strchr(pathname, ';');
+ if (p == NULL) {
+ p = pathname + strlen(pathname);
+ }
+ /* check for NULL path */
+ if (p == pathname) {
+ continue;
+ }
+ if (*(p-1) == ':' || *(p-1) == '\\') {
+ (void)_snprintf(buffer, buflen, "%.*s%s.dll", (p - pathname),
+ pathname, fname);
+ } else {
+ (void)_snprintf(buffer, buflen, "%.*s\\%s.dll", (p - pathname),
+ pathname, fname);
+ }
+ if (_access(buffer, 0) == 0) {
+ break;
+ }
+ pathname = p + 1;
+ *buffer = '\0';
+ }
+}
+
/* Build a machine dependent library name out of a path and file name. */
void
md_build_library_name(char *holder, int holderlen, char *pname, char *fname)
{
int pnamelen;
- char c;
pnamelen = pname ? (int)strlen(pname) : 0;
- c = (pnamelen > 0) ? pname[pnamelen-1] : 0;
+ *holder = '\0';
/* Quietly truncates on buffer overflow. Should be an error. */
if (pnamelen + strlen(fname) + 10 > (unsigned int)holderlen) {
- *holder = '\0';
return;
}
if (pnamelen == 0) {
sprintf(holder, "%s.dll", fname);
- } else if (c == ':' || c == '\\') {
- sprintf(holder, "%s%s.dll", pname, fname);
} else {
- sprintf(holder, "%s\\%s.dll", pname, fname);
+ dll_build_name(holder, holderlen, pname, fname);
}
}
--- a/jdk/src/windows/npt/npt_md.h Sun Dec 02 16:37:31 2012 +0000
+++ b/jdk/src/windows/npt/npt_md.h Sun Dec 02 19:16:56 2012 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,30 +33,16 @@
#include <string.h>
#include <errno.h>
-#define NPT_LIBNAME "npt.dll"
+#define NPT_LIBNAME "npt"
-#define NPT_INITIALIZE(pnpt,version,options) \
+#define NPT_INITIALIZE(path,pnpt,version,options) \
{ \
- HINSTANCE jvm; \
void *_handle; \
void *_sym; \
- char buf[FILENAME_MAX+32]; \
- char *lastSlash; \
\
if ( (pnpt) == NULL ) NPT_ERROR("NptEnv* is NULL"); \
- _handle = NULL; \
*(pnpt) = NULL; \
- buf[0] = 0; \
- jvm = GetModuleHandle("jvm.dll"); \
- if ( jvm == NULL ) NPT_ERROR("Cannot find jvm.dll"); \
- GetModuleFileName(jvm, buf, FILENAME_MAX); \
- lastSlash = strrchr(buf, '\\'); \
- if ( lastSlash != NULL ) { \
- *lastSlash = '\0'; \
- (void)strcat(buf, "\\..\\"); \
- (void)strcat(buf, NPT_LIBNAME); \
- _handle = LoadLibrary(buf); \
- } \
+ _handle = LoadLibrary(path); \
if ( _handle == NULL ) NPT_ERROR("Cannot open library"); \
_sym = GetProcAddress(_handle, "nptInitialize"); \
if ( _sym == NULL ) NPT_ERROR("Cannot find nptInitialize"); \