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-10-25 20:35:58 +0400
committerCorinna Vinschen <corinna@vinschen.de>2011-10-25 20:35:58 +0400
commitbe2280986de5339bca3d648ec0e7538541dcd674 (patch)
treed31ee4917ee5b00f024ce32b89a065c8204f85b6 /winsup
parent4c28f4392a52852d34acd04cc698047bc21375ea (diff)
* hookapi.cc (hook_or_detect_cygwin): Take additional handle
to a file mapping as parameter. If this handle is not NULL, create another file mapping for the IAT. * spawn.cc (av::fixup): Only map the first 64K of an image and keep the mapping handle to use as argument to hook_or_detect_cygwin. * winsup.h (hook_or_detect_cygwin): Add mapping handle as default parameter in declaration.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog10
-rw-r--r--winsup/cygwin/hookapi.cc38
-rw-r--r--winsup/cygwin/spawn.cc30
-rw-r--r--winsup/cygwin/winsup.h2
4 files changed, 69 insertions, 11 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 20bb859e2..2e2c194d0 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,13 @@
+2011-10-25 Corinna Vinschen <corinna@vinschen.de>
+
+ * hookapi.cc (hook_or_detect_cygwin): Take additional handle
+ to a file mapping as parameter. If this handle is not NULL,
+ create another file mapping for the IAT.
+ * spawn.cc (av::fixup): Only map the first 64K of an image and
+ keep the mapping handle to use as argument to hook_or_detect_cygwin.
+ * winsup.h (hook_or_detect_cygwin): Add mapping handle as default
+ parameter in declaration.
+
2011-10-24 Corinna Vinschen <corinna@vinschen.de>
* syscalls.cc (unlink_nt): Fix a bug which overwrites the NT status
diff --git a/winsup/cygwin/hookapi.cc b/winsup/cygwin/hookapi.cc
index b82e4b4c5..8137b85d2 100644
--- a/winsup/cygwin/hookapi.cc
+++ b/winsup/cygwin/hookapi.cc
@@ -10,6 +10,7 @@ details. */
#include "winsup.h"
#include <stdlib.h>
+#include <sys/param.h>
#include "ntdll.h"
#include "cygerrno.h"
#include "security.h"
@@ -226,7 +227,7 @@ out:
// Top level routine to find the EXE's imports and redirect them
void *
-hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys)
+hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys, HANDLE h)
{
HMODULE hm = fn ? GetModuleHandle (NULL) : (HMODULE) name;
PIMAGE_NT_HEADERS pExeNTHdr = PEHeaderFromHModule (hm);
@@ -238,15 +239,36 @@ hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys)
DWORD importRVA = pExeNTHdr->OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
+ DWORD importRVASize = pExeNTHdr->OptionalHeader.DataDirectory
+ [IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
if (!importRVA)
return false;
long delta = fn ? 0 : rvadelta (pExeNTHdr, importRVA);
if (delta < 0)
return false;
+ importRVA -= delta;
// Convert imports RVA to a usable pointer
- PIMAGE_IMPORT_DESCRIPTOR pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, hm, importRVA - delta);
+ PIMAGE_IMPORT_DESCRIPTOR pdfirst;
+ char *map = NULL;
+ DWORD offset = 0;
+ if (h && importRVA + importRVASize > wincap.allocation_granularity ())
+ {
+ /* If h is not NULL, the calling function only mapped at most the first
+ 64K of the image. The IAT is usually at the end of the image, so
+ what we do here is to map the IAT into our address space if it doesn't
+ reside in the first 64K anyway. The offset must be a multiple of the
+ allocation granularity, though, so we have to map a bit more. */
+ offset = rounddown (importRVA, wincap.allocation_granularity ());
+ DWORD size = importRVA - offset + importRVASize;
+ map = (char *) MapViewOfFile (h, FILE_MAP_READ, 0, offset, size);
+ if (!map)
+ return false;
+ pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, map, importRVA - offset);
+ }
+ else
+ pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, hm, importRVA);
function_hook fh;
fh.origfn = NULL;
@@ -256,10 +278,15 @@ hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys)
// Iterate through each import descriptor, and redirect if appropriate
for (PIMAGE_IMPORT_DESCRIPTOR pd = pdfirst; pd->FirstThunk; pd++)
{
- if (!ascii_strcasematch (rva (PSTR, hm, pd->Name - delta), "cygwin1.dll"))
+ if (!ascii_strcasematch (rva (PSTR, map ?: (char *) hm,
+ pd->Name - delta - offset), "cygwin1.dll"))
continue;
if (!fn)
- return (void *) "found it"; // just checking if executable used cygwin1.dll
+ {
+ if (map)
+ UnmapViewOfFile (map);
+ return (void *) "found it"; // just checking if executable used cygwin1.dll
+ }
i = -1;
while (!fh.origfn && (fh.name = makename (name, buf, i, 1)))
RedirectIAT (fh, pd, hm);
@@ -267,6 +294,9 @@ hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys)
break;
}
+ if (map)
+ UnmapViewOfFile (map);
+
while (!fh.origfn && (fh.name = makename (name, buf, i, -1)))
get_export (fh);
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 48d639a8a..f9e1504b1 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -1059,6 +1059,7 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext,
IO_STATUS_BLOCK io;
HANDLE h;
NTSTATUS status;
+ LARGE_INTEGER size;
status = NtOpenFile (&h, SYNCHRONIZE | GENERIC_READ,
real_path.get_object_attr (attr, sec_none_nih),
@@ -1069,7 +1070,7 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext,
if (!NT_SUCCESS (status))
{
/* File is not readable? Doesn't mean it's not executable.
- Test for executablility and if so, just assume the file is
+ Test for executability and if so, just assume the file is
a cygwin executable and go ahead. */
if (status == STATUS_ACCESS_DENIED && real_path.has_acls ()
&& check_file_access (real_path, X_OK, true) == 0)
@@ -1079,8 +1080,16 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext,
}
goto err;
}
+ if (!GetFileSizeEx (h, &size))
+ {
+ NtClose (h);
+ goto err;
+ }
+ if (size.QuadPart > wincap.allocation_granularity ())
+ size.LowPart = wincap.allocation_granularity ();
- HANDLE hm = CreateFileMapping (h, &sec_none_nih, PAGE_READONLY, 0, 0, NULL);
+ HANDLE hm = CreateFileMapping (h, &sec_none_nih, PAGE_READONLY,
+ 0, 0, NULL);
NtClose (h);
if (!hm)
{
@@ -1092,16 +1101,22 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext,
}
goto err;
}
- buf = (char *) MapViewOfFile(hm, FILE_MAP_READ, 0, 0, 0);
- CloseHandle (hm);
+ /* Try to map the first 64K of the image. That's enough for the local
+ tests, and it's enough for hook_or_detect_cygwin to compute the IAT
+ address. */
+ buf = (char *) MapViewOfFile (hm, FILE_MAP_READ, 0, 0, size.LowPart);
if (!buf)
- goto err;
+ {
+ CloseHandle (hm);
+ goto err;
+ }
{
myfault efault;
if (efault.faulted ())
{
UnmapViewOfFile (buf);
+ CloseHandle (hm);
real_path.set_cygexec (false);
break;
}
@@ -1111,13 +1126,16 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext,
unsigned off = (unsigned char) buf[0x18] | (((unsigned char) buf[0x19]) << 8);
win16_exe = off < sizeof (IMAGE_DOS_HEADER);
if (!win16_exe)
- real_path.set_cygexec (!!hook_or_detect_cygwin (buf, NULL, subsys));
+ real_path.set_cygexec (!!hook_or_detect_cygwin (buf, NULL,
+ subsys, hm));
else
real_path.set_cygexec (false);
UnmapViewOfFile (buf);
+ CloseHandle (hm);
break;
}
}
+ CloseHandle (hm);
debug_printf ("%s is possibly a script", real_path.get_win32 ());
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index e865cbc57..a7b828580 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -216,7 +216,7 @@ __ino64_t __stdcall hash_path_name (__ino64_t hash, PCWSTR name) __attribute__ (
__ino64_t __stdcall hash_path_name (__ino64_t hash, const char *name) __attribute__ ((regparm(2)));
void __stdcall nofinalslash (const char *src, char *dst) __attribute__ ((regparm(2)));
-void *hook_or_detect_cygwin (const char *, const void *, WORD&) __attribute__ ((regparm (3)));
+void *hook_or_detect_cygwin (const char *, const void *, WORD&, HANDLE h = NULL) __attribute__ ((regparm (3)));
/* Time related */
void __stdcall totimeval (struct timeval *, FILETIME *, int, int);