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
24static void
25cancel_handler (void *arg __attribute__((unused)))
26{
27 __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
28}
29
30int
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->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}
85hidden_def (__dl_iterate_phdr)
86
87weak_alias (__dl_iterate_phdr, dl_iterate_phdr);
88

source code of glibc/elf/dl-iteratephdr.c