LCOV - code coverage report
Current view: top level - libdw - libdw_find_split_unit.c (source / functions) Hit Total Coverage
Test: elfutils-0.175 Lines: 40 42 95.2 %
Date: 2018-11-16 13:02:39 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          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             : 
      36             : #include <limits.h>
      37             : #include <search.h>
      38             : #include <stdlib.h>
      39             : #include <string.h>
      40             : #include <sys/types.h>
      41             : #include <sys/stat.h>
      42             : #include <fcntl.h>
      43             : #include <unistd.h>
      44             : 
      45             : void
      46          50 : try_split_file (Dwarf_CU *cu, const char *dwo_path)
      47             : {
      48          50 :   int split_fd = open (dwo_path, O_RDONLY);
      49          50 :   if (split_fd != -1)
      50             :     {
      51          49 :       Dwarf *split_dwarf = dwarf_begin (split_fd, DWARF_C_READ);
      52          49 :       if (split_dwarf != NULL)
      53             :         {
      54          49 :           Dwarf_CU *split = NULL;
      55          99 :           while (dwarf_get_units (split_dwarf, split, &split,
      56             :                                   NULL, NULL, NULL, NULL) == 0)
      57             :             {
      58          49 :               if (split->unit_type == DW_UT_split_compile
      59          49 :                   && cu->unit_id8 == split->unit_id8)
      60             :                 {
      61          48 :                   if (tsearch (split->dbg, &cu->dbg->split_tree,
      62             :                                __libdw_finddbg_cb) == NULL)
      63             :                     {
      64             :                       /* Something went wrong.  Don't link.  */
      65           0 :                       __libdw_seterrno (DWARF_E_NOMEM);
      66           0 :                       break;
      67             :                     }
      68             : 
      69             :                   /* Link skeleton and split compile units.  */
      70          48 :                   __libdw_link_skel_split (cu, split);
      71             : 
      72             :                   /* We have everything we need from this ELF
      73             :                      file.  And we are going to close the fd to
      74             :                      not run out of file descriptors.  */
      75          48 :                   elf_cntl (split_dwarf->elf, ELF_C_FDDONE);
      76          48 :                   break;
      77             :                 }
      78             :             }
      79          49 :           if (cu->split == (Dwarf_CU *) -1)
      80           1 :             dwarf_end (split_dwarf);
      81             :         }
      82             :       /* Always close, because we don't want to run out of file
      83             :          descriptors.  See also the elf_fcntl ELF_C_FDDONE call
      84             :          above.  */
      85          49 :       close (split_fd);
      86             :     }
      87          50 : }
      88             : 
      89             : Dwarf_CU *
      90             : internal_function
      91         310 : __libdw_find_split_unit (Dwarf_CU *cu)
      92             : {
      93             :   /* Only try once.  */
      94         310 :   if (cu->split != (Dwarf_CU *) -1)
      95             :     return cu->split;
      96             : 
      97             :   /* We need a skeleton unit with a comp_dir and [GNU_]dwo_name attributes.
      98             :      The split unit will be the first in the dwo file and should have the
      99             :      same id as the skeleton.  */
     100          49 :   if (cu->unit_type == DW_UT_skeleton)
     101             :     {
     102          98 :       Dwarf_Die cudie = CUDIE (cu);
     103             :       Dwarf_Attribute dwo_name;
     104             :       /* It is fine if dwo_dir doesn't exists, but then dwo_name needs
     105             :          to be an absolute path.  */
     106          49 :       if (dwarf_attr (&cudie, DW_AT_dwo_name, &dwo_name) != NULL
     107          26 :           || dwarf_attr (&cudie, DW_AT_GNU_dwo_name, &dwo_name) != NULL)
     108             :         {
     109             :           /* First try the dwo file name in the same directory
     110             :              as we found the skeleton file.  */
     111          49 :           const char *dwo_file = dwarf_formstring (&dwo_name);
     112          49 :           const char *debugdir = cu->dbg->debugdir;
     113          49 :           char *dwo_path = __libdw_filepath (debugdir, NULL, dwo_file);
     114          49 :           if (dwo_path != NULL)
     115             :             {
     116          49 :               try_split_file (cu, dwo_path);
     117          49 :               free (dwo_path);
     118             :             }
     119             : 
     120          49 :           if (cu->split == (Dwarf_CU *) -1)
     121             :             {
     122             :               /* Try compdir plus dwo_name.  */
     123             :               Dwarf_Attribute compdir;
     124           1 :               dwarf_attr (&cudie, DW_AT_comp_dir, &compdir);
     125           1 :               const char *dwo_dir = dwarf_formstring (&compdir);
     126           1 :               if (dwo_dir != NULL)
     127             :                 {
     128           1 :                   dwo_path = __libdw_filepath (debugdir, dwo_dir, dwo_file);
     129           1 :                   if (dwo_path != NULL)
     130             :                     {
     131           1 :                       try_split_file (cu, dwo_path);
     132           1 :                       free (dwo_path);
     133             :                     }
     134             :                 }
     135             :             }
     136             :           /* XXX If still not found we could try stripping dirs from the
     137             :              comp_dir and adding them from the comp_dir, assuming
     138             :              someone moved a whole build tree around.  */
     139             :         }
     140             :     }
     141             : 
     142             :   /* If we found nothing, make sure we don't try again.  */
     143          49 :   if (cu->split == (Dwarf_CU *) -1)
     144           1 :     cu->split = NULL;
     145             : 
     146          49 :   return cu->split;
     147             : }

Generated by: LCOV version 1.13