8056242: Add function to return structured information about loaded libraries.
Summary: Return structured information about loaded libraries.
Reviewed-by: sla, dsamersoff
Contributed-by: fredrik.arvidsson@oracle.com
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Tue Sep 02 21:27:08 2014 -0400
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Wed Sep 03 14:43:49 2014 +0200
@@ -1644,8 +1644,20 @@
return true;
}
+int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
+ outputStream * out = (outputStream *) param;
+ out->print_cr(PTR_FORMAT " \t%s", base_address, name);
+ return 0;
+}
+
void os::print_dll_info(outputStream *st) {
st->print_cr("Dynamic libraries:");
+ if (get_loaded_modules_info(_print_dll_info_cb, (void *)st)) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ }
+}
+
+int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
#ifdef RTLD_DI_LINKMAP
Dl_info dli;
void *handle;
@@ -1654,36 +1666,41 @@
if (dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli) == 0 ||
dli.dli_fname == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
+ return 1;
}
handle = dlopen(dli.dli_fname, RTLD_LAZY);
if (handle == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
+ return 1;
}
dlinfo(handle, RTLD_DI_LINKMAP, &map);
if (map == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
+ dlclose(handle);
+ return 1;
}
while (map->l_prev != NULL)
map = map->l_prev;
while (map != NULL) {
- st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name);
+ // Value for top_address is returned as 0 since we don't have any information about module size
+ if (callback(map->l_name, (address)map->l_addr, (address)0, param)) {
+ dlclose(handle);
+ return 1;
+ }
map = map->l_next;
}
dlclose(handle);
#elif defined(__APPLE__)
for (uint32_t i = 1; i < _dyld_image_count(); i++) {
- st->print_cr(PTR_FORMAT " \t%s", _dyld_get_image_header(i),
- _dyld_get_image_name(i));
+ // Value for top_address is returned as 0 since we don't have any information about module size
+ if (callback(_dyld_get_image_name(i), (address)_dyld_get_image_header(i), (address)0, param)) {
+ return 1;
+ }
}
+ return 0;
#else
- st->print_cr("Error: Cannot print dynamic libraries.");
+ return 1;
#endif
}
--- a/hotspot/src/os/linux/vm/os_linux.cpp Tue Sep 02 21:27:08 2014 -0400
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Wed Sep 03 14:43:49 2014 +0200
@@ -2120,6 +2120,40 @@
}
}
+int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
+ FILE *procmapsFile = NULL;
+
+ // Open the procfs maps file for the current process
+ if ((procmapsFile = fopen("/proc/self/maps", "r")) != NULL) {
+ // Allocate PATH_MAX for file name plus a reasonable size for other fields.
+ char line[PATH_MAX + 100];
+
+ // Read line by line from 'file'
+ while (fgets(line, sizeof(line), procmapsFile) != NULL) {
+ u8 base, top, offset, inode;
+ char permissions[5];
+ char device[6];
+ char name[PATH_MAX + 1];
+
+ // Parse fields from line
+ sscanf(line, "%lx-%lx %4s %lx %5s %ld %s", &base, &top, permissions, &offset, device, &inode, name);
+
+ // Filter by device id '00:00' so that we only get file system mapped files.
+ if (strcmp(device, "00:00") != 0) {
+
+ // Call callback with the fields of interest
+ if(callback(name, (address)base, (address)top, param)) {
+ // Oops abort, callback aborted
+ fclose(procmapsFile);
+ return 1;
+ }
+ }
+ }
+ fclose(procmapsFile);
+ }
+ return 0;
+}
+
void os::print_os_info_brief(outputStream* st) {
os::Linux::print_distro_info(st);
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Tue Sep 02 21:27:08 2014 -0400
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Sep 03 14:43:49 2014 +0200
@@ -1722,41 +1722,54 @@
return false;
}
-// Prints the names and full paths of all opened dynamic libraries
-// for current process
-void os::print_dll_info(outputStream * st) {
+int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
Dl_info dli;
- void *handle;
+ // Sanity check?
+ if (dladdr(CAST_FROM_FN_PTR(void *, os::get_loaded_modules_info), &dli) == 0 ||
+ dli.dli_fname == NULL) {
+ return 1;
+ }
+
+ void * handle = dlopen(dli.dli_fname, RTLD_LAZY);
+ if (handle == NULL) {
+ return 1;
+ }
+
Link_map *map;
- Link_map *p;
-
- st->print_cr("Dynamic libraries:"); st->flush();
-
- if (dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli) == 0 ||
- dli.dli_fname == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
- handle = dlopen(dli.dli_fname, RTLD_LAZY);
- if (handle == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
dlinfo(handle, RTLD_DI_LINKMAP, &map);
if (map == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
-
- while (map->l_prev != NULL)
+ dlclose(handle);
+ return 1;
+ }
+
+ while (map->l_prev != NULL) {
map = map->l_prev;
+ }
while (map != NULL) {
- st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name);
+ // Iterate through all map entries and call callback with fields of interest
+ if(callback(map->l_name, (address)map->l_addr, (address)0, param)) {
+ dlclose(handle);
+ return 1;
+ }
map = map->l_next;
}
dlclose(handle);
+ return 0;
+}
+
+int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
+ outputStream * out = (outputStream *) param;
+ out->print_cr(PTR_FORMAT " \t%s", base_address, name);
+ return 0;
+}
+
+void os::print_dll_info(outputStream * st) {
+ st->print_cr("Dynamic libraries:"); st->flush();
+ if (get_loaded_modules_info(_print_dll_info_cb, (void *)st)) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ }
}
// Loads .dll/.so and
--- a/hotspot/src/os/windows/vm/os_windows.cpp Tue Sep 02 21:27:08 2014 -0400
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Wed Sep 03 14:43:49 2014 +0200
@@ -1301,120 +1301,6 @@
}
#endif
-
-// Enumerate all modules for a given process ID
-//
-// Notice that Windows 95/98/Me and Windows NT/2000/XP have
-// different API for doing this. We use PSAPI.DLL on NT based
-// Windows and ToolHelp on 95/98/Me.
-
-// Callback function that is called by enumerate_modules() on
-// every DLL module.
-// Input parameters:
-// int pid,
-// char* module_file_name,
-// address module_base_addr,
-// unsigned module_size,
-// void* param
-typedef int (*EnumModulesCallbackFunc)(int, char *, address, unsigned, void *);
-
-// enumerate_modules for Windows NT, using PSAPI
-static int _enumerate_modules_winnt( int pid, EnumModulesCallbackFunc func, void * param)
-{
- HANDLE hProcess;
-
-# define MAX_NUM_MODULES 128
- HMODULE modules[MAX_NUM_MODULES];
- static char filename[MAX_PATH];
- int result = 0;
-
- if (!os::PSApiDll::PSApiAvailable()) {
- return 0;
- }
-
- hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
- FALSE, pid);
- if (hProcess == NULL) return 0;
-
- DWORD size_needed;
- if (!os::PSApiDll::EnumProcessModules(hProcess, modules,
- sizeof(modules), &size_needed)) {
- CloseHandle(hProcess);
- return 0;
- }
-
- // number of modules that are currently loaded
- int num_modules = size_needed / sizeof(HMODULE);
-
- for (int i = 0; i < MIN2(num_modules, MAX_NUM_MODULES); i++) {
- // Get Full pathname:
- if (!os::PSApiDll::GetModuleFileNameEx(hProcess, modules[i],
- filename, sizeof(filename))) {
- filename[0] = '\0';
- }
-
- MODULEINFO modinfo;
- if (!os::PSApiDll::GetModuleInformation(hProcess, modules[i],
- &modinfo, sizeof(modinfo))) {
- modinfo.lpBaseOfDll = NULL;
- modinfo.SizeOfImage = 0;
- }
-
- // Invoke callback function
- result = func(pid, filename, (address)modinfo.lpBaseOfDll,
- modinfo.SizeOfImage, param);
- if (result) break;
- }
-
- CloseHandle(hProcess);
- return result;
-}
-
-
-// enumerate_modules for Windows 95/98/ME, using TOOLHELP
-static int _enumerate_modules_windows( int pid, EnumModulesCallbackFunc func, void *param)
-{
- HANDLE hSnapShot;
- static MODULEENTRY32 modentry;
- int result = 0;
-
- if (!os::Kernel32Dll::HelpToolsAvailable()) {
- return 0;
- }
-
- // Get a handle to a Toolhelp snapshot of the system
- hSnapShot = os::Kernel32Dll::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
- if (hSnapShot == INVALID_HANDLE_VALUE) {
- return FALSE;
- }
-
- // iterate through all modules
- modentry.dwSize = sizeof(MODULEENTRY32);
- bool not_done = os::Kernel32Dll::Module32First( hSnapShot, &modentry ) != 0;
-
- while (not_done) {
- // invoke the callback
- result=func(pid, modentry.szExePath, (address)modentry.modBaseAddr,
- modentry.modBaseSize, param);
- if (result) break;
-
- modentry.dwSize = sizeof(MODULEENTRY32);
- not_done = os::Kernel32Dll::Module32Next( hSnapShot, &modentry ) != 0;
- }
-
- CloseHandle(hSnapShot);
- return result;
-}
-
-int enumerate_modules( int pid, EnumModulesCallbackFunc func, void * param )
-{
- // Get current process ID if caller doesn't provide it.
- if (!pid) pid = os::current_process_id();
-
- if (os::win32::is_nt()) return _enumerate_modules_winnt (pid, func, param);
- else return _enumerate_modules_windows(pid, func, param);
-}
-
struct _modinfo {
address addr;
char* full_path; // point to a char buffer
@@ -1422,13 +1308,13 @@
address base_addr;
};
-static int _locate_module_by_addr(int pid, char * mod_fname, address base_addr,
- unsigned size, void * param) {
+static int _locate_module_by_addr(const char * mod_fname, address base_addr,
+ address top_address, void * param) {
struct _modinfo *pmod = (struct _modinfo *)param;
if (!pmod) return -1;
- if (base_addr <= pmod->addr &&
- base_addr+size > pmod->addr) {
+ if (base_addr <= pmod->addr &&
+ top_address > pmod->addr) {
// if a buffer is provided, copy path name to the buffer
if (pmod->full_path) {
jio_snprintf(pmod->full_path, pmod->buflen, "%s", mod_fname);
@@ -1453,8 +1339,7 @@
mi.addr = addr;
mi.full_path = buf;
mi.buflen = buflen;
- int pid = os::current_process_id();
- if (enumerate_modules(pid, _locate_module_by_addr, (void *)&mi)) {
+ if (get_loaded_modules_info(_locate_module_by_addr, (void *)&mi)) {
// buf already contains path name
if (offset) *offset = addr - mi.base_addr;
return true;
@@ -1479,14 +1364,14 @@
}
// save the start and end address of jvm.dll into param[0] and param[1]
-static int _locate_jvm_dll(int pid, char* mod_fname, address base_addr,
- unsigned size, void * param) {
+static int _locate_jvm_dll(const char* mod_fname, address base_addr,
+ address top_address, void * param) {
if (!param) return -1;
- if (base_addr <= (address)_locate_jvm_dll &&
- base_addr+size > (address)_locate_jvm_dll) {
+ if (base_addr <= (address)_locate_jvm_dll &&
+ top_address > (address)_locate_jvm_dll) {
((address*)param)[0] = base_addr;
- ((address*)param)[1] = base_addr + size;
+ ((address*)param)[1] = top_address;
return 1;
}
return 0;
@@ -1497,8 +1382,7 @@
// check if addr is inside jvm.dll
bool os::address_is_in_vm(address addr) {
if (!vm_lib_location[0] || !vm_lib_location[1]) {
- int pid = os::current_process_id();
- if (!enumerate_modules(pid, _locate_jvm_dll, (void *)vm_lib_location)) {
+ if (!get_loaded_modules_info(_locate_jvm_dll, (void *)vm_lib_location)) {
assert(false, "Can't find jvm module.");
return false;
}
@@ -1508,14 +1392,13 @@
}
// print module info; param is outputStream*
-static int _print_module(int pid, char* fname, address base,
- unsigned size, void* param) {
+static int _print_module(const char* fname, address base_address,
+ address top_address, void* param) {
if (!param) return -1;
outputStream* st = (outputStream*)param;
- address end_addr = base + size;
- st->print(PTR_FORMAT " - " PTR_FORMAT " \t%s\n", base, end_addr, fname);
+ st->print(PTR_FORMAT " - " PTR_FORMAT " \t%s\n", base_address, top_address, fname);
return 0;
}
@@ -1644,11 +1527,60 @@
return NULL;
}
-
void os::print_dll_info(outputStream *st) {
- int pid = os::current_process_id();
st->print_cr("Dynamic libraries:");
- enumerate_modules(pid, _print_module, (void *)st);
+ get_loaded_modules_info(_print_module, (void *)st);
+}
+
+int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
+ HANDLE hProcess;
+
+# define MAX_NUM_MODULES 128
+ HMODULE modules[MAX_NUM_MODULES];
+ static char filename[MAX_PATH];
+ int result = 0;
+
+ if (!os::PSApiDll::PSApiAvailable()) {
+ return 0;
+ }
+
+ int pid = os::current_process_id();
+ hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
+ FALSE, pid);
+ if (hProcess == NULL) return 0;
+
+ DWORD size_needed;
+ if (!os::PSApiDll::EnumProcessModules(hProcess, modules,
+ sizeof(modules), &size_needed)) {
+ CloseHandle(hProcess);
+ return 0;
+ }
+
+ // number of modules that are currently loaded
+ int num_modules = size_needed / sizeof(HMODULE);
+
+ for (int i = 0; i < MIN2(num_modules, MAX_NUM_MODULES); i++) {
+ // Get Full pathname:
+ if (!os::PSApiDll::GetModuleFileNameEx(hProcess, modules[i],
+ filename, sizeof(filename))) {
+ filename[0] = '\0';
+ }
+
+ MODULEINFO modinfo;
+ if (!os::PSApiDll::GetModuleInformation(hProcess, modules[i],
+ &modinfo, sizeof(modinfo))) {
+ modinfo.lpBaseOfDll = NULL;
+ modinfo.SizeOfImage = 0;
+ }
+
+ // Invoke callback function
+ result = callback(filename, (address)modinfo.lpBaseOfDll,
+ (address)((u8)modinfo.lpBaseOfDll + (u8)modinfo.SizeOfImage), param);
+ if (result) break;
+ }
+
+ CloseHandle(hProcess);
+ return result;
}
void os::print_os_info_brief(outputStream* st) {
--- a/hotspot/src/share/vm/runtime/os.hpp Tue Sep 02 21:27:08 2014 -0400
+++ b/hotspot/src/share/vm/runtime/os.hpp Wed Sep 03 14:43:49 2014 +0200
@@ -557,6 +557,16 @@
// Unload library
static void dll_unload(void *lib);
+ // Callback for loaded module information
+ // Input parameters:
+ // char* module_file_name,
+ // address module_base_addr,
+ // address module_top_addr,
+ // void* param
+ typedef int (*LoadedModulesCallbackFunc)(const char *, address, address, void *);
+
+ static int get_loaded_modules_info(LoadedModulesCallbackFunc callback, void *param);
+
// Return the handle of this process
static void* get_default_process_handle();