public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 00/22] More splitting of dwarf2/read.c
@ 2020-03-22 18:45 Tom Tromey
  2020-03-22 18:45 ` [PATCH 01/22] Introduce dwarf2/dwz.h Tom Tromey
                   ` (22 more replies)
  0 siblings, 23 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches

One goal of mine is to split up the DWARF reader code into many
smaller, more self-contained files.  I think this will make the code
easier to read and to work on; and also let us tease out (and repair)
hidden dependencies.  This latter part is desirable because, in the
longer run, I'd like to parallelize DWARF reading.

So, here is round 2 of splitting.

The main change here is that the macro-reading code is moved to its
own file.  It's almost possible, after this, to scan macros in a
worker thread.  (However, dwz file handling, and the recent move to
sharing a bcache, interfere with this.)

Some smaller utility functions are also moved into other files as
well.

Let me know what you think,
Tom



^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 01/22] Introduce dwarf2/dwz.h
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 02/22] Add dwz.c and dwz_file::read_string Tom Tromey
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This moves "struct dwz_file" to a new header file, dwarf2/dwz.h.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.h (struct dwz_file): Move to dwz.h.
	* dwarf2/read.c: Add include.
	* dwarf2/index-write.c: Add include.
	* dwarf2/index-cache.c: Add include.
	* dwarf2/dwz.h: New file.
---
 gdb/ChangeLog            |  8 ++++++
 gdb/dwarf2/dwz.h         | 58 ++++++++++++++++++++++++++++++++++++++++
 gdb/dwarf2/index-cache.c |  1 +
 gdb/dwarf2/index-write.c |  1 +
 gdb/dwarf2/read.c        |  1 +
 gdb/dwarf2/read.h        | 31 ---------------------
 6 files changed, 69 insertions(+), 31 deletions(-)
 create mode 100644 gdb/dwarf2/dwz.h

diff --git a/gdb/dwarf2/dwz.h b/gdb/dwarf2/dwz.h
new file mode 100644
index 00000000000..94b84ebf3d9
--- /dev/null
+++ b/gdb/dwarf2/dwz.h
@@ -0,0 +1,58 @@
+/* DWARF DWZ handling for GDB.
+
+   Copyright (C) 2003-2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program 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.
+
+   This program 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/>.  */
+
+#ifndef GDB_DWARF2_DWZ_H
+#define GDB_DWARF2_DWZ_H
+
+#include "gdb_bfd.h"
+#include "dwarf2/index-cache.h"
+#include "dwarf2/section.h"
+
+/* This represents a '.dwz' file.  */
+
+struct dwz_file
+{
+  dwz_file (gdb_bfd_ref_ptr &&bfd)
+    : dwz_bfd (std::move (bfd))
+  {
+  }
+
+  const char *filename () const
+  {
+    return bfd_get_filename (this->dwz_bfd.get ());
+  }
+
+  /* A dwz file can only contain a few sections.  */
+  struct dwarf2_section_info abbrev {};
+  struct dwarf2_section_info info {};
+  struct dwarf2_section_info str {};
+  struct dwarf2_section_info line {};
+  struct dwarf2_section_info macro {};
+  struct dwarf2_section_info gdb_index {};
+  struct dwarf2_section_info debug_names {};
+
+  /* The dwz's BFD.  */
+  gdb_bfd_ref_ptr dwz_bfd;
+
+  /* If we loaded the index from an external file, this contains the
+     resources associated to the open file, memory mapping, etc.  */
+  std::unique_ptr<index_cache_resource> index_cache_res;
+};
+
+#endif /* GDB_DWARF2_DWZ_H */
diff --git a/gdb/dwarf2/index-cache.c b/gdb/dwarf2/index-cache.c
index 7b4d9975905..62fbe2a0b4d 100644
--- a/gdb/dwarf2/index-cache.c
+++ b/gdb/dwarf2/index-cache.c
@@ -27,6 +27,7 @@
 #include "gdbsupport/pathstuff.h"
 #include "dwarf2/index-write.h"
 #include "dwarf2/read.h"
+#include "dwarf2/dwz.h"
 #include "objfiles.h"
 #include "gdbsupport/selftest.h"
 #include <string>
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
index 4b711d0d29a..8c933dc63b7 100644
--- a/gdb/dwarf2/index-write.c
+++ b/gdb/dwarf2/index-write.c
@@ -32,6 +32,7 @@
 #include "dwarf2/index-common.h"
 #include "dwarf2.h"
 #include "dwarf2/read.h"
+#include "dwarf2/dwz.h"
 #include "gdb/gdb-index.h"
 #include "gdbcmd.h"
 #include "objfiles.h"
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 0e879e08a0c..57ef2428c02 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -37,6 +37,7 @@
 #include "dwarf2/index-common.h"
 #include "dwarf2/leb.h"
 #include "dwarf2/line-header.h"
+#include "dwarf2/dwz.h"
 #include "bfd.h"
 #include "elf-bfd.h"
 #include "symtab.h"
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index f0e3d6bb723..c5a8ecf8a6a 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -491,37 +491,6 @@ struct signatured_type
   struct dwo_unit *dwo_unit;
 };
 
-/* This represents a '.dwz' file.  */
-
-struct dwz_file
-{
-  dwz_file (gdb_bfd_ref_ptr &&bfd)
-    : dwz_bfd (std::move (bfd))
-  {
-  }
-
-  const char *filename () const
-  {
-    return bfd_get_filename (this->dwz_bfd.get ());
-  }
-
-  /* A dwz file can only contain a few sections.  */
-  struct dwarf2_section_info abbrev {};
-  struct dwarf2_section_info info {};
-  struct dwarf2_section_info str {};
-  struct dwarf2_section_info line {};
-  struct dwarf2_section_info macro {};
-  struct dwarf2_section_info gdb_index {};
-  struct dwarf2_section_info debug_names {};
-
-  /* The dwz's BFD.  */
-  gdb_bfd_ref_ptr dwz_bfd;
-
-  /* If we loaded the index from an external file, this contains the
-     resources associated to the open file, memory mapping, etc.  */
-  std::unique_ptr<index_cache_resource> index_cache_res;
-};
-
 /* Open the separate '.dwz' debug file, if needed.  Return NULL if
    there is no .gnu_debugaltlink section in the file.  Error if there
    is such a section but the file cannot be found.  */
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 02/22] Add dwz.c and dwz_file::read_string
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
  2020-03-22 18:45 ` [PATCH 01/22] Introduce dwarf2/dwz.h Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 03/22] Change dwarf_decode_macro_bytes calling convention Tom Tromey
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes read_indirect_string_from_dwz to be a method on the
dwz_file, and adds a new dwarf2/dwz.c file.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.c (read_attribute_value): Update.
	(read_indirect_string_from_dwz): Move to dwz.c; change into
	method.
	(dwarf_decode_macro_bytes): Update.
	* dwarf2/dwz.h (struct dwz_file) <read_string>: Declare method.
	* dwarf2/dwz.c: New file.
	* Makefile.in (COMMON_SFILES): Add dwz.c.
---
 gdb/ChangeLog     | 10 ++++++++++
 gdb/Makefile.in   |  1 +
 gdb/dwarf2/dwz.c  | 40 ++++++++++++++++++++++++++++++++++++++++
 gdb/dwarf2/dwz.h  |  7 +++++++
 gdb/dwarf2/read.c | 34 ++--------------------------------
 5 files changed, 60 insertions(+), 32 deletions(-)
 create mode 100644 gdb/dwarf2/dwz.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 0c331af4bff..c9450ce7b52 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1003,6 +1003,7 @@ COMMON_SFILES = \
 	dwarf2/abbrev.c \
 	dwarf2/attribute.c \
 	dwarf2/comp-unit.c \
+	dwarf2/dwz.c \
 	dwarf2/expr.c \
 	dwarf2/frame-tailcall.c \
 	dwarf2/frame.c \
diff --git a/gdb/dwarf2/dwz.c b/gdb/dwarf2/dwz.c
new file mode 100644
index 00000000000..a7143738194
--- /dev/null
+++ b/gdb/dwarf2/dwz.c
@@ -0,0 +1,40 @@
+/* DWARF DWZ handling for GDB.
+
+   Copyright (C) 2003-2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program 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.
+
+   This program 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/>.  */
+
+#include "defs.h"
+#include "dwarf2/dwz.h"
+
+const char *
+dwz_file::read_string (struct objfile *objfile, LONGEST str_offset)
+{
+  str.read (objfile);
+
+  if (str.buffer == NULL)
+    error (_("DW_FORM_GNU_strp_alt used without .debug_str "
+	     "section [in module %s]"),
+	   bfd_get_filename (dwz_bfd.get ()));
+  if (str_offset >= str.size)
+    error (_("DW_FORM_GNU_strp_alt pointing outside of "
+	     ".debug_str section [in module %s]"),
+	   bfd_get_filename (dwz_bfd.get ()));
+  gdb_assert (HOST_CHAR_BIT == 8);
+  if (str.buffer[str_offset] == '\0')
+    return NULL;
+  return (const char *) (str.buffer + str_offset);
+}
diff --git a/gdb/dwarf2/dwz.h b/gdb/dwarf2/dwz.h
index 94b84ebf3d9..54e60612a3f 100644
--- a/gdb/dwarf2/dwz.h
+++ b/gdb/dwarf2/dwz.h
@@ -53,6 +53,13 @@ struct dwz_file
   /* If we loaded the index from an external file, this contains the
      resources associated to the open file, memory mapping, etc.  */
   std::unique_ptr<index_cache_resource> index_cache_res;
+
+  /* Read a string at offset STR_OFFSET in the .debug_str section from
+     this dwz file.  Throw an error if the offset is too large.  If
+     the string consists of a single NUL byte, return NULL; otherwise
+     return a pointer to the string.  */
+
+  const char *read_string (struct objfile *objfile, LONGEST str_offset);
 };
 
 #endif /* GDB_DWARF2_DWZ_H */
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 57ef2428c02..23b3fab1be5 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1259,9 +1259,6 @@ static const char *read_indirect_string_at_offset
   (struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *abfd,
    LONGEST str_offset);
 
-static const char *read_indirect_string_from_dwz
-  (struct objfile *objfile, struct dwz_file *, LONGEST);
-
 static CORE_ADDR read_addr_index_from_leb128 (struct dwarf2_cu *,
 					      const gdb_byte *,
 					      unsigned int *);
@@ -18585,8 +18582,7 @@ read_attribute_value (const struct die_reader_specs *reader,
 	LONGEST str_offset = cu_header->read_offset (abfd, info_ptr,
 						     &bytes_read);
 
-	DW_STRING (attr) = read_indirect_string_from_dwz (objfile,
-							  dwz, str_offset);
+	DW_STRING (attr) = dwz->read_string (objfile, str_offset);
 	DW_STRING_IS_CANONICAL (attr) = 0;
 	info_ptr += bytes_read;
       }
@@ -18831,31 +18827,6 @@ read_indirect_line_string_at_offset (struct dwarf2_per_objfile *dwarf2_per_objfi
 					      ".debug_line_str");
 }
 
-/* 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
-   return a pointer to the string.  */
-
-static const char *
-read_indirect_string_from_dwz (struct objfile *objfile, struct dwz_file *dwz,
-			       LONGEST str_offset)
-{
-  dwz->str.read (objfile);
-
-  if (dwz->str.buffer == NULL)
-    error (_("DW_FORM_GNU_strp_alt used without .debug_str "
-	     "section [in module %s]"),
-	   bfd_get_filename (dwz->dwz_bfd.get ()));
-  if (str_offset >= dwz->str.size)
-    error (_("DW_FORM_GNU_strp_alt pointing outside of "
-	     ".debug_str section [in module %s]"),
-	   bfd_get_filename (dwz->dwz_bfd.get ()));
-  gdb_assert (HOST_CHAR_BIT == 8);
-  if (dwz->str.buffer[str_offset] == '\0')
-    return NULL;
-  return (const char *) (dwz->str.buffer + str_offset);
-}
-
 /* Return pointer to string at .debug_str offset as read from BUF.
    BUF is assumed to be in a compilation unit described by CU_HEADER.
    Return *BYTES_READ_PTR count of bytes read from BUF.  */
@@ -23584,8 +23555,7 @@ dwarf_decode_macro_bytes (struct dwarf2_cu *cu,
 		    struct dwz_file *dwz
 		      = dwarf2_get_dwz_file (dwarf2_per_objfile);
 
-		    body = read_indirect_string_from_dwz (objfile,
-							  dwz, str_offset);
+		    body = dwz->read_string (objfile, str_offset);
 		  }
 		else
 		  body = read_indirect_string_at_offset (dwarf2_per_objfile,
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 03/22] Change dwarf_decode_macro_bytes calling convention
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
  2020-03-22 18:45 ` [PATCH 01/22] Introduce dwarf2/dwz.h Tom Tromey
  2020-03-22 18:45 ` [PATCH 02/22] Add dwz.c and dwz_file::read_string Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 04/22] Split dwarf_decode_macros into two overloads Tom Tromey
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes dwarf_decode_macro_bytes to accept a buildsym_compunit
rather than a dwarf2_cu.  This enables some subsequent changes; and
also makes the function accept a "more specific" parameter.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.c (macro_start_file): Change "cu" parameter to
	"builder".
	(dwarf_decode_macro_bytes): Likewise.  Add dwarf2_per_objfile
	parameter.
	(dwarf_decode_macros): Update.
---
 gdb/ChangeLog     |  8 ++++++++
 gdb/dwarf2/read.c | 23 +++++++++++++----------
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 23b3fab1be5..1410dd48a2f 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -23090,7 +23090,7 @@ dwarf_alloc_die (struct dwarf2_cu *cu, int num_attrs)
 /* Macro support.  */
 
 static struct macro_source_file *
-macro_start_file (struct dwarf2_cu *cu,
+macro_start_file (buildsym_compunit *builder,
 		  int file, int line,
                   struct macro_source_file *current_file,
                   struct line_header *lh)
@@ -23102,7 +23102,7 @@ macro_start_file (struct dwarf2_cu *cu,
     {
       /* Note: We don't create a macro table for this compilation unit
 	 at all until we actually get a filename.  */
-      struct macro_table *macro_table = cu->get_builder ()->get_macro_table ();
+      struct macro_table *macro_table = builder->get_macro_table ();
 
       /* If we have no current file, then this must be the start_file
 	 directive for the compilation unit's main source file.  */
@@ -23463,7 +23463,8 @@ dwarf_parse_macro_header (const gdb_byte **opcode_definitions,
    including DW_MACRO_import.  */
 
 static void
-dwarf_decode_macro_bytes (struct dwarf2_cu *cu,
+dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
+			  buildsym_compunit *builder,
 			  bfd *abfd,
 			  const gdb_byte *mac_ptr, const gdb_byte *mac_end,
 			  struct macro_source_file *current_file,
@@ -23473,8 +23474,6 @@ dwarf_decode_macro_bytes (struct dwarf2_cu *cu,
 			  unsigned int offset_size,
 			  htab_t include_hash)
 {
-  struct dwarf2_per_objfile *dwarf2_per_objfile
-    = cu->per_cu->dwarf2_per_objfile;
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   enum dwarf_macro_record_type macinfo_type;
   int at_commandline;
@@ -23631,8 +23630,8 @@ dwarf_decode_macro_bytes (struct dwarf2_cu *cu,
 		at_commandline = 0;
 	      }
 	    else
-	      current_file = macro_start_file (cu, file, line, current_file,
-					       lh);
+	      current_file = macro_start_file (builder, file, line,
+					       current_file, lh);
           }
           break;
 
@@ -23713,7 +23712,8 @@ dwarf_decode_macro_bytes (struct dwarf2_cu *cu,
 	      {
 		*slot = (void *) new_mac_ptr;
 
-		dwarf_decode_macro_bytes (cu, include_bfd, new_mac_ptr,
+		dwarf_decode_macro_bytes (dwarf2_per_objfile, builder,
+					  include_bfd, new_mac_ptr,
 					  include_mac_end, current_file, lh,
 					  section, section_is_gnu, is_dwz,
 					  offset_size, include_hash);
@@ -23827,6 +23827,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
       return;
     }
 
+  buildsym_compunit *builder = cu->get_builder ();
   do
     {
       /* Do we at least have room for a macinfo type byte?  */
@@ -23875,7 +23876,8 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
 	    file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
 	    mac_ptr += bytes_read;
 
-	    current_file = macro_start_file (cu, file, line, current_file, lh);
+	    current_file = macro_start_file (builder, file, line,
+					     current_file, lh);
 	  }
 	  break;
 
@@ -23940,7 +23942,8 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
   mac_ptr = section->buffer + offset;
   slot = htab_find_slot (include_hash.get (), mac_ptr, INSERT);
   *slot = (void *) mac_ptr;
-  dwarf_decode_macro_bytes (cu, abfd, mac_ptr, mac_end,
+  dwarf_decode_macro_bytes (dwarf2_per_objfile, builder,
+			    abfd, mac_ptr, mac_end,
 			    current_file, lh, section,
 			    section_is_gnu, 0, offset_size,
 			    include_hash.get ());
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 04/22] Split dwarf_decode_macros into two overloads
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (2 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 03/22] Change dwarf_decode_macro_bytes calling convention Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-23 16:13   ` Christian Biesinger
  2020-03-24  1:58   ` Simon Marchi
  2020-03-22 18:45 ` [PATCH 05/22] Move dwarf2_section_buffer_overflow_complaint to dwarf2/section.c Tom Tromey
                   ` (18 subsequent siblings)
  22 siblings, 2 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This splits dwarf_decode_macros into two overloads -- one that's
suitable for splitting into a separate file, and one that finds the
correct section and should remain in dwarf2/read.c.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.c (dwarf_decode_macros): Split into two overloads.
---
 gdb/ChangeLog     |   4 ++
 gdb/dwarf2/read.c | 102 +++++++++++++++++++++++++++-------------------
 2 files changed, 63 insertions(+), 43 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 1410dd48a2f..2d126461c74 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -23753,56 +23753,18 @@ dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
 }
 
 static void
-dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
-                     int section_is_gnu)
+dwarf_decode_macros (struct dwarf2_per_objfile *dwarf2_per_objfile,
+		     buildsym_compunit *builder, dwarf2_section_info *section,
+		     struct line_header *lh, unsigned int offset_size,
+		     unsigned int offset, int section_is_gnu)
 {
-  struct dwarf2_per_objfile *dwarf2_per_objfile
-    = cu->per_cu->dwarf2_per_objfile;
-  struct objfile *objfile = dwarf2_per_objfile->objfile;
-  struct line_header *lh = cu->line_header;
   bfd *abfd;
   const gdb_byte *mac_ptr, *mac_end;
   struct macro_source_file *current_file = 0;
   enum dwarf_macro_record_type macinfo_type;
-  unsigned int offset_size = cu->header.offset_size;
   const gdb_byte *opcode_definitions[256];
   void **slot;
-  struct dwarf2_section_info *section;
-  const char *section_name;
 
-  if (cu->dwo_unit != NULL)
-    {
-      if (section_is_gnu)
-	{
-	  section = &cu->dwo_unit->dwo_file->sections.macro;
-	  section_name = ".debug_macro.dwo";
-	}
-      else
-	{
-	  section = &cu->dwo_unit->dwo_file->sections.macinfo;
-	  section_name = ".debug_macinfo.dwo";
-	}
-    }
-  else
-    {
-      if (section_is_gnu)
-	{
-	  section = &dwarf2_per_objfile->macro;
-	  section_name = ".debug_macro";
-	}
-      else
-	{
-	  section = &dwarf2_per_objfile->macinfo;
-	  section_name = ".debug_macinfo";
-	}
-    }
-
-  section->read (objfile);
-  if (section->buffer == NULL)
-    {
-      complaint (_("missing %s section"), section_name);
-      return;
-    }
   abfd = section->get_bfd_owner ();
 
   /* First pass: Find the name of the base filename.
@@ -23827,7 +23789,6 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
       return;
     }
 
-  buildsym_compunit *builder = cu->get_builder ();
   do
     {
       /* Do we at least have room for a macinfo type byte?  */
@@ -23949,6 +23910,61 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
 			    include_hash.get ());
 }
 
+/* An overload of dwarf_decode_macros that finds the correct section
+   and ensures it is read in before calling the other overload.  */
+
+static void
+dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
+                     int section_is_gnu)
+{
+  struct dwarf2_per_objfile *dwarf2_per_objfile
+    = cu->per_cu->dwarf2_per_objfile;
+  struct objfile *objfile = dwarf2_per_objfile->objfile;
+  struct line_header *lh = cu->line_header;
+  unsigned int offset_size = cu->header.offset_size;
+  struct dwarf2_section_info *section;
+  const char *section_name;
+
+  if (cu->dwo_unit != NULL)
+    {
+      if (section_is_gnu)
+	{
+	  section = &cu->dwo_unit->dwo_file->sections.macro;
+	  section_name = ".debug_macro.dwo";
+	}
+      else
+	{
+	  section = &cu->dwo_unit->dwo_file->sections.macinfo;
+	  section_name = ".debug_macinfo.dwo";
+	}
+    }
+  else
+    {
+      if (section_is_gnu)
+	{
+	  section = &dwarf2_per_objfile->macro;
+	  section_name = ".debug_macro";
+	}
+      else
+	{
+	  section = &dwarf2_per_objfile->macinfo;
+	  section_name = ".debug_macinfo";
+	}
+    }
+
+  section->read (objfile);
+  if (section->buffer == NULL)
+    {
+      complaint (_("missing %s section"), section_name);
+      return;
+    }
+
+  buildsym_compunit *builder = cu->get_builder ();
+
+  dwarf_decode_macros (dwarf2_per_objfile, builder, section, lh,
+		       offset_size, offset, section_is_gnu);
+}
+
 /* Return the .debug_loc section to use for CU.
    For DWO files use .debug_loc.dwo.  */
 
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 05/22] Move dwarf2_section_buffer_overflow_complaint to dwarf2/section.c
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (3 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 04/22] Split dwarf_decode_macros into two overloads Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 06/22] Convert dwarf2_section_buffer_overflow_complaint to a method Tom Tromey
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This moves dwarf2_section_buffer_overflow_complaint to
dwarf2/section.c.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/section.h (dwarf2_section_buffer_overflow_complaint):
	Declare.
	* dwarf2/section.c (dwarf2_section_buffer_overflow_complaint):
	Move from read.c.
	* dwarf2/read.c (dwarf2_section_buffer_overflow_complaint): Move
	to section.c.
---
 gdb/ChangeLog        |  9 +++++++++
 gdb/dwarf2/read.c    |  9 ---------
 gdb/dwarf2/section.c | 10 ++++++++++
 gdb/dwarf2/section.h |  3 +++
 4 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 2d126461c74..2b4f693c38a 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1711,15 +1711,6 @@ dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2,
 	     arg1, arg2, arg3);
 }
 
-static void
-dwarf2_section_buffer_overflow_complaint (struct dwarf2_section_info *section)
-{
-  complaint (_("debug info runs off end of %s section"
-	       " [in module %s]"),
-	     section->get_name (),
-	     section->get_file_name ());
-}
-
 static void
 dwarf2_macro_malformed_definition_complaint (const char *arg1)
 {
diff --git a/gdb/dwarf2/section.c b/gdb/dwarf2/section.c
index 5e33809117d..31cb8b9b2e7 100644
--- a/gdb/dwarf2/section.c
+++ b/gdb/dwarf2/section.c
@@ -28,6 +28,16 @@
 #include "dwarf2/section.h"
 #include "gdb_bfd.h"
 #include "objfiles.h"
+#include "complaints.h"
+
+void
+dwarf2_section_buffer_overflow_complaint (struct dwarf2_section_info *section)
+{
+  complaint (_("debug info runs off end of %s section"
+	       " [in module %s]"),
+	     section->get_name (),
+	     section->get_file_name ());
+}
 
 struct dwarf2_section_info *
 dwarf2_section_info::get_containing_section () const
diff --git a/gdb/dwarf2/section.h b/gdb/dwarf2/section.h
index 8ddedcaf761..f4ac9af311e 100644
--- a/gdb/dwarf2/section.h
+++ b/gdb/dwarf2/section.h
@@ -116,4 +116,7 @@ struct dwarf2_section_info
   bool is_virtual;
 };
 
+extern void dwarf2_section_buffer_overflow_complaint
+  (struct dwarf2_section_info *section);
+
 #endif /* GDB_DWARF2_SECTION_H */
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 06/22] Convert dwarf2_section_buffer_overflow_complaint to a method
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (4 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 05/22] Move dwarf2_section_buffer_overflow_complaint to dwarf2/section.c Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 07/22] Add dwarf2_section_info::read_string method Tom Tromey
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes dwarf2_section_buffer_overflow_complaint to be a method
on dwarf2_section_info.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/section.h (struct dwarf2_section_info)
	<overload_complaint>: Declare.
	(dwarf2_section_buffer_overflow_complaint): Don't declare.
	* dwarf2/section.c (dwarf2_section_info::overflow_complaint):
	Rename from dwarf2_section_buffer_overflow_complaint.
	* dwarf2/read.c (skip_one_die, partial_die_info::read)
	(skip_form_bytes, dwarf_decode_macro_bytes): Update.
---
 gdb/ChangeLog        | 10 ++++++++++
 gdb/dwarf2/read.c    | 10 +++++-----
 gdb/dwarf2/section.c |  5 ++---
 gdb/dwarf2/section.h |  7 ++++---
 4 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 2b4f693c38a..52a53428d5b 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -8595,7 +8595,7 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
 	      if (sibling_ptr < info_ptr)
 		complaint (_("DW_AT_sibling points backwards"));
 	      else if (sibling_ptr > reader->buffer_end)
-		dwarf2_section_buffer_overflow_complaint (reader->die_section);
+		reader->die_section->overflow_complaint ();
 	      else
 		return sibling_ptr;
 	    }
@@ -18079,7 +18079,7 @@ partial_die_info::read (const struct die_reader_specs *reader,
 	      if (sibling_ptr < info_ptr)
 		complaint (_("DW_AT_sibling points backwards"));
 	      else if (sibling_ptr > reader->buffer_end)
-		dwarf2_section_buffer_overflow_complaint (reader->die_section);
+		reader->die_section->overflow_complaint ();
 	      else
 		sibling = sibling_ptr;
 	    }
@@ -23329,7 +23329,7 @@ skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end,
       bytes = gdb_skip_leb128 (bytes, buffer_end);
       if (bytes == NULL)
 	{
-	  dwarf2_section_buffer_overflow_complaint (section);
+	  section->overflow_complaint ();
 	  return NULL;
 	}
       break;
@@ -23492,7 +23492,7 @@ dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
       /* Do we at least have room for a macinfo type byte?  */
       if (mac_ptr >= mac_end)
 	{
-	  dwarf2_section_buffer_overflow_complaint (section);
+	  section->overflow_complaint ();
 	  break;
 	}
 
@@ -23645,7 +23645,7 @@ dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
                   /* Do we at least have room for a macinfo type byte?  */
                   if (mac_ptr >= mac_end)
                     {
-		      dwarf2_section_buffer_overflow_complaint (section);
+		      section->overflow_complaint ();
                       return;
                     }
 
diff --git a/gdb/dwarf2/section.c b/gdb/dwarf2/section.c
index 31cb8b9b2e7..9714368a5d2 100644
--- a/gdb/dwarf2/section.c
+++ b/gdb/dwarf2/section.c
@@ -31,12 +31,11 @@
 #include "complaints.h"
 
 void
-dwarf2_section_buffer_overflow_complaint (struct dwarf2_section_info *section)
+dwarf2_section_info::overflow_complaint () const
 {
   complaint (_("debug info runs off end of %s section"
 	       " [in module %s]"),
-	     section->get_name (),
-	     section->get_file_name ());
+	     get_name (), get_file_name ());
 }
 
 struct dwarf2_section_info *
diff --git a/gdb/dwarf2/section.h b/gdb/dwarf2/section.h
index f4ac9af311e..555efecacd6 100644
--- a/gdb/dwarf2/section.h
+++ b/gdb/dwarf2/section.h
@@ -94,6 +94,10 @@ struct dwarf2_section_info
     return size;
   }
 
+  /* Issue a complaint that something was outside the bounds of this
+     buffer.  */
+  void overflow_complaint () const;
+
   union
   {
     /* If this is a real section, the bfd section.  */
@@ -116,7 +120,4 @@ struct dwarf2_section_info
   bool is_virtual;
 };
 
-extern void dwarf2_section_buffer_overflow_complaint
-  (struct dwarf2_section_info *section);
-
 #endif /* GDB_DWARF2_SECTION_H */
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 07/22] Add dwarf2_section_info::read_string method
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (5 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 06/22] Convert dwarf2_section_buffer_overflow_complaint to a method Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 08/22] Move code to new file dwarf2/macro.c Tom Tromey
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This moves a string-reading function to be a method on
dwarf2_section_info, and then updates the users.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/section.h (struct dwarf2_section_info) <read_string>: New
	method.
	* dwarf2/section.c: New method.  From
	read_indirect_string_at_offset_from.
	* dwarf2/read.c (mapped_debug_names::namei_to_name): Update.
	(read_indirect_string_at_offset_from): Move to section.c.
	(read_indirect_string_at_offset): Rewrite.
	(read_indirect_line_string_at_offset): Remove.
	(read_indirect_string, read_indirect_line_string)
	(dwarf_decode_macro_bytes): Update.
---
 gdb/ChangeLog        | 13 ++++++++++
 gdb/dwarf2/read.c    | 60 ++++++++------------------------------------
 gdb/dwarf2/section.c | 17 +++++++++++++
 gdb/dwarf2/section.h |  5 ++++
 4 files changed, 46 insertions(+), 49 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 52a53428d5b..75d028d95b1 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1256,8 +1256,7 @@ static const char *read_indirect_line_string
    const struct comp_unit_head *, unsigned int *);
 
 static const char *read_indirect_string_at_offset
-  (struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *abfd,
-   LONGEST str_offset);
+  (struct dwarf2_per_objfile *dwarf2_per_objfile, LONGEST str_offset);
 
 static CORE_ADDR read_addr_index_from_leb128 (struct dwarf2_cu *,
 					      const gdb_byte *,
@@ -5171,8 +5170,8 @@ mapped_debug_names::namei_to_name (uint32_t namei) const
 				 + namei * offset_size),
 				offset_size,
 				dwarf5_byte_order);
-  return read_indirect_string_at_offset
-    (dwarf2_per_objfile, dwarf2_per_objfile->objfile->obfd, namei_string_offs);
+  return read_indirect_string_at_offset (dwarf2_per_objfile,
+					 namei_string_offs);
 }
 
 /* Find a slot in .debug_names for the object named NAME.  If NAME is
@@ -18770,52 +18769,14 @@ read_checked_initial_length_and_offset (bfd *abfd, const gdb_byte *buf,
   return length;
 }
 
-/* Return pointer to string at section SECT offset STR_OFFSET with error
-   reporting strings FORM_NAME and SECT_NAME.  */
-
-static const char *
-read_indirect_string_at_offset_from (struct objfile *objfile,
-				     bfd *abfd, LONGEST str_offset,
-				     struct dwarf2_section_info *sect,
-				     const char *form_name,
-				     const char *sect_name)
-{
-  sect->read (objfile);
-  if (sect->buffer == NULL)
-    error (_("%s used without %s section [in module %s]"),
-	   form_name, sect_name, bfd_get_filename (abfd));
-  if (str_offset >= sect->size)
-    error (_("%s pointing outside of %s section [in module %s]"),
-	   form_name, sect_name, bfd_get_filename (abfd));
-  gdb_assert (HOST_CHAR_BIT == 8);
-  if (sect->buffer[str_offset] == '\0')
-    return NULL;
-  return (const char *) (sect->buffer + str_offset);
-}
-
 /* Return pointer to string at .debug_str offset STR_OFFSET.  */
 
 static const char *
 read_indirect_string_at_offset (struct dwarf2_per_objfile *dwarf2_per_objfile,
-				bfd *abfd, LONGEST str_offset)
-{
-  return read_indirect_string_at_offset_from (dwarf2_per_objfile->objfile,
-					      abfd, str_offset,
-					      &dwarf2_per_objfile->str,
-					      "DW_FORM_strp", ".debug_str");
-}
-
-/* Return pointer to string at .debug_line_str offset STR_OFFSET.  */
-
-static const char *
-read_indirect_line_string_at_offset (struct dwarf2_per_objfile *dwarf2_per_objfile,
-				     bfd *abfd, LONGEST str_offset)
+				LONGEST str_offset)
 {
-  return read_indirect_string_at_offset_from (dwarf2_per_objfile->objfile,
-					      abfd, str_offset,
-					      &dwarf2_per_objfile->line_str,
-					      "DW_FORM_line_strp",
-					      ".debug_line_str");
+  return dwarf2_per_objfile->str.read_string (dwarf2_per_objfile->objfile,
+					      str_offset, "DW_FORM_strp");
 }
 
 /* Return pointer to string at .debug_str offset as read from BUF.
@@ -18830,7 +18791,7 @@ read_indirect_string (struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *abfd,
 {
   LONGEST str_offset = cu_header->read_offset (abfd, buf, bytes_read_ptr);
 
-  return read_indirect_string_at_offset (dwarf2_per_objfile, abfd, str_offset);
+  return read_indirect_string_at_offset (dwarf2_per_objfile, str_offset);
 }
 
 /* Return pointer to string at .debug_line_str offset as read from BUF.
@@ -18845,8 +18806,9 @@ read_indirect_line_string (struct dwarf2_per_objfile *dwarf2_per_objfile,
 {
   LONGEST str_offset = cu_header->read_offset (abfd, buf, bytes_read_ptr);
 
-  return read_indirect_line_string_at_offset (dwarf2_per_objfile, abfd,
-					      str_offset);
+  return dwarf2_per_objfile->line_str.read_string (dwarf2_per_objfile->objfile,
+						   str_offset,
+						   "DW_FORM_line_strp");
 }
 
 /* Given index ADDR_INDEX in .debug_addr, fetch the value.
@@ -23549,7 +23511,7 @@ dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
 		  }
 		else
 		  body = read_indirect_string_at_offset (dwarf2_per_objfile,
-							 abfd, str_offset);
+							 str_offset);
 	      }
 
 	    is_define = (macinfo_type == DW_MACRO_define
diff --git a/gdb/dwarf2/section.c b/gdb/dwarf2/section.c
index 9714368a5d2..776617911a2 100644
--- a/gdb/dwarf2/section.c
+++ b/gdb/dwarf2/section.c
@@ -187,3 +187,20 @@ dwarf2_section_info::read (struct objfile *objfile)
 	     bfd_section_name (sectp), bfd_get_filename (abfd));
     }
 }
+
+const char *
+dwarf2_section_info::read_string (struct objfile *objfile, LONGEST str_offset,
+				  const char *form_name)
+{
+  read (objfile);
+  if (buffer == NULL)
+    error (_("%s used without %s section [in module %s]"),
+	   form_name, get_name (), get_file_name ());
+  if (str_offset >= size)
+    error (_("%s pointing outside of %s section [in module %s]"),
+	   form_name, get_name (), get_file_name ());
+  gdb_assert (HOST_CHAR_BIT == 8);
+  if (buffer[str_offset] == '\0')
+    return NULL;
+  return (const char *) (buffer + str_offset);
+}
diff --git a/gdb/dwarf2/section.h b/gdb/dwarf2/section.h
index 555efecacd6..02f42df78c6 100644
--- a/gdb/dwarf2/section.h
+++ b/gdb/dwarf2/section.h
@@ -98,6 +98,11 @@ struct dwarf2_section_info
      buffer.  */
   void overflow_complaint () const;
 
+  /* Return pointer to string in this section at offset STR_OFFSET
+     with error reporting string FORM_NAME.  */
+  const char *read_string (struct objfile *objfile, LONGEST str_offset,
+			   const char *form_name);
+
   union
   {
     /* If this is a real section, the bfd section.  */
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 08/22] Move code to new file dwarf2/macro.c
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (6 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 07/22] Add dwarf2_section_info::read_string method Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 09/22] Make some line_header methods const Tom Tromey
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This moves some more code out of dwarf2/read.c, introducing new files
dwarf2/macro.c and dwarf2/macro.h.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.c (dwarf2_macro_malformed_definition_complaint)
	(macro_start_file, consume_improper_spaces)
	(parse_macro_definition, skip_form_bytes, skip_unknown_opcode)
	(dwarf_parse_macro_header, dwarf_decode_macro_bytes)
	(dwarf_decode_macros): Move to macro.c.
	* dwarf2/macro.c: New file.
	* dwarf2/macro.h: New file.
	* Makefile.in (COMMON_SFILES): Add dwarf2/macro.c.
---
 gdb/ChangeLog      |  11 +
 gdb/Makefile.in    |   1 +
 gdb/dwarf2/macro.c | 867 +++++++++++++++++++++++++++++++++++++++++++++
 gdb/dwarf2/macro.h |  33 ++
 gdb/dwarf2/read.c  | 832 +------------------------------------------
 5 files changed, 914 insertions(+), 830 deletions(-)
 create mode 100644 gdb/dwarf2/macro.c
 create mode 100644 gdb/dwarf2/macro.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index c9450ce7b52..f66affd3e5f 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1013,6 +1013,7 @@ COMMON_SFILES = \
 	dwarf2/leb.c \
 	dwarf2/line-header.c \
 	dwarf2/loc.c \
+	dwarf2/macro.c \
 	dwarf2/read.c \
 	dwarf2/section.c \
 	eval.c \
diff --git a/gdb/dwarf2/macro.c b/gdb/dwarf2/macro.c
new file mode 100644
index 00000000000..1f1cca858c1
--- /dev/null
+++ b/gdb/dwarf2/macro.c
@@ -0,0 +1,867 @@
+/* Read DWARF macro information
+
+   Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+   Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
+   Inc.  with support from Florida State University (under contract
+   with the Ada Joint Program Office), and Silicon Graphics, Inc.
+   Initial contribution by Brent Benson, Harris Computer Systems, Inc.,
+   based on Fred Fish's (Cygnus Support) implementation of DWARF 1
+   support.
+
+   This file is part of GDB.
+
+   This program 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.
+
+   This program 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/>.  */
+
+#include "defs.h"
+#include "dwarf2/read.h"
+#include "dwarf2/leb.h"
+#include "dwarf2/expr.h"
+#include "dwarf2/line-header.h"
+#include "dwarf2/section.h"
+#include "dwarf2/macro.h"
+#include "dwarf2/dwz.h"
+#include "buildsym.h"
+#include "macrotab.h"
+#include "complaints.h"
+
+static void
+dwarf2_macro_malformed_definition_complaint (const char *arg1)
+{
+  complaint (_("macro debug info contains a "
+	       "malformed macro definition:\n`%s'"),
+	     arg1);
+}
+
+static struct macro_source_file *
+macro_start_file (buildsym_compunit *builder,
+		  int file, int line,
+                  struct macro_source_file *current_file,
+                  struct line_header *lh)
+{
+  /* File name relative to the compilation directory of this source file.  */
+  gdb::unique_xmalloc_ptr<char> file_name = lh->file_file_name (file);
+
+  if (! current_file)
+    {
+      /* Note: We don't create a macro table for this compilation unit
+	 at all until we actually get a filename.  */
+      struct macro_table *macro_table = builder->get_macro_table ();
+
+      /* If we have no current file, then this must be the start_file
+	 directive for the compilation unit's main source file.  */
+      current_file = macro_set_main (macro_table, file_name.get ());
+      macro_define_special (macro_table);
+    }
+  else
+    current_file = macro_include (current_file, line, file_name.get ());
+
+  return current_file;
+}
+
+static const char *
+consume_improper_spaces (const char *p, const char *body)
+{
+  if (*p == ' ')
+    {
+      complaint (_("macro definition contains spaces "
+		   "in formal argument list:\n`%s'"),
+		 body);
+
+      while (*p == ' ')
+        p++;
+    }
+
+  return p;
+}
+
+
+static void
+parse_macro_definition (struct macro_source_file *file, int line,
+                        const char *body)
+{
+  const char *p;
+
+  /* The body string takes one of two forms.  For object-like macro
+     definitions, it should be:
+
+        <macro name> " " <definition>
+
+     For function-like macro definitions, it should be:
+
+        <macro name> "() " <definition>
+     or
+        <macro name> "(" <arg name> ( "," <arg name> ) * ") " <definition>
+
+     Spaces may appear only where explicitly indicated, and in the
+     <definition>.
+
+     The Dwarf 2 spec says that an object-like macro's name is always
+     followed by a space, but versions of GCC around March 2002 omit
+     the space when the macro's definition is the empty string.
+
+     The Dwarf 2 spec says that there should be no spaces between the
+     formal arguments in a function-like macro's formal argument list,
+     but versions of GCC around March 2002 include spaces after the
+     commas.  */
+
+
+  /* Find the extent of the macro name.  The macro name is terminated
+     by either a space or null character (for an object-like macro) or
+     an opening paren (for a function-like macro).  */
+  for (p = body; *p; p++)
+    if (*p == ' ' || *p == '(')
+      break;
+
+  if (*p == ' ' || *p == '\0')
+    {
+      /* It's an object-like macro.  */
+      int name_len = p - body;
+      std::string name (body, name_len);
+      const char *replacement;
+
+      if (*p == ' ')
+        replacement = body + name_len + 1;
+      else
+        {
+	  dwarf2_macro_malformed_definition_complaint (body);
+          replacement = body + name_len;
+        }
+
+      macro_define_object (file, line, name.c_str (), replacement);
+    }
+  else if (*p == '(')
+    {
+      /* It's a function-like macro.  */
+      std::string name (body, p - body);
+      int argc = 0;
+      int argv_size = 1;
+      char **argv = XNEWVEC (char *, argv_size);
+
+      p++;
+
+      p = consume_improper_spaces (p, body);
+
+      /* Parse the formal argument list.  */
+      while (*p && *p != ')')
+        {
+          /* Find the extent of the current argument name.  */
+          const char *arg_start = p;
+
+          while (*p && *p != ',' && *p != ')' && *p != ' ')
+            p++;
+
+          if (! *p || p == arg_start)
+	    dwarf2_macro_malformed_definition_complaint (body);
+          else
+            {
+              /* Make sure argv has room for the new argument.  */
+              if (argc >= argv_size)
+                {
+                  argv_size *= 2;
+                  argv = XRESIZEVEC (char *, argv, argv_size);
+                }
+
+              argv[argc++] = savestring (arg_start, p - arg_start);
+            }
+
+          p = consume_improper_spaces (p, body);
+
+          /* Consume the comma, if present.  */
+          if (*p == ',')
+            {
+              p++;
+
+              p = consume_improper_spaces (p, body);
+            }
+        }
+
+      if (*p == ')')
+        {
+          p++;
+
+          if (*p == ' ')
+            /* Perfectly formed definition, no complaints.  */
+            macro_define_function (file, line, name.c_str (),
+                                   argc, (const char **) argv,
+                                   p + 1);
+          else if (*p == '\0')
+            {
+              /* Complain, but do define it.  */
+	      dwarf2_macro_malformed_definition_complaint (body);
+              macro_define_function (file, line, name.c_str (),
+                                     argc, (const char **) argv,
+                                     p);
+            }
+          else
+            /* Just complain.  */
+	    dwarf2_macro_malformed_definition_complaint (body);
+        }
+      else
+        /* Just complain.  */
+	dwarf2_macro_malformed_definition_complaint (body);
+
+      {
+        int i;
+
+        for (i = 0; i < argc; i++)
+          xfree (argv[i]);
+      }
+      xfree (argv);
+    }
+  else
+    dwarf2_macro_malformed_definition_complaint (body);
+}
+
+/* Skip some bytes from BYTES according to the form given in FORM.
+   Returns the new pointer.  */
+
+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)
+{
+  unsigned int bytes_read;
+
+  switch (form)
+    {
+    case DW_FORM_data1:
+    case DW_FORM_flag:
+      ++bytes;
+      break;
+
+    case DW_FORM_data2:
+      bytes += 2;
+      break;
+
+    case DW_FORM_data4:
+      bytes += 4;
+      break;
+
+    case DW_FORM_data8:
+      bytes += 8;
+      break;
+
+    case DW_FORM_data16:
+      bytes += 16;
+      break;
+
+    case DW_FORM_string:
+      read_direct_string (abfd, bytes, &bytes_read);
+      bytes += bytes_read;
+      break;
+
+    case DW_FORM_sec_offset:
+    case DW_FORM_strp:
+    case DW_FORM_GNU_strp_alt:
+      bytes += offset_size;
+      break;
+
+    case DW_FORM_block:
+      bytes += read_unsigned_leb128 (abfd, bytes, &bytes_read);
+      bytes += bytes_read;
+      break;
+
+    case DW_FORM_block1:
+      bytes += 1 + read_1_byte (abfd, bytes);
+      break;
+    case DW_FORM_block2:
+      bytes += 2 + read_2_bytes (abfd, bytes);
+      break;
+    case DW_FORM_block4:
+      bytes += 4 + read_4_bytes (abfd, bytes);
+      break;
+
+    case DW_FORM_addrx:
+    case DW_FORM_sdata:
+    case DW_FORM_strx:
+    case DW_FORM_udata:
+    case DW_FORM_GNU_addr_index:
+    case DW_FORM_GNU_str_index:
+      bytes = gdb_skip_leb128 (bytes, buffer_end);
+      if (bytes == NULL)
+	{
+	  section->overflow_complaint ();
+	  return NULL;
+	}
+      break;
+
+    case DW_FORM_implicit_const:
+      break;
+
+    default:
+      {
+	complaint (_("invalid form 0x%x in `%s'"),
+		   form, section->get_name ());
+	return NULL;
+      }
+    }
+
+  return bytes;
+}
+
+/* A helper for dwarf_decode_macros that handles skipping an unknown
+   opcode.  Returns an updated pointer to the macro data buffer; or,
+   on error, issues a complaint and returns NULL.  */
+
+static const gdb_byte *
+skip_unknown_opcode (unsigned int opcode,
+		     const gdb_byte **opcode_definitions,
+		     const gdb_byte *mac_ptr, const gdb_byte *mac_end,
+		     bfd *abfd,
+		     unsigned int offset_size,
+		     struct dwarf2_section_info *section)
+{
+  unsigned int bytes_read, i;
+  unsigned long arg;
+  const gdb_byte *defn;
+
+  if (opcode_definitions[opcode] == NULL)
+    {
+      complaint (_("unrecognized DW_MACFINO opcode 0x%x"),
+		 opcode);
+      return NULL;
+    }
+
+  defn = opcode_definitions[opcode];
+  arg = read_unsigned_leb128 (abfd, defn, &bytes_read);
+  defn += bytes_read;
+
+  for (i = 0; i < arg; ++i)
+    {
+      mac_ptr = skip_form_bytes (abfd, mac_ptr, mac_end,
+				 (enum dwarf_form) defn[i], offset_size,
+				 section);
+      if (mac_ptr == NULL)
+	{
+	  /* skip_form_bytes already issued the complaint.  */
+	  return NULL;
+	}
+    }
+
+  return mac_ptr;
+}
+
+/* A helper function which parses the header of a macro section.
+   If the macro section is the extended (for now called "GNU") type,
+   then this updates *OFFSET_SIZE.  Returns a pointer to just after
+   the header, or issues a complaint and returns NULL on error.  */
+
+static const gdb_byte *
+dwarf_parse_macro_header (const gdb_byte **opcode_definitions,
+			  bfd *abfd,
+			  const gdb_byte *mac_ptr,
+			  unsigned int *offset_size,
+			  int section_is_gnu)
+{
+  memset (opcode_definitions, 0, 256 * sizeof (gdb_byte *));
+
+  if (section_is_gnu)
+    {
+      unsigned int version, flags;
+
+      version = read_2_bytes (abfd, mac_ptr);
+      if (version != 4 && version != 5)
+	{
+	  complaint (_("unrecognized version `%d' in .debug_macro section"),
+		     version);
+	  return NULL;
+	}
+      mac_ptr += 2;
+
+      flags = read_1_byte (abfd, mac_ptr);
+      ++mac_ptr;
+      *offset_size = (flags & 1) ? 8 : 4;
+
+      if ((flags & 2) != 0)
+	/* We don't need the line table offset.  */
+	mac_ptr += *offset_size;
+
+      /* Vendor opcode descriptions.  */
+      if ((flags & 4) != 0)
+	{
+	  unsigned int i, count;
+
+	  count = read_1_byte (abfd, mac_ptr);
+	  ++mac_ptr;
+	  for (i = 0; i < count; ++i)
+	    {
+	      unsigned int opcode, bytes_read;
+	      unsigned long arg;
+
+	      opcode = read_1_byte (abfd, mac_ptr);
+	      ++mac_ptr;
+	      opcode_definitions[opcode] = mac_ptr;
+	      arg = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+	      mac_ptr += bytes_read;
+	      mac_ptr += arg;
+	    }
+	}
+    }
+
+  return mac_ptr;
+}
+
+/* A helper for dwarf_decode_macros that handles the GNU extensions,
+   including DW_MACRO_import.  */
+
+static void
+dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
+			  buildsym_compunit *builder,
+			  bfd *abfd,
+			  const gdb_byte *mac_ptr, const gdb_byte *mac_end,
+			  struct macro_source_file *current_file,
+			  struct line_header *lh,
+			  struct dwarf2_section_info *section,
+			  int section_is_gnu, int section_is_dwz,
+			  unsigned int offset_size,
+			  htab_t include_hash)
+{
+  struct objfile *objfile = dwarf2_per_objfile->objfile;
+  enum dwarf_macro_record_type macinfo_type;
+  int at_commandline;
+  const gdb_byte *opcode_definitions[256];
+
+  mac_ptr = dwarf_parse_macro_header (opcode_definitions, abfd, mac_ptr,
+				      &offset_size, section_is_gnu);
+  if (mac_ptr == NULL)
+    {
+      /* We already issued a complaint.  */
+      return;
+    }
+
+  /* Determines if GDB is still before first DW_MACINFO_start_file.  If true
+     GDB is still reading the definitions from command line.  First
+     DW_MACINFO_start_file will need to be ignored as it was already executed
+     to create CURRENT_FILE for the main source holding also the command line
+     definitions.  On first met DW_MACINFO_start_file this flag is reset to
+     normally execute all the remaining DW_MACINFO_start_file macinfos.  */
+
+  at_commandline = 1;
+
+  do
+    {
+      /* Do we at least have room for a macinfo type byte?  */
+      if (mac_ptr >= mac_end)
+	{
+	  section->overflow_complaint ();
+	  break;
+	}
+
+      macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr);
+      mac_ptr++;
+
+      /* Note that we rely on the fact that the corresponding GNU and
+	 DWARF constants are the same.  */
+      DIAGNOSTIC_PUSH
+      DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
+      switch (macinfo_type)
+	{
+	  /* A zero macinfo type indicates the end of the macro
+	     information.  */
+	case 0:
+	  break;
+
+        case DW_MACRO_define:
+        case DW_MACRO_undef:
+	case DW_MACRO_define_strp:
+	case DW_MACRO_undef_strp:
+	case DW_MACRO_define_sup:
+	case DW_MACRO_undef_sup:
+          {
+            unsigned int bytes_read;
+            int line;
+            const char *body;
+	    int is_define;
+
+	    line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+	    mac_ptr += bytes_read;
+
+	    if (macinfo_type == DW_MACRO_define
+		|| macinfo_type == DW_MACRO_undef)
+	      {
+		body = read_direct_string (abfd, mac_ptr, &bytes_read);
+		mac_ptr += bytes_read;
+	      }
+	    else
+	      {
+		LONGEST str_offset;
+
+		str_offset = read_offset (abfd, mac_ptr, offset_size);
+		mac_ptr += offset_size;
+
+		if (macinfo_type == DW_MACRO_define_sup
+		    || macinfo_type == DW_MACRO_undef_sup
+		    || section_is_dwz)
+		  {
+		    struct dwz_file *dwz
+		      = dwarf2_get_dwz_file (dwarf2_per_objfile);
+
+		    body = dwz->read_string (objfile, str_offset);
+		  }
+		else
+		  body = (dwarf2_per_objfile->str.read_string
+			  (dwarf2_per_objfile->objfile,
+			   str_offset, "DW_FORM_strp"));
+	      }
+
+	    is_define = (macinfo_type == DW_MACRO_define
+			 || macinfo_type == DW_MACRO_define_strp
+			 || macinfo_type == DW_MACRO_define_sup);
+            if (! current_file)
+	      {
+		/* DWARF violation as no main source is present.  */
+		complaint (_("debug info with no main source gives macro %s "
+			     "on line %d: %s"),
+			   is_define ? _("definition") : _("undefinition"),
+			   line, body);
+		break;
+	      }
+	    if ((line == 0 && !at_commandline)
+		|| (line != 0 && at_commandline))
+	      complaint (_("debug info gives %s macro %s with %s line %d: %s"),
+			 at_commandline ? _("command-line") : _("in-file"),
+			 is_define ? _("definition") : _("undefinition"),
+			 line == 0 ? _("zero") : _("non-zero"), line, body);
+
+	    if (body == NULL)
+	      {
+		/* Fedora's rpm-build's "debugedit" binary
+		   corrupted .debug_macro sections.
+
+		   For more info, see
+		   https://bugzilla.redhat.com/show_bug.cgi?id=1708786 */
+		complaint (_("debug info gives %s invalid macro %s "
+			     "without body (corrupted?) at line %d "
+			     "on file %s"),
+			   at_commandline ? _("command-line") : _("in-file"),
+			   is_define ? _("definition") : _("undefinition"),
+			   line, current_file->filename);
+	      }
+	    else if (is_define)
+	      parse_macro_definition (current_file, line, body);
+	    else
+	      {
+		gdb_assert (macinfo_type == DW_MACRO_undef
+			    || macinfo_type == DW_MACRO_undef_strp
+			    || macinfo_type == DW_MACRO_undef_sup);
+		macro_undef (current_file, line, body);
+	      }
+          }
+          break;
+
+        case DW_MACRO_start_file:
+          {
+            unsigned int bytes_read;
+            int line, file;
+
+            line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+            mac_ptr += bytes_read;
+            file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+            mac_ptr += bytes_read;
+
+	    if ((line == 0 && !at_commandline)
+		|| (line != 0 && at_commandline))
+	      complaint (_("debug info gives source %d included "
+			   "from %s at %s line %d"),
+			 file, at_commandline ? _("command-line") : _("file"),
+			 line == 0 ? _("zero") : _("non-zero"), line);
+
+	    if (at_commandline)
+	      {
+		/* This DW_MACRO_start_file was executed in the
+		   pass one.  */
+		at_commandline = 0;
+	      }
+	    else
+	      current_file = macro_start_file (builder, file, line,
+					       current_file, lh);
+          }
+          break;
+
+        case DW_MACRO_end_file:
+          if (! current_file)
+	    complaint (_("macro debug info has an unmatched "
+			 "`close_file' directive"));
+          else
+            {
+              current_file = current_file->included_by;
+              if (! current_file)
+                {
+                  enum dwarf_macro_record_type next_type;
+
+                  /* GCC circa March 2002 doesn't produce the zero
+                     type byte marking the end of the compilation
+                     unit.  Complain if it's not there, but exit no
+                     matter what.  */
+
+                  /* Do we at least have room for a macinfo type byte?  */
+                  if (mac_ptr >= mac_end)
+                    {
+		      section->overflow_complaint ();
+                      return;
+                    }
+
+                  /* We don't increment mac_ptr here, so this is just
+                     a look-ahead.  */
+                  next_type
+		    = (enum dwarf_macro_record_type) read_1_byte (abfd,
+								  mac_ptr);
+                  if (next_type != 0)
+		    complaint (_("no terminating 0-type entry for "
+				 "macros in `.debug_macinfo' section"));
+
+                  return;
+                }
+            }
+          break;
+
+	case DW_MACRO_import:
+	case DW_MACRO_import_sup:
+	  {
+	    LONGEST offset;
+	    void **slot;
+	    bfd *include_bfd = abfd;
+	    struct dwarf2_section_info *include_section = section;
+	    const gdb_byte *include_mac_end = mac_end;
+	    int is_dwz = section_is_dwz;
+	    const gdb_byte *new_mac_ptr;
+
+	    offset = read_offset (abfd, mac_ptr, offset_size);
+	    mac_ptr += offset_size;
+
+	    if (macinfo_type == DW_MACRO_import_sup)
+	      {
+		struct dwz_file *dwz = dwarf2_get_dwz_file (dwarf2_per_objfile);
+
+		dwz->macro.read (objfile);
+
+		include_section = &dwz->macro;
+		include_bfd = include_section->get_bfd_owner ();
+		include_mac_end = dwz->macro.buffer + dwz->macro.size;
+		is_dwz = 1;
+	      }
+
+	    new_mac_ptr = include_section->buffer + offset;
+	    slot = htab_find_slot (include_hash, new_mac_ptr, INSERT);
+
+	    if (*slot != NULL)
+	      {
+		/* This has actually happened; see
+		   http://sourceware.org/bugzilla/show_bug.cgi?id=13568.  */
+		complaint (_("recursive DW_MACRO_import in "
+			     ".debug_macro section"));
+	      }
+	    else
+	      {
+		*slot = (void *) new_mac_ptr;
+
+		dwarf_decode_macro_bytes (dwarf2_per_objfile, builder,
+					  include_bfd, new_mac_ptr,
+					  include_mac_end, current_file, lh,
+					  section, section_is_gnu, is_dwz,
+					  offset_size, include_hash);
+
+		htab_remove_elt (include_hash, (void *) new_mac_ptr);
+	      }
+	  }
+	  break;
+
+        case DW_MACINFO_vendor_ext:
+	  if (!section_is_gnu)
+	    {
+	      unsigned int bytes_read;
+
+	      /* This reads the constant, but since we don't recognize
+		 any vendor extensions, we ignore it.  */
+	      read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+	      mac_ptr += bytes_read;
+	      read_direct_string (abfd, mac_ptr, &bytes_read);
+	      mac_ptr += bytes_read;
+
+	      /* We don't recognize any vendor extensions.  */
+	      break;
+	    }
+	  /* FALLTHROUGH */
+
+	default:
+	  mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
+					 mac_ptr, mac_end, abfd, offset_size,
+					 section);
+	  if (mac_ptr == NULL)
+	    return;
+	  break;
+        }
+      DIAGNOSTIC_POP
+    } while (macinfo_type != 0);
+}
+
+void
+dwarf_decode_macros (struct dwarf2_per_objfile *dwarf2_per_objfile,
+		     buildsym_compunit *builder, dwarf2_section_info *section,
+		     struct line_header *lh, unsigned int offset_size,
+		     unsigned int offset, int section_is_gnu)
+{
+  bfd *abfd;
+  const gdb_byte *mac_ptr, *mac_end;
+  struct macro_source_file *current_file = 0;
+  enum dwarf_macro_record_type macinfo_type;
+  const gdb_byte *opcode_definitions[256];
+  void **slot;
+
+  abfd = section->get_bfd_owner ();
+
+  /* First pass: Find the name of the base filename.
+     This filename is needed in order to process all macros whose definition
+     (or undefinition) comes from the command line.  These macros are defined
+     before the first DW_MACINFO_start_file entry, and yet still need to be
+     associated to the base file.
+
+     To determine the base file name, we scan the macro definitions until we
+     reach the first DW_MACINFO_start_file entry.  We then initialize
+     CURRENT_FILE accordingly so that any macro definition found before the
+     first DW_MACINFO_start_file can still be associated to the base file.  */
+
+  mac_ptr = section->buffer + offset;
+  mac_end = section->buffer + section->size;
+
+  mac_ptr = dwarf_parse_macro_header (opcode_definitions, abfd, mac_ptr,
+				      &offset_size, section_is_gnu);
+  if (mac_ptr == NULL)
+    {
+      /* We already issued a complaint.  */
+      return;
+    }
+
+  do
+    {
+      /* Do we at least have room for a macinfo type byte?  */
+      if (mac_ptr >= mac_end)
+        {
+	  /* Complaint is printed during the second pass as GDB will probably
+	     stop the first pass earlier upon finding
+	     DW_MACINFO_start_file.  */
+	  break;
+        }
+
+      macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr);
+      mac_ptr++;
+
+      /* Note that we rely on the fact that the corresponding GNU and
+	 DWARF constants are the same.  */
+      DIAGNOSTIC_PUSH
+      DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
+      switch (macinfo_type)
+        {
+          /* A zero macinfo type indicates the end of the macro
+             information.  */
+        case 0:
+	  break;
+
+	case DW_MACRO_define:
+	case DW_MACRO_undef:
+	  /* Only skip the data by MAC_PTR.  */
+	  {
+	    unsigned int bytes_read;
+
+	    read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+	    mac_ptr += bytes_read;
+	    read_direct_string (abfd, mac_ptr, &bytes_read);
+	    mac_ptr += bytes_read;
+	  }
+	  break;
+
+	case DW_MACRO_start_file:
+	  {
+	    unsigned int bytes_read;
+	    int line, file;
+
+	    line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+	    mac_ptr += bytes_read;
+	    file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+	    mac_ptr += bytes_read;
+
+	    current_file = macro_start_file (builder, file, line,
+					     current_file, lh);
+	  }
+	  break;
+
+	case DW_MACRO_end_file:
+	  /* No data to skip by MAC_PTR.  */
+	  break;
+
+	case DW_MACRO_define_strp:
+	case DW_MACRO_undef_strp:
+	case DW_MACRO_define_sup:
+	case DW_MACRO_undef_sup:
+	  {
+	    unsigned int bytes_read;
+
+	    read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+	    mac_ptr += bytes_read;
+	    mac_ptr += offset_size;
+	  }
+	  break;
+
+	case DW_MACRO_import:
+	case DW_MACRO_import_sup:
+	  /* Note that, according to the spec, a transparent include
+	     chain cannot call DW_MACRO_start_file.  So, we can just
+	     skip this opcode.  */
+	  mac_ptr += offset_size;
+	  break;
+
+	case DW_MACINFO_vendor_ext:
+	  /* Only skip the data by MAC_PTR.  */
+	  if (!section_is_gnu)
+	    {
+	      unsigned int bytes_read;
+
+	      read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+	      mac_ptr += bytes_read;
+	      read_direct_string (abfd, mac_ptr, &bytes_read);
+	      mac_ptr += bytes_read;
+	    }
+	  /* FALLTHROUGH */
+
+	default:
+	  mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
+					 mac_ptr, mac_end, abfd, offset_size,
+					 section);
+	  if (mac_ptr == NULL)
+	    return;
+	  break;
+	}
+      DIAGNOSTIC_POP
+    } while (macinfo_type != 0 && current_file == NULL);
+
+  /* Second pass: Process all entries.
+
+     Use the AT_COMMAND_LINE flag to determine whether we are still processing
+     command-line macro definitions/undefinitions.  This flag is unset when we
+     reach the first DW_MACINFO_start_file entry.  */
+
+  htab_up include_hash (htab_create_alloc (1, htab_hash_pointer,
+					   htab_eq_pointer,
+					   NULL, xcalloc, xfree));
+  mac_ptr = section->buffer + offset;
+  slot = htab_find_slot (include_hash.get (), mac_ptr, INSERT);
+  *slot = (void *) mac_ptr;
+  dwarf_decode_macro_bytes (dwarf2_per_objfile, builder,
+			    abfd, mac_ptr, mac_end,
+			    current_file, lh, section,
+			    section_is_gnu, 0, offset_size,
+			    include_hash.get ());
+}
diff --git a/gdb/dwarf2/macro.h b/gdb/dwarf2/macro.h
new file mode 100644
index 00000000000..3937c550088
--- /dev/null
+++ b/gdb/dwarf2/macro.h
@@ -0,0 +1,33 @@
+/* DWARF macro support for GDB.
+
+   Copyright (C) 2003-2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program 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.
+
+   This program 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/>.  */
+
+#ifndef GDB_DWARF2_MACRO_H
+#define GDB_DWARF2_MACRO_H
+
+struct buildsym_compunit;
+
+extern void dwarf_decode_macros (struct dwarf2_per_objfile *dwarf2_per_objfile,
+				 buildsym_compunit *builder,
+				 dwarf2_section_info *section,
+				 struct line_header *lh,
+				 unsigned int offset_size,
+				 unsigned int offset,
+				 int section_is_gnu);
+
+#endif /* GDB_DWARF2_MACRO_H */
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 75d028d95b1..ca90418e45e 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -38,6 +38,7 @@
 #include "dwarf2/leb.h"
 #include "dwarf2/line-header.h"
 #include "dwarf2/dwz.h"
+#include "dwarf2/macro.h"
 #include "bfd.h"
 #include "elf-bfd.h"
 #include "symtab.h"
@@ -48,7 +49,6 @@
 #include "demangle.h"
 #include "gdb-demangle.h"
 #include "filenames.h"	/* for DOSish file names */
-#include "macrotab.h"
 #include "language.h"
 #include "complaints.h"
 #include "dwarf2/expr.h"
@@ -1710,14 +1710,6 @@ dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2,
 	     arg1, arg2, arg3);
 }
 
-static void
-dwarf2_macro_malformed_definition_complaint (const char *arg1)
-{
-  complaint (_("macro debug info contains a "
-	       "malformed macro definition:\n`%s'"),
-	     arg1);
-}
-
 static void
 dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
 {
@@ -23040,828 +23032,8 @@ dwarf_alloc_die (struct dwarf2_cu *cu, int num_attrs)
 }
 
 \f
-/* Macro support.  */
-
-static struct macro_source_file *
-macro_start_file (buildsym_compunit *builder,
-		  int file, int line,
-                  struct macro_source_file *current_file,
-                  struct line_header *lh)
-{
-  /* File name relative to the compilation directory of this source file.  */
-  gdb::unique_xmalloc_ptr<char> file_name = lh->file_file_name (file);
-
-  if (! current_file)
-    {
-      /* Note: We don't create a macro table for this compilation unit
-	 at all until we actually get a filename.  */
-      struct macro_table *macro_table = builder->get_macro_table ();
-
-      /* If we have no current file, then this must be the start_file
-	 directive for the compilation unit's main source file.  */
-      current_file = macro_set_main (macro_table, file_name.get ());
-      macro_define_special (macro_table);
-    }
-  else
-    current_file = macro_include (current_file, line, file_name.get ());
-
-  return current_file;
-}
-
-static const char *
-consume_improper_spaces (const char *p, const char *body)
-{
-  if (*p == ' ')
-    {
-      complaint (_("macro definition contains spaces "
-		   "in formal argument list:\n`%s'"),
-		 body);
-
-      while (*p == ' ')
-        p++;
-    }
-
-  return p;
-}
-
-
-static void
-parse_macro_definition (struct macro_source_file *file, int line,
-                        const char *body)
-{
-  const char *p;
-
-  /* The body string takes one of two forms.  For object-like macro
-     definitions, it should be:
-
-        <macro name> " " <definition>
-
-     For function-like macro definitions, it should be:
-
-        <macro name> "() " <definition>
-     or
-        <macro name> "(" <arg name> ( "," <arg name> ) * ") " <definition>
-
-     Spaces may appear only where explicitly indicated, and in the
-     <definition>.
-
-     The Dwarf 2 spec says that an object-like macro's name is always
-     followed by a space, but versions of GCC around March 2002 omit
-     the space when the macro's definition is the empty string.
-
-     The Dwarf 2 spec says that there should be no spaces between the
-     formal arguments in a function-like macro's formal argument list,
-     but versions of GCC around March 2002 include spaces after the
-     commas.  */
-
-
-  /* Find the extent of the macro name.  The macro name is terminated
-     by either a space or null character (for an object-like macro) or
-     an opening paren (for a function-like macro).  */
-  for (p = body; *p; p++)
-    if (*p == ' ' || *p == '(')
-      break;
-
-  if (*p == ' ' || *p == '\0')
-    {
-      /* It's an object-like macro.  */
-      int name_len = p - body;
-      std::string name (body, name_len);
-      const char *replacement;
-
-      if (*p == ' ')
-        replacement = body + name_len + 1;
-      else
-        {
-	  dwarf2_macro_malformed_definition_complaint (body);
-          replacement = body + name_len;
-        }
-
-      macro_define_object (file, line, name.c_str (), replacement);
-    }
-  else if (*p == '(')
-    {
-      /* It's a function-like macro.  */
-      std::string name (body, p - body);
-      int argc = 0;
-      int argv_size = 1;
-      char **argv = XNEWVEC (char *, argv_size);
-
-      p++;
-
-      p = consume_improper_spaces (p, body);
-
-      /* Parse the formal argument list.  */
-      while (*p && *p != ')')
-        {
-          /* Find the extent of the current argument name.  */
-          const char *arg_start = p;
-
-          while (*p && *p != ',' && *p != ')' && *p != ' ')
-            p++;
-
-          if (! *p || p == arg_start)
-	    dwarf2_macro_malformed_definition_complaint (body);
-          else
-            {
-              /* Make sure argv has room for the new argument.  */
-              if (argc >= argv_size)
-                {
-                  argv_size *= 2;
-                  argv = XRESIZEVEC (char *, argv, argv_size);
-                }
-
-              argv[argc++] = savestring (arg_start, p - arg_start);
-            }
-
-          p = consume_improper_spaces (p, body);
-
-          /* Consume the comma, if present.  */
-          if (*p == ',')
-            {
-              p++;
-
-              p = consume_improper_spaces (p, body);
-            }
-        }
-
-      if (*p == ')')
-        {
-          p++;
-
-          if (*p == ' ')
-            /* Perfectly formed definition, no complaints.  */
-            macro_define_function (file, line, name.c_str (),
-                                   argc, (const char **) argv,
-                                   p + 1);
-          else if (*p == '\0')
-            {
-              /* Complain, but do define it.  */
-	      dwarf2_macro_malformed_definition_complaint (body);
-              macro_define_function (file, line, name.c_str (),
-                                     argc, (const char **) argv,
-                                     p);
-            }
-          else
-            /* Just complain.  */
-	    dwarf2_macro_malformed_definition_complaint (body);
-        }
-      else
-        /* Just complain.  */
-	dwarf2_macro_malformed_definition_complaint (body);
-
-      {
-        int i;
-
-        for (i = 0; i < argc; i++)
-          xfree (argv[i]);
-      }
-      xfree (argv);
-    }
-  else
-    dwarf2_macro_malformed_definition_complaint (body);
-}
-
-/* Skip some bytes from BYTES according to the form given in FORM.
-   Returns the new pointer.  */
-
-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)
-{
-  unsigned int bytes_read;
-
-  switch (form)
-    {
-    case DW_FORM_data1:
-    case DW_FORM_flag:
-      ++bytes;
-      break;
-
-    case DW_FORM_data2:
-      bytes += 2;
-      break;
-
-    case DW_FORM_data4:
-      bytes += 4;
-      break;
-
-    case DW_FORM_data8:
-      bytes += 8;
-      break;
-
-    case DW_FORM_data16:
-      bytes += 16;
-      break;
-
-    case DW_FORM_string:
-      read_direct_string (abfd, bytes, &bytes_read);
-      bytes += bytes_read;
-      break;
-
-    case DW_FORM_sec_offset:
-    case DW_FORM_strp:
-    case DW_FORM_GNU_strp_alt:
-      bytes += offset_size;
-      break;
-
-    case DW_FORM_block:
-      bytes += read_unsigned_leb128 (abfd, bytes, &bytes_read);
-      bytes += bytes_read;
-      break;
-
-    case DW_FORM_block1:
-      bytes += 1 + read_1_byte (abfd, bytes);
-      break;
-    case DW_FORM_block2:
-      bytes += 2 + read_2_bytes (abfd, bytes);
-      break;
-    case DW_FORM_block4:
-      bytes += 4 + read_4_bytes (abfd, bytes);
-      break;
-
-    case DW_FORM_addrx:
-    case DW_FORM_sdata:
-    case DW_FORM_strx:
-    case DW_FORM_udata:
-    case DW_FORM_GNU_addr_index:
-    case DW_FORM_GNU_str_index:
-      bytes = gdb_skip_leb128 (bytes, buffer_end);
-      if (bytes == NULL)
-	{
-	  section->overflow_complaint ();
-	  return NULL;
-	}
-      break;
-
-    case DW_FORM_implicit_const:
-      break;
-
-    default:
-      {
-	complaint (_("invalid form 0x%x in `%s'"),
-		   form, section->get_name ());
-	return NULL;
-      }
-    }
-
-  return bytes;
-}
-
-/* A helper for dwarf_decode_macros that handles skipping an unknown
-   opcode.  Returns an updated pointer to the macro data buffer; or,
-   on error, issues a complaint and returns NULL.  */
-
-static const gdb_byte *
-skip_unknown_opcode (unsigned int opcode,
-		     const gdb_byte **opcode_definitions,
-		     const gdb_byte *mac_ptr, const gdb_byte *mac_end,
-		     bfd *abfd,
-		     unsigned int offset_size,
-		     struct dwarf2_section_info *section)
-{
-  unsigned int bytes_read, i;
-  unsigned long arg;
-  const gdb_byte *defn;
-
-  if (opcode_definitions[opcode] == NULL)
-    {
-      complaint (_("unrecognized DW_MACFINO opcode 0x%x"),
-		 opcode);
-      return NULL;
-    }
-
-  defn = opcode_definitions[opcode];
-  arg = read_unsigned_leb128 (abfd, defn, &bytes_read);
-  defn += bytes_read;
-
-  for (i = 0; i < arg; ++i)
-    {
-      mac_ptr = skip_form_bytes (abfd, mac_ptr, mac_end,
-				 (enum dwarf_form) defn[i], offset_size,
-				 section);
-      if (mac_ptr == NULL)
-	{
-	  /* skip_form_bytes already issued the complaint.  */
-	  return NULL;
-	}
-    }
-
-  return mac_ptr;
-}
-
-/* A helper function which parses the header of a macro section.
-   If the macro section is the extended (for now called "GNU") type,
-   then this updates *OFFSET_SIZE.  Returns a pointer to just after
-   the header, or issues a complaint and returns NULL on error.  */
-
-static const gdb_byte *
-dwarf_parse_macro_header (const gdb_byte **opcode_definitions,
-			  bfd *abfd,
-			  const gdb_byte *mac_ptr,
-			  unsigned int *offset_size,
-			  int section_is_gnu)
-{
-  memset (opcode_definitions, 0, 256 * sizeof (gdb_byte *));
-
-  if (section_is_gnu)
-    {
-      unsigned int version, flags;
-
-      version = read_2_bytes (abfd, mac_ptr);
-      if (version != 4 && version != 5)
-	{
-	  complaint (_("unrecognized version `%d' in .debug_macro section"),
-		     version);
-	  return NULL;
-	}
-      mac_ptr += 2;
-
-      flags = read_1_byte (abfd, mac_ptr);
-      ++mac_ptr;
-      *offset_size = (flags & 1) ? 8 : 4;
-
-      if ((flags & 2) != 0)
-	/* We don't need the line table offset.  */
-	mac_ptr += *offset_size;
-
-      /* Vendor opcode descriptions.  */
-      if ((flags & 4) != 0)
-	{
-	  unsigned int i, count;
-
-	  count = read_1_byte (abfd, mac_ptr);
-	  ++mac_ptr;
-	  for (i = 0; i < count; ++i)
-	    {
-	      unsigned int opcode, bytes_read;
-	      unsigned long arg;
-
-	      opcode = read_1_byte (abfd, mac_ptr);
-	      ++mac_ptr;
-	      opcode_definitions[opcode] = mac_ptr;
-	      arg = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
-	      mac_ptr += bytes_read;
-	      mac_ptr += arg;
-	    }
-	}
-    }
-
-  return mac_ptr;
-}
-
-/* A helper for dwarf_decode_macros that handles the GNU extensions,
-   including DW_MACRO_import.  */
-
-static void
-dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
-			  buildsym_compunit *builder,
-			  bfd *abfd,
-			  const gdb_byte *mac_ptr, const gdb_byte *mac_end,
-			  struct macro_source_file *current_file,
-			  struct line_header *lh,
-			  struct dwarf2_section_info *section,
-			  int section_is_gnu, int section_is_dwz,
-			  unsigned int offset_size,
-			  htab_t include_hash)
-{
-  struct objfile *objfile = dwarf2_per_objfile->objfile;
-  enum dwarf_macro_record_type macinfo_type;
-  int at_commandline;
-  const gdb_byte *opcode_definitions[256];
-
-  mac_ptr = dwarf_parse_macro_header (opcode_definitions, abfd, mac_ptr,
-				      &offset_size, section_is_gnu);
-  if (mac_ptr == NULL)
-    {
-      /* We already issued a complaint.  */
-      return;
-    }
-
-  /* Determines if GDB is still before first DW_MACINFO_start_file.  If true
-     GDB is still reading the definitions from command line.  First
-     DW_MACINFO_start_file will need to be ignored as it was already executed
-     to create CURRENT_FILE for the main source holding also the command line
-     definitions.  On first met DW_MACINFO_start_file this flag is reset to
-     normally execute all the remaining DW_MACINFO_start_file macinfos.  */
-
-  at_commandline = 1;
-
-  do
-    {
-      /* Do we at least have room for a macinfo type byte?  */
-      if (mac_ptr >= mac_end)
-	{
-	  section->overflow_complaint ();
-	  break;
-	}
-
-      macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr);
-      mac_ptr++;
-
-      /* Note that we rely on the fact that the corresponding GNU and
-	 DWARF constants are the same.  */
-      DIAGNOSTIC_PUSH
-      DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
-      switch (macinfo_type)
-	{
-	  /* A zero macinfo type indicates the end of the macro
-	     information.  */
-	case 0:
-	  break;
-
-        case DW_MACRO_define:
-        case DW_MACRO_undef:
-	case DW_MACRO_define_strp:
-	case DW_MACRO_undef_strp:
-	case DW_MACRO_define_sup:
-	case DW_MACRO_undef_sup:
-          {
-            unsigned int bytes_read;
-            int line;
-            const char *body;
-	    int is_define;
-
-	    line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
-	    mac_ptr += bytes_read;
-
-	    if (macinfo_type == DW_MACRO_define
-		|| macinfo_type == DW_MACRO_undef)
-	      {
-		body = read_direct_string (abfd, mac_ptr, &bytes_read);
-		mac_ptr += bytes_read;
-	      }
-	    else
-	      {
-		LONGEST str_offset;
-
-		str_offset = read_offset (abfd, mac_ptr, offset_size);
-		mac_ptr += offset_size;
-
-		if (macinfo_type == DW_MACRO_define_sup
-		    || macinfo_type == DW_MACRO_undef_sup
-		    || section_is_dwz)
-		  {
-		    struct dwz_file *dwz
-		      = dwarf2_get_dwz_file (dwarf2_per_objfile);
-
-		    body = dwz->read_string (objfile, str_offset);
-		  }
-		else
-		  body = read_indirect_string_at_offset (dwarf2_per_objfile,
-							 str_offset);
-	      }
-
-	    is_define = (macinfo_type == DW_MACRO_define
-			 || macinfo_type == DW_MACRO_define_strp
-			 || macinfo_type == DW_MACRO_define_sup);
-            if (! current_file)
-	      {
-		/* DWARF violation as no main source is present.  */
-		complaint (_("debug info with no main source gives macro %s "
-			     "on line %d: %s"),
-			   is_define ? _("definition") : _("undefinition"),
-			   line, body);
-		break;
-	      }
-	    if ((line == 0 && !at_commandline)
-		|| (line != 0 && at_commandline))
-	      complaint (_("debug info gives %s macro %s with %s line %d: %s"),
-			 at_commandline ? _("command-line") : _("in-file"),
-			 is_define ? _("definition") : _("undefinition"),
-			 line == 0 ? _("zero") : _("non-zero"), line, body);
-
-	    if (body == NULL)
-	      {
-		/* Fedora's rpm-build's "debugedit" binary
-		   corrupted .debug_macro sections.
-
-		   For more info, see
-		   https://bugzilla.redhat.com/show_bug.cgi?id=1708786 */
-		complaint (_("debug info gives %s invalid macro %s "
-			     "without body (corrupted?) at line %d "
-			     "on file %s"),
-			   at_commandline ? _("command-line") : _("in-file"),
-			   is_define ? _("definition") : _("undefinition"),
-			   line, current_file->filename);
-	      }
-	    else if (is_define)
-	      parse_macro_definition (current_file, line, body);
-	    else
-	      {
-		gdb_assert (macinfo_type == DW_MACRO_undef
-			    || macinfo_type == DW_MACRO_undef_strp
-			    || macinfo_type == DW_MACRO_undef_sup);
-		macro_undef (current_file, line, body);
-	      }
-          }
-          break;
-
-        case DW_MACRO_start_file:
-          {
-            unsigned int bytes_read;
-            int line, file;
-
-            line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
-            mac_ptr += bytes_read;
-            file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
-            mac_ptr += bytes_read;
-
-	    if ((line == 0 && !at_commandline)
-		|| (line != 0 && at_commandline))
-	      complaint (_("debug info gives source %d included "
-			   "from %s at %s line %d"),
-			 file, at_commandline ? _("command-line") : _("file"),
-			 line == 0 ? _("zero") : _("non-zero"), line);
-
-	    if (at_commandline)
-	      {
-		/* This DW_MACRO_start_file was executed in the
-		   pass one.  */
-		at_commandline = 0;
-	      }
-	    else
-	      current_file = macro_start_file (builder, file, line,
-					       current_file, lh);
-          }
-          break;
-
-        case DW_MACRO_end_file:
-          if (! current_file)
-	    complaint (_("macro debug info has an unmatched "
-			 "`close_file' directive"));
-          else
-            {
-              current_file = current_file->included_by;
-              if (! current_file)
-                {
-                  enum dwarf_macro_record_type next_type;
-
-                  /* GCC circa March 2002 doesn't produce the zero
-                     type byte marking the end of the compilation
-                     unit.  Complain if it's not there, but exit no
-                     matter what.  */
-
-                  /* Do we at least have room for a macinfo type byte?  */
-                  if (mac_ptr >= mac_end)
-                    {
-		      section->overflow_complaint ();
-                      return;
-                    }
-
-                  /* We don't increment mac_ptr here, so this is just
-                     a look-ahead.  */
-                  next_type
-		    = (enum dwarf_macro_record_type) read_1_byte (abfd,
-								  mac_ptr);
-                  if (next_type != 0)
-		    complaint (_("no terminating 0-type entry for "
-				 "macros in `.debug_macinfo' section"));
-
-                  return;
-                }
-            }
-          break;
-
-	case DW_MACRO_import:
-	case DW_MACRO_import_sup:
-	  {
-	    LONGEST offset;
-	    void **slot;
-	    bfd *include_bfd = abfd;
-	    struct dwarf2_section_info *include_section = section;
-	    const gdb_byte *include_mac_end = mac_end;
-	    int is_dwz = section_is_dwz;
-	    const gdb_byte *new_mac_ptr;
-
-	    offset = read_offset (abfd, mac_ptr, offset_size);
-	    mac_ptr += offset_size;
-
-	    if (macinfo_type == DW_MACRO_import_sup)
-	      {
-		struct dwz_file *dwz = dwarf2_get_dwz_file (dwarf2_per_objfile);
-
-		dwz->macro.read (objfile);
-
-		include_section = &dwz->macro;
-		include_bfd = include_section->get_bfd_owner ();
-		include_mac_end = dwz->macro.buffer + dwz->macro.size;
-		is_dwz = 1;
-	      }
 
-	    new_mac_ptr = include_section->buffer + offset;
-	    slot = htab_find_slot (include_hash, new_mac_ptr, INSERT);
-
-	    if (*slot != NULL)
-	      {
-		/* This has actually happened; see
-		   http://sourceware.org/bugzilla/show_bug.cgi?id=13568.  */
-		complaint (_("recursive DW_MACRO_import in "
-			     ".debug_macro section"));
-	      }
-	    else
-	      {
-		*slot = (void *) new_mac_ptr;
-
-		dwarf_decode_macro_bytes (dwarf2_per_objfile, builder,
-					  include_bfd, new_mac_ptr,
-					  include_mac_end, current_file, lh,
-					  section, section_is_gnu, is_dwz,
-					  offset_size, include_hash);
-
-		htab_remove_elt (include_hash, (void *) new_mac_ptr);
-	      }
-	  }
-	  break;
-
-        case DW_MACINFO_vendor_ext:
-	  if (!section_is_gnu)
-	    {
-	      unsigned int bytes_read;
-
-	      /* This reads the constant, but since we don't recognize
-		 any vendor extensions, we ignore it.  */
-	      read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
-	      mac_ptr += bytes_read;
-	      read_direct_string (abfd, mac_ptr, &bytes_read);
-	      mac_ptr += bytes_read;
-
-	      /* We don't recognize any vendor extensions.  */
-	      break;
-	    }
-	  /* FALLTHROUGH */
-
-	default:
-	  mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
-					 mac_ptr, mac_end, abfd, offset_size,
-					 section);
-	  if (mac_ptr == NULL)
-	    return;
-	  break;
-        }
-      DIAGNOSTIC_POP
-    } while (macinfo_type != 0);
-}
-
-static void
-dwarf_decode_macros (struct dwarf2_per_objfile *dwarf2_per_objfile,
-		     buildsym_compunit *builder, dwarf2_section_info *section,
-		     struct line_header *lh, unsigned int offset_size,
-		     unsigned int offset, int section_is_gnu)
-{
-  bfd *abfd;
-  const gdb_byte *mac_ptr, *mac_end;
-  struct macro_source_file *current_file = 0;
-  enum dwarf_macro_record_type macinfo_type;
-  const gdb_byte *opcode_definitions[256];
-  void **slot;
-
-  abfd = section->get_bfd_owner ();
-
-  /* First pass: Find the name of the base filename.
-     This filename is needed in order to process all macros whose definition
-     (or undefinition) comes from the command line.  These macros are defined
-     before the first DW_MACINFO_start_file entry, and yet still need to be
-     associated to the base file.
-
-     To determine the base file name, we scan the macro definitions until we
-     reach the first DW_MACINFO_start_file entry.  We then initialize
-     CURRENT_FILE accordingly so that any macro definition found before the
-     first DW_MACINFO_start_file can still be associated to the base file.  */
-
-  mac_ptr = section->buffer + offset;
-  mac_end = section->buffer + section->size;
-
-  mac_ptr = dwarf_parse_macro_header (opcode_definitions, abfd, mac_ptr,
-				      &offset_size, section_is_gnu);
-  if (mac_ptr == NULL)
-    {
-      /* We already issued a complaint.  */
-      return;
-    }
-
-  do
-    {
-      /* Do we at least have room for a macinfo type byte?  */
-      if (mac_ptr >= mac_end)
-        {
-	  /* Complaint is printed during the second pass as GDB will probably
-	     stop the first pass earlier upon finding
-	     DW_MACINFO_start_file.  */
-	  break;
-        }
-
-      macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr);
-      mac_ptr++;
-
-      /* Note that we rely on the fact that the corresponding GNU and
-	 DWARF constants are the same.  */
-      DIAGNOSTIC_PUSH
-      DIAGNOSTIC_IGNORE_SWITCH_DIFFERENT_ENUM_TYPES
-      switch (macinfo_type)
-        {
-          /* A zero macinfo type indicates the end of the macro
-             information.  */
-        case 0:
-	  break;
-
-	case DW_MACRO_define:
-	case DW_MACRO_undef:
-	  /* Only skip the data by MAC_PTR.  */
-	  {
-	    unsigned int bytes_read;
-
-	    read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
-	    mac_ptr += bytes_read;
-	    read_direct_string (abfd, mac_ptr, &bytes_read);
-	    mac_ptr += bytes_read;
-	  }
-	  break;
-
-	case DW_MACRO_start_file:
-	  {
-	    unsigned int bytes_read;
-	    int line, file;
-
-	    line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
-	    mac_ptr += bytes_read;
-	    file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
-	    mac_ptr += bytes_read;
-
-	    current_file = macro_start_file (builder, file, line,
-					     current_file, lh);
-	  }
-	  break;
-
-	case DW_MACRO_end_file:
-	  /* No data to skip by MAC_PTR.  */
-	  break;
-
-	case DW_MACRO_define_strp:
-	case DW_MACRO_undef_strp:
-	case DW_MACRO_define_sup:
-	case DW_MACRO_undef_sup:
-	  {
-	    unsigned int bytes_read;
-
-	    read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
-	    mac_ptr += bytes_read;
-	    mac_ptr += offset_size;
-	  }
-	  break;
-
-	case DW_MACRO_import:
-	case DW_MACRO_import_sup:
-	  /* Note that, according to the spec, a transparent include
-	     chain cannot call DW_MACRO_start_file.  So, we can just
-	     skip this opcode.  */
-	  mac_ptr += offset_size;
-	  break;
-
-	case DW_MACINFO_vendor_ext:
-	  /* Only skip the data by MAC_PTR.  */
-	  if (!section_is_gnu)
-	    {
-	      unsigned int bytes_read;
-
-	      read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
-	      mac_ptr += bytes_read;
-	      read_direct_string (abfd, mac_ptr, &bytes_read);
-	      mac_ptr += bytes_read;
-	    }
-	  /* FALLTHROUGH */
-
-	default:
-	  mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
-					 mac_ptr, mac_end, abfd, offset_size,
-					 section);
-	  if (mac_ptr == NULL)
-	    return;
-	  break;
-	}
-      DIAGNOSTIC_POP
-    } while (macinfo_type != 0 && current_file == NULL);
-
-  /* Second pass: Process all entries.
-
-     Use the AT_COMMAND_LINE flag to determine whether we are still processing
-     command-line macro definitions/undefinitions.  This flag is unset when we
-     reach the first DW_MACINFO_start_file entry.  */
-
-  htab_up include_hash (htab_create_alloc (1, htab_hash_pointer,
-					   htab_eq_pointer,
-					   NULL, xcalloc, xfree));
-  mac_ptr = section->buffer + offset;
-  slot = htab_find_slot (include_hash.get (), mac_ptr, INSERT);
-  *slot = (void *) mac_ptr;
-  dwarf_decode_macro_bytes (dwarf2_per_objfile, builder,
-			    abfd, mac_ptr, mac_end,
-			    current_file, lh, section,
-			    section_is_gnu, 0, offset_size,
-			    include_hash.get ());
-}
+/* Macro support.  */
 
 /* An overload of dwarf_decode_macros that finds the correct section
    and ensures it is read in before calling the other overload.  */
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 09/22] Make some line_header methods const
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (7 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 08/22] Move code to new file dwarf2/macro.c Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 10/22] Use a const line_header in macro reader Tom Tromey
                   ` (13 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes a few line_header methods to be const.  In some cases, a
const overload is added.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/line-header.h (struct line_header) <is_valid_file_index,
	file_names_size, file_full_name, file_file_name>: Use const.
	<file_name_at, file_names>: Add const overload.
	* dwarf2/line-header.c (line_header::file_file_name)
	(line_header::file_full_name): Update.
---
 gdb/ChangeLog            |  8 ++++++++
 gdb/dwarf2/line-header.c |  4 ++--
 gdb/dwarf2/line-header.h | 18 ++++++++++++++----
 3 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/gdb/dwarf2/line-header.c b/gdb/dwarf2/line-header.c
index 56dfb5c2dd2..f417f2d0fae 100644
--- a/gdb/dwarf2/line-header.c
+++ b/gdb/dwarf2/line-header.c
@@ -59,7 +59,7 @@ line_header::add_file_name (const char *name,
 }
 
 gdb::unique_xmalloc_ptr<char>
-line_header::file_file_name (int file)
+line_header::file_file_name (int file) const
 {
   /* Is the file number a valid index into the line header's file name
      table?  Remember that file numbers start with one, not zero.  */
@@ -95,7 +95,7 @@ line_header::file_file_name (int file)
 }
 
 gdb::unique_xmalloc_ptr<char>
-line_header::file_full_name (int file, const char *comp_dir)
+line_header::file_full_name (int file, const char *comp_dir) const
 {
   /* Is the file number a valid index into the line header's file name
      table?  Remember that file numbers start with one, not zero.  */
diff --git a/gdb/dwarf2/line-header.h b/gdb/dwarf2/line-header.h
index 08cf7b0810f..30bc37fb85a 100644
--- a/gdb/dwarf2/line-header.h
+++ b/gdb/dwarf2/line-header.h
@@ -96,7 +96,7 @@ struct line_header
     return m_include_dirs[vec_index];
   }
 
-  bool is_valid_file_index (int file_index)
+  bool is_valid_file_index (int file_index) const
   {
     if (version >= 5)
       return 0 <= file_index && file_index < file_names_size ();
@@ -117,11 +117,21 @@ struct line_header
     return &m_file_names[vec_index];
   }
 
+  /* A const overload of the same.  */
+  const file_entry *file_name_at (file_name_index index) const
+  {
+    line_header *lh = const_cast<line_header *> (this);
+    return lh->file_name_at (index);
+  }
+
   /* The indexes are 0-based in DWARF 5 and 1-based in DWARF 4. Therefore,
      this method should only be used to iterate through all file entries in an
      index-agnostic manner.  */
   std::vector<file_entry> &file_names ()
   { return m_file_names; }
+  /* A const overload of the same.  */
+  const std::vector<file_entry> &file_names () const
+  { return m_file_names; }
 
   /* Offset of line number information in .debug_line section.  */
   sect_offset sect_off {};
@@ -145,7 +155,7 @@ struct line_header
      element is standard_opcode_lengths[opcode_base - 1].  */
   std::unique_ptr<unsigned char[]> standard_opcode_lengths;
 
-  int file_names_size ()
+  int file_names_size () const
   { return m_file_names.size(); }
 
   /* The start and end of the statement program following this
@@ -157,13 +167,13 @@ struct line_header
      compilation.  The result is allocated using xmalloc; the caller
      is responsible for freeing it.  */
   gdb::unique_xmalloc_ptr<char> file_full_name (int file,
-						const char *comp_dir);
+						const char *comp_dir) const;
 
   /* Return file name relative to the compilation directory of file
      number I in this object's file name table.  The result is
      allocated using xmalloc; the caller is responsible for freeing
      it.  */
-  gdb::unique_xmalloc_ptr<char> file_file_name (int file);
+  gdb::unique_xmalloc_ptr<char> file_file_name (int file) const;
 
  private:
   /* The include_directories table.  Note these are observing
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 10/22] Use a const line_header in macro reader
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (8 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 09/22] Make some line_header methods const Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 11/22] Use a const dwarf2_section_info " Tom Tromey
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes the DWARF macro reader to use a const line_header.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.c (dwarf_decode_macros): Make "lh" const.
	* dwarf2/macro.h (dwarf_decode_macros): Constify "lh" parameter.
	* dwarf2/macro.c (macro_start_file): Constify "lh" parameter.
	(dwarf_decode_macro_bytes, dwarf_decode_macros): Likewise.
---
 gdb/ChangeLog      | 7 +++++++
 gdb/dwarf2/macro.c | 6 +++---
 gdb/dwarf2/macro.h | 2 +-
 gdb/dwarf2/read.c  | 2 +-
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/gdb/dwarf2/macro.c b/gdb/dwarf2/macro.c
index 1f1cca858c1..01af58de29f 100644
--- a/gdb/dwarf2/macro.c
+++ b/gdb/dwarf2/macro.c
@@ -48,7 +48,7 @@ static struct macro_source_file *
 macro_start_file (buildsym_compunit *builder,
 		  int file, int line,
                   struct macro_source_file *current_file,
-                  struct line_header *lh)
+                  const struct line_header *lh)
 {
   /* File name relative to the compilation directory of this source file.  */
   gdb::unique_xmalloc_ptr<char> file_name = lh->file_file_name (file);
@@ -423,7 +423,7 @@ dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
 			  bfd *abfd,
 			  const gdb_byte *mac_ptr, const gdb_byte *mac_end,
 			  struct macro_source_file *current_file,
-			  struct line_header *lh,
+			  const struct line_header *lh,
 			  struct dwarf2_section_info *section,
 			  int section_is_gnu, int section_is_dwz,
 			  unsigned int offset_size,
@@ -711,7 +711,7 @@ dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
 void
 dwarf_decode_macros (struct dwarf2_per_objfile *dwarf2_per_objfile,
 		     buildsym_compunit *builder, dwarf2_section_info *section,
-		     struct line_header *lh, unsigned int offset_size,
+		     const struct line_header *lh, unsigned int offset_size,
 		     unsigned int offset, int section_is_gnu)
 {
   bfd *abfd;
diff --git a/gdb/dwarf2/macro.h b/gdb/dwarf2/macro.h
index 3937c550088..b92987cf0d1 100644
--- a/gdb/dwarf2/macro.h
+++ b/gdb/dwarf2/macro.h
@@ -25,7 +25,7 @@ struct buildsym_compunit;
 extern void dwarf_decode_macros (struct dwarf2_per_objfile *dwarf2_per_objfile,
 				 buildsym_compunit *builder,
 				 dwarf2_section_info *section,
-				 struct line_header *lh,
+				 const struct line_header *lh,
 				 unsigned int offset_size,
 				 unsigned int offset,
 				 int section_is_gnu);
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index ca90418e45e..13fa63bff57 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -23045,7 +23045,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = cu->per_cu->dwarf2_per_objfile;
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  struct line_header *lh = cu->line_header;
+  const struct line_header *lh = cu->line_header;
   unsigned int offset_size = cu->header.offset_size;
   struct dwarf2_section_info *section;
   const char *section_name;
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 11/22] Use a const dwarf2_section_info in macro reader
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (9 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 10/22] Use a const line_header in macro reader Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 12/22] Trivial fix in dwarf_decode_macro_bytes Tom Tromey
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes the DWARF macro reader to use a const dwarf2_section_info.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/macro.h (dwarf_decode_macros): Make section parameter
	const.
	* dwarf2/macro.c (skip_form_bytes, skip_unknown_opcode)
	(dwarf_decode_macro_bytes, dwarf_decode_macros): Make section
	parameter const.
---
 gdb/ChangeLog      |  8 ++++++++
 gdb/dwarf2/macro.c | 11 ++++++-----
 gdb/dwarf2/macro.h |  2 +-
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/gdb/dwarf2/macro.c b/gdb/dwarf2/macro.c
index 01af58de29f..49586399673 100644
--- a/gdb/dwarf2/macro.c
+++ b/gdb/dwarf2/macro.c
@@ -231,7 +231,7 @@ 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)
+		 const struct dwarf2_section_info *section)
 {
   unsigned int bytes_read;
 
@@ -322,7 +322,7 @@ skip_unknown_opcode (unsigned int opcode,
 		     const gdb_byte *mac_ptr, const gdb_byte *mac_end,
 		     bfd *abfd,
 		     unsigned int offset_size,
-		     struct dwarf2_section_info *section)
+		     const struct dwarf2_section_info *section)
 {
   unsigned int bytes_read, i;
   unsigned long arg;
@@ -424,7 +424,7 @@ dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
 			  const gdb_byte *mac_ptr, const gdb_byte *mac_end,
 			  struct macro_source_file *current_file,
 			  const struct line_header *lh,
-			  struct dwarf2_section_info *section,
+			  const struct dwarf2_section_info *section,
 			  int section_is_gnu, int section_is_dwz,
 			  unsigned int offset_size,
 			  htab_t include_hash)
@@ -634,7 +634,7 @@ dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
 	    LONGEST offset;
 	    void **slot;
 	    bfd *include_bfd = abfd;
-	    struct dwarf2_section_info *include_section = section;
+	    const struct dwarf2_section_info *include_section = section;
 	    const gdb_byte *include_mac_end = mac_end;
 	    int is_dwz = section_is_dwz;
 	    const gdb_byte *new_mac_ptr;
@@ -710,7 +710,8 @@ dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
 
 void
 dwarf_decode_macros (struct dwarf2_per_objfile *dwarf2_per_objfile,
-		     buildsym_compunit *builder, dwarf2_section_info *section,
+		     buildsym_compunit *builder,
+		     const dwarf2_section_info *section,
 		     const struct line_header *lh, unsigned int offset_size,
 		     unsigned int offset, int section_is_gnu)
 {
diff --git a/gdb/dwarf2/macro.h b/gdb/dwarf2/macro.h
index b92987cf0d1..cb66a6f50cd 100644
--- a/gdb/dwarf2/macro.h
+++ b/gdb/dwarf2/macro.h
@@ -24,7 +24,7 @@ struct buildsym_compunit;
 
 extern void dwarf_decode_macros (struct dwarf2_per_objfile *dwarf2_per_objfile,
 				 buildsym_compunit *builder,
-				 dwarf2_section_info *section,
+				 const dwarf2_section_info *section,
 				 const struct line_header *lh,
 				 unsigned int offset_size,
 				 unsigned int offset,
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 12/22] Trivial fix in dwarf_decode_macro_bytes
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (10 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 11/22] Use a const dwarf2_section_info " Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 13/22] Convert read_indirect_line_string to a method Tom Tromey
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

One spot in dwarf_decode_macro_bytes could use the existing "objfile"
local variable.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/macro.c (dwarf_decode_macro_bytes): Use objfile local
	variable.
---
 gdb/ChangeLog      | 5 +++++
 gdb/dwarf2/macro.c | 6 +++---
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/gdb/dwarf2/macro.c b/gdb/dwarf2/macro.c
index 49586399673..6c2d2514652 100644
--- a/gdb/dwarf2/macro.c
+++ b/gdb/dwarf2/macro.c
@@ -512,9 +512,9 @@ dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
 		    body = dwz->read_string (objfile, str_offset);
 		  }
 		else
-		  body = (dwarf2_per_objfile->str.read_string
-			  (dwarf2_per_objfile->objfile,
-			   str_offset, "DW_FORM_strp"));
+		  body = dwarf2_per_objfile->str.read_string (objfile,
+							      str_offset,
+							      "DW_FORM_strp");
 	      }
 
 	    is_define = (macinfo_type == DW_MACRO_define
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 13/22] Convert read_indirect_line_string to a method
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (11 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 12/22] Trivial fix in dwarf_decode_macro_bytes Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-24  2:49   ` Simon Marchi
  2020-03-22 18:45 ` [PATCH 14/22] Move more code to line-header.c Tom Tromey
                   ` (9 subsequent siblings)
  22 siblings, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes read_indirect_line_string to be a method on
dwarf2_per_objfile.  This makes it a bit simpler to share between
files.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.h (struct dwarf2_per_objfile) <read_line_string>:
	Declare method.
	* dwarf2/read.c (read_attribute_value): Update.
	(dwarf2_per_objfile::read_line_string): Rename from
	read_indirect_line_string.
	(read_formatted_entries): Update.
---
 gdb/ChangeLog     |  9 +++++++++
 gdb/dwarf2/read.c | 28 +++++++++++-----------------
 gdb/dwarf2/read.h |  8 ++++++++
 3 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 13fa63bff57..001030b31c0 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1251,10 +1251,6 @@ static const char *read_indirect_string
   (struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *, const gdb_byte *,
    const struct comp_unit_head *, unsigned int *);
 
-static const char *read_indirect_line_string
-  (struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *, const gdb_byte *,
-   const struct comp_unit_head *, unsigned int *);
-
 static const char *read_indirect_string_at_offset
   (struct dwarf2_per_objfile *dwarf2_per_objfile, LONGEST str_offset);
 
@@ -18550,9 +18546,9 @@ read_attribute_value (const struct die_reader_specs *reader,
     case DW_FORM_line_strp:
       if (!cu->per_cu->is_dwz)
 	{
-	  DW_STRING (attr) = read_indirect_line_string (dwarf2_per_objfile,
-							abfd, info_ptr,
-							cu_header, &bytes_read);
+	  DW_STRING (attr)
+	    = dwarf2_per_objfile->read_line_string (info_ptr, cu_header,
+						    &bytes_read);
 	  DW_STRING_IS_CANONICAL (attr) = 0;
 	  info_ptr += bytes_read;
 	  break;
@@ -18790,17 +18786,15 @@ read_indirect_string (struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *abfd,
    BUF is assumed to be in a compilation unit described by CU_HEADER.
    Return *BYTES_READ_PTR count of bytes read from BUF.  */
 
-static const char *
-read_indirect_line_string (struct dwarf2_per_objfile *dwarf2_per_objfile,
-			   bfd *abfd, const gdb_byte *buf,
+const char *
+dwarf2_per_objfile::read_line_string (const gdb_byte *buf,
 			   const struct comp_unit_head *cu_header,
 			   unsigned int *bytes_read_ptr)
 {
+  bfd *abfd = objfile->obfd;
   LONGEST str_offset = cu_header->read_offset (abfd, buf, bytes_read_ptr);
 
-  return dwarf2_per_objfile->line_str.read_string (dwarf2_per_objfile->objfile,
-						   str_offset,
-						   "DW_FORM_line_strp");
+  return line_str.read_string (objfile, str_offset, "DW_FORM_line_strp");
 }
 
 /* Given index ADDR_INDEX in .debug_addr, fetch the value.
@@ -19284,10 +19278,10 @@ read_formatted_entries (struct dwarf2_per_objfile *dwarf2_per_objfile,
 	      break;
 
 	    case DW_FORM_line_strp:
-	      string.emplace (read_indirect_line_string (dwarf2_per_objfile,
-							 abfd, buf,
-							 cu_header,
-							 &bytes_read));
+	      string.emplace
+		(dwarf2_per_objfile->read_line_string (buf,
+						       cu_header,
+						       &bytes_read));
 	      buf += bytes_read;
 	      break;
 
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index c5a8ecf8a6a..039113f87e9 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -110,6 +110,14 @@ struct dwarf2_per_objfile
 
   /* Free all cached compilation units.  */
   void free_cached_comp_units ();
+
+  /* Return pointer to string at .debug_line_str offset as read from BUF.
+     BUF is assumed to be in a compilation unit described by CU_HEADER.
+     Return *BYTES_READ_PTR count of bytes read from BUF.  */
+  const char *read_line_string (const gdb_byte *buf,
+				const struct comp_unit_head *cu_header,
+				unsigned int *bytes_read_ptr);
+
 private:
   /* This function is mapped across the sections and remembers the
      offset and size of each of the debugging sections we are
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 14/22] Move more code to line-header.c
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (12 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 13/22] Convert read_indirect_line_string to a method Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 15/22] Move die_info to new header Tom Tromey
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This moves some more code out of read.c and into line-header.c.
dwarf_decode_line_header is split into two -- the part remaining in
read.c handles interfacing to the dwarf2_cu; while the part in
line-header.c (more or less) purely handles the actual decoding.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/line-header.h (dwarf_decode_line_header): Declare.
	* dwarf2/read.c
	(dwarf2_statement_list_fits_in_line_number_section_complaint):
	Move to line-header.c.
	(read_checked_initial_length_and_offset, read_formatted_entries):
	Likewise.
	(dwarf_decode_line_header): Split into two.
	* dwarf2/line-header.c
	(dwarf2_statement_list_fits_in_line_number_section_complaint):
	Move from read.c.
	(read_checked_initial_length_and_offset, read_formatted_entries):
	Likewise.
	(dwarf_decode_line_header): New function, split from read.c.
---
 gdb/ChangeLog            |  16 ++
 gdb/dwarf2/line-header.c | 335 +++++++++++++++++++++++++++++++++++++++
 gdb/dwarf2/line-header.h |  14 ++
 gdb/dwarf2/read.c        | 332 +-------------------------------------
 4 files changed, 368 insertions(+), 329 deletions(-)

diff --git a/gdb/dwarf2/line-header.c b/gdb/dwarf2/line-header.c
index f417f2d0fae..58749e9594b 100644
--- a/gdb/dwarf2/line-header.c
+++ b/gdb/dwarf2/line-header.c
@@ -18,6 +18,8 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "dwarf2/comp-unit.h"
+#include "dwarf2/leb.h"
 #include "dwarf2/line-header.h"
 #include "dwarf2/read.h"
 #include "complaints.h"
@@ -112,3 +114,336 @@ line_header::file_full_name (int file, const char *comp_dir) const
   else
     return file_file_name (file);
 }
+
+static void
+dwarf2_statement_list_fits_in_line_number_section_complaint (void)
+{
+  complaint (_("statement list doesn't fit in .debug_line section"));
+}
+
+/* Cover function for read_initial_length.
+   Returns the length of the object at BUF, and stores the size of the
+   initial length in *BYTES_READ and stores the size that offsets will be in
+   *OFFSET_SIZE.
+   If the initial length size is not equivalent to that specified in
+   CU_HEADER then issue a complaint.
+   This is useful when reading non-comp-unit headers.  */
+
+static LONGEST
+read_checked_initial_length_and_offset (bfd *abfd, const gdb_byte *buf,
+					const struct comp_unit_head *cu_header,
+					unsigned int *bytes_read,
+					unsigned int *offset_size)
+{
+  LONGEST length = read_initial_length (abfd, buf, bytes_read);
+
+  gdb_assert (cu_header->initial_length_size == 4
+	      || cu_header->initial_length_size == 8
+	      || cu_header->initial_length_size == 12);
+
+  if (cu_header->initial_length_size != *bytes_read)
+    complaint (_("intermixed 32-bit and 64-bit DWARF sections"));
+
+  *offset_size = (*bytes_read == 4) ? 4 : 8;
+  return length;
+}
+
+/* Read directory or file name entry format, starting with byte of
+   format count entries, ULEB128 pairs of entry formats, ULEB128 of
+   entries count and the entries themselves in the described entry
+   format.  */
+
+static void
+read_formatted_entries (struct dwarf2_per_objfile *dwarf2_per_objfile,
+			bfd *abfd, const gdb_byte **bufp,
+			struct line_header *lh,
+			const struct comp_unit_head *cu_header,
+			void (*callback) (struct line_header *lh,
+					  const char *name,
+					  dir_index d_index,
+					  unsigned int mod_time,
+					  unsigned int length))
+{
+  gdb_byte format_count, formati;
+  ULONGEST data_count, datai;
+  const gdb_byte *buf = *bufp;
+  const gdb_byte *format_header_data;
+  unsigned int bytes_read;
+
+  format_count = read_1_byte (abfd, buf);
+  buf += 1;
+  format_header_data = buf;
+  for (formati = 0; formati < format_count; formati++)
+    {
+      read_unsigned_leb128 (abfd, buf, &bytes_read);
+      buf += bytes_read;
+      read_unsigned_leb128 (abfd, buf, &bytes_read);
+      buf += bytes_read;
+    }
+
+  data_count = read_unsigned_leb128 (abfd, buf, &bytes_read);
+  buf += bytes_read;
+  for (datai = 0; datai < data_count; datai++)
+    {
+      const gdb_byte *format = format_header_data;
+      struct file_entry fe;
+
+      for (formati = 0; formati < format_count; formati++)
+	{
+	  ULONGEST content_type = read_unsigned_leb128 (abfd, format, &bytes_read);
+	  format += bytes_read;
+
+	  ULONGEST form  = read_unsigned_leb128 (abfd, format, &bytes_read);
+	  format += bytes_read;
+
+	  gdb::optional<const char *> string;
+	  gdb::optional<unsigned int> uint;
+
+	  switch (form)
+	    {
+	    case DW_FORM_string:
+	      string.emplace (read_direct_string (abfd, buf, &bytes_read));
+	      buf += bytes_read;
+	      break;
+
+	    case DW_FORM_line_strp:
+	      string.emplace
+		(dwarf2_per_objfile->read_line_string (buf,
+						       cu_header,
+						       &bytes_read));
+	      buf += bytes_read;
+	      break;
+
+	    case DW_FORM_data1:
+	      uint.emplace (read_1_byte (abfd, buf));
+	      buf += 1;
+	      break;
+
+	    case DW_FORM_data2:
+	      uint.emplace (read_2_bytes (abfd, buf));
+	      buf += 2;
+	      break;
+
+	    case DW_FORM_data4:
+	      uint.emplace (read_4_bytes (abfd, buf));
+	      buf += 4;
+	      break;
+
+	    case DW_FORM_data8:
+	      uint.emplace (read_8_bytes (abfd, buf));
+	      buf += 8;
+	      break;
+
+	    case DW_FORM_data16:
+	      /*  This is used for MD5, but file_entry does not record MD5s. */
+	      buf += 16;
+	      break;
+
+	    case DW_FORM_udata:
+	      uint.emplace (read_unsigned_leb128 (abfd, buf, &bytes_read));
+	      buf += bytes_read;
+	      break;
+
+	    case DW_FORM_block:
+	      /* It is valid only for DW_LNCT_timestamp which is ignored by
+		 current GDB.  */
+	      break;
+	    }
+
+	  switch (content_type)
+	    {
+	    case DW_LNCT_path:
+	      if (string.has_value ())
+		fe.name = *string;
+	      break;
+	    case DW_LNCT_directory_index:
+	      if (uint.has_value ())
+		fe.d_index = (dir_index) *uint;
+	      break;
+	    case DW_LNCT_timestamp:
+	      if (uint.has_value ())
+		fe.mod_time = *uint;
+	      break;
+	    case DW_LNCT_size:
+	      if (uint.has_value ())
+		fe.length = *uint;
+	      break;
+	    case DW_LNCT_MD5:
+	      break;
+	    default:
+	      complaint (_("Unknown format content type %s"),
+			 pulongest (content_type));
+	    }
+	}
+
+      callback (lh, fe.name, fe.d_index, fe.mod_time, fe.length);
+    }
+
+  *bufp = buf;
+}
+
+/* See line-header.h.  */
+
+line_header_up
+dwarf_decode_line_header  (sect_offset sect_off, bool is_dwz,
+			   struct dwarf2_per_objfile *dwarf2_per_objfile,
+			   struct dwarf2_section_info *section,
+			   const struct comp_unit_head *cu_header)
+{
+  const gdb_byte *line_ptr;
+  unsigned int bytes_read, offset_size;
+  int i;
+  const char *cur_dir, *cur_file;
+
+  bfd *abfd = section->get_bfd_owner ();
+
+  /* Make sure that at least there's room for the total_length field.
+     That could be 12 bytes long, but we're just going to fudge that.  */
+  if (to_underlying (sect_off) + 4 >= section->size)
+    {
+      dwarf2_statement_list_fits_in_line_number_section_complaint ();
+      return 0;
+    }
+
+  line_header_up lh (new line_header ());
+
+  lh->sect_off = sect_off;
+  lh->offset_in_dwz = is_dwz;
+
+  line_ptr = section->buffer + to_underlying (sect_off);
+
+  /* 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;
+
+  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 = start_here + lh->total_length;
+  lh->version = read_2_bytes (abfd, line_ptr);
+  line_ptr += 2;
+  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.  */
+      complaint (_("unsupported version in .debug_line section"));
+      return NULL;
+    }
+  if (lh->version >= 5)
+    {
+      gdb_byte segment_selector_size;
+
+      /* Skip address size.  */
+      read_1_byte (abfd, line_ptr);
+      line_ptr += 1;
+
+      segment_selector_size = read_1_byte (abfd, line_ptr);
+      line_ptr += 1;
+      if (segment_selector_size != 0)
+	{
+	  complaint (_("unsupported segment selector size %u "
+		       "in .debug_line section"),
+		     segment_selector_size);
+	  return NULL;
+	}
+    }
+  lh->header_length = read_offset (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)
+    {
+      lh->maximum_ops_per_instruction = read_1_byte (abfd, line_ptr);
+      line_ptr += 1;
+    }
+  else
+    lh->maximum_ops_per_instruction = 1;
+
+  if (lh->maximum_ops_per_instruction == 0)
+    {
+      lh->maximum_ops_per_instruction = 1;
+      complaint (_("invalid maximum_ops_per_instruction "
+		   "in `.debug_line' section"));
+    }
+
+  lh->default_is_stmt = read_1_byte (abfd, line_ptr);
+  line_ptr += 1;
+  lh->line_base = read_1_signed_byte (abfd, line_ptr);
+  line_ptr += 1;
+  lh->line_range = read_1_byte (abfd, line_ptr);
+  line_ptr += 1;
+  lh->opcode_base = read_1_byte (abfd, line_ptr);
+  line_ptr += 1;
+  lh->standard_opcode_lengths.reset (new unsigned char[lh->opcode_base]);
+
+  lh->standard_opcode_lengths[0] = 1;  /* This should never be used anyway.  */
+  for (i = 1; i < lh->opcode_base; ++i)
+    {
+      lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
+      line_ptr += 1;
+    }
+
+  if (lh->version >= 5)
+    {
+      /* Read directory table.  */
+      read_formatted_entries (dwarf2_per_objfile, abfd, &line_ptr, lh.get (),
+			      cu_header,
+			      [] (struct line_header *header, const char *name,
+				  dir_index d_index, unsigned int mod_time,
+				  unsigned int length)
+	{
+	  header->add_include_dir (name);
+	});
+
+      /* Read file name table.  */
+      read_formatted_entries (dwarf2_per_objfile, abfd, &line_ptr, lh.get (),
+			      cu_header,
+			      [] (struct line_header *header, const char *name,
+				  dir_index d_index, unsigned int mod_time,
+				  unsigned int length)
+	{
+	  header->add_file_name (name, d_index, mod_time, length);
+	});
+    }
+  else
+    {
+      /* Read directory table.  */
+      while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+	{
+	  line_ptr += bytes_read;
+	  lh->add_include_dir (cur_dir);
+	}
+      line_ptr += bytes_read;
+
+      /* Read file name table.  */
+      while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+	{
+	  unsigned int mod_time, length;
+	  dir_index d_index;
+
+	  line_ptr += bytes_read;
+	  d_index = (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;
+
+	  lh->add_file_name (cur_file, d_index, mod_time, length);
+	}
+      line_ptr += bytes_read;
+    }
+
+  if (line_ptr > (section->buffer + section->size))
+    complaint (_("line number info header doesn't "
+		 "fit in `.debug_line' section"));
+
+  return lh;
+}
diff --git a/gdb/dwarf2/line-header.h b/gdb/dwarf2/line-header.h
index 30bc37fb85a..700aaddacf7 100644
--- a/gdb/dwarf2/line-header.h
+++ b/gdb/dwarf2/line-header.h
@@ -195,4 +195,18 @@ file_entry::include_dir (const line_header *lh) const
   return lh->include_dir_at (d_index);
 }
 
+/* Read the statement program header starting at SECT_OFF in SECTION.
+   Return line_header.  Returns nullptr if there is a problem reading
+   the header, e.g., if it has a version we don't understand.
+
+   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.  */
+
+extern line_header_up dwarf_decode_line_header
+  (sect_offset sect_off, bool is_dwz,
+   struct dwarf2_per_objfile *dwarf2_per_objfile,
+   struct dwarf2_section_info *section,
+   const struct comp_unit_head *cu_header);
+
 #endif /* DWARF2_LINE_HEADER_H */
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 001030b31c0..5d9fed2d827 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1239,10 +1239,6 @@ static void read_attribute_reprocess (const struct die_reader_specs *reader,
 
 static CORE_ADDR read_addr_index (struct dwarf2_cu *cu, unsigned int addr_index);
 
-static LONGEST read_checked_initial_length_and_offset
-  (bfd *, const gdb_byte *, const struct comp_unit_head *,
-   unsigned int *, unsigned int *);
-
 static sect_offset read_abbrev_offset
   (struct dwarf2_per_objfile *dwarf2_per_objfile,
    struct dwarf2_section_info *, sect_offset);
@@ -1673,12 +1669,6 @@ static void free_line_header_voidp (void *arg);
 \f
 /* Various complaints about symbol reading that don't abort the process.  */
 
-static void
-dwarf2_statement_list_fits_in_line_number_section_complaint (void)
-{
-  complaint (_("statement list doesn't fit in .debug_line section"));
-}
-
 static void
 dwarf2_debug_line_missing_file_complaint (void)
 {
@@ -18730,33 +18720,6 @@ read_attribute (const struct die_reader_specs *reader,
 			       need_reprocess);
 }
 
-/* Cover function for read_initial_length.
-   Returns the length of the object at BUF, and stores the size of the
-   initial length in *BYTES_READ and stores the size that offsets will be in
-   *OFFSET_SIZE.
-   If the initial length size is not equivalent to that specified in
-   CU_HEADER then issue a complaint.
-   This is useful when reading non-comp-unit headers.  */
-
-static LONGEST
-read_checked_initial_length_and_offset (bfd *abfd, const gdb_byte *buf,
-					const struct comp_unit_head *cu_header,
-					unsigned int *bytes_read,
-					unsigned int *offset_size)
-{
-  LONGEST length = read_initial_length (abfd, buf, bytes_read);
-
-  gdb_assert (cu_header->initial_length_size == 4
-	      || cu_header->initial_length_size == 8
-	      || cu_header->initial_length_size == 12);
-
-  if (cu_header->initial_length_size != *bytes_read)
-    complaint (_("intermixed 32-bit and 64-bit DWARF sections"));
-
-  *offset_size = (*bytes_read == 4) ? 4 : 8;
-  return length;
-}
-
 /* Return pointer to string at .debug_str offset STR_OFFSET.  */
 
 static const char *
@@ -19219,140 +19182,6 @@ get_debug_line_section (struct dwarf2_cu *cu)
   return section;
 }
 
-/* Read directory or file name entry format, starting with byte of
-   format count entries, ULEB128 pairs of entry formats, ULEB128 of
-   entries count and the entries themselves in the described entry
-   format.  */
-
-static void
-read_formatted_entries (struct dwarf2_per_objfile *dwarf2_per_objfile,
-			bfd *abfd, const gdb_byte **bufp,
-			struct line_header *lh,
-			const struct comp_unit_head *cu_header,
-			void (*callback) (struct line_header *lh,
-					  const char *name,
-					  dir_index d_index,
-					  unsigned int mod_time,
-					  unsigned int length))
-{
-  gdb_byte format_count, formati;
-  ULONGEST data_count, datai;
-  const gdb_byte *buf = *bufp;
-  const gdb_byte *format_header_data;
-  unsigned int bytes_read;
-
-  format_count = read_1_byte (abfd, buf);
-  buf += 1;
-  format_header_data = buf;
-  for (formati = 0; formati < format_count; formati++)
-    {
-      read_unsigned_leb128 (abfd, buf, &bytes_read);
-      buf += bytes_read;
-      read_unsigned_leb128 (abfd, buf, &bytes_read);
-      buf += bytes_read;
-    }
-
-  data_count = read_unsigned_leb128 (abfd, buf, &bytes_read);
-  buf += bytes_read;
-  for (datai = 0; datai < data_count; datai++)
-    {
-      const gdb_byte *format = format_header_data;
-      struct file_entry fe;
-
-      for (formati = 0; formati < format_count; formati++)
-	{
-	  ULONGEST content_type = read_unsigned_leb128 (abfd, format, &bytes_read);
-	  format += bytes_read;
-
-	  ULONGEST form  = read_unsigned_leb128 (abfd, format, &bytes_read);
-	  format += bytes_read;
-
-	  gdb::optional<const char *> string;
-	  gdb::optional<unsigned int> uint;
-
-	  switch (form)
-	    {
-	    case DW_FORM_string:
-	      string.emplace (read_direct_string (abfd, buf, &bytes_read));
-	      buf += bytes_read;
-	      break;
-
-	    case DW_FORM_line_strp:
-	      string.emplace
-		(dwarf2_per_objfile->read_line_string (buf,
-						       cu_header,
-						       &bytes_read));
-	      buf += bytes_read;
-	      break;
-
-	    case DW_FORM_data1:
-	      uint.emplace (read_1_byte (abfd, buf));
-	      buf += 1;
-	      break;
-
-	    case DW_FORM_data2:
-	      uint.emplace (read_2_bytes (abfd, buf));
-	      buf += 2;
-	      break;
-
-	    case DW_FORM_data4:
-	      uint.emplace (read_4_bytes (abfd, buf));
-	      buf += 4;
-	      break;
-
-	    case DW_FORM_data8:
-	      uint.emplace (read_8_bytes (abfd, buf));
-	      buf += 8;
-	      break;
-
-	    case DW_FORM_data16:
-	      /*  This is used for MD5, but file_entry does not record MD5s. */
-	      buf += 16;
-	      break;
-
-	    case DW_FORM_udata:
-	      uint.emplace (read_unsigned_leb128 (abfd, buf, &bytes_read));
-	      buf += bytes_read;
-	      break;
-
-	    case DW_FORM_block:
-	      /* It is valid only for DW_LNCT_timestamp which is ignored by
-		 current GDB.  */
-	      break;
-	    }
-
-	  switch (content_type)
-	    {
-	    case DW_LNCT_path:
-	      if (string.has_value ())
-		fe.name = *string;
-	      break;
-	    case DW_LNCT_directory_index:
-	      if (uint.has_value ())
-		fe.d_index = (dir_index) *uint;
-	      break;
-	    case DW_LNCT_timestamp:
-	      if (uint.has_value ())
-		fe.mod_time = *uint;
-	      break;
-	    case DW_LNCT_size:
-	      if (uint.has_value ())
-		fe.length = *uint;
-	      break;
-	    case DW_LNCT_MD5:
-	      break;
-	    default:
-	      complaint (_("Unknown format content type %s"),
-			 pulongest (content_type));
-	    }
-	}
-
-      callback (lh, fe.name, fe.d_index, fe.mod_time, fe.length);
-    }
-
-  *bufp = buf;
-}
-
 /* 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.
@@ -19366,12 +19195,7 @@ read_formatted_entries (struct dwarf2_per_objfile *dwarf2_per_objfile,
 static line_header_up
 dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
 {
-  const gdb_byte *line_ptr;
-  unsigned int bytes_read, offset_size;
-  int i;
-  const char *cur_dir, *cur_file;
   struct dwarf2_section_info *section;
-  bfd *abfd;
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = cu->per_cu->dwarf2_per_objfile;
 
@@ -19386,159 +19210,9 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu)
       return 0;
     }
 
-  /* We can't do this until we know the section is non-empty.
-     Only then do we know we have such a section.  */
-  abfd = section->get_bfd_owner ();
-
-  /* Make sure that at least there's room for the total_length field.
-     That could be 12 bytes long, but we're just going to fudge that.  */
-  if (to_underlying (sect_off) + 4 >= section->size)
-    {
-      dwarf2_statement_list_fits_in_line_number_section_complaint ();
-      return 0;
-    }
-
-  line_header_up lh (new line_header ());
-
-  lh->sect_off = sect_off;
-  lh->offset_in_dwz = cu->per_cu->is_dwz;
-
-  line_ptr = section->buffer + to_underlying (sect_off);
-
-  /* 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;
-
-  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 = start_here + lh->total_length;
-  lh->version = read_2_bytes (abfd, line_ptr);
-  line_ptr += 2;
-  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.  */
-      complaint (_("unsupported version in .debug_line section"));
-      return NULL;
-    }
-  if (lh->version >= 5)
-    {
-      gdb_byte segment_selector_size;
-
-      /* Skip address size.  */
-      read_1_byte (abfd, line_ptr);
-      line_ptr += 1;
-
-      segment_selector_size = read_1_byte (abfd, line_ptr);
-      line_ptr += 1;
-      if (segment_selector_size != 0)
-	{
-	  complaint (_("unsupported segment selector size %u "
-		       "in .debug_line section"),
-		     segment_selector_size);
-	  return NULL;
-	}
-    }
-  lh->header_length = read_offset (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)
-    {
-      lh->maximum_ops_per_instruction = read_1_byte (abfd, line_ptr);
-      line_ptr += 1;
-    }
-  else
-    lh->maximum_ops_per_instruction = 1;
-
-  if (lh->maximum_ops_per_instruction == 0)
-    {
-      lh->maximum_ops_per_instruction = 1;
-      complaint (_("invalid maximum_ops_per_instruction "
-		   "in `.debug_line' section"));
-    }
-
-  lh->default_is_stmt = read_1_byte (abfd, line_ptr);
-  line_ptr += 1;
-  lh->line_base = read_1_signed_byte (abfd, line_ptr);
-  line_ptr += 1;
-  lh->line_range = read_1_byte (abfd, line_ptr);
-  line_ptr += 1;
-  lh->opcode_base = read_1_byte (abfd, line_ptr);
-  line_ptr += 1;
-  lh->standard_opcode_lengths.reset (new unsigned char[lh->opcode_base]);
-
-  lh->standard_opcode_lengths[0] = 1;  /* This should never be used anyway.  */
-  for (i = 1; i < lh->opcode_base; ++i)
-    {
-      lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
-      line_ptr += 1;
-    }
-
-  if (lh->version >= 5)
-    {
-      /* Read directory table.  */
-      read_formatted_entries (dwarf2_per_objfile, abfd, &line_ptr, lh.get (),
-			      &cu->header,
-			      [] (struct line_header *header, const char *name,
-				  dir_index d_index, unsigned int mod_time,
-				  unsigned int length)
-	{
-	  header->add_include_dir (name);
-	});
-
-      /* Read file name table.  */
-      read_formatted_entries (dwarf2_per_objfile, abfd, &line_ptr, lh.get (),
-			      &cu->header,
-			      [] (struct line_header *header, const char *name,
-				  dir_index d_index, unsigned int mod_time,
-				  unsigned int length)
-	{
-	  header->add_file_name (name, d_index, mod_time, length);
-	});
-    }
-  else
-    {
-      /* Read directory table.  */
-      while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
-	{
-	  line_ptr += bytes_read;
-	  lh->add_include_dir (cur_dir);
-	}
-      line_ptr += bytes_read;
-
-      /* Read file name table.  */
-      while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
-	{
-	  unsigned int mod_time, length;
-	  dir_index d_index;
-
-	  line_ptr += bytes_read;
-	  d_index = (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;
-
-	  lh->add_file_name (cur_file, d_index, mod_time, length);
-	}
-      line_ptr += bytes_read;
-    }
-
-  if (line_ptr > (section->buffer + section->size))
-    complaint (_("line number info header doesn't "
-		 "fit in `.debug_line' section"));
-
-  return lh;
+  return dwarf_decode_line_header (sect_off, cu->per_cu->is_dwz,
+				   dwarf2_per_objfile, section,
+				   &cu->header);
 }
 
 /* Subroutine of dwarf_decode_lines to simplify it.
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 15/22] Move die_info to new header
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (13 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 14/22] Move more code to line-header.c Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 16/22] Remove dwarf2_cu::base_known Tom Tromey
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This moves struct die_info to a new header, dwarf2/die.h.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.c (struct die_info): Move to die.h.
	* dwarf2/die.h: New file.
---
 gdb/ChangeLog     |  5 ++++
 gdb/dwarf2/die.h  | 62 +++++++++++++++++++++++++++++++++++++++++++++++
 gdb/dwarf2/read.c | 40 +-----------------------------
 3 files changed, 68 insertions(+), 39 deletions(-)
 create mode 100644 gdb/dwarf2/die.h

diff --git a/gdb/dwarf2/die.h b/gdb/dwarf2/die.h
new file mode 100644
index 00000000000..f8826a276e8
--- /dev/null
+++ b/gdb/dwarf2/die.h
@@ -0,0 +1,62 @@
+/* DWARF DIEs
+
+   Copyright (C) 2003-2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program 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.
+
+   This program 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/>.  */
+
+#ifndef GDB_DWARF2_DIE_H
+#define GDB_DWARF2_DIE_H
+
+/* This data structure holds a complete die structure.  */
+struct die_info
+{
+  /* DWARF-2 tag for this DIE.  */
+  ENUM_BITFIELD(dwarf_tag) tag : 16;
+
+  /* Number of attributes */
+  unsigned char num_attrs;
+
+  /* True if we're presently building the full type name for the
+     type derived from this DIE.  */
+  unsigned char building_fullname : 1;
+
+  /* True if this die is in process.  PR 16581.  */
+  unsigned char in_process : 1;
+
+  /* True if this DIE has children.  */
+  unsigned char has_children : 1;
+
+  /* Abbrev number */
+  unsigned int abbrev;
+
+  /* Offset in .debug_info or .debug_types section.  */
+  sect_offset sect_off;
+
+  /* The dies in a compilation unit form an n-ary tree.  PARENT
+     points to this die's parent; CHILD points to the first child of
+     this node; and all the children of a given node are chained
+     together via their SIBLING fields.  */
+  struct die_info *child;	/* Its first child, if any.  */
+  struct die_info *sibling;	/* Its next sibling, if any.  */
+  struct die_info *parent;	/* Its parent, if any.  */
+
+  /* An array of attributes, with NUM_ATTRS elements.  There may be
+     zero, but it's not common and zero-sized arrays are not
+     sufficiently portable C.  */
+  struct attribute attrs[1];
+};
+
+#endif /* GDB_DWARF2_DIE_H */
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 5d9fed2d827..8b9b6bc3ea0 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -39,6 +39,7 @@
 #include "dwarf2/line-header.h"
 #include "dwarf2/dwz.h"
 #include "dwarf2/macro.h"
+#include "dwarf2/die.h"
 #include "bfd.h"
 #include "elf-bfd.h"
 #include "symtab.h"
@@ -1045,45 +1046,6 @@ struct partial_die_info : public allocate_on_obstack
     }
   };
 
-/* This data structure holds a complete die structure.  */
-struct die_info
-  {
-    /* DWARF-2 tag for this DIE.  */
-    ENUM_BITFIELD(dwarf_tag) tag : 16;
-
-    /* Number of attributes */
-    unsigned char num_attrs;
-
-    /* True if we're presently building the full type name for the
-       type derived from this DIE.  */
-    unsigned char building_fullname : 1;
-
-    /* True if this die is in process.  PR 16581.  */
-    unsigned char in_process : 1;
-
-    /* True if this DIE has children.  */
-    unsigned char has_children : 1;
-
-    /* Abbrev number */
-    unsigned int abbrev;
-
-    /* Offset in .debug_info or .debug_types section.  */
-    sect_offset sect_off;
-
-    /* The dies in a compilation unit form an n-ary tree.  PARENT
-       points to this die's parent; CHILD points to the first child of
-       this node; and all the children of a given node are chained
-       together via their SIBLING fields.  */
-    struct die_info *child;	/* Its first child, if any.  */
-    struct die_info *sibling;	/* Its next sibling, if any.  */
-    struct die_info *parent;	/* Its parent, if any.  */
-
-    /* An array of attributes, with NUM_ATTRS elements.  There may be
-       zero, but it's not common and zero-sized arrays are not
-       sufficiently portable C.  */
-    struct attribute attrs[1];
-  };
-
 /* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte,
    but this would require a corresponding change in unpack_field_as_long
    and friends.  */
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 16/22] Remove dwarf2_cu::base_known
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (14 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 15/22] Move die_info to new header Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 17/22] Change dwarf2_attr_no_follow to be a method Tom Tromey
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This removes dwarf2_cu::base_known, changing base_address to be a
gdb::optional.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.c (struct dwarf2_cu) <base_known>: Remove.
	<base_address>: Now an optional.
	(dwarf2_find_base_address, dwarf2_rnglists_process)
	(dwarf2_ranges_process, fill_in_loclist_baton)
	(dwarf2_symbol_mark_computed): Update.
---
 gdb/ChangeLog     |  8 ++++++++
 gdb/dwarf2/read.c | 47 +++++++++++++++++------------------------------
 2 files changed, 25 insertions(+), 30 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 8b9b6bc3ea0..3479cd55a2e 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -393,10 +393,7 @@ struct dwarf2_cu
   struct comp_unit_head header {};
 
   /* Base address of this compilation unit.  */
-  CORE_ADDR base_address = 0;
-
-  /* Non-zero if base_address has been set.  */
-  int base_known = 0;
+  gdb::optional<CORE_ADDR> base_address;
 
   /* The language we are debugging.  */
   enum language language = language_unknown;
@@ -5783,23 +5780,16 @@ dwarf2_find_base_address (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;
 
-  cu->base_known = 0;
-  cu->base_address = 0;
+  cu->base_address.reset ();
 
   attr = dwarf2_attr (die, DW_AT_entry_pc, cu);
   if (attr != nullptr)
-    {
-      cu->base_address = attr->value_as_address ();
-      cu->base_known = 1;
-    }
+    cu->base_address = attr->value_as_address ();
   else
     {
       attr = dwarf2_attr (die, DW_AT_low_pc, cu);
       if (attr != nullptr)
-	{
-	  cu->base_address = attr->value_as_address ();
-	  cu->base_known = 1;
-	}
+	cu->base_address = attr->value_as_address ();
     }
 }
 
@@ -13441,13 +13431,11 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   bfd *obfd = objfile->obfd;
   /* Base address selection entry.  */
-  CORE_ADDR base;
-  int found_base;
+  gdb::optional<CORE_ADDR> base;
   const gdb_byte *buffer;
   CORE_ADDR baseaddr;
   bool overflow = false;
 
-  found_base = cu->base_known;
   base = cu->base_address;
 
   dwarf2_per_objfile->rnglists.read (objfile);
@@ -13486,7 +13474,6 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
 	      break;
 	    }
 	  base = cu->header.read_address (obfd, buffer, &bytes_read);
-	  found_base = 1;
 	  buffer += bytes_read;
 	  break;
 	case DW_RLE_start_length:
@@ -13544,7 +13531,7 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
       if (rlet == DW_RLE_base_address)
 	continue;
 
-      if (!found_base)
+      if (!base.has_value ())
 	{
 	  /* We have no valid base address for the ranges
 	     data.  */
@@ -13563,8 +13550,8 @@ dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
       if (range_beginning == range_end)
 	continue;
 
-      range_beginning += base;
-      range_end += base;
+      range_beginning += *base;
+      range_end += *base;
 
       /* A not-uncommon case of bad debug info.
 	 Don't pollute the addrmap with bad data.  */
@@ -13608,8 +13595,7 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
   unsigned int addr_size = cu_header->addr_size;
   CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
   /* Base address selection entry.  */
-  CORE_ADDR base;
-  int found_base;
+  gdb::optional<CORE_ADDR> base;
   unsigned int dummy;
   const gdb_byte *buffer;
   CORE_ADDR baseaddr;
@@ -13617,7 +13603,6 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
   if (cu_header->version >= 5)
     return dwarf2_rnglists_process (offset, cu, callback);
 
-  found_base = cu->base_known;
   base = cu->base_address;
 
   dwarf2_per_objfile->ranges.read (objfile);
@@ -13654,11 +13639,10 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
 	  /* If we found the largest possible address, then we already
 	     have the base address in range_end.  */
 	  base = range_end;
-	  found_base = 1;
 	  continue;
 	}
 
-      if (!found_base)
+      if (!base.has_value ())
 	{
 	  /* We have no valid base address for the ranges
 	     data.  */
@@ -13677,8 +13661,8 @@ dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
       if (range_beginning == range_end)
 	continue;
 
-      range_beginning += base;
-      range_end += base;
+      range_beginning += *base;
+      range_end += *base;
 
       /* A not-uncommon case of bad debug info.
 	 Don't pollute the addrmap with bad data.  */
@@ -22758,7 +22742,10 @@ fill_in_loclist_baton (struct dwarf2_cu *cu,
      don't run off the edge of the section.  */
   baton->size = section->size - DW_UNSND (attr);
   baton->data = section->buffer + DW_UNSND (attr);
-  baton->base_address = cu->base_address;
+  if (cu->base_address.has_value ())
+    baton->base_address = *cu->base_address;
+  else
+    baton->base_address = 0;
   baton->from_dwo = cu->dwo_unit != NULL;
 }
 
@@ -22783,7 +22770,7 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
 
       fill_in_loclist_baton (cu, baton, attr);
 
-      if (cu->base_known == 0)
+      if (!cu->base_address.has_value ())
 	complaint (_("Location list used without "
 		     "specifying the CU base address."));
 
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 17/22] Change dwarf2_attr_no_follow to be a method
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (15 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 16/22] Remove dwarf2_cu::base_known Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 18/22] Remove sibling_die Tom Tromey
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes dwarf2_attr_no_follow to be a method on die_info.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.c (lookup_addr_base, lookup_ranges_base)
	(build_type_psymtabs_reader, read_structure_type)
	(read_enumeration_type, read_full_die_1): Update.
	(dwarf2_attr_no_follow): Move to die.h.
	* dwarf2/die.h (struct die_info) <attr>: New method.
---
 gdb/ChangeLog     |  8 ++++++++
 gdb/dwarf2/die.h  | 11 +++++++++++
 gdb/dwarf2/read.c | 37 ++++++++-----------------------------
 3 files changed, 27 insertions(+), 29 deletions(-)

diff --git a/gdb/dwarf2/die.h b/gdb/dwarf2/die.h
index f8826a276e8..3a265b7df03 100644
--- a/gdb/dwarf2/die.h
+++ b/gdb/dwarf2/die.h
@@ -23,6 +23,17 @@
 /* This data structure holds a complete die structure.  */
 struct die_info
 {
+  /* Return the named attribute or NULL if not there, but do not
+     follow DW_AT_specification, etc.  */
+  struct attribute *attr (dwarf_attribute name)
+  {
+    for (unsigned i = 0; i < num_attrs; ++i)
+      if (attrs[i].name == name)
+	return &attrs[i];
+    return NULL;
+  }
+
+
   /* DWARF-2 tag for this DIE.  */
   ENUM_BITFIELD(dwarf_tag) tag : 16;
 
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 3479cd55a2e..87c4cae9b01 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1224,9 +1224,6 @@ static void set_cu_language (unsigned int, struct dwarf2_cu *);
 static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
 				      struct dwarf2_cu *);
 
-static struct attribute *dwarf2_attr_no_follow (struct die_info *,
-						unsigned int);
-
 static const char *dwarf2_string_attr (struct die_info *die, unsigned int name,
                                        struct dwarf2_cu *cu);
 
@@ -6397,9 +6394,9 @@ static gdb::optional<ULONGEST>
 lookup_addr_base (struct die_info *comp_unit_die)
 {
   struct attribute *attr;
-  attr = dwarf2_attr_no_follow (comp_unit_die, DW_AT_addr_base);
+  attr = comp_unit_die->attr (DW_AT_addr_base);
   if (attr == nullptr)
-    attr = dwarf2_attr_no_follow (comp_unit_die, DW_AT_GNU_addr_base);
+    attr = comp_unit_die->attr (DW_AT_GNU_addr_base);
   if (attr == nullptr)
     return gdb::optional<ULONGEST> ();
   return DW_UNSND (attr);
@@ -6411,9 +6408,9 @@ static ULONGEST
 lookup_ranges_base (struct die_info *comp_unit_die)
 {
   struct attribute *attr;
-  attr = dwarf2_attr_no_follow (comp_unit_die, DW_AT_rnglists_base);
+  attr = comp_unit_die->attr (DW_AT_rnglists_base);
   if (attr == nullptr)
-    attr = dwarf2_attr_no_follow (comp_unit_die, DW_AT_GNU_ranges_base);
+    attr = comp_unit_die->attr (DW_AT_GNU_ranges_base);
   if (attr == nullptr)
     return 0;
   return DW_UNSND (attr);
@@ -7399,7 +7396,7 @@ build_type_psymtabs_reader (const struct die_reader_specs *reader,
   if (! type_unit_die->has_children)
     return;
 
-  attr = dwarf2_attr_no_follow (type_unit_die, DW_AT_stmt_list);
+  attr = type_unit_die->attr (DW_AT_stmt_list);
   tu_group = get_type_unit_group (cu, attr);
 
   if (tu_group->tus == nullptr)
@@ -14977,7 +14974,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
   /* If the definition of this type lives in .debug_types, read that type.
      Don't follow DW_AT_specification though, that will take us back up
      the chain and we want to go down.  */
-  attr = dwarf2_attr_no_follow (die, DW_AT_signature);
+  attr = die->attr (DW_AT_signature);
   if (attr != nullptr)
     {
       type = get_DW_AT_signature_type (die, attr, cu);
@@ -15513,7 +15510,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
   /* If the definition of this type lives in .debug_types, read that type.
      Don't follow DW_AT_specification though, that will take us back up
      the chain and we want to go down.  */
-  attr = dwarf2_attr_no_follow (die, DW_AT_signature);
+  attr = die->attr (DW_AT_signature);
   if (attr != nullptr)
     {
       type = get_DW_AT_signature_type (die, attr, cu);
@@ -17539,7 +17536,7 @@ read_full_die_1 (const struct die_reader_specs *reader,
         indexes_that_need_reprocess.push_back (i);
     }
 
-  struct attribute *attr = dwarf2_attr_no_follow (die, DW_AT_str_offsets_base);
+  struct attribute *attr = die->attr (DW_AT_str_offsets_base);
   if (attr != nullptr)
     cu->str_offsets_base = DW_UNSND (attr);
 
@@ -18984,24 +18981,6 @@ dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu)
   return NULL;
 }
 
-/* Return the named attribute or NULL if not there,
-   but do not follow DW_AT_specification, etc.
-   This is for use in contexts where we're reading .debug_types dies.
-   Following DW_AT_specification, DW_AT_abstract_origin will take us
-   back up the chain, and we want to go down.  */
-
-static struct attribute *
-dwarf2_attr_no_follow (struct die_info *die, unsigned int name)
-{
-  unsigned int i;
-
-  for (i = 0; i < die->num_attrs; ++i)
-    if (die->attrs[i].name == name)
-      return &die->attrs[i];
-
-  return NULL;
-}
-
 /* Return the string associated with a string-typed attribute, or NULL if it
    is either not found or is of an incorrect type.  */
 
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 18/22] Remove sibling_die
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (16 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 17/22] Change dwarf2_attr_no_follow to be a method Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 19/22] Change two more functions to be methods on die_info Tom Tromey
                   ` (4 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

The sibling_die helper function does not seem to add much value,
considering that many other fields of die_info are directly accessed.
So, this removes it.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.c (read_import_statement, read_file_scope)
	(read_type_unit_scope, inherit_abstract_dies, read_func_scope)
	(read_lexical_block_scope, read_call_site_scope)
	(dwarf2_get_subprogram_pc_bounds, get_scope_pc_bounds)
	(handle_struct_member_die, process_structure_scope)
	(update_enumeration_type_from_children)
	(process_enumeration_scope, read_array_type, read_common_block)
	(read_namespace, read_module, read_subroutine_type): Update.
	(sibling_die): Remove.
---
 gdb/ChangeLog     | 12 +++++++++
 gdb/dwarf2/read.c | 62 ++++++++++++++++++++---------------------------
 2 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 87c4cae9b01..9d744ab0825 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1416,8 +1416,6 @@ static const char *dwarf_bool_name (unsigned int);
 
 static const char *dwarf_type_encoding_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 *);
 
 static void dump_die_for_error (struct die_info *);
@@ -10461,7 +10459,7 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
 
   if (die->tag == DW_TAG_imported_module && cu->language == language_fortran)
     for (child_die = die->child; child_die && child_die->tag;
-	 child_die = sibling_die (child_die))
+	 child_die = child_die->sibling)
       {
 	/* DWARF-4: A Fortran use statement with a “rename list” may be
 	   represented by an imported module entry with an import attribute
@@ -10739,7 +10737,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
       while (child_die && child_die->tag)
 	{
 	  process_die (child_die, cu);
-	  child_die = sibling_die (child_die);
+	  child_die = child_die->sibling;
 	}
     }
 
@@ -10907,7 +10905,7 @@ read_type_unit_scope (struct die_info *die, struct dwarf2_cu *cu)
       while (child_die && child_die->tag)
 	{
 	  process_die (child_die, cu);
-	  child_die = sibling_die (child_die);
+	  child_die = child_die->sibling;
 	}
     }
 }
@@ -12680,7 +12678,7 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
 
   for (child_die = die->child;
        child_die && child_die->tag;
-       child_die = sibling_die (child_die))
+       child_die = child_die->sibling)
     {
       struct die_info *child_origin_die;
       struct dwarf2_cu *child_origin_cu;
@@ -12757,7 +12755,7 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
 	  if (!origin_child_die->in_process)
 	    process_die (origin_child_die, origin_cu);
 	}
-      origin_child_die = sibling_die (origin_child_die);
+      origin_child_die = origin_child_die->sibling;
     }
   origin_cu->list_in_scope = origin_previous_list_in_scope;
 
@@ -12826,7 +12824,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   /* If we have any template arguments, then we must allocate a
      different sort of symbol.  */
-  for (child_die = die->child; child_die; child_die = sibling_die (child_die))
+  for (child_die = die->child; child_die; child_die = child_die->sibling)
     {
       if (child_die->tag == DW_TAG_template_type_param
 	  || child_die->tag == DW_TAG_template_value_param)
@@ -12879,7 +12877,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
 	    }
 	  else
 	    process_die (child_die, cu);
-	  child_die = sibling_die (child_die);
+	  child_die = child_die->sibling;
 	}
     }
 
@@ -12901,7 +12899,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
 	    {
 	      if (child_die->tag == DW_TAG_imported_module)
 		process_die (child_die, spec_cu);
-	      child_die = sibling_die (child_die);
+	      child_die = child_die->sibling;
 	    }
 
 	  /* In some cases, GCC generates specification DIEs that
@@ -12990,7 +12988,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
 	 GCC does no longer produces such DWARF since GCC r224161.  */
       for (child_die = die->child;
 	   child_die != NULL && child_die->tag;
-	   child_die = sibling_die (child_die))
+	   child_die = child_die->sibling)
 	process_die (child_die, cu);
       return;
     case PC_BOUNDS_INVALID:
@@ -13006,7 +13004,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
       while (child_die && child_die->tag)
 	{
 	  process_die (child_die, cu);
-	  child_die = sibling_die (child_die);
+	  child_die = child_die->sibling;
 	}
     }
   inherit_abstract_dies (die, cu);
@@ -13087,7 +13085,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   nparams = 0;
   for (child_die = die->child; child_die && child_die->tag;
-       child_die = sibling_die (child_die))
+       child_die = child_die->sibling)
     {
       if (child_die->tag != DW_TAG_call_site_parameter
           && child_die->tag != DW_TAG_GNU_call_site_parameter)
@@ -13232,7 +13230,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   for (child_die = die->child;
        child_die && child_die->tag;
-       child_die = sibling_die (child_die))
+       child_die = child_die->sibling)
     {
       struct call_site_parameter *parameter;
       struct attribute *loc, *origin;
@@ -13859,7 +13857,7 @@ dwarf2_get_subprogram_pc_bounds (struct die_info *die,
       if (child->tag == DW_TAG_subprogram
           || child->tag == DW_TAG_lexical_block)
         dwarf2_get_subprogram_pc_bounds (child, lowpc, highpc, cu);
-      child = sibling_die (child);
+      child = child->sibling;
     }
 }
 
@@ -13915,7 +13913,7 @@ get_scope_pc_bounds (struct die_info *die,
 	    break;
 	  }
 
-	  child = sibling_die (child);
+	  child = child->sibling;
 	}
     }
 
@@ -15153,7 +15151,7 @@ handle_struct_member_die (struct die_info *child_die, struct type *type,
 
       for (die_info *variant_child = child_die->child;
 	   variant_child != NULL;
-	   variant_child = sibling_die (variant_child))
+	   variant_child = variant_child->sibling)
 	{
 	  if (variant_child->tag == DW_TAG_member)
 	    {
@@ -15243,7 +15241,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
 	  if (is_variant_part && discr_offset == child_die->sect_off)
 	    fi.fields.back ().variant.is_discriminant = true;
 
-	  child_die = sibling_die (child_die);
+	  child_die = child_die->sibling;
 	}
 
       /* Attach template arguments to type.  */
@@ -15391,7 +15389,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
       else
 	process_die (child_die, cu);
 
-      child_die = sibling_die (child_die);
+      child_die = child_die->sibling;
     }
 
   /* Do not consider external references.  According to the DWARF standard,
@@ -15452,7 +15450,7 @@ update_enumeration_type_from_children (struct die_info *die,
 
   for (child_die = die->child;
        child_die != NULL && child_die->tag;
-       child_die = sibling_die (child_die))
+       child_die = child_die->sibling)
     {
       struct attribute *attr;
       LONGEST value;
@@ -15628,7 +15626,7 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
 		}
 	    }
 
-	  child_die = sibling_die (child_die);
+	  child_die = child_die->sibling;
 	}
 
       if (!fields.empty ())
@@ -15739,7 +15737,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
 	      range_types.push_back (child_type);
             }
 	}
-      child_die = sibling_die (child_die);
+      child_die = child_die->sibling;
     }
 
   /* Dwarf2 dimensions are output from left to right, create the
@@ -15976,7 +15974,7 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu)
 
       for (child_die = die->child;
 	   child_die && child_die->tag;
-	   child_die = sibling_die (child_die))
+	   child_die = child_die->sibling)
 	++n_entries;
 
       size = (sizeof (struct common_block)
@@ -15989,7 +15987,7 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu)
 
       for (child_die = die->child;
 	   child_die && child_die->tag;
-	   child_die = sibling_die (child_die))
+	   child_die = child_die->sibling)
 	{
 	  /* Create the symbol in the DW_TAG_common_block block in the current
 	     symbol scope.  */
@@ -16111,7 +16109,7 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu)
       while (child_die && child_die->tag)
 	{
 	  process_die (child_die, cu);
-	  child_die = sibling_die (child_die);
+	  child_die = child_die->sibling;
 	}
     }
 }
@@ -16147,7 +16145,7 @@ read_module (struct die_info *die, struct dwarf2_cu *cu)
   while (child_die && child_die->tag)
     {
       process_die (child_die, cu);
-      child_die = sibling_die (child_die);
+      child_die = child_die->sibling;
     }
 }
 
@@ -16646,7 +16644,7 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
 	    nparams++;
 	  else if (child_die->tag == DW_TAG_unspecified_parameters)
 	    TYPE_VARARGS (ftype) = 1;
-	  child_die = sibling_die (child_die);
+	  child_die = child_die->sibling;
 	}
 
       /* Allocate storage for parameters and fill them in.  */
@@ -16717,7 +16715,7 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
 	      TYPE_FIELD_TYPE (ftype, iparams) = arg_type;
 	      iparams++;
 	    }
-	  child_die = sibling_die (child_die);
+	  child_die = child_die->sibling;
 	}
     }
 
@@ -21238,14 +21236,6 @@ typename_concat (struct obstack *obs, const char *prefix, const char *suffix,
     }
 }
 
-/* Return sibling of die, NULL if no sibling.  */
-
-static struct die_info *
-sibling_die (struct die_info *die)
-{
-  return die->sibling;
-}
-
 /* Get name of a die, return NULL if not found.  */
 
 static const char *
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 19/22] Change two more functions to be methods on die_info
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (17 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 18/22] Remove sibling_die Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-23 19:07   ` Christian Biesinger
  2020-03-22 18:45 ` [PATCH 20/22] Rewrite new die_info methods Tom Tromey
                   ` (3 subsequent siblings)
  22 siblings, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes lookup_addr_base and lookup_ranges_base to be methods on
die_info.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/die.h (struct die_info) <addr_base, ranges_base>: New
	methods.
	* dwarf2/read.c (lookup_addr_base): Move to die.h.
	(lookup_ranges_base): Likewise.
	(read_cutu_die_from_dwo, read_full_die_1): Update.
---
 gdb/ChangeLog     |  8 ++++++++
 gdb/dwarf2/die.h  | 28 ++++++++++++++++++++++++++++
 gdb/dwarf2/read.c | 34 +++-------------------------------
 3 files changed, 39 insertions(+), 31 deletions(-)

diff --git a/gdb/dwarf2/die.h b/gdb/dwarf2/die.h
index 3a265b7df03..5673ae261ac 100644
--- a/gdb/dwarf2/die.h
+++ b/gdb/dwarf2/die.h
@@ -33,6 +33,34 @@ struct die_info
     return NULL;
   }
 
+  /* Return the address base of the compile unit, which, if exists, is
+     stored either at the attribute DW_AT_GNU_addr_base, or
+     DW_AT_addr_base.  */
+  gdb::optional<ULONGEST> addr_base ()
+  {
+    struct attribute *attr;
+    attr = attr (DW_AT_addr_base);
+    if (attr == nullptr)
+      attr = attr (DW_AT_GNU_addr_base);
+    if (attr == nullptr)
+      return gdb::optional<ULONGEST> ();
+    return DW_UNSND (attr);
+  }
+
+  /* Return range lists base of the compile unit, which, if exists, is
+     stored either at the attribute DW_AT_rnglists_base or
+     DW_AT_GNU_ranges_base.  */
+  ULONGEST ranges_base ()
+  {
+    struct attribute *attr;
+    attr = attr (DW_AT_rnglists_base);
+    if (attr == nullptr)
+      attr = attr (DW_AT_GNU_ranges_base);
+    if (attr == nullptr)
+      return 0;
+    return DW_UNSND (attr);
+  }
+
 
   /* DWARF-2 tag for this DIE.  */
   ENUM_BITFIELD(dwarf_tag) tag : 16;
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 9d744ab0825..9e7152d03e6 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -6386,34 +6386,6 @@ lookup_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
     }
 }
 
-/* Return the address base of the compile unit, which, if exists, is stored
-   either at the attribute DW_AT_GNU_addr_base, or DW_AT_addr_base.  */
-static gdb::optional<ULONGEST>
-lookup_addr_base (struct die_info *comp_unit_die)
-{
-  struct attribute *attr;
-  attr = comp_unit_die->attr (DW_AT_addr_base);
-  if (attr == nullptr)
-    attr = comp_unit_die->attr (DW_AT_GNU_addr_base);
-  if (attr == nullptr)
-    return gdb::optional<ULONGEST> ();
-  return DW_UNSND (attr);
-}
-
-/* Return range lists base of the compile unit, which, if exists, is stored
-   either at the attribute DW_AT_rnglists_base or DW_AT_GNU_ranges_base.  */
-static ULONGEST
-lookup_ranges_base (struct die_info *comp_unit_die)
-{
-  struct attribute *attr;
-  attr = comp_unit_die->attr (DW_AT_rnglists_base);
-  if (attr == nullptr)
-    attr = comp_unit_die->attr (DW_AT_GNU_ranges_base);
-  if (attr == nullptr)
-    return 0;
-  return DW_UNSND (attr);
-}
-
 /* Low level DIE reading support.  */
 
 /* Initialize a die_reader_specs struct from a dwarf2_cu struct.  */
@@ -6502,12 +6474,12 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu,
       ranges = dwarf2_attr (stub_comp_unit_die, DW_AT_ranges, cu);
       comp_dir = dwarf2_attr (stub_comp_unit_die, DW_AT_comp_dir, cu);
 
-      cu->addr_base = lookup_addr_base (stub_comp_unit_die);
+      cu->addr_base = stub_comp_unit_die->addr_base ();
 
       /* There should be a DW_AT_rnglists_base (DW_AT_GNU_ranges_base) attribute
 	 here (if needed). We need the value before we can process
 	 DW_AT_ranges.  */
-      cu->ranges_base = lookup_ranges_base (stub_comp_unit_die);
+      cu->ranges_base = stub_comp_unit_die->ranges_base ();
     }
   else if (stub_comp_dir != NULL)
     {
@@ -17538,7 +17510,7 @@ read_full_die_1 (const struct die_reader_specs *reader,
   if (attr != nullptr)
     cu->str_offsets_base = DW_UNSND (attr);
 
-  auto maybe_addr_base = lookup_addr_base(die);
+  auto maybe_addr_base = die->addr_base ();
   if (maybe_addr_base.has_value ())
     cu->addr_base = *maybe_addr_base;
   for (int index : indexes_that_need_reprocess)
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 20/22] Rewrite new die_info methods
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (18 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 19/22] Change two more functions to be methods on die_info Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 21/22] Move DWARF-constant stringifying code to new file Tom Tromey
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This rewrites the two new die_info to iterate over attributes rather
than to do two separate searches.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/die.h (struct die_info) <addr_base, ranges_base>:
	Rewrite.
---
 gdb/ChangeLog    |  5 +++++
 gdb/dwarf2/die.h | 30 ++++++++++++++++--------------
 2 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/gdb/dwarf2/die.h b/gdb/dwarf2/die.h
index 5673ae261ac..5522ebdf311 100644
--- a/gdb/dwarf2/die.h
+++ b/gdb/dwarf2/die.h
@@ -38,13 +38,14 @@ struct die_info
      DW_AT_addr_base.  */
   gdb::optional<ULONGEST> addr_base ()
   {
-    struct attribute *attr;
-    attr = attr (DW_AT_addr_base);
-    if (attr == nullptr)
-      attr = attr (DW_AT_GNU_addr_base);
-    if (attr == nullptr)
-      return gdb::optional<ULONGEST> ();
-    return DW_UNSND (attr);
+    for (unsigned i = 0; i < num_attrs; ++i)
+      if (attrs[i].name == DW_AT_addr_base
+	  || attrs[i].name == DW_AT_GNU_addr_base)
+	{
+	  /* If both exist, just use the first one.  */
+	  return DW_UNSND (&attrs[i]);
+	}
+    return gdb::optional<ULONGEST> ();
   }
 
   /* Return range lists base of the compile unit, which, if exists, is
@@ -52,13 +53,14 @@ struct die_info
      DW_AT_GNU_ranges_base.  */
   ULONGEST ranges_base ()
   {
-    struct attribute *attr;
-    attr = attr (DW_AT_rnglists_base);
-    if (attr == nullptr)
-      attr = attr (DW_AT_GNU_ranges_base);
-    if (attr == nullptr)
-      return 0;
-    return DW_UNSND (attr);
+    for (unsigned i = 0; i < num_attrs; ++i)
+      if (attrs[i].name == DW_AT_rnglists_base
+	  || attrs[i].name == DW_AT_GNU_ranges_base)
+	{
+	  /* If both exist, just use the first one.  */
+	  return DW_UNSND (&attrs[i]);
+	}
+    return 0;
   }
 
 
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 21/22] Move DWARF-constant stringifying code to new file
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (19 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 20/22] Rewrite new die_info methods Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-22 18:45 ` [PATCH 22/22] Change two functions to be methods on struct attribute Tom Tromey
  2020-03-24 13:34 ` [PATCH 00/22] More splitting of dwarf2/read.c Simon Marchi
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This moves the DWARF debugging functions that stringify various
constants to a new file, dwarf2/stringify.c.

gdb/ChangeLog
2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.c (dwarf_unit_type_name, dwarf_tag_name)
	(dwarf_attr_name, dwarf_form_name, dwarf_bool_name)
	(dwarf_type_encoding_name): Move to stringify.c.
	* Makefile.in (COMMON_SFILES): Add dwarf2/stringify.c.
	* dwarf2/stringify.c: New file.
	* dwarf2/stringify.h: New file.
---
 gdb/ChangeLog          |   9 ++++
 gdb/Makefile.in        |   1 +
 gdb/dwarf2/read.c      |  94 +--------------------------------
 gdb/dwarf2/stringify.c | 114 +++++++++++++++++++++++++++++++++++++++++
 gdb/dwarf2/stringify.h |  38 ++++++++++++++
 5 files changed, 163 insertions(+), 93 deletions(-)
 create mode 100644 gdb/dwarf2/stringify.c
 create mode 100644 gdb/dwarf2/stringify.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index f66affd3e5f..bc3ef695bbd 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1016,6 +1016,7 @@ COMMON_SFILES = \
 	dwarf2/macro.c \
 	dwarf2/read.c \
 	dwarf2/section.c \
+	dwarf2/stringify.c \
 	eval.c \
 	event-loop.c \
 	event-top.c \
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 9e7152d03e6..87305ec3688 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -40,6 +40,7 @@
 #include "dwarf2/dwz.h"
 #include "dwarf2/macro.h"
 #include "dwarf2/die.h"
+#include "dwarf2/stringify.h"
 #include "bfd.h"
 #include "elf-bfd.h"
 #include "symtab.h"
@@ -1406,16 +1407,6 @@ static const char *dwarf2_physname (const char *name, struct die_info *die,
 static struct die_info *dwarf2_extension (struct die_info *die,
 					  struct dwarf2_cu **);
 
-static const char *dwarf_tag_name (unsigned int);
-
-static const char *dwarf_attr_name (unsigned int);
-
-static const char *dwarf_form_name (unsigned int);
-
-static const char *dwarf_bool_name (unsigned int);
-
-static const char *dwarf_type_encoding_name (unsigned int);
-
 static void dump_die_shallow (struct ui_file *, int indent, struct die_info *);
 
 static void dump_die_for_error (struct die_info *);
@@ -21336,89 +21327,6 @@ dwarf2_extension (struct die_info *die, struct dwarf2_cu **ext_cu)
   return follow_die_ref (die, attr, ext_cu);
 }
 
-/* A convenience function that returns an "unknown" DWARF name,
-   including the value of V.  STR is the name of the entity being
-   printed, e.g., "TAG".  */
-
-static const char *
-dwarf_unknown (const char *str, unsigned v)
-{
-  char *cell = get_print_cell ();
-  xsnprintf (cell, PRINT_CELL_SIZE, "DW_%s_<unknown: %u>", str, v);
-  return cell;
-}
-
-/* Convert a DIE tag into its string name.  */
-
-static const char *
-dwarf_tag_name (unsigned tag)
-{
-  const char *name = get_DW_TAG_name (tag);
-
-  if (name == NULL)
-    return dwarf_unknown ("TAG", tag);
-
-  return name;
-}
-
-/* Convert a DWARF attribute code into its string name.  */
-
-static const char *
-dwarf_attr_name (unsigned attr)
-{
-  const char *name;
-
-#ifdef MIPS /* collides with DW_AT_HP_block_index */
-  if (attr == DW_AT_MIPS_fde)
-    return "DW_AT_MIPS_fde";
-#else
-  if (attr == DW_AT_HP_block_index)
-    return "DW_AT_HP_block_index";
-#endif
-
-  name = get_DW_AT_name (attr);
-
-  if (name == NULL)
-    return dwarf_unknown ("AT", attr);
-
-  return name;
-}
-
-/* Convert a DWARF value form code into its string name.  */
-
-static const char *
-dwarf_form_name (unsigned form)
-{
-  const char *name = get_DW_FORM_name (form);
-
-  if (name == NULL)
-    return dwarf_unknown ("FORM", form);
-
-  return name;
-}
-
-static const char *
-dwarf_bool_name (unsigned mybool)
-{
-  if (mybool)
-    return "TRUE";
-  else
-    return "FALSE";
-}
-
-/* Convert a DWARF type code into its string name.  */
-
-static const char *
-dwarf_type_encoding_name (unsigned enc)
-{
-  const char *name = get_DW_ATE_name (enc);
-
-  if (name == NULL)
-    return dwarf_unknown ("ATE", enc);
-
-  return name;
-}
-
 static void
 dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
 {
diff --git a/gdb/dwarf2/stringify.c b/gdb/dwarf2/stringify.c
new file mode 100644
index 00000000000..0cdefe81081
--- /dev/null
+++ b/gdb/dwarf2/stringify.c
@@ -0,0 +1,114 @@
+/* DWARF stringify code
+
+   Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+   Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
+   Inc.  with support from Florida State University (under contract
+   with the Ada Joint Program Office), and Silicon Graphics, Inc.
+   Initial contribution by Brent Benson, Harris Computer Systems, Inc.,
+   based on Fred Fish's (Cygnus Support) implementation of DWARF 1
+   support.
+
+   This file is part of GDB.
+
+   This program 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.
+
+   This program 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/>.  */
+
+#include "defs.h"
+#include "dwarf2.h"
+#include "dwarf2/stringify.h"
+
+/* A convenience function that returns an "unknown" DWARF name,
+   including the value of V.  STR is the name of the entity being
+   printed, e.g., "TAG".  */
+
+static const char *
+dwarf_unknown (const char *str, unsigned v)
+{
+  char *cell = get_print_cell ();
+  xsnprintf (cell, PRINT_CELL_SIZE, "DW_%s_<unknown: %u>", str, v);
+  return cell;
+}
+
+/* See stringify.h.  */
+
+const char *
+dwarf_tag_name (unsigned tag)
+{
+  const char *name = get_DW_TAG_name (tag);
+
+  if (name == NULL)
+    return dwarf_unknown ("TAG", tag);
+
+  return name;
+}
+
+/* See stringify.h.  */
+
+const char *
+dwarf_attr_name (unsigned attr)
+{
+  const char *name;
+
+#ifdef MIPS /* collides with DW_AT_HP_block_index */
+  if (attr == DW_AT_MIPS_fde)
+    return "DW_AT_MIPS_fde";
+#else
+  if (attr == DW_AT_HP_block_index)
+    return "DW_AT_HP_block_index";
+#endif
+
+  name = get_DW_AT_name (attr);
+
+  if (name == NULL)
+    return dwarf_unknown ("AT", attr);
+
+  return name;
+}
+
+/* See stringify.h.  */
+
+const char *
+dwarf_form_name (unsigned form)
+{
+  const char *name = get_DW_FORM_name (form);
+
+  if (name == NULL)
+    return dwarf_unknown ("FORM", form);
+
+  return name;
+}
+
+/* See stringify.h.  */
+
+const char *
+dwarf_bool_name (unsigned mybool)
+{
+  if (mybool)
+    return "TRUE";
+  else
+    return "FALSE";
+}
+
+/* See stringify.h.  */
+
+const char *
+dwarf_type_encoding_name (unsigned enc)
+{
+  const char *name = get_DW_ATE_name (enc);
+
+  if (name == NULL)
+    return dwarf_unknown ("ATE", enc);
+
+  return name;
+}
diff --git a/gdb/dwarf2/stringify.h b/gdb/dwarf2/stringify.h
new file mode 100644
index 00000000000..d3b3d2c191a
--- /dev/null
+++ b/gdb/dwarf2/stringify.h
@@ -0,0 +1,38 @@
+/* DWARF stringify code
+
+   Copyright (C) 2003-2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program 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.
+
+   This program 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/>.  */
+
+#ifndef GDB_DWARF2_STRINGIFY_H
+#define GDB_DWARF2_STRINGIFY_H
+
+/* Convert a DIE tag into its string name.  */
+extern const char *dwarf_tag_name (unsigned tag);
+
+/* Convert a DWARF attribute code into its string name.  */
+extern const char *dwarf_attr_name (unsigned attr);
+
+/* Convert a DWARF value form code into its string name.  */
+extern const char *dwarf_form_name (unsigned form);
+
+/* Convert a boolean to a string form.  */
+extern const char *dwarf_bool_name (unsigned mybool);
+
+/* Convert a DWARF type code into its string name.  */
+extern const char *dwarf_type_encoding_name (unsigned enc);
+
+#endif /* GDB_DWARF2_STRINGIFY_H */
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 22/22] Change two functions to be methods on struct attribute
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (20 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 21/22] Move DWARF-constant stringifying code to new file Tom Tromey
@ 2020-03-22 18:45 ` Tom Tromey
  2020-03-24 13:34 ` [PATCH 00/22] More splitting of dwarf2/read.c Simon Marchi
  22 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-22 18:45 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes dwarf2_get_ref_die_offset and
dwarf2_get_attr_constant_value to be methods on struct attribute.

2020-03-22  Tom Tromey  <tom@tromey.com>

	* dwarf2/read.c (handle_data_member_location, dwarf2_add_field)
	(mark_common_block_symbol_computed, read_tag_string_type)
	(attr_to_dynamic_prop, read_subrange_type): Update.
	(dwarf2_get_ref_die_offset, dwarf2_get_attr_constant_value): Move
	to be methods on struct attribute.
	(skip_one_die, process_imported_unit_die, read_namespace_alias)
	(read_call_site_scope, partial_die_info::read)
	(partial_die_info::read, lookup_die_type, follow_die_ref):
	Update.
	* dwarf2/attribute.c (attribute::get_ref_die_offset): New method,
	from dwarf2_get_ref_die_offset.
	(attribute::constant_value): New method, from
	dwarf2_get_attr_constant_value.
	* dwarf2/attribute.h (struct attribute) <get_ref_die_offset>:
	Declare method.
	<constant_value>: New method.
---
 gdb/ChangeLog          | 19 ++++++++++
 gdb/dwarf2/attribute.c | 37 ++++++++++++++++++++
 gdb/dwarf2/attribute.h | 12 +++++++
 gdb/dwarf2/read.c      | 78 ++++++++++--------------------------------
 4 files changed, 86 insertions(+), 60 deletions(-)

diff --git a/gdb/dwarf2/attribute.c b/gdb/dwarf2/attribute.c
index 6efff3e2c0a..0e5a8c8f536 100644
--- a/gdb/dwarf2/attribute.c
+++ b/gdb/dwarf2/attribute.c
@@ -26,6 +26,8 @@
 
 #include "defs.h"
 #include "dwarf2/attribute.h"
+#include "dwarf2/stringify.h"
+#include "complaints.h"
 
 /* See attribute.h.  */
 
@@ -119,3 +121,38 @@ attribute::form_is_ref () const
       return false;
     }
 }
+
+/* See attribute.h.  */
+
+sect_offset
+attribute::get_ref_die_offset () const
+{
+  if (form_is_ref ())
+    return (sect_offset) DW_UNSND (this);
+
+  complaint (_("unsupported die ref attribute form: '%s'"),
+	     dwarf_form_name (form));
+  return {};
+}
+
+/* See attribute.h.  */
+
+LONGEST
+attribute::constant_value (int default_value) const
+{
+  if (form == DW_FORM_sdata || form == DW_FORM_implicit_const)
+    return DW_SND (this);
+  else if (form == DW_FORM_udata
+	   || form == DW_FORM_data1
+	   || form == DW_FORM_data2
+	   || form == DW_FORM_data4
+	   || form == DW_FORM_data8)
+    return DW_UNSND (this);
+  else
+    {
+      /* For DW_FORM_data16 see attribute::form_is_constant.  */
+      complaint (_("Attribute value is not a constant (%s)"),
+		 dwarf_form_name (form));
+      return default_value;
+    }
+}
diff --git a/gdb/dwarf2/attribute.h b/gdb/dwarf2/attribute.h
index c2602310715..483b805433b 100644
--- a/gdb/dwarf2/attribute.h
+++ b/gdb/dwarf2/attribute.h
@@ -28,6 +28,7 @@
 #define GDB_DWARF2_ATTRIBUTE_H
 
 #include "dwarf2.h"
+#include "gdbtypes.h"
 
 /* Blocks are a bunch of untyped bytes.  */
 struct dwarf_block
@@ -84,6 +85,17 @@ struct attribute
 
   bool form_is_block () const;
 
+  /* Return DIE offset of this attribute.  Return 0 with complaint if
+     the attribute is not of the required kind.  */
+
+  sect_offset get_ref_die_offset () const;
+
+  /* Return the constant value held by this attribute.  Return
+     DEFAULT_VALUE if the value held by the attribute is not
+     constant.  */
+
+  LONGEST constant_value (int default_value) const;
+
 
   ENUM_BITFIELD(dwarf_attribute) name : 16;
   ENUM_BITFIELD(dwarf_form) form : 15;
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 87305ec3688..73df64d15fd 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1419,10 +1419,6 @@ static void dump_die_1 (struct ui_file *, int level, int max_level,
 static void store_in_ref_table (struct die_info *,
 				struct dwarf2_cu *);
 
-static sect_offset dwarf2_get_ref_die_offset (const struct attribute *);
-
-static LONGEST dwarf2_get_attr_constant_value (const struct attribute *, int);
-
 static struct die_info *follow_die_ref_or_sig (struct die_info *,
 					       const struct attribute *,
 					       struct dwarf2_cu **);
@@ -8476,7 +8472,7 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
 	    complaint (_("ignoring absolute DW_AT_sibling"));
 	  else
 	    {
-	      sect_offset off = dwarf2_get_ref_die_offset (&attr);
+	      sect_offset off = attr.get_ref_die_offset ();
 	      const gdb_byte *sibling_ptr = buffer + to_underlying (off);
 
 	      if (sibling_ptr < info_ptr)
@@ -9643,7 +9639,7 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
   attr = dwarf2_attr (die, DW_AT_import, cu);
   if (attr != NULL)
     {
-      sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
+      sect_offset sect_off = attr->get_ref_die_offset ();
       bool is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
       dwarf2_per_cu_data *per_cu
 	= dwarf2_find_containing_comp_unit (sect_off, is_dwz,
@@ -10296,7 +10292,7 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
       if (attr != NULL)
 	{
 	  struct type *type;
-	  sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
+	  sect_offset sect_off = attr->get_ref_die_offset ();
 
 	  type = get_die_type_at_offset (sect_off, cu->per_cu);
 	  if (type != NULL && TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
@@ -13224,8 +13220,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
 	{
 	  parameter->kind = CALL_SITE_PARAMETER_PARAM_OFFSET;
 
-	  sect_offset sect_off
-	    = (sect_offset) dwarf2_get_ref_die_offset (origin);
+	  sect_offset sect_off = origin->get_ref_die_offset ();
 	  if (!cu->header.offset_in_cu_p (sect_off))
 	    {
 	      /* As DW_OP_GNU_parameter_ref uses CU-relative offset this
@@ -14059,7 +14054,7 @@ handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu,
 	 so if we see it, we can assume that a constant form is really
 	 a constant and not a section offset.  */
       if (attr->form_is_constant ())
-	*offset = dwarf2_get_attr_constant_value (attr, 0);
+	*offset = attr->constant_value (0);
       else if (attr->form_is_section_offset ())
 	dwarf2_complex_location_expr_complaint ();
       else if (attr->form_is_block ())
@@ -14186,7 +14181,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
       attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
       if (attr != NULL)
 	SET_FIELD_BITPOS (*fp, (FIELD_BITPOS (*fp)
-				+ dwarf2_get_attr_constant_value (attr, 0)));
+				+ attr->constant_value (0)));
 
       /* Get name of field.  */
       fieldname = dwarf2_name (die, cu);
@@ -15860,7 +15855,7 @@ mark_common_block_symbol_computed (struct symbol *sym,
 
   if (member_loc->form_is_constant ())
     {
-      offset = dwarf2_get_attr_constant_value (member_loc, 0);
+      offset = member_loc->constant_value (0);
       baton->size += 1 /* DW_OP_addr */ + cu->header.addr_size;
     }
   else
@@ -16452,7 +16447,7 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
 	{
 	  /* Pass 0 as the default as we know this attribute is constant
 	     and the default value will not be returned.  */
-	  LONGEST sz = dwarf2_get_attr_constant_value (len, 0);
+	  LONGEST sz = len->constant_value (0);
 	  prop_type = cu->per_cu->int_type (sz, true);
 	}
       else
@@ -16474,12 +16469,12 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
 	 indirection.  There's no need to create a dynamic property in this
 	 case.  Pass 0 for the default value as we know it will not be
 	 returned in this case.  */
-      length = dwarf2_get_attr_constant_value (attr, 0);
+      length = attr->constant_value (0);
     }
   else if ((attr = dwarf2_attr (die, DW_AT_byte_size, cu)) != nullptr)
     {
       /* We don't currently support non-constant byte sizes for strings.  */
-      length = dwarf2_get_attr_constant_value (attr, 1);
+      length = attr->constant_value (1);
     }
   else
     {
@@ -17058,7 +17053,7 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
     }
   else if (attr->form_is_constant ())
     {
-      prop->data.const_val = dwarf2_get_attr_constant_value (attr, 0);
+      prop->data.const_val = attr->constant_value (0);
       prop->kind = PROP_CONST;
     }
   else
@@ -17236,7 +17231,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
   LONGEST bias = 0;
   struct attribute *bias_attr = dwarf2_attr (die, DW_AT_GNU_bias, cu);
   if (bias_attr != nullptr && bias_attr->form_is_constant ())
-    bias = dwarf2_get_attr_constant_value (bias_attr, 0);
+    bias = bias_attr->constant_value (0);
 
   /* Normally, the DWARF producers are expected to use a signed
      constant form (Eg. DW_FORM_sdata) to express negative bounds.
@@ -17942,7 +17937,7 @@ partial_die_info::read (const struct die_reader_specs *reader,
 	case DW_AT_specification:
 	case DW_AT_extension:
 	  has_specification = 1;
-	  spec_offset = dwarf2_get_ref_die_offset (&attr);
+	  spec_offset = attr.get_ref_die_offset ();
 	  spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
 				   || cu->per_cu->is_dwz);
 	  break;
@@ -17954,7 +17949,7 @@ partial_die_info::read (const struct die_reader_specs *reader,
 	  else
 	    {
 	      const gdb_byte *buffer = reader->buffer;
-	      sect_offset off = dwarf2_get_ref_die_offset (&attr);
+	      sect_offset off = attr.get_ref_die_offset ();
 	      const gdb_byte *sibling_ptr = buffer + to_underlying (off);
 
 	      if (sibling_ptr < info_ptr)
@@ -17999,7 +17994,7 @@ partial_die_info::read (const struct die_reader_specs *reader,
 	case DW_AT_import:
 	  if (tag == DW_TAG_imported_unit)
 	    {
-	      d.sect_off = dwarf2_get_ref_die_offset (&attr);
+	      d.sect_off = attr.get_ref_die_offset ();
 	      is_dwz = (attr.form == DW_FORM_GNU_ref_alt
 				  || cu->per_cu->is_dwz);
 	    }
@@ -20703,7 +20698,7 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
   if (attr->form == DW_FORM_GNU_ref_alt)
     {
       struct dwarf2_per_cu_data *per_cu;
-      sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
+      sect_offset sect_off = attr->get_ref_die_offset ();
 
       per_cu = dwarf2_find_containing_comp_unit (sect_off, 1,
 						 dwarf2_per_objfile);
@@ -20711,7 +20706,7 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
     }
   else if (attr->form_is_ref ())
     {
-      sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
+      sect_offset sect_off = attr->get_ref_die_offset ();
 
       this_type = get_die_type_at_offset (sect_off, cu->per_cu);
     }
@@ -21513,43 +21508,6 @@ store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu)
   *slot = die;
 }
 
-/* Return DIE offset of ATTR.  Return 0 with complaint if ATTR is not of the
-   required kind.  */
-
-static sect_offset
-dwarf2_get_ref_die_offset (const struct attribute *attr)
-{
-  if (attr->form_is_ref ())
-    return (sect_offset) DW_UNSND (attr);
-
-  complaint (_("unsupported die ref attribute form: '%s'"),
-	     dwarf_form_name (attr->form));
-  return {};
-}
-
-/* Return the constant value held by ATTR.  Return DEFAULT_VALUE if
- * the value held by the attribute is not constant.  */
-
-static LONGEST
-dwarf2_get_attr_constant_value (const struct attribute *attr, int default_value)
-{
-  if (attr->form == DW_FORM_sdata || attr->form == DW_FORM_implicit_const)
-    return DW_SND (attr);
-  else if (attr->form == DW_FORM_udata
-           || attr->form == DW_FORM_data1
-           || attr->form == DW_FORM_data2
-           || attr->form == DW_FORM_data4
-           || attr->form == DW_FORM_data8)
-    return DW_UNSND (attr);
-  else
-    {
-      /* For DW_FORM_data16 see attribute::form_is_constant.  */
-      complaint (_("Attribute value is not a constant (%s)"),
-                 dwarf_form_name (attr->form));
-      return default_value;
-    }
-}
-
 /* Follow reference or signature attribute ATTR of SRC_DIE.
    On entry *REF_CU is the CU of SRC_DIE.
    On exit *REF_CU is the CU of the result.  */
@@ -21640,7 +21598,7 @@ static struct die_info *
 follow_die_ref (struct die_info *src_die, const struct attribute *attr,
 		struct dwarf2_cu **ref_cu)
 {
-  sect_offset sect_off = dwarf2_get_ref_die_offset (attr);
+  sect_offset sect_off = attr->get_ref_die_offset ();
   struct dwarf2_cu *cu = *ref_cu;
   struct die_info *die;
 
-- 
2.17.2


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 04/22] Split dwarf_decode_macros into two overloads
  2020-03-22 18:45 ` [PATCH 04/22] Split dwarf_decode_macros into two overloads Tom Tromey
@ 2020-03-23 16:13   ` Christian Biesinger
  2020-03-26  2:09     ` Tom Tromey
  2020-03-24  1:58   ` Simon Marchi
  1 sibling, 1 reply; 32+ messages in thread
From: Christian Biesinger @ 2020-03-23 16:13 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Sun, Mar 22, 2020 at 1:45 PM Tom Tromey <tom@tromey.com> wrote:
>
> This splits dwarf_decode_macros into two overloads -- one that's
> suitable for splitting into a separate file, and one that finds the
> correct section and should remain in dwarf2/read.c.
>
> gdb/ChangeLog
> 2020-03-22  Tom Tromey  <tom@tromey.com>
>
>         * dwarf2/read.c (dwarf_decode_macros): Split into two overloads.
> ---
>  gdb/ChangeLog     |   4 ++
>  gdb/dwarf2/read.c | 102 +++++++++++++++++++++++++++-------------------
>  2 files changed, 63 insertions(+), 43 deletions(-)
>
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index 1410dd48a2f..2d126461c74 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -23753,56 +23753,18 @@ dwarf_decode_macro_bytes (struct dwarf2_per_objfile *dwarf2_per_objfile,
>  }
>
>  static void
> -dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
> -                     int section_is_gnu)
> +dwarf_decode_macros (struct dwarf2_per_objfile *dwarf2_per_objfile,
> +                    buildsym_compunit *builder, dwarf2_section_info *section,
> +                    struct line_header *lh, unsigned int offset_size,
> +                    unsigned int offset, int section_is_gnu)
>  {
> -  struct dwarf2_per_objfile *dwarf2_per_objfile
> -    = cu->per_cu->dwarf2_per_objfile;
> -  struct objfile *objfile = dwarf2_per_objfile->objfile;
> -  struct line_header *lh = cu->line_header;
>    bfd *abfd;
>    const gdb_byte *mac_ptr, *mac_end;
>    struct macro_source_file *current_file = 0;
>    enum dwarf_macro_record_type macinfo_type;
> -  unsigned int offset_size = cu->header.offset_size;
>    const gdb_byte *opcode_definitions[256];
>    void **slot;
> -  struct dwarf2_section_info *section;
> -  const char *section_name;
>
> -  if (cu->dwo_unit != NULL)
> -    {
> -      if (section_is_gnu)
> -       {
> -         section = &cu->dwo_unit->dwo_file->sections.macro;
> -         section_name = ".debug_macro.dwo";
> -       }
> -      else
> -       {
> -         section = &cu->dwo_unit->dwo_file->sections.macinfo;
> -         section_name = ".debug_macinfo.dwo";
> -       }
> -    }
> -  else
> -    {
> -      if (section_is_gnu)
> -       {
> -         section = &dwarf2_per_objfile->macro;
> -         section_name = ".debug_macro";
> -       }
> -      else
> -       {
> -         section = &dwarf2_per_objfile->macinfo;
> -         section_name = ".debug_macinfo";
> -       }
> -    }
> -
> -  section->read (objfile);
> -  if (section->buffer == NULL)
> -    {
> -      complaint (_("missing %s section"), section_name);
> -      return;
> -    }
>    abfd = section->get_bfd_owner ();
>
>    /* First pass: Find the name of the base filename.
> @@ -23827,7 +23789,6 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
>        return;
>      }
>
> -  buildsym_compunit *builder = cu->get_builder ();
>    do
>      {
>        /* Do we at least have room for a macinfo type byte?  */
> @@ -23949,6 +23910,61 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
>                             include_hash.get ());
>  }
>
> +/* An overload of dwarf_decode_macros that finds the correct section
> +   and ensures it is read in before calling the other overload.  */
> +
> +static void
> +dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
> +                     int section_is_gnu)
> +{
> +  struct dwarf2_per_objfile *dwarf2_per_objfile
> +    = cu->per_cu->dwarf2_per_objfile;
> +  struct objfile *objfile = dwarf2_per_objfile->objfile;
> +  struct line_header *lh = cu->line_header;
> +  unsigned int offset_size = cu->header.offset_size;
> +  struct dwarf2_section_info *section;
> +  const char *section_name;
> +
> +  if (cu->dwo_unit != NULL)

Since you're touching these lines, want to change NULL to nullptr? (in
a few places)

Christian

> +    {
> +      if (section_is_gnu)
> +       {
> +         section = &cu->dwo_unit->dwo_file->sections.macro;
> +         section_name = ".debug_macro.dwo";
> +       }
> +      else
> +       {
> +         section = &cu->dwo_unit->dwo_file->sections.macinfo;
> +         section_name = ".debug_macinfo.dwo";
> +       }
> +    }
> +  else
> +    {
> +      if (section_is_gnu)
> +       {
> +         section = &dwarf2_per_objfile->macro;
> +         section_name = ".debug_macro";
> +       }
> +      else
> +       {
> +         section = &dwarf2_per_objfile->macinfo;
> +         section_name = ".debug_macinfo";
> +       }
> +    }
> +
> +  section->read (objfile);
> +  if (section->buffer == NULL)
> +    {
> +      complaint (_("missing %s section"), section_name);
> +      return;
> +    }
> +
> +  buildsym_compunit *builder = cu->get_builder ();
> +
> +  dwarf_decode_macros (dwarf2_per_objfile, builder, section, lh,
> +                      offset_size, offset, section_is_gnu);
> +}
> +
>  /* Return the .debug_loc section to use for CU.
>     For DWO files use .debug_loc.dwo.  */
>
> --
> 2.17.2
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 19/22] Change two more functions to be methods on die_info
  2020-03-22 18:45 ` [PATCH 19/22] Change two more functions to be methods on die_info Tom Tromey
@ 2020-03-23 19:07   ` Christian Biesinger
  2020-03-26  2:17     ` Tom Tromey
  0 siblings, 1 reply; 32+ messages in thread
From: Christian Biesinger @ 2020-03-23 19:07 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Sun, Mar 22, 2020 at 1:46 PM Tom Tromey <tom@tromey.com> wrote:
>
> This changes lookup_addr_base and lookup_ranges_base to be methods on
> die_info.
>
> gdb/ChangeLog
> 2020-03-22  Tom Tromey  <tom@tromey.com>
>
>         * dwarf2/die.h (struct die_info) <addr_base, ranges_base>: New
>         methods.
>         * dwarf2/read.c (lookup_addr_base): Move to die.h.
>         (lookup_ranges_base): Likewise.
>         (read_cutu_die_from_dwo, read_full_die_1): Update.
> ---
>  gdb/ChangeLog     |  8 ++++++++
>  gdb/dwarf2/die.h  | 28 ++++++++++++++++++++++++++++
>  gdb/dwarf2/read.c | 34 +++-------------------------------
>  3 files changed, 39 insertions(+), 31 deletions(-)
>
> diff --git a/gdb/dwarf2/die.h b/gdb/dwarf2/die.h
> index 3a265b7df03..5673ae261ac 100644
> --- a/gdb/dwarf2/die.h
> +++ b/gdb/dwarf2/die.h
> @@ -33,6 +33,34 @@ struct die_info
>      return NULL;
>    }
>
> +  /* Return the address base of the compile unit, which, if exists, is
> +     stored either at the attribute DW_AT_GNU_addr_base, or
> +     DW_AT_addr_base.  */
> +  gdb::optional<ULONGEST> addr_base ()
> +  {
> +    struct attribute *attr;
> +    attr = attr (DW_AT_addr_base);

I get that you want to avoid making code changes while moving code but
I would really suggest merging these two lines at least (similar in
the next function)

> +    if (attr == nullptr)
> +      attr = attr (DW_AT_GNU_addr_base);
> +    if (attr == nullptr)
> +      return gdb::optional<ULONGEST> ();
> +    return DW_UNSND (attr);
> +  }
> +
> +  /* Return range lists base of the compile unit, which, if exists, is
> +     stored either at the attribute DW_AT_rnglists_base or
> +     DW_AT_GNU_ranges_base.  */
> +  ULONGEST ranges_base ()
> +  {
> +    struct attribute *attr;
> +    attr = attr (DW_AT_rnglists_base);
> +    if (attr == nullptr)
> +      attr = attr (DW_AT_GNU_ranges_base);
> +    if (attr == nullptr)
> +      return 0;
> +    return DW_UNSND (attr);
> +  }
> +
>
>    /* DWARF-2 tag for this DIE.  */
>    ENUM_BITFIELD(dwarf_tag) tag : 16;
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index 9d744ab0825..9e7152d03e6 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -6386,34 +6386,6 @@ lookup_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
>      }
>  }
>
> -/* Return the address base of the compile unit, which, if exists, is stored
> -   either at the attribute DW_AT_GNU_addr_base, or DW_AT_addr_base.  */
> -static gdb::optional<ULONGEST>
> -lookup_addr_base (struct die_info *comp_unit_die)
> -{
> -  struct attribute *attr;
> -  attr = comp_unit_die->attr (DW_AT_addr_base);
> -  if (attr == nullptr)
> -    attr = comp_unit_die->attr (DW_AT_GNU_addr_base);
> -  if (attr == nullptr)
> -    return gdb::optional<ULONGEST> ();
> -  return DW_UNSND (attr);
> -}
> -
> -/* Return range lists base of the compile unit, which, if exists, is stored
> -   either at the attribute DW_AT_rnglists_base or DW_AT_GNU_ranges_base.  */
> -static ULONGEST
> -lookup_ranges_base (struct die_info *comp_unit_die)
> -{
> -  struct attribute *attr;
> -  attr = comp_unit_die->attr (DW_AT_rnglists_base);
> -  if (attr == nullptr)
> -    attr = comp_unit_die->attr (DW_AT_GNU_ranges_base);
> -  if (attr == nullptr)
> -    return 0;
> -  return DW_UNSND (attr);
> -}
> -
>  /* Low level DIE reading support.  */
>
>  /* Initialize a die_reader_specs struct from a dwarf2_cu struct.  */
> @@ -6502,12 +6474,12 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu,
>        ranges = dwarf2_attr (stub_comp_unit_die, DW_AT_ranges, cu);
>        comp_dir = dwarf2_attr (stub_comp_unit_die, DW_AT_comp_dir, cu);
>
> -      cu->addr_base = lookup_addr_base (stub_comp_unit_die);
> +      cu->addr_base = stub_comp_unit_die->addr_base ();
>
>        /* There should be a DW_AT_rnglists_base (DW_AT_GNU_ranges_base) attribute
>          here (if needed). We need the value before we can process
>          DW_AT_ranges.  */
> -      cu->ranges_base = lookup_ranges_base (stub_comp_unit_die);
> +      cu->ranges_base = stub_comp_unit_die->ranges_base ();
>      }
>    else if (stub_comp_dir != NULL)
>      {
> @@ -17538,7 +17510,7 @@ read_full_die_1 (const struct die_reader_specs *reader,
>    if (attr != nullptr)
>      cu->str_offsets_base = DW_UNSND (attr);
>
> -  auto maybe_addr_base = lookup_addr_base(die);
> +  auto maybe_addr_base = die->addr_base ();
>    if (maybe_addr_base.has_value ())
>      cu->addr_base = *maybe_addr_base;
>    for (int index : indexes_that_need_reprocess)
> --
> 2.17.2
>

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 04/22] Split dwarf_decode_macros into two overloads
  2020-03-22 18:45 ` [PATCH 04/22] Split dwarf_decode_macros into two overloads Tom Tromey
  2020-03-23 16:13   ` Christian Biesinger
@ 2020-03-24  1:58   ` Simon Marchi
  2020-03-26  2:10     ` Tom Tromey
  1 sibling, 1 reply; 32+ messages in thread
From: Simon Marchi @ 2020-03-24  1:58 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 2020-03-22 2:45 p.m., Tom Tromey wrote:
> @@ -23949,6 +23910,61 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
>  			    include_hash.get ());
>  }
>  
> +/* An overload of dwarf_decode_macros that finds the correct section
> +   and ensures it is read in before calling the other overload.  */
> +
> +static void
> +dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
> +                     int section_is_gnu)

Spaces -> tabs.

Simon

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 13/22] Convert read_indirect_line_string to a method
  2020-03-22 18:45 ` [PATCH 13/22] Convert read_indirect_line_string to a method Tom Tromey
@ 2020-03-24  2:49   ` Simon Marchi
  0 siblings, 0 replies; 32+ messages in thread
From: Simon Marchi @ 2020-03-24  2:49 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 2020-03-22 2:45 p.m., Tom Tromey wrote:
> @@ -18790,17 +18786,15 @@ read_indirect_string (struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *abfd,
>     BUF is assumed to be in a compilation unit described by CU_HEADER.
>     Return *BYTES_READ_PTR count of bytes read from BUF.  */
>  
> -static const char *
> -read_indirect_line_string (struct dwarf2_per_objfile *dwarf2_per_objfile,
> -			   bfd *abfd, const gdb_byte *buf,
> +const char *
> +dwarf2_per_objfile::read_line_string (const gdb_byte *buf,
>  			   const struct comp_unit_head *cu_header,
>  			   unsigned int *bytes_read_ptr)

The comment above this definition should become

  /* See read.h.  */

Simon

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 00/22] More splitting of dwarf2/read.c
  2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
                   ` (21 preceding siblings ...)
  2020-03-22 18:45 ` [PATCH 22/22] Change two functions to be methods on struct attribute Tom Tromey
@ 2020-03-24 13:34 ` Simon Marchi
  2020-03-26 15:32   ` Tom Tromey
  22 siblings, 1 reply; 32+ messages in thread
From: Simon Marchi @ 2020-03-24 13:34 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 2020-03-22 2:45 p.m., Tom Tromey wrote:
> One goal of mine is to split up the DWARF reader code into many
> smaller, more self-contained files.  I think this will make the code
> easier to read and to work on; and also let us tease out (and repair)
> hidden dependencies.  This latter part is desirable because, in the
> longer run, I'd like to parallelize DWARF reading.
> 
> So, here is round 2 of splitting.
> 
> The main change here is that the macro-reading code is moved to its
> own file.  It's almost possible, after this, to scan macros in a
> worker thread.  (However, dwz file handling, and the recent move to
> sharing a bcache, interfere with this.)
> 
> Some smaller utility functions are also moved into other files as
> well.
> 
> Let me know what you think,
> Tom
> 
> 

Other than the little nits I pointed out, this all looks good to me,
thanks for doing this!

Simon

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 04/22] Split dwarf_decode_macros into two overloads
  2020-03-23 16:13   ` Christian Biesinger
@ 2020-03-26  2:09     ` Tom Tromey
  0 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-26  2:09 UTC (permalink / raw)
  To: Christian Biesinger; +Cc: Tom Tromey, gdb-patches

>>>>> "Christian" == Christian Biesinger <cbiesinger@google.com> writes:

>> +  if (cu->dwo_unit != NULL)

Christian> Since you're touching these lines, want to change NULL to nullptr? (in
Christian> a few places)

I made this change.

Tom

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 04/22] Split dwarf_decode_macros into two overloads
  2020-03-24  1:58   ` Simon Marchi
@ 2020-03-26  2:10     ` Tom Tromey
  0 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-26  2:10 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:

>> +static void
>> +dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
>> +                     int section_is_gnu)

Simon> Spaces -> tabs.

Done.

Tom

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 19/22] Change two more functions to be methods on die_info
  2020-03-23 19:07   ` Christian Biesinger
@ 2020-03-26  2:17     ` Tom Tromey
  0 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-26  2:17 UTC (permalink / raw)
  To: Christian Biesinger; +Cc: Tom Tromey, gdb-patches

>>>>> "Christian" == Christian Biesinger <cbiesinger@google.com> writes:

>> +    attr = attr (DW_AT_addr_base);

Christian> I get that you want to avoid making code changes while moving code but
Christian> I would really suggest merging these two lines at least (similar in
Christian> the next function)

This line doesn't even compile actually.
I must have only built this after writing the next patch?  Ugh.

Anyway I changed it as you suggest and used this->attr, which I normally
wouldn't do, but thought was ok since this patch is just a transition.

Tom

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 00/22] More splitting of dwarf2/read.c
  2020-03-24 13:34 ` [PATCH 00/22] More splitting of dwarf2/read.c Simon Marchi
@ 2020-03-26 15:32   ` Tom Tromey
  0 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2020-03-26 15:32 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:

Simon> Other than the little nits I pointed out, this all looks good to me,
Simon> thanks for doing this!

Thanks.  I fixed all of those, and I re-regression-tested the series on
x86-64 Fedora 28.  I'm checking it in now.

Tom

^ permalink raw reply	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2020-03-26 15:48 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-22 18:45 [PATCH 00/22] More splitting of dwarf2/read.c Tom Tromey
2020-03-22 18:45 ` [PATCH 01/22] Introduce dwarf2/dwz.h Tom Tromey
2020-03-22 18:45 ` [PATCH 02/22] Add dwz.c and dwz_file::read_string Tom Tromey
2020-03-22 18:45 ` [PATCH 03/22] Change dwarf_decode_macro_bytes calling convention Tom Tromey
2020-03-22 18:45 ` [PATCH 04/22] Split dwarf_decode_macros into two overloads Tom Tromey
2020-03-23 16:13   ` Christian Biesinger
2020-03-26  2:09     ` Tom Tromey
2020-03-24  1:58   ` Simon Marchi
2020-03-26  2:10     ` Tom Tromey
2020-03-22 18:45 ` [PATCH 05/22] Move dwarf2_section_buffer_overflow_complaint to dwarf2/section.c Tom Tromey
2020-03-22 18:45 ` [PATCH 06/22] Convert dwarf2_section_buffer_overflow_complaint to a method Tom Tromey
2020-03-22 18:45 ` [PATCH 07/22] Add dwarf2_section_info::read_string method Tom Tromey
2020-03-22 18:45 ` [PATCH 08/22] Move code to new file dwarf2/macro.c Tom Tromey
2020-03-22 18:45 ` [PATCH 09/22] Make some line_header methods const Tom Tromey
2020-03-22 18:45 ` [PATCH 10/22] Use a const line_header in macro reader Tom Tromey
2020-03-22 18:45 ` [PATCH 11/22] Use a const dwarf2_section_info " Tom Tromey
2020-03-22 18:45 ` [PATCH 12/22] Trivial fix in dwarf_decode_macro_bytes Tom Tromey
2020-03-22 18:45 ` [PATCH 13/22] Convert read_indirect_line_string to a method Tom Tromey
2020-03-24  2:49   ` Simon Marchi
2020-03-22 18:45 ` [PATCH 14/22] Move more code to line-header.c Tom Tromey
2020-03-22 18:45 ` [PATCH 15/22] Move die_info to new header Tom Tromey
2020-03-22 18:45 ` [PATCH 16/22] Remove dwarf2_cu::base_known Tom Tromey
2020-03-22 18:45 ` [PATCH 17/22] Change dwarf2_attr_no_follow to be a method Tom Tromey
2020-03-22 18:45 ` [PATCH 18/22] Remove sibling_die Tom Tromey
2020-03-22 18:45 ` [PATCH 19/22] Change two more functions to be methods on die_info Tom Tromey
2020-03-23 19:07   ` Christian Biesinger
2020-03-26  2:17     ` Tom Tromey
2020-03-22 18:45 ` [PATCH 20/22] Rewrite new die_info methods Tom Tromey
2020-03-22 18:45 ` [PATCH 21/22] Move DWARF-constant stringifying code to new file Tom Tromey
2020-03-22 18:45 ` [PATCH 22/22] Change two functions to be methods on struct attribute Tom Tromey
2020-03-24 13:34 ` [PATCH 00/22] More splitting of dwarf2/read.c Simon Marchi
2020-03-26 15:32   ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).