This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCHx3] LD plugins: matters outstanding.
- From: Dave Korn <dave dot korn dot cygwin at gmail dot com>
- To: "binutils at sourceware dot org" <binutils at sourceware dot org>
- Cc: Tristan Gingold <gingold at adacore dot com>
- Date: Fri, 15 Oct 2010 16:56:39 +0100
- Subject: [PATCHx3] LD plugins: matters outstanding.
Hello binutils,
The attached three patches fix two small bugs in the LD plugin interface,
and add support for MinGW.
[PATCH] Avoid testsuite errors when no cross compiler is available.
ld/testsuite/ChangeLog:
* ld-plugin/plugin.exp: Don't error out if there is no target compiler
available, make tests UNSUPPORTED instead.
This is just a repost of the patch I sent earlier to prevent noise in
cross-target testsuite runs.
[PATCH] Fix potential use-after-free bugs.
ld/ChangeLog:
* plugin.c (add_input_file): Take copy of input string.
(add_input_library): Likewise.
(set_extra_library_path): Likewise.
This patch fixes a bug I found while porting the GCC lto-plugin. The
strings passed to these callbacks belong to the plugin, and it is allowed to
free them after the callback returns. So ld can't hang on to a copy of a
pointer to the string (embedded in a lang input statement); it has to make a
dup. Without this fix, plugin pass-through filenames were getting mangled.
[PATCH] Provide win32-based dlapi replacements on windows platforms without
dlfcn.h.
ld/ChangeLog:
* configure.in: If <dlfcn.h> can't be found, try for <Windows.h>
* configure: Regenerate.
* config.in: Likewise.
* plugin.c [!HAVE_DLFCN_H && HAVE_WINDOWS_H] (dlopen): Provide
trival LoadLibrary-based replacement for Windows systems.
[!HAVE_DLFCN_H && HAVE_WINDOWS_H] (dlsym): Likewise trivial
replacement based on GetProcAddress.
[!HAVE_DLFCN_H && HAVE_WINDOWS_H] (dlsym): Likewise FreeLibrary.
* sysdep.h: Don't infer presence of <dlfcn.h> from ENABLE_PLUGINS
anymore, use its own guard.
I took a look at libltdl, and decided it was too much of a top-heavy and
intrusive solution. Given that so far it's looking like Windows is going to
be the only non-ELF platform fully supporting LTO, I decided just to slap a
trivial shim layer in for MinGW's sake.
Built and tested on i686-pc-cygwin. Built on i686-pc-mingw32, but there's
no dejagnu on that platform, so I just manually ran the equivalent of the most
basic plugin load test. (It worked.)
These patches complete the LD plugin interface work. (Tristan, the patch I
thought I might need to do about rescanning libs turns out not to be needed,
so this is everything.)
OK for trunk?
cheers,
DaveK
>From babff63d4d6d96ab9fae22b67a729445d767d459 Mon Sep 17 00:00:00 2001
From: Dave Korn <dave.korn.cygwin@gmail.com>
Date: Fri, 15 Oct 2010 16:05:51 +0100
Subject: [PATCH] Avoid testsuite errors when no cross compiler is available.
ld/testsuite/ChangeLog:
* ld-plugin/plugin.exp: Don't error out if there is no target compiler
available, make tests UNSUPPORTED instead.
---
ld/testsuite/ld-plugin/plugin.exp | 20 +++++++++++++++-----
1 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/ld/testsuite/ld-plugin/plugin.exp b/ld/testsuite/ld-plugin/plugin.exp
index 796cb0e..416159a 100644
--- a/ld/testsuite/ld-plugin/plugin.exp
+++ b/ld/testsuite/ld-plugin/plugin.exp
@@ -24,6 +24,13 @@ if ![check_plugin_api_available] {
return
}
+# And a compiler to be available.
+set can_compile 1
+if { [which $CC] == 0 } {
+ # Don't fail immediately,
+ set can_compile 0
+}
+
pass "plugin API enabled"
global base_dir
@@ -62,12 +69,15 @@ set regcln "-plugin-opt registercleanup"
set failed_compile 0
set _ ""
set plugin_nm_output ""
-if { ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/main.c tmpdir/main.o]
- || ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/func.c tmpdir/func.o]
- || ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/text.c tmpdir/text.o] } {
+if { $can_compile && \
+ (![ld_compile "$CC $CFLAGS" $srcdir/$subdir/main.c tmpdir/main.o] \
+ || ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/func.c tmpdir/func.o] \
+ || ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/text.c tmpdir/text.o]) } {
# Defer fail until we have list of tests set.
set failed_compile 1
-} else {
+}
+
+if { $can_compile && !$failed_compile } {
# Find out if symbols have prefix on this platform before setting tests.
catch "exec $NM tmpdir/func.o" plugin_nm_output
if { [regexp "_func" "$plugin_nm_output"] } {
@@ -142,7 +152,7 @@ set plugin_extra_elf_tests [list \
{readelf -s plugin-vis-1.d}} "main.x" ] \
]
-if { $failed_compile != 0 } {
+if { !$can_compile || $failed_compile } {
foreach testitem $plugin_tests {
unresolved [lindex $testitem 0]
}
>From 1478b11d6ed70bde869ad90d52a6194abd92d88d Mon Sep 17 00:00:00 2001
From: Dave Korn <dave.korn.cygwin@gmail.com>
Date: Fri, 15 Oct 2010 16:09:56 +0100
Subject: [PATCH] Fix potential use-after-free bugs.
ld/ChangeLog:
* plugin.c (add_input_file): Take copy of input string.
(add_input_library): Likewise.
(set_extra_library_path): Likewise.
---
ld/plugin.c | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/ld/plugin.c b/ld/plugin.c
index b484bd0..0c88ef8 100644
--- a/ld/plugin.c
+++ b/ld/plugin.c
@@ -433,7 +433,8 @@ static enum ld_plugin_status
add_input_file (const char *pathname)
{
ASSERT (called_plugin);
- if (!lang_add_input_file (pathname, lang_input_file_is_file_enum, NULL))
+ if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum,
+ NULL))
return LDPS_ERR;
return LDPS_OK;
}
@@ -443,7 +444,8 @@ static enum ld_plugin_status
add_input_library (const char *pathname)
{
ASSERT (called_plugin);
- if (!lang_add_input_file (pathname, lang_input_file_is_l_enum, NULL))
+ if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum,
+ NULL))
return LDPS_ERR;
return LDPS_OK;
}
@@ -454,7 +456,7 @@ static enum ld_plugin_status
set_extra_library_path (const char *path)
{
ASSERT (called_plugin);
- ldfile_add_library_path (path, FALSE);
+ ldfile_add_library_path (xstrdup (path), FALSE);
return LDPS_OK;
}
>From 9b6758820e42a6b6ea97226f860a22dfb4b653e6 Mon Sep 17 00:00:00 2001
From: Dave Korn <dave.korn.cygwin@gmail.com>
Date: Fri, 15 Oct 2010 16:34:37 +0100
Subject: [PATCH] Provide win32-based dlapi replacements on windows platforms without dlfcn.h.
ld/ChangeLog:
* configure.in: If <dlfcn.h> can't be found, try for <Windows.h>
* configure: Regenerate.
* config.in: Likewise.
* plugin.c [!HAVE_DLFCN_H && HAVE_WINDOWS_H] (dlopen): Provide
trival LoadLibrary-based replacement for Windows systems.
[!HAVE_DLFCN_H && HAVE_WINDOWS_H] (dlsym): Likewise trivial
replacement based on GetProcAddress.
[!HAVE_DLFCN_H && HAVE_WINDOWS_H] (dlsym): Likewise FreeLibrary.
* sysdep.h: Don't infer presence of <dlfcn.h> from ENABLE_PLUGINS
anymore, use its own guard.
---
ld/config.in | 3 +++
ld/configure | 16 ++++++++++++++++
ld/configure.in | 4 ++++
ld/plugin.c | 28 ++++++++++++++++++++++++++++
ld/sysdep.h | 3 +--
5 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/ld/config.in b/ld/config.in
index 9e6e97b..f49327c 100644
--- a/ld/config.in
+++ b/ld/config.in
@@ -129,6 +129,9 @@
/* Define to 1 if you have the `waitpid' function. */
#undef HAVE_WAITPID
+/* Define to 1 if you have the <Windows.h> header file. */
+#undef HAVE_WINDOWS_H
+
/* Define to 1 if you have the <zlib.h> header file. */
#undef HAVE_ZLIB_H
diff --git a/ld/configure b/ld/configure
index 9ff8529..3367a88 100755
--- a/ld/configure
+++ b/ld/configure
@@ -12919,6 +12919,22 @@ else
fi
done
+# We also support plugins on Windows (MinGW).
+if test x$enable_plugins = xno ; then
+ for ac_header in Windows.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "Windows.h" "ac_cv_header_Windows_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_Windows_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_WINDOWS_H 1
+_ACEOF
+ enable_plugins=yes
+fi
+
+done
+
+fi
if test x$enable_plugins = xyes; then
ENABLE_PLUGINS_TRUE=
ENABLE_PLUGINS_FALSE='#'
diff --git a/ld/configure.in b/ld/configure.in
index 29d01cc..122f65e 100644
--- a/ld/configure.in
+++ b/ld/configure.in
@@ -169,6 +169,10 @@ enable_plugins=yes
AC_CHECK_HEADER([dlfcn.h],[],[enable_plugins=no],[AC_INCLUDES_DEFAULT])
AC_SEARCH_LIBS([dlopen],[dl],[],[enable_plugins=no],[])
AC_CHECK_FUNCS([dlopen dlsym dlclose],[],[enable_plugins=no])
+# We also support plugins on Windows (MinGW).
+if test x$enable_plugins = xno ; then
+ AC_CHECK_HEADERS([Windows.h],[enable_plugins=yes],[],[AC_INCLUDES_DEFAULT])
+fi
AM_CONDITIONAL([ENABLE_PLUGINS], [test x$enable_plugins = xyes])
AC_MSG_CHECKING(for a known getopt prototype in unistd.h)
diff --git a/ld/plugin.c b/ld/plugin.c
index 0c88ef8..caf8a34 100644
--- a/ld/plugin.c
+++ b/ld/plugin.c
@@ -32,6 +32,9 @@
#include "plugin.h"
#include "plugin-api.h"
#include "elf-bfd.h"
+#if defined (HAVE_WINDOWS_H)
+#include <Windows.h>
+#endif
/* The suffix to append to the name of the real (claimed) object file
when generating a dummy BFD to hold the IR symbols sent from the
@@ -128,6 +131,31 @@ static const enum ld_plugin_tag tv_header_tags[] =
/* How many entries in the constant leading part of the tv array. */
static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags);
+#if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
+
+#define RTLD_NOW 0 /* Dummy value. */
+
+static void *
+dlopen (const char *file, int mode ATTRIBUTE_UNUSED)
+{
+ return LoadLibrary (file);
+}
+
+static void *
+dlsym (void *handle, const char *name)
+{
+ return GetProcAddress (handle, name);
+}
+
+static int
+dlclose (void *handle)
+{
+ FreeLibrary (handle);
+ return 0;
+}
+
+#endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) */
+
/* Helper function for exiting with error status. */
static int
set_plugin_error (const char *plugin)
diff --git a/ld/sysdep.h b/ld/sysdep.h
index 9dfae10..b7d5b88 100644
--- a/ld/sysdep.h
+++ b/ld/sysdep.h
@@ -90,8 +90,7 @@ extern char *strrchr ();
#endif
#endif
-/* This is both more precise than and includes HAVE_DLFCN_H. */
-#ifdef ENABLE_PLUGINS
+#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif