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

Generated by: LCOV version 1.12