(root)/
glibc-2.38/
elf/
dl-find_object.h
       1  /* Locating objects in the process image.  ld.so implementation.
       2     Copyright (C) 2021-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
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the 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; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef _DL_FIND_EH_FRAME_H
      20  #define _DL_FIND_EH_FRAME_H
      21  
      22  #include <assert.h>
      23  #include <atomic.h>
      24  #include <dlfcn.h>
      25  #include <ldsodefs.h>
      26  #include <stdbool.h>
      27  #include <stdint.h>
      28  
      29  /* Internal version of struct dl_find_object.  Does not include the
      30     (yet unused) flags member.  We need to make a copy of data also in
      31     struct link_map to support non-contiguous mappings, and to support
      32     software transactional memory (the link map is not covered by
      33     transactions).  */
      34  struct dl_find_object_internal
      35  {
      36    uintptr_t map_start;
      37    uintptr_t map_end;            /* Set to map_start by dlclose.  */
      38    struct link_map *map;         /* Set to NULL by dlclose.  */
      39    void *eh_frame;
      40  #if DLFO_STRUCT_HAS_EH_DBASE
      41    void *eh_dbase;
      42  #endif
      43  #if DLFO_STRUCT_HAS_EH_COUNT
      44    int eh_count;
      45  #endif
      46  };
      47  
      48  /* Create a copy of *SOURCE in *COPY using relaxed MO loads and
      49     stores.  */
      50  static inline void
      51  _dl_find_object_internal_copy (const struct dl_find_object_internal *source,
      52                                 struct dl_find_object_internal *copy)
      53  {
      54    atomic_store_relaxed (&copy->map_start,
      55                          atomic_load_relaxed (&source->map_start));
      56    atomic_store_relaxed (&copy->map_end,
      57                          atomic_load_relaxed (&source->map_end));
      58    atomic_store_relaxed (&copy->map,
      59                          atomic_load_relaxed (&source->map));
      60    atomic_store_relaxed (&copy->eh_frame,
      61                          atomic_load_relaxed (&source->eh_frame));
      62  #if DLFO_STRUCT_HAS_EH_DBASE
      63    atomic_store_relaxed (&copy->eh_dbase,
      64                          atomic_load_relaxed (&source->eh_dbase));
      65  #endif
      66  #if DLFO_STRUCT_HAS_EH_COUNT
      67    atomic_store_relaxed (&copy->eh_count,
      68                          atomic_load_relaxed (&source->eh_count));
      69  #endif
      70  }
      71  
      72  static inline void
      73  _dl_find_object_to_external (struct dl_find_object_internal *internal,
      74                               struct dl_find_object *external)
      75  {
      76    external->dlfo_flags = 0;
      77    external->dlfo_map_start = (void *) internal->map_start;
      78    external->dlfo_map_end = (void *) internal->map_end;
      79    external->dlfo_link_map = internal->map;
      80    external->dlfo_eh_frame = internal->eh_frame;
      81  # if DLFO_STRUCT_HAS_EH_DBASE
      82    external->dlfo_eh_dbase = internal->eh_dbase;
      83  # endif
      84  # if DLFO_STRUCT_HAS_EH_COUNT
      85    external->dlfo_eh_count = internal->eh_count;
      86  # endif
      87  }
      88  
      89  /* Extract the object location data from a link map and writes it to
      90     *RESULT using relaxed MO stores.  */
      91  static void __attribute__ ((unused))
      92  _dl_find_object_from_map (struct link_map *l,
      93                            struct dl_find_object_internal *result)
      94  {
      95    atomic_store_relaxed (&result->map_start, (uintptr_t) l->l_map_start);
      96    atomic_store_relaxed (&result->map_end, (uintptr_t) l->l_map_end);
      97    atomic_store_relaxed (&result->map, l);
      98  
      99  #if DLFO_STRUCT_HAS_EH_DBASE
     100    atomic_store_relaxed (&result->eh_dbase, (void *) l->l_info[DT_PLTGOT]);
     101  #endif
     102  
     103    for (const ElfW(Phdr) *ph = l->l_phdr, *ph_end = l->l_phdr + l->l_phnum;
     104         ph < ph_end; ++ph)
     105      if (ph->p_type == DLFO_EH_SEGMENT_TYPE)
     106        {
     107          atomic_store_relaxed (&result->eh_frame,
     108                                (void *) (ph->p_vaddr + l->l_addr));
     109  #if DLFO_STRUCT_HAS_EH_COUNT
     110          atomic_store_relaxed (&result->eh_count, ph->p_memsz / 8);
     111  #endif
     112          return;
     113        }
     114  
     115    /* Object has no exception handling segment.  */
     116    atomic_store_relaxed (&result->eh_frame, NULL);
     117  #if DLFO_STRUCT_HAS_EH_COUNT
     118    atomic_store_relaxed (&result->eh_count, 0);
     119  #endif
     120  }
     121  
     122  /* Called by the dynamic linker to set up the data structures for the
     123     initially loaded objects.  This creates a few persistent
     124     allocations, so it should be called with the minimal malloc.  */
     125  void _dl_find_object_init (void) attribute_hidden;
     126  
     127  /* Called by dlopen/dlmopen to add new objects to the DWARF EH frame
     128     data structures.  NEW_MAP is the dlopen'ed link map.  Link maps on
     129     the l_next list are added if l_object_processed is 0.  Needs to
     130     be protected by loader write lock.  Returns true on success, false
     131     on malloc failure.  */
     132  bool _dl_find_object_update (struct link_map *new_map) attribute_hidden;
     133  
     134  /* Called by dlclose to remove the link map from the DWARF EH frame
     135     data structures.  Needs to be protected by loader write lock.  */
     136  void _dl_find_object_dlclose (struct link_map *l) attribute_hidden;
     137  
     138  /* Called from __libc_freeres to deallocate malloc'ed memory.  */
     139  void _dl_find_object_freeres (void) attribute_hidden;
     140  
     141  #endif /* _DL_FIND_OBJECT_H */