[PATCH 01/24] Add -gcodeview debugging option

Mark Harmstone mark@harmstone.com
Sat Mar 20 16:26:29 GMT 2021


This is a series of patches to allow gcc to emit debugging information
in the PE-specific CodeView format, which allows Microsoft debuggers to
work with mingw EXEs. The format is semi-documented: Microsoft have
open-sourced some of their header files at
https://github.com/microsoft/microsoft-pdb, along with a program
cvdump.exe which outputs the textual form of the data.

This works by adding two new sections to every object file: .debug$T,
which contains the type definitions, and .debug$S, which is everything
else (line numbers, file checksums, symbols). The linker then merges
everything together, resolves any duplicate types etc., and outputs this
as a PDB file. Obviously this needs linker support to be useful - lld
does the job, or you can try my binutils patches at
https://github.com/maharmstone/binutils-gdb/tree/for-gcc.

It also needs support for the asm-pseudo directive .secidx, which
outputs the IMAGE_REL_AMD64_SECTION / IMAGE_REL_I386_SECTION PE
relocations. This is likewise not in mainstream binutils - you can
either try llvm-mc instead of gas, or my binutils repo above.

In terms of debuggers and the like, I've tested this successfully with
Visual Studio, windbg, radare2, and of course the aforementioned cvdump
- I don't think there's any other significant tools which use the
 format.

I've only tested this on x86 and amd64, as I've no idea how you go about
compiling Windows EXEs for arm or aarch64 with gcc, or if such a thing
is possible. The other architectures the format provides for are 16-bit
x86, alpha, mips, m68k, ppc, sh3, arm, aarch64, and ia64 - adding these
would at the very least require updating the register mapping.

If you're looking to test this, Wine makes a good victim: set
CROSSCFLAGS to "-gcodeview" when configuring. You probably also want to
set CFLAGS_FOR_TARGET and CXXFLAGS_FOR_TARGET to "-gcodeview" when
configuring gcc, to make sure that debugging information gets generated
for libgcc etc.

---
 gcc/Makefile.in           |  3 ++
 gcc/common.opt            |  4 +++
 gcc/config/i386/cygming.h |  1 +
 gcc/config/i386/x86-64.h  |  2 ++
 gcc/debug.h               |  1 +
 gcc/defaults.h            |  3 ++
 gcc/doc/invoke.texi       |  7 ++++
 gcc/flag-types.h          |  5 +--
 gcc/gcc.c                 |  6 ++++
 gcc/opts.c                |  4 +++
 gcc/pdbout.c              | 70 +++++++++++++++++++++++++++++++++++++++
 gcc/pdbout.h              | 23 +++++++++++++
 gcc/toplev.c              |  4 +++
 13 files changed, 131 insertions(+), 2 deletions(-)
 create mode 100644 gcc/pdbout.c
 create mode 100644 gcc/pdbout.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 543b477ff18..f0249bde720 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1476,6 +1476,7 @@ OBJS = \
 	opts-global.o \
 	ordered-hash-map-tests.o \
 	passes.o \
+	pdbout.o \
 	plugin.o \
 	postreload-gcse.o \
 	postreload.o \
@@ -2637,6 +2638,8 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/hsa-common.c \
   $(srcdir)/calls.c \
   $(srcdir)/omp-general.h \
+  $(srcdir)/pdbout.c \
+  $(srcdir)/pdbout.h \
   @all_gtfiles@
 
 # Compute the list of GT header files from the corresponding C sources,
diff --git a/gcc/common.opt b/gcc/common.opt
index d33383b523c..80c488c0d70 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -3127,6 +3127,10 @@ gno-pubnames
 Common Driver Negative(gpubnames) Var(debug_generate_pub_sections, 0) Init(-1)
 Don't generate DWARF pubnames and pubtypes sections.
 
+gcodeview
+Common Driver JoinedOrMissing
+Generate debug information in CodeView format.
+
 gpubnames
 Common Driver Negative(ggnu-pubnames) Var(debug_generate_pub_sections, 1)
 Generate DWARF pubnames and pubtypes sections.
diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index 1b1ea7d3d8a..42191b16c99 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 #define DBX_DEBUGGING_INFO 1
+#define PDB_DEBUGGING_INFO 1
 #if TARGET_64BIT_DEFAULT || defined (HAVE_GAS_PE_SECREL32_RELOC)
 #define DWARF2_DEBUGGING_INFO 1
 #endif
diff --git a/gcc/config/i386/x86-64.h b/gcc/config/i386/x86-64.h
index 88db428f592..e84ee6c4026 100644
--- a/gcc/config/i386/x86-64.h
+++ b/gcc/config/i386/x86-64.h
@@ -91,6 +91,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define DWARF2_DEBUGGING_INFO 1
 #define DWARF2_UNWIND_INFO 1
 
+#define PDB_DEBUGGING_INFO 1
+
 #undef PREFERRED_DEBUGGING_TYPE
 #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
 
diff --git a/gcc/debug.h b/gcc/debug.h
index 260325920ea..c8f182962dd 100644
--- a/gcc/debug.h
+++ b/gcc/debug.h
@@ -235,6 +235,7 @@ extern const struct gcc_debug_hooks xcoff_debug_hooks;
 extern const struct gcc_debug_hooks dwarf2_debug_hooks;
 extern const struct gcc_debug_hooks dwarf2_lineno_debug_hooks;
 extern const struct gcc_debug_hooks vmsdbg_debug_hooks;
+extern const struct gcc_debug_hooks pdb_debug_hooks;
 
 /* Dwarf2 frame information.  */
 
diff --git a/gcc/defaults.h b/gcc/defaults.h
index f1a38626624..c6bbb203ef3 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -922,6 +922,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #elif defined XCOFF_DEBUGGING_INFO
 #define PREFERRED_DEBUGGING_TYPE XCOFF_DEBUG
 
+#elif defined PDB_DEBUGGING_INFO
+#define PREFERRED_DEBUGGING_TYPE PDB_DEBUG
+
 #else
 /* No debugging format is supported by this target.  */
 #define PREFERRED_DEBUGGING_TYPE NO_DEBUG
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 527d362533a..f83cec6f5e0 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -435,6 +435,7 @@ Objective-C and Objective-C++ Dialects}.
 -gstabs  -gstabs+  -gstrict-dwarf  -gno-strict-dwarf @gol
 -gas-loc-support  -gno-as-loc-support @gol
 -gas-locview-support  -gno-as-locview-support @gol
+-gcodeview @gol
 -gcolumn-info  -gno-column-info @gol
 -gstatement-frontiers  -gno-statement-frontiers @gol
 -gvariable-location-views  -gno-variable-location-views @gol
@@ -8707,6 +8708,12 @@ assembler (GAS) to fail with an error.
 Produce debugging information in Alpha/VMS debug format (if that is
 supported).  This is the format used by DEBUG on Alpha/VMS systems.
 
+@item -gcodeview
+@opindex gcodeview
+Produce debugging information in CodeView debug format (if that is
+supported).  This is the format used by Microsoft Visual C++ on
+Windows.
+
 @item -g@var{level}
 @itemx -ggdb@var{level}
 @itemx -gstabs@var{level}
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index b092c563f3d..d4d7bdd5158 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -27,8 +27,9 @@ enum debug_info_type
   DWARF2_DEBUG,	    /* Write Dwarf v2 debug info (using dwarf2out.c).  */
   XCOFF_DEBUG,	    /* Write IBM/Xcoff debug info (using dbxout.c).  */
   VMS_DEBUG,        /* Write VMS debug info (using vmsdbgout.c).  */
-  VMS_AND_DWARF2_DEBUG /* Write VMS debug info (using vmsdbgout.c).
-                          and DWARF v2 debug info (using dwarf2out.c).  */
+  VMS_AND_DWARF2_DEBUG, /* Write VMS debug info (using vmsdbgout.c).
+			   and DWARF v2 debug info (using dwarf2out.c).  */
+  PDB_DEBUG	    /* Write CodeView debug info (using pdbout.c).  */
 };
 
 enum debug_info_levels
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 9f790db0daf..327cb4387db 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -4289,6 +4289,12 @@ driver_handle_option (struct gcc_options *opts,
       handle_foffload_option (arg);
       break;
 
+    case OPT_gcodeview:
+      /* If we've generated CodeView debugging information, make sure
+       * linker creates a PDB file for it. */
+      add_infile ("--pdb=", "*");
+      break;
+
     default:
       /* Various driver options need no special processing at this
 	 point, having been handled in a prescan above or being
diff --git a/gcc/opts.c b/gcc/opts.c
index c212a1a57dc..09b91aa2b87 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -2730,6 +2730,10 @@ common_handle_option (struct gcc_options *opts,
       set_debug_level (NO_DEBUG, 2, arg, opts, opts_set, loc);
       break;
 
+    case OPT_gcodeview:
+      set_debug_level (PDB_DEBUG, false, "", opts, opts_set, loc);
+      break;
+
     case OPT_gstabs:
     case OPT_gstabs_:
       set_debug_level (DBX_DEBUG, code == OPT_gstabs_, arg, opts, opts_set,
diff --git a/gcc/pdbout.c b/gcc/pdbout.c
new file mode 100644
index 00000000000..e8f39bb64ea
--- /dev/null
+++ b/gcc/pdbout.c
@@ -0,0 +1,70 @@
+/* Output CodeView debugging information from GNU compiler.
+ * Copyright (C) 2021 Mark Harmstone
+ *
+ * This file is part of GCC.
+ *
+ * GCC 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, or (at your option) any later
+ * version.
+ *
+ * GCC 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 GCC; see the file COPYING3.  If not see
+ * <http://www.gnu.org/licenses/>.  */
+
+/* The CodeView structure is partially documented - definitions of structures
+ * output below can be found at:
+ * https://github.com/microsoft/microsoft-pdb/blob/master/include/cvinfo.h
+ */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "debug.h"
+#include "pdbout.h"
+
+const struct gcc_debug_hooks pdb_debug_hooks = {
+  debug_nothing_charstar,	/* init */
+  debug_nothing_charstar,	/* finish */
+  debug_nothing_charstar,	/* early_finish */
+  debug_nothing_void,		/* assembly_start */
+  debug_nothing_int_charstar,	/* define */
+  debug_nothing_int_charstar,	/* undef */
+  debug_nothing_int_charstar,	/* start_source_file */
+  debug_nothing_int,		/* end_source_file */
+  debug_nothing_int_int,	/* begin_block */
+  debug_nothing_int_int,	/* end_block */
+  debug_true_const_tree,	/* ignore_block */
+  debug_nothing_int_int_charstar_int_bool,	/* source_line */
+  debug_nothing_int_int_charstar,	/* begin_prologue */
+  debug_nothing_int_charstar,	/* end_prologue */
+  debug_nothing_int_charstar,	/* begin_epilogue */
+  debug_nothing_int_charstar,	/* end_epilogue */
+  debug_nothing_tree,		/* begin_function */
+  debug_nothing_int,		/* end_function */
+  debug_nothing_tree,		/* register_main_translation_unit */
+  debug_nothing_tree,		/* function_decl */
+  debug_nothing_tree,		/* early_global_decl */
+  debug_nothing_tree,		/* late_global_decl */
+  debug_nothing_tree_int,	/* type_decl */
+  debug_nothing_tree_tree_tree_bool_bool,	/* imported_module_or_decl */
+  debug_false_tree_charstarstar_uhwistar,	/* die_ref_for_decl */
+  debug_nothing_tree_charstar_uhwi,	/* register_external_die */
+  debug_nothing_tree,		/* deferred_inline_function */
+  debug_nothing_tree,		/* outlining_inline_function */
+  debug_nothing_rtx_code_label,	/* label */
+  debug_nothing_int,		/* handle_pch */
+  debug_nothing_rtx_insn,	/* var_location */
+  debug_nothing_tree,		/* inline_entry */
+  debug_nothing_tree,		/* size_function */
+  debug_nothing_void,		/* switch_text_section */
+  debug_nothing_tree_tree,	/* set_name */
+  0,				/* start_end_main_source_file */
+  TYPE_SYMTAB_IS_ADDRESS	/* tree_type_symtab_field */
+};
diff --git a/gcc/pdbout.h b/gcc/pdbout.h
new file mode 100644
index 00000000000..f957cd5eca1
--- /dev/null
+++ b/gcc/pdbout.h
@@ -0,0 +1,23 @@
+/* CodeView structures and constants
+ * Copyright (c) 2021 Mark Harmstone
+ *
+ * This file is part of GCC.
+ *
+ * GCC 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, or (at your option) any later
+ * version.
+ *
+ * GCC 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 GCC; see the file COPYING3.  If not see
+ * <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_PDBOUT_H
+#define GCC_PDBOUT_H 1
+
+#endif
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 5c026feece2..a14a9177ee3 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1588,6 +1588,10 @@ process_options (void)
 #ifdef DWARF2_LINENO_DEBUGGING_INFO
   else if (write_symbols == DWARF2_DEBUG)
     debug_hooks = &dwarf2_lineno_debug_hooks;
+#endif
+#ifdef PDB_DEBUGGING_INFO
+  else if (write_symbols == PDB_DEBUG)
+    debug_hooks = &pdb_debug_hooks;
 #endif
   else
     error_at (UNKNOWN_LOCATION,
-- 
2.26.2



More information about the Gcc-patches mailing list