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