Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2011-08-17 00:08:34 +0400
committerCorinna Vinschen <corinna@vinschen.de>2011-08-17 00:08:34 +0400
commit833db5481f1f86745979d3ceda580c2d8fdd24a8 (patch)
treeb7aca64ec232f5fd51b5a4c84187b9fb10e8ce7e /winsup
parent9d3b795b47430b4518e5fafb6fb29a96d4bb8f0c (diff)
* dlfcn.cc (dlopen): Reimplement RTLD_NODELETE for Windows 2000 using
internal datastructures. Explain the code. * ntdll.h (struct _LDR_DATA_TABLE_ENTRY): Define. (struct _PEB_LDR_DATA): Define. (struct _PEB): Change PVOID LoaderData to PPEB_LDR_DATA Ldr. * fhandler_process.cc (format_process_maps): Call NtQueryVirtualMemory with valid return length pointer. Explain why.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog11
-rw-r--r--winsup/cygwin/dlfcn.cc27
-rw-r--r--winsup/cygwin/fhandler_process.cc8
-rw-r--r--winsup/cygwin/ntdll.h30
4 files changed, 67 insertions, 9 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 452d17c4d..315972e58 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,16 @@
2011-08-16 Corinna Vinschen <corinna@vinschen.de>
+ * dlfcn.cc (dlopen): Reimplement RTLD_NODELETE for Windows 2000 using
+ internal datastructures. Explain the code.
+ * ntdll.h (struct _LDR_DATA_TABLE_ENTRY): Define.
+ (struct _PEB_LDR_DATA): Define.
+ (struct _PEB): Change PVOID LoaderData to PPEB_LDR_DATA Ldr.
+
+ * fhandler_process.cc (format_process_maps): Call NtQueryVirtualMemory
+ with valid return length pointer. Explain why.
+
+2011-08-16 Corinna Vinschen <corinna@vinschen.de>
+
* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
2011-08-16 Corinna Vinschen <corinna@vinschen.de>
diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc
index 91ffc9a6c..fbcdfedfb 100644
--- a/winsup/cygwin/dlfcn.cc
+++ b/winsup/cygwin/dlfcn.cc
@@ -120,12 +120,27 @@ dlopen (const char *name, int flags)
(HMODULE *) &ret))
{
/* Windows 2000 is missing the GetModuleHandleEx call, so we
- just use a trick. Call LoadLibrary 10 times more if the
- RTLD_NODELETE flag has been specified. That makes it
- unlikely (but not impossible) that dlclose will actually
- free the library. */
- for (int i = 0; i < 10; ++i)
- LoadLibraryW (path);
+ use a non-documented way to set the DLL to "don't free".
+ This is how it works: Fetch the Windows Loader data from
+ the PEB. Iterate backwards through the list of loaded
+ DLLs and compare the DllBase address with the address
+ returned by LoadLibrary. If they are equal we found the
+ right entry. Now set the LoadCount to -1, which is the
+ marker for a DLL which should never be free'd. */
+ PPEB_LDR_DATA ldr = NtCurrentTeb ()->Peb->Ldr;
+
+ for (PLDR_DATA_TABLE_ENTRY entry = (PLDR_DATA_TABLE_ENTRY)
+ ldr->InLoadOrderModuleList.Blink;
+ entry && entry->DllBase;
+ entry = (PLDR_DATA_TABLE_ENTRY)
+ entry->InLoadOrderLinks.Blink)
+ {
+ if (entry->DllBase == ret)
+ {
+ entry->LoadCount = (WORD) -1;
+ break;
+ }
+ }
}
}
diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc
index eb36d9d56..36270d1ba 100644
--- a/winsup/cygwin/fhandler_process.cc
+++ b/winsup/cygwin/fhandler_process.cc
@@ -960,12 +960,16 @@ format_process_maps (void *data, char *&destbuf)
// if a new allocation, figure out what kind it is
if (newbase && !last_pass && mb.State != MEM_FREE)
{
+ /* If the return length pointer is missing, NtQueryVirtualMemory
+ returns with STATUS_ACCESS_VIOLATION on Windows 2000. */
+ ULONG ret_len = 0;
+
st.st_dev = 0;
st.st_ino = 0;
if ((mb.Type & (MEM_MAPPED | MEM_IMAGE))
- && NT_SUCCESS (NtQueryVirtualMemory (proc, cur.abase,
+ && NT_SUCCESS (status = NtQueryVirtualMemory (proc, cur.abase,
MemorySectionName,
- msi, 65536, NULL)))
+ msi, 65536, &ret_len)))
{
PWCHAR dosname =
drive_maps.fixup_if_match (msi->SectionFileName.Buffer);
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index c5b3597a7..ce1a87a34 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -579,6 +579,34 @@ typedef struct _KERNEL_USER_TIMES
LARGE_INTEGER UserTime;
} KERNEL_USER_TIMES, *PKERNEL_USER_TIMES;
+typedef struct _LDR_DATA_TABLE_ENTRY
+{
+ LIST_ENTRY InLoadOrderLinks;
+ LIST_ENTRY InMemoryOrderLinks;
+ LIST_ENTRY InInitializationOrderLinks;
+ PVOID DllBase;
+ PVOID EntryPoint;
+ ULONG SizeOfImage;
+ UNICODE_STRING FullDllName;
+ UNICODE_STRING BaseDllName;
+ ULONG Flags;
+ WORD LoadCount;
+ /* More follows. Left out since it's just not used. The aforementioned
+ part of the structure is stable from at least NT4 up to Windows 7,
+ including WOW64. */
+} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
+
+typedef struct _PEB_LDR_DATA
+{
+ ULONG Length;
+ UCHAR Initialized;
+ PVOID SsHandle;
+ LIST_ENTRY InLoadOrderModuleList;
+ LIST_ENTRY InMemoryOrderModuleList;
+ LIST_ENTRY InInitializationOrderModuleList;
+ PVOID EntryInProgress;
+} PEB_LDR_DATA, *PPEB_LDR_DATA;
+
typedef struct _RTL_USER_PROCESS_PARAMETERS
{
ULONG AllocationSize;
@@ -616,7 +644,7 @@ typedef struct _PEB
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[9];
- PVOID LoaderData;
+ PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved3[4];
PVOID ProcessHeap;