LCOV - code coverage report
Current view: top level - libdw - libdw_find_split_unit.c (source / functions) Coverage Total Hit
Test: elfutils-0.196 Lines: 91.2 % 91 83
Test Date: 2026-08-14 16:31:37 Functions: 100.0 % 3 3
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 67.1 % 76 51

             Branch data     Line data    Source code
       1                 :             : /* Find the split (or skeleton) unit for a given unit.
       2                 :             :    Copyright (C) 2018 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                 :             : #ifdef HAVE_CONFIG_H
      30                 :             : # include <config.h>
      31                 :             : #endif
      32                 :             : 
      33                 :             : #include "libdwP.h"
      34                 :             : #include "libelfP.h"
      35                 :             : #include "libdwelfP.h"
      36                 :             : #include "eu-search.h"
      37                 :             : 
      38                 :             : #include <limits.h>
      39                 :             : #include <stdlib.h>
      40                 :             : #include <string.h>
      41                 :             : #include <sys/types.h>
      42                 :             : #include <sys/stat.h>
      43                 :             : #include <fcntl.h>
      44                 :             : 
      45                 :             : static void
      46                 :         112 : try_split_file (Dwarf_CU *cu, const char *dwo_path)
      47                 :             : {
      48                 :         112 :   int split_fd = open (dwo_path, O_RDONLY);
      49         [ +  + ]:         112 :   if (split_fd != -1)
      50                 :             :     {
      51                 :         110 :       Dwarf *split_dwarf = INTUSE(dwarf_begin_type) (split_fd, DWARF_C_READ,
      52                 :             :                                                      DWARF_T_DWO);
      53         [ +  - ]:         110 :       if (split_dwarf != NULL)
      54                 :             :         {
      55                 :         110 :           Dwarf_CU *split = NULL;
      56                 :         110 :           while (INTUSE(dwarf_get_units) (split_dwarf, split, &split,
      57         [ +  + ]:         112 :                                           NULL, NULL, NULL, NULL) == 0)
      58                 :             :             {
      59         [ +  - ]:         110 :               if (split->unit_type == DW_UT_split_compile
      60         [ +  + ]:         110 :                   && cu->unit_id8 == split->unit_id8)
      61                 :             :                 {
      62         [ -  + ]:         108 :                   if (eu_tsearch (split->dbg, &cu->dbg->split_tree,
      63                 :             :                                   __libdw_finddbg_cb) == NULL)
      64                 :             :                     {
      65                 :             :                       /* Something went wrong.  Don't link.  */
      66                 :           0 :                       __libdw_seterrno (DWARF_E_NOMEM);
      67                 :           0 :                       break;
      68                 :             :                     }
      69                 :             : 
      70                 :             :                   /* Link skeleton and split compile units.  */
      71                 :         108 :                   __libdw_link_skel_split (cu, split);
      72                 :             : 
      73                 :             :                   /* We have everything we need from this ELF
      74                 :             :                      file.  And we are going to close the fd to
      75                 :             :                      not run out of file descriptors.  */
      76                 :         108 :                   elf_cntl (split_dwarf->elf, ELF_C_FDDONE);
      77                 :         108 :                   break;
      78                 :             :                 }
      79                 :             :             }
      80         [ +  + ]:         110 :           if (cu->split == (Dwarf_CU *) -1)
      81                 :           2 :             INTUSE (dwarf_end) (split_dwarf);
      82                 :             :         }
      83                 :             :       /* Always close, because we don't want to run out of file
      84                 :             :          descriptors.  See also the elf_fcntl ELF_C_FDDONE call
      85                 :             :          above.  */
      86                 :         110 :       close (split_fd);
      87                 :             :     }
      88                 :         112 : }
      89                 :             : 
      90                 :             : static void
      91                 :         198 : try_dwp_file (Dwarf_CU *cu)
      92                 :             : {
      93         [ +  + ]:         198 :   if (cu->dbg->dwp_dwarf == NULL)
      94                 :             :     {
      95                 :          98 :       uint8_t is_dwp;
      96                 :          98 :       const char *filename;
      97                 :          98 :       const uint8_t *dwp_id;
      98                 :          98 :       int dwp_fd = -1;
      99                 :             : 
     100                 :          98 :       ssize_t idlen = INTUSE(dwelf_dwarf_debug_dwp) (cu->dbg, NULL, &is_dwp,
     101                 :             :                                                      &filename, &dwp_id);
     102   [ +  -  +  +  :          98 :       if (idlen >= 0 && filename != NULL && is_dwp == 0 && *filename != '\0')
             +  -  +  - ]
     103                 :             :         {
     104                 :             :           /* XXX we need to set standards where/how to find id based
     105                 :             :              dwp files, including debuginfod support. For now only use
     106                 :             :              the file path.  */
     107                 :           2 :           char *path = __libdw_filepath (cu->dbg->debugdir, NULL, filename);
     108         [ +  - ]:           2 :           if (path != NULL)
     109                 :             :             {
     110   [ -  +  -  - ]:           2 :               dwp_fd = TEMP_FAILURE_RETRY (open (path, O_RDONLY));
     111                 :           2 :               free (path);
     112                 :             :             }
     113                 :             :         }
     114                 :             : 
     115   [ -  +  +  - ]:          98 :       if (dwp_fd == -1 && cu->dbg->elfpath != NULL)
     116                 :             :         {
     117                 :             :           /* The DWARF 5 standard says "the package file is typically placed in
     118                 :             :              the same directory as the application, and is given the same name
     119                 :             :              with a '.dwp' extension".  */
     120                 :          96 :           size_t elfpath_len = strlen (cu->dbg->elfpath);
     121                 :          96 :           char *dwp_path = malloc (elfpath_len + 5);
     122         [ -  + ]:          96 :           if (dwp_path == NULL)
     123                 :             :             {
     124                 :           0 :               __libdw_seterrno (DWARF_E_NOMEM);
     125                 :           0 :               return;
     126                 :             :             }
     127                 :          96 :           memcpy (dwp_path, cu->dbg->elfpath, elfpath_len);
     128                 :          96 :           strcpy (dwp_path + elfpath_len, ".dwp");
     129   [ +  +  -  + ]:          96 :           dwp_fd = TEMP_FAILURE_RETRY (open (dwp_path, O_RDONLY));
     130                 :          96 :           free (dwp_path);
     131                 :             :         }
     132                 :             : 
     133         [ +  + ]:          96 :       if (dwp_fd != -1)
     134                 :             :         {
     135                 :          28 :           Dwarf *dwp_dwarf = INTUSE(dwarf_begin_type) (dwp_fd, DWARF_C_READ,
     136                 :             :                                                        DWARF_T_DWO);
     137                 :             :           /* There's no way to know whether we got the correct file until
     138                 :             :              we look up the unit, but it should at least be a dwp file.  */
     139         [ +  - ]:          28 :           if (dwp_dwarf != NULL
     140         [ -  + ]:          28 :               && (dwp_dwarf->sectiondata[IDX_debug_cu_index] != NULL
     141         [ #  # ]:           0 :                   || dwp_dwarf->sectiondata[IDX_debug_tu_index] != NULL))
     142                 :             :             {
     143                 :          28 :               cu->dbg->dwp_dwarf = dwp_dwarf;
     144                 :          28 :               cu->dbg->dwp_fd = dwp_fd;
     145                 :             :             }
     146                 :             :           else
     147                 :           0 :             close (dwp_fd);
     148                 :             :         }
     149         [ +  + ]:          98 :       if (cu->dbg->dwp_dwarf == NULL)
     150                 :          70 :         cu->dbg->dwp_dwarf = (Dwarf *) -1;
     151                 :             :     }
     152                 :             : 
     153         [ +  + ]:         198 :   if (cu->dbg->dwp_dwarf != (Dwarf *) -1)
     154                 :             :     {
     155                 :          88 :       Dwarf_CU *split = __libdw_dwp_findcu_id (cu->dbg->dwp_dwarf,
     156                 :             :                                                cu->unit_id8);
     157         [ +  - ]:          88 :       if (split != NULL)
     158                 :             :         {
     159         [ -  + ]:          88 :           if (eu_tsearch (split->dbg, &cu->dbg->split_tree,
     160                 :             :                           __libdw_finddbg_cb) == NULL)
     161                 :             :             {
     162                 :             :               /* Something went wrong.  Don't link.  */
     163                 :           0 :               __libdw_seterrno (DWARF_E_NOMEM);
     164                 :           0 :               return;
     165                 :             :             }
     166                 :             : 
     167                 :             :           /* Link skeleton and split compile units.  */
     168                 :          88 :           __libdw_link_skel_split (cu, split);
     169                 :             :         }
     170                 :             :     }
     171                 :             : }
     172                 :             : 
     173                 :             : Dwarf_CU *
     174                 :             : internal_function
     175                 :        1108 : __libdw_find_split_unit (Dwarf_CU *cu)
     176                 :             : {
     177                 :             :   /* Set result before releasing the lock.  */
     178                 :        1108 :   Dwarf_CU *result;
     179                 :             : 
     180                 :        1108 :   rwlock_wrlock(cu->split_lock);
     181                 :             : 
     182                 :             :   /* Only try once.  */
     183         [ +  + ]:        1108 :   if (cu->split != (Dwarf_CU *) -1)
     184                 :             :     {
     185                 :        1108 :       result = cu->split;
     186                 :             :       rwlock_unlock(cu->split_lock);
     187                 :             :       return result;
     188                 :             :     }
     189                 :             : 
     190                 :             :   /* We need a skeleton unit with a comp_dir and [GNU_]dwo_name attributes.
     191                 :             :      The split unit will be the first in the dwo file and should have the
     192                 :             :      same id as the skeleton.  */
     193         [ +  - ]:         198 :   if (cu->unit_type == DW_UT_skeleton)
     194                 :             :     {
     195                 :             :       /* First, try the dwp file.  */
     196                 :         198 :       try_dwp_file (cu);
     197                 :             : 
     198                 :         198 :       Dwarf_Die cudie = CUDIE (cu);
     199                 :         198 :       Dwarf_Attribute dwo_name;
     200                 :             :       /* Try a dwo file.  It is fine if dwo_dir doesn't exist, but then
     201                 :             :          dwo_name needs to be an absolute path.  */
     202         [ +  + ]:         198 :       if (cu->split == (Dwarf_CU *) -1
     203         [ +  + ]:         110 :           && (dwarf_attr (&cudie, DW_AT_dwo_name, &dwo_name) != NULL
     204         [ +  - ]:          56 :               || dwarf_attr (&cudie, DW_AT_GNU_dwo_name, &dwo_name) != NULL))
     205                 :             :         {
     206                 :             :           /* Try the dwo file name in the same directory
     207                 :             :              as we found the skeleton file.  */
     208                 :         110 :           const char *dwo_file = dwarf_formstring (&dwo_name);
     209                 :         110 :           const char *debugdir = cu->dbg->debugdir;
     210                 :         110 :           char *dwo_path = __libdw_filepath (debugdir, NULL, dwo_file);
     211         [ +  - ]:         110 :           if (dwo_path != NULL)
     212                 :             :             {
     213                 :         110 :               try_split_file (cu, dwo_path);
     214                 :         110 :               free (dwo_path);
     215                 :             :             }
     216                 :             : 
     217         [ +  + ]:         110 :           if (cu->split == (Dwarf_CU *) -1)
     218                 :             :             {
     219                 :             :               /* Try compdir plus dwo_name.  */
     220                 :           2 :               Dwarf_Attribute compdir;
     221                 :           2 :               dwarf_attr (&cudie, DW_AT_comp_dir, &compdir);
     222                 :           2 :               const char *dwo_dir = dwarf_formstring (&compdir);
     223         [ +  - ]:           2 :               if (dwo_dir != NULL)
     224                 :             :                 {
     225                 :           2 :                   dwo_path = __libdw_filepath (debugdir, dwo_dir, dwo_file);
     226         [ +  - ]:           2 :                   if (dwo_path != NULL)
     227                 :             :                     {
     228                 :           2 :                       try_split_file (cu, dwo_path);
     229                 :           2 :                       free (dwo_path);
     230                 :             :                     }
     231                 :             :                 }
     232                 :             :             }
     233                 :             :           /* XXX If still not found we could try stripping dirs from the
     234                 :             :              comp_dir and adding them from the comp_dir, assuming
     235                 :             :              someone moved a whole build tree around.  */
     236                 :             :         }
     237                 :             :     }
     238                 :             : 
     239                 :             :   /* If we found nothing, make sure we don't try again.  */
     240         [ +  + ]:         198 :   if (cu->split == (Dwarf_CU *) -1)
     241                 :           2 :     cu->split = NULL;
     242                 :             : 
     243                 :         198 :   result = cu->split;
     244                 :         198 :   rwlock_unlock(cu->split_lock);
     245                 :         198 :   return result;
     246                 :             : }
        

Generated by: LCOV version 2.0-1