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: Handle DWARF5 line tables in dwarf_getsrclines.


In DWARF5 the actual line number table format doesn't change, except for
not allowing DW_LNE_define_file (but we still just accept it). The
changes are the header having new fields for address and segment
selector sizes, and new formats for the directory and file names tables.

The directory and file name tables are much more flexible in DWARF5, but
we only interpret the actual names and file/dir index relationships,
skipping/ignoring any other information. There also is no new interface
yet to get at the new directory and file properties.

There is some small confusion about the file name table indexing. Older
DWARF versions explicitly called the first file name table 1. DWARF5
implies the first index is 0 (but for file attributes, zero means not
associated with a file). We get away with that by having an actual zero
index for older DWARF versions (the null_fill). It looks like gcc gets
around it by explicitly duplicating the first (0) and second (1) file
name entry in the table. This can also be seen in the new testcase.

The patch looks big because of moving a few initializations around
and because the code that is different for older/newer DWARF got moved
under if statements. But the original old DWARF code path didn't really
change.

Signed-off-by: Mark Wielaard <mark@klomp.org>
---
 libdw/ChangeLog                |   8 +
 libdw/dwarf.h                  |  11 ++
 libdw/dwarf_getsrclines.c      | 437 +++++++++++++++++++++++++++++++----------
 libdw/libdwP.h                 |  38 ++++
 tests/ChangeLog                |  10 +
 tests/Makefile.am              |   2 +
 tests/run-readelf-line.sh      | 163 +++++++++++++++
 tests/testfile-dwarf-4.bz2     | Bin 0 -> 4304 bytes
 tests/testfile-dwarf-45.source |  81 ++++++++
 tests/testfile-dwarf-5.bz2     | Bin 0 -> 4318 bytes
 10 files changed, 646 insertions(+), 104 deletions(-)
 create mode 100755 tests/testfile-dwarf-4.bz2
 create mode 100644 tests/testfile-dwarf-45.source
 create mode 100755 tests/testfile-dwarf-5.bz2

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 9ec493f..cc7eae9 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,11 @@
+2018-05-05  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DWARF line content descriptions.
+	* libdwP.h (libdw_valid_user_form): New static function.
+	* dwarf_getsrclines.c (read_srclines): Check and parse version 5
+	DWARF header, dir and file tables separately from older versions
+	where different.
+
 2018-04-24  Mark Wielaard  <mark@klomp.org>
 
 	* dwarf_begin_elf.c (dwarf_scnnames): Add ".debug_line_str".
diff --git a/libdw/dwarf.h b/libdw/dwarf.h
index 99cc112..fc9801b 100644
--- a/libdw/dwarf.h
+++ b/libdw/dwarf.h
@@ -783,6 +783,17 @@ enum
     DW_DEFAULTED_out_of_class = 2
   };
 
+/* DWARF line content descriptions.  */
+enum
+  {
+    DW_LNCT_path = 0x1,
+    DW_LNCT_directory_index = 0x2,
+    DW_LNCT_timestamp = 0x3,
+    DW_LNCT_size = 0x4,
+    DW_LNCT_MD5 = 0x5,
+    DW_LNCT_lo_user = 0x2000,
+    DW_LNCT_hi_user = 0x3fff
+  };
 
 /* DWARF standard opcode encodings.  */
 enum
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index d02c38d..2f966ab 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -1,7 +1,6 @@
 /* Return line number information of CU.
-   Copyright (C) 2004-2010, 2013, 2014, 2015, 2016 Red Hat, Inc.
+   Copyright (C) 2004-2010, 2013, 2014, 2015, 2016, 2018 Red Hat, Inc.
    This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
 
    This file is free software; you can redistribute it and/or modify
    it under the terms of either
@@ -157,18 +156,6 @@ read_srclines (Dwarf *dbg,
   size_t nfilelist = 0;
   unsigned int ndirlist = 0;
 
-  struct filelist null_file =
-    {
-      .info =
-      {
-	.name = "???",
-	.mtime = 0,
-	.length = 0
-      },
-      .next = NULL
-    };
-  struct filelist *filelist = &null_file;
-
   /* If there are a large number of lines, files or dirs don't blow up
      the stack.  Stack allocate some entries, only dynamically malloc
      when more than MAX.  */
@@ -177,16 +164,7 @@ read_srclines (Dwarf *dbg,
 #define MAX_STACK_FILES (MAX_STACK_ALLOC / 4)
 #define MAX_STACK_DIRS  (MAX_STACK_ALLOC / 16)
 
-  struct dirlist
-  {
-    const char *dir;
-    size_t len;
-  };
-  struct dirlist dirstack[MAX_STACK_DIRS];
-  struct dirlist *dirarray = dirstack;
-
-  /* We are about to process the statement program.  Initialize the
-     state machine registers (see 6.2.2 in the v2.1 specification).  */
+  /* Initial statement program state (except for stmt_list, see below).  */
   struct line_state state =
     {
       .linelist = NULL,
@@ -222,25 +200,45 @@ read_srclines (Dwarf *dbg,
     }
 
   /* Check whether we have enough room in the section.  */
-  if (unlikely (unit_length > (size_t) (lineendp - linep)
-      || unit_length < 2 + length + 5 * 1))
+  if (unlikely (unit_length > (size_t) (lineendp - linep)))
     goto invalid_data;
   lineendp = linep + unit_length;
 
   /* The next element of the header is the version identifier.  */
+  if ((size_t) (lineendp - linep) < 2)
+    goto invalid_data;
   uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
-  if (unlikely (version < 2) || unlikely (version > 4))
+  if (unlikely (version < 2) || unlikely (version > 5))
     {
       __libdw_seterrno (DWARF_E_VERSION);
       goto out;
     }
 
+  /* DWARF5 explicitly lists address and segment_selector sizes.  */
+  if (version >= 5)
+    {
+      if ((size_t) (lineendp - linep) < 2)
+	goto invalid_data;
+      size_t line_address_size = *linep++;
+      size_t segment_selector_size = *linep++;
+      if (line_address_size != address_size || segment_selector_size != 0)
+	goto invalid_data;
+    }
+
   /* Next comes the header length.  */
   Dwarf_Word header_length;
   if (length == 4)
-    header_length = read_4ubyte_unaligned_inc (dbg, linep);
+    {
+      if ((size_t) (lineendp - linep) < 4)
+	goto invalid_data;
+      header_length = read_4ubyte_unaligned_inc (dbg, linep);
+    }
   else
-    header_length = read_8ubyte_unaligned_inc (dbg, linep);
+    {
+      if ((size_t) (lineendp - linep) < 8)
+	goto invalid_data;
+      header_length = read_8ubyte_unaligned_inc (dbg, linep);
+    }
   const unsigned char *header_start = linep;
 
   /* Next the minimum instruction length.  */
@@ -250,13 +248,17 @@ read_srclines (Dwarf *dbg,
   uint_fast8_t max_ops_per_instr = 1;
   if (version >= 4)
     {
-      if (unlikely (lineendp - linep < 5))
+      if (unlikely ((size_t) (lineendp - linep) < 1))
 	goto invalid_data;
       max_ops_per_instr = *linep++;
       if (unlikely (max_ops_per_instr == 0))
 	goto invalid_data;
     }
 
+  /* 4 more bytes, is_stmt, line_base, line_range and opcode_base.  */
+  if ((size_t) (lineendp - linep) < 4)
+    goto invalid_data;
+
   /* Then the flag determining the default value of the is_stmt
      register.  */
   uint_fast8_t default_is_stmt = *linep++;
@@ -277,29 +279,84 @@ read_srclines (Dwarf *dbg,
     goto invalid_data;
   linep += opcode_base - 1;
 
-  /* First comes the list of directories.  Add the compilation
-     directory first since the index zero is used for it.  */
-  struct dirlist comp_dir_elem =
-    {
-      .dir = comp_dir,
-      .len = comp_dir ? strlen (comp_dir) : 0,
-    };
-  ndirlist = 1;
+  /* To read DWARF5 dir and file lists we need to know the forms.  For
+     now we skip everything, except the DW_LNCT_path and
+     DW_LNCT_directory_index.  */
+  uint16_t forms[256];
+  unsigned char nforms = 0;
+  unsigned char form_path = -1; /* Which forms is DW_LNCT_path.  */
+  unsigned char form_idx = -1;  /* And which is DW_LNCT_directory_index.  */
+
+  /* To read/skip form data.  */
+  Dwarf_CU fake_cu = {
+    .dbg = dbg,
+    .sec_idx = IDX_debug_line,
+    .version = 5,
+    .offset_size = length,
+    .address_size = address_size,
+    .startp = (void *) linep,
+    .endp = (void *) lineendp,
+  };
 
   /* First count the entries.  */
-  const unsigned char *dirp = linep;
   unsigned int ndirs = 0;
-  while (*dirp != 0)
+  if (version < 5)
     {
-      uint8_t *endp = memchr (dirp, '\0', lineendp - dirp);
-      if (endp == NULL)
+      const unsigned char *dirp = linep;
+      while (*dirp != 0)
+	{
+	  uint8_t *endp = memchr (dirp, '\0', lineendp - dirp);
+	  if (endp == NULL)
+	    goto invalid_data;
+	  ++ndirs;
+	  dirp = endp + 1;
+	}
+      ndirs = ndirs + 1; /* There is always the "unknown" dir.  */
+    }
+  else
+    {
+      if ((size_t) (lineendp - linep) < 1)
+	goto invalid_data;
+      nforms = *linep++;
+      for (int i = 0; i < nforms; i++)
+	{
+	  uint16_t desc, form;
+	  if ((size_t) (lineendp - linep) < 1)
+	    goto invalid_data;
+	  get_uleb128 (desc, linep, lineendp);
+	  if ((size_t) (lineendp - linep) < 1)
+	    goto invalid_data;
+	  get_uleb128 (form, linep, lineendp);
+
+	  if (! libdw_valid_user_form (form))
+	    goto invalid_data;
+
+	  forms[i] = form;
+	  if (desc == DW_LNCT_path)
+	    form_path = i;
+	}
+
+      if (nforms > 0 && form_path == (unsigned char) -1)
+	goto invalid_data;
+
+      if ((size_t) (lineendp - linep) < 1)
+	goto invalid_data;
+      get_uleb128 (ndirs, linep, lineendp);
+
+      if (nforms == 0 && ndirs != 0)
 	goto invalid_data;
-      ++ndirs;
-      dirp = endp + 1;
     }
-  ndirlist += ndirs;
+
+  struct dirlist
+  {
+    const char *dir;
+    size_t len;
+  };
+  struct dirlist dirstack[MAX_STACK_DIRS];
+  struct dirlist *dirarray = dirstack;
 
   /* Arrange the list in array form.  */
+  ndirlist = ndirs;
   if (ndirlist >= MAX_STACK_DIRS)
     {
       dirarray = (struct dirlist *) malloc (ndirlist * sizeof (*dirarray));
@@ -310,20 +367,82 @@ read_srclines (Dwarf *dbg,
 	  goto out;
 	}
     }
-  dirarray[0] = comp_dir_elem;
-  for (unsigned int n = 1; n < ndirlist; n++)
+
+  /* Entry zero is implicit for older versions, but explicit for 5+.  */
+  struct dirlist comp_dir_elem;
+  if (version < 5)
     {
-      dirarray[n].dir = (char *) linep;
-      uint8_t *endp = memchr (linep, '\0', lineendp - linep);
-      assert (endp != NULL);
-      dirarray[n].len = endp - linep;
-      linep = endp + 1;
+      /* First comes the list of directories.  Add the compilation
+	 directory first since the index zero is used for it.  */
+      comp_dir_elem.dir = comp_dir;
+      comp_dir_elem.len = comp_dir ? strlen (comp_dir) : 0,
+      dirarray[0] = comp_dir_elem;
+      for (unsigned int n = 1; n < ndirlist; n++)
+	{
+	  dirarray[n].dir = (char *) linep;
+	  uint8_t *endp = memchr (linep, '\0', lineendp - linep);
+	  assert (endp != NULL);
+	  dirarray[n].len = endp - linep;
+	  linep = endp + 1;
+	}
+      /* Skip the final NUL byte.  */
+      ++linep;
     }
-  /* Skip the final NUL byte.  */
-  ++linep;
+  else
+    {
+      Dwarf_Attribute attr;
+      attr.code = DW_AT_name;
+      attr.cu = &fake_cu;
+      for (unsigned int n = 0; n < ndirlist; n++)
+	{
+	  const char *dir = NULL;
+	  for (unsigned char m = 0; m < nforms; m++)
+	    {
+	      if (m == form_path)
+		{
+		  attr.form = forms[m];
+		  attr.valp = (void *) linep;
+		  dir = dwarf_formstring (&attr);
+		}
+
+	      size_t len = __libdw_form_val_len (&fake_cu, forms[m], linep);
+	      if ((size_t) (lineendp - linep) < len)
+		goto invalid_data;
+
+	      linep += len;
+	    }
+
+	  if (dir == NULL)
+	    goto invalid_data;
+
+	  dirarray[n].dir = dir;
+	  dirarray[n].len = strlen (dir);
+	}
+    }
+
+  /* File index zero doesn't exist for DWARF < 5.  Files are indexed
+     starting from 1.  But for DWARF5 they are indexed starting from
+     zero, but the default index is still 1.  In both cases the
+     "first" file is special and refers to the main compile unit file,
+     equal to the DW_AT_name of the DW_TAG_compile_unit.  */
+  struct filelist null_file =
+    {
+      .info =
+      {
+	.name = "???",
+	.mtime = 0,
+	.length = 0
+      },
+      .next = NULL
+    };
+  struct filelist *filelist = &null_file;
+  nfilelist = 1;
 
   /* Allocate memory for a new file.  For the first MAX_STACK_FILES
-     entries just return a slot in the preallocated stack array.  */
+     entries just return a slot in the preallocated stack array.
+     This is slightly complicated because in DWARF < 5 new files could
+     be defined with DW_LNE_define_file after the normal file list was
+     read.  */
   struct filelist flstack[MAX_STACK_FILES];
 #define NEW_FILE() ({							\
   struct filelist *fl = (nfilelist < MAX_STACK_FILES			\
@@ -337,69 +456,176 @@ read_srclines (Dwarf *dbg,
   fl; })
 
   /* Now read the files.  */
-  nfilelist = 1;
-
-  if (unlikely (linep >= lineendp))
-    goto invalid_data;
-  while (*linep != 0)
+  if (version < 5)
     {
-      struct filelist *new_file = NEW_FILE ();
-
-      /* First comes the file name.  */
-      char *fname = (char *) linep;
-      uint8_t *endp = memchr (fname, '\0', lineendp - linep);
-      if (endp == NULL)
-	goto invalid_data;
-      size_t fnamelen = endp - (uint8_t *) fname;
-      linep = endp + 1;
-
-      /* Then the index.  */
-      Dwarf_Word diridx;
       if (unlikely (linep >= lineendp))
 	goto invalid_data;
-      get_uleb128 (diridx, linep, lineendp);
-      if (unlikely (diridx >= ndirlist))
+      while (*linep != 0)
 	{
-	  __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
-	  goto out;
-	}
+	  struct filelist *new_file = NEW_FILE ();
 
-      if (*fname == '/')
-	/* It's an absolute path.  */
-	new_file->info.name = fname;
-      else
-	{
-	  new_file->info.name = libdw_alloc (dbg, char, 1,
-					     dirarray[diridx].len + 1
-					     + fnamelen + 1);
-	  char *cp = new_file->info.name;
+	  /* First comes the file name.  */
+	  char *fname = (char *) linep;
+	  uint8_t *endp = memchr (fname, '\0', lineendp - linep);
+	  if (endp == NULL)
+	    goto invalid_data;
+	  size_t fnamelen = endp - (uint8_t *) fname;
+	  linep = endp + 1;
 
-	  if (dirarray[diridx].dir != NULL)
+	  /* Then the index.  */
+	  Dwarf_Word diridx;
+	  if (unlikely (linep >= lineendp))
+	    goto invalid_data;
+	  get_uleb128 (diridx, linep, lineendp);
+	  if (unlikely (diridx >= ndirlist))
 	    {
-	      /* 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);
+	      __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
+	      goto out;
 	    }
-	  *cp++ = '/';
-	  strcpy (cp, fname);
-	  assert (strlen (new_file->info.name)
-		  < dirarray[diridx].len + 1 + fnamelen + 1);
+
+	  if (*fname == '/')
+	    /* It's an absolute path.  */
+	    new_file->info.name = fname;
+	  else
+	    {
+	      new_file->info.name = libdw_alloc (dbg, char, 1,
+						 dirarray[diridx].len + 1
+						 + fnamelen + 1);
+	      char *cp = new_file->info.name;
+
+	      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++ = '/';
+	      strcpy (cp, fname);
+	      assert (strlen (new_file->info.name)
+		      < dirarray[diridx].len + 1 + fnamelen + 1);
+	    }
+
+	  /* Next comes the modification time.  */
+	  if (unlikely (linep >= lineendp))
+	    goto invalid_data;
+	  get_uleb128 (new_file->info.mtime, linep, lineendp);
+
+	  /* Finally the length of the file.  */
+	  if (unlikely (linep >= lineendp))
+	    goto invalid_data;
+	  get_uleb128 (new_file->info.length, linep, lineendp);
+	}
+      /* Skip the final NUL byte.  */
+      ++linep;
+    }
+  else
+    {
+      if ((size_t) (lineendp - linep) < 1)
+	goto invalid_data;
+      nforms = *linep++;
+      form_path = form_idx = -1;
+      for (int i = 0; i < nforms; i++)
+	{
+	  uint16_t desc, form;
+	  if ((size_t) (lineendp - linep) < 1)
+	    goto invalid_data;
+	  get_uleb128 (desc, linep, lineendp);
+	  if ((size_t) (lineendp - linep) < 1)
+	    goto invalid_data;
+	  get_uleb128 (form, linep, lineendp);
+
+	  if (! libdw_valid_user_form (form))
+	    goto invalid_data;
+
+	  forms[i] = form;
+	  if (desc == DW_LNCT_path)
+	    form_path = i;
+	  else if (desc == DW_LNCT_directory_index)
+	    form_idx = i;
 	}
 
-      /* Next comes the modification time.  */
-      if (unlikely (linep >= lineendp))
+      if (nforms > 0 && (form_path == (unsigned char) -1
+			 || form_idx == (unsigned char) -1))
 	goto invalid_data;
-      get_uleb128 (new_file->info.mtime, linep, lineendp);
 
-      /* Finally the length of the file.  */
-      if (unlikely (linep >= lineendp))
+      size_t nfiles;
+      get_uleb128 (nfiles, linep, lineendp);
+
+      if (nforms == 0 && nfiles != 0)
 	goto invalid_data;
-      get_uleb128 (new_file->info.length, linep, lineendp);
+
+      Dwarf_Attribute attr;
+      attr.cu = &fake_cu;
+      for (unsigned int n = 0; n < nfiles; n++)
+	{
+	  const char *fname = NULL;
+	  Dwarf_Word diridx = -1;
+	  for (unsigned char m = 0; m < nforms; m++)
+	    {
+	      if (m == form_path)
+		{
+		  attr.code = DW_AT_name;
+		  attr.form = forms[m];
+		  attr.valp = (void *) linep;
+		  fname = dwarf_formstring (&attr);
+		}
+	      else if (m == form_idx)
+		{
+		  attr.code = DW_AT_decl_file; /* Close enough.  */
+		  attr.form = forms[m];
+		  attr.valp = (void *) linep;
+		  dwarf_formudata (&attr, &diridx);
+		}
+
+	      size_t len = __libdw_form_val_len (&fake_cu, forms[m], linep);
+	      if ((size_t) (lineendp - linep) < len)
+		goto invalid_data;
+
+	      linep += len;
+	    }
+
+	  if (fname == NULL || diridx == (Dwarf_Word) -1)
+	    goto invalid_data;
+
+	  size_t fnamelen = strlen (fname);
+
+	  if (unlikely (diridx >= ndirlist))
+	    {
+	      __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
+	      goto out;
+	    }
+
+	  /* Yes, weird.  Looks like an off-by-one in the spec.  */
+	  struct filelist *new_file = n == 0 ? &null_file : NEW_FILE ();
+
+	  /* We follow the same rules as above for DWARF < 5, even
+	     though the standard doesn't explicitly mention absolute
+	     paths and ignoring the dir index.  */
+	  if (*fname == '/')
+	    /* It's an absolute path.  */
+	    new_file->info.name = (char *) fname;
+	  else
+	    {
+	      new_file->info.name = libdw_alloc (dbg, char, 1,
+						 dirarray[diridx].len + 1
+						 + fnamelen + 1);
+	      char *cp = new_file->info.name;
+
+	      /* In the DWARF >= 5 case, dir can never be NULL.  */
+	      cp = stpcpy (cp, dirarray[diridx].dir);
+	      *cp++ = '/';
+	      strcpy (cp, fname);
+	      assert (strlen (new_file->info.name)
+		      < dirarray[diridx].len + 1 + fnamelen + 1);
+	    }
+
+	  /* For now we just ignore the modification time and file length.  */
+	  new_file->info.mtime = 0;
+	  new_file->info.length = 0;
+	}
     }
-  /* Skip the final NUL byte.  */
-  ++linep;
 
   /* Consistency check.  */
   if (unlikely (linep != header_start + header_length))
@@ -408,6 +634,9 @@ read_srclines (Dwarf *dbg,
       goto out;
     }
 
+  /* We are about to process the statement program.  Most state machine
+     registers have already been initialize above.  Just add the is_stmt
+     default. See 6.2.2 in the v2.1 specification.  */
   state.is_stmt = default_is_stmt;
 
   /* Apply the "operation advance" from a special opcode or
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 4de0f6c..751206d 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -493,6 +493,44 @@ libdw_macro_nforms (Dwarf_Macro *macro)
   return macro->table->table[macro->table->opcodes[macro->opcode - 1]].nforms;
 }
 
+/* Returns true for any allowed FORM in the opcode_operands_table as
+   mentioned in the DWARF5 spec (6.3.1 Macro Information Header).
+   Or those mentioned in DWARF5 spec (6.2.4.2 Vendor-defined Content
+   Descriptions) for the directory/file table (plus DW_FORM_strp_sup).  */
+static inline bool
+libdw_valid_user_form (int form)
+{
+  switch (form)
+    {
+      case DW_FORM_block:
+      case DW_FORM_block1:
+      case DW_FORM_block2:
+      case DW_FORM_block4:
+      case DW_FORM_data1:
+      case DW_FORM_data2:
+      case DW_FORM_data4:
+      case DW_FORM_data8:
+      case DW_FORM_data16:
+      case DW_FORM_flag:
+      case DW_FORM_line_strp:
+      case DW_FORM_sdata:
+      case DW_FORM_sec_offset:
+      case DW_FORM_string:
+      case DW_FORM_strp:
+      case DW_FORM_strp_sup:
+      case DW_FORM_strx:
+      case DW_FORM_strx1:
+      case DW_FORM_strx2:
+      case DW_FORM_strx3:
+      case DW_FORM_strx4:
+      case DW_FORM_udata:
+	return true;
+      default:
+	return false;
+    }
+}
+
+
 /* We have to include the file at this point because the inline
    functions access internals of the Dwarf structure.  */
 #include "memory-access.h"
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 14159d8..8a098b4 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,13 @@
+2018-05-05  Mark Wielaard  <mark@klomp.org>
+
+	* testfile-dwarf-45.source: New file.
+	* testfile-dwarf-4.bz2: New test file.
+	* testfile-dwarf-5.bz2: Likewise.
+	* run-readelf-line.sh: Add testcases for testfile-dwarf-4 and
+	testfile-dwarf-5.
+	* Makefile (EXTRA_DIST): Add testfile-dwarf-45.source,
+	testfile-dwarf-4.bz2 and testfile-dwarf-5.bz2.
+
 2018-04-19  Andreas Schwab  <schwab@suse.de>
 
 	* hello_riscv64.ko.bz2: New file.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6b1356e..2f9ae23 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -231,6 +231,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 	     run-readelf-loc.sh testfileloc.bz2 \
 	     run-readelf-aranges.sh run-readelf-line.sh testfilefoobarbaz.bz2 \
 	     testfile-ppc64-min-instr.bz2 \
+	     testfile-dwarf-45.source \
+	     testfile-dwarf-4.bz2 testfile-dwarf-5.bz2 \
 	     run-readelf-z.sh \
 	     run-readelf-dwz-multi.sh libtestfile_multi_shared.so.bz2 \
 	     testfile_multi.dwz.bz2 testfile_multi_main.bz2 \
diff --git a/tests/run-readelf-line.sh b/tests/run-readelf-line.sh
index f93bf47..b08752e 100755
--- a/tests/run-readelf-line.sh
+++ b/tests/run-readelf-line.sh
@@ -345,4 +345,167 @@ DWARF section [29] '.debug_line' at offset 0xdf6:
      8:3   S   *    0   0  0 0x00000000100005f7 <main+0x53>
 
 EOF
+
+# Two tests for the same code but encoded using DWARF4 or DWARF5.
+# Output is identical except for the section offset and CU numbers.
+# See tests/testfile-dwarf-45.source.
+
+testfiles testfile-dwarf-4 testfile-dwarf-5
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=decodedline testfile-dwarf-4 << \EOF
+
+DWARF section [29] '.debug_line' at offset 0x1734:
+
+ CU [b] hello.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+  /var/tmp/hello/hello.c (mtime: 0, length: 0)
+    21:0   S        0   0  0 0x0000000000400510 <foo>
+    22:1   S        0   0  0 0x0000000000400510 <foo>
+    22:3            0   0  0 0x0000000000400510 <foo>
+    25:6            0   0  0 0x0000000000400514 <foo+0x4>
+    25:34  S        0   0  0 0x000000000040051a <foo+0xa>
+    25:3            0   0  0 0x000000000040051a <foo+0xa>
+    26:34           0   0  0 0x000000000040051e <foo+0xe>
+    25:1            1   0  0 0x0000000000400528 <foo+0x18>
+  /var/tmp/hello/hello.h (mtime: 0, length: 0)
+     7:18  S        0   0  0 0x000000000040052b <foo+0x1b>
+     9:3   S        0   0  0 0x000000000040052b <foo+0x1b>
+     9:3            0   0  0 0x000000000040052b <foo+0x1b>
+    10:6   S        0   0  0 0x000000000040052f <foo+0x1f>
+    10:5            0   0  0 0x000000000040052f <foo+0x1f>
+    12:7   S        0   0  0 0x0000000000400531 <foo+0x21>
+  /var/tmp/hello/hello.c (mtime: 0, length: 0)
+    10:3   S        0   0  0 0x0000000000400531 <foo+0x21>
+    12:3   S        0   0  0 0x0000000000400531 <foo+0x21>
+    12:3            0   0  0 0x0000000000400531 <foo+0x21>
+    13:6   S        0   0  0 0x0000000000400535 <foo+0x25>
+    13:5            0   0  0 0x0000000000400535 <foo+0x25>
+    15:7   S        0   0  0 0x0000000000400539 <foo+0x29>
+    22:3   S        0   0  0 0x0000000000400539 <foo+0x29>
+    22:3            0   0  0 0x0000000000400539 <foo+0x29>
+    23:6   S        0   0  0 0x000000000040053d <foo+0x2d>
+    23:5            0   0  0 0x000000000040053d <foo+0x2d>
+     9:12  S        0   0  0 0x0000000000400550 <baz>
+    10:1   S        0   0  0 0x0000000000400550 <baz>
+    12:3   S        0   0  0 0x0000000000400550 <baz>
+    12:3            0   0  0 0x0000000000400550 <baz>
+    13:9            0   0  0 0x0000000000400556 <baz+0x6>
+    15:7   S        0   0  0 0x000000000040055f <baz+0xf>
+    15:3            0   0  0 0x000000000040055f <baz+0xf>
+    15:7       *    0   0  0 0x0000000000400560 <baz+0x10>
+
+ CU [21c] world.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+  /var/tmp/hello/world.c (mtime: 0, length: 0)
+    15:0   S        0   0  0 0x0000000000400410 <main>
+    16:1   S        0   0  0 0x0000000000400410 <main>
+    17:3   S        0   0  0 0x0000000000400410 <main>
+    15:3            0   0  0 0x0000000000400410 <main>
+    17:1            0   0  0 0x0000000000400419 <main+0x9>
+    18:6   S        0   0  0 0x000000000040041e <main+0xe>
+    18:5            0   0  0 0x000000000040041e <main+0xe>
+    22:7   S        0   0  0 0x0000000000400421 <main+0x11>
+    22:3   S   *    0   0  0 0x000000000040042f <main+0x1f>
+
+     6:0   S        0   0  0 0x0000000000400570 <calc>
+     7:1   S        0   0  0 0x0000000000400570 <calc>
+     7:3            0   0  0 0x0000000000400570 <calc>
+     7:6            1   0  0 0x0000000000400575 <calc+0x5>
+     7:24           0   0  0 0x0000000000400578 <calc+0x8>
+    10:17  S        0   0  0 0x000000000040057d <calc+0xd>
+    10:3            0   0  0 0x000000000040057d <calc+0xd>
+  /var/tmp/hello/hello.h (mtime: 0, length: 0)
+    10:10           0   0  0 0x0000000000400583 <calc+0x13>
+  /var/tmp/hello/world.c (mtime: 0, length: 0)
+    10:7            0   0  0 0x0000000000400585 <calc+0x15>
+  /var/tmp/hello/hello.h (mtime: 0, length: 0)
+     7:10  S        0   0  0 0x0000000000400588 <calc+0x18>
+     9:3   S        0   0  0 0x0000000000400588 <calc+0x18>
+    10:3            0   0  0 0x0000000000400588 <calc+0x18>
+    12:7   S        0   0  0 0x000000000040058f <calc+0x1f>
+    12:3            0   0  0 0x000000000040058f <calc+0x1f>
+  /var/tmp/hello/world.c (mtime: 0, length: 0)
+    11:10           0   0  0 0x0000000000400598 <calc+0x28>
+    11:1       *    0   0  0 0x000000000040059a <calc+0x2a>
+
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=decodedline testfile-dwarf-5 << \EOF
+
+DWARF section [29] '.debug_line' at offset 0x171f:
+
+ CU [c] hello.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+  /var/tmp/hello/hello.c (mtime: 0, length: 0)
+    21:0   S        0   0  0 0x0000000000400510 <foo>
+    22:1   S        0   0  0 0x0000000000400510 <foo>
+    22:3            0   0  0 0x0000000000400510 <foo>
+    25:6            0   0  0 0x0000000000400514 <foo+0x4>
+    25:34  S        0   0  0 0x000000000040051a <foo+0xa>
+    25:3            0   0  0 0x000000000040051a <foo+0xa>
+    26:34           0   0  0 0x000000000040051e <foo+0xe>
+    25:1            1   0  0 0x0000000000400528 <foo+0x18>
+  /var/tmp/hello/hello.h (mtime: 0, length: 0)
+     7:18  S        0   0  0 0x000000000040052b <foo+0x1b>
+     9:3   S        0   0  0 0x000000000040052b <foo+0x1b>
+     9:3            0   0  0 0x000000000040052b <foo+0x1b>
+    10:6   S        0   0  0 0x000000000040052f <foo+0x1f>
+    10:5            0   0  0 0x000000000040052f <foo+0x1f>
+    12:7   S        0   0  0 0x0000000000400531 <foo+0x21>
+  /var/tmp/hello/hello.c (mtime: 0, length: 0)
+    10:3   S        0   0  0 0x0000000000400531 <foo+0x21>
+    12:3   S        0   0  0 0x0000000000400531 <foo+0x21>
+    12:3            0   0  0 0x0000000000400531 <foo+0x21>
+    13:6   S        0   0  0 0x0000000000400535 <foo+0x25>
+    13:5            0   0  0 0x0000000000400535 <foo+0x25>
+    15:7   S        0   0  0 0x0000000000400539 <foo+0x29>
+    22:3   S        0   0  0 0x0000000000400539 <foo+0x29>
+    22:3            0   0  0 0x0000000000400539 <foo+0x29>
+    23:6   S        0   0  0 0x000000000040053d <foo+0x2d>
+    23:5            0   0  0 0x000000000040053d <foo+0x2d>
+     9:12  S        0   0  0 0x0000000000400550 <baz>
+    10:1   S        0   0  0 0x0000000000400550 <baz>
+    12:3   S        0   0  0 0x0000000000400550 <baz>
+    12:3            0   0  0 0x0000000000400550 <baz>
+    13:9            0   0  0 0x0000000000400556 <baz+0x6>
+    15:7   S        0   0  0 0x000000000040055f <baz+0xf>
+    15:3            0   0  0 0x000000000040055f <baz+0xf>
+    15:7       *    0   0  0 0x0000000000400560 <baz+0x10>
+
+ CU [218] world.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+  /var/tmp/hello/world.c (mtime: 0, length: 0)
+    15:0   S        0   0  0 0x0000000000400410 <main>
+    16:1   S        0   0  0 0x0000000000400410 <main>
+    17:3   S        0   0  0 0x0000000000400410 <main>
+    15:3            0   0  0 0x0000000000400410 <main>
+    17:1            0   0  0 0x0000000000400419 <main+0x9>
+    18:6   S        0   0  0 0x000000000040041e <main+0xe>
+    18:5            0   0  0 0x000000000040041e <main+0xe>
+    22:7   S        0   0  0 0x0000000000400421 <main+0x11>
+    22:3   S   *    0   0  0 0x000000000040042f <main+0x1f>
+
+     6:0   S        0   0  0 0x0000000000400570 <calc>
+     7:1   S        0   0  0 0x0000000000400570 <calc>
+     7:3            0   0  0 0x0000000000400570 <calc>
+     7:6            1   0  0 0x0000000000400575 <calc+0x5>
+     7:24           0   0  0 0x0000000000400578 <calc+0x8>
+    10:17  S        0   0  0 0x000000000040057d <calc+0xd>
+    10:3            0   0  0 0x000000000040057d <calc+0xd>
+  /var/tmp/hello/hello.h (mtime: 0, length: 0)
+    10:10           0   0  0 0x0000000000400583 <calc+0x13>
+  /var/tmp/hello/world.c (mtime: 0, length: 0)
+    10:7            0   0  0 0x0000000000400585 <calc+0x15>
+  /var/tmp/hello/hello.h (mtime: 0, length: 0)
+     7:10  S        0   0  0 0x0000000000400588 <calc+0x18>
+     9:3   S        0   0  0 0x0000000000400588 <calc+0x18>
+    10:3            0   0  0 0x0000000000400588 <calc+0x18>
+    12:7   S        0   0  0 0x000000000040058f <calc+0x1f>
+    12:3            0   0  0 0x000000000040058f <calc+0x1f>
+  /var/tmp/hello/world.c (mtime: 0, length: 0)
+    11:10           0   0  0 0x0000000000400598 <calc+0x28>
+    11:1       *    0   0  0 0x000000000040059a <calc+0x2a>
+
+EOF
+
 exit 0
diff --git a/tests/testfile-dwarf-4.bz2 b/tests/testfile-dwarf-4.bz2
new file mode 100755
index 0000000000000000000000000000000000000000..fd3aaea560a7ee56fde293656c57ab94d62ed710
GIT binary patch
literal 4304
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

literal 0
HcmV?d00001

diff --git a/tests/testfile-dwarf-45.source b/tests/testfile-dwarf-45.source
new file mode 100644
index 0000000..c9c4446
--- /dev/null
+++ b/tests/testfile-dwarf-45.source
@@ -0,0 +1,81 @@
+# Nonsensical program used to generate an example DWARF4 and DWARF5 file.
+# The generated code is the same, but the DWARF representation is different.
+
+# = hello.h =
+
+extern int m;
+extern int baz (int x);
+
+static inline int
+frob (int a, int b)
+{
+  int c = a;
+
+  if (a > b)
+    c -= b;
+
+  return baz (c);
+}
+
+# = hello.c =
+
+#include <stddef.h>
+#include "hello.h"
+
+extern int main (int, char **);
+int m = 2;
+
+wchar_t foo (wchar_t);
+int baz (int x)
+{
+  int r = x;
+
+  if (x > m)
+    r -= m;
+
+  r = foo (r);
+  return r;
+}
+
+wchar_t
+foo (wchar_t f)
+{
+  if (f < 0)
+    return main (f, NULL);
+
+  return f > 0 ? frob (f - 1, m) : 0;
+}
+
+# = world.c =
+
+#include "hello.h"
+#include <stdlib.h>
+
+int
+calc (const char *word)
+{
+  if (word == 0 || word[0] == '\0')
+    return 0;
+
+  return frob (word[0], m + 42);
+}
+
+int
+main (int argc, const char **argv)
+{
+  const char *n;
+  if (argc > 1)
+    n = argv[0];
+  else
+    n = "world";
+
+  exit (calc (n));
+}
+
+$ gcc -gdwarf-4 -gno-as-loc-support -gno-variable-location-views -O2 -c world.c
+$ gcc -gdwarf-4 -gno-as-loc-support -gno-variable-location-views -O2 -c hello.c
+$ gcc -o testfile-dwarf-4 hello.o world.o
+
+$ gcc -gdwarf-5 -gno-as-loc-support -gno-variable-location-views -O2 -c world.c
+$ gcc -gdwarf-5 -gno-as-loc-support -gno-variable-location-views -O2 -c hello.c
+$ gcc -o testfile-dwarf-5 hello.o world.o
diff --git a/tests/testfile-dwarf-5.bz2 b/tests/testfile-dwarf-5.bz2
new file mode 100755
index 0000000000000000000000000000000000000000..689fa4fc5c97b561beeff03b480e5966ce04ed64
GIT binary patch
literal 4318
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
MBvXY637F?70RKDT2LJ#7

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]