This is the mail archive of the cygwin-patches mailing list for the Cygwin project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
>From discussions with Bruno Haible about the slowness of full relocation support in libintl and libiconv, he said: > - The Cygwin API only allows me to get _all_ file names behind all > addresses across the entire current process, and this is slow. (talking about parsing /proc/self/maps) > - It would be useful to have a Cygwin API that gives me the file > file name behind one particular address in the current process. > This should not be that slow. This patch is a proof of concept for the latter. Naturally, it needs additional work -- updating version.h, real changelog entries, documentation somewhere, etc. But...is it worth the effort? Is something like this likely to be accepted? I've also attached a test program. To compile it (using g++), you need to ensure that the updated sys/cygwin.h is in the search path. It prints the contents of /proc/self/maps, and then you can type any (hex) memory address and it should report the func's return value, and the correct path to the associated module. CTRL-D to exit. 61000020 0x61000020 (0) /usr/bin/cygwin1.dll 00020000 0x00020000 (1) The call signature is: unsigned long cygwin_internal (CW_GET_MODULE_PATH_FOR_ADDR, uintptr_t addr, PWCHAR buf, size_t buflen); -- Chuck
Index: external.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/external.cc,v retrieving revision 1.124 diff -u -p -r1.124 external.cc --- external.cc 5 Oct 2011 12:27:36 -0000 1.124 +++ external.cc 13 Oct 2011 06:50:43 -0000 @@ -197,6 +197,9 @@ exit_process (UINT status, bool useTermi ExitProcess (status); } +/* Defined in fhandler_process.cc */ +extern int +get_module_path_for_addr (uintptr_t addr, PWCHAR dest, size_t dlen); extern "C" unsigned long cygwin_internal (cygwin_getinfo_types t, ...) @@ -528,6 +531,15 @@ cygwin_internal (cygwin_getinfo_types t, } break; + case CW_GET_MODULE_PATH_FOR_ADDR: + { + uintptr_t addr = va_arg (arg, uintptr_t); + PWCHAR dest = va_arg (arg, PWCHAR); + size_t dlen = va_arg (arg, size_t); + res = get_module_path_for_addr (addr, dest, dlen); + } + break; + default: set_errno (ENOSYS); } Index: fhandler_process.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/fhandler_process.cc,v retrieving revision 1.110 diff -u -p -r1.110 fhandler_process.cc --- fhandler_process.cc 10 Oct 2011 18:59:56 -0000 1.110 +++ fhandler_process.cc 13 Oct 2011 06:50:44 -0000 @@ -1441,3 +1441,97 @@ out: CloseHandle (hProcess); return res; } + +/* Helper function for cygwin_internal. Implemented here, rather + * than in external.cc, so as to reuse dos_drive_mappings, + * heap_info, and thread_info helper classes. Returns 0 on success, + * nonzero otherwise. Borrows heavily from format_process_maps(). + */ +int +get_module_path_for_addr (uintptr_t addr, PWCHAR dest, size_t dlen) +{ + int rval = -1; + DWORD wpid = GetCurrentProcessId (); + HANDLE proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, wpid); + if (!proc) + return rval; + + NTSTATUS status; + PROCESS_BASIC_INFORMATION pbi; + + memset (&pbi, 0, sizeof (pbi)); + status = NtQueryInformationProcess (proc, ProcessBasicInformation, + &pbi, sizeof pbi, NULL); + if (!NT_SUCCESS (status)) + { + CloseHandle (proc); + return rval; + } + PPEB peb = pbi.PebBaseAddress; + + /* myself is in the same spot in every process, so is the pointer to the + procinfo. But make sure the destructor doesn't try to release procinfo! */ + pinfo proc_pinfo; + if (ReadProcessMemory (proc, &myself, &proc_pinfo, sizeof proc_pinfo, NULL)) + proc_pinfo.preserve (); + /* The heap info on the cygheap is also in the same spot in each process + because the cygheap is located at the same address. */ + user_heap_info user_heap; + ReadProcessMemory (proc, &cygheap->user_heap, &user_heap, + sizeof user_heap, NULL); + + MEMORY_BASIC_INFORMATION mb; + VirtualQueryEx (proc, (const void*)addr, &mb, sizeof mb); + + dos_drive_mappings drive_maps; + heap_info heaps (wpid); + thread_info threads (wpid, proc); + + tmp_pathbuf tp; + PMEMORY_SECTION_NAME msi = (PMEMORY_SECTION_NAME) tp.w_get (); + char *posix_modname = tp.c_get(); + posix_modname[0] = '\0'; + /* If the return length pointer is missing, NtQueryVirtualMemory + * returns with STATUS_ACCESS_VIOLATION on Windows 2000. */ + ULONG ret_len = 0; + + if ((mb.State != MEM_FREE) + && (mb.Type & (MEM_MAPPED | MEM_IMAGE)) + && NT_SUCCESS (status = NtQueryVirtualMemory (proc, mb.AllocationBase, + MemorySectionName, + msi, 65536, &ret_len))) + { + PWCHAR dosname = + drive_maps.fixup_if_match (msi->SectionFileName.Buffer); + if (mount_table->conv_to_posix_path (dosname, + posix_modname, 0)) + sys_wcstombs (posix_modname, NT_MAX_PATH, dosname); + } + else if (!threads.fill_if_match ((char*)mb.AllocationBase, mb.Type, + posix_modname) + && !heaps.fill_if_match ((char*)mb.AllocationBase, mb.Type, + posix_modname)) + { + if (mb.AllocationBase == (char *) peb) + strcpy (posix_modname, "[peb]"); + else if (mb.AllocationBase == (char *) &SharedUserData) + strcpy (posix_modname, "[shared-user-data]"); + else if (mb.AllocationBase == (char *) cygwin_shared) + strcpy (posix_modname, "[cygwin-shared]"); + else if (mb.AllocationBase == (char *) user_shared) + strcpy (posix_modname, "[cygwin-user-shared]"); + else if (mb.AllocationBase == (char *) *proc_pinfo) + strcpy (posix_modname, "[procinfo]"); + else if (mb.AllocationBase == user_heap.base) + strcpy (posix_modname, "[heap]"); + else + posix_modname[0] = 0; + } + + CloseHandle (proc); + rval = (posix_modname[0] == 0); + sys_mbstowcs (dest, dlen, posix_modname, NT_MAX_PATH); + return rval; +} + Index: include/sys/cygwin.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/include/sys/cygwin.h,v retrieving revision 1.97 diff -u -p -r1.97 cygwin.h --- include/sys/cygwin.h 7 Oct 2011 13:49:17 -0000 1.97 +++ include/sys/cygwin.h 13 Oct 2011 06:50:44 -0000 @@ -135,7 +135,8 @@ typedef enum CW_CVT_MNT_OPTS, CW_LST_MNT_OPTS, CW_STRERROR, - CW_CVT_ENV_TO_WINENV + CW_CVT_ENV_TO_WINENV, + CW_GET_MODULE_PATH_FOR_ADDR } cygwin_getinfo_types; #define CW_LOCK_PINFO CW_LOCK_PINFO @@ -183,6 +184,7 @@ typedef enum #define CW_LST_MNT_OPTS CW_LST_MNT_OPTS #define CW_STRERROR CW_STRERROR #define CW_CVT_ENV_TO_WINENV CW_CVT_ENV_TO_WINENV +#define CW_GET_MODULE_PATH_FOR_ADDR CW_GET_MODULE_PATH_FOR_ADDR /* Token type for CW_SET_EXTERNAL_TOKEN */ enum
Attachment:
test-get-module-path-for-addr.cc
Description: Text document
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |