This patch and the following add initial support for Microsoft's CodeView debugging format, as used by MSVC, to mingw targets.
Note that you will need a recent version of binutils for this to be useful. The best way to view the output is to run Microsoft's cvdump.exe, found in their microsoft-pdb repo on GitHub, against the object files. --- gcc/Makefile.in | 2 + gcc/config/i386/cygming.h | 2 + gcc/dwarf2codeview.cc | 50 +++++++++++++++++++ gcc/dwarf2codeview.h | 30 +++++++++++ gcc/dwarf2out.cc | 4 ++ gcc/flag-types.h | 3 ++ gcc/flags.h | 4 ++ gcc/opts.cc | 23 +++++++-- .../gcc.dg/debug/codeview/codeview-1.c | 6 +++ .../gcc.dg/debug/codeview/codeview.exp | 48 ++++++++++++++++++ gcc/toplev.cc | 4 ++ 11 files changed, 171 insertions(+), 5 deletions(-) create mode 100644 gcc/dwarf2codeview.cc create mode 100644 gcc/dwarf2codeview.h create mode 100644 gcc/testsuite/gcc.dg/debug/codeview/codeview-1.c create mode 100644 gcc/testsuite/gcc.dg/debug/codeview/codeview.exp diff --git a/gcc/Makefile.in b/gcc/Makefile.in index a25a1e32fbc..d011946379d 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1428,6 +1428,7 @@ OBJS = \ dumpfile.o \ dwarf2asm.o \ dwarf2cfi.o \ + dwarf2codeview.o \ dwarf2ctf.o \ dwarf2out.o \ early-remat.o \ @@ -2794,6 +2795,7 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/dwarf2out.h \ $(srcdir)/dwarf2asm.cc \ $(srcdir)/dwarf2cfi.cc \ + $(srcdir)/dwarf2codeview.cc \ $(srcdir)/dwarf2ctf.cc \ $(srcdir)/dwarf2out.cc \ $(srcdir)/ctfc.h \ diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h index d539f8d0699..a141462133b 100644 --- a/gcc/config/i386/cygming.h +++ b/gcc/config/i386/cygming.h @@ -20,6 +20,8 @@ along with GCC; see the file COPYING3. If not see #define DWARF2_DEBUGGING_INFO 1 +#define CODEVIEW_DEBUGGING_INFO 1 + #undef PREFERRED_DEBUGGING_TYPE #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc new file mode 100644 index 00000000000..e2bfdf8efeb --- /dev/null +++ b/gcc/dwarf2codeview.cc @@ -0,0 +1,50 @@ +/* Generate CodeView debugging info from the GCC DWARF. + Copyright (C) 2023 Free Software Foundation, Inc. + +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/>. */ + +/* See gas/codeview.h in binutils for more about the constants and structs + listed below. References to Microsoft files refer to Microsoft's PDB + repository: https://github.com/microsoft/microsoft-pdb. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "output.h" +#include "errors.h" +#include "md5.h" +#include "function.h" +#include "version.h" +#include "tree.h" +#include "langhooks.h" +#include "dwarf2out.h" +#include "dwarf2codeview.h" + +#define CV_SIGNATURE_C13 4 + +/* Finish CodeView debug info emission. */ + +void +codeview_debug_finish (void) +{ + targetm.asm_out.named_section (".debug$S", SECTION_DEBUG, NULL); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, CV_SIGNATURE_C13); + putc ('\n', asm_out_file); +} diff --git a/gcc/dwarf2codeview.h b/gcc/dwarf2codeview.h new file mode 100644 index 00000000000..efda148eb49 --- /dev/null +++ b/gcc/dwarf2codeview.h @@ -0,0 +1,30 @@ +/* dwarf2codeview.h - DWARF interface for CodeView generation. + Copyright (C) 2023 Free Software Foundation, Inc. + +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_DWARF2CODEVIEW_H +#define GCC_DWARF2CODEVIEW_H 1 + +#include "dwarf2out.h" +#include "flags.h" + +/* Debug Format Interface. Used in dwarf2out.cc. */ + +extern void codeview_debug_finish (void); + +#endif /* GCC_DWARF2CODEVIEW_H */ diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index 0ea73bf782e..557464c4c24 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -80,6 +80,7 @@ along with GCC; see the file COPYING3. If not see #include "expr.h" #include "dwarf2out.h" #include "dwarf2ctf.h" +#include "dwarf2codeview.h" #include "dwarf2asm.h" #include "toplev.h" #include "md5.h" @@ -32207,6 +32208,9 @@ dwarf2out_finish (const char *filename) || btf_debuginfo_p ()) && lang_GNU_C ()) ctf_debug_finish (filename); + if (codeview_debuginfo_p ()) + codeview_debug_finish (); + /* Skip emitting DWARF if not required. */ if (!dwarf_debuginfo_p ()) return; diff --git a/gcc/flag-types.h b/gcc/flag-types.h index c1852cd810c..dae1d0a8095 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -29,6 +29,7 @@ enum debug_info_type DINFO_TYPE_VMS, /* VMS debug info. */ DINFO_TYPE_CTF, /* CTF debug info. */ DINFO_TYPE_BTF, /* BTF debug info. */ + DINFO_TYPE_CODEVIEW, /* CodeView debug info. */ DINFO_TYPE_BTF_WITH_CORE, /* BTF debug info with CO-RE relocations. */ DINFO_TYPE_MAX = DINFO_TYPE_BTF_WITH_CORE /* Marker only. */ }; @@ -42,6 +43,8 @@ enum debug_info_type #define CTF_DEBUG (1U << DINFO_TYPE_CTF) /* Write BTF debug info (using btfout.cc). */ #define BTF_DEBUG (1U << DINFO_TYPE_BTF) +/* Write CodeView debug info (using dwarf2codeview.cc). */ +#define CODEVIEW_DEBUG (1U << DINFO_TYPE_CODEVIEW) /* Write BTF debug info for BPF CO-RE usecase (using btfout.cc). */ #define BTF_WITH_CORE_DEBUG (1U << DINFO_TYPE_BTF_WITH_CORE) diff --git a/gcc/flags.h b/gcc/flags.h index e4bafa310d6..50036459328 100644 --- a/gcc/flags.h +++ b/gcc/flags.h @@ -53,6 +53,10 @@ extern bool btf_with_core_debuginfo_p (); extern bool ctf_debuginfo_p (); +/* Return true iff CodeView debug info is enabled. */ + +extern bool codeview_debuginfo_p (); + /* Return true iff DWARF2 debug info is enabled. */ extern bool dwarf_debuginfo_p (struct gcc_options *opts = &global_options); diff --git a/gcc/opts.cc b/gcc/opts.cc index 8015cb7556a..f02101ceea3 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -50,7 +50,7 @@ static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff); const char *const debug_type_names[] = { - "none", "dwarf-2", "vms", "ctf", "btf" + "none", "dwarf-2", "vms", "ctf", "btf", "codeview" }; /* Bitmasks of fundamental debug info formats indexed by enum @@ -59,13 +59,13 @@ const char *const debug_type_names[] = static uint32_t debug_type_masks[] = { NO_DEBUG, DWARF2_DEBUG, VMS_DEBUG, - CTF_DEBUG, BTF_DEBUG + CTF_DEBUG, BTF_DEBUG, CODEVIEW_DEBUG }; /* Names of the set of debug formats requested by user. Updated and accessed via debug_set_names. */ -static char df_set_names[sizeof "none dwarf-2 vms ctf btf"]; +static char df_set_names[sizeof "none dwarf-2 vms ctf btf codeview"]; /* Get enum debug_info_type of the specified debug format, for error messages. Can be used only for individual debug format types. */ @@ -159,6 +159,14 @@ ctf_debuginfo_p () return (write_symbols & CTF_DEBUG); } +/* Return TRUE iff CodeView debug info is enabled. */ + +bool +codeview_debuginfo_p () +{ + return (write_symbols & CODEVIEW_DEBUG); +} + /* Return TRUE iff dwarf2 debug info is enabled. */ bool @@ -173,7 +181,8 @@ dwarf_debuginfo_p (struct gcc_options *opts) bool dwarf_based_debuginfo_p () { return ((write_symbols & CTF_DEBUG) - || (write_symbols & BTF_DEBUG)); + || (write_symbols & BTF_DEBUG) + || (write_symbols & CODEVIEW_DEBUG)); } /* All flag uses below need to explicitely reference the option sets @@ -3145,6 +3154,9 @@ common_handle_option (struct gcc_options *opts, break; case OPT_gcodeview: + set_debug_level (CODEVIEW_DEBUG, false, arg, opts, opts_set, loc); + if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL) + opts->x_debug_info_level = DINFO_LEVEL_NORMAL; break; case OPT_gbtf: @@ -3419,7 +3431,8 @@ set_debug_level (uint32_t dinfo, int extended, const char *arg, warning_at (loc, 0, "target system does not support debug output"); } else if ((opts->x_write_symbols & CTF_DEBUG) - || (opts->x_write_symbols & BTF_DEBUG)) + || (opts->x_write_symbols & BTF_DEBUG) + || (opts->x_write_symbols & CODEVIEW_DEBUG)) { opts->x_write_symbols |= DWARF2_DEBUG; opts_set->x_write_symbols |= DWARF2_DEBUG; diff --git a/gcc/testsuite/gcc.dg/debug/codeview/codeview-1.c b/gcc/testsuite/gcc.dg/debug/codeview/codeview-1.c new file mode 100644 index 00000000000..eb5f14530dc --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/codeview/codeview-1.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-gcodeview" } */ + +void func(void) +{ +} diff --git a/gcc/testsuite/gcc.dg/debug/codeview/codeview.exp b/gcc/testsuite/gcc.dg/debug/codeview/codeview.exp new file mode 100644 index 00000000000..ff705a4ae78 --- /dev/null +++ b/gcc/testsuite/gcc.dg/debug/codeview/codeview.exp @@ -0,0 +1,48 @@ +# Copyright (C) 2023 Free Software Foundation, Inc. + +# 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 GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# GCC testsuite that uses the `dg.exp' driver. + +# Load support procs. +load_lib gcc-dg.exp + +if {![istarget i*86-*-mingw*] + && ![istarget x86_64-*-mingw*]} { + return 0 +} + +# If a testcase doesn't have special options, use these. +global DEFAULT_CFLAGS +if ![info exists DEFAULT_CFLAGS] then { + set DEFAULT_CFLAGS " -ansi -pedantic-errors" +} + +# Initialize `dg'. +dg-init + +# Main loop. +set comp_output [gcc_target_compile \ + "$srcdir/$subdir/../trivial.c" "trivial.S" assembly \ + "additional_flags=-gcodeview"] +if { ! [string match "*: target system does not support the * debug format*" \ + $comp_output] } { + remove-build-file "trivial.S" + dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\] ]] \ + "" $DEFAULT_CFLAGS +} + +# All done. +dg-finish diff --git a/gcc/toplev.cc b/gcc/toplev.cc index 8af9bf5090e..862583df0f4 100644 --- a/gcc/toplev.cc +++ b/gcc/toplev.cc @@ -1431,6 +1431,10 @@ process_options (bool no_backend) #ifdef DWARF2_LINENO_DEBUGGING_INFO else if (write_symbols == DWARF2_DEBUG) debug_hooks = &dwarf2_lineno_debug_hooks; +#endif +#ifdef CODEVIEW_DEBUGGING_INFO + else if (codeview_debuginfo_p ()) + debug_hooks = &dwarf2_debug_hooks; #endif else { -- 2.41.0