https://gcc.gnu.org/g:36781ef8fd26eb9a0686957e7bac8f5ccc5ecc3f
commit r15-381-g36781ef8fd26eb9a0686957e7bac8f5ccc5ecc3f Author: Mark Harmstone <m...@harmstone.com> Date: Sat May 11 08:08:50 2024 -0600 [PATCH v2 1/4] Support for CodeView debugging format 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 (OBJS): Add dwarf2codeview.o. (GTFILES): Add dwarf2codeview.cc * config/i386/cygming.h (CODEVIEW_DEBUGGING_INFO): Define. * dwarf2codeview.cc: New file. * dwarf2codeview.h: New file. * dwarf2out.cc: Include dwarf2codeview.h. (dwarf2out_finish): Call codeview_debug_finish as needed. * flag-types.h (DINFO_TYPE_CODEVIEW): Add enum member. (CODEVIEW_DEBUG): Define. * flags.h (codeview_debuginfo_p): Proottype. * opts.cc (debug_type_names): Add codeview. (debug_type_masks): Add CODEVIEW_DEBUG. (df_set_names): Add codeview. (codeview_debuginfo_p): New function. (dwarf_based_debuginfo_p): Add CODEVIEW clause. (set_debug_level): Handle CODEVIEW_DEBUG. * toplev.cc (process_options): Handle codeview. gcc/testsuite * gcc.dg/debug/codeview/codeview-1.c: New test. * gcc.dg/debug/codeview/codeview.exp: New testsuite driver. Diff: --- gcc/Makefile.in | 2 + gcc/config/i386/cygming.h | 2 + gcc/dwarf2codeview.cc | 54 ++++++++++++++++++++++++ gcc/dwarf2codeview.h | 30 +++++++++++++ gcc/dwarf2out.cc | 6 +++ gcc/flag-types.h | 3 ++ gcc/flags.h | 4 ++ gcc/opts.cc | 23 +++++++--- gcc/testsuite/gcc.dg/debug/codeview/codeview-1.c | 6 +++ gcc/testsuite/gcc.dg/debug/codeview/codeview.exp | 48 +++++++++++++++++++++ gcc/toplev.cc | 4 ++ 11 files changed, 177 insertions(+), 5 deletions(-) diff --git a/gcc/Makefile.in b/gcc/Makefile.in index ecd511463572..a7f15694c34b 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1443,6 +1443,7 @@ OBJS = \ dumpfile.o \ dwarf2asm.o \ dwarf2cfi.o \ + dwarf2codeview.o \ dwarf2ctf.o \ dwarf2out.o \ early-remat.o \ @@ -2838,6 +2839,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 beedf7c398a5..98b375538e75 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 000000000000..f08f5d55ad7c --- /dev/null +++ b/gcc/dwarf2codeview.cc @@ -0,0 +1,54 @@ +/* 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" + +#ifdef CODEVIEW_DEBUGGING_INFO + +#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); +} + +#endif diff --git a/gcc/dwarf2codeview.h b/gcc/dwarf2codeview.h new file mode 100644 index 000000000000..efda148eb498 --- /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 1b0e8b5a5b29..f7e9f90e2746 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" @@ -32278,6 +32279,11 @@ dwarf2out_finish (const char *filename) || btf_debuginfo_p ()) && lang_GNU_C ()) ctf_debug_finish (filename); +#ifdef CODEVIEW_DEBUGGING_INFO + if (codeview_debuginfo_p ()) + codeview_debug_finish (); +#endif + /* Skip emitting DWARF if not required. */ if (!dwarf_debuginfo_p ()) return; diff --git a/gcc/flag-types.h b/gcc/flag-types.h index 5062f59bc8fc..5a2b461fa75f 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 b3f8e2ecf55c..52d60583025a 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 3333600e0ea2..b38d1e45f22e 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -53,7 +53,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 @@ -62,13 +62,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. */ @@ -162,6 +162,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 @@ -176,7 +184,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 @@ -3206,6 +3215,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: @@ -3480,7 +3492,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 000000000000..eb5f14530dca --- /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 000000000000..ff705a4ae78b --- /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 2cd4096558e4..bed1b0b780bd 100644 --- a/gcc/toplev.cc +++ b/gcc/toplev.cc @@ -1437,6 +1437,10 @@ process_options () #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 {