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:
parent
d2d5213b87
commit
ecdf296456
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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"); \
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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"); \
|
||||
|
Loading…
Reference in New Issue
Block a user