]> sourceware.org Git - newlib-cygwin.git/commitdiff
* hookapi.cc (hook_or_detect_cygwin): Take additional handle
authorCorinna Vinschen <corinna@vinschen.de>
Tue, 25 Oct 2011 16:35:58 +0000 (16:35 +0000)
committerCorinna Vinschen <corinna@vinschen.de>
Tue, 25 Oct 2011 16:35:58 +0000 (16:35 +0000)
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.

winsup/cygwin/ChangeLog
winsup/cygwin/hookapi.cc
winsup/cygwin/spawn.cc
winsup/cygwin/winsup.h

index 20bb859e2164ec0414b89f47380ec9427fbeddee..2e2c194d0172107c936f762838ad77b25b4e1640 100644 (file)
@@ -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
index b82e4b4c5106c50bd85885921609de1ce7f41b17..8137b85d29597d36b95ca57faa539ae1aa8d0174 100644 (file)
@@ -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);
 
index 48d639a8a42b2eb4e7ec0ff71fba221cddbbb792..f9e1504b1a39b6e3498d3f8809133e23258fffc1 100644 (file)
@@ -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 ());
 
index e865cbc57234ffbd3dba4dd47496aab550d4054a..a7b82858058b9160e0653c745fdf4b81b8a8c67e 100644 (file)
@@ -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);
This page took 0.0431 seconds and 5 git commands to generate.