aboutsummaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-05-10 19:02:19 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-05-10 23:47:00 +0000
commit630caa95d46191220dd457c2ae2d06460cb4f71b (patch)
treec3631054a3f71b1a7688c2a846bdb39e047a02b7 /libexec
parent5e7cdf1817924f8ae0333c0b53c2da32f35b65ea (diff)
downloadsrc-630caa95d46191220dd457c2ae2d06460cb4f71b.tar.gz
src-630caa95d46191220dd457c2ae2d06460cb4f71b.zip
Diffstat (limited to 'libexec')
-rw-r--r--libexec/rtld-elf/rtld.c37
1 files changed, 25 insertions, 12 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index fce455a0ee79..75c502e8cc85 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -81,6 +81,10 @@ extern struct r_debug r_debug; /* For GDB */
extern int _thread_autoinit_dummy_decl;
extern void (*__cleanup)(void);
+struct dlerror_save {
+ int seen;
+ char *msg;
+};
/*
* Function declarations.
@@ -100,8 +104,8 @@ static Obj_Entry *dlopen_object(const char *name, int fd, Obj_Entry *refobj,
static Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int);
static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *);
static bool donelist_check(DoneList *, const Obj_Entry *);
-static void errmsg_restore(char *);
-static char *errmsg_save(void);
+static void errmsg_restore(struct dlerror_save *);
+static struct dlerror_save *errmsg_save(void);
static void *fill_search_info(const char *, size_t, void *);
static char *find_library(const char *, const Obj_Entry *, int *);
static const char *gethints(bool);
@@ -941,10 +945,16 @@ _rtld_error(const char *fmt, ...)
/*
* Return a dynamically-allocated copy of the current error message, if any.
*/
-static char *
+static struct dlerror_save *
errmsg_save(void)
{
- return (xstrdup(lockinfo.dlerror_loc()));
+ struct dlerror_save *res;
+
+ res = xmalloc(sizeof(*res));
+ res->seen = *lockinfo.dlerror_seen();
+ if (res->seen == 0)
+ res->msg = xstrdup(lockinfo.dlerror_loc());
+ return (res);
}
/*
@@ -952,14 +962,17 @@ errmsg_save(void)
* by errmsg_save(). The copy is freed.
*/
static void
-errmsg_restore(char *saved_msg)
+errmsg_restore(struct dlerror_save *saved_msg)
{
- if (saved_msg == NULL)
- _rtld_error("");
- else {
- _rtld_error("%s", saved_msg);
- free(saved_msg);
+ if (saved_msg == NULL || saved_msg->seen == 1) {
+ *lockinfo.dlerror_seen() = 1;
+ } else {
+ *lockinfo.dlerror_seen() = 0;
+ strlcpy(lockinfo.dlerror_loc(), saved_msg->msg,
+ lockinfo.dlerror_loc_sz);
+ free(saved_msg->msg);
}
+ free(saved_msg);
}
static const char *
@@ -2736,7 +2749,7 @@ static void
objlist_call_fini(Objlist *list, Obj_Entry *root, RtldLockState *lockstate)
{
Objlist_Entry *elm;
- char *saved_msg;
+ struct dlerror_save *saved_msg;
Elf_Addr *fini_addr;
int index;
@@ -2812,7 +2825,7 @@ objlist_call_init(Objlist *list, RtldLockState *lockstate)
{
Objlist_Entry *elm;
Obj_Entry *obj;
- char *saved_msg;
+ struct dlerror_save *saved_msg;
Elf_Addr *init_addr;
void (*reg)(void (*)(void));
int index;