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