* 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.
This commit is contained in:
Corinna Vinschen 2011-08-16 20:08:34 +00:00
parent 9d3b795b47
commit 833db5481f
4 changed files with 67 additions and 9 deletions

View File

@ -1,3 +1,14 @@
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> 2011-08-16 Corinna Vinschen <corinna@vinschen.de>
* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump. * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.

View File

@ -120,12 +120,27 @@ dlopen (const char *name, int flags)
(HMODULE *) &ret)) (HMODULE *) &ret))
{ {
/* Windows 2000 is missing the GetModuleHandleEx call, so we /* Windows 2000 is missing the GetModuleHandleEx call, so we
just use a trick. Call LoadLibrary 10 times more if the use a non-documented way to set the DLL to "don't free".
RTLD_NODELETE flag has been specified. That makes it This is how it works: Fetch the Windows Loader data from
unlikely (but not impossible) that dlclose will actually the PEB. Iterate backwards through the list of loaded
free the library. */ DLLs and compare the DllBase address with the address
for (int i = 0; i < 10; ++i) returned by LoadLibrary. If they are equal we found the
LoadLibraryW (path); 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;
}
}
} }
} }

View File

@ -960,12 +960,16 @@ format_process_maps (void *data, char *&destbuf)
// if a new allocation, figure out what kind it is // if a new allocation, figure out what kind it is
if (newbase && !last_pass && mb.State != MEM_FREE) 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_dev = 0;
st.st_ino = 0; st.st_ino = 0;
if ((mb.Type & (MEM_MAPPED | MEM_IMAGE)) if ((mb.Type & (MEM_MAPPED | MEM_IMAGE))
&& NT_SUCCESS (NtQueryVirtualMemory (proc, cur.abase, && NT_SUCCESS (status = NtQueryVirtualMemory (proc, cur.abase,
MemorySectionName, MemorySectionName,
msi, 65536, NULL))) msi, 65536, &ret_len)))
{ {
PWCHAR dosname = PWCHAR dosname =
drive_maps.fixup_if_match (msi->SectionFileName.Buffer); drive_maps.fixup_if_match (msi->SectionFileName.Buffer);

View File

@ -579,6 +579,34 @@ typedef struct _KERNEL_USER_TIMES
LARGE_INTEGER UserTime; LARGE_INTEGER UserTime;
} KERNEL_USER_TIMES, *PKERNEL_USER_TIMES; } 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 typedef struct _RTL_USER_PROCESS_PARAMETERS
{ {
ULONG AllocationSize; ULONG AllocationSize;
@ -616,7 +644,7 @@ typedef struct _PEB
BYTE Reserved1[2]; BYTE Reserved1[2];
BYTE BeingDebugged; BYTE BeingDebugged;
BYTE Reserved2[9]; BYTE Reserved2[9];
PVOID LoaderData; PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters; PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
BYTE Reserved3[4]; BYTE Reserved3[4];
PVOID ProcessHeap; PVOID ProcessHeap;