This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB 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 5/6] DWARF Two Level Line Tables: DWARF 5 line table extensions


Hi.

This patch adds support for DWARF 5 line tables described here:

http://www.dwarfstd.org/ShowIssue.php?issue=140724.1

2015-03-12  Doug Evans  <dje@google.com>

	include/
	* dwarf2.def (DW_FORM_line_strp): New form.
	* dwarf2.h (dwarf_line_number_content_type): New enum.

	gdb/
	* NEWS: Mention DWARF 5 line tables.
	* dwarf2read.c (dwarf2_per_objfile): New member line_str.
	(dwarf2_elf_names): Update.
	(struct file_entry): Add comment.  New member offset_size.
	Rename member header_length to prologue_length, all uses updated.
	New members address_size, segment_size.
	(dwarf_line_number_content_type_name): New function.
	(skip_form_bytes): New function.
	(dwarf2_statement_list_fits_in_line_number_section_complaint): Delete.
	(dwarf2_invalid_form_complaint): New function.
	(dwarf2_locate_sections): Handle .debug_line_str.
	(read_indirect_line_string): New function.
	(read_unsigned_integer): New function.
	(read_dwarf2_line_header_paths): New function.
	(dwarf5_line_header_format): New struct.
	(dwarf5_line_header_entry): New struct.
	(read_dwarf5_line_header_entry): New function.
	(read_dwarf5_line_header_subtable): New function.
	(read_dwarf5_line_header_paths): New function.
	(dwarf_decode_line_header): Update to handle DWARF5 line tables.
	(dwarf_line_number_content_type_name): New function.
	(skip_form_bytes): Mention DW_FORM_data16.  Call
	dwarf2_invalid_form_complaint.
	* symfile.h (struct dwarf2_debug_sections): New member line_str.
	* xcoffread.c (dwarf2_xcoff_names): Add entry for .debug_line_str.

diff --git a/gdb/NEWS b/gdb/NEWS
index 9674ec2..51cd4e6 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,10 @@
 
 *** Changes since GDB 7.9
 
+* DWARF
+
+GDB now supports DWARF 5 line tables and the new .debug_line_str section.
+
 * The "info source" command now displays the producer string if it was
   present in the debug info.  This typically includes the compiler version
   and may include things like its command line arguments.
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 827ae6c..c82bbcb 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -223,6 +223,7 @@ struct dwarf2_per_objfile
   struct dwarf2_section_info macinfo;
   struct dwarf2_section_info macro;
   struct dwarf2_section_info str;
+  struct dwarf2_section_info line_str;
   struct dwarf2_section_info ranges;
   struct dwarf2_section_info addr;
   struct dwarf2_section_info frame;
@@ -334,6 +335,7 @@ static const struct dwarf2_debug_sections dwarf2_elf_names =
   { ".debug_macinfo", ".zdebug_macinfo" },
   { ".debug_macro", ".zdebug_macro" },
   { ".debug_str", ".zdebug_str" },
+  { ".debug_line_str", ".zdebug_line_str" },
   { ".debug_ranges", ".zdebug_ranges" },
   { ".debug_types", ".zdebug_types" },
   { ".debug_addr", ".zdebug_addr" },
@@ -1030,6 +1032,10 @@ typedef void (die_reader_func_ftype) (const struct die_reader_specs *reader,
 struct file_entry
 {
   const char *name;
+  /* Note: In DWARF5, the current directory is defined to exist in the
+     directory table as the first entry and has number zero.  To preserve
+     the meaning of "dir_index == 0 -> no directory", one is added to the
+     DWARF5 directory number.  */
   unsigned int dir_index;
   unsigned int mod_time;
   unsigned int length;
@@ -1051,8 +1057,9 @@ struct line_header
   unsigned offset_in_dwz : 1;
 
   unsigned int total_length;
+  unsigned int offset_size;
   unsigned short version;
-  unsigned int header_length;
+  unsigned int prologue_length;
   unsigned char minimum_instruction_length;
   unsigned char maximum_ops_per_instruction;
   unsigned char default_is_stmt;
@@ -1060,6 +1067,9 @@ struct line_header
   unsigned char line_range;
   unsigned char opcode_base;
 
+  /* The address and segment sizes.  These were added in DWARF5.  */
+  unsigned char address_size, segment_size;
+
   /* standard_opcode_lengths[i] is the number of operands for the
      standard opcode whose value is i.  This means that
      standard_opcode_lengths[0] is unused, and the last meaningful
@@ -1692,6 +1702,8 @@ static char *dwarf_bool_name (unsigned int);
 
 static const char *dwarf_type_encoding_name (unsigned int);
 
+static const char *dwarf_line_number_content_type_name (unsigned int);
+
 static struct die_info *sibling_die (struct die_info *);
 
 static void dump_die_shallow (struct ui_file *, int indent, struct die_info *);
@@ -1762,6 +1774,12 @@ static const gdb_byte *skip_one_die (const struct die_reader_specs *reader,
 				     const gdb_byte *info_ptr,
 				     struct abbrev_info *abbrev);
 
+static const gdb_byte *skip_form_bytes (bfd *abfd, const gdb_byte *bytes,
+					const gdb_byte *buffer_end,
+					enum dwarf_form form,
+					unsigned int offset_size,
+					struct dwarf2_section_info *section);
+
 static void free_stack_comp_unit (void *);
 
 static hashval_t partial_die_hash (const void *item);
@@ -1872,13 +1890,6 @@ static void free_line_header_voidp (void *arg);
 /* Various complaints about symbol reading that don't abort the process.  */
 
 static void
-dwarf2_statement_list_fits_in_line_number_section_complaint (void)
-{
-  complaint (&symfile_complaints,
-	     _("statement list doesn't fit in .debug_line section"));
-}
-
-static void
 dwarf2_debug_line_missing_file_complaint (void)
 {
   complaint (&symfile_complaints,
@@ -1935,6 +1946,20 @@ dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
 	     arg1, arg2);
 }
 
+/* Issue a complaint saying FORM is invalid in context CONTEXT
+   in section SECTION.  */
+
+static void
+dwarf2_invalid_form_complaint (unsigned int form, const char *context,
+			       unsigned int offset,
+			       struct dwarf2_section_info *section)
+{
+  complaint (&symfile_complaints,
+	     _("invalid form %s(0x%x) in %s at offset 0x%x of section %s [in module %s]"),
+	     dwarf_form_name (form), form, context, offset,
+	     get_section_name (section), get_section_file_name (section));
+}
+
 /* Hash function for line_header_hash.  */
 
 static hashval_t
@@ -2181,6 +2206,11 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
       dwarf2_per_objfile->line.s.asection = sectp;
       dwarf2_per_objfile->line.size = bfd_get_section_size (sectp);
     }
+  else if (section_is_p (sectp->name, &names->line_str))
+    {
+      dwarf2_per_objfile->line_str.s.asection = sectp;
+      dwarf2_per_objfile->line_str.size = bfd_get_section_size (sectp);
+    }
   else if (section_is_p (sectp->name, &names->loc))
     {
       dwarf2_per_objfile->loc.s.asection = sectp;
@@ -16642,6 +16672,36 @@ read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset)
   return (const char *) (dwarf2_per_objfile->str.buffer + str_offset);
 }
 
+/* Return the string in .debug_line_str at STR_OFFSET.
+   Returns NULL if there is no such section or if STR_OFFSET is invalid,
+   a complaint will have already been issued.
+   The caller is responsible for converting "" to NULL if desired.  */
+
+static const char *
+read_indirect_line_string (bfd *abfd, LONGEST str_offset)
+{
+  dwarf2_read_section (dwarf2_per_objfile->objfile,
+		       &dwarf2_per_objfile->line_str);
+  if (dwarf2_per_objfile->line_str.buffer == NULL)
+    {
+      complaint (&symfile_complaints,
+		 _("DW_FORM_line_strp used without .debug_line_str section"
+		   " [in module %s]"),
+		 bfd_get_filename (abfd));
+      return NULL;
+    }
+  if (str_offset >= dwarf2_per_objfile->line_str.size)
+    {
+      complaint (&symfile_complaints,
+		 _("DW_FORM_line_strp pointing outside of"
+		   " .debug_line_str section [in module %s]"),
+		 bfd_get_filename (abfd));
+      return NULL;
+    }
+  gdb_assert (HOST_CHAR_BIT == 8);
+  return (const char *) (dwarf2_per_objfile->line_str.buffer + str_offset);
+}
+
 /* Read a string at offset STR_OFFSET in the .debug_str section from
    the .dwz file DWZ.  Throw an error if the offset is too large.  If
    the string consists of a single NUL byte, return NULL; otherwise
@@ -16735,6 +16795,53 @@ read_signed_leb128 (bfd *abfd, const gdb_byte *buf,
   return result;
 }
 
+/* Read an unsigned integer of form FORM from SECTION at INFO_PTR.
+   INFO_PTR must point into SECTION's buffer.
+   The value is stored in *RESULT_PTR.
+   CONTEXT describes the context in which the value is being read and is
+   only used in complaints.
+   The result is the number of bytes read, unless there was an error
+   (e.g., bad form), in which case a complaint is issued and NULL
+   is returned.  */
+
+static const gdb_byte *
+read_unsigned_integer (struct dwarf2_section_info *section,
+		       const gdb_byte *buf, unsigned int form,
+		       const char *context, ULONGEST *result_ptr)
+{
+  bfd *abfd = get_section_bfd_owner (section);
+
+  gdb_assert (buf >= section->buffer
+	      && buf < section->buffer + section->size);
+
+  switch (form)
+    {
+    case DW_FORM_data1:
+      *result_ptr = read_1_byte (abfd, buf);
+      return buf + 1;
+    case DW_FORM_data2:
+      *result_ptr = read_2_bytes (abfd, buf);
+      return buf + 2;
+    case DW_FORM_data4:
+      *result_ptr = read_4_bytes (abfd, buf);
+      return buf + 4;
+    case DW_FORM_data8:
+      *result_ptr = read_8_bytes (abfd, buf);
+      return buf + 8;
+    case DW_FORM_udata:
+      {
+	unsigned int bytes_read;
+
+	*result_ptr = read_unsigned_leb128 (abfd, buf, &bytes_read);
+	return buf + bytes_read;
+      }
+    default:
+      dwarf2_invalid_form_complaint (form, context, buf - section->buffer,
+				     section);
+      return NULL;
+    }
+}
+
 /* Given index ADDR_INDEX in .debug_addr, fetch the value.
    ADDR_BASE is the DW_AT_GNU_addr_base attribute or zero.
    ADDR_SIZE is the size of addresses from the CU header.  */
@@ -17193,22 +17300,317 @@ get_debug_line_section (struct dwarf2_cu *cu)
   return section;
 }
 
+/* Subroutine of dwarf_decode_line_header to simplify it.
+   Read old style (pre-dwarf5) line header paths (directory and
+   file name entries).
+   The result is a pointer to the end of the read data, or NULL
+   if there was an error (a complaint has already been issued).  */
+
+static const gdb_byte *
+read_dwarf2_line_header_paths (struct line_header *lh,
+			       struct dwarf2_section_info *section,
+			       const gdb_byte *line_ptr)
+{
+  bfd *abfd = get_section_bfd_owner (section);
+  const gdb_byte *end_ptr = section->buffer + section->size;
+  unsigned int bytes_read;
+  const char *cur_dir, *cur_file;
+
+  /* Read directory table.  */
+  while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+    {
+      line_ptr += bytes_read;
+      add_include_dir (lh, cur_dir);
+    }
+  line_ptr += bytes_read;
+
+  /* Read file name table.  */
+  while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+    {
+      unsigned int dir_index, mod_time, length;
+
+      line_ptr += bytes_read;
+      dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      line_ptr += bytes_read;
+      mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      line_ptr += bytes_read;
+      length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      line_ptr += bytes_read;
+
+      add_file_name (lh, cur_file, dir_index, mod_time, length);
+    }
+  line_ptr += bytes_read;
+
+  if (line_ptr > end_ptr)
+    {
+      dwarf2_section_buffer_overflow_complaint (section);
+      return NULL;
+    }
+
+  return line_ptr;
+}
+
+struct dwarf5_line_header_format
+{
+  /* One of DW_LNCT_*.  */
+  unsigned int type;
+  /* One of DW_FORM_*.  */
+  unsigned int form;
+};
+
+struct dwarf5_line_header_entry
+{
+  /* DW_LNCT_path.  */
+  const char *path;
+  /* DW_LNCT_directory_index.  */
+  unsigned int dir_index;
+  /* DW_LNCT_timestamp.  */
+  unsigned int timestamp;
+  /* DW_LNCT_size.  */
+  unsigned int size;
+};
+
+/* Subroutine of read_dwarf5_line_header_paths to simplify it.
+   Process TYPE,FORM for ENTRY.
+   The result is a pointer to the end of the read data, or NULL
+   if an error was found (complaint has already been issued).  */
+
+static const gdb_byte *
+read_dwarf5_line_header_entry (struct line_header *lh,
+			       struct dwarf2_section_info *section,
+			       const gdb_byte *line_ptr,
+			       unsigned int type, unsigned int form,
+			       struct dwarf5_line_header_entry *entry)
+{
+  bfd *abfd = get_section_bfd_owner (section);
+  const gdb_byte *end_ptr = section->buffer + section->size;
+  unsigned int offset_size = lh->offset_size;
+  unsigned int bytes_read;
+  const char *context = dwarf_line_number_content_type_name (type);
+  const char *string = NULL;
+  ULONGEST value = 0;
+
+  switch (type)
+    {
+    case DW_LNCT_path:
+      switch (form)
+	{
+	case DW_FORM_string:
+	  string = read_direct_string (abfd, line_ptr, &bytes_read);
+	  break;
+	case DW_FORM_line_strp:
+	  value = read_offset_1 (abfd, line_ptr, offset_size);
+	  line_ptr += offset_size;
+	  string = read_indirect_line_string (abfd, value);
+	  if (string == NULL)
+	    string = "<invalid-file>";
+	  break;
+	/*case DW_FORM_strx: - TODO(dje) */
+	default:
+	  goto complaint_bad_form;
+	}
+      break;
+    case DW_LNCT_directory_index:
+    case DW_LNCT_timestamp:
+    case DW_LNCT_size:
+      line_ptr = read_unsigned_integer (section, line_ptr, form, context,
+					&value);
+      if (line_ptr == NULL)
+	return NULL;
+      break;
+#if 0 /* Disabled until DW_FORM_data16 appears in dwarf2.def.  */
+    case DW_LNCT_MD5:
+      if (form != DW_FORM_data16)
+	goto complaint_bad_form;
+      /* Ignore for now.  */
+      line_ptr += 16;
+      break;
+#endif
+    default:
+      /* Ignore.  */
+      line_ptr = skip_form_bytes (abfd, line_ptr, end_ptr, form,
+				  offset_size, section);
+      if (line_ptr == NULL)
+	return NULL;
+      if (line_ptr > end_ptr)
+	{
+	  dwarf2_section_buffer_overflow_complaint (section);
+	  return NULL;
+	}
+      return line_ptr;
+    }
+
+  switch (type)
+    {
+    case DW_LNCT_path:
+      entry->path = string;
+      break;
+    case DW_LNCT_directory_index:
+      entry->dir_index = value;
+      break;
+    case DW_LNCT_timestamp:
+      entry->timestamp = value;
+      break;
+    case DW_LNCT_size:
+      entry->size = value;
+      break;
+    default:
+      gdb_assert_not_reached ("bad type handling");
+    }
+
+  if (line_ptr > end_ptr)
+    {
+      dwarf2_section_buffer_overflow_complaint (section);
+      return NULL;
+    }
+
+  return line_ptr;
+
+ complaint_bad_form:
+  dwarf2_invalid_form_complaint (form, context, line_ptr - section->buffer,
+				 section);
+  return NULL;
+}
+
+/* Utility to read the directory / file-names / subprogram-names entries.
+   They all have the same format, which is self-describing.
+   The processed table is stored in *ENTRIES_PTR, with its size stored in
+   *NR_ENTRIES_PTR.
+   The result is a pointer to the end of the read data, or NULL
+   if an error was found (complaint has already been issued).  */
+
+static const gdb_byte *
+read_dwarf5_line_header_subtable (struct line_header *lh,
+				  struct dwarf2_section_info *section,
+				  const gdb_byte *line_ptr,
+				  struct dwarf5_line_header_entry **entries_ptr,
+				  unsigned int *nr_entries_ptr)
+{
+  bfd *abfd = get_section_bfd_owner (section);
+  const gdb_byte *end_ptr = section->buffer + section->size;
+  unsigned char entry_format_count;
+  struct dwarf5_line_header_format *format;
+  unsigned int entry_count;
+  struct dwarf5_line_header_entry *entries;
+  unsigned int bytes_read;
+  unsigned int i, j;
+  struct cleanup *cleanups;
+
+  entry_format_count = read_1_byte (abfd, line_ptr);
+  ++line_ptr;
+
+  format = (struct dwarf5_line_header_format *)
+    alloca (entry_format_count
+	     * sizeof (struct dwarf5_line_header_format *));
+  for (i = 0; i < entry_format_count; ++i)
+    {
+      format[i].type = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      line_ptr += bytes_read;
+      format[i].form = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      line_ptr += bytes_read;
+    }
+
+  entry_count = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+  line_ptr += bytes_read;
+  entries = XCNEWVEC (struct dwarf5_line_header_entry, entry_count);
+  cleanups = make_cleanup (xfree, entries);
+
+  for (i = 0; i < entry_count; ++i)
+    {
+      for (j = 0; j < entry_format_count; ++j)
+	{
+	  line_ptr = read_dwarf5_line_header_entry (lh, section, line_ptr,
+						    format[j].type,
+						    format[j].form,
+						    &entries[i]);
+	  if (line_ptr == NULL)
+	    {
+	      do_cleanups (cleanups);
+	      return NULL;
+	    }
+	}
+    }
+
+  gdb_assert (line_ptr != NULL);
+  discard_cleanups (cleanups);
+  *entries_ptr = entries;
+  *nr_entries_ptr = entry_count;
+  return line_ptr;
+}
+
+/* Subroutine of dwarf_decode_line_header to simplify it.
+   Read new style (dwarf5) line header paths (directory and
+   file name entries).
+   The result is a pointer to the end of the read data, or NULL
+   if an error was found (complaint has already been issued).  */
+
+static const gdb_byte *
+read_dwarf5_line_header_paths (struct line_header *lh,
+			       struct dwarf2_section_info *section,
+			       const gdb_byte *line_ptr)
+{
+  bfd *abfd = get_section_bfd_owner (section);
+  unsigned int i, dir_count, file_count;
+  struct dwarf5_line_header_entry *directories, *files;
+  struct cleanup *cleanups;
+
+  cleanups = make_cleanup (null_cleanup, NULL);
+
+  line_ptr = read_dwarf5_line_header_subtable (lh, section, line_ptr,
+					       &directories, &dir_count);
+  if (line_ptr == NULL)
+    {
+      do_cleanups (cleanups);
+      return NULL;
+    }
+
+  make_cleanup (xfree, directories);
+
+  line_ptr = read_dwarf5_line_header_subtable (lh, section, line_ptr,
+					       &files, &file_count);
+  if (line_ptr == NULL)
+    {
+      do_cleanups (cleanups);
+      return NULL;
+    }
+
+  make_cleanup (xfree, files);
+
+  for (i = 0; i < dir_count; ++i)
+    {
+      add_include_dir (lh, directories[i].path);
+    }
+
+  for (i = 0; i < file_count; ++i)
+    {
+      add_file_name (lh, files[i].path, files[i].dir_index,
+		     files[i].timestamp, files[i].size);
+    }
+
+  gdb_assert (line_ptr != NULL);
+  do_cleanups (cleanups);
+  return line_ptr;
+}
+
 /* Read the statement program header starting at OFFSET in
    .debug_line, or .debug_line.dwo.  Return a pointer
    to a struct line_header, allocated using xmalloc.
-   Returns NULL if there is a problem reading the header, e.g., if it
-   has a version we don't understand.
+   Returns NULL if there is a problem reading the header, e.g., if it has a
+   version we don't understand, a complaint will have already been issued.
 
    NOTE: the strings in the include directory and file name tables of
    the returned object point into the dwarf line section buffer,
-   and must not be freed.  */
+   and must not be freed.
+
+   DWARF5 support follows the proposal here:
+   http://dwarfstd.org/ShowIssue.php?issue=140724.1 */
 
 static struct line_header *
 dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
 {
   struct cleanup *back_to;
   struct line_header *lh;
-  const gdb_byte *line_ptr;
+  const gdb_byte *line_ptr, *end_ptr, *program_end;
   unsigned int bytes_read, offset_size;
   int i;
   const char *cur_dir, *cur_file;
@@ -17223,7 +17625,7 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
 	complaint (&symfile_complaints, _("missing .debug_line.dwo section"));
       else
 	complaint (&symfile_complaints, _("missing .debug_line section"));
-      return 0;
+      return NULL;
     }
 
   /* We can't do this until we know the section is non-empty.
@@ -17234,8 +17636,8 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
      That could be 12 bytes long, but we're just going to fudge that.  */
   if (offset + 4 >= section->size)
     {
-      dwarf2_statement_list_fits_in_line_number_section_complaint ();
-      return 0;
+      dwarf2_section_buffer_overflow_complaint (section);
+      return NULL;
     }
 
   lh = xmalloc (sizeof (*lh));
@@ -17247,22 +17649,25 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
   lh->offset_in_dwz = cu->per_cu->is_dwz;
 
   line_ptr = section->buffer + offset;
+  end_ptr = section->buffer + section->size;
 
   /* Read in the header.  */
+
   lh->total_length =
     read_checked_initial_length_and_offset (abfd, line_ptr, &cu->header,
 					    &bytes_read, &offset_size);
   line_ptr += bytes_read;
-  if (line_ptr + lh->total_length > (section->buffer + section->size))
+  lh->offset_size = offset_size;
+  if (line_ptr + lh->total_length > end_ptr)
     {
-      dwarf2_statement_list_fits_in_line_number_section_complaint ();
+      dwarf2_section_buffer_overflow_complaint (section);
       do_cleanups (back_to);
-      return 0;
+      return NULL;
     }
-  lh->statement_program_end = line_ptr + lh->total_length;
+  program_end = line_ptr + lh->total_length;
   lh->version = read_2_bytes (abfd, line_ptr);
   line_ptr += 2;
-  if (lh->version > 4)
+  if (lh->version > 5)
     {
       /* This is a version we don't understand.  The format could have
 	 changed in ways we don't handle properly so just punt.  */
@@ -17270,7 +17675,14 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
 		 _("unsupported version in .debug_line section"));
       return NULL;
     }
-  lh->header_length = read_offset_1 (abfd, line_ptr, offset_size);
+  if (lh->version >= 5)
+    {
+      lh->address_size = read_1_byte (abfd, line_ptr);
+      line_ptr += 1;
+      lh->segment_size = read_1_byte (abfd, line_ptr);
+      line_ptr += 1;
+    }
+  lh->prologue_length = read_offset_1 (abfd, line_ptr, offset_size);
   line_ptr += offset_size;
   lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
@@ -17308,36 +17720,41 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
       line_ptr += 1;
     }
 
-  /* Read directory table.  */
-  while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+  if (line_ptr >= program_end)
     {
-      line_ptr += bytes_read;
-      add_include_dir (lh, cur_dir);
+      dwarf2_section_buffer_overflow_complaint (section);
+      do_cleanups (back_to);
+      return NULL;
     }
-  line_ptr += bytes_read;
-
-  /* Read file name table.  */
-  while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
-    {
-      unsigned int dir_index, mod_time, length;
 
-      line_ptr += bytes_read;
-      dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-      line_ptr += bytes_read;
-      mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-      line_ptr += bytes_read;
-      length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-      line_ptr += bytes_read;
+  /* Read in the directory and file tables.  */
 
-      add_file_name (lh, cur_file, dir_index, mod_time, length);
+  if (lh->version <= 4)
+    line_ptr = read_dwarf2_line_header_paths (lh, section, line_ptr);
+  else if (lh->version == 5)
+    {
+      line_ptr = read_dwarf5_line_header_paths (lh, section, line_ptr);
+      if (line_ptr == NULL)
+	{
+	  do_cleanups (back_to);
+	  return NULL;
+	}
     }
-  line_ptr += bytes_read;
+  if (line_ptr == NULL)
+    {
+      do_cleanups (back_to);
+      return NULL;
+    }
+
   lh->statement_program_start = line_ptr;
+  lh->statement_program_end = program_end;
 
-  if (line_ptr > (section->buffer + section->size))
-    complaint (&symfile_complaints,
-	       _("line number info header doesn't "
-		 "fit in `.debug_line' section"));
+  if (line_ptr > program_end)
+    {
+      dwarf2_section_buffer_overflow_complaint (section);
+      do_cleanups (back_to);
+      return NULL;
+    }
 
   discard_cleanups (back_to);
   return lh;
@@ -19628,6 +20045,28 @@ dwarf_type_encoding_name (unsigned enc)
   return name;
 }
 
+/* Return name of a line number table content type.  */
+
+static const char *
+dwarf_line_number_content_type_name (unsigned int type)
+{
+  switch (type)
+    {
+    case DW_LNCT_path:
+      return "DW_LNCT_path";
+    case DW_LNCT_directory_index:
+      return "DW_LNCT_directory_index";
+    case DW_LNCT_timestamp:
+      return "DW_LNCT_timestamp";
+    case DW_LNCT_size:
+      return "DW_LNCT_size";
+    case DW_LNCT_MD5:
+      return "DW_LNCT_MD5";
+    default:
+      return "DW_LNCT_<unknown>";
+    }
+}
+
 static void
 dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
 {
@@ -21014,6 +21453,12 @@ skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end,
       bytes += 8;
       break;
 
+#if 0 /* Disabled until DW_FORM_data16 appears in dwarf2.def.  */
+    case DW_FORM_data16:
+      bytes += 16;
+      break;
+#endif
+
     case DW_FORM_string:
       read_direct_string (abfd, bytes, &bytes_read);
       bytes += bytes_read;
@@ -21053,13 +21498,9 @@ skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end,
       break;
 
     default:
-      {
-      complain:
-	complaint (&symfile_complaints,
-		   _("invalid form 0x%x in `%s'"),
-		   form, get_section_name (section));
-	return NULL;
-      }
+      dwarf2_invalid_form_complaint (form, _("skipping"),
+				     bytes - section->buffer, section);
+      return NULL;
     }
 
   return bytes;
diff --git a/gdb/symfile.h b/gdb/symfile.h
index 7b66c62..ffd2b0c 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -616,6 +616,7 @@ struct dwarf2_debug_sections {
   struct dwarf2_section_names macinfo;
   struct dwarf2_section_names macro;
   struct dwarf2_section_names str;
+  struct dwarf2_section_names line_str;
   struct dwarf2_section_names ranges;
   struct dwarf2_section_names types;
   struct dwarf2_section_names addr;
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 3cb6eda..c845dac 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -162,6 +162,7 @@ static const struct dwarf2_debug_sections dwarf2_xcoff_names = {
   { NULL, NULL }, /* debug_macinfo */
   { NULL, NULL }, /* debug_macro */
   { ".dwstr", NULL },
+  { NULL, NULL }, /* debug_line_str */
   { ".dwrnges", NULL },
   { NULL, NULL }, /* debug_types */
   { NULL, NULL }, /* debug_addr */
diff --git a/include/dwarf2.def b/include/dwarf2.def
index e61cfbe..4f1a748 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -202,6 +202,8 @@ DW_FORM (DW_FORM_sec_offset, 0x17)
 DW_FORM (DW_FORM_exprloc, 0x18)
 DW_FORM (DW_FORM_flag_present, 0x19)
 DW_FORM (DW_FORM_ref_sig8, 0x20)
+/* DWARF 5.  */
+DW_FORM (DW_FORM_line_strp, 0x1f)
 /* Extensions for Fission.  See http://gcc.gnu.org/wiki/DebugFission.  */
 DW_FORM (DW_FORM_GNU_addr_index, 0x1f01)
 DW_FORM (DW_FORM_GNU_str_index, 0x1f02)
diff --git a/include/dwarf2.h b/include/dwarf2.h
index 4ada871..52e39b2 100644
--- a/include/dwarf2.h
+++ b/include/dwarf2.h
@@ -268,6 +268,19 @@ enum dwarf_location_list_entry_type
     DW_LLE_GNU_start_length_entry = 3
   };
 
+/* Type codes for line number program content descriptors (DWARF 5).  */
+
+enum dwarf_line_number_content_type
+  {
+    DW_LNCT_path = 1,
+    DW_LNCT_directory_index = 2,
+    DW_LNCT_timestamp = 3,
+    DW_LNCT_size = 4,
+    DW_LNCT_MD5 = 5,
+    DW_LNCT_lo_user = 0x2000,
+    DW_LNCT_hi_user = 0x3fff
+  };
+
 #define DW_CIE_ID	  0xffffffff
 #define DW64_CIE_ID	  0xffffffffffffffffULL
 #define DW_CIE_VERSION	  1


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