Include sys/types.h before fts.h
[platform/upstream/elfutils.git] / libdwfl / dwfl_module_getsrc.c
index 3b341b9..f7e340b 100644 (file)
@@ -1,15 +1,30 @@
 /* Find source location for PC address in module.
-   Copyright (C) 2005 Red Hat, Inc.
+   Copyright (C) 2005, 2008, 2014 Red Hat, Inc.
+   This file is part of elfutils.
 
-   This program is Open Source software; you can redistribute it and/or
-   modify it under the terms of the Open Software License version 1.0 as
-   published by the Open Source Initiative.
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
 
-   You should have received a copy of the Open Software License along
-   with this program; if not, you may obtain a copy of the Open Software
-   License version 1.0 from http://www.opensource.org/licenses/osl.php or
-   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
-   3001 King Ranch Road, Ukiah, CA 95482.   */
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
 
 #include "libdwflP.h"
 #include "../libdw/libdwP.h"
@@ -27,29 +42,35 @@ dwfl_module_getsrc (Dwfl_Module *mod, Dwarf_Addr addr)
     error = __libdwfl_cu_getsrclines (cu);
   if (likely (error == DWFL_E_NOERROR))
     {
-      /* The lines are sorted by address, so we can use binary search.  */
-      size_t l = 0, u = cu->die.cu->lines->nlines;
-      while (l < u)
+      Dwarf_Lines *lines = cu->die.cu->lines;
+      size_t nlines = lines->nlines;
+      if (nlines > 0)
        {
-         size_t idx = (l + u) / 2;
-         if (addr < cu->die.cu->lines->info[idx].addr)
-           u = idx;
-         else if (addr > cu->die.cu->lines->info[idx].addr)
-           l = idx + 1;
-         else
-           return &cu->lines->idx[idx];
-       }
+         /* This is guaranteed for us by libdw read_srclines.  */
+         assert(lines->info[nlines - 1].end_sequence);
 
-      if (cu->die.cu->lines->nlines > 0)
-       assert (cu->die.cu->lines->info
-               [cu->die.cu->lines->nlines - 1].end_sequence);
+         /* Now we look at the module-relative address.  */
+         addr -= bias;
 
-      /* If none were equal, the closest one below is what we want.
-        We never want the last one, because it's the end-sequence
-        marker with an address at the high bound of the CU's code.  */
-      if (u > 0 && u < cu->die.cu->lines->nlines
-         && addr > cu->die.cu->lines->info[u - 1].addr)
-       return &cu->lines->idx[u - 1];
+         /* The lines are sorted by address, so we can use binary search.  */
+         size_t l = 0, u = nlines - 1;
+         while (l < u)
+           {
+             size_t idx = u - (u - l) / 2;
+             Dwarf_Line *line = &lines->info[idx];
+             if (addr < line->addr)
+               u = idx - 1;
+             else
+               l = idx;
+           }
+
+         /* The last line which is less than or equal to addr is what
+            we want, unless it is the end_sequence which is after the
+            current line sequence.  */
+         Dwarf_Line *line = &lines->info[l];
+         if (! line->end_sequence && line->addr <= addr)
+           return &cu->lines->idx[l];
+       }
 
       error = DWFL_E_ADDR_OUTOFRANGE;
     }