public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] Move code to new file dwarf2/macro.c
@ 2020-03-26 15:33 Tom Tromey
  0 siblings, 0 replies; only message in thread
From: Tom Tromey @ 2020-03-26 15:33 UTC (permalink / raw)
  To: gdb-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=c90ec28ae44ebf72d57d58439d02fc5aab90f1f6

commit c90ec28ae44ebf72d57d58439d02fc5aab90f1f6
Author: Tom Tromey <tom@tromey.com>
Date:   Thu Mar 26 09:28:08 2020 -0600

    Move code to new file dwarf2/macro.c
    
    This moves some more code out of dwarf2/read.c, introducing new files
    dwarf2/macro.c and dwarf2/macro.h.
    
    gdb/ChangeLog
    2020-03-26  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.

Diff:
---
 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(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 15e65eb2e02..70b58f22455 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2020-03-26  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.
+
 2020-03-26  Tom Tromey  <tom@tromey.com>
 
 	* dwarf2/section.h (struct dwarf2_section_info) <read_string>: New
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 fab5b94f0a7..29f3aeb7e70 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.  */


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-03-26 15:33 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-26 15:33 [binutils-gdb] Move code to new file dwarf2/macro.c 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).