summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <cgf@redhat.com>2003-02-01 04:59:13 +0000
committerChristopher Faylor <cgf@redhat.com>2003-02-01 04:59:13 +0000
commit2bd224eca959d67eafbbb3d22fef740eeb282deb (patch)
tree1600c1dcf340b550ca91e5014792cf9464fa67e7
parentcb393d5e461b30cb058bfe3293ebf8dba23ee7f1 (diff)
downloadgdb-2bd224eca959d67eafbbb3d22fef740eeb282deb.tar.gz
* dlfcn.cc (dlerror): Only report load errors once per error.
-rw-r--r--winsup/cygwin/ChangeLog4
-rw-r--r--winsup/cygwin/dlfcn.cc156
2 files changed, 160 insertions, 0 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index fc3bfcb8150..8a29585ddfa 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,9 @@
2003-01-31 Christopher Faylor <cgf@redhat.com>
+ * dlfcn.cc (dlerror): Only report load errors once per error.
+
+2003-01-31 Christopher Faylor <cgf@redhat.com>
+
* fhandler_serial.cc (fhandler_serial::open): Avoid extraneous setting
of res.
diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc
new file mode 100644
index 00000000000..b03f685fc6a
--- /dev/null
+++ b/winsup/cygwin/dlfcn.cc
@@ -0,0 +1,156 @@
+/* dlfcn.cc
+
+ Copyright 1998, 2000, 2001 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include "security.h"
+#include "fhandler.h"
+#include "perprocess.h"
+#include "path.h"
+#include "thread.h"
+#include "dlfcn.h"
+#include "dll_init.h"
+#include "cygerrno.h"
+
+#define _dl_error _reent_winsup ()->_dl_error
+#define _dl_buffer _reent_winsup ()->_dl_buffer
+
+static void __stdcall
+set_dl_error (const char *str)
+{
+ __small_sprintf (_dl_buffer, "%s: %E", str);
+ _dl_error = 1;
+}
+
+/* Look for an executable file given the name and the environment
+ variable to use for searching (eg., PATH); returns the full
+ pathname (static buffer) if found or NULL if not. */
+inline const char * __stdcall
+check_path_access (const char *mywinenv, const char *name, path_conv& buf)
+{
+ return find_exec (name, buf, mywinenv, FE_NNF | FE_NATIVE | FE_CWD);
+}
+
+/* Search LD_LIBRARY_PATH for dll, if it exists.
+ Return Windows version of given path. */
+static const char * __stdcall
+get_full_path_of_dll (const char* str, char *name)
+{
+ int len = strlen (str);
+
+ /* empty string or too long to be legal win32 pathname? */
+ if (len == 0 || len >= MAX_PATH - 1)
+ return str; /* Yes. Let caller deal with it. */
+
+ const char *ret;
+
+ strcpy (name, str); /* Put it somewhere where we can manipulate it. */
+
+ /* Add extension if necessary */
+ if (str[len - 1] != '.')
+ {
+ /* Add .dll only if no extension provided. */
+ const char *p = strrchr (str, '.');
+ if (!p || strpbrk (p, "\\/"))
+ strcat (name, ".dll");
+ }
+
+ path_conv real_filename;
+
+ if (isabspath (name) ||
+ (ret = check_path_access ("LD_LIBRARY_PATH=", name, real_filename)) == NULL)
+ real_filename.check (name); /* Convert */
+
+ if (!real_filename.error)
+ ret = strcpy (name, real_filename);
+ else
+ {
+ set_errno (real_filename.error);
+ ret = NULL;
+ }
+
+ return ret;
+}
+
+void *
+dlopen (const char *name, int)
+{
+ SetResourceLock (LOCK_DLL_LIST, READ_LOCK | WRITE_LOCK, "dlopen");
+
+ void *ret;
+
+ if (name == NULL)
+ ret = (void *) GetModuleHandle (NULL); /* handle for the current module */
+ else
+ {
+ char buf[MAX_PATH];
+ /* handle for the named library */
+ const char *fullpath = get_full_path_of_dll (name, buf);
+ if (!fullpath)
+ ret = NULL;
+ else
+ {
+ ret = (void *) LoadLibrary (fullpath);
+ if (ret == NULL)
+ __seterrno ();
+ }
+ }
+
+ if (!ret)
+ set_dl_error ("dlopen");
+ debug_printf ("ret %p", ret);
+
+ ReleaseResourceLock (LOCK_DLL_LIST, READ_LOCK | WRITE_LOCK, "dlopen");
+ return ret;
+}
+
+void *
+dlsym (void *handle, const char *name)
+{
+ void *ret = (void *) GetProcAddress ((HMODULE) handle, name);
+ if (!ret)
+ set_dl_error ("dlsym");
+ debug_printf ("ret %p", ret);
+ return ret;
+}
+
+int
+dlclose (void *handle)
+{
+ SetResourceLock (LOCK_DLL_LIST, READ_LOCK | WRITE_LOCK, "dlclose");
+
+ int ret = -1;
+ void *temphandle = (void *) GetModuleHandle (NULL);
+ if (temphandle == handle || FreeLibrary ((HMODULE) handle))
+ ret = 0;
+ if (ret)
+ set_dl_error ("dlclose");
+ CloseHandle ((HMODULE) temphandle);
+
+ ReleaseResourceLock (LOCK_DLL_LIST, READ_LOCK | WRITE_LOCK, "dlclose");
+ return ret;
+}
+
+char *
+dlerror ()
+{
+ char *res;
+ if (!_dl_error)
+ res = NULL;
+ else
+ {
+ _dl_error = 0;
+ res = _dl_buffer;
+ }
+ return res;
+}