diff options
Diffstat (limited to 'winsup/cygwin/hookapi.cc')
-rw-r--r-- | winsup/cygwin/hookapi.cc | 127 |
1 files changed, 20 insertions, 107 deletions
diff --git a/winsup/cygwin/hookapi.cc b/winsup/cygwin/hookapi.cc index 83e9f498a..8137b85d2 100644 --- a/winsup/cygwin/hookapi.cc +++ b/winsup/cygwin/hookapi.cc @@ -1,6 +1,6 @@ /* hookapi.cc - Copyright 2005, 2006, 2007, 2008, 2011, 2012 Red Hat, Inc. + Copyright 2005, 2006, 2007, 2008, 2011 Red Hat, Inc. This file is part of Cygwin. @@ -49,18 +49,14 @@ PEHeaderFromHModule (HMODULE hModule) } static long -rvadelta (PIMAGE_NT_HEADERS pnt, DWORD import_rva, DWORD &max_size) +rvadelta (PIMAGE_NT_HEADERS pnt, DWORD import_rva) { PIMAGE_SECTION_HEADER section = (PIMAGE_SECTION_HEADER) (pnt + 1); for (int i = 0; i < pnt->FileHeader.NumberOfSections; i++) if (section[i].VirtualAddress <= import_rva && (section[i].VirtualAddress + section[i].Misc.VirtualSize) > import_rva) // if (ascii_strncasematch ((char *) section[i].Name, ".idata", IMAGE_SIZEOF_SHORT_NAME)) - { - max_size = section[i].SizeOfRawData - - (import_rva - section[i].VirtualAddress); - return section[i].VirtualAddress - section[i].PointerToRawData; - } + return section[i].VirtualAddress - section[i].PointerToRawData; return -1; } @@ -165,8 +161,7 @@ makename (const char *name, char *&buf, int& i, int inc) /* Find first missing dll in a given executable. FIXME: This is not foolproof since it doesn't look for dlls in the same directory as the given executable, like Windows. Instead it - searches for dlls in the context of the current executable. - It also only finds direct dependencies, not indirect ones. */ + searches for dlls in the context of the current executable. */ const char * find_first_notloaded_dll (path_conv& pc) { @@ -177,7 +172,6 @@ find_first_notloaded_dll (path_conv& pc) IO_STATUS_BLOCK io; HANDLE h; NTSTATUS status; - LARGE_INTEGER size; status = NtOpenFile (&h, SYNCHRONIZE | GENERIC_READ, pc.get_object_attr (attr, sec_none_nih), @@ -187,27 +181,13 @@ find_first_notloaded_dll (path_conv& pc) | FILE_NON_DIRECTORY_FILE); if (!NT_SUCCESS (status)) goto out; - /* Just as in hook_or_detect_cygwin below, we have to take big executables - into account. That means, we must not try to map the entire file, since - there's no guarantee that the current process has enough VM in one block - left for this mapping. The offset computation below ignores very big - executables for now. In theory, since the import RVA table appears to - be more or less at the end of the data section, independent of the used - compiler, that shouldn't matter. */ - if (!GetFileSizeEx (h, &size)) - { - NtClose (h); - goto out; - } - if (size.QuadPart > wincap.allocation_granularity ()) - size.LowPart = wincap.allocation_granularity (); + hc = CreateFileMapping (h, &sec_none_nih, PAGE_READONLY, 0, 0, NULL); NtClose (h); if (!hc) goto out; - hm = (HMODULE) MapViewOfFile(hc, FILE_MAP_READ, 0, 0, size.LowPart); - if (!hm) - goto out; + hm = (HMODULE) MapViewOfFile(hc, FILE_MAP_READ, 0, 0, 0); + CloseHandle (hc); PIMAGE_NT_HEADERS pExeNTHdr; pExeNTHdr = PEHeaderFromHModule (hm); @@ -215,55 +195,32 @@ find_first_notloaded_dll (path_conv& pc) if (pExeNTHdr) { DWORD importRVA; - DWORD importRVAMaxSize; importRVA = pExeNTHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; if (importRVA) { - long delta = rvadelta (pExeNTHdr, importRVA, importRVAMaxSize); - if (delta < 0) - goto out; - importRVA -= delta; - - DWORD offset = 0; - HMODULE map = NULL; - if (importRVA + importRVAMaxSize > wincap.allocation_granularity ()) - { - offset = rounddown (importRVA, wincap.allocation_granularity ()); - DWORD size = importRVA - offset + importRVAMaxSize; - map = (HMODULE) MapViewOfFile (hc, FILE_MAP_READ, 0, - offset, size); - if (!map) - goto out; - } + long delta = rvadelta (pExeNTHdr, importRVA); // Convert imports RVA to a usable pointer PIMAGE_IMPORT_DESCRIPTOR pdfirst; - pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, map ?: hm, - importRVA - offset); + pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, hm, importRVA - delta); // Iterate through each import descriptor, and redirect if appropriate for (PIMAGE_IMPORT_DESCRIPTOR pd = pdfirst; pd->FirstThunk; pd++) { - const char *lib = rva (PSTR, map ?: hm, - pd->Name - delta - offset); + const char *lib = rva (PSTR, hm, pd->Name - delta); if (!LoadLibraryEx (lib, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE)) { - static char buf[MAX_PATH]; - strlcpy (buf, lib, MAX_PATH); - res = buf; + static char buf[NT_MAX_PATH]; + res = strcpy (buf, lib); } } - if (map) - UnmapViewOfFile (map); } } out: if (hm) UnmapViewOfFile (hm); - if (hc) - CloseHandle (hc); return res; } @@ -276,11 +233,7 @@ hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys, HANDLE h) PIMAGE_NT_HEADERS pExeNTHdr = PEHeaderFromHModule (hm); if (!pExeNTHdr) - return NULL; - - /* FIXME: This code has to be made 64 bit capable. */ - if (pExeNTHdr->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) - return NULL; + return false; subsys = pExeNTHdr->OptionalHeader.Subsystem; @@ -289,19 +242,18 @@ hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys, HANDLE h) DWORD importRVASize = pExeNTHdr->OptionalHeader.DataDirectory [IMAGE_DIRECTORY_ENTRY_IMPORT].Size; if (!importRVA) - return NULL; + return false; - DWORD importRVAMaxSize; - long delta = fn ? 0 : rvadelta (pExeNTHdr, importRVA, importRVAMaxSize); + long delta = fn ? 0 : rvadelta (pExeNTHdr, importRVA); if (delta < 0) - return NULL; + return false; importRVA -= delta; // Convert imports RVA to a usable pointer PIMAGE_IMPORT_DESCRIPTOR pdfirst; char *map = NULL; DWORD offset = 0; - if (h && importRVA + importRVAMaxSize > wincap.allocation_granularity ()) + 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 @@ -309,46 +261,11 @@ hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys, HANDLE h) 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 ()); - /* But that's not all, unfortunately. Apparently there's a difference - between the importRVASize of applications built with gcc and those - built with Visual Studio. When built with gcc, importRVASize contains - the size of the import RVA table plus the size of the referenced - string table with the DLL names. When built with VS, it only contains - the size of the naked import RVA table. The following code handles - the situation. importRVAMaxSize contains the size of the remainder - of the section. If the difference between importRVAMaxSize and - importRVASize is less than 64K, we just use importRVAMaxSize to - compute the size of the memory map. Otherwise the executable may be - very big. In that case we only map the import RVA table and ... */ - DWORD size = importRVA - offset - + ((importRVAMaxSize - importRVASize - <= wincap.allocation_granularity ()) - ? importRVAMaxSize : importRVASize); + DWORD size = importRVA - offset + importRVASize; map = (char *) MapViewOfFile (h, FILE_MAP_READ, 0, offset, size); if (!map) - return NULL; + return false; pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, map, importRVA - offset); - /* ... carefully check the required size to fit the string table into - the map as well. Allow NAME_MAX bytes for the DLL name, but don't - go beyond the remainder of the section. */ - if (importRVAMaxSize - importRVASize > wincap.allocation_granularity ()) - { - DWORD newsize = size; - for (PIMAGE_IMPORT_DESCRIPTOR pd = pdfirst; pd->FirstThunk; pd++) - if (pd->Name - delta - offset + (NAME_MAX + 1) > newsize) - newsize = pd->Name - delta - offset + (NAME_MAX + 1); - if (newsize > size) - { - if (newsize > importRVA - offset + importRVAMaxSize) - newsize = importRVA - offset + importRVAMaxSize; - UnmapViewOfFile (map); - map = (char *) MapViewOfFile (h, FILE_MAP_READ, 0, offset, - newsize); - if (!map) - return NULL; - pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, map, importRVA - offset); - } - } } else pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, hm, importRVA); @@ -356,9 +273,7 @@ hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys, HANDLE h) function_hook fh; fh.origfn = NULL; fh.hookfn = fn; - char *buf = NULL; - if (fn) - buf = (char *) alloca (strlen (name) + sizeof ("_64")); + char *buf = (char *) alloca (strlen (name) + sizeof ("_64")); int i = 0; // Iterate through each import descriptor, and redirect if appropriate for (PIMAGE_IMPORT_DESCRIPTOR pd = pdfirst; pd->FirstThunk; pd++) @@ -381,8 +296,6 @@ hook_or_detect_cygwin (const char *name, const void *fn, WORD& subsys, HANDLE h) if (map) UnmapViewOfFile (map); - if (!fn) - return NULL; while (!fh.origfn && (fh.name = makename (name, buf, i, -1))) get_export (fh); |