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
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog22
-rw-r--r--winsup/cygwin/Makefile.in18
-rw-r--r--winsup/cygwin/cygheap.cc2
-rw-r--r--winsup/cygwin/cygheap.h9
-rw-r--r--winsup/cygwin/dcrt0.cc3
-rw-r--r--winsup/cygwin/external.cc8
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc4
-rw-r--r--winsup/cygwin/fhandler_socket.cc4
-rw-r--r--winsup/cygwin/fork.cc2
-rw-r--r--winsup/cygwin/hookapi.cc218
-rw-r--r--winsup/cygwin/include/sys/cygwin.h4
-rw-r--r--winsup/cygwin/init.cc3
-rw-r--r--winsup/cygwin/select.cc1
13 files changed, 282 insertions, 16 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 4ff4cc971..1e6ea30e5 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,25 @@
+2005-03-22 Christopher Faylor <cgf@timesys.com>
+
+ * Makefile.in (DLL_OFILES): Add hookapi.o. Eliminate some cruft.
+ * cygheap.h (cygheap_types): Add new enum: HEAP_1_HOOK.
+ (hook_chain): New struct.
+ (init_cygheap::hooks): Define new element.
+ * cygheap.cc (cygheap_fixup_in_child): Zero hook chain on exec.
+ * dcrt0.cc (dll_crt0_1): Call ld_preload just before calling main function.
+ * external.cc (cygwin_internal): Implement CW_HOOK.
+ * fork.cc (fork_child): Call fixup_hooks_after_fork.
+ * init.cc (cygwin_hmodule): Reinstate after a long absence.
+ * include/sys/cygwin.h: Define CW_HOOK.
+ * hookapi.cc: New file.
+
+ * select.cc (start_thread_socket): Add debugging output.
+
+ * fhandler_disk_file.cc (fhandler_disk_file::fchmod): gcc 4.x
+ accommodation.
+
+ * fhandler_socket.cc (fhandler_socket::connect): Make sure that err is
+ initialized.
+
2005-03-22 Corinna Vinschen <corinna@vinschen.de>
* cygwin.din (__ctype_ptr): Export.
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index de9c9f8bb..589da2b28 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -117,7 +117,7 @@ MALLOC_OFILES=@MALLOC_OFILES@
DLL_IMPORTS:=$(w32api_lib)/libkernel32.a $(w32api_lib)/libadvapi32.a
MT_SAFE_OBJECTS:=
-# Please maintain this list in sorted order, with maximum files per 80 col line
+# Please maintain this list in sorted order, with maximum files per 85 col line
#
DLL_OFILES:=assert.o autoload.o bsdlib.o cxx.o cygheap.o cygthread.o cygtls.o \
dcrt0.o debug.o delqueue.o devices.o dir.o dlfcn.o dll_init.o dtable.o \
@@ -127,12 +127,12 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o cxx.o cygheap.o cygthread.o cygtls.o \
fhandler_nodevice.o fhandler_proc.o fhandler_process.o \
fhandler_random.o fhandler_raw.o fhandler_registry.o fhandler_serial.o \
fhandler_socket.o fhandler_tape.o fhandler_termios.o \
- fhandler_tty.o fhandler_virtual.o fhandler_windows.o \
- fhandler_zero.o flock.o fnmatch.o fork.o getopt.o glob.o grp.o heap.o \
+ fhandler_tty.o fhandler_virtual.o fhandler_windows.o fhandler_zero.o \
+ flock.o fnmatch.o fork.o getopt.o glob.o grp.o heap.o hookapi.o \
init.o ioctl.o ipc.o iruserok.o localtime.o malloc_wrapper.o miscfuncs.o \
mmap.o msg.o net.o netdb.o ntea.o passwd.o path.o pinfo.o pipe.o \
- poll.o pthread.o regcomp.o regerror.o regexec.o regfree.o registry.o \
- resource.o scandir.o sched.o sec_acl.o sec_helper.o security.o \
+ poll.o pthread.o regcomp.o regerror.o regexec.o regfree.o \
+ registry.o resource.o scandir.o sched.o sec_acl.o sec_helper.o security.o \
select.o sem.o shared.o shm.o sigfe.o signal.o sigproc.o smallprint.o \
spawn.o strace.o strsep.o strsig.o sync.o syscalls.o sysconf.o \
syslog.o termios.o thread.o timer.o times.o tty.o uinfo.o uname.o \
@@ -254,6 +254,7 @@ grp_CFLAGS:=-fomit-frame-pointer
malloc_CFLAGS:=-fomit-frame-pointer
malloc_wrapper_CFLAGS:=-fomit-frame-pointer
miscfuncs_CFLAGS:=-fomit-frame-pointer
+net_CFLAGS:=-fomit-frame-pointer
passwd_CFLAGS:=-fomit-frame-pointer
regcomp_CFLAGS=-fomit-frame-pointer
regerror_CFLAGS=-fomit-frame-pointer
@@ -267,7 +268,7 @@ uinfo_CFLAGS:=-fomit-frame-pointer
endif
.PHONY: all force dll_ofiles install all_target install_target all_host install_host \
- install install-libs install-headers -lgcc
+ install install-libs install-headers
.SUFFIXES:
.SUFFIXES: .c .cc .def .a .o .d .s
@@ -434,11 +435,6 @@ winver_stamp: mkvers.sh include/cygwin/version.h winver.rc $(DLL_OFILES)
$(COMPILE_CXX) -o version.o version.cc && \
touch $@
--lgcc:
- :
-
-#
-
Makefile: cygwin.din
$(DEF_FILE): gendef cygwin.din $(srcdir)/tlsoffsets.h
diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc
index a8bf8e410..ef5804d6d 100644
--- a/winsup/cygwin/cygheap.cc
+++ b/winsup/cygwin/cygheap.cc
@@ -21,7 +21,6 @@
#include "child_info.h"
#include "heap.h"
#include "sync.h"
-#include "shared_info.h"
#include "sigproc.h"
init_cygheap NO_COPY *cygheap;
@@ -185,6 +184,7 @@ cygheap_fixup_in_child (bool execed)
if (execed)
{
+ cygheap->hooks.next = NULL;
cygheap->user_heap.base = NULL; /* We can allocate the heap anywhere */
/* Walk the allocated memory chain looking for orphaned memory from
previous execs */
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index 9a57a9b2d..a338c6ed7 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -21,6 +21,7 @@ enum cygheap_types
HEAP_ARCHETYPES,
HEAP_TLS,
HEAP_1_START,
+ HEAP_1_HOOK,
HEAP_1_STR,
HEAP_1_ARGV,
HEAP_1_BUF,
@@ -262,6 +263,13 @@ struct user_heap_info
unsigned chunk;
};
+struct hook_chain
+{
+ void **loc;
+ const void *func;
+ struct hook_chain *next;
+};
+
struct init_cygheap
{
_cmalloc_entry *chain;
@@ -291,6 +299,7 @@ struct init_cygheap
int open_fhs;
pid_t pid; /* my pid */
HANDLE pid_handle; /* handle for my pid */
+ hook_chain hooks;
void close_ctty ();
};
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 524b30034..fdec9bc41 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -41,6 +41,8 @@ details. */
#define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
+void ld_preload ();
+
HANDLE NO_COPY hMainProc = (HANDLE) -1;
HANDLE NO_COPY hMainThread;
@@ -857,6 +859,7 @@ dll_crt0_1 (char *)
do this for noncygwin case since the signal thread is blocked due to
LoadLibrary serialization. */
wait_for_sigthread ();
+ ld_preload ();
if (user_data->main)
exit (user_data->main (__argc, __argv, *user_data->envptr));
}
diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc
index 56ef0c6b6..c28039cc0 100644
--- a/winsup/cygwin/external.cc
+++ b/winsup/cygwin/external.cc
@@ -28,6 +28,8 @@ details. */
#include "pwdgrp.h"
#include "cygtls.h"
+void *hook_cygwin (const char *, const void *);
+
static external_pinfo *
fillout_pinfo (pid_t pid, int winpid)
{
@@ -298,6 +300,12 @@ cygwin_internal (cygwin_getinfo_types t, ...)
}
return p.binmode ();
}
+ case CW_HOOK:
+ {
+ const char *name = va_arg (arg, const char *);
+ const void *hookfn = va_arg (arg, const void *);
+ return (unsigned long) hook_cygwin (name, hookfn);
+ }
default:
return (DWORD) -1;
}
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 7842bcafa..da89e5422 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -429,9 +429,9 @@ fhandler_disk_file::fchmod (mode_t mode)
/* if the mode we want has any write bits set, we can't be read only. */
if (mode & (S_IWUSR | S_IWGRP | S_IWOTH))
- (DWORD) pc &= ~FILE_ATTRIBUTE_READONLY;
+ pc &= (DWORD) ~FILE_ATTRIBUTE_READONLY;
else
- (DWORD) pc |= FILE_ATTRIBUTE_READONLY;
+ pc |= (DWORD) FILE_ATTRIBUTE_READONLY;
if (!SetFileAttributes (pc, pc))
__seterrno ();
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index c2e87478d..e7194dfe5 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -698,7 +698,9 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
res = ::connect (get_socket (), (sockaddr *) &sin, namelen);
- if (res)
+ if (!res)
+ err = 0;
+ else
{
err = WSAGetLastError ();
/* Special handling for connect to return the correct error code
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index b04e518fe..4ae2d0a21 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -154,6 +154,7 @@ sync_with_parent (const char *s, bool hang_self)
static int __stdcall
fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
{
+ extern void fixup_hooks_after_fork ();
extern void fixup_timers_after_fork ();
debug_printf ("child is running. pid %d, ppid %d, stack here %p",
myself->pid, myself->ppid, __builtin_frame_address (0));
@@ -232,6 +233,7 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
pthread::atforkchild ();
fixup_timers_after_fork ();
+ fixup_hooks_after_fork ();
cygbench ("fork-child");
cygwin_finished_initializing = true;
return 0;
diff --git a/winsup/cygwin/hookapi.cc b/winsup/cygwin/hookapi.cc
new file mode 100644
index 000000000..09c70c24b
--- /dev/null
+++ b/winsup/cygwin/hookapi.cc
@@ -0,0 +1,218 @@
+#include "winsup.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>
+
+#define rva(coerce, base, addr) (coerce) ((char *) (base) + (addr))
+#define rvacyg(coerce, addr) rva (coerce, cygwin_hmodule, addr)
+
+struct function_hook
+{
+ const char *name; // Function name, e.g. "DirectDrawCreateEx".
+ const void *hookfn; // Address of your function.
+ void *origfn; // Stored by HookAPICalls, the address of the original function.
+};
+
+/* Given an HMODULE, returns a pointer to the PE header */
+static PIMAGE_NT_HEADERS
+PEHeaderFromHModule (HMODULE hModule)
+{
+ PIMAGE_NT_HEADERS pNTHeader = NULL;
+
+ if (PIMAGE_DOS_HEADER(hModule) ->e_magic != IMAGE_DOS_SIGNATURE)
+ /* nothing */;
+ else
+ {
+ pNTHeader = PIMAGE_NT_HEADERS (PBYTE (hModule)
+ + PIMAGE_DOS_HEADER (hModule) ->e_lfanew);
+ if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
+ pNTHeader = NULL;
+ }
+
+ return pNTHeader;
+}
+
+void *
+putmem (PIMAGE_THUNK_DATA pi, const void *hookfn)
+{
+
+ DWORD flOldProtect, flNewProtect, flDontCare;
+ MEMORY_BASIC_INFORMATION mbi;
+
+ /* Get the current protection attributes */
+ VirtualQuery (pi, &mbi, sizeof (mbi));
+
+ /* Remove ReadOnly and ExecuteRead attributes, add on ReadWrite flag */
+ flNewProtect = mbi.Protect;
+ flNewProtect &= ~(PAGE_READONLY | PAGE_EXECUTE_READ);
+ flNewProtect |= PAGE_READWRITE;
+
+ if (!VirtualProtect (pi, sizeof (PVOID), flNewProtect, &flOldProtect) )
+ return NULL;
+
+ void *origfn = (void *) pi->u1.Function;
+ pi->u1.Function = (DWORD) hookfn;
+
+ (void) VirtualProtect (pi, sizeof (PVOID), flOldProtect, &flDontCare);
+ return origfn;
+}
+
+/* Builds stubs for and redirects the IAT for one DLL (pImportDesc) */
+
+static bool
+RedirectIAT (function_hook& fh, PIMAGE_IMPORT_DESCRIPTOR pImportDesc,
+ HMODULE hm)
+{
+ // If no import names table, we can't redirect this, so bail
+ if (pImportDesc->OriginalFirstThunk == 0)
+ return false;
+
+ /* import address table */
+ PIMAGE_THUNK_DATA pt = rva (PIMAGE_THUNK_DATA, hm, pImportDesc->FirstThunk);
+ /* import names table */
+ PIMAGE_THUNK_DATA pn = rva (PIMAGE_THUNK_DATA, hm, pImportDesc->OriginalFirstThunk);
+
+ /* Scan through the IAT, completing the stubs and redirecting the IAT
+ entries to point to the stubs. */
+ for (PIMAGE_THUNK_DATA pi = pt; pn->u1.Ordinal; pi++, pn++)
+ {
+ if (IMAGE_SNAP_BY_ORDINAL (pn->u1.Ordinal) )
+ continue;
+
+ /* import by name */
+ PIMAGE_IMPORT_BY_NAME pimp = rva (PIMAGE_IMPORT_BY_NAME, hm, pn->u1.AddressOfData);
+
+ if (strcmp (fh.name, (char *) pimp->Name) == 0)
+ {
+ fh.origfn = putmem (pi, fh.hookfn);
+ if (!fh.origfn)
+ return false;
+ hook_chain *hc;
+ for (hc = &cygheap->hooks; hc->next; hc = hc->next)
+ continue;
+ hc->next = (hook_chain *) cmalloc (HEAP_1_HOOK, sizeof (hook_chain));
+ hc->next->loc = (void **) pi;
+ hc->next->func = fh.hookfn;
+ hc->next->next = NULL;
+ break;
+ }
+ }
+
+ return true;
+}
+
+void
+get_export (function_hook& fh)
+{
+ extern HMODULE cygwin_hmodule;
+ PIMAGE_DOS_HEADER pdh = (PIMAGE_DOS_HEADER) cygwin_hmodule;
+ if (pdh->e_magic != IMAGE_DOS_SIGNATURE)
+ return;
+ PIMAGE_NT_HEADERS pnt = (PIMAGE_NT_HEADERS) ((char *) pdh + pdh->e_lfanew);
+ if (pnt->Signature != IMAGE_NT_SIGNATURE || pnt->FileHeader.SizeOfOptionalHeader == 0)
+ return;
+ PIMAGE_EXPORT_DIRECTORY pexp =
+ rvacyg (PIMAGE_EXPORT_DIRECTORY,
+ pnt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
+ if (!pexp)
+ return;
+
+ PDWORD pfuncs = rvacyg (PDWORD, pexp->AddressOfFunctions);
+ PDWORD pnames = rvacyg (PDWORD, pexp->AddressOfNames);
+ for (DWORD i = 0; i < pexp->NumberOfNames; i++)
+ if (strcmp (fh.name, rvacyg (char *, pnames[i])) == 0)
+ {
+ fh.origfn = rvacyg (void *, pfuncs[i]);
+ break;
+ }
+}
+
+static const char *
+makename (const char *name, char *&buf, int& i, int inc)
+{
+ i += inc;
+ static const char *testers[] = {"NOTUSED", "64", "32"};
+ if (i < 0 || i >= (int) (sizeof (testers) / sizeof (testers[0])))
+ return NULL;
+ if (i)
+ {
+ __small_sprintf (buf, "_%s%s", name, testers[i]);
+ name = buf;
+ }
+ return name;
+}
+
+// Top level routine to find the EXE's imports, and redirect them
+void *
+hook_cygwin (const char *name, const void *fn)
+{
+ HMODULE hm = GetModuleHandle (NULL);
+ PIMAGE_NT_HEADERS pExeNTHdr = PEHeaderFromHModule (hm);
+
+ if (!pExeNTHdr)
+ return false;
+
+ DWORD importRVA = pExeNTHdr->OptionalHeader.DataDirectory
+ [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
+ if (!importRVA)
+ return false;
+
+ // Convert imports RVA to a usable pointer
+ PIMAGE_IMPORT_DESCRIPTOR pdfirst = rva (PIMAGE_IMPORT_DESCRIPTOR, hm, importRVA);
+
+ function_hook fh;
+ fh.origfn = NULL;
+ fh.hookfn = fn;
+ char *buf = (char *) alloca (strlen (name) + strlen ("64") + sizeof ("_"));
+ int i = -1;
+ while (!fh.origfn && (fh.name = makename (name, buf, i, 1)))
+ {
+ // Iterate through each import descriptor, and redirect if appropriate
+ for (PIMAGE_IMPORT_DESCRIPTOR pd = pdfirst; pd->FirstThunk; pd++)
+ {
+ PSTR modname = rva (PSTR, hm, pd->Name);
+ if (strcasematch (modname, "cygwin1.dll"))
+ RedirectIAT (fh, pd, hm);
+ }
+ }
+
+ while (!fh.origfn && (fh.name = makename (name, buf, i, -1)))
+ get_export (fh);
+
+ return fh.origfn;
+}
+
+void
+ld_preload ()
+{
+ char *p = getenv ("LD_PRELOAD");
+ if (!p)
+ return;
+ char *s = (char *) alloca (strlen (p) + 1);
+ strcpy (s, p);
+ char *here = NULL;
+ for (p = strtok_r (s, " \t\n", &here); p; p = strtok_r (NULL, " \t\n", &here))
+ {
+ path_conv lib (p);
+ if (!LoadLibrary (lib))
+ {
+ __seterrno ();
+ api_fatal ("error while loading shared libraries: %s: "
+ "cannot open shared object file: %s", p,
+ strerror (get_errno ()));
+ }
+ }
+}
+
+void
+fixup_hooks_after_fork ()
+{
+ for (hook_chain *hc = &cygheap->hooks; (hc = hc->next); )
+ putmem ((PIMAGE_THUNK_DATA) hc->loc, hc->func);
+}
diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h
index 04d0b003f..eb29cceb2 100644
--- a/winsup/cygwin/include/sys/cygwin.h
+++ b/winsup/cygwin/include/sys/cygwin.h
@@ -49,6 +49,7 @@ struct __cygwin_perfile
/* External interface stuff */
+/* Always add at the bottom. Do not add new values in the middle. */
typedef enum
{
CW_LOCK_PINFO,
@@ -78,7 +79,8 @@ typedef enum
CW_GET_SHMLBA,
CW_GET_UID_FROM_SID,
CW_GET_GID_FROM_SID,
- CW_GET_BINMODE
+ CW_GET_BINMODE,
+ CW_HOOK
} cygwin_getinfo_types;
#define CW_NEXTPID 0x80000000 /* or with pid to get next one */
diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc
index d3e41b6a4..3d7a91c50 100644
--- a/winsup/cygwin/init.cc
+++ b/winsup/cygwin/init.cc
@@ -108,6 +108,8 @@ respawn_wow64_process ()
extern void __stdcall dll_crt0_0 ();
+HMODULE NO_COPY cygwin_hmodule;
+
extern "C" int WINAPI
dll_entry (HANDLE h, DWORD reason, void *static_load)
{
@@ -116,6 +118,7 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
switch (reason)
{
case DLL_PROCESS_ATTACH:
+ cygwin_hmodule = (HMODULE) h;
/* Is the stack at an unusual high address? Check if we're running on
a 64 bit machine. If so, respawn. */
if (&is_64bit_machine >= (PBOOL) 0x400000
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 50489aa1d..8b77d2a70 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -1394,6 +1394,7 @@ start_thread_socket (select_record *me, select_stuff *stuff)
SetHandleInformation ((HANDLE) si->exitsock, HANDLE_FLAG_INHERIT, 0);
/* else
too bad? */
+ select_printf ("opened new socket %p", _my_tls.locals.exitsock);
}
select_printf ("exitsock %p", si->exitsock);