8056242: Add function to return structured information about loaded libraries
Return structured information about loaded libraries. Reviewed-by: sla, dsamersoff
This commit is contained in:
parent
88eb5fb4d6
commit
07001d0332
@ -1644,8 +1644,20 @@ static bool _print_ascii_file(const char* filename, outputStream* st) {
|
||||
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 @@ void os::print_dll_info(outputStream *st) {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -2120,6 +2120,40 @@ void os::print_dll_info(outputStream *st) {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -1722,41 +1722,54 @@ bool os::dll_address_to_library_name(address addr, char* buf,
|
||||
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;
|
||||
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 ||
|
||||
// Sanity check?
|
||||
if (dladdr(CAST_FROM_FN_PTR(void *, os::get_loaded_modules_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);
|
||||
|
||||
void * handle = dlopen(dli.dli_fname, RTLD_LAZY);
|
||||
if (handle == NULL) {
|
||||
st->print_cr("Error: Cannot print dynamic libraries.");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Link_map *map;
|
||||
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)
|
||||
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
|
||||
|
@ -1301,120 +1301,6 @@ static bool _addr_in_ntdll( address addr )
|
||||
}
|
||||
#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 @@ struct _modinfo {
|
||||
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 @@ bool os::dll_address_to_library_name(address addr, char* buf,
|
||||
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 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||
}
|
||||
|
||||
// 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 @@ address vm_lib_location[2]; // start and end address of jvm.dll
|
||||
// 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 @@ bool os::address_is_in_vm(address addr) {
|
||||
}
|
||||
|
||||
// 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 @@ void * os::dll_load(const char *name, char *ebuf, int ebuflen)
|
||||
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) {
|
||||
|
@ -557,6 +557,16 @@ class os: AllStatic {
|
||||
// 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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user