7200297: agent code does not handle multiple boot library path elements correctly

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
This commit is contained in:
Bill Pittore 2012-12-02 19:16:56 -05:00 committed by David Holmes
parent d2d5213b87
commit ecdf296456
11 changed files with 175 additions and 61 deletions

View File

@ -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 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
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 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
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 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
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 */

View File

@ -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 @@ vprint_message(FILE *fp, const char *prefix, const char *suffix,
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);
}

View File

@ -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 @@ loadTransport(char *name, jdwpTransportEnv **transportPtr)
/* 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) {

View File

@ -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 */

View File

@ -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 @@ load_library(char *name)
*/
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 @@ lookup_library_symbol(void *library, char **symbols, int nsymbols)
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 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
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 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
}
#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");

View File

@ -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 @@ dbgsysBuildLibName(char *holder, int holderlen, char *pname, char *fname)
{
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);
}
}

View File

@ -380,6 +380,31 @@ md_ntohl(unsigned l)
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 @@ md_build_library_name(char *holder, int holderlen, char *pname, char *fname)
/* 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 @@ md_build_library_name(char *holder, int holderlen, char *pname, char *fname)
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);
}
}

View File

@ -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"); \

View File

@ -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 @@ void
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);
}
}

View File

@ -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 @@ get_last_error_string(char *buf, int len)
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);
}
}

View File

@ -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"); \