1 /* Get loaded objects program headers.
2 Copyright (C) 2001-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If
17 not, see <https://www.gnu.org/licenses/>. */
18
19 #include <errno.h>
20 #include <ldsodefs.h>
21 #include <stddef.h>
22 #include <libc-lock.h>
23
24 static void
cancel_handler(void * arg)25 cancel_handler (void *arg __attribute__((unused)))
26 {
27 __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
28 }
29
30 int
__dl_iterate_phdr(int (* callback)(struct dl_phdr_info * info,size_t size,void * data),void * data)31 __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
32 size_t size, void *data), void *data)
33 {
34 struct link_map *l;
35 struct dl_phdr_info info;
36 int ret = 0;
37
38 /* Make sure nobody modifies the list of loaded objects. */
39 __rtld_lock_lock_recursive (GL(dl_load_write_lock));
40 __libc_cleanup_push (cancel_handler, NULL);
41
42 /* We have to determine the namespace of the caller since this determines
43 which namespace is reported. */
44 size_t nloaded = GL(dl_ns)[0]._ns_nloaded;
45 Lmid_t ns = 0;
46 #ifdef SHARED
47 const void *caller = RETURN_ADDRESS (0);
48 for (Lmid_t cnt = GL(dl_nns) - 1; cnt > 0; --cnt)
49 for (struct link_map *l = GL(dl_ns)[cnt]._ns_loaded; l; l = l->l_next)
50 {
51 /* We have to count the total number of loaded objects. */
52 nloaded += GL(dl_ns)[cnt]._ns_nloaded;
53
54 if (caller >= (const void *) l->l_map_start
55 && caller < (const void *) l->l_map_end
56 && (l->l_contiguous
57 || _dl_addr_inside_object (l, (ElfW(Addr)) caller)))
58 ns = cnt;
59 }
60 #endif
61
62 for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
63 {
64 info.dlpi_addr = l->l_real->l_addr;
65 info.dlpi_name = l->l_real->l_name;
66 info.dlpi_phdr = l->l_real->l_phdr;
67 info.dlpi_phnum = l->l_real->l_phnum;
68 info.dlpi_adds = GL(dl_load_adds);
69 info.dlpi_subs = GL(dl_load_adds) - nloaded;
70 info.dlpi_tls_data = NULL;
71 info.dlpi_tls_modid = l->l_real->l_tls_modid;
72 if (info.dlpi_tls_modid != 0)
73 info.dlpi_tls_data = GLRO(dl_tls_get_addr_soft) (l->l_real);
74 ret = callback (&info, sizeof (struct dl_phdr_info), data);
75 if (ret)
76 break;
77 }
78
79 /* Release the lock. */
80 __libc_cleanup_pop (0);
81 __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
82
83 return ret;
84 }
85 hidden_def (__dl_iterate_phdr)
86
87 weak_alias (__dl_iterate_phdr, dl_iterate_phdr);
88