LCOV - code coverage report
Current view: top level - libdwfl - dwfl_module_getsrc_file.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 52 64 81.2 %
Date: 2017-01-05 09:15:16 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Find matching source locations in a module.
       2             :    Copyright (C) 2005 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             : #include "libdwflP.h"
      30             : #include "../libdw/libdwP.h"
      31             : 
      32             : 
      33             : static inline const char *
      34             : dwfl_dwarf_line_file (const Dwarf_Line *line)
      35             : {
      36        2512 :   return line->files->info[line->file].name;
      37             : }
      38             : 
      39             : static inline Dwarf_Line *
      40             : dwfl_line (const Dwfl_Line *line)
      41             : {
      42        1902 :   return &dwfl_linecu (line)->die.cu->lines->info[line->idx];
      43             : }
      44             : 
      45             : static inline const char *
      46             : dwfl_line_file (const Dwfl_Line *line)
      47             : {
      48         631 :   return dwfl_dwarf_line_file (dwfl_line (line));
      49             : }
      50             : 
      51             : int
      52          10 : dwfl_module_getsrc_file (Dwfl_Module *mod,
      53             :                          const char *fname, int lineno, int column,
      54             :                          Dwfl_Line ***srcsp, size_t *nsrcs)
      55             : {
      56          10 :   if (mod == NULL)
      57             :     return -1;
      58             : 
      59          10 :   if (mod->dw == NULL)
      60             :     {
      61             :       Dwarf_Addr bias;
      62           0 :       if (INTUSE(dwfl_module_getdwarf) (mod, &bias) == NULL)
      63           0 :         return -1;
      64             :     }
      65             : 
      66          10 :   bool is_basename = strchr (fname, '/') == NULL;
      67             : 
      68          10 :   size_t max_match = *nsrcs ?: ~0u;
      69          10 :   size_t act_match = *nsrcs;
      70          10 :   size_t cur_match = 0;
      71          10 :   Dwfl_Line **match = *nsrcs == 0 ? NULL : *srcsp;
      72             : 
      73          10 :   struct dwfl_cu *cu = NULL;
      74             :   Dwfl_Error error;
      75          40 :   while ((error = __libdwfl_nextcu (mod, cu, &cu)) == DWFL_E_NOERROR
      76          30 :          && cu != NULL
      77          20 :          && (error = __libdwfl_cu_getsrclines (cu)) == DWFL_E_NOERROR)
      78             :     {
      79             :       /* Search through all the line number records for a matching
      80             :          file and line/column number.  If any of the numbers is zero,
      81             :          no match is performed.  */
      82             :       const char *lastfile = NULL;
      83             :       bool lastmatch = false;
      84        1250 :       for (size_t cnt = 0; cnt < cu->die.cu->lines->nlines; ++cnt)
      85             :         {
      86        1250 :           Dwarf_Line *line = &cu->die.cu->lines->info[cnt];
      87             : 
      88        1250 :           if (unlikely (line->file >= line->files->nfiles))
      89             :             {
      90           0 :               if (*nsrcs == 0)
      91           0 :                 free (match);
      92           0 :               __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_INVALID_DWARF));
      93           0 :               return -1;
      94             :             }
      95             :           else
      96             :             {
      97        2500 :               const char *file = dwfl_dwarf_line_file (line);
      98        1250 :               if (file != lastfile)
      99             :                 {
     100             :                   /* Match the name with the name the user provided.  */
     101          28 :                   lastfile = file;
     102          28 :                   lastmatch = !strcmp (is_basename ? basename (file) : file,
     103             :                                        fname);
     104             :                 }
     105             :             }
     106        1250 :           if (!lastmatch)
     107          56 :             continue;
     108             : 
     109             :           /* See whether line and possibly column match.  */
     110        1194 :           if (lineno != 0
     111        1194 :               && (lineno > line->line
     112         639 :                   || (column != 0 && column > line->column)))
     113             :             /* Cannot match.  */
     114         555 :             continue;
     115             : 
     116             :           /* Determine whether this is the best match so far.  */
     117             :           size_t inner;
     118           0 :           for (inner = 0; inner < cur_match; ++inner)
     119        1893 :             if (dwfl_line_file (match[inner])
     120         631 :                 == dwfl_dwarf_line_file (line))
     121             :               break;
     122         639 :           if (inner < cur_match
     123        1262 :               && (dwfl_line (match[inner])->line != line->line
     124           8 :                   || dwfl_line (match[inner])->line != lineno
     125           3 :                   || (column != 0
     126           0 :                       && (dwfl_line (match[inner])->column != line->column
     127           0 :                           || dwfl_line (match[inner])->column != column))))
     128             :             {
     129             :               /* We know about this file already.  If this is a better
     130             :                  match for the line number, use it.  */
     131        1256 :               if (dwfl_line (match[inner])->line >= line->line
     132          14 :                   && (dwfl_line (match[inner])->line != line->line
     133           2 :                       || dwfl_line (match[inner])->column >= line->column))
     134             :                 /* Use the new line.  Otherwise the old one.  */
     135           7 :                 match[inner] = &cu->lines->idx[cnt];
     136         628 :               continue;
     137             :             }
     138             : 
     139          11 :           if (cur_match < max_match)
     140             :             {
     141          11 :               if (cur_match == act_match)
     142             :                 {
     143             :                   /* Enlarge the array for the results.  */
     144           8 :                   act_match += 10;
     145           8 :                   Dwfl_Line **newp = realloc (match,
     146             :                                               act_match
     147             :                                               * sizeof (Dwfl_Line *));
     148           8 :                   if (newp == NULL)
     149             :                     {
     150           0 :                       free (match);
     151           0 :                       __libdwfl_seterrno (DWFL_E_NOMEM);
     152           0 :                       return -1;
     153             :                     }
     154             :                   match = newp;
     155             :                 }
     156             : 
     157          11 :               match[cur_match++] = &cu->lines->idx[cnt];
     158             :             }
     159             :         }
     160             :     }
     161             : 
     162          10 :   if (cur_match > 0)
     163             :     {
     164           8 :       assert (*nsrcs == 0 || *srcsp == match);
     165             : 
     166           8 :       *nsrcs = cur_match;
     167           8 :       *srcsp = match;
     168             : 
     169           8 :       return 0;
     170             :     }
     171             : 
     172           2 :   __libdwfl_seterrno (DWFL_E_NO_MATCH);
     173           2 :   return -1;
     174             : }

Generated by: LCOV version 1.12