8320890: [AIX] Find a better way to mimic dl handle equality
Reviewed-by: stuefe, mdoerr
This commit is contained in:
parent
e5aed6be7a
commit
b8ae4a8c09
@ -1118,7 +1118,9 @@ void *os::dll_load(const char *filename, char *ebuf, int ebuflen) {
|
||||
}
|
||||
|
||||
if (!filename || strlen(filename) == 0) {
|
||||
::strncpy(ebuf, "dll_load: empty filename specified", ebuflen - 1);
|
||||
if (ebuf != nullptr && ebuflen > 0) {
|
||||
::strncpy(ebuf, "dll_load: empty filename specified", ebuflen - 1);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1133,8 +1135,9 @@ void *os::dll_load(const char *filename, char *ebuf, int ebuflen) {
|
||||
}
|
||||
|
||||
void* result;
|
||||
const char* error_report = nullptr;
|
||||
JFR_ONLY(NativeLibraryLoadEvent load_event(filename, &result);)
|
||||
result = ::dlopen(filename, dflags);
|
||||
result = Aix_dlopen(filename, dflags, &error_report);
|
||||
if (result != nullptr) {
|
||||
Events::log_dll_message(nullptr, "Loaded shared library %s", filename);
|
||||
// Reload dll cache. Don't do this in signal handling.
|
||||
@ -1143,7 +1146,6 @@ void *os::dll_load(const char *filename, char *ebuf, int ebuflen) {
|
||||
return result;
|
||||
} else {
|
||||
// error analysis when dlopen fails
|
||||
const char* error_report = ::dlerror();
|
||||
if (error_report == nullptr) {
|
||||
error_report = "dlerror returned no error description";
|
||||
}
|
||||
@ -3026,31 +3028,3 @@ void os::jfr_report_memory_info() {}
|
||||
|
||||
#endif // INCLUDE_JFR
|
||||
|
||||
// Simulate the library search algorithm of dlopen() (in os::dll_load)
|
||||
int os::Aix::stat64x_via_LIBPATH(const char* path, struct stat64x* stat) {
|
||||
if (path[0] == '/' ||
|
||||
(path[0] == '.' && (path[1] == '/' ||
|
||||
(path[1] == '.' && path[2] == '/')))) {
|
||||
return stat64x(path, stat);
|
||||
}
|
||||
|
||||
const char* env = getenv("LIBPATH");
|
||||
if (env == nullptr || *env == 0)
|
||||
return -1;
|
||||
|
||||
int ret = -1;
|
||||
size_t libpathlen = strlen(env);
|
||||
char* libpath = NEW_C_HEAP_ARRAY(char, libpathlen + 1, mtServiceability);
|
||||
char* combined = NEW_C_HEAP_ARRAY(char, libpathlen + strlen(path) + 1, mtServiceability);
|
||||
char *saveptr, *token;
|
||||
strcpy(libpath, env);
|
||||
for (token = strtok_r(libpath, ":", &saveptr); token != nullptr; token = strtok_r(nullptr, ":", &saveptr)) {
|
||||
sprintf(combined, "%s/%s", token, path);
|
||||
if (0 == (ret = stat64x(combined, stat)))
|
||||
break;
|
||||
}
|
||||
|
||||
FREE_C_HEAP_ARRAY(char*, combined);
|
||||
FREE_C_HEAP_ARRAY(char*, libpath);
|
||||
return ret;
|
||||
}
|
||||
|
@ -175,8 +175,6 @@ class os::Aix {
|
||||
static bool platform_print_native_stack(outputStream* st, const void* context, char *buf, int buf_size, address& lastpc);
|
||||
static void* resolve_function_descriptor(void* p);
|
||||
|
||||
// Simulate the library search algorithm of dlopen() (in os::dll_load)
|
||||
static int stat64x_via_LIBPATH(const char* path, struct stat64x* stat);
|
||||
};
|
||||
|
||||
#endif // OS_AIX_OS_AIX_HPP
|
||||
|
@ -21,6 +21,12 @@
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
// needs to be defined first, so that the implicit loaded xcoff.h header defines
|
||||
// the right structures to analyze the loader header of 64 Bit executable files
|
||||
// this is needed for rtv_linkedin_libpath() to get the linked (burned) in library
|
||||
// search path of an XCOFF executable
|
||||
#define __XCOFF64__
|
||||
#include <xcoff.h>
|
||||
|
||||
#include "asm/assembler.hpp"
|
||||
#include "compiler/disassembler.hpp"
|
||||
@ -891,3 +897,275 @@ bool AixMisc::query_stack_bounds_for_current_thread(stackbounds_t* out) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// variables needed to emulate linux behavior in os::dll_load() if library is loaded twice
|
||||
static pthread_mutex_t g_handletable_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
struct TableLocker {
|
||||
TableLocker() { pthread_mutex_lock(&g_handletable_mutex); }
|
||||
~TableLocker() { pthread_mutex_unlock(&g_handletable_mutex); }
|
||||
};
|
||||
struct handletableentry{
|
||||
void* handle;
|
||||
ino64_t inode;
|
||||
dev64_t devid;
|
||||
uint refcount;
|
||||
};
|
||||
constexpr unsigned init_num_handles = 128;
|
||||
static unsigned max_handletable = 0;
|
||||
static unsigned g_handletable_used = 0;
|
||||
// We start with an empty array. At first use we will dynamically allocate memory for 128 entries.
|
||||
// If this table is full we dynamically reallocate a memory reagion of double size, and so on.
|
||||
static struct handletableentry* p_handletable = nullptr;
|
||||
|
||||
// get the library search path burned in to the executable file during linking
|
||||
// If the libpath cannot be retrieved return an empty path
|
||||
static const char* rtv_linkedin_libpath() {
|
||||
constexpr int bufsize = 4096;
|
||||
static char buffer[bufsize];
|
||||
static const char* libpath = 0;
|
||||
|
||||
// we only try to retrieve the libpath once. After that try we
|
||||
// let libpath point to buffer, which then contains a valid libpath
|
||||
// or an empty string
|
||||
if (libpath != nullptr) {
|
||||
return libpath;
|
||||
}
|
||||
|
||||
// retrieve the path to the currently running executable binary
|
||||
// to open it
|
||||
snprintf(buffer, 100, "/proc/%ld/object/a.out", (long)getpid());
|
||||
FILE* f = nullptr;
|
||||
struct xcoffhdr the_xcoff;
|
||||
struct scnhdr the_scn;
|
||||
struct ldhdr the_ldr;
|
||||
constexpr size_t xcoffsz = FILHSZ + _AOUTHSZ_EXEC;
|
||||
STATIC_ASSERT(sizeof(the_xcoff) == xcoffsz);
|
||||
STATIC_ASSERT(sizeof(the_scn) == SCNHSZ);
|
||||
STATIC_ASSERT(sizeof(the_ldr) == LDHDRSZ);
|
||||
// read the generic XCOFF header and analyze the substructures
|
||||
// to find the burned in libpath. In any case of error perform the assert
|
||||
if (nullptr == (f = fopen(buffer, "r")) ||
|
||||
xcoffsz != fread(&the_xcoff, 1, xcoffsz, f) ||
|
||||
the_xcoff.filehdr.f_magic != U64_TOCMAGIC ||
|
||||
0 != fseek(f, (FILHSZ + the_xcoff.filehdr.f_opthdr + (the_xcoff.aouthdr.o_snloader -1)*SCNHSZ), SEEK_SET) ||
|
||||
SCNHSZ != fread(&the_scn, 1, SCNHSZ, f) ||
|
||||
0 != strcmp(the_scn.s_name, ".loader") ||
|
||||
0 != fseek(f, the_scn.s_scnptr, SEEK_SET) ||
|
||||
LDHDRSZ != fread(&the_ldr, 1, LDHDRSZ, f) ||
|
||||
0 != fseek(f, the_scn.s_scnptr + the_ldr.l_impoff, SEEK_SET) ||
|
||||
0 == fread(buffer, 1, bufsize, f)) {
|
||||
buffer[0] = 0;
|
||||
assert(false, "could not retrieve burned in library path from executables loader section");
|
||||
}
|
||||
|
||||
if (f) {
|
||||
fclose(f);
|
||||
}
|
||||
libpath = buffer;
|
||||
|
||||
return libpath;
|
||||
}
|
||||
|
||||
// Simulate the library search algorithm of dlopen() (in os::dll_load)
|
||||
static bool search_file_in_LIBPATH(const char* path, struct stat64x* stat) {
|
||||
if (path == nullptr)
|
||||
return false;
|
||||
|
||||
char* path2 = os::strdup(path);
|
||||
// if exist, strip off trailing (shr_64.o) or similar
|
||||
char* substr;
|
||||
if (path2[strlen(path2) - 1] == ')' && (substr = strrchr(path2, '('))) {
|
||||
*substr = 0;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
// If FilePath contains a slash character, FilePath is used directly,
|
||||
// and no directories are searched.
|
||||
// But if FilePath does not start with / or . we have to prepend it with ./
|
||||
if (strchr(path2, '/')) {
|
||||
stringStream combined;
|
||||
if (*path2 == '/' || *path2 == '.') {
|
||||
combined.print("%s", path2);
|
||||
} else {
|
||||
combined.print("./%s", path2);
|
||||
}
|
||||
ret = (0 == stat64x(combined.base(), stat));
|
||||
os::free(path2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* env = getenv("LIBPATH");
|
||||
if (env == nullptr) {
|
||||
// no LIBPATH, try with LD_LIBRARY_PATH
|
||||
env = getenv("LD_LIBRARY_PATH");
|
||||
}
|
||||
|
||||
stringStream Libpath;
|
||||
if (env == nullptr) {
|
||||
// no LIBPATH or LD_LIBRARY_PATH given -> try only with burned in libpath
|
||||
Libpath.print("%s", rtv_linkedin_libpath());
|
||||
} else if (*env == 0) {
|
||||
// LIBPATH or LD_LIBRARY_PATH given but empty -> try first with burned
|
||||
// in libpath and with current working directory second
|
||||
Libpath.print("%s:.", rtv_linkedin_libpath());
|
||||
} else {
|
||||
// LIBPATH or LD_LIBRARY_PATH given with content -> try first with
|
||||
// LIBPATH or LD_LIBRARY_PATH and second with burned in libpath.
|
||||
// No check against current working directory
|
||||
Libpath.print("%s:%s", env, rtv_linkedin_libpath());
|
||||
}
|
||||
|
||||
char* libpath = os::strdup(Libpath.base());
|
||||
|
||||
char *saveptr, *token;
|
||||
for (token = strtok_r(libpath, ":", &saveptr); token != nullptr; token = strtok_r(nullptr, ":", &saveptr)) {
|
||||
stringStream combined;
|
||||
combined.print("%s/%s", token, path2);
|
||||
if ((ret = (0 == stat64x(combined.base(), stat))))
|
||||
break;
|
||||
}
|
||||
|
||||
os::free(libpath);
|
||||
os::free(path2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// specific AIX versions for ::dlopen() and ::dlclose(), which handles the struct g_handletable
|
||||
// This way we mimic dl handle equality for a library
|
||||
// opened a second time, as it is implemented on other platforms.
|
||||
void* Aix_dlopen(const char* filename, int Flags, const char** error_report) {
|
||||
assert(error_report != nullptr, "error_report is nullptr");
|
||||
void* result;
|
||||
struct stat64x libstat;
|
||||
|
||||
if (false == search_file_in_LIBPATH(filename, &libstat)) {
|
||||
// file with filename does not exist
|
||||
#ifdef ASSERT
|
||||
result = ::dlopen(filename, Flags);
|
||||
assert(result == nullptr, "dll_load: Could not stat() file %s, but dlopen() worked; Have to improve stat()", filename);
|
||||
#endif
|
||||
*error_report = "Could not load module .\nSystem error: No such file or directory";
|
||||
return nullptr;
|
||||
}
|
||||
else {
|
||||
unsigned i = 0;
|
||||
TableLocker lock;
|
||||
// check if library belonging to filename is already loaded.
|
||||
// If yes use stored handle from previous ::dlopen() and increase refcount
|
||||
for (i = 0; i < g_handletable_used; i++) {
|
||||
if ((p_handletable + i)->handle &&
|
||||
(p_handletable + i)->inode == libstat.st_ino &&
|
||||
(p_handletable + i)->devid == libstat.st_dev) {
|
||||
(p_handletable + i)->refcount++;
|
||||
result = (p_handletable + i)->handle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == g_handletable_used) {
|
||||
// library not yet loaded. Check if there is space left in array
|
||||
// to store new ::dlopen() handle
|
||||
if (g_handletable_used == max_handletable) {
|
||||
// No place in array anymore; increase array.
|
||||
unsigned new_max = MAX2(max_handletable * 2, init_num_handles);
|
||||
struct handletableentry* new_tab = (struct handletableentry*)::realloc(p_handletable, new_max * sizeof(struct handletableentry));
|
||||
assert(new_tab != nullptr, "no more memory for handletable");
|
||||
if (new_tab == nullptr) {
|
||||
*error_report = "dlopen: no more memory for handletable";
|
||||
return nullptr;
|
||||
}
|
||||
max_handletable = new_max;
|
||||
p_handletable = new_tab;
|
||||
}
|
||||
// Library not yet loaded; load it, then store its handle in handle table
|
||||
result = ::dlopen(filename, Flags);
|
||||
if (result != nullptr) {
|
||||
g_handletable_used++;
|
||||
(p_handletable + i)->handle = result;
|
||||
(p_handletable + i)->inode = libstat.st_ino;
|
||||
(p_handletable + i)->devid = libstat.st_dev;
|
||||
(p_handletable + i)->refcount = 1;
|
||||
}
|
||||
else {
|
||||
// error analysis when dlopen fails
|
||||
*error_report = ::dlerror();
|
||||
if (*error_report == nullptr) {
|
||||
*error_report = "dlerror returned no error description";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool os::pd_dll_unload(void* libhandle, char* ebuf, int ebuflen) {
|
||||
unsigned i = 0;
|
||||
bool res = false;
|
||||
|
||||
if (ebuf && ebuflen > 0) {
|
||||
ebuf[0] = '\0';
|
||||
ebuf[ebuflen - 1] = '\0';
|
||||
}
|
||||
|
||||
{
|
||||
TableLocker lock;
|
||||
// try to find handle in array, which means library was loaded by os::dll_load() call
|
||||
for (i = 0; i < g_handletable_used; i++) {
|
||||
if ((p_handletable + i)->handle == libhandle) {
|
||||
// handle found, decrease refcount
|
||||
assert((p_handletable + i)->refcount > 0, "Sanity");
|
||||
(p_handletable + i)->refcount--;
|
||||
if ((p_handletable + i)->refcount > 0) {
|
||||
// if refcount is still >0 then we have to keep library and just return true
|
||||
return true;
|
||||
}
|
||||
// refcount == 0, so we have to ::dlclose() the lib
|
||||
// and delete the entry from the array.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we reach this point either the libhandle was found with refcount == 0, or the libhandle
|
||||
// was not found in the array at all. In both cases we have to ::dlclose the lib and perform
|
||||
// the error handling. In the first case we then also have to delete the entry from the array
|
||||
// while in the second case we simply have to nag.
|
||||
res = (0 == ::dlclose(libhandle));
|
||||
if (!res) {
|
||||
// error analysis when dlopen fails
|
||||
const char* error_report = ::dlerror();
|
||||
if (error_report == nullptr) {
|
||||
error_report = "dlerror returned no error description";
|
||||
}
|
||||
if (ebuf != nullptr && ebuflen > 0) {
|
||||
snprintf(ebuf, ebuflen - 1, "%s", error_report);
|
||||
}
|
||||
assert(false, "os::pd_dll_unload() ::dlclose() failed");
|
||||
}
|
||||
|
||||
if (i < g_handletable_used) {
|
||||
if (res) {
|
||||
// First case: libhandle was found (with refcount == 0) and ::dlclose successful,
|
||||
// so delete entry from array
|
||||
g_handletable_used--;
|
||||
// If the entry was the last one of the array, the previous g_handletable_used--
|
||||
// is sufficient to remove the entry from the array, otherwise we move the last
|
||||
// entry of the array to the place of the entry we want to remove and overwrite it
|
||||
if (i < g_handletable_used) {
|
||||
*(p_handletable + i) = *(p_handletable + g_handletable_used);
|
||||
(p_handletable + g_handletable_used)->handle = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Second case: libhandle was not found (library was not loaded by os::dll_load())
|
||||
// therefore nag
|
||||
assert(false, "os::pd_dll_unload() library was not loaded by os::dll_load()");
|
||||
}
|
||||
}
|
||||
|
||||
// Update the dll cache
|
||||
LoadedLibraries::reload();
|
||||
|
||||
return res;
|
||||
} // end: os::pd_dll_unload()
|
||||
|
||||
|
@ -115,4 +115,6 @@ class AixMisc {
|
||||
|
||||
};
|
||||
|
||||
void* Aix_dlopen(const char* filename, int Flags, const char** error_report);
|
||||
|
||||
#endif // OS_AIX_PORTING_AIX_HPP
|
||||
|
@ -2530,3 +2530,25 @@ void os::jfr_report_memory_info() {
|
||||
}
|
||||
|
||||
#endif // INCLUDE_JFR
|
||||
|
||||
bool os::pd_dll_unload(void* libhandle, char* ebuf, int ebuflen) {
|
||||
|
||||
if (ebuf && ebuflen > 0) {
|
||||
ebuf[0] = '\0';
|
||||
ebuf[ebuflen - 1] = '\0';
|
||||
}
|
||||
|
||||
bool res = (0 == ::dlclose(libhandle));
|
||||
if (!res) {
|
||||
// error analysis when dlopen fails
|
||||
const char* error_report = ::dlerror();
|
||||
if (error_report == nullptr) {
|
||||
error_report = "dlerror returned no error description";
|
||||
}
|
||||
if (ebuf != nullptr && ebuflen > 0) {
|
||||
snprintf(ebuf, ebuflen - 1, "%s", error_report);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
} // end: os::pd_dll_unload()
|
||||
|
@ -5469,3 +5469,25 @@ bool os::trim_native_heap(os::size_change_t* rss_change) {
|
||||
return false; // musl
|
||||
#endif
|
||||
}
|
||||
|
||||
bool os::pd_dll_unload(void* libhandle, char* ebuf, int ebuflen) {
|
||||
|
||||
if (ebuf && ebuflen > 0) {
|
||||
ebuf[0] = '\0';
|
||||
ebuf[ebuflen - 1] = '\0';
|
||||
}
|
||||
|
||||
bool res = (0 == ::dlclose(libhandle));
|
||||
if (!res) {
|
||||
// error analysis when dlopen fails
|
||||
const char* error_report = ::dlerror();
|
||||
if (error_report == nullptr) {
|
||||
error_report = "dlerror returned no error description";
|
||||
}
|
||||
if (ebuf != nullptr && ebuflen > 0) {
|
||||
snprintf(ebuf, ebuflen - 1, "%s", error_report);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
} // end: os::pd_dll_unload()
|
||||
|
@ -56,6 +56,7 @@
|
||||
|
||||
#ifdef AIX
|
||||
#include "loadlib_aix.hpp"
|
||||
#include "os_aix.hpp"
|
||||
#endif
|
||||
#ifdef LINUX
|
||||
#include "os_linux.hpp"
|
||||
@ -731,27 +732,22 @@ void os::dll_unload(void *lib) {
|
||||
if (l_path == nullptr) {
|
||||
l_path = "<not available>";
|
||||
}
|
||||
int res = ::dlclose(lib);
|
||||
|
||||
if (res == 0) {
|
||||
char ebuf[1024];
|
||||
bool res = os::pd_dll_unload(lib, ebuf, sizeof(ebuf));
|
||||
|
||||
if (res) {
|
||||
Events::log_dll_message(nullptr, "Unloaded shared library \"%s\" [" INTPTR_FORMAT "]",
|
||||
l_path, p2i(lib));
|
||||
log_info(os)("Unloaded shared library \"%s\" [" INTPTR_FORMAT "]", l_path, p2i(lib));
|
||||
JFR_ONLY(unload_event.set_result(true);)
|
||||
} else {
|
||||
const char* error_report = ::dlerror();
|
||||
if (error_report == nullptr) {
|
||||
error_report = "dlerror returned no error description";
|
||||
}
|
||||
|
||||
Events::log_dll_message(nullptr, "Attempt to unload shared library \"%s\" [" INTPTR_FORMAT "] failed, %s",
|
||||
l_path, p2i(lib), error_report);
|
||||
l_path, p2i(lib), ebuf);
|
||||
log_info(os)("Attempt to unload shared library \"%s\" [" INTPTR_FORMAT "] failed, %s",
|
||||
l_path, p2i(lib), error_report);
|
||||
JFR_ONLY(unload_event.set_error_msg(error_report);)
|
||||
l_path, p2i(lib), ebuf);
|
||||
JFR_ONLY(unload_event.set_error_msg(ebuf);)
|
||||
}
|
||||
// Update the dll cache
|
||||
AIX_ONLY(LoadedLibraries::reload());
|
||||
LINUX_ONLY(os::free(l_pathdup));
|
||||
}
|
||||
|
||||
|
@ -75,10 +75,6 @@ JvmtiAgent::JvmtiAgent(const char* name, const char* options, bool is_absolute_p
|
||||
_options(copy_string(options)),
|
||||
_os_lib(nullptr),
|
||||
_os_lib_path(nullptr),
|
||||
#ifdef AIX
|
||||
_inode(0),
|
||||
_device(0),
|
||||
#endif
|
||||
_jplis(nullptr),
|
||||
_loaded(false),
|
||||
_absolute_path(is_absolute_path),
|
||||
@ -123,24 +119,6 @@ const char* JvmtiAgent::os_lib_path() const {
|
||||
return _os_lib_path;
|
||||
}
|
||||
|
||||
#ifdef AIX
|
||||
void JvmtiAgent::set_inode(ino64_t inode) {
|
||||
_inode = inode;
|
||||
}
|
||||
|
||||
void JvmtiAgent::set_device(dev64_t device) {
|
||||
_device = device;
|
||||
}
|
||||
|
||||
ino64_t JvmtiAgent::inode() const {
|
||||
return _inode;
|
||||
}
|
||||
|
||||
dev64_t JvmtiAgent::device() const {
|
||||
return _device;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool JvmtiAgent::is_loaded() const {
|
||||
return _loaded;
|
||||
}
|
||||
@ -295,20 +273,6 @@ static bool load_agent_from_executable(JvmtiAgent* agent, const char* on_load_sy
|
||||
return os::find_builtin_agent(agent, &on_load_symbols[0], num_symbol_entries);
|
||||
}
|
||||
|
||||
#ifdef AIX
|
||||
// save the inode and device of the library's file as a signature. This signature can be used
|
||||
// in the same way as the library handle as a signature on other platforms.
|
||||
static void save_library_signature(JvmtiAgent* agent, const char* name) {
|
||||
struct stat64x libstat;
|
||||
if (0 == os::Aix::stat64x_via_LIBPATH(name, &libstat)) {
|
||||
agent->set_inode(libstat.st_ino);
|
||||
agent->set_device(libstat.st_dev);
|
||||
} else {
|
||||
assert(false, "stat64x failed");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Load the library from the absolute path of the agent, if available.
|
||||
static void* load_agent_from_absolute_path(JvmtiAgent* agent, bool vm_exit_on_error) {
|
||||
DEBUG_ONLY(assert_preload(agent);)
|
||||
@ -318,7 +282,6 @@ static void* load_agent_from_absolute_path(JvmtiAgent* agent, bool vm_exit_on_er
|
||||
if (library == nullptr && vm_exit_on_error) {
|
||||
vm_exit(agent, " in absolute path, with error: ", nullptr);
|
||||
}
|
||||
AIX_ONLY(if (library != nullptr) save_library_signature(agent, agent->name());)
|
||||
return library;
|
||||
}
|
||||
|
||||
@ -331,13 +294,11 @@ static void* load_agent_from_relative_path(JvmtiAgent* agent, bool vm_exit_on_er
|
||||
// Try to load the agent from the standard dll directory
|
||||
if (os::dll_locate_lib(&buffer[0], sizeof buffer, Arguments::get_dll_dir(), name)) {
|
||||
library = os::dll_load(&buffer[0], &ebuf[0], sizeof ebuf);
|
||||
AIX_ONLY(if (library != nullptr) save_library_signature(agent, &buffer[0]);)
|
||||
}
|
||||
if (library == nullptr && os::dll_build_name(&buffer[0], sizeof buffer, name)) {
|
||||
// Try the library path directory.
|
||||
library = os::dll_load(&buffer[0], &ebuf[0], sizeof ebuf);
|
||||
if (library != nullptr) {
|
||||
AIX_ONLY(save_library_signature(agent, &buffer[0]);)
|
||||
return library;
|
||||
}
|
||||
if (vm_exit_on_error) {
|
||||
@ -555,11 +516,7 @@ static bool invoke_Agent_OnAttach(JvmtiAgent* agent, outputStream* st) {
|
||||
agent->set_os_lib_path(&buffer[0]);
|
||||
agent->set_os_lib(library);
|
||||
agent->set_loaded();
|
||||
#ifdef AIX
|
||||
previously_loaded = JvmtiAgentList::is_dynamic_lib_loaded(agent->device(), agent->inode());
|
||||
#else
|
||||
previously_loaded = JvmtiAgentList::is_dynamic_lib_loaded(library);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Print warning if agent was not previously loaded and EnableDynamicAgentLoading not enabled on the command line.
|
||||
|
@ -43,10 +43,6 @@ class JvmtiAgent : public CHeapObj<mtServiceability> {
|
||||
const char* _options;
|
||||
void* _os_lib;
|
||||
const char* _os_lib_path;
|
||||
#ifdef AIX
|
||||
ino64_t _inode;
|
||||
dev64_t _device;
|
||||
#endif
|
||||
const void* _jplis;
|
||||
bool _loaded;
|
||||
bool _absolute_path;
|
||||
@ -84,12 +80,6 @@ class JvmtiAgent : public CHeapObj<mtServiceability> {
|
||||
void initialization_end();
|
||||
const Ticks& initialization_time() const;
|
||||
const Tickspan& initialization_duration() const;
|
||||
#ifdef AIX
|
||||
void set_inode(ino64_t inode);
|
||||
void set_device(dev64_t device);
|
||||
unsigned long inode() const;
|
||||
unsigned long device() const;
|
||||
#endif
|
||||
|
||||
bool load(outputStream* st = nullptr);
|
||||
void unload();
|
||||
|
@ -243,19 +243,6 @@ bool JvmtiAgentList::is_dynamic_lib_loaded(void* os_lib) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#ifdef AIX
|
||||
bool JvmtiAgentList::is_dynamic_lib_loaded(dev64_t device, ino64_t inode) {
|
||||
JvmtiAgentList::Iterator it = JvmtiAgentList::agents();
|
||||
while (it.has_next()) {
|
||||
JvmtiAgent* const agent = it.next();
|
||||
if (!agent->is_static_lib() && device != 0 && inode != 0 &&
|
||||
agent->device() == device && agent->inode() == inode) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool match(JvmtiEnv* env, const JvmtiAgent* agent, const void* os_module_address) {
|
||||
assert(env != nullptr, "invariant");
|
||||
|
@ -78,9 +78,6 @@ class JvmtiAgentList : AllStatic {
|
||||
|
||||
static bool is_static_lib_loaded(const char* name);
|
||||
static bool is_dynamic_lib_loaded(void* os_lib);
|
||||
#ifdef AIX
|
||||
static bool is_dynamic_lib_loaded(dev64_t device, ino64_t inode);
|
||||
#endif
|
||||
|
||||
static JvmtiAgent* lookup(JvmtiEnv* env, void* f_ptr);
|
||||
|
||||
|
@ -1063,6 +1063,7 @@ class os: AllStatic {
|
||||
char pathSep);
|
||||
static bool set_boot_path(char fileSep, char pathSep);
|
||||
|
||||
static bool pd_dll_unload(void* libhandle, char* ebuf, int ebuflen);
|
||||
};
|
||||
|
||||
// Note that "PAUSE" is almost always used with synchronization
|
||||
|
Loading…
x
Reference in New Issue
Block a user