This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch master updated. glibc-2.26-69-g2449ae7


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  2449ae7b2da24c9940962304a3e44bc80e389265 (commit)
      from  f87cc2bfba9b844da48a63441c6099342b1551c7 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=2449ae7b2da24c9940962304a3e44bc80e389265

commit 2449ae7b2da24c9940962304a3e44bc80e389265
Author: Florian Weimer <fweimer@redhat.com>
Date:   Thu Aug 10 13:40:22 2017 +0200

    ld.so: Introduce struct dl_exception
    
    This commit separates allocating and raising exceptions.  This
    simplifies catching and re-raising them because it is no longer
    necessary to make a temporary, on-stack copy of the exception message.

diff --git a/ChangeLog b/ChangeLog
index 6648ce1..dcf8626 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,65 @@
 2017-08-10  Florian Weimer  <fweimer@redhat.com>
 
+	Introduce ld.so exceptions.
+	* sysdeps/generic/ldsodefs.h (struct dl_exception): Define.
+	(_dl_exception_create, _dl_exception_create_format)
+	(_dl_exception_free, _dl_signal_exception, _dl_signal_cexception)
+	(_dl_catch_exception): Declare.
+	(_dl_catch_error): Update comment.
+	* elf/dl-error-skeleton.c (struct catch): Replace objname,
+	errstring, malloced members with exception member.
+	(_dl_out_of_memory): Remove.
+	(fatal_error): New function, extracted from _dl_signal_error.
+	(_dl_signal_exception, _dl_signal_cexception): New functions.
+	(_dl_signal_error): Call _dl_exception_create to allocate an
+	exception object.
+	(_dl_catch_exception): New function, based on _dl_catch_error.
+	(_dl_catch_error): Implement using _dl_catch_exception.
+	* elf/dl-exception.c: New file.
+	* elf/Makefile (dl-routines): Add dl-exception.
+	(elide-routines.os): Likewise.
+	* elf/Version (ld/GLIBC_PRIVATE): Add _dl_exception_create,
+	_dl_exception_create_format, _dl_exception_free.
+	* elf/dl-deps.c (_dl_map_object_deps): Use _dl_catch_exception and
+	_dl_signal_exception.
+	* elf/dl-lookup.c (make_string): Remove.
+	(_dl_lookup_symbol_x): Use _dl_exception_create_format,
+	_dl_signal_cexception, _dl_exception_free.
+	* elf/dl-open.c (_dl_open): Use _dl_catch_exception and
+	_dl_signal_exception.
+	* elf/dl-sym.c (do_sym): Likewise.
+	* elf/dl-version.c (make_string): Remove.
+	(match_symbol): Use _dl_exception_create_format,
+	_dl_signal_cexception, _dl_exception_free.
+	(_dl_check_map_versions): Likewise.
+	* sysdeps/generic/localplt.data (ld.so): Add _dl_signal_exception,
+	_dl_catch_exception.
+	* sysdeps/unix/sysv/linux/aarch64/localplt.data (ld.so): Likewise.
+	* sysdeps/unix/sysv/linux/alpha/localplt.data (ld.so): Likewise.
+	* sysdeps/unix/sysv/linux/arm/localplt.data (ld.so): Likewise.
+	* sysdeps/unix/sysv/linux/hppa/localplt.data (ld.so): Likewise.
+	* sysdeps/unix/sysv/linux/i386/localplt.data (ld.so): Likewise.
+	* sysdeps/unix/sysv/linux/ia64/localplt.data (ld.so): Likewise.
+	* sysdeps/unix/sysv/linux/m68k/localplt.data (ld.so): Likewise.
+	* sysdeps/unix/sysv/linux/microblaze/localplt.data (ld.so):
+	Likewise.
+	* sysdeps/unix/sysv/linux/nios2/localplt.data (ld.so): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data
+	(ld.so): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data
+	(ld.so): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data (ld.so):
+	Likewise.
+	* sysdeps/unix/sysv/linux/s390/localplt.data (ld.so): Likewise.
+	* sysdeps/unix/sysv/linux/sh/localplt.data (ld.so): Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data (ld.so):
+	Likewise.
+	* sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data (ld.so):
+	Likewise.
+	* sysdeps/x86_64/localplt.data (ld.so): Likewise.
+
+2017-08-10  Florian Weimer  <fweimer@redhat.com>
+
 	* inet/net-internal.h (__inet6_scopeid_pton): Remove
 	attribute_hidden, internal_function.
 	* inet/inet6_scopeid_pton.c (__inet6_scopeid_pton): Remove
diff --git a/elf/Makefile b/elf/Makefile
index b54ebf8..d314a5f 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -31,7 +31,8 @@ routines	= $(all-dl-routines) dl-support dl-iteratephdr \
 dl-routines	= $(addprefix dl-,load lookup object reloc deps hwcaps \
 				  runtime init fini debug misc \
 				  version profile tls origin scope \
-				  execstack caller open close trampoline)
+				  execstack caller open close trampoline \
+				  exception)
 ifeq (yes,$(use-ldconfig))
 dl-routines += dl-cache
 endif
@@ -51,7 +52,7 @@ endif
 all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
 # But they are absent from the shared libc, because that code is in ld.so.
 elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \
-		    dl-sysdep
+		    dl-sysdep dl-exception
 shared-only-routines += dl-caller
 
 # ld.so uses those routines, plus some special stuff for being the program
diff --git a/elf/Versions b/elf/Versions
index e65f2fa..79ffaf7 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -28,6 +28,7 @@ libc {
     __libc_dlclose; __libc_dlopen_mode; __libc_dlsym;
 
     # Internal error handling support.  Interposes the functions in ld.so.
+    _dl_signal_exception; _dl_catch_exception;
     _dl_signal_error; _dl_catch_error;
   }
 }
@@ -68,7 +69,11 @@ ld {
     # Pointer protection.
     __pointer_chk_guard;
 
+    # Internal error handling support.
+    _dl_exception_create; _dl_exception_create_format; _dl_exception_free;
+
     # Internal error handling support.  Interposed by libc.so.
+    _dl_signal_exception; _dl_catch_exception;
     _dl_signal_error; _dl_catch_error;
 
     # Set value of a tunable.
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 1b8bac6..7c82d42 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -165,8 +165,7 @@ _dl_map_object_deps (struct link_map *map,
   const char *name;
   int errno_saved;
   int errno_reason;
-  const char *errstring;
-  const char *objname;
+  struct dl_exception exception;
 
   /* No loaded object so far.  */
   nlist = 0;
@@ -200,7 +199,6 @@ _dl_map_object_deps (struct link_map *map,
      alloca means we cannot use recursive function calls.  */
   errno_saved = errno;
   errno_reason = 0;
-  errstring = NULL;
   errno = 0;
   name = NULL;
   for (runp = known; runp; )
@@ -250,17 +248,9 @@ _dl_map_object_deps (struct link_map *map,
 		/* Store the tag in the argument structure.  */
 		args.name = name;
 
-		bool malloced;
-		int err = _dl_catch_error (&objname, &errstring, &malloced,
-					   openaux, &args);
-		if (__glibc_unlikely (errstring != NULL))
+		int err = _dl_catch_exception (&exception, openaux, &args);
+		if (__glibc_unlikely (exception.errstring != NULL))
 		  {
-		    char *new_errstring = strdupa (errstring);
-		    objname = strdupa (objname);
-		    if (malloced)
-		      free ((char *) errstring);
-		    errstring = new_errstring;
-
 		    if (err)
 		      errno_reason = err;
 		    else
@@ -313,31 +303,18 @@ _dl_map_object_deps (struct link_map *map,
 		/* We must be prepared that the addressed shared
 		   object is not available.  For filter objects the dependency
 		   must be available.  */
-		bool malloced;
-		int err = _dl_catch_error (&objname, &errstring, &malloced,
-					openaux, &args);
-
-		if (__glibc_unlikely (errstring != NULL))
+		int err = _dl_catch_exception (&exception, openaux, &args);
+		if (__glibc_unlikely (exception.errstring != NULL))
 		  {
 		    if (d->d_tag == DT_AUXILIARY)
 		      {
 			/* We are not interested in the error message.  */
-			assert (errstring != NULL);
-			if (malloced)
-			  free ((char *) errstring);
-
+			_dl_exception_free (&exception);
 			/* Simply ignore this error and continue the work.  */
 			continue;
 		      }
 		    else
 		      {
-
-			char *new_errstring = strdupa (errstring);
-			objname = strdupa (objname);
-			if (malloced)
-			  free ((char *) errstring);
-			errstring = new_errstring;
-
 			if (err)
 			  errno_reason = err;
 			else
@@ -683,6 +660,6 @@ Filters not supported with LD_TRACE_PRELINKING"));
     _dl_scope_free (old_l_initfini);
 
   if (errno_reason)
-    _dl_signal_error (errno_reason == -1 ? 0 : errno_reason, objname,
-		      NULL, errstring);
+    _dl_signal_exception (errno_reason == -1 ? 0 : errno_reason,
+			  &exception, NULL);
 }
diff --git a/elf/dl-error-skeleton.c b/elf/dl-error-skeleton.c
index 8e5888d..8de6c87 100644
--- a/elf/dl-error-skeleton.c
+++ b/elf/dl-error-skeleton.c
@@ -39,10 +39,7 @@
    _dl_signal_error.  */
 struct catch
   {
-    const char **objname;	/* Object/File name.  */
-    const char **errstring;	/* Error detail filled in here.  */
-    bool *malloced;		/* Nonzero if the string is malloced
-				   by the libc malloc.  */
+    struct dl_exception *exception; /* The exception data is stored there.  */
     volatile int *errcode;	/* Return value of _dl_signal_error.  */
     jmp_buf env;		/* longjmp here on error.  */
   };
@@ -60,11 +57,6 @@ static __thread struct catch *catch_hook attribute_tls_model_ie;
 static struct catch *catch_hook;
 #endif
 
-/* This message we return as a last resort.  We define the string in a
-   variable since we have to avoid freeing it and so have to enable
-   a pointer comparison.  See below and in dlfcn/dlerror.c.  */
-static const char _dl_out_of_memory[] = "out of memory";
-
 #if DL_ERROR_BOOTSTRAP
 /* This points to a function which is called when an continuable error is
    received.  Unlike the handling of `catch' this function may return.
@@ -76,6 +68,41 @@ static const char _dl_out_of_memory[] = "out of memory";
 static receiver_fct receiver;
 #endif /* DL_ERROR_BOOTSTRAP */
 
+/* Lossage while resolving the program's own symbols is always fatal.  */
+static void
+__attribute__ ((noreturn))
+fatal_error (int errcode, const char *objname, const char *occasion,
+	     const char *errstring)
+{
+  char buffer[1024];
+  _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n",
+		    RTLD_PROGNAME,
+		    occasion ?: N_("error while loading shared libraries"),
+		    objname, *objname ? ": " : "",
+		    errstring, errcode ? ": " : "",
+		    (errcode
+		     ? __strerror_r (errcode, buffer, sizeof buffer)
+		     : ""));
+}
+
+void
+_dl_signal_exception (int errcode, struct dl_exception *exception,
+		      const char *occasion)
+{
+  struct catch *lcatch = catch_hook;
+  if (lcatch != NULL)
+    {
+      *lcatch->exception = *exception;
+      *lcatch->errcode = errcode;
+
+      /* We do not restore the signal mask because none was saved.  */
+      __longjmp (lcatch->env[0].__jmpbuf, 1);
+    }
+  else
+    fatal_error (errcode, exception->objname, occasion, exception->errstring);
+}
+libc_hidden_def (_dl_signal_exception)
+
 void
 internal_function
 _dl_signal_error (int errcode, const char *objname, const char *occation,
@@ -86,66 +113,43 @@ _dl_signal_error (int errcode, const char *objname, const char *occation,
   if (! errstring)
     errstring = N_("DYNAMIC LINKER BUG!!!");
 
-  if (objname == NULL)
-    objname = "";
   if (lcatch != NULL)
     {
-      /* We are inside _dl_catch_error.  Return to it.  We have to
-	 duplicate the error string since it might be allocated on the
-	 stack.  The object name is always a string constant.  */
-      size_t len_objname = strlen (objname) + 1;
-      size_t len_errstring = strlen (errstring) + 1;
-
-      char *errstring_copy = malloc (len_objname + len_errstring);
-      if (errstring_copy != NULL)
-	{
-	  /* Make a copy of the object file name and the error string.  */
-	  *lcatch->objname = memcpy (__mempcpy (errstring_copy,
-						errstring, len_errstring),
-				     objname, len_objname);
-	  *lcatch->errstring = errstring_copy;
-
-	  /* If the main executable is relocated it means the libc's malloc
-	     is used.  */
-          bool malloced = true;
-#ifdef SHARED
-	  malloced = (GL(dl_ns)[LM_ID_BASE]._ns_loaded != NULL
-                      && (GL(dl_ns)[LM_ID_BASE]._ns_loaded->l_relocated != 0));
-#endif
-	  *lcatch->malloced = malloced;
-	}
-      else
-	{
-	  /* This is better than nothing.  */
-	  *lcatch->objname = "";
-	  *lcatch->errstring = _dl_out_of_memory;
-	  *lcatch->malloced = false;
-	}
-
+      _dl_exception_create (lcatch->exception, objname, errstring);
       *lcatch->errcode = errcode;
 
       /* We do not restore the signal mask because none was saved.  */
       __longjmp (lcatch->env[0].__jmpbuf, 1);
     }
   else
-    {
-      /* Lossage while resolving the program's own symbols is always fatal.  */
-      char buffer[1024];
-      _dl_fatal_printf ("%s: %s: %s%s%s%s%s\n",
-			RTLD_PROGNAME,
-			occation ?: N_("error while loading shared libraries"),
-			objname, *objname ? ": " : "",
-			errstring, errcode ? ": " : "",
-			(errcode
-			 ? __strerror_r (errcode, buffer, sizeof buffer)
-			 : ""));
-    }
+    fatal_error (errcode, objname, occation, errstring);
 }
 libc_hidden_def (_dl_signal_error)
 
 
 #if DL_ERROR_BOOTSTRAP
 void
+_dl_signal_cexception (int errcode, struct dl_exception *exception,
+		       const char *occasion)
+{
+  if (__builtin_expect (GLRO(dl_debug_mask)
+			& ~(DL_DEBUG_STATISTICS|DL_DEBUG_PRELINK), 0))
+    _dl_debug_printf ("%s: error: %s: %s (%s)\n",
+		      exception->objname, occasion,
+		      exception->errstring, receiver ? "continued" : "fatal");
+
+  if (receiver)
+    {
+      /* We are inside _dl_receive_error.  Call the user supplied
+	 handler and resume the work.  The receiver will still be
+	 installed.  */
+      (*receiver) (errcode, exception->objname, exception->errstring);
+    }
+  else
+    _dl_signal_exception (errcode, exception, occasion);
+}
+
+void
 internal_function
 _dl_signal_cerror (int errcode, const char *objname, const char *occation,
 		   const char *errstring)
@@ -167,11 +171,9 @@ _dl_signal_cerror (int errcode, const char *objname, const char *occation,
 }
 #endif /* DL_ERROR_BOOTSTRAP */
 
-
 int
-internal_function
-_dl_catch_error (const char **objname, const char **errstring,
-		 bool *mallocedp, void (*operate) (void *), void *args)
+_dl_catch_exception (struct dl_exception *exception,
+		     void (*operate) (void *), void *args)
 {
   /* We need not handle `receiver' since setting a `catch' is handled
      before it.  */
@@ -184,9 +186,7 @@ _dl_catch_error (const char **objname, const char **errstring,
 
   struct catch c;
   /* Don't use an initializer since we don't need to clear C.env.  */
-  c.objname = objname;
-  c.errstring = errstring;
-  c.malloced = mallocedp;
+  c.exception = exception;
   c.errcode = &errcode;
 
   struct catch *const old = catch_hook;
@@ -197,17 +197,30 @@ _dl_catch_error (const char **objname, const char **errstring,
     {
       (*operate) (args);
       catch_hook = old;
-      *objname = NULL;
-      *errstring = NULL;
-      *mallocedp = false;
+      *exception = (struct dl_exception) { NULL };
       return 0;
     }
 
-  /* We get here only if we longjmp'd out of OPERATE.  _dl_signal_error has
-     already stored values into *OBJNAME, *ERRSTRING, and *MALLOCEDP.  */
+  /* We get here only if we longjmp'd out of OPERATE.
+     _dl_signal_exception has already stored values into
+     *EXCEPTION.  */
   catch_hook = old;
   return errcode;
 }
+libc_hidden_def (_dl_catch_exception)
+
+int
+internal_function
+_dl_catch_error (const char **objname, const char **errstring,
+		 bool *mallocedp, void (*operate) (void *), void *args)
+{
+  struct dl_exception exception;
+  int errorcode = _dl_catch_exception (&exception, operate, args);
+  *objname = exception.objname;
+  *errstring = exception.errstring;
+  *mallocedp = exception.message_buffer == exception.errstring;
+  return errorcode;
+}
 libc_hidden_def (_dl_catch_error)
 
 #if DL_ERROR_BOOTSTRAP
diff --git a/elf/dl-exception.c b/elf/dl-exception.c
new file mode 100644
index 0000000..b4d0ca7
--- /dev/null
+++ b/elf/dl-exception.c
@@ -0,0 +1,202 @@
+/* ld.so error exception allocation and deallocation.
+   Copyright (C) 1995-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ldsodefs.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+/* This message we return as a last resort.  We define the string in a
+   variable since we have to avoid freeing it and so have to enable
+   a pointer comparison.  See below and in dlfcn/dlerror.c.  */
+static const char _dl_out_of_memory[] = "out of memory";
+
+/* Dummy allocation object used if allocating the message buffer
+   fails.  */
+static void
+oom_exception (struct dl_exception *exception)
+{
+  exception->objname = "";
+  exception->errstring = _dl_out_of_memory;
+  exception->message_buffer = NULL;
+}
+
+static void
+__attribute__ ((noreturn))
+length_mismatch (void)
+{
+  _dl_fatal_printf ("Fatal error: "
+                    "length accounting in _dl_exception_create_format\n");
+}
+
+/* Adjust the message buffer to indicate whether it is possible to
+   free it.  EXCEPTION->errstring must be a potentially deallocatable
+   pointer.  */
+static void
+adjust_message_buffer (struct dl_exception *exception)
+{
+  /* If the main executable is relocated it means the libc's malloc
+     is used.  */
+  bool malloced = true;
+#ifdef SHARED
+  malloced = (GL(dl_ns)[LM_ID_BASE]._ns_loaded != NULL
+              && (GL(dl_ns)[LM_ID_BASE]._ns_loaded->l_relocated != 0));
+#endif
+  if (malloced)
+    exception->message_buffer = (char *) exception->errstring;
+  else
+    exception->message_buffer = NULL;
+}
+
+void
+_dl_exception_create (struct dl_exception *exception, const char *objname,
+                      const char *errstring)
+{
+  if (objname == NULL)
+    objname = "";
+  size_t len_objname = strlen (objname) + 1;
+  size_t len_errstring = strlen (errstring) + 1;
+  char *errstring_copy = malloc (len_objname + len_errstring);
+  if (errstring_copy != NULL)
+    {
+      /* Make a copy of the object file name and the error string.  */
+      exception->objname = memcpy (__mempcpy (errstring_copy,
+                                              errstring, len_errstring),
+                                   objname, len_objname);
+      exception->errstring = errstring_copy;
+      adjust_message_buffer (exception);
+    }
+  else
+    oom_exception (exception);
+}
+rtld_hidden_def (_dl_exception_create)
+
+void
+_dl_exception_create_format (struct dl_exception *exception, const char *objname,
+                             const char *fmt, ...)
+{
+  if (objname == NULL)
+    objname = "";
+  size_t len_objname = strlen (objname) + 1;
+  /* Compute the length of the result.  Include room for two NUL
+     bytes.  */
+  size_t length = len_objname + 1;
+  {
+    va_list ap;
+    va_start (ap, fmt);
+    for (const char *p = fmt; *p != '\0'; ++p)
+      if (*p == '%')
+        {
+          ++p;
+          switch (*p)
+            {
+            case 's':
+              length += strlen (va_arg (ap, const char *));
+              break;
+            default:
+              /* Assumed to be '%'.  */
+              ++length;
+              break;
+            }
+        }
+      else
+        ++length;
+    va_end (ap);
+  }
+
+  if (length > PTRDIFF_MAX)
+    {
+      oom_exception (exception);
+      return;
+    }
+  char *errstring = malloc (length);
+  if (errstring == NULL)
+    {
+      oom_exception (exception);
+      return;
+    }
+  exception->errstring = errstring;
+  adjust_message_buffer (exception);
+
+  /* Copy the error message to errstring.  */
+  {
+    /* Next byte to be written in errstring.  */
+    char *wptr = errstring;
+    /* End of the allocated string.  */
+    char *const end = errstring + length;
+
+    va_list ap;
+    va_start (ap, fmt);
+
+    for (const char *p = fmt; *p != '\0'; ++p)
+      if (*p == '%')
+        {
+          ++p;
+          switch (*p)
+            {
+            case 's':
+              {
+                const char *ptr = va_arg (ap, const char *);
+                size_t len_ptr = strlen (ptr);
+                if (len_ptr > end - wptr)
+                  length_mismatch ();
+                wptr = __mempcpy (wptr, ptr, len_ptr);
+              }
+              break;
+            case '%':
+              if (wptr == end)
+                length_mismatch ();
+              *wptr = '%';
+              ++wptr;
+              break;
+            default:
+              _dl_fatal_printf ("Fatal error:"
+                                " invalid format in exception string\n");
+            }
+        }
+      else
+        {
+          if (wptr == end)
+            length_mismatch ();
+          *wptr = *p;
+          ++wptr;
+        }
+
+    if (wptr == end)
+      length_mismatch ();
+    *wptr = '\0';
+    ++wptr;
+    if (len_objname != end - wptr)
+      length_mismatch ();
+    exception->objname = memcpy (wptr, objname, len_objname);
+  }
+}
+rtld_hidden_def (_dl_exception_create_format)
+
+void
+_dl_exception_free (struct dl_exception *exception)
+{
+  free (exception->message_buffer);
+  exception->objname = NULL;
+  exception->errstring = NULL;
+  exception->message_buffer = NULL;
+}
+rtld_hidden_def (_dl_exception_free)
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 3d2369d..645dc3e 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -47,23 +47,6 @@ struct sym_val
   };
 
 
-#define make_string(string, rest...) \
-  ({									      \
-    const char *all[] = { string, ## rest };				      \
-    size_t len, cnt;							      \
-    char *result, *cp;							      \
-									      \
-    len = 1;								      \
-    for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)		      \
-      len += strlen (all[cnt]);						      \
-									      \
-    cp = result = alloca (len);						      \
-    for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)		      \
-      cp = __stpcpy (cp, all[cnt]);					      \
-									      \
-    result;								      \
-  })
-
 /* Statistics function.  */
 #ifdef SHARED
 # define bump_num_relocations() ++GL(dl_num_relocations)
@@ -843,17 +826,16 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
 	     for unversioned lookups.  */
 	  assert (version != NULL);
 	  const char *reference_name = undef_map ? undef_map->l_name : "";
-
+	  struct dl_exception exception;
 	  /* XXX We cannot translate the message.  */
-	  _dl_signal_cerror (0, DSO_FILENAME (reference_name),
-			     N_("relocation error"),
-			     make_string ("symbol ", undef_name, ", version ",
-					  version->name,
-					  " not defined in file ",
-					  version->filename,
-					  " with link time reference",
-					  res == -2
-					  ? " (no version symbols)" : ""));
+	  _dl_exception_create_format
+	    (&exception, DSO_FILENAME (reference_name),
+	     "symbol %s version %s not defined in file %s"
+	     " with link time reference%s",
+	     undef_name, version->name, version->filename,
+	     res == -2 ? " (no version symbols)" : "");
+	  _dl_signal_cexception (0, &exception, N_("relocation error"));
+	  _dl_exception_free (&exception);
 	  *ref = NULL;
 	  return 0;
 	}
@@ -869,12 +851,14 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
 	  const char *versionstr = version ? ", version " : "";
 	  const char *versionname = (version && version->name
 				     ? version->name : "");
-
+	  struct dl_exception exception;
 	  /* XXX We cannot translate the message.  */
-	  _dl_signal_cerror (0, DSO_FILENAME (reference_name),
-			     N_("symbol lookup error"),
-			     make_string ("undefined symbol: ", undef_name,
-					  versionstr, versionname));
+	  _dl_exception_create_format
+	    (&exception, DSO_FILENAME (reference_name),
+	     "undefined symbol: %s%s%s",
+	     undef_name, versionstr, versionname);
+	  _dl_signal_cexception (0, &exception, N_("symbol lookup error"));
+	  _dl_exception_free (&exception);
 	}
       *ref = NULL;
       return 0;
diff --git a/elf/dl-open.c b/elf/dl-open.c
index cec54db..91a1d1a 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -643,11 +643,8 @@ no more namespaces available for dlmopen()"));
   args.argv = argv;
   args.env = env;
 
-  const char *objname;
-  const char *errstring;
-  bool malloced;
-  int errcode = _dl_catch_error (&objname, &errstring, &malloced,
-				 dl_open_worker, &args);
+  struct dl_exception exception;
+  int errcode = _dl_catch_exception (&exception, dl_open_worker, &args);
 
 #if defined USE_LDCONFIG && !defined MAP_COPY
   /* We must unmap the cache file.  */
@@ -655,7 +652,7 @@ no more namespaces available for dlmopen()"));
 #endif
 
   /* See if an error occurred during loading.  */
-  if (__glibc_unlikely (errstring != NULL))
+  if (__glibc_unlikely (exception.errstring != NULL))
     {
       /* Remove the object from memory.  It may be in an inconsistent
 	 state if relocation failed, for example.  */
@@ -679,28 +676,8 @@ no more namespaces available for dlmopen()"));
       /* Release the lock.  */
       __rtld_lock_unlock_recursive (GL(dl_load_lock));
 
-      /* Make a local copy of the error string so that we can release the
-	 memory allocated for it.  */
-      size_t len_errstring = strlen (errstring) + 1;
-      char *local_errstring;
-      if (objname == errstring + len_errstring)
-	{
-	  size_t total_len = len_errstring + strlen (objname) + 1;
-	  local_errstring = alloca (total_len);
-	  memcpy (local_errstring, errstring, total_len);
-	  objname = local_errstring + len_errstring;
-	}
-      else
-	{
-	  local_errstring = alloca (len_errstring);
-	  memcpy (local_errstring, errstring, len_errstring);
-	}
-
-      if (malloced)
-	free ((char *) errstring);
-
       /* Reraise the error.  */
-      _dl_signal_error (errcode, objname, NULL, local_errstring);
+      _dl_signal_exception (errcode, &exception, NULL);
     }
 
   assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT);
diff --git a/elf/dl-sym.c b/elf/dl-sym.c
index 7cd6e97..fb54a91 100644
--- a/elf/dl-sym.c
+++ b/elf/dl-sym.c
@@ -119,26 +119,11 @@ do_sym (void *handle, const char *name, void *who,
 	  args.refp = &ref;
 
 	  THREAD_GSCOPE_SET_FLAG ();
-
-	  const char *objname;
-	  const char *errstring = NULL;
-	  bool malloced;
-	  int err = _dl_catch_error (&objname, &errstring, &malloced,
-				     call_dl_lookup, &args);
-
+	  struct dl_exception exception;
+	  int err = _dl_catch_exception (&exception, call_dl_lookup, &args);
 	  THREAD_GSCOPE_RESET_FLAG ();
-
-	  if (__glibc_unlikely (errstring != NULL))
-	    {
-	      /* The lookup was unsuccessful.  Rethrow the error.  */
-	      char *errstring_dup = strdupa (errstring);
-	      char *objname_dup = strdupa (objname);
-	      if (malloced)
-		free ((char *) errstring);
-
-	      _dl_signal_error (err, objname_dup, NULL, errstring_dup);
-	      /* NOTREACHED */
-	    }
+	  if (__glibc_unlikely (exception.errstring != NULL))
+	    _dl_signal_exception (err, &exception, NULL);
 
 	  result = args.map;
 	}
diff --git a/elf/dl-version.c b/elf/dl-version.c
index c00078e..c0d76ad 100644
--- a/elf/dl-version.c
+++ b/elf/dl-version.c
@@ -27,25 +27,6 @@
 
 #include <assert.h>
 
-
-#define make_string(string, rest...) \
-  ({									      \
-    const char *all[] = { string, ## rest };				      \
-    size_t len, cnt;							      \
-    char *result, *cp;							      \
-									      \
-    len = 1;								      \
-    for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)		      \
-      len += strlen (all[cnt]);						      \
-									      \
-    cp = result = alloca (len);						      \
-    for (cnt = 0; cnt < sizeof (all) / sizeof (all[0]); ++cnt)		      \
-      cp = __stpcpy (cp, all[cnt]);					      \
-									      \
-    result;								      \
-  })
-
-
 static inline struct link_map *
 __attribute ((always_inline))
 find_needed (const char *name, struct link_map *map)
@@ -78,8 +59,8 @@ match_symbol (const char *name, Lmid_t ns, ElfW(Word) hash, const char *string,
   ElfW(Addr) def_offset;
   ElfW(Verdef) *def;
   /* Initialize to make the compiler happy.  */
-  const char *errstring = NULL;
   int result = 0;
+  struct dl_exception exception;
 
   /* Display information about what we are doing while debugging.  */
   if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_VERSIONS))
@@ -96,8 +77,9 @@ checking for version `%s' in file %s [%lu] required by file %s [%lu]\n",
       if (verbose)
 	{
 	  /* XXX We cannot translate the messages.  */
-	  errstring = make_string ("\
-no version information available (required by ", name, ")");
+	  _dl_exception_create_format
+	    (&exception, DSO_FILENAME (map->l_name),
+	     "no version information available (required by %s)", name);
 	  goto call_cerror;
 	}
       return 0;
@@ -116,10 +98,10 @@ no version information available (required by ", name, ")");
 	  char buf[20];
 	  buf[sizeof (buf) - 1] = '\0';
 	  /* XXX We cannot translate the message.  */
-	  errstring = make_string ("unsupported version ",
-				   _itoa (def->vd_version,
-					  &buf[sizeof (buf) - 1], 10, 0),
-				   " of Verdef record");
+	  _dl_exception_create_format
+	    (&exception, DSO_FILENAME (map->l_name),
+	     "unsupported version %s of Verdef record",
+	     _itoa (def->vd_version, &buf[sizeof (buf) - 1], 10, 0));
 	  result = 1;
 	  goto call_cerror;
 	}
@@ -150,20 +132,22 @@ no version information available (required by ", name, ")");
       if (verbose)
 	{
 	  /* XXX We cannot translate the message.  */
-	  errstring = make_string ("weak version `", string,
-				   "' not found (required by ", name, ")");
+	  _dl_exception_create_format
+	    (&exception, DSO_FILENAME (map->l_name),
+	     "weak version `%s' not found (required by %s)", string, name);
 	  goto call_cerror;
 	}
       return 0;
     }
 
   /* XXX We cannot translate the message.  */
-  errstring = make_string ("version `", string, "' not found (required by ",
-			   name, ")");
+  _dl_exception_create_format
+    (&exception, DSO_FILENAME (map->l_name),
+     "version `%s' not found (required by %s)", string, name);
   result = 1;
  call_cerror:
-  _dl_signal_cerror (0, DSO_FILENAME (map->l_name),
-		     N_("version lookup error"), errstring);
+  _dl_signal_cexception (0, &exception, N_("version lookup error"));
+  _dl_exception_free (&exception);
   return result;
 }
 
@@ -181,8 +165,8 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
   /* We need to find out which is the highest version index used
     in a dependecy.  */
   unsigned int ndx_high = 0;
+  struct dl_exception exception;
   /* Initialize to make the compiler happy.  */
-  const char *errstring = NULL;
   int errval = 0;
 
   /* If we don't have a string table, we must be ok.  */
@@ -205,13 +189,12 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
 	  char buf[20];
 	  buf[sizeof (buf) - 1] = '\0';
 	  /* XXX We cannot translate the message.  */
-	  errstring = make_string ("unsupported version ",
-				   _itoa (ent->vn_version,
-					  &buf[sizeof (buf) - 1], 10, 0),
-				   " of Verneed record\n");
+	  _dl_exception_create_format
+	    (&exception, DSO_FILENAME (map->l_name),
+	     "unsupported version %s of Verneed record",
+	     _itoa (ent->vn_version, &buf[sizeof (buf) - 1], 10, 0));
 	call_error:
-	  _dl_signal_error (errval, DSO_FILENAME (map->l_name),
-			    NULL, errstring);
+	  _dl_signal_exception (errval, &exception, NULL);
 	}
 
       while (1)
@@ -293,7 +276,9 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode)
 	calloc (ndx_high + 1, sizeof (*map->l_versions));
       if (__glibc_unlikely (map->l_versions == NULL))
 	{
-	  errstring = N_("cannot allocate version reference table");
+	  _dl_exception_create
+	    (&exception, DSO_FILENAME (map->l_name),
+	     N_("cannot allocate version reference table"));
 	  errval = ENOMEM;
 	  goto call_error;
 	}
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 4508365..1c0b9cb 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -732,31 +732,88 @@ _dl_dprintf (int fd, const char *fmt, ...)
   while (1)
 
 
-/* This function is called by all the internal dynamic linker functions
-   when they encounter an error.  ERRCODE is either an `errno' code or
-   zero; OBJECT is the name of the problematical shared object, or null if
-   it is a general problem; ERRSTRING is a string describing the specific
-   problem.  */
+/* An exception raised by the _dl_signal_error function family and
+   caught by _dl_catch_error function family.  Exceptions themselves
+   are copied as part of the raise operation, but the strings are
+   not.  */
+struct dl_exception
+{
+  const char *objname;
+  const char *errstring;
+
+  /* This buffer typically stores both objname and errstring
+     above.  */
+  char *message_buffer;
+};
+
+/* Creates a new exception.  This calls malloc; if allocation fails,
+   dummy values are inserted.  OBJECT is the name of the problematical
+   shared object, or null if its a general problem.  ERRSTRING is a
+   string describing the specific problem.  */
+void _dl_exception_create (struct dl_exception *, const char *object,
+			   const char *errstring)
+  __attribute__ ((nonnull (1, 3)));
+rtld_hidden_proto (_dl_exception_create)
+
+/* Like _dl_exception_create, but create errstring from a format
+   string FMT.  Currently, only "%s" and "%%" are supported as format
+   directives.  */
+void _dl_exception_create_format (struct dl_exception *, const char *objname,
+				  const char *fmt, ...)
+  __attribute__ ((nonnull (1, 3), format (printf, 3, 4)));
+rtld_hidden_proto (_dl_exception_create_format)
+
+/* Deallocate the exception, freeing allocated buffers (if
+   possible).  */
+void _dl_exception_free (struct dl_exception *)
+  __attribute__ ((nonnull (1)));
+rtld_hidden_proto (_dl_exception_free)
+
+/* This function is called by all the internal dynamic linker
+   functions when they encounter an error.  ERRCODE is either an
+   `errno' code or zero; it specifies the return value of
+   _dl_catch_error.  OCCASION is included in the error message if the
+   process is terminated immediately.  */
+void _dl_signal_exception (int errcode, struct dl_exception *,
+			   const char *occasion)
+  __attribute__ ((__noreturn__));
+libc_hidden_proto (_dl_signal_exception)
+
+/* Like _dl_signal_exception, but creates the exception first.  */
 extern void _dl_signal_error (int errcode, const char *object,
-			      const char *occurred, const char *errstring)
+			      const char *occasion, const char *errstring)
      internal_function __attribute__ ((__noreturn__));
 libc_hidden_proto (_dl_signal_error)
 
-/* Like _dl_signal_error, but may return when called in the context of
-   _dl_receive_error.  This is only used during ld.so bootstrap.  In
-   static and profiled builds, this is equivalent to
-   _dl_signal_error.  */
+/* Like _dl_signal_exception, but may return when called in the
+   context of _dl_receive_error.  This is only used during ld.so
+   bootstrap.  In static and profiled builds, this is equivalent to
+   _dl_signal_exception.  */
+#if IS_IN (rtld)
+extern void _dl_signal_cexception (int errcode, struct dl_exception *,
+				   const char *occasion) attribute_hidden;
+#else
+__attribute__ ((always_inline))
+static inline void
+_dl_signal_cexception (int errcode, struct dl_exception *exception,
+		       const char *occasion)
+{
+  _dl_signal_exception (errcode, exception, occasion);
+}
+#endif
+
+/* See _dl_signal_cexception above.  */
 #if IS_IN (rtld)
 extern void _dl_signal_cerror (int errcode, const char *object,
-			       const char *occation, const char *errstring)
+			       const char *occasion, const char *errstring)
      internal_function attribute_hidden;
 #else
 __attribute__ ((always_inline))
 static inline void
 _dl_signal_cerror (int errcode, const char *object,
-			       const char *occation, const char *errstring)
+			       const char *occasion, const char *errstring)
 {
-  _dl_signal_error (errcode, object, occation, errstring);
+  _dl_signal_error (errcode, object, occasion, errstring);
 }
 #endif
 
@@ -768,20 +825,28 @@ extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *),
 			       void *args)
      internal_function attribute_hidden;
 
-/* Call OPERATE, catching errors from `dl_signal_error'.  If there is no
-   error, *ERRSTRING is set to null.  If there is an error, *ERRSTRING is
-   set to a string constructed from the strings passed to _dl_signal_error,
-   and the error code passed is the return value and *OBJNAME is set to
-   the object name which experienced the problems.  ERRSTRING if nonzero
-   points to a malloc'ed string which the caller has to free after use.
-   ARGS is passed as argument to OPERATE.  MALLOCEDP is set to true only
-   if the returned string is allocated using the libc's malloc.  */
+/* Call OPERATE, catching errors from `_dl_signal_error' and related
+   functions.  If there is no error, *ERRSTRING is set to null.  If
+   there is an error, *ERRSTRING is set to a string constructed from
+   the strings passed to _dl_signal_error, and the error code passed
+   is the return value and *OBJNAME is set to the object name which
+   experienced the problems.  ERRSTRING if nonzero points to a
+   malloc'ed string which the caller has to free after use.  ARGS is
+   passed as argument to OPERATE.  MALLOCEDP is set to true only if
+   the returned string is allocated using the libc's malloc.  */
 extern int _dl_catch_error (const char **objname, const char **errstring,
 			    bool *mallocedp, void (*operate) (void *),
 			    void *args)
      internal_function;
 libc_hidden_proto (_dl_catch_error)
 
+/* Call OPERATE (ARGS).  If no error occurs, set *EXCEPTION to zero.
+   Otherwise, store a copy of the raised exception in *EXCEPTION,
+   which has to be freed by _dl_exception_free.  */
+int _dl_catch_exception (struct dl_exception *exception,
+			 void (*operate) (void *), void *args);
+libc_hidden_proto (_dl_catch_exception)
+
 /* Open the shared object NAME and map in its segments.
    LOADER's DT_RPATH is used in searching for NAME.
    If the object is already opened, returns its existing map.  */
diff --git a/sysdeps/generic/localplt.data b/sysdeps/generic/localplt.data
index 81c741b..2d5c66a 100644
--- a/sysdeps/generic/localplt.data
+++ b/sysdeps/generic/localplt.data
@@ -16,3 +16,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/aarch64/localplt.data b/sysdeps/unix/sysv/linux/aarch64/localplt.data
index bb18ff9..a60053b 100644
--- a/sysdeps/unix/sysv/linux/aarch64/localplt.data
+++ b/sysdeps/unix/sysv/linux/aarch64/localplt.data
@@ -18,3 +18,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/alpha/localplt.data b/sysdeps/unix/sysv/linux/alpha/localplt.data
index 1f0e3b4..c69eb04 100644
--- a/sysdeps/unix/sysv/linux/alpha/localplt.data
+++ b/sysdeps/unix/sysv/linux/alpha/localplt.data
@@ -35,3 +35,5 @@ ld.so: free + RELA R_ALPHA_GLOB_DAT
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error + RELA R_ALPHA_GLOB_DAT
 ld.so: _dl_catch_error + RELA R_ALPHA_GLOB_DAT
+ld.so: _dl_signal_exception + RELA R_ALPHA_GLOB_DAT
+ld.so: _dl_catch_exception + RELA R_ALPHA_GLOB_DAT
diff --git a/sysdeps/unix/sysv/linux/arm/localplt.data b/sysdeps/unix/sysv/linux/arm/localplt.data
index 19d3299..7bd541c 100644
--- a/sysdeps/unix/sysv/linux/arm/localplt.data
+++ b/sysdeps/unix/sysv/linux/arm/localplt.data
@@ -17,3 +17,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/hppa/localplt.data b/sysdeps/unix/sysv/linux/hppa/localplt.data
index db9e24b..3279c0a 100644
--- a/sysdeps/unix/sysv/linux/hppa/localplt.data
+++ b/sysdeps/unix/sysv/linux/hppa/localplt.data
@@ -21,3 +21,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/i386/localplt.data b/sysdeps/unix/sysv/linux/i386/localplt.data
index 8ea4333..f6f20a5 100644
--- a/sysdeps/unix/sysv/linux/i386/localplt.data
+++ b/sysdeps/unix/sysv/linux/i386/localplt.data
@@ -16,3 +16,5 @@ ld.so: free + REL R_386_GLOB_DAT
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error + REL R_386_GLOB_DAT
 ld.so: _dl_catch_error + REL R_386_GLOB_DAT
+ld.so: _dl_signal_exception + REL R_386_GLOB_DAT
+ld.so: _dl_catch_exception + REL R_386_GLOB_DAT
diff --git a/sysdeps/unix/sysv/linux/ia64/localplt.data b/sysdeps/unix/sysv/linux/ia64/localplt.data
index fd2b98c..3820e2a 100644
--- a/sysdeps/unix/sysv/linux/ia64/localplt.data
+++ b/sysdeps/unix/sysv/linux/ia64/localplt.data
@@ -15,3 +15,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/m68k/localplt.data b/sysdeps/unix/sysv/linux/m68k/localplt.data
index 1a2acfd..c70d6ea 100644
--- a/sysdeps/unix/sysv/linux/m68k/localplt.data
+++ b/sysdeps/unix/sysv/linux/m68k/localplt.data
@@ -15,3 +15,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/microblaze/localplt.data b/sysdeps/unix/sysv/linux/microblaze/localplt.data
index ca476be..8ca2389 100644
--- a/sysdeps/unix/sysv/linux/microblaze/localplt.data
+++ b/sysdeps/unix/sysv/linux/microblaze/localplt.data
@@ -16,3 +16,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/nios2/localplt.data b/sysdeps/unix/sysv/linux/nios2/localplt.data
index b0d6dca..4430a58 100644
--- a/sysdeps/unix/sysv/linux/nios2/localplt.data
+++ b/sysdeps/unix/sysv/linux/nios2/localplt.data
@@ -36,3 +36,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data
index 5000631..e822e0a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data
@@ -14,3 +14,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data
index 1c20d2f..fead931 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data
@@ -44,3 +44,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data
index 6f8ed25..c120933 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data
@@ -13,3 +13,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/s390/localplt.data b/sysdeps/unix/sysv/linux/s390/localplt.data
index 5000631..e822e0a 100644
--- a/sysdeps/unix/sysv/linux/s390/localplt.data
+++ b/sysdeps/unix/sysv/linux/s390/localplt.data
@@ -14,3 +14,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/sh/localplt.data b/sysdeps/unix/sysv/linux/sh/localplt.data
index f1f5eff..2753547 100644
--- a/sysdeps/unix/sysv/linux/sh/localplt.data
+++ b/sysdeps/unix/sysv/linux/sh/localplt.data
@@ -19,3 +19,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data b/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data
index 2f6ff3c..1668f40 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data
@@ -26,3 +26,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data b/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data
index 912bd1a..b881b90 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data
@@ -27,3 +27,5 @@ ld.so: free
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error
 ld.so: _dl_catch_error
+ld.so: _dl_signal_exception
+ld.so: _dl_catch_exception
diff --git a/sysdeps/x86_64/localplt.data b/sysdeps/x86_64/localplt.data
index a1840cf..c27a02b 100644
--- a/sysdeps/x86_64/localplt.data
+++ b/sysdeps/x86_64/localplt.data
@@ -18,3 +18,5 @@ ld.so: free + RELA R_X86_64_GLOB_DAT
 # The TLS-enabled version of these functions is interposed from libc.so.
 ld.so: _dl_signal_error + RELA R_X86_64_GLOB_DAT
 ld.so: _dl_catch_error + RELA R_X86_64_GLOB_DAT
+ld.so: _dl_signal_exception + RELA R_X86_64_GLOB_DAT
+ld.so: _dl_catch_exception + RELA R_X86_64_GLOB_DAT

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                                          |   60 ++++++
 elf/Makefile                                       |    5 +-
 elf/Versions                                       |    5 +
 elf/dl-deps.c                                      |   39 +---
 elf/dl-error-skeleton.c                            |  147 ++++++++-------
 elf/dl-exception.c                                 |  202 ++++++++++++++++++++
 elf/dl-lookup.c                                    |   48 ++---
 elf/dl-open.c                                      |   31 +---
 elf/dl-sym.c                                       |   23 +--
 elf/dl-version.c                                   |   65 +++----
 sysdeps/generic/ldsodefs.h                         |  107 +++++++++--
 sysdeps/generic/localplt.data                      |    2 +
 sysdeps/unix/sysv/linux/aarch64/localplt.data      |    2 +
 sysdeps/unix/sysv/linux/alpha/localplt.data        |    2 +
 sysdeps/unix/sysv/linux/arm/localplt.data          |    2 +
 sysdeps/unix/sysv/linux/hppa/localplt.data         |    2 +
 sysdeps/unix/sysv/linux/i386/localplt.data         |    2 +
 sysdeps/unix/sysv/linux/ia64/localplt.data         |    2 +
 sysdeps/unix/sysv/linux/m68k/localplt.data         |    2 +
 sysdeps/unix/sysv/linux/microblaze/localplt.data   |    2 +
 sysdeps/unix/sysv/linux/nios2/localplt.data        |    2 +
 .../sysv/linux/powerpc/powerpc32/fpu/localplt.data |    2 +
 .../linux/powerpc/powerpc32/nofpu/localplt.data    |    2 +
 .../sysv/linux/powerpc/powerpc64/localplt.data     |    2 +
 sysdeps/unix/sysv/linux/s390/localplt.data         |    2 +
 sysdeps/unix/sysv/linux/sh/localplt.data           |    2 +
 .../unix/sysv/linux/sparc/sparc32/localplt.data    |    2 +
 .../unix/sysv/linux/sparc/sparc64/localplt.data    |    2 +
 sysdeps/x86_64/localplt.data                       |    2 +
 29 files changed, 529 insertions(+), 239 deletions(-)
 create mode 100644 elf/dl-exception.c


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]