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:
authorChristopher Faylor <me@cgf.cx>2008-03-27 04:50:40 +0300
committerChristopher Faylor <me@cgf.cx>2008-03-27 04:50:40 +0300
commit93d606f60aed779c555017828656c8a4e3c9c6a9 (patch)
treea1064ee801fa9606f9c06a4dc7f03f79db0314d9 /winsup
parent73de02f44b83eeccdacf7b803cc37074660f75b2 (diff)
* hookapi.cc (find_first_notloaded_dll): New function.
* pinfo.cc (status_exit): New function. Issue message when dll not found. Use find_first_notloaded_dll to find a nonexistent dll. (pinfo::maybe_set_exit_code_from_windows): Call status_exit when exit code >= 0xc0000000UL. * sigproc.cc (child_info::proc_retry): Return exit code when STATUS_DLL_NOT_FOUND. * spawn.cc (spawn_guts): Minor cleanup. * syscalls.cc (close_all_files): Don't actually close stderr filehandle. Just make it noninheritable. * winsup.h (find_first_notloaded_dll): Declare new function. * ntdll.h: Add several missing NTSTATUS defines.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog18
-rw-r--r--winsup/cygwin/dtable.h2
-rw-r--r--winsup/cygwin/exceptions.cc2
-rw-r--r--winsup/cygwin/hookapi.cc79
-rw-r--r--winsup/cygwin/ntdll.h6
-rw-r--r--winsup/cygwin/pinfo.cc30
-rw-r--r--winsup/cygwin/pinfo.h2
-rw-r--r--winsup/cygwin/sigproc.cc3
-rw-r--r--winsup/cygwin/spawn.cc7
-rw-r--r--winsup/cygwin/syscalls.cc7
-rw-r--r--winsup/cygwin/winsup.h3
11 files changed, 143 insertions, 16 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index a4e5219fb..57d26da74 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,21 @@
+2008-03-26 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * hookapi.cc (find_first_notloaded_dll): New function.
+ * pinfo.cc (status_exit): New function. Issue message when dll not
+ found. Use find_first_notloaded_dll to find a nonexistent dll.
+ (pinfo::maybe_set_exit_code_from_windows): Call status_exit when exit
+ code >= 0xc0000000UL.
+ * sigproc.cc (child_info::proc_retry): Return exit code when
+ STATUS_DLL_NOT_FOUND.
+ * spawn.cc (spawn_guts): Minor cleanup.
+ * syscalls.cc (close_all_files): Don't actually close stderr
+ filehandle. Just make it noninheritable.
+ * winsup.h (find_first_notloaded_dll): Declare new function.
+
+2008-03-26 Brian Dessent <brian@dessent.net>
+
+ * ntdll.h: Add several missing NTSTATUS defines.
+
2008-03-24 Corinna Vinschen <corinna@vinschen.de>
* flock.cc (inode_t::get_all_locks_list): Don't allow F_WAIT flag
diff --git a/winsup/cygwin/dtable.h b/winsup/cygwin/dtable.h
index 74163a0b4..ff82740dc 100644
--- a/winsup/cygwin/dtable.h
+++ b/winsup/cygwin/dtable.h
@@ -1,6 +1,6 @@
/* dtable.h: fd table definition.
- Copyright 2000, 2001, 2003, 2004, 2005 Red Hat, Inc.
+ Copyright 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc.
This file is part of Cygwin.
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 6eb17153a..86b793b6f 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -153,7 +153,7 @@ open_stackdumpfile ()
p, strlen (p)) * sizeof (WCHAR);
RtlAppendUnicodeToString (&ucore, L".stackdump");
/* Create an object attribute which refers to <progname>.stackdump
- in Cygwin's cwd. */
+ in Cygwin's cwd. */
InitializeObjectAttributes (&attr, &ucore, OBJ_CASE_INSENSITIVE,
cygheap->cwd.get_handle (), NULL);
HANDLE h;
diff --git a/winsup/cygwin/hookapi.cc b/winsup/cygwin/hookapi.cc
index 975879bf6..2e9ba0ece 100644
--- a/winsup/cygwin/hookapi.cc
+++ b/winsup/cygwin/hookapi.cc
@@ -1,6 +1,6 @@
/* hookapi.cc
- Copyright 2005, 2006 Red Hat, Inc.
+ Copyright 2005, 2006, 2007, 2008 Red Hat, Inc.
This file is part of Cygwin.
@@ -9,15 +9,17 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
+#include <imagehlp.h>
+#include <stdlib.h>
+#include <alloca.h>
+#include "ntdll.h"
#include "cygerrno.h"
#include "security.h"
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
#include "cygheap.h"
-#include <stdlib.h>
-#include <imagehlp.h>
-#include <alloca.h>
+#include "pinfo.h"
#define rva(coerce, base, addr) (coerce) ((char *) (base) + (addr))
#define rvacyg(coerce, addr) rva (coerce, cygwin_hmodule, addr)
@@ -158,7 +160,74 @@ makename (const char *name, char *&buf, int& i, int inc)
return name;
}
-// Top level routine to find the EXE's imports, and redirect them
+/* 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. */
+const char *
+find_first_notloaded_dll (path_conv& pc)
+{
+ const char *res = "?";
+ HANDLE hc = NULL;
+ HMODULE hm = NULL;
+ OBJECT_ATTRIBUTES attr;
+ IO_STATUS_BLOCK io;
+ HANDLE h;
+ NTSTATUS status;
+
+ status = NtOpenFile (&h, SYNCHRONIZE | GENERIC_READ,
+ pc.get_object_attr (attr, sec_none_nih),
+ &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ | FILE_OPEN_FOR_BACKUP_INTENT
+ | FILE_NON_DIRECTORY_FILE);
+ if (!NT_SUCCESS (status))
+ goto out;
+
+ 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, 0);
+ CloseHandle (hc);
+
+ PIMAGE_NT_HEADERS pExeNTHdr;
+ pExeNTHdr = PEHeaderFromHModule (hm);
+
+ if (!pExeNTHdr)
+ goto out;
+
+ DWORD importRVA;
+ importRVA = pExeNTHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
+ if (!importRVA)
+ goto out;
+
+ long delta = rvadelta (pExeNTHdr, importRVA);
+
+ // Convert imports RVA to a usable pointer
+ PIMAGE_IMPORT_DESCRIPTOR pdfirst;
+ 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, hm, pd->Name - delta);
+ if (!LoadLibraryEx (lib, NULL, DONT_RESOLVE_DLL_REFERENCES
+ | LOAD_LIBRARY_AS_DATAFILE))
+ {
+ static char buf[NT_MAX_PATH];
+ res = strcpy (buf, lib);
+ }
+ }
+
+out:
+ if (hm)
+ UnmapViewOfFile (hm);
+
+ return res;
+}
+
+// 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)
{
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 4ec281025..695c229cd 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -37,6 +37,12 @@
#define STATUS_INVALID_LEVEL ((NTSTATUS) 0xc0000148)
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS) 0x80000005)
#define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006)
+#define STATUS_DLL_NOT_FOUND ((NTSTATUS) 0xC0000135)
+#define STATUS_ENTRYPOINT_NOT_FOUND ((NTSTATUS) 0xC0000139)
+#define STATUS_BAD_DLL_ENTRYPOINT ((NTSTATUS) 0xC0000251)
+#define STATUS_ILLEGAL_DLL_RELOCATION ((NTSTATUS) 0xC0000269)
+
+
#define PDI_MODULES 0x01
#define PDI_HEAPS 0x04
#define LDRP_IMAGE_DLL 0x00000004
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index 85fdf9b37..d6b5de527 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -104,6 +104,28 @@ pinfo_init (char **envp, int envc)
debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid);
}
+static DWORD
+status_exit (DWORD x)
+{
+ const char *find_first_notloaded_dll (path_conv &);
+ switch (x)
+ {
+ case STATUS_DLL_NOT_FOUND:
+ {
+ char posix_prog[NT_MAX_PATH];
+ path_conv pc (myself->progname, PC_NOWARN);
+ mount_table->conv_to_posix_path (pc.get_win32 (), posix_prog, 1);
+ small_printf ("%s: error while loading shared libraries: %s: cannot open shared object file: No such file or directory\n",
+ posix_prog, find_first_notloaded_dll (pc));
+ x = 127;
+ }
+ break;
+ default:
+ x = 127;
+ }
+ return x;
+}
+
# define self (*this)
void
pinfo::maybe_set_exit_code_from_windows ()
@@ -114,10 +136,12 @@ pinfo::maybe_set_exit_code_from_windows ()
if (hProcess && !(self->exitcode & EXITCODE_SET))
{
- WaitForSingleObject (hProcess, INFINITE); // just to be safe, in case
- // process hasn't quite exited
- // after closing pipe
+ WaitForSingleObject (hProcess, INFINITE); /* just to be safe, in case
+ process hasn't quite exited
+ after closing pipe */
GetExitCodeProcess (hProcess, &x);
+ if (x >= 0xc0000000UL)
+ x = status_exit (x);
self->exitcode = EXITCODE_SET | (sigExeced ?: (x & 0xff) << 8);
}
sigproc_printf ("pid %d, exit value - old %p, windows %p, cygwin %p",
diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h
index 9d45bd2cb..9976ad1a0 100644
--- a/winsup/cygwin/pinfo.h
+++ b/winsup/cygwin/pinfo.h
@@ -45,7 +45,7 @@ public:
pid_t pid;
/* Various flags indicating the state of the process. See PID_
- constants below. */
+ constants in <sys/cygwin.h>. */
DWORD process_state;
DWORD exitcode; /* set when process exits */
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index af2b023d7..4c8c471e9 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -32,6 +32,7 @@ details. */
#include "cygtls.h"
#include "sigproc.h"
#include "exceptions.h"
+#include "ntdll.h"
/*
* Convenience defines
@@ -935,6 +936,8 @@ child_info::proc_retry (HANDLE h)
case STILL_ACTIVE: /* shouldn't happen */
sigproc_printf ("STILL_ACTIVE? How'd we get here?");
break;
+ case STATUS_DLL_NOT_FOUND:
+ return exit_code;
case STATUS_CONTROL_C_EXIT:
if (saw_ctrl_c ())
return EXITCODE_OK;
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index cb5af8017..2b728b0c4 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -1,7 +1,7 @@
/* spawn.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007 Red Hat, Inc.
+ 2005, 2006, 2007, 2008 Red Hat, Inc.
This file is part of Cygwin.
@@ -265,7 +265,7 @@ do_cleanup (void *args)
int __stdcall
-spawn_guts (const char * prog_arg, const char *const *argv,
+spawn_guts (const char *prog_arg, const char *const *argv,
const char *const envp[], int mode, int __stdin, int __stdout)
{
bool rc;
@@ -745,8 +745,7 @@ loop:
myself->wr_proc_pipe_owner = GetCurrentProcessId ();
myself->wr_proc_pipe = orig_wr_proc_pipe;
}
- DWORD res = ch.proc_retry (pi.hProcess);
- if (!res)
+ if (!ch.proc_retry (pi.hProcess))
{
looped++;
goto loop;
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 337d50282..d5f468344 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -109,12 +109,17 @@ close_all_files (bool norelease)
semaphore::terminate ();
fhandler_base *fh;
+ HANDLE h = NULL;
+
for (int i = 0; i < (int) cygheap->fdtab.size; i++)
if ((fh = cygheap->fdtab[i]) != NULL)
{
#ifdef DEBUGGING
debug_printf ("closing fd %d", i);
#endif
+ if (i == 2)
+ DuplicateHandle (GetCurrentProcess (), fh->get_output_handle (), GetCurrentProcess (), &h, 0, false,
+ DUPLICATE_SAME_ACCESS);
fh->close ();
if (!norelease)
cygheap->fdtab.release (i);
@@ -123,6 +128,8 @@ close_all_files (bool norelease)
if (!hExeced && cygheap->ctty)
cygheap->close_ctty ();
+ if (h)
+ SetStdHandle (STD_ERROR_HANDLE, h);
cygheap->fdtab.unlock ();
}
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index 5d9af096c..33cdba39d 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -261,7 +261,8 @@ void __stdcall close_all_files (bool = false);
extern "C" void error_start_init (const char*);
extern "C" int try_to_debug (bool waitloop = 1);
-extern void ld_preload ();
+void ld_preload ();
+const char *find_first_notloaded_dll (class path_conv &);
void set_file_api_mode (codepage_type);