8315706: com/sun/tools/attach/warnings/DynamicLoadWarningTest.java real fix for failure on AIX
Reviewed-by: dholmes, mbaesken
This commit is contained in:
parent
ecce2afc1a
commit
21c2dac159
src/hotspot
os/aix
share/prims
test/jdk/com/sun/tools/attach/warnings
@ -3043,3 +3043,32 @@ void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {}
|
||||
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;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2016 SAP SE. All rights reserved.
|
||||
* Copyright (c) 2013, 2023 SAP SE. 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
|
||||
@ -174,6 +174,9 @@ 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
|
||||
|
@ -74,6 +74,10 @@ 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),
|
||||
@ -118,6 +122,24 @@ 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;
|
||||
}
|
||||
@ -272,6 +294,20 @@ 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);)
|
||||
@ -281,6 +317,7 @@ 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;
|
||||
}
|
||||
|
||||
@ -293,11 +330,13 @@ 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) {
|
||||
@ -515,7 +554,11 @@ 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,6 +43,10 @@ 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;
|
||||
@ -80,6 +84,12 @@ 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,6 +243,19 @@ 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,6 +78,9 @@ 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);
|
||||
|
||||
|
@ -123,18 +123,15 @@ class DynamicLoadWarningTest {
|
||||
.whenRunning(loadJvmtiAgent1)
|
||||
.stderrShouldNotContain(JVMTI_AGENT_WARNING);
|
||||
|
||||
// test behavior on platforms that can detect if an agent library was previously loaded
|
||||
if (!Platform.isAix()) {
|
||||
// start loadJvmtiAgent1 via the command line, then dynamically load loadJvmtiAgent1
|
||||
test().withOpts("-agentpath:" + jvmtiAgentPath1)
|
||||
.whenRunning(loadJvmtiAgent1)
|
||||
.stderrShouldNotContain(JVMTI_AGENT_WARNING);
|
||||
// start loadJvmtiAgent1 via the command line, then dynamically load loadJvmtiAgent1
|
||||
test().withOpts("-agentpath:" + jvmtiAgentPath1)
|
||||
.whenRunning(loadJvmtiAgent1)
|
||||
.stderrShouldNotContain(JVMTI_AGENT_WARNING);
|
||||
|
||||
// dynamically load loadJvmtiAgent1 twice, should be one warning
|
||||
test().whenRunning(loadJvmtiAgent1)
|
||||
.whenRunning(loadJvmtiAgent1)
|
||||
.stderrShouldContain(JVMTI_AGENT_WARNING, 1);
|
||||
}
|
||||
// dynamically load loadJvmtiAgent1 twice, should be one warning
|
||||
test().whenRunning(loadJvmtiAgent1)
|
||||
.whenRunning(loadJvmtiAgent1)
|
||||
.stderrShouldContain(JVMTI_AGENT_WARNING, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user