* 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.
This commit is contained in:
Christopher Faylor 2008-03-27 01:50:40 +00:00
parent 73de02f44b
commit 93d606f60a
11 changed files with 143 additions and 16 deletions

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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)
{

View File

@ -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

View File

@ -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",

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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 ();
}

View File

@ -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);