From: Stas Sergeev <stsp2@yandex.ru>
To: libc-alpha@sourceware.org
Cc: Stas Sergeev <stsp2@yandex.ru>
Subject: [PATCH 04/13] elf: split _dl_map_object_from_fd() into reusable parts
Date: Sat, 18 Mar 2023 21:51:01 +0500 [thread overview]
Message-ID: <20230318165110.3672749-5-stsp2@yandex.ru> (raw)
In-Reply-To: <20230318165110.3672749-1-stsp2@yandex.ru>
This is mostly a mechanical split, with just a very minor moves
of 2 small code fragments. This change should introduce no
functional differences.
The test-suite was run on x86_64/64 and showed no regressions.
Signed-off-by: Stas Sergeev <stsp2@yandex.ru>
---
elf/dl-load.c | 317 ++++++++++++++++++++++++++++----------------------
1 file changed, 175 insertions(+), 142 deletions(-)
diff --git a/elf/dl-load.c b/elf/dl-load.c
index ab8b648687..9e0e63b9a3 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -929,147 +929,25 @@ _dl_process_pt_gnu_property (struct link_map *l, int fd, const ElfW(Phdr) *ph)
}
}
-
-/* Map in the shared object NAME, actually located in REALNAME, and already
- opened on FD. */
-
-#ifndef EXTERNAL_MAP_FROM_FD
-static
-#endif
-struct link_map *
-_dl_map_object_from_fd (const char *name, const char *origname, int fd,
- struct filebuf *fbp, char *realname,
- struct link_map *loader, int l_type, int mode,
- void **stack_endp, Lmid_t nsid)
+static int
+_ld_map_object_1 (struct link_map *l, int fd,
+ struct filebuf *fbp,
+ int mode, struct link_map *loader,
+ void **stack_endp, int *errval_p,
+ const char **errstring_p)
{
- struct link_map *l = NULL;
const ElfW(Ehdr) *header;
const ElfW(Phdr) *phdr;
const ElfW(Phdr) *ph;
size_t maplength;
int type;
/* Initialize to keep the compiler happy. */
- const char *errstring = NULL;
- int errval = 0;
- struct r_debug *r = _dl_debug_update (nsid);
- bool make_consistent = false;
-
- /* Get file information. To match the kernel behavior, do not fill
- in this information for the executable in case of an explicit
- loader invocation. */
- struct r_file_id id;
- if (mode & __RTLD_OPENEXEC)
- {
- assert (nsid == LM_ID_BASE);
- memset (&id, 0, sizeof (id));
- }
- else
- {
- if (__glibc_unlikely (!_dl_get_file_id (fd, &id)))
- {
- errstring = N_("cannot stat shared object");
- lose_errno:
- errval = errno;
- lose:
- /* The file might already be closed. */
- if (fd != -1)
- __close_nocancel (fd);
- if (l != NULL && l->l_map_start != 0)
- _dl_unmap_segments (l);
- if (l != NULL && l->l_origin != (char *) -1l)
- free ((char *) l->l_origin);
- if (l != NULL && !l->l_libname->dont_free)
- free (l->l_libname);
- if (l != NULL && l->l_phdr_allocated)
- free ((void *) l->l_phdr);
- free (l);
- free (realname);
-
- if (make_consistent && r != NULL)
- {
- r->r_state = RT_CONSISTENT;
- _dl_debug_state ();
- LIBC_PROBE (map_failed, 2, nsid, r);
- }
-
- _dl_signal_error (errval, name, NULL, errstring);
- }
-
- /* Look again to see if the real name matched another already loaded. */
- for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
- if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id))
- {
- /* The object is already loaded.
- Just bump its reference count and return it. */
- __close_nocancel (fd);
-
- /* If the name is not in the list of names for this object add
- it. */
- free (realname);
- add_name_to_object (l, name);
-
- return l;
- }
- }
-
-#ifdef SHARED
- /* When loading into a namespace other than the base one we must
- avoid loading ld.so since there can only be one copy. Ever. */
- if (__glibc_unlikely (nsid != LM_ID_BASE)
- && (_dl_file_id_match_p (&id, &GL(dl_rtld_map).l_file_id)
- || _dl_name_match_p (name, &GL(dl_rtld_map))))
- {
- /* This is indeed ld.so. Create a new link_map which refers to
- the real one for almost everything. */
- l = _dl_new_object (realname, name, l_type, loader, mode, nsid);
- if (l == NULL)
- goto fail_new;
-
- /* Refer to the real descriptor. */
- l->l_real = &GL(dl_rtld_map);
-
- /* Copy l_addr and l_ld to avoid a GDB warning with dlmopen(). */
- l->l_addr = l->l_real->l_addr;
- l->l_ld = l->l_real->l_ld;
-
- /* No need to bump the refcount of the real object, ld.so will
- never be unloaded. */
- __close_nocancel (fd);
-
- /* Add the map for the mirrored object to the object list. */
- _dl_add_to_namespace_list (l, nsid);
-
- return l;
- }
-#endif
-
- if (mode & RTLD_NOLOAD)
- {
- /* We are not supposed to load the object unless it is already
- loaded. So return now. */
- free (realname);
- __close_nocancel (fd);
- return NULL;
- }
-
- /* Print debugging message. */
- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
- _dl_debug_printf ("file=%s [%lu]; generating link map\n", name, nsid);
+#define errstring (*errstring_p)
+#define errval (*errval_p)
/* This is the ELF header. We read it in `open_verify'. */
header = (void *) fbp->buf;
- /* Enter the new object in the list of loaded objects. */
- l = _dl_new_object (realname, name, l_type, loader, mode, nsid);
- if (__glibc_unlikely (l == NULL))
- {
-#ifdef SHARED
- fail_new:
-#endif
- errstring = N_("cannot create shared object descriptor");
- goto lose_errno;
- }
-
/* Extract the remaining details we need from the ELF header
and then read in the program header table. */
l->l_entry = header->e_entry;
@@ -1093,7 +971,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
/* On most platforms presume that PT_GNU_STACK is absent and the stack is
* executable. Other platforms default to a nonexecutable stack and don't
* need PT_GNU_STACK to do so. */
- unsigned int stack_flags = DEFAULT_STACK_PERMS;
+ unsigned int stack_flags = DEFAULT_STACK_PERMS;
{
/* Scan the program header table, collecting its load commands. */
@@ -1386,15 +1264,6 @@ cannot enable executable stack as shared object requires");
break;
}
- /* We are done mapping in the file. We no longer need the descriptor. */
- if (__glibc_unlikely (__close_nocancel (fd) != 0))
- {
- errstring = N_("cannot close file descriptor");
- goto lose_errno;
- }
- /* Signal that we closed the file. */
- fd = -1;
-
/* Failures before this point are handled locally via lose.
There are no more failures in this function until return,
to change that the cleanup handling needs to be updated. */
@@ -1419,6 +1288,23 @@ cannot enable executable stack as shared object requires");
(unsigned long int) l->l_phdr,
(int) sizeof (void *) * 2, l->l_phnum);
+ return 0;
+
+lose_errno:
+ errval = errno;
+lose:
+ return -1;
+
+#undef errval
+#undef errstring
+}
+
+static void
+_ld_map_object_2 (struct link_map *l, int mode,
+ struct r_file_id id, const char *origname,
+ Lmid_t nsid, struct r_debug *r,
+ bool *make_consistent_p)
+{
/* Set up the symbol hash table. */
_dl_setup_hash (l);
@@ -1510,7 +1396,7 @@ cannot enable executable stack as shared object requires");
r->r_state = RT_ADD;
_dl_debug_state ();
LIBC_PROBE (map_start, 2, nsid, r);
- make_consistent = true;
+ *make_consistent_p = true;
}
else
assert (r->r_state == RT_ADD);
@@ -1520,10 +1406,157 @@ cannot enable executable stack as shared object requires");
if (!GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
_dl_audit_objopen (l, nsid);
#endif
+}
+
+/* Map in the shared object NAME, actually located in REALNAME, and already
+ opened on FD. */
+
+#ifndef EXTERNAL_MAP_FROM_FD
+static
+#endif
+struct link_map *
+_dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ struct filebuf *fbp, char *realname,
+ struct link_map *loader, int l_type, int mode,
+ void **stack_endp, Lmid_t nsid)
+{
+ struct link_map *l = NULL;
+ /* Initialize to keep the compiler happy. */
+ const char *errstring = NULL;
+ int errval = 0;
+ struct r_debug *r = _dl_debug_update (nsid);
+ bool make_consistent = false;
+
+ /* Get file information. To match the kernel behavior, do not fill
+ in this information for the executable in case of an explicit
+ loader invocation. */
+ struct r_file_id id;
+ if (mode & __RTLD_OPENEXEC)
+ {
+ assert (nsid == LM_ID_BASE);
+ memset (&id, 0, sizeof (id));
+ }
+ else
+ {
+ if (__glibc_unlikely (!_dl_get_file_id (fd, &id)))
+ {
+ errstring = N_("cannot stat shared object");
+ lose_errno:
+ errval = errno;
+ lose:
+ /* The file might already be closed. */
+ if (fd != -1)
+ __close_nocancel (fd);
+ if (l != NULL && l->l_map_start != 0)
+ _dl_unmap_segments (l);
+ if (l != NULL && l->l_origin != (char *) -1l)
+ free ((char *) l->l_origin);
+ if (l != NULL && !l->l_libname->dont_free)
+ free (l->l_libname);
+ if (l != NULL && l->l_phdr_allocated)
+ free ((void *) l->l_phdr);
+ free (l);
+ free (realname);
+
+ if (make_consistent && r != NULL)
+ {
+ r->r_state = RT_CONSISTENT;
+ _dl_debug_state ();
+ LIBC_PROBE (map_failed, 2, nsid, r);
+ }
+
+ _dl_signal_error (errval, name, NULL, errstring);
+ }
+
+ /* Look again to see if the real name matched another already loaded. */
+ for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
+ if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id))
+ {
+ /* The object is already loaded.
+ Just bump its reference count and return it. */
+ __close_nocancel (fd);
+
+ /* If the name is not in the list of names for this object add
+ it. */
+ free (realname);
+ add_name_to_object (l, name);
+
+ return l;
+ }
+ }
+
+#ifdef SHARED
+ /* When loading into a namespace other than the base one we must
+ avoid loading ld.so since there can only be one copy. Ever. */
+ if (__glibc_unlikely (nsid != LM_ID_BASE)
+ && (_dl_file_id_match_p (&id, &GL(dl_rtld_map).l_file_id)
+ || _dl_name_match_p (name, &GL(dl_rtld_map))))
+ {
+ /* This is indeed ld.so. Create a new link_map which refers to
+ the real one for almost everything. */
+ l = _dl_new_object (realname, name, l_type, loader, mode, nsid);
+ if (l == NULL)
+ goto fail_new;
+
+ /* Refer to the real descriptor. */
+ l->l_real = &GL(dl_rtld_map);
+
+ /* Copy l_addr and l_ld to avoid a GDB warning with dlmopen(). */
+ l->l_addr = l->l_real->l_addr;
+ l->l_ld = l->l_real->l_ld;
+
+ /* No need to bump the refcount of the real object, ld.so will
+ never be unloaded. */
+ __close_nocancel (fd);
+
+ /* Add the map for the mirrored object to the object list. */
+ _dl_add_to_namespace_list (l, nsid);
+
+ return l;
+ }
+#endif
+ if (mode & RTLD_NOLOAD)
+ {
+ /* We are not supposed to load the object unless it is already
+ loaded. So return now. */
+ free (realname);
+ __close_nocancel (fd);
+ return NULL;
+ }
+
+ /* Print debugging message. */
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+ _dl_debug_printf ("file=%s [%lu]; generating link map\n", name, nsid);
+
+ /* Enter the new object in the list of loaded objects. */
+ l = _dl_new_object (realname, name, l_type, loader, mode, nsid);
+ if (__glibc_unlikely (l == NULL))
+ {
+#ifdef SHARED
+ fail_new:
+#endif
+ errstring = N_("cannot create shared object descriptor");
+ goto lose_errno;
+ }
+
+ if (_ld_map_object_1 (l, fd, fbp, mode, loader, stack_endp, &errval,
+ &errstring))
+ goto lose;
+
+ /* We are done mapping in the file. We no longer need the descriptor. */
+ if (__glibc_unlikely (__close_nocancel (fd) != 0))
+ {
+ errstring = N_("cannot close file descriptor");
+ goto lose_errno;
+ }
+ /* Signal that we closed the file. */
+ fd = -1;
+
+ _ld_map_object_2 (l, mode, id, origname, nsid, r, &make_consistent);
return l;
}
-\f
+
/* Print search path. */
static void
print_search_path (struct r_search_path_elem **list,
--
2.37.2
next prev parent reply other threads:[~2023-03-18 16:51 UTC|newest]
Thread overview: 107+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-18 16:50 [PATCH v9 0/13] implement dlmem() function Stas Sergeev
2023-03-18 16:50 ` [PATCH 01/13] elf: strdup() l_name if no realname [BZ #30100] Stas Sergeev
2023-03-29 13:54 ` Adhemerval Zanella Netto
2023-03-29 14:12 ` stsp
2023-03-29 14:19 ` Adhemerval Zanella Netto
2023-03-29 14:28 ` stsp
2023-03-29 14:30 ` Adhemerval Zanella Netto
2023-03-29 14:33 ` stsp
2023-03-18 16:50 ` [PATCH 02/13] elf: switch _dl_map_segment() to anonymous mapping Stas Sergeev
2023-03-29 17:01 ` Adhemerval Zanella Netto
2023-03-29 18:00 ` stsp
2023-03-29 18:29 ` Adhemerval Zanella Netto
2023-03-29 18:46 ` stsp
2023-03-29 19:17 ` Adhemerval Zanella Netto
2023-03-29 19:43 ` stsp
2023-03-18 16:51 ` [PATCH 03/13] elf: dont pass fd to _dl_process_pt_xx Stas Sergeev
2023-03-29 17:10 ` Adhemerval Zanella Netto
2023-03-30 16:08 ` stsp
2023-03-30 20:46 ` Adhemerval Zanella Netto
2023-03-31 12:02 ` Szabolcs Nagy
2023-03-31 12:54 ` Adhemerval Zanella Netto
2023-03-31 14:04 ` stsp
2023-03-18 16:51 ` Stas Sergeev [this message]
2023-03-18 16:51 ` [PATCH 05/13] elf: split open_verify() into reusable parts Stas Sergeev
2023-03-18 16:51 ` [PATCH 06/13] elf: load elf hdr fully in open_verify() Stas Sergeev
2023-03-18 16:51 ` [PATCH 07/13] elf: convert pread64 to callback in do_open_verify() Stas Sergeev
2023-03-18 16:51 ` [PATCH 08/13] elf: convert _dl_map_segments's mmap() to a callback Stas Sergeev
2023-03-18 16:51 ` [PATCH 09/13] elf: call _dl_map_segment() via premap callback Stas Sergeev
2023-03-18 16:51 ` [PATCH 10/13] elf: convert _dl_map_object to a callback Stas Sergeev
2023-03-18 16:51 ` [PATCH 11/13] elf: split _dl_check_loaded() from _dl_map_object Stas Sergeev
2023-03-18 16:51 ` [PATCH 12/13] dlfcn,elf: implement dlmem() [BZ #11767] Stas Sergeev
2023-03-29 13:45 ` Carlos O'Donell
2023-03-29 13:51 ` stsp
2023-03-29 14:10 ` Jonathon Anderson
2023-03-29 14:20 ` stsp
2023-03-29 14:31 ` Adhemerval Zanella Netto
2023-03-29 15:01 ` stsp
2023-03-29 14:35 ` Carlos O'Donell
2023-03-29 14:50 ` stsp
2023-03-29 15:20 ` Carlos O'Donell
2023-03-29 15:34 ` stsp
2023-03-30 8:09 ` stsp
2023-03-18 16:51 ` [PATCH 13/13] dlfcn,elf: impl DLMEM_DONTREPLACE dlmem() flag Stas Sergeev
2023-03-29 12:32 ` [PATCH v9 0/13] implement dlmem() function Adhemerval Zanella Netto
2023-03-29 13:10 ` stsp
2023-03-29 13:18 ` stsp
2023-03-31 12:20 ` Szabolcs Nagy
2023-03-31 13:51 ` stsp
2023-03-31 14:49 ` Rich Felker
2023-03-31 14:56 ` stsp
2023-03-31 14:58 ` Rich Felker
2023-03-31 15:03 ` stsp
2023-03-31 14:44 ` stsp
2023-03-31 15:12 ` stsp
2023-03-31 17:12 ` Szabolcs Nagy
2023-03-31 17:36 ` stsp
2023-04-01 9:28 ` stsp
2023-04-03 10:04 ` Szabolcs Nagy
2023-04-03 10:43 ` stsp
2023-04-03 12:01 ` Szabolcs Nagy
2023-04-03 13:07 ` stsp
2023-04-05 7:29 ` stsp
2023-04-05 8:51 ` Szabolcs Nagy
2023-04-05 9:26 ` stsp
2023-04-05 9:31 ` Florian Weimer
2023-04-12 17:23 ` stsp
2023-04-12 18:00 ` stsp
2023-04-12 18:20 ` Rich Felker
2023-04-12 18:46 ` stsp
2023-04-12 19:52 ` Zack Weinberg
2023-04-12 19:07 ` stsp
2023-04-13 10:01 ` stsp
2023-04-13 12:38 ` Szabolcs Nagy
2023-04-13 15:59 ` stsp
2023-04-13 18:09 ` Adhemerval Zanella Netto
2023-04-13 18:59 ` stsp
2023-04-13 19:12 ` Adhemerval Zanella Netto
2023-04-13 19:29 ` stsp
2023-04-13 20:02 ` Adhemerval Zanella Netto
2023-04-13 20:21 ` stsp
2023-04-13 20:57 ` stsp
2023-04-14 7:07 ` stsp
2023-04-14 7:36 ` stsp
2023-04-14 11:30 ` stsp
2023-04-14 19:04 ` proof for dlmem() (Re: [PATCH v9 0/13] implement dlmem() function) stsp
2023-05-01 23:11 ` Zack Weinberg
2023-05-02 5:48 ` stsp
2023-05-08 16:00 ` stsp
2023-05-02 6:24 ` stsp
2023-05-08 15:10 ` [PATCH v9 0/13] implement dlmem() function stsp
2023-03-31 18:47 ` stsp
2023-03-31 19:00 ` stsp
2023-03-29 13:17 ` Carlos O'Donell
2023-03-29 13:26 ` stsp
2023-03-29 17:03 ` stsp
2023-03-29 18:13 ` Carlos O'Donell
2023-03-29 18:29 ` stsp
2023-03-31 11:04 ` stsp
2023-04-13 21:17 ` Carlos O'Donell
2023-04-13 21:58 ` stsp
2023-04-13 22:08 ` stsp
2023-04-13 22:50 ` stsp
2023-04-14 16:15 ` Autoconf maintenance (extremely tangential to Re: [PATCH v9 0/13] implement dlmem() function) Zack Weinberg
2023-04-14 20:24 ` Carlos O'Donell
2023-04-14 20:40 ` Zack Weinberg
2023-05-08 15:05 ` [PATCH v9 0/13] implement dlmem() function stsp
2023-05-19 7:26 ` stsp
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230318165110.3672749-5-stsp2@yandex.ru \
--to=stsp2@yandex.ru \
--cc=libc-alpha@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).