LCOV - code coverage report
Current view: top level - libdwfl_stacktrace - dwflst_tracker_find_elf.c (source / functions) Hit Total Coverage
Test: elfutils-0.193 Lines: 0 87 0.0 %
Date: 2025-05-08 22:46:17 Functions: 0 6 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 64 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* Find Elf file and cache via Dwflst_Process_Tracker.
       2                 :            :    Copyright (C) 2025, Red Hat, Inc.
       3                 :            :    This file is part of elfutils.
       4                 :            : 
       5                 :            :    This file is free software; you can redistribute it and/or modify
       6                 :            :    it under the terms of either
       7                 :            : 
       8                 :            :      * the GNU Lesser General Public License as published by the Free
       9                 :            :        Software Foundation; either version 3 of the License, or (at
      10                 :            :        your option) any later version
      11                 :            : 
      12                 :            :    or
      13                 :            : 
      14                 :            :      * the GNU General Public License as published by the Free
      15                 :            :        Software Foundation; either version 2 of the License, or (at
      16                 :            :        your option) any later version
      17                 :            : 
      18                 :            :    or both in parallel, as here.
      19                 :            : 
      20                 :            :    elfutils is distributed in the hope that it will be useful, but
      21                 :            :    WITHOUT ANY WARRANTY; without even the implied warranty of
      22                 :            :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      23                 :            :    General Public License for more details.
      24                 :            : 
      25                 :            :    You should have received copies of the GNU General Public License and
      26                 :            :    the GNU Lesser General Public License along with this program.  If
      27                 :            :    not, see <http://www.gnu.org/licenses/>.  */
      28                 :            : 
      29                 :            : 
      30                 :            : #ifdef HAVE_CONFIG_H
      31                 :            : # include <config.h>
      32                 :            : #endif
      33                 :            : 
      34                 :            : #include <sys/stat.h>
      35                 :            : #include "../libelf/libelfP.h"
      36                 :            : /* XXX: Private header needed for Elf * ref_count field. */
      37                 :            : /* TODO: Consider dup_elf() rather than direct ref_count access. */
      38                 :            : 
      39                 :            : #include "libdwfl_stacktraceP.h"
      40                 :            : 
      41                 :            : unsigned long int
      42                 :          0 : __libdwfl_stacktrace_elftab_hash_st (const char *module_name,
      43                 :            :                                      dev_t st_dev,
      44                 :            :                                      ino_t st_ino)
      45                 :            : {
      46                 :          0 :   unsigned long int hval = elf_hash(module_name);
      47                 :          0 :   hval ^= (unsigned long int)st_dev;
      48                 :          0 :   hval ^= (unsigned long int)st_ino;
      49                 :          0 :   return hval;
      50                 :            : }
      51                 :            : 
      52                 :            : unsigned long int
      53                 :          0 : __libdwfl_stacktrace_elftab_hash (const char *module_name,
      54                 :            :                                   const char *module_path,
      55                 :            :                                   int fd)
      56                 :            : {
      57                 :          0 :   struct stat sb;
      58                 :          0 :   int rc = -1;
      59         [ #  # ]:          0 :   if (fd >= 0)
      60                 :          0 :     rc = fstat(fd, &sb);
      61         [ #  # ]:          0 :   else if (module_path != NULL)
      62                 :          0 :     rc = stat(module_path, &sb);
      63         [ #  # ]:          0 :   if (rc < 0)
      64                 :          0 :     return elf_hash(module_name);
      65                 :          0 :   return __libdwfl_stacktrace_elftab_hash_st
      66                 :            :     (module_name, sb.st_dev, sb.st_ino);
      67                 :            : }
      68                 :            : 
      69                 :            : int
      70                 :          0 : dwflst_tracker_find_cached_elf (Dwflst_Process_Tracker *tracker,
      71                 :            :                                 const char *module_name,
      72                 :            :                                 const char *module_path,
      73                 :            :                                 char **file_name, Elf **elfp)
      74                 :            : {
      75                 :          0 :   dwflst_tracker_elf_info *ent = NULL;
      76                 :          0 :   int rc = -1;
      77                 :          0 :   struct stat sb;
      78                 :            : 
      79         [ #  # ]:          0 :   if (module_path == NULL)
      80                 :          0 :     module_path = module_name;
      81                 :          0 :   unsigned long int hval =
      82                 :          0 :     __libdwfl_stacktrace_elftab_hash (module_name, module_path, -1/* no fd */);
      83                 :            : 
      84                 :          0 :   rwlock_rdlock(tracker->elftab_lock);
      85                 :          0 :   ent = dwflst_tracker_elftab_find(&tracker->elftab, hval);
      86                 :          0 :   rwlock_unlock(tracker->elftab_lock);
      87                 :            : 
      88                 :            :   /* Guard against collisions.
      89                 :            :      TODO: Need proper chaining, dynamicsizehash_concurrent isn't really
      90                 :            :      equipped for it. */
      91         [ #  # ]:          0 :   if (ent != NULL)
      92                 :          0 :     rc = fstat(ent->fd, &sb);
      93   [ #  #  #  # ]:          0 :   if (rc < 0 || strcmp (module_name, ent->module_name) != 0
      94   [ #  #  #  # ]:          0 :       || ent->dev != sb.st_dev || ent->ino != sb.st_ino)
      95                 :          0 :     return -1;
      96                 :            : 
      97                 :            :   /* Verify that ent->fd has not been updated: */
      98                 :          0 :   if (rc < 0 || ent->dev != sb.st_dev || ent->ino != sb.st_ino
      99         [ #  # ]:          0 :       || ent->last_mtime != sb.st_mtime)
     100                 :            :     return -1;
     101                 :            : 
     102         [ #  # ]:          0 :   if (ent->elf != NULL)
     103                 :          0 :     ent->elf->ref_count++;
     104                 :          0 :   *elfp = ent->elf;
     105                 :          0 :   *file_name = strdup(ent->module_name);
     106                 :          0 :   return ent->fd;
     107                 :            : }
     108                 :            : INTDEF(dwflst_tracker_find_cached_elf)
     109                 :            : 
     110                 :            : bool
     111                 :          0 : dwflst_tracker_cache_elf (Dwflst_Process_Tracker *tracker,
     112                 :            :                           const char *module_name,
     113                 :            :                           const char *file_name __attribute__((unused)),
     114                 :            :                           Elf *elf, int fd)
     115                 :            : {
     116                 :          0 :   dwflst_tracker_elf_info *ent = NULL;
     117                 :          0 :   int rc = -1;
     118                 :          0 :   struct stat sb;
     119                 :            : 
     120         [ #  # ]:          0 :   if (fd >= 0)
     121                 :          0 :     rc = fstat(fd, &sb);
     122         [ #  # ]:          0 :   if (rc < 0)
     123                 :          0 :     return false;
     124                 :          0 :   unsigned long int hval =
     125                 :          0 :     __libdwfl_stacktrace_elftab_hash_st (module_name, sb.st_dev, sb.st_ino);
     126                 :            : 
     127                 :          0 :   rwlock_wrlock(tracker->elftab_lock);
     128                 :          0 :   ent = dwflst_tracker_elftab_find(&tracker->elftab, hval);
     129                 :            :   /* Guard against collisions.
     130                 :            :      TODO: Need proper chaining, dynamicsizehash_concurrent isn't really
     131                 :            :      equipped for it. */
     132   [ #  #  #  # ]:          0 :   if (ent != NULL && (strcmp (module_name, ent->module_name) != 0
     133   [ #  #  #  # ]:          0 :                       || ent->dev != sb.st_dev || ent->ino != sb.st_ino))
     134                 :            :     {
     135                 :            :       rwlock_unlock(tracker->elftab_lock);
     136                 :            :       return false;
     137                 :            :     }
     138                 :          0 :   if (ent == NULL)
     139                 :            :     {
     140                 :          0 :       ent = calloc (1, sizeof (dwflst_tracker_elf_info));
     141         [ #  # ]:          0 :       if (ent == NULL)
     142                 :            :         {
     143                 :          0 :           rwlock_unlock(tracker->elftab_lock);
     144                 :          0 :           __libdwfl_seterrno (DWFL_E_NOMEM);
     145                 :          0 :           return false;
     146                 :            :         }
     147                 :          0 :       ent->module_name = strdup(module_name);
     148                 :            : 
     149         [ #  # ]:          0 :       if (dwflst_tracker_elftab_insert(&tracker->elftab, hval, ent) != 0)
     150                 :            :         {
     151                 :          0 :           free(ent->module_name);
     152                 :          0 :           free(ent);
     153                 :          0 :           rwlock_unlock(tracker->elftab_lock);
     154                 :          0 :           assert(false); /* Should not occur due to the wrlock on elftab. */
     155                 :            :         }
     156                 :            :     }
     157                 :            :   else
     158                 :            :     {
     159                 :            :       /* TODO: The following assertions are still triggered on certain
     160                 :            :          code paths that acquire fds or create Elf structs without
     161                 :            :          checking the caching mechanism first.  This is not a serious
     162                 :            :          problem, and can be fixed incrementally. */
     163                 :            : 
     164                 :            :       /* assert(ent->elf == NULL || ent->elf == elf); */ /* Guard against redundant/leaked Elf *. */
     165                 :            :       /* assert(ent->fd == fd); */ /* Guard against redundant open. */
     166                 :            : 
     167                 :            :       /* For now, correct behaviour (from dwfl_module_getdwarf.c open_elf)
     168                 :            :          is to replace the existing elf, keep module_name. */
     169   [ #  #  #  # ]:          0 :       if (ent->elf != NULL && ent->elf != elf)
     170                 :          0 :         elf_end(ent->elf);
     171                 :            :     }
     172   [ #  #  #  # ]:          0 :   if (elf != NULL && ent->elf != elf)
     173                 :          0 :     elf->ref_count++;
     174                 :          0 :   ent->elf = elf;
     175                 :          0 :   ent->fd = fd;
     176         [ #  # ]:          0 :   if (rc == 0)
     177                 :            :     {
     178                 :          0 :       ent->dev = sb.st_dev;
     179                 :          0 :       ent->ino = sb.st_ino;
     180                 :          0 :       ent->last_mtime = sb.st_mtime;
     181                 :            :     }
     182                 :            :   /* else create a cache entry with 0 values for dev/ino/mtime;
     183                 :            :      since dev/ino are hashed, this will not conflict with entries
     184                 :            :      for which fstat was successful */
     185                 :            :   rwlock_unlock(tracker->elftab_lock);
     186                 :            :   return true;
     187                 :            : }
     188                 :            : INTDEF(dwflst_tracker_cache_elf)
     189                 :            : 
     190                 :            : Dwflst_Process_Tracker *
     191                 :          0 : dwflst_module_gettracker (Dwfl_Module *mod)
     192                 :            : {
     193         [ #  # ]:          0 :   if (mod == NULL)
     194                 :            :     return NULL;
     195   [ #  #  #  # ]:          0 :   if (mod->dwfl == NULL)
     196                 :            :     return NULL;
     197                 :          0 :   return mod->dwfl->tracker;
     198                 :            : }
     199                 :            : INTDEF(dwflst_module_gettracker)
     200                 :            : 
     201                 :            : int
     202                 :          0 : dwflst_tracker_linux_proc_find_elf (Dwfl_Module *mod,
     203                 :            :                                     void **userdata __attribute__ ((unused)),
     204                 :            :                                     const char *module_name, Dwarf_Addr base,
     205                 :            :                                     char **file_name, Elf **elfp)
     206                 :            : {
     207         [ #  # ]:          0 :   Dwflst_Process_Tracker *tracker = INTUSE(dwflst_module_gettracker) (mod);
     208                 :          0 :   int fd;
     209                 :            : 
     210         [ #  # ]:          0 :   if (tracker != NULL)
     211                 :            :     {
     212                 :          0 :       fd = INTUSE(dwflst_tracker_find_cached_elf)
     213                 :            :         (tracker, module_name, module_name, file_name, elfp);
     214         [ #  # ]:          0 :       if (fd >= 0)
     215                 :            :         return fd;
     216                 :            :     }
     217                 :            : 
     218                 :          0 :   fd = INTUSE(dwfl_linux_proc_find_elf) (mod, userdata, module_name,
     219                 :            :                                          base, file_name, elfp);
     220                 :            : 
     221   [ #  #  #  # ]:          0 :   if (tracker != NULL && fd >= 0 && *file_name != NULL)
     222                 :            :     {
     223                 :          0 :       INTUSE(dwflst_tracker_cache_elf)
     224                 :            :         (tracker, module_name, *file_name, *elfp, fd);
     225                 :            :     }
     226                 :            :   return fd;
     227                 :            : }

Generated by: LCOV version 1.16