[PATCH 3/4] Increasing support for dwarf 5.

Ali Tamur via gdb-patches gdb-patches@sourceware.org
Tue Aug 27 23:42:00 GMT 2019


* Line table header has new fields.
* Fix handling of file and directory indexes in line tables; in dwarf 5 the
indexes are zero-based.


gdb/ChangeLog:                                                                   
2019-08-26  Ali Tamur  <tamur@google.com>

	* gdb/dwarf2read.c (dir_index): Change definition and update comment.    
	(file_name_index): Likewise.                                             
	(line_header::include_dir_at): Allow for zero based indexes for dwarf 5. 
	(line_header::file_name_at): Likewise.                                   
	(line_header::file_names): Make the field private to abstract the fact   
	that dwarf 4 and 5 use different index bases.                            
	(line_header::file_names_size): New method to let the clients use        
	instead of accessing file_names directly.                                
	(line_header::first_file_index): Likewise.                               
	(file_full_name): Add parameter, is_zero_indexed. The file indexes in    
	the line table is 1-based in dwarf 4, and 0 based in dwarf 5.            
	(dw2_get_file_names_reader): Initialize variable, use added methods to   
	access file names in the line table.                                     
	(dwarf2_cu::setup_type_unit_groups): Use added methods to access file    
	and directory names in line table.                                       
	(process_structure_scope): Use added methods to access file names at the 
	line table.                                                              
	(line_header::add_file_name): Reflect API change.                        
	(dwarf_decode_line_header): Fix statement_program boundry calculations.  
	(psymtab_include_file_name): Reflect API changes.                        
	(lnp_state_machine::current_file): Likewise.                             
	(lnp_state_machine::record_line): Likewise.                              
	(lnp_state_machine::lnp_state_machine): Initialize m_file.               
	(dwarf_decode_lines): Reflect API changes.                               
	(new_symbol): Likewise.                                                  
	(is_valid_file_index): New function.                                     
	(file_file_name): Add parameter, is_zero_indexed.                        
	(file_full_name): Likewise.
---
 gdb/dwarf2read.c | 161 +++++++++++++++++++++++++++--------------------
 1 file changed, 93 insertions(+), 68 deletions(-)

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index b04993e9b6..73ec371af1 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -919,13 +919,13 @@ typedef void (die_reader_func_ftype) (const struct die_reader_specs *reader,
 				      int has_children,
 				      void *data);
 
-/* A 1-based directory index.  This is a strong typedef to prevent
-   accidentally using a directory index as a 0-based index into an
-   array/vector.  */
-enum class dir_index : unsigned int {};
+/* dir_index is 1-based in dwarf 4 and before, and is 0-based in dwarf5 and
+   later.  */
+typedef int dir_index;
 
-/* Likewise, a 1-based file name index.  */
-enum class file_name_index : unsigned int {};
+/* file_name_index is 1-based in dwarf 4 and before, and is 0-based in dwarf5
+   and later.  */
+typedef int file_name_index;
 
 struct file_entry
 {
@@ -977,26 +977,30 @@ struct line_header
   void add_file_name (const char *name, dir_index d_index,
 		      unsigned int mod_time, unsigned int length);
 
-  /* Return the include dir at INDEX (1-based).  Returns NULL if INDEX
-     is out of bounds.  */
+  /* Return the include dir at INDEX (0-based in dwarf5 and 1-based before).
+     Returns NULL if INDEX is out of bounds.  */
   const char *include_dir_at (dir_index index) const
   {
-    /* Convert directory index number (1-based) to vector index
-       (0-based).  */
-    size_t vec_index = to_underlying (index) - 1;
+    size_t vec_index;
+    if (version <= 4)
+      vec_index = index - 1;
+    else
+      vec_index = index;
 
     if (vec_index >= include_dirs.size ())
       return NULL;
     return include_dirs[vec_index];
   }
 
-  /* Return the file name at INDEX (1-based).  Returns NULL if INDEX
-     is out of bounds.  */
-  file_entry *file_name_at (file_name_index index)
+  /* Return the file name at INDEX (0-based in dwarf5 and 1-based before).
+     Returns NULL if INDEX is out of bounds.  */
+  file_entry *file_name_at (file_name_index index, bool is_zero_indexed)
   {
-    /* Convert file name index number (1-based) to vector index
-       (0-based).  */
-    size_t vec_index = to_underlying (index) - 1;
+    size_t vec_index;
+    if (is_zero_indexed || version >= 5)
+        vec_index = index;
+    else
+      vec_index = index - 1;
 
     if (vec_index >= file_names.size ())
       return NULL;
@@ -1029,12 +1033,24 @@ struct line_header
      pointers.  The memory is owned by debug_line_buffer.  */
   std::vector<const char *> include_dirs;
 
-  /* The file_names table.  */
-  std::vector<file_entry> file_names;
+  int file_names_size() {
+    return file_names.size();
+  }
+
+  int first_file_index() {
+    return version >= 5 ? 0 : 1;
+  }
 
   /* The start and end of the statement program following this
      header.  These point into dwarf2_per_objfile->line_buffer.  */
   const gdb_byte *statement_program_start {}, *statement_program_end {};
+
+ private:
+  /* The file_names table. This is private because the meaning of indexes differ
+     among dwarf versions (The first valid index is 1 in dwarf 4 and before,
+     and is 0 in dwarf 5 and later). So the client should use file_name_at
+     method for access.  */
+  std::vector<file_entry> file_names;
 };
 
 typedef std::unique_ptr<line_header> line_header_up;
@@ -1957,7 +1973,7 @@ static file_and_directory find_file_and_directory (struct die_info *die,
 						   struct dwarf2_cu *cu);
 
 static char *file_full_name (int file, struct line_header *lh,
-			     const char *comp_dir);
+			     const char *comp_dir, bool is_zero_indexed);
 
 /* Expected enum dwarf_unit_type for read_comp_unit_head.  */
 enum class rcuh_kind { COMPILE, TYPE };
@@ -3633,7 +3649,7 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   struct dwarf2_per_cu_data *lh_cu;
   struct attribute *attr;
-  int i;
+  int i = 0;
   void **slot;
   struct quick_file_names *qfn;
 
@@ -3688,11 +3704,11 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
 
   file_and_directory fnd = find_file_and_directory (comp_unit_die, cu);
 
-  qfn->num_file_names = lh->file_names.size ();
+  qfn->num_file_names = lh->file_names_size ();
   qfn->file_names =
-    XOBNEWVEC (&objfile->objfile_obstack, const char *, lh->file_names.size ());
-  for (i = 0; i < lh->file_names.size (); ++i)
-    qfn->file_names[i] = file_full_name (i + 1, lh.get (), fnd.comp_dir);
+    XOBNEWVEC (&objfile->objfile_obstack, const char *, lh->file_names_size ());
+  for (i = 0; i < lh->file_names_size (); ++i)
+    qfn->file_names[i] = file_full_name (i, lh.get (), fnd.comp_dir, true);
   qfn->real_names = NULL;
 
   lh_cu->v.quick->file_names = qfn;
@@ -11648,16 +11664,16 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
 	 process_full_type_unit still needs to know if this is the first
 	 time.  */
 
-      tu_group->num_symtabs = line_header->file_names.size ();
+      tu_group->num_symtabs = line_header->file_names_size ();
       tu_group->symtabs = XNEWVEC (struct symtab *,
-				   line_header->file_names.size ());
+				   line_header->file_names_size ());
 
-      for (i = 0; i < line_header->file_names.size (); ++i)
+      for (i = 0; i < line_header->file_names_size (); ++i)
 	{
-	  file_entry &fe = line_header->file_names[i];
+	  file_entry *fe = line_header->file_name_at(i, true);
 
-	  dwarf2_start_subfile (this, fe.name,
-				fe.include_dir (line_header));
+	  dwarf2_start_subfile (this, fe->name,
+				fe->include_dir (line_header));
 	  buildsym_compunit *b = get_builder ();
 	  if (b->get_current_subfile ()->symtab == NULL)
 	    {
@@ -11670,8 +11686,8 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
 		= allocate_symtab (cust, b->get_current_subfile ()->name);
 	    }
 
-	  fe.symtab = b->get_current_subfile ()->symtab;
-	  tu_group->symtabs[i] = fe.symtab;
+	  fe->symtab = b->get_current_subfile ()->symtab;
+	  tu_group->symtabs[i] = fe->symtab;
 	}
     }
   else
@@ -11684,11 +11700,10 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
 			compunit_language (cust),
 			0, cust));
 
-      for (i = 0; i < line_header->file_names.size (); ++i)
+      for (i = 0; i < line_header->file_names_size (); ++i)
 	{
-	  file_entry &fe = line_header->file_names[i];
-
-	  fe.symtab = tu_group->symtabs[i];
+	  file_entry *fe = line_header->file_name_at(i, true);
+	  fe->symtab = tu_group->symtabs[i];
 	}
     }
 
@@ -16161,7 +16176,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
 	    {
 	      /* Any related symtab will do.  */
 	      symtab
-		= cu->line_header->file_name_at (file_name_index (1))->symtab;
+		= cu->line_header->file_name_at (0, true)->symtab;
 	    }
 	  else
 	    {
@@ -20224,7 +20239,7 @@ line_header::add_file_name (const char *name,
 {
   if (dwarf_line_debug >= 2)
     fprintf_unfiltered (gdb_stdlog, "Adding file %u: %s\n",
-			(unsigned) file_names.size () + 1, name);
+			(unsigned) file_names_size () + 1, name);
 
   file_names.emplace_back (name, d_index, mod_time, length);
 }
@@ -20440,12 +20455,15 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
     read_checked_initial_length_and_offset (abfd, line_ptr, &cu->header,
 					    &bytes_read, &offset_size);
   line_ptr += bytes_read;
+
+  const gdb_byte *start_here = line_ptr;
+
   if (line_ptr + lh->total_length > (section->buffer + section->size))
     {
       dwarf2_statement_list_fits_in_line_number_section_complaint ();
       return 0;
     }
-  lh->statement_program_end = line_ptr + lh->total_length;
+  lh->statement_program_end = start_here + lh->total_length;
   lh->version = read_2_bytes (abfd, line_ptr);
   line_ptr += 2;
   if (lh->version > 5)
@@ -20475,6 +20493,7 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
     }
   lh->header_length = read_offset_1 (abfd, line_ptr, offset_size);
   line_ptr += offset_size;
+  lh->statement_program_start = line_ptr + lh->header_length;
   lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
   if (lh->version >= 4)
@@ -20559,7 +20578,6 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
 	}
       line_ptr += bytes_read;
     }
-  lh->statement_program_start = line_ptr;
 
   if (line_ptr > (section->buffer + section->size))
     complaint (_("line number info header doesn't "
@@ -20576,18 +20594,18 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
    Returns NULL if FILE_INDEX should be ignored, i.e., it is pst->filename.  */
 
 static const char *
-psymtab_include_file_name (const struct line_header *lh, int file_index,
+psymtab_include_file_name (struct line_header *lh, int file_index,
 			   const struct partial_symtab *pst,
 			   const char *comp_dir,
 			   gdb::unique_xmalloc_ptr<char> *name_holder)
 {
-  const file_entry &fe = lh->file_names[file_index];
-  const char *include_name = fe.name;
+  file_entry *fe = lh->file_name_at(file_index, true);
+  const char *include_name = fe->name;
   const char *include_name_to_compare = include_name;
   const char *pst_filename;
   int file_is_pst;
 
-  const char *dir_name = fe.include_dir (lh);
+  const char *dir_name = fe->include_dir (lh);
 
   gdb::unique_xmalloc_ptr<char> hold_compare;
   if (!IS_ABSOLUTE_PATH (include_name)
@@ -20659,7 +20677,7 @@ public:
   {
     /* lh->file_names is 0-based, but the file name numbers in the
        statement program are 1-based.  */
-    return m_line_header->file_name_at (m_file);
+    return m_line_header->file_name_at (m_file, false);
   }
 
   /* Record the line in the state machine.  END_SEQUENCE is true if
@@ -20756,12 +20774,11 @@ private:
      and initialized according to the DWARF spec.  */
 
   unsigned char m_op_index = 0;
-  /* The line table index (1-based) of the current file.  */
-  file_name_index m_file = (file_name_index) 1;
   unsigned int m_line = 1;
 
   /* These are initialized in the constructor.  */
 
+  file_name_index m_file;
   CORE_ADDR m_address;
   bool m_is_stmt;
   unsigned int m_discriminator;
@@ -20949,7 +20966,7 @@ lnp_state_machine::record_line (bool end_sequence)
       fprintf_unfiltered (gdb_stdlog,
 			  "Processing actual line %u: file %u,"
 			  " address %s, is_stmt %u, discrim %u\n",
-			  m_line, to_underlying (m_file),
+			  m_line, m_file,
 			  paddress (m_gdbarch, m_address),
 			  m_is_stmt, m_discriminator);
     }
@@ -20999,6 +21016,7 @@ lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
   m_gdbarch = arch;
   m_record_lines_p = record_lines_p;
   m_line_header = lh;
+  m_file = m_line_header->first_file_index();
 
   m_currently_recording_lines = true;
 
@@ -21292,8 +21310,8 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
 
       /* Now that we're done scanning the Line Header Program, we can
          create the psymtab of each included file.  */
-      for (file_index = 0; file_index < lh->file_names.size (); file_index++)
-        if (lh->file_names[file_index].included_p == 1)
+      for (file_index = 0; file_index < lh->file_names_size (); file_index++)
+        if (lh->file_name_at(file_index, true)->included_p == 1)
           {
 	    gdb::unique_xmalloc_ptr<char> name_holder;
 	    const char *include_name =
@@ -21312,11 +21330,11 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
       struct compunit_symtab *cust = builder->get_compunit_symtab ();
       int i;
 
-      for (i = 0; i < lh->file_names.size (); i++)
+      for (i = 0; i < lh->file_names_size (); i++)
 	{
-	  file_entry &fe = lh->file_names[i];
+	  file_entry *fe = lh->file_name_at(i, true);
 
-	  dwarf2_start_subfile (cu, fe.name, fe.include_dir (lh));
+	  dwarf2_start_subfile (cu, fe->name, fe->include_dir (lh));
 
 	  if (builder->get_current_subfile ()->symtab == NULL)
 	    {
@@ -21324,7 +21342,7 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
 		= allocate_symtab (cust,
 				   builder->get_current_subfile ()->name);
 	    }
-	  fe.symtab = builder->get_current_subfile ()->symtab;
+	  fe->symtab = builder->get_current_subfile ()->symtab;
 	}
     }
 }
@@ -21543,7 +21561,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 	  struct file_entry *fe;
 
 	  if (cu->line_header != NULL)
-	    fe = cu->line_header->file_name_at (file_index);
+	    fe = cu->line_header->file_name_at (file_index, false);
 	  else
 	    fe = NULL;
 
@@ -24074,22 +24092,28 @@ dwarf_alloc_die (struct dwarf2_cu *cu, int num_attrs)
    *LH's file name table.  The result is allocated using xmalloc; the caller is
    responsible for freeing it.  */
 
+bool is_valid_file_index(int file_index, struct line_header *lh, bool is_zero_indexed) {
+  if (is_zero_indexed || lh->version >= 5)
+    return 0 <= file_index && file_index < lh->file_names_size ();
+  return 1 <= file_index && file_index <= lh->file_names_size ();
+}
+
 static char *
-file_file_name (int file, struct line_header *lh)
+file_file_name (int file, struct line_header *lh, bool is_zero_indexed)
 {
   /* Is the file number a valid index into the line header's file name
      table?  Remember that file numbers start with one, not zero.  */
-  if (1 <= file && file <= lh->file_names.size ())
+  if (is_valid_file_index(file, lh, is_zero_indexed))
     {
-      const file_entry &fe = lh->file_names[file - 1];
+      const file_entry *fe = lh->file_name_at(file, is_zero_indexed);
 
-      if (!IS_ABSOLUTE_PATH (fe.name))
+      if (!IS_ABSOLUTE_PATH (fe->name))
 	{
-	  const char *dir = fe.include_dir (lh);
+	  const char *dir = fe->include_dir (lh);
 	  if (dir != NULL)
-	    return concat (dir, SLASH_STRING, fe.name, (char *) NULL);
+	    return concat (dir, SLASH_STRING, fe->name, (char *) NULL);
 	}
-      return xstrdup (fe.name);
+      return xstrdup (fe->name);
     }
   else
     {
@@ -24113,13 +24137,14 @@ file_file_name (int file, struct line_header *lh)
    compilation.  The result is allocated using xmalloc; the caller is
    responsible for freeing it.  */
 static char *
-file_full_name (int file, struct line_header *lh, const char *comp_dir)
+file_full_name (int file, struct line_header *lh, const char *comp_dir,
+		bool is_zero_indexed)
 {
   /* Is the file number a valid index into the line header's file name
      table?  Remember that file numbers start with one, not zero.  */
-  if (1 <= file && file <= lh->file_names.size ())
+  if (is_valid_file_index(file, lh, is_zero_indexed))
     {
-      char *relative = file_file_name (file, lh);
+      char *relative = file_file_name (file, lh, is_zero_indexed);
 
       if (IS_ABSOLUTE_PATH (relative) || comp_dir == NULL)
 	return relative;
@@ -24127,7 +24152,7 @@ file_full_name (int file, struct line_header *lh, const char *comp_dir)
 		       relative, (char *) NULL);
     }
   else
-    return file_file_name (file, lh);
+    return file_file_name (file, lh, is_zero_indexed);
 }
 
 
@@ -24138,7 +24163,7 @@ macro_start_file (struct dwarf2_cu *cu,
                   struct line_header *lh)
 {
   /* File name relative to the compilation directory of this source file.  */
-  char *file_name = file_file_name (file, lh);
+  char *file_name = file_file_name (file, lh, false);
 
   if (! current_file)
     {
-- 
2.23.0.187.g17f5b7556c-goog



More information about the Gdb-patches mailing list