aboutsummaryrefslogtreecommitdiff
path: root/elf/dl-error-skeleton.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2017-08-10 13:40:22 +0200
committerFlorian Weimer <fweimer@redhat.com>2017-08-10 16:54:57 +0200
commit2449ae7b2da24c9940962304a3e44bc80e389265 (patch)
treec2cfdcfc3a90731d2da26dda79984eda95e9079e /elf/dl-error-skeleton.c
parentf87cc2bfba9b844da48a63441c6099342b1551c7 (diff)
downloadglibc-2449ae7b2da24c9940962304a3e44bc80e389265.zip
glibc-2449ae7b2da24c9940962304a3e44bc80e389265.tar.gz
glibc-2449ae7b2da24c9940962304a3e44bc80e389265.tar.bz2
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.
Diffstat (limited to 'elf/dl-error-skeleton.c')
-rw-r--r--elf/dl-error-skeleton.c147
1 files changed, 80 insertions, 67 deletions
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