This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] libdw: Add dwarf_next_lines to read .debug_line tables without CUs.


It is sometimes useful to read .debug_line tables on their own without
having an associated CU DIE. DWARF5 line tables are self-contained.

Adjust dwarf_begin_elf to accept ELF files with just a .debug_line.

Add a new function dwarf_next_lines that returns the Dwarf_Files and
Dwarf_Lines while iterating over just the .debug_lines section. Since
we parse and cache the information it also will try to match the CU
a table is associated with. This is only necessary for DWARF4 line
tables (we will need at least the compilation dir from the CU) and
won't be done for DWARF5 line tables. It also isn't an error if there
is no associated CU (but will mean for DWARF4 line tables the dir list
and the file paths might not be complete).

A typical way to call this new function is:

  Dwarf_Off off, next_off = 0;
  Dwarf_CU *cu = NULL;
  Dwarf_Files *files;
  size_t nfiles;
  Dwarf_Lines *lines;
  size_t nlines;
  int res;
  while ((res = dwarf_next_lines (dbg, off = next_off, &next_off, &cu,
                                  &files, &nfiles, &lines, &nlines)) == 0)
    {
      /* ... handle files and lines ... */
    }

  if (res < 0)
    printf ("BAD dwarf_next_lines: %s\n", dwarf_errmsg (-1));

See libdw.h for the full documentation. For more examples on how to use
the function see the new testcases next-files and next-lines.

Also adjust the file paths for line tables missing a comp_dir.
They are no longer made "absolute" by prepending a slash '/' in front
of them. This really was not useful and didn't happen in any of the
testcases. They are now just kept relative.

Make eu-readelf --debug-dump=decodedline use dwarf_next_lines instead
of iterating over the CUs to show the (decoded) line tables. This allows
it to show decoded line tables even if there is no .debug_info section.

New tests have been added that mimic the get-files and get-lines tests
but use dwarf_next_lines instead of iterating over all CUs. They produce
identical output (modulo the CU information). Also add a new test file
that contains only a .debug_line section.

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 libdw/ChangeLog                    |  12 +++
 libdw/Makefile.am                  |   3 +-
 libdw/dwarf_begin_elf.c            |  21 ++--
 libdw/dwarf_getsrclines.c          |  16 +--
 libdw/dwarf_next_lines.c           | 197 +++++++++++++++++++++++++++++++++++++
 libdw/libdw.h                      |  18 ++++
 libdw/libdw.map                    |   5 +
 src/ChangeLog                      |   6 ++
 src/readelf.c                      |  78 ++++++++-------
 tests/ChangeLog                    |  14 +++
 tests/Makefile.am                  |   7 +-
 tests/next-files.c                 |  93 +++++++++++++++++
 tests/next-lines.c                 | 144 +++++++++++++++++++++++++++
 tests/run-next-files.sh            | 165 +++++++++++++++++++++++++++++++
 tests/run-next-lines.sh            | 116 ++++++++++++++++++++++
 tests/testfile-only-debug-line.bz2 | Bin 0 -> 2514 bytes
 16 files changed, 833 insertions(+), 62 deletions(-)
 create mode 100644 libdw/dwarf_next_lines.c
 create mode 100644 tests/next-files.c
 create mode 100644 tests/next-lines.c
 create mode 100755 tests/run-next-files.sh
 create mode 100755 tests/run-next-lines.sh
 create mode 100644 tests/testfile-only-debug-line.bz2

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 4280c55..4148a44 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,15 @@
+2018-06-25  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_next_lines.c.
+	* libdw.h (dwarf_next_lines): New function declaration.
+	* libdw.map (ELFUTILS_0.173): New section.
+	* dwarf_next_lines.c: New files.
+	* dwarf_begin_elf.c (check_section): Don't error out when elf
+	decompression fails.
+	(valid_p): Allow just a single .debug_line section.
+	* dwarf_getsrclines.c (read_srclines): Keep files relative if comp_dir
+	is missing.
+
 2018-06-18  Mark Wielaard  <mark@klomp.org>
 
 	* dwarf_aggregate_size.c (array_size): New depth argument. Use
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 41df4f3..7a3d532 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -91,7 +91,8 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
 		  dwarf_getalt.c dwarf_setalt.c dwarf_cu_getdwarf.c \
 		  dwarf_cu_die.c dwarf_peel_type.c dwarf_default_lower_bound.c \
 		  dwarf_die_addr_die.c dwarf_get_units.c \
-		  libdw_find_split_unit.c dwarf_cu_info.c
+		  libdw_find_split_unit.c dwarf_cu_info.c \
+		  dwarf_next_lines.c
 
 if MAINTAINER_MODE
 BUILT_SOURCES = $(srcdir)/known-dwarf.h
diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
index 513af2b..e1542c7 100644
--- a/libdw/dwarf_begin_elf.c
+++ b/libdw/dwarf_begin_elf.c
@@ -156,17 +156,9 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
     {
       if (elf_compress (scn, 0, 0) < 0)
 	{
-	  /* If we failed to decompress the section and it's the
-	     debug_info section, then fail with specific error rather
-	     than the generic NO_DWARF. Without debug_info we can't do
-	     anything (see also valid_p()). */
-	  if (cnt == IDX_debug_info)
-	    {
-	      Dwarf_Sig8_Hash_free (&result->sig8_hash);
-	      __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
-	      free (result);
-	      return NULL;
-	    }
+	  /* It would be nice if we could fail with a specific error.
+	     But we don't know if this was an essential section or not.
+	     So just continue for now. See also valid_p().  */
 	  return result;
 	}
     }
@@ -214,11 +206,10 @@ valid_p (Dwarf *result)
   /* We looked at all the sections.  Now determine whether all the
      sections with debugging information we need are there.
 
-     XXX Which sections are absolutely necessary?  Add tests if
-     necessary.  For now we require only .debug_info.  Hopefully this
-     is correct.  */
+     Require at least one section that can be read "standalone".  */
   if (likely (result != NULL)
-      && unlikely (result->sectiondata[IDX_debug_info] == NULL))
+      && unlikely (result->sectiondata[IDX_debug_info] == NULL
+		   && result->sectiondata[IDX_debug_line] == NULL))
     {
       Dwarf_Sig8_Hash_free (&result->sig8_hash);
       __libdw_seterrno (DWARF_E_NO_DWARF);
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 8510538..1432b1d 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -508,11 +508,10 @@ read_srclines (Dwarf *dbg,
 		{
 		  /* This value could be NULL in case the DW_AT_comp_dir
 		     was not present.  We cannot do much in this case.
-		     The easiest thing is to convert the path in an
-		     absolute path.  */
+		     Just keep the file relative.  */
 		  cp = stpcpy (cp, dirarray[diridx].dir);
+		  *cp++ = '/';
 		}
-	      *cp++ = '/';
 	      strcpy (cp, fname);
 	      assert (strlen (new_file->info.name)
 		      < dirarray[diridx].len + 1 + fnamelen + 1);
@@ -803,11 +802,12 @@ read_srclines (Dwarf *dbg,
 		    if (dirarray[diridx].dir != NULL)
 		      /* This value could be NULL in case the
 			 DW_AT_comp_dir was not present.  We
-			 cannot do much in this case.  The easiest
-			 thing is to convert the path in an
-			 absolute path.  */
-		      cp = stpcpy (cp, dirarray[diridx].dir);
-		    *cp++ = '/';
+			 cannot do much in this case.  Just
+			 keep the file relative.  */
+		      {
+			cp = stpcpy (cp, dirarray[diridx].dir);
+			*cp++ = '/';
+		      }
 		    strcpy (cp, fname);
 		  }
 
diff --git a/libdw/dwarf_next_lines.c b/libdw/dwarf_next_lines.c
new file mode 100644
index 0000000..9b76b47
--- /dev/null
+++ b/libdw/dwarf_next_lines.c
@@ -0,0 +1,197 @@
+/* Iterate through the debug line table.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * 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/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwP.h>
+
+
+int
+dwarf_next_lines (Dwarf *dbg, Dwarf_Off off,
+		  Dwarf_Off *next_off, Dwarf_CU **cu,
+		  Dwarf_Files **srcfiles, size_t *nfiles,
+		  Dwarf_Lines **srclines, size_t *nlines)
+{
+  /* Ignore existing errors.  */
+  if (dbg == NULL)
+    return -1;
+
+  Elf_Data *lines = dbg->sectiondata[IDX_debug_line];
+  if (lines == NULL)
+    {
+      __libdw_seterrno (DWARF_E_NO_DEBUG_LINE);
+      return -1;
+    }
+
+  if (off == (Dwarf_Off) -1
+      || lines->d_size < 4
+      || off >= lines->d_size)
+    {
+      *next_off = (Dwarf_Off) -1;
+      return 1;
+    }
+
+  /* Read enough of the header to know where the next table is and
+     whether we need to lookup the CU (version < 5).  */
+  const unsigned char *linep = lines->d_buf + off;
+  const unsigned char *lineendp = lines->d_buf + lines->d_size;
+
+  if ((size_t) (lineendp - linep) < 4)
+    {
+    invalid_data:
+      __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
+      return -1;
+    }
+
+  *next_off = off + 4;
+  Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
+  if (unit_length == DWARF3_LENGTH_64_BIT)
+    {
+      if ((size_t) (lineendp - linep) < 8)
+	goto invalid_data;
+      unit_length = read_8ubyte_unaligned_inc (dbg, linep);
+      *next_off += 8;
+    }
+
+  if (unit_length > (size_t) (lineendp - linep))
+    goto invalid_data;
+
+  *next_off += unit_length;
+  lineendp = linep + unit_length;
+
+  if ((size_t) (lineendp - linep) < 2)
+    goto invalid_data;
+  uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
+
+  Dwarf_Die cudie;
+  if (version < 5)
+    {
+      /* We need to find the matching CU to get the comp_dir.  Use the
+	 given CU as hint where to start searching.  Normally it will
+	 be the next CU that has a statement list. */
+      Dwarf_CU *given_cu = *cu;
+      Dwarf_CU *next_cu = given_cu;
+      bool found = false;
+      while (dwarf_get_units (dbg, next_cu, &next_cu, NULL, NULL,
+			      &cudie, NULL) == 0)
+	{
+	  if (dwarf_hasattr (&cudie, DW_AT_stmt_list))
+	    {
+	      Dwarf_Attribute attr;
+	      Dwarf_Word stmt_off;
+	      if (dwarf_formudata (dwarf_attr (&cudie, DW_AT_stmt_list, &attr),
+				   &stmt_off) == 0
+		  && stmt_off == off)
+		{
+		  found = true;
+		  break;
+		}
+	    }
+	  else if (off == 0
+		   && (next_cu->unit_type == DW_UT_split_compile
+		       || next_cu->unit_type == DW_UT_split_type))
+	    {
+	      /* For split units (in .dwo files) there is only one table
+		 at offset zero (containing just the files, no lines).  */
+	      found = true;
+	      break;
+	    }
+	}
+
+      if (!found && given_cu != NULL)
+	{
+	  /* The CUs might be in a different order from the line
+	     tables. Need to do a linear search (but stop at the given
+	     CU, since we already searched those.  */
+	  next_cu = NULL;
+	  while (dwarf_get_units (dbg, next_cu, &next_cu, NULL, NULL,
+				  &cudie, NULL) == 0
+		 && next_cu != given_cu)
+	    {
+	      Dwarf_Attribute attr;
+	      Dwarf_Word stmt_off;
+	      if (dwarf_formudata (dwarf_attr (&cudie, DW_AT_stmt_list, &attr),
+				   &stmt_off) == 0
+		  && stmt_off == off)
+		{
+		  found = true;
+		  break;
+		}
+	    }
+	}
+
+      if (found)
+	*cu = next_cu;
+      else
+	*cu = NULL;
+    }
+  else
+    *cu = NULL;
+
+  const char *comp_dir;
+  unsigned address_size;
+  if (*cu != NULL)
+    {
+      comp_dir = __libdw_getcompdir (&cudie);
+      address_size = (*cu)->address_size;
+    }
+  else
+    {
+      comp_dir = NULL;
+
+      size_t esize;
+      char *ident = elf_getident (dbg->elf, &esize);
+      if (ident == NULL || esize < EI_NIDENT)
+	goto invalid_data;
+      address_size = ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+    }
+
+  if (__libdw_getsrclines (dbg, off, comp_dir, address_size,
+			   srclines, srcfiles) != 0)
+    return -1;
+
+  if (nlines != NULL)
+    {
+      if (srclines != NULL && *srclines != NULL)
+	*nlines = (*srclines)->nlines;
+      else
+	*nlines = 0;
+    }
+
+  if (nfiles != NULL)
+    {
+      if (srcfiles != NULL && *srcfiles != NULL)
+	*nfiles = (*srcfiles)->nfiles;
+      else
+	*nfiles = 0;
+    }
+
+  return 0;
+}
diff --git a/libdw/libdw.h b/libdw/libdw.h
index a871eb2..b500aa8 100644
--- a/libdw/libdw.h
+++ b/libdw/libdw.h
@@ -716,6 +716,24 @@ extern int dwarf_getsrcdirs (Dwarf_Files *files,
 			     const char *const **result, size_t *ndirs)
   __nonnull_attribute__ (2, 3);
 
+/* Iterates through the debug line units.  Returns 0 on success, -1 on
+   error or 1 if there are no more units.  To start iterating use zero
+   for OFF and set *CU to NULL.  On success NEXT_OFF will be set to
+   the next offset to use.  The *CU will be set if this line table
+   needed a specific CU and needs to be given when calling
+   dwarf_next_lines again (to help dwarf_next_lines quickly find the
+   next CU).  *CU might be set to NULL when it couldn't be found (the
+   compilation directory entry will be the empty string in that case)
+   or for DWARF 5 or later tables, which are self contained.  SRCFILES
+   and SRCLINES may be NULL if the caller is not interested in the
+   actual line or file table.  On success and when not NULL, NFILES
+   and NLINES will be set to the number of files in the file table and
+   number of lines in the line table.  */
+extern int dwarf_next_lines (Dwarf *dwarf, Dwarf_Off off,
+			     Dwarf_Off *next_off, Dwarf_CU **cu,
+			     Dwarf_Files **srcfiles, size_t *nfiles,
+			     Dwarf_Lines **srclines, size_t *nlines)
+  __nonnull_attribute__ (3,4);
 
 /* Return location expression, decoded as a list of operations.  */
 extern int dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **expr,
diff --git a/libdw/libdw.map b/libdw/libdw.map
index 17c99f6..b3e84d5 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -352,3 +352,8 @@ ELFUTILS_0.171 {
     dwarf_getabbrevattr_data;
     dwarf_cu_info;
 } ELFUTILS_0.170;
+
+ELFUTILS_0.173 {
+  global:
+    dwarf_next_lines;
+} ELFUTILS_0.171;
diff --git a/src/ChangeLog b/src/ChangeLog
index 54bb925..6d962bb 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,9 @@
+2018-06-25  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_decoded_line_section): Use dwarf_next_lines
+	instead of dwarf_nextcu.
+	(print_debug_line_section): Don't explicitly lookup CU.
+
 2018-06-15  Mark Wielaard  <mark@klomp.org>
 
 	* readelf.c (attr_callback): Only print block as expressions if it
diff --git a/src/readelf.c b/src/readelf.c
index 4172046..faed61a 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -7824,23 +7824,51 @@ print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
   size_t address_size
     = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
 
-  Dwarf_Off cuoffset;
-  Dwarf_Off ncuoffset = 0;
-  size_t hsize;
-  while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
-		       NULL, NULL, NULL) == 0)
+  Dwarf_Lines *lines;
+  size_t nlines;
+  Dwarf_Off off, next_off = 0;
+  Dwarf_CU *cu = NULL;
+  while (dwarf_next_lines (dbg, off = next_off, &next_off, &cu, NULL, NULL,
+			   &lines, &nlines) == 0)
     {
       Dwarf_Die cudie;
-      if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
-	continue;
+      if (cu != NULL && dwarf_cu_info (cu, NULL, NULL, &cudie,
+				       NULL, NULL, NULL, NULL) == 0)
+	printf (" CU [%" PRIx64 "] %s\n",
+		dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
+      else
+	{
+	  /* DWARF5 lines can be independent of any CU, but they probably
+	     are used by some CU.  Determine the CU this block is for.  */
+	  Dwarf_Off cuoffset;
+	  Dwarf_Off ncuoffset = 0;
+	  size_t hsize;
+	  while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
+			       NULL, NULL, NULL) == 0)
+	    {
+	      if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
+		continue;
+	      Dwarf_Attribute stmt_list;
+	      if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
+		continue;
+	      Dwarf_Word lineoff;
+	      if (dwarf_formudata (&stmt_list, &lineoff) != 0)
+		continue;
+	      if (lineoff == off)
+		{
+		  /* Found the CU.  */
+		  cu = cudie.cu;
+		  break;
+		}
+	    }
 
-      size_t nlines;
-      Dwarf_Lines *lines;
-      if (dwarf_getsrclines (&cudie, &lines, &nlines) != 0)
-	continue;
+	  if (cu != NULL)
+	    printf (" CU [%" PRIx64 "] %s\n",
+		    dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
+	  else
+	    printf (" No CU\n");
+	}
 
-      printf (" CU [%" PRIx64 "] %s\n",
-	      dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
       printf ("  line:col SBPE* disc isa op address"
 	      " (Statement Block Prologue Epilogue *End)\n");
       const char *last_file = "";
@@ -8504,30 +8532,6 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
       size_t line = 1;
       uint_fast8_t is_stmt = default_is_stmt;
 
-      /* Determine the CU this block is for.  */
-      Dwarf_Off cuoffset;
-      Dwarf_Off ncuoffset = 0;
-      size_t hsize;
-      while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
-			   NULL, NULL, NULL) == 0)
-	{
-	  Dwarf_Die cudie;
-	  if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
-	    continue;
-	  Dwarf_Attribute stmt_list;
-	  if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
-	    continue;
-	  Dwarf_Word lineoff;
-	  if (dwarf_formudata (&stmt_list, &lineoff) != 0)
-	    continue;
-	  if (lineoff == start_offset)
-	    {
-	      /* Found the CU.  */
-	      address_size = cudie.cu->address_size;
-	      break;
-	    }
-	}
-
       /* Apply the "operation advance" from a special opcode
 	 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
       unsigned int op_addr_advance;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index c494286..8eb6331 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,17 @@
+2018-06-25  Mark Wielaard  <mark@klomp.org>
+
+	* next-files.c: New file.
+	* next-lines.c: Likewise.
+	* run-next-files.sh: New test.
+	* run-next-lines.sh: Likewise.
+	* testfile-only-debug-line.bz2: New test file.
+	* Makefile.am (check_PROGRAMS): Add next-files and next-lines.
+	(TESTS): Add run-next-files.sh and run-next-lines.sh.
+	(EXTRA_DIST): Add run-next-files.sh, run-next-lines.sh and
+	testfile-only-debug-line.bz2.
+	(next_lines_LDADD): New variable.
+	(next_files_LDADD): Likewise.
+
 2018-06-16  Yonghong Song  <yhs@fb.com>
 
 	* run-reloc-bpf.sh: New test.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index bdb82fc..7b29fd8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -38,7 +38,8 @@ endif
 
 check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
 		  showptable update1 update2 update3 update4 test-nlist \
-		  show-die-info get-files get-lines get-pubnames \
+		  show-die-info get-files next-files get-lines next-lines \
+		  get-pubnames \
 		  get-aranges allfcts line2addr addrscopes funcscopes \
 		  show-abbrev hash newscn ecp dwflmodtest \
 		  find-prologues funcretval allregs rdwrmmap \
@@ -77,6 +78,7 @@ backtrace-child-biarch$(EXEEXT): backtrace-child.c
 TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \
 	update1 update2 update3 update4 \
 	run-show-die-info.sh run-get-files.sh run-get-lines.sh \
+	run-next-files.sh run-next-lines.sh \
 	run-get-pubnames.sh run-get-aranges.sh run-allfcts.sh \
 	run-show-abbrev.sh run-line2addr.sh hash \
 	newscn run-strip-test.sh run-strip-test2.sh \
@@ -173,6 +175,7 @@ endif
 
 EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 	     run-show-die-info.sh run-get-files.sh run-get-lines.sh \
+	     run-next-files.sh run-next-lines.sh testfile-only-debug-line.bz2 \
 	     run-get-pubnames.sh run-get-aranges.sh \
 	     run-show-abbrev.sh run-strip-test.sh \
 	     run-strip-test2.sh run-ecp-test.sh run-ecp-test2.sh \
@@ -470,7 +473,9 @@ show_die_info_LDADD = $(libdw) $(libelf)
 get_pubnames_LDADD = $(libdw) $(libelf)
 show_abbrev_LDADD = $(libdw) $(libelf)
 get_lines_LDADD = $(libdw) $(libelf)
+next_lines_LDADD = $(libdw) $(libelf)
 get_files_LDADD = $(libdw) $(libelf)
+next_files_LDADD = $(libdw) $(libelf)
 get_aranges_LDADD = $(libdw) $(libelf)
 allfcts_LDADD = $(libdw) $(libelf)
 line2addr_LDADD = $(libdw) $(argp_LDADD)
diff --git a/tests/next-files.c b/tests/next-files.c
new file mode 100644
index 0000000..9de5c8b
--- /dev/null
+++ b/tests/next-files.c
@@ -0,0 +1,93 @@
+/* A variant of get-files test that uses dwarf_next_lines.
+   Copyright (C) 2002, 2004, 2005, 2007, 2014, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   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 a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libelf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  int cnt;
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable\n", argv[cnt]);
+	  result = 1;
+	  if (fd != -1)
+	    close (fd);
+	  continue;
+	}
+
+      Dwarf_Off off;
+      Dwarf_Off next_off = 0;
+      Dwarf_CU *cu = NULL;
+      Dwarf_Files *files;
+      size_t nfiles;
+      int res;
+      while ((res = dwarf_next_lines (dbg, off = next_off, &next_off, &cu,
+				      &files, &nfiles, NULL, NULL)) == 0)
+	{
+	  printf ("off = %" PRIu64 "\n", off);
+
+	  const char *const *dirs;
+	  size_t ndirs;
+	  if (dwarf_getsrcdirs (files, &dirs, &ndirs) != 0)
+	    {
+	      printf ("%s: cannot get include directories\n", argv[cnt]);
+	      result = 1;
+	      break;
+	    }
+
+	  if (dirs[0] == NULL)
+	    puts (" dirs[0] = (null)");
+	  else
+	    printf (" dirs[0] = \"%s\"\n", dirs[0]);
+	  for (size_t i = 1; i < ndirs; ++i)
+	    printf (" dirs[%zu] = \"%s\"\n", i, dirs[i]);
+
+	  for (size_t i = 0; i < nfiles; ++i)
+	    printf (" file[%zu] = \"%s\"\n", i,
+		    dwarf_filesrc (files, i, NULL, NULL));
+	}
+
+      if (res < 0)
+	{
+	  printf ("dwarf_next_lines failed: %s\n", dwarf_errmsg (-1));
+	  result = 1;
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return result;
+}
diff --git a/tests/next-lines.c b/tests/next-lines.c
new file mode 100644
index 0000000..cfb74cd
--- /dev/null
+++ b/tests/next-lines.c
@@ -0,0 +1,144 @@
+/* A variant of get-lines that uses dwarf_next_lines.
+   Copyright (C) 2002, 2004, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   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 a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libelf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  int cnt;
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if  (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (-1));
+	  close  (fd);
+	  continue;
+	}
+
+      Dwarf_Off off;
+      Dwarf_Off next_off = 0;
+      Dwarf_CU *cu = NULL;
+      Dwarf_Lines *lb;
+      size_t nlb;
+      int res;
+      while ((res = dwarf_next_lines (dbg, off = next_off, &next_off, &cu,
+				      NULL, NULL, &lb, &nlb)) == 0)
+	{
+	  printf ("off = %" PRIu64 "\n", off);
+	  printf (" %zu lines\n", nlb);
+
+	  for (size_t i = 0; i < nlb; ++i)
+	    {
+	      Dwarf_Line *l = dwarf_onesrcline (lb, i);
+	      if (l == NULL)
+		{
+		  printf ("%s: cannot get individual line\n", argv[cnt]);
+		  result = 1;
+		  break;
+		}
+
+	      Dwarf_Addr addr;
+	      if (dwarf_lineaddr (l, &addr) != 0)
+		addr = 0;
+	      const char *file = dwarf_linesrc (l, NULL, NULL);
+	      int line;
+	      if (dwarf_lineno (l, &line) != 0)
+		line = 0;
+
+	      printf ("%" PRIx64 ": %s:%d:", (uint64_t) addr,
+		      file ?: "???", line);
+
+	      /* Getting the file path through the Dwarf_Files should
+		 result in the same path.  */
+	      Dwarf_Files *files;
+	      size_t idx;
+	      if (dwarf_line_file (l, &files, &idx) != 0)
+		{
+		  printf ("%s: cannot get file from line (%zd): %s\n",
+			  argv[cnt], i, dwarf_errmsg (-1));
+		  result = 1;
+		  break;
+		}
+	      const char *path = dwarf_filesrc (files, idx, NULL, NULL);
+	      if ((path == NULL && file != NULL)
+		  || (path != NULL && file == NULL)
+		  || (strcmp (file, path) != 0))
+		{
+		  printf ("%s: line %zd srcline (%s) != file srcline (%s)\n",
+			  argv[cnt], i, file ?: "???", path ?: "???");
+		  result = 1;
+		  break;
+		}
+
+	      int column;
+	      if (dwarf_linecol (l, &column) != 0)
+		column = 0;
+	      if (column >= 0)
+		printf ("%d:", column);
+
+	      bool is_stmt;
+	      if (dwarf_linebeginstatement (l, &is_stmt) != 0)
+		is_stmt = false;
+	      bool end_sequence;
+	      if (dwarf_lineendsequence (l, &end_sequence) != 0)
+		end_sequence = false;
+	      bool basic_block;
+	      if (dwarf_lineblock (l, &basic_block) != 0)
+		basic_block = false;
+	      bool prologue_end;
+	      if (dwarf_lineprologueend (l, &prologue_end) != 0)
+		prologue_end = false;
+	      bool epilogue_begin;
+	      if (dwarf_lineepiloguebegin (l, &epilogue_begin) != 0)
+		epilogue_begin = false;
+
+	      printf (" is_stmt:%s, end_seq:%s, bb:%s, prologue:%s, epilogue:%s\n",
+		      is_stmt ? "yes" : "no", end_sequence ? "yes" : "no",
+		      basic_block ? "yes" : "no", prologue_end  ? "yes" : "no",
+		      epilogue_begin ? "yes" : "no");
+	    }
+	}
+
+      if (res < 0)
+	{
+	  printf ("dwarf_next_lines failed: %s\n", dwarf_errmsg (-1));
+	  result = 1;
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return result;
+}
diff --git a/tests/run-next-files.sh b/tests/run-next-files.sh
new file mode 100755
index 0000000..7a3b6d0
--- /dev/null
+++ b/tests/run-next-files.sh
@@ -0,0 +1,165 @@
+#! /bin/sh
+# Variant of run-get-files that uses dwarf_next_lines.
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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 a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile testfile2
+
+testrun_compare ${abs_builddir}/next-files testfile testfile2 <<\EOF
+off = 0
+ dirs[0] = "/home/drepper/gnu/new-bu/build/ttt"
+ file[0] = "???"
+ file[1] = "/home/drepper/gnu/new-bu/build/ttt/m.c"
+off = 75
+ dirs[0] = "/home/drepper/gnu/new-bu/build/ttt"
+ file[0] = "???"
+ file[1] = "/home/drepper/gnu/new-bu/build/ttt/b.c"
+ file[2] = "/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h"
+ file[3] = "/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h"
+ file[4] = "/usr/include/bits/types.h"
+ file[5] = "/usr/include/bits/sched.h"
+ file[6] = "/usr/include/bits/pthreadtypes.h"
+ file[7] = "/usr/include/stdio.h"
+ file[8] = "/usr/include/libio.h"
+ file[9] = "/usr/include/wchar.h"
+ file[10] = "/usr/include/_G_config.h"
+ file[11] = "/usr/include/gconv.h"
+off = 480
+ dirs[0] = "/home/drepper/gnu/new-bu/build/ttt"
+ file[0] = "???"
+ file[1] = "/home/drepper/gnu/new-bu/build/ttt/f.c"
+off = 0
+ dirs[0] = "/shoggoth/drepper"
+ file[0] = "???"
+ file[1] = "/shoggoth/drepper/b.c"
+ file[2] = "/home/geoffk/objs/laurel-000912-branch/lib/gcc-lib/powerpc-unknown-linux-gnu/2.96-laurel-000912/include/stddef.h"
+ file[3] = "/home/geoffk/objs/laurel-000912-branch/lib/gcc-lib/powerpc-unknown-linux-gnu/2.96-laurel-000912/include/stdarg.h"
+ file[4] = "/shoggoth/drepper/<built-in>"
+ file[5] = "/usr/include/bits/types.h"
+ file[6] = "/usr/include/stdio.h"
+ file[7] = "/usr/include/libio.h"
+ file[8] = "/usr/include/_G_config.h"
+off = 418
+ dirs[0] = "/shoggoth/drepper"
+ file[0] = "???"
+ file[1] = "/shoggoth/drepper/f.c"
+off = 485
+ dirs[0] = "/shoggoth/drepper"
+ file[0] = "???"
+ file[1] = "/shoggoth/drepper/m.c"
+EOF
+
+# see tests/testfile-dwarf-45.source
+testfiles testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo
+testfiles testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo
+
+testrun_compare ${abs_builddir}/next-files testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo <<\EOF
+off = 0
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include"
+ file[0] = "???"
+ file[1] = "/home/mark/src/elfutils/tests/hello.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h"
+off = 612
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/mark/src/elfutils/tests/world.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/usr/include/stdlib.h"
+off = 0
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include"
+ file[0] = "???"
+ file[1] = "/home/mark/src/elfutils/tests/hello.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h"
+off = 0
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/mark/src/elfutils/tests/world.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/usr/include/stdlib.h"
+EOF
+
+# No problem with dirs[0] for DWARF5 line tables.
+testrun_compare ${abs_builddir}/next-files testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo <<\EOF
+off = 0
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include"
+ file[0] = "/home/mark/src/elfutils/tests/hello.c"
+ file[1] = "/home/mark/src/elfutils/tests/hello.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h"
+off = 655
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/mark/src/elfutils/tests/world.c"
+ file[1] = "/home/mark/src/elfutils/tests/world.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/usr/include/stdlib.h"
+off = 0
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include"
+ file[0] = "/home/mark/src/elfutils/tests/hello.c"
+ file[1] = "/home/mark/src/elfutils/tests/hello.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h"
+off = 0
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/mark/src/elfutils/tests/world.c"
+ file[1] = "/home/mark/src/elfutils/tests/world.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/usr/include/stdlib.h"
+EOF
+
+# Created from testfile using
+# cp testfile testfile-only-debug-line
+# eu-strip -g --keep-section .debug_line
+#
+# Note how the comp dir cannot be retrieved and some files become relative.
+testfiles testfile-only-debug-line
+testrun_compare ${abs_builddir}/next-files testfile-only-debug-line <<\EOF
+off = 0
+ dirs[0] = (null)
+ file[0] = "???"
+ file[1] = "m.c"
+off = 75
+ dirs[0] = (null)
+ file[0] = "???"
+ file[1] = "b.c"
+ file[2] = "/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h"
+ file[3] = "/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h"
+ file[4] = "/usr/include/bits/types.h"
+ file[5] = "/usr/include/bits/sched.h"
+ file[6] = "/usr/include/bits/pthreadtypes.h"
+ file[7] = "/usr/include/stdio.h"
+ file[8] = "/usr/include/libio.h"
+ file[9] = "/usr/include/wchar.h"
+ file[10] = "/usr/include/_G_config.h"
+ file[11] = "/usr/include/gconv.h"
+off = 480
+ dirs[0] = (null)
+ file[0] = "???"
+ file[1] = "f.c"
+EOF
+
+exit 0
diff --git a/tests/run-next-lines.sh b/tests/run-next-lines.sh
new file mode 100755
index 0000000..84aee1c
--- /dev/null
+++ b/tests/run-next-lines.sh
@@ -0,0 +1,116 @@
+#! /bin/sh
+# Variant of run-get-lines that uses dwarf_next_lines.
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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 a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile testfile2 testfilenolines
+
+testrun_compare ${abs_builddir}/next-lines testfile testfile2 <<\EOF
+off = 0
+ 5 lines
+804842c: /home/drepper/gnu/new-bu/build/ttt/m.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048432: /home/drepper/gnu/new-bu/build/ttt/m.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804844d: /home/drepper/gnu/new-bu/build/ttt/m.c:7:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048458: /home/drepper/gnu/new-bu/build/ttt/m.c:8:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804845a: /home/drepper/gnu/new-bu/build/ttt/m.c:8:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 75
+ 4 lines
+804845c: /home/drepper/gnu/new-bu/build/ttt/b.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804845f: /home/drepper/gnu/new-bu/build/ttt/b.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048464: /home/drepper/gnu/new-bu/build/ttt/b.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048466: /home/drepper/gnu/new-bu/build/ttt/b.c:6:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 480
+ 4 lines
+8048468: /home/drepper/gnu/new-bu/build/ttt/f.c:3:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804846b: /home/drepper/gnu/new-bu/build/ttt/f.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048470: /home/drepper/gnu/new-bu/build/ttt/f.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048472: /home/drepper/gnu/new-bu/build/ttt/f.c:5:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 0
+ 4 lines
+10000470: /shoggoth/drepper/b.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+1000047c: /shoggoth/drepper/b.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+10000480: /shoggoth/drepper/b.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+10000490: /shoggoth/drepper/b.c:6:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 418
+ 4 lines
+10000490: /shoggoth/drepper/f.c:3:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+1000049c: /shoggoth/drepper/f.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004a0: /shoggoth/drepper/f.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004b0: /shoggoth/drepper/f.c:5:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 485
+ 5 lines
+100004b0: /shoggoth/drepper/m.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004cc: /shoggoth/drepper/m.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004e8: /shoggoth/drepper/m.c:7:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004f4: /shoggoth/drepper/m.c:8:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+10000514: /shoggoth/drepper/m.c:8:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+EOF
+
+# - lines.c
+# int ft;
+#
+# int
+# main (int argc, char **argv)
+# {
+#   return ft - 42;
+# }
+#
+# - nolines.c
+# int ft = 42;
+#
+# gcc -g -c lines.c
+# gcc -g -c nolines.c
+# gcc -g -o testfilenolines lines.o nolines.o
+
+testrun_compare ${abs_builddir}/next-lines testfilenolines <<\EOF
+off = 0
+ 4 lines
+400474: /home/mark/src/tests/lines.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40047f: /home/mark/src/tests/lines.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+400488: /home/mark/src/tests/lines.c:7:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40048a: /home/mark/src/tests/lines.c:7:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 59
+ 0 lines
+EOF
+
+# See run-next-files.
+# Note no, comp_dir, so all paths are relative.
+testfiles testfile-only-debug-line
+testrun_compare ${abs_builddir}/next-lines testfile-only-debug-line <<\EOF
+off = 0
+ 5 lines
+804842c: m.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048432: m.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804844d: m.c:7:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048458: m.c:8:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804845a: m.c:8:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 75
+ 4 lines
+804845c: b.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804845f: b.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048464: b.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048466: b.c:6:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 480
+ 4 lines
+8048468: f.c:3:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804846b: f.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048470: f.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048472: f.c:5:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+EOF
+
+exit 0
diff --git a/tests/testfile-only-debug-line.bz2 b/tests/testfile-only-debug-line.bz2
new file mode 100644
index 0000000000000000000000000000000000000000..a931bcd4f79e145fe09d92c9a77902504262f402
GIT binary patch
literal 2514
zcmV;@2`%<QT4*^jL0KkKS*E($+5ic9fB*mg|Nr0b|Mvgy|9`*#|Mvbb=0t2A?@rum
zeFt`bXI<b47vACJz$<p`SOC#Vpa6Dl*|3x%m`x^XX&$Mj@g`G79!ZqM#PFV`QRy2|
zrkXS~(V%9UhDL^uL>T}8(Ahv~>SQqowI`|S4H_Px0Sb_5nudp{0MIl500Ton8UO$Q
z0000o82|tp02%-Q0LTnL)ix%Qr|O;)Nc5kTF#rt>4H^K@007YS8UO$Q3~B%X0MIlv
z0000088i(vri71F&<&{3qiSf;w3!Bsj7=Ie4H_95XwVG+2ALQMkkDw;KpG4{$jPQ4
z0MVdgAkmOAXagfgngBGyWHAjiXfyx;qecX2kOM%-G|&uzp`bJ}WB_Q;02*K<L_rCJ
zz=?^VnrNFzv>}nSnlwE_MnGg51}1|;L7)I=&;S9TWM}};01W_t0e=#LA^=#rkccYO
z2n8dK&zLuZq)ORh2oM#an<!+Kb|Oe6fnQ$c&MyxWdw+wAr7au!-ZZsv*d$}14{Ka$
zcn^aRo+xesAQwS#N|FKWL|6M^TXsSg1I&$&R!`yO!O$F`fU6B1nUA#8UE63uDC^rD
zQ4pQg^5FO_e9Vlvsbo(xIUD{|w-L2AVGe;nM!J?xny##l6B0B{w`|BG^jKLpuU#`$
zQV<a}k~;3zD%4*ayEtTcPbXLXSk&jJaX0+P6GPWUJRS#kyphNvU7~UDD5WKtaS3OZ
z@i1WZbfZvpS0n*54a0>{%@<?0R{iCI;r$i!NNi=cTYGhb1KkX3V-ZAiGGu|_2m<WJ
zXr?%sDWs3MK>G+B@f-+f>8a{tU681_b|k{C6oo}QK@|B37ItO|j+P4OC)OszPchh0
zVA7XAd&%*miqlW5>kspb23qs7s8Fz?A!?`yDu@&6Fb9UxOUtw%-C%YtD;PGVpoSzU
zI3q&>gA#{E2q%65lNBbkno+EbU2_Vutw((c5oQSjSauB>(sf~hr41Es=t$+^%US_~
z$Vyn)nA2s9EiQtR;$c80(5`(o{P_woCczxlr9u%d)(Y{Z3_&dlMgma8lVYRc?N><7
z(Uev&=C#!|R*EnIuoGuU(HzK`gxujWIAG}O726`rW$c=T%_(DY#RFEkX-N<kxNyQ9
zB54$;$Zl0)25nOJt6@;rD2CxF+qgnCGItp+_1~#~7j?4ZSN5XFnod4#F%dgR7VBPo
z2bG&_=-OV}>BkwBU~=LSqZX@j$9RrqCaNxcv~D}9auyN4kow1gj=9R5r+n5jnom~W
z(O$a8X}R%Z7#zr~6Cyxp!bm7iQSg??Bn;sQv1*`!6j2NE3<+o$#8|~ftK)!V0^~L5
z8qS|>)^w?@E9PBbP?P0=N=ineBLJn9G<>Z-?ezKilU-x5zvOeh?B91cnfd*k&vu`^
z)A7Fm2((5jB9sK7D1tQz9d|QLvH{1D6iEqJD%z)&f%#XjYv)LvqM{*LhEzh!Un(T(
zEQr<^1iV2|Ai*e(kOO2CLQ91ds+9>UU!f!o<&Ay<<DnGM3}I^Ha=3tgq6612(cTA!
zDp0XliHJj`B48*uDGDrbH(>~Ez~~f|6m_X2$x4-V3cD;Q6DWcPsb!QYOA8AbE*o^L
zMa#tdQM&v_j+us+#F^@0(_;qHV5ru11T*$Cb)RLTgKZ(OTyR2dCYMDD5PD|_bb&UI
z5YjTSR!T`hrr6aepb;!YF0+m9r7KS&|Js$cJefxTo6QUxX*Oc!#h9Ti-TW4`XJR(l
zxY5h`{ri&-#q8w^z@#ACXodx?LQd)^mP<r2;Bj2g62qW&I{kQAyMBu`5qmrUJwP3}
z9;go34y+7dT4Q3y@$V47m62YaF}LghBb3I%S<!*tff^qb?sleaqdDPWr>X4P@Ic%G
zl6gz$M2KSAcl+*Wu{yiv0)4&&?vKGO8DZVTgi3~vlO|~5P@XEALe?@FWibsn5gpVU
z;6QAc0zfo@07x7SP!2Uapd<(_<k`?r?uE$%!WbGk6*xfOFT+@ehR?nSIA#DU2P-LH
zk7Nc~nc2lVy?sDDiqB7E$@Vy&jo_7iL8yW80P<*xk)t=>sg0Lp{4kfHh|ye^9mPEB
zOY^;ny2qRXFxP|(xJ8d{(oUYX)Kwm<fNPb5xwTk>W;|Fof`t!Dua~6M8UVVs*TgR#
z3Y^tmOtF!c=o?hHaKf%8EgZ_#p?>M^DlG<WM})<?kK650Jx4}=oxs+^a8Utc=}GWr
zom(n$c-;Kt8}l|H9cdknH&WuFh|z0r<2J&ZKA<BajBT7@3(QFkdxyw6f}Tv~m&wC;
zUC8H>iyvUQ<;D%MMtVNN)Dge~Bw3DEzRt3n5v+&~6*{{6^TM%<Y|7bw#h>C}&?4+M
zyJHO~psz9j-fLBvCerHlqAb%=!m9+TyzN5fUxRyg>;Hy0+7UHIofQ504ulKu-pz4y
z49uK11xMJNa{1dkEn4&8Hl4Q686#n%UQO%w%U%$<7(s5j>6P8tX3KODmg?SQ!L9eN
zY_H(WIY*@i&0Y4*i#bB!7Uc;I5wxS21y#I#2N*IURY#{`jHWyG^2z$glPL~W%V@K3
zN5{EZSS>G)zOPVQRTz^762xS-DA2T(D>jWHx`))QMG6zYoUVf}7R|MJl|g{O7`7Mm
zI3Tkrd7EC#FzV86h|(BEr;oT>R`C}&uo);XGvdl(Gg?@vQv90?6H%KeBXwgzXveHI
zZQY7vqTQP_?L!Z+xL!~@CTg<5vP8|@nnbV~pfO~>gGRlf+N!ZenqGf=;xy~3!dfG2
zxg+~<=_fI{Zvn(Y&S}`QnHFP7cRz@4^Sx{NWsoqcv&j1Ra!Z(=xaMtaX6Yuewj_-t
zT9>3XNGtX3li<Zv*Vt+TCRD{>h-EH=uNyVVq0S*;Zf3%FAH=#3ElhhilP_?8N@P&O
z*y7f{xz5-_6#{81TN(on<%b#E0m6W#MNjEz=V8HhjnYLSz+A37Z!wu6a5+&_je-VK
z(K9D;&9pYYA5}9L+!ZV(RZ?%gXV-_F&LS{LtkuhM{L=R=7nQQW6;)dLu!TevkWL%G
zg#uZtn(@U8gAfYRy7e&fL4}zz=yDmM1gS+K;@z+hH92GY2&9!)dLi=eaNIGhEW^p<
zIWNd#izhZ57O04Uqx^qM=iWNDHS(>3TFX#f$9a>*Tgi7P+B~uxyeSw_J$aYCl`{aY
zV=R<JVp9gzF#$UeB(ZrOS5dWF@r2S)ah(ZU0g(RKNeI>m0rIY4fgqG=VkBK-VFnbD
c3QB8AKXLCC61|?4;{V0mkxmpODXzA*fB|rS+5i9m

literal 0
HcmV?d00001

-- 
1.8.3.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]