1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Find matching source locations in a module.
2b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper   Copyright (C) 2005 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
5de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of either
7b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU Lesser General Public License as published by the Free
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 3 of the License, or (at
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU General Public License as published by the Free
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 2 of the License, or (at
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or both in parallel, as here.
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
21361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   General Public License for more details.
24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
25de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received copies of the GNU General Public License and
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the GNU Lesser General Public License along with this program.  If
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   not, see <http://www.gnu.org/licenses/>.  */
28b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "libdwflP.h"
30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "../libdw/libdwP.h"
31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
333148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsiehstatic inline const char *
343148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsiehdwfl_dwarf_line_file (const Dwarf_Line *line)
353148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh{
363148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh  return line->files->info[line->file].name;
373148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh}
383148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh
393148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsiehstatic inline Dwarf_Line *
403148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsiehdwfl_line (const Dwfl_Line *line)
413148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh{
423148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh  return &dwfl_linecu (line)->die.cu->lines->info[line->idx];
433148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh}
443148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh
453148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsiehstatic inline const char *
463148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsiehdwfl_line_file (const Dwfl_Line *line)
473148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh{
483148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh  return dwfl_dwarf_line_file (dwfl_line (line));
493148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh}
503148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh
51b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperint
52b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperdwfl_module_getsrc_file (Dwfl_Module *mod,
53b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 const char *fname, int lineno, int column,
54b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			 Dwfl_Line ***srcsp, size_t *nsrcs)
55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{
56b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (mod == NULL)
57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    return -1;
58b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
59d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  if (mod->dw == NULL)
60d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath    {
61d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      Dwarf_Addr bias;
62d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      if (INTUSE(dwfl_module_getdwarf) (mod, &bias) == NULL)
63d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	return -1;
64d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath    }
65d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
66b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  bool is_basename = strchr (fname, '/') == NULL;
67b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
68b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t max_match = *nsrcs ?: ~0u;
69b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t act_match = *nsrcs;
70b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  size_t cur_match = 0;
71b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwfl_Line **match = *nsrcs == 0 ? NULL : *srcsp;
72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
73b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  struct dwfl_cu *cu = NULL;
74b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  Dwfl_Error error;
75b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  while ((error = __libdwfl_nextcu (mod, cu, &cu)) == DWFL_E_NOERROR
76b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 && cu != NULL
77b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 && (error = __libdwfl_cu_getsrclines (cu)) == DWFL_E_NOERROR)
78b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      /* Search through all the line number records for a matching
80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 file and line/column number.  If any of the numbers is zero,
81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	 no match is performed.  */
82b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      const char *lastfile = NULL;
83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      bool lastmatch = false;
84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      for (size_t cnt = 0; cnt < cu->die.cu->lines->nlines; ++cnt)
85b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	{
86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  Dwarf_Line *line = &cu->die.cu->lines->info[cnt];
87b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (unlikely (line->file >= line->files->nfiles))
89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_INVALID_DWARF));
91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      return -1;
92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  else
94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
953148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh	      const char *file = dwfl_dwarf_line_file (line);
96b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (file != lastfile)
97b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
98b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* Match the name with the name the user provided.  */
99b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  lastfile = file;
100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  lastmatch = !strcmp (is_basename ? basename (file) : file,
101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper				       fname);
102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (!lastmatch)
105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* See whether line and possibly column match.  */
108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (lineno != 0
109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && (lineno > line->line
110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  || (column != 0 && column > line->column)))
111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    /* Cannot match.  */
112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    continue;
113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  /* Determine whether this is the best match so far.  */
115b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  size_t inner;
116b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  for (inner = 0; inner < cur_match; ++inner)
1174959bf89d92b59ba72bea5786d7b3f9b5564f750Roland McGrath	    if (dwfl_line_file (match[inner])
1183148f5cd3dafdce78a30b609901fc9b27cceb983Chih-Hung Hsieh		== dwfl_dwarf_line_file (line))
119b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      break;
120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (inner < cur_match
121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      && (dwfl_line (match[inner])->line != line->line
122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  || dwfl_line (match[inner])->line != lineno
123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  || (column != 0
124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      && (dwfl_line (match[inner])->column != line->column
125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper			  || dwfl_line (match[inner])->column != column))))
126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      /* We know about this file already.  If this is a better
128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		 match for the line number, use it.  */
129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (dwfl_line (match[inner])->line >= line->line
130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  && (dwfl_line (match[inner])->line != line->line
131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      || dwfl_line (match[inner])->column >= line->column))
132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		/* Use the new line.  Otherwise the old one.  */
133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		match[inner] = &cu->lines->idx[cnt];
134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      continue;
135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	  if (cur_match < max_match)
138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    {
139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      if (cur_match == act_match)
140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		{
141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  /* Enlarge the array for the results.  */
142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  act_match += 10;
143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  Dwfl_Line **newp = realloc (match,
144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					      act_match
145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper					      * sizeof (Dwfl_Line *));
146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  if (newp == NULL)
147b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    {
148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      free (match);
149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      __libdwfl_seterrno (DWFL_E_NOMEM);
150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		      return -1;
151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		    }
152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		  match = newp;
153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper		}
154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	      match[cur_match++] = &cu->lines->idx[cnt];
156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	    }
157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper	}
158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  if (cur_match > 0)
161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    {
162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      assert (*nsrcs == 0 || *srcsp == match);
163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      *nsrcs = cur_match;
165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      *srcsp = match;
166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper      return 0;
168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper    }
169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper
170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  __libdwfl_seterrno (DWFL_E_NO_MATCH);
171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper  return -1;
172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper}
173