(root)/
glibc-2.38/
elf/
dl-iteratephdr.c
       1  /* Get loaded objects program headers.
       2     Copyright (C) 2001-2023 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
      25  cancel_handler (void *arg __attribute__((unused)))
      26  {
      27    __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
      28  }
      29  
      30  int
      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);