# HG changeset patch # User sla # Date 1409748229 -7200 # Node ID e399effe36f95d2d015d40d029396254be262412 # Parent 72da4c813e442bdb9cf9f905937fa3f0a923b8ad 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 diff -r 72da4c813e44 -r e399effe36f9 hotspot/src/os/bsd/vm/os_bsd.cpp --- 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 } diff -r 72da4c813e44 -r e399effe36f9 hotspot/src/os/linux/vm/os_linux.cpp --- 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); diff -r 72da4c813e44 -r e399effe36f9 hotspot/src/os/solaris/vm/os_solaris.cpp --- 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 diff -r 72da4c813e44 -r e399effe36f9 hotspot/src/os/windows/vm/os_windows.cpp --- 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) { diff -r 72da4c813e44 -r e399effe36f9 hotspot/src/share/vm/runtime/os.hpp --- 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();