From patchwork Tue Oct 31 00:28:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Harmstone X-Patchwork-Id: 1857285 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=harmstone.com header.i=@harmstone.com header.a=rsa-sha256 header.s=mail header.b=WfI9tsNH; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SK9yD35fFz1yQ5 for ; Tue, 31 Oct 2023 11:29:56 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7F39C3858C2D for ; Tue, 31 Oct 2023 00:29:54 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail.burntcomma.com (mail2.burntcomma.com [217.169.27.34]) by sourceware.org (Postfix) with ESMTPS id DAF103858D32 for ; Tue, 31 Oct 2023 00:29:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DAF103858D32 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=harmstone.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=harmstone.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org DAF103858D32 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=217.169.27.34 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698712150; cv=none; b=dDcyLt+/fgrAt6xOVPTaGOQqAvKwZyFofQZ0fqG4STx27oBRb4HvHPSoLp2kPUinp2VhRczCfynvxydcUPtOyD777WtBWQB32nAv9hzesdZB9IqDrUyKkbPUOHm7oWG03jeWdKXvnH/Kp5rKc2lkaQ+mPHRgMODYdI4vOopnFPQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698712150; c=relaxed/simple; bh=JWOHLycR8vsjPyscLFbe5CFCt5iwrSSRi4UTqR2/mHc=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:Mime-Version; b=iHL/GD9NkEIbKa9vCb7hJwxdLQcXurpAklAph1kAAa8TDlrfgfDLmGBQDpdYtAjGLrApKxek1inBJGNnvRK0gpQ3Xf978ZPgOa1xJoJE8hviLj1rLdn+PMP+ZxQPd4DMmjAQjCmUnT0qf2SmarA/LS1GWAFJjumRsD/JQtcExBg= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from localhost.localdomain (beren.burntcomma.com [IPv6:2a02:8012:8cf0:0:b62e:99ff:fee9:ad9f]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (Client did not present a certificate) by mail.burntcomma.com (Postfix) with ESMTPSA id 5269416B3C0CD; Tue, 31 Oct 2023 00:29:06 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=harmstone.com; s=mail; t=1698712146; bh=CDHNkpPaan+6LH+FLgf2dWquPWVGrYVEAyzxyjo7JfQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=WfI9tsNH1u8qiLcrrwIsPFeH9rXpoKCu/GA+PlQyAuV1+0QoS0/D20cBONQWHosx+ ABwIJJNhDxDw5hmsTqlPdzotqCamea05xEHeSXTrMIgyUiG7Bo0MOVI391KNAx9hAZ 3pzuzwxzKu/L+000FFUihKXcBwjVXzHLjaglYICg= From: Mark Harmstone To: gcc-patches@gcc.gnu.org Cc: Mark Harmstone Subject: [PATCH v2 1/4] Support for CodeView debugging format Date: Tue, 31 Oct 2023 00:28:16 +0000 Message-ID: <20231031002859.18892-2-mark@harmstone.com> In-Reply-To: <20231031002859.18892-1-mark@harmstone.com> References: <20231031002859.18892-1-mark@harmstone.com> Mime-Version: 1.0 X-Spam-Status: No, score=-13.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org 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 | 54 +++++++++++++++++++ gcc/dwarf2codeview.h | 30 +++++++++++ gcc/dwarf2out.cc | 6 +++ 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, 177 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 91d6bfbea4d..b260fe12c08 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1430,6 +1430,7 @@ OBJS = \ dumpfile.o \ dwarf2asm.o \ dwarf2cfi.o \ + dwarf2codeview.o \ dwarf2ctf.o \ dwarf2out.o \ early-remat.o \ @@ -2800,6 +2801,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..f08f5d55ad7 --- /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 +. */ + +/* 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 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 +. */ + +#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 1e0cec66c5e..e987a8e9a3d 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" @@ -32209,6 +32210,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 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 +# . + +# 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 9a734890a18..dd7ed2233c7 100644 --- a/gcc/toplev.cc +++ b/gcc/toplev.cc @@ -1432,6 +1432,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 { From patchwork Tue Oct 31 00:28:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Harmstone X-Patchwork-Id: 1857286 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=harmstone.com header.i=@harmstone.com header.a=rsa-sha256 header.s=mail header.b=qKbPJY2t; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SK9yp2DLVz1yQ6 for ; Tue, 31 Oct 2023 11:30:26 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 1CADA3858402 for ; Tue, 31 Oct 2023 00:30:24 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail.burntcomma.com (mail2.burntcomma.com [217.169.27.34]) by sourceware.org (Postfix) with ESMTPS id D7CD73858D28 for ; Tue, 31 Oct 2023 00:29:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D7CD73858D28 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=harmstone.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=harmstone.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D7CD73858D28 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=217.169.27.34 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698712150; cv=none; b=hZK7o+nFPpWorNUJNwaoXxzF9G8RMtENxB6ulboLsH+Sk6jQ/daOj8ATDM/tiPueStzjg90vFxEwyF20+VUttKY6l0EMrSlZJYyOZ2dP/Jgqm3YDx9TpCY/wCH+lGlrtHR+LGQoRAvyrOYblCTVhrpBJbJ23/o3CjAdOMI+A52k= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698712150; c=relaxed/simple; bh=HjJHimkQurlWnzv2ksU2qqnMjIY4GXs456zXRTfvJmM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:Mime-Version; b=hVcZoWPpMtkDicRUeNCR/KoR3OKlnGrLXfOi4Q4lBt/mZOlx74xPvK3b8OiRLu0pRuBZPdyt5W3zgW5MLTczEjqVqQPjBGgJ72Y2V5EEJ14qzNjDTkYJNeFfZ4wkZGhdvqEj3h4fOYWAx/Gsjv+J009i5oQEIKYh3T47Tm4aeQQ= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from localhost.localdomain (beren.burntcomma.com [IPv6:2a02:8012:8cf0:0:b62e:99ff:fee9:ad9f]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (Client did not present a certificate) by mail.burntcomma.com (Postfix) with ESMTPSA id 65CA516B3C0D0; Tue, 31 Oct 2023 00:29:06 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=harmstone.com; s=mail; t=1698712146; bh=4hcajE1x9B1auiLZytCi7I6Tussmmr3OCdSq5ivwvsQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=qKbPJY2tf/4/ilRJ5FeSk6ejK5U0/ZHH3Mfi2JlXl26QWqZNgnsVSaPKzLYnlE6oo Hz/47Cc8frVQvupUCp7kow+EvDDw1cabU2BoDM3spgEYIIQn+ENKrd/eNPsFeAzxvb dpfuiYYwlg9wj36JkSKBbxoueL49uiviwQxeJI1c= From: Mark Harmstone To: gcc-patches@gcc.gnu.org Cc: Mark Harmstone Subject: [PATCH v2 2/4] Output file checksums in CodeView section Date: Tue, 31 Oct 2023 00:28:17 +0000 Message-ID: <20231031002859.18892-3-mark@harmstone.com> In-Reply-To: <20231031002859.18892-1-mark@harmstone.com> References: <20231031002859.18892-1-mark@harmstone.com> Mime-Version: 1.0 X-Spam-Status: No, score=-12.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Outputs the file name and MD5 hash of the main source file into the CodeView .debug$S section, along with that of any #include'd files. --- gcc/dwarf2codeview.cc | 254 ++++++++++++++++++++++++++++++++++++++++++ gcc/dwarf2codeview.h | 1 + gcc/dwarf2out.cc | 5 + 3 files changed, 260 insertions(+) diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index f08f5d55ad7..da8315310b5 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -39,6 +39,257 @@ along with GCC; see the file COPYING3. If not see #define CV_SIGNATURE_C13 4 +#define DEBUG_S_STRINGTABLE 0xf3 +#define DEBUG_S_FILECHKSMS 0xf4 + +#define CHKSUM_TYPE_MD5 1 + +#define HASH_SIZE 16 + +struct codeview_string +{ + codeview_string *next; + uint32_t offset; + char *string; +}; + +struct string_hasher : free_ptr_hash +{ + typedef const char *compare_type; + + static hashval_t hash (const codeview_string *x) + { + return htab_hash_string (x->string); + } + + static bool equal (const codeview_string *x, const char *y) + { + return !strcmp (x->string, y); + } + + static void mark_empty (codeview_string *x) + { + if (x->string) + { + free (x->string); + x->string = NULL; + } + } + + static void remove (codeview_string *&x) + { + free (x->string); + } +}; + +struct codeview_source_file +{ + codeview_source_file *next; + unsigned int file_num; + uint32_t string_offset; + char *filename; + uint8_t hash[HASH_SIZE]; +}; + +static codeview_source_file *files, *last_file; +static unsigned int num_files; +static uint32_t string_offset = 1; +static hash_table *strings_htab; +static codeview_string *strings, *last_string; + +/* Adds string to the string table, returning its offset. If already present, + this returns the offset of the existing string. */ + +static uint32_t +add_string (const char *string) +{ + codeview_string **slot; + codeview_string *s; + size_t len; + + if (!strings_htab) + strings_htab = new hash_table (10); + + slot = strings_htab->find_slot_with_hash (string, htab_hash_string (string), + INSERT); + + if (*slot) + return (*slot)->offset; + + s = (codeview_string *) xmalloc (sizeof (codeview_string)); + len = strlen (string); + + s->next = NULL; + + s->offset = string_offset; + string_offset += len + 1; + + s->string = xstrdup (string); + + if (last_string) + last_string->next = s; + else + strings = s; + + last_string = s; + + *slot = s; + + return s->offset; +} + +/* A new source file has been encountered - record the details and calculate + its hash. */ + +void +codeview_start_source_file (const char *filename) +{ + codeview_source_file *sf; + char *path; + uint32_t string_offset; + FILE *f; + + path = lrealpath (filename); + string_offset = add_string (path); + free (path); + + sf = files; + while (sf) + { + if (sf->string_offset == string_offset) + return; + + sf = sf->next; + } + + sf = (codeview_source_file *) xmalloc (sizeof (codeview_source_file)); + sf->next = NULL; + sf->file_num = num_files; + sf->string_offset = string_offset; + sf->filename = xstrdup (filename); + + f = fopen (filename, "r"); + if (!f) + internal_error ("could not open %s for reading", filename); + + if (md5_stream (f, sf->hash)) + { + fclose (f); + internal_error ("md5_stream failed"); + } + + fclose (f); + + if (last_file) + last_file->next = sf; + else + files = sf; + + last_file = sf; + num_files++; +} + +/* Write out the strings table into the .debug$S section. The linker will + parse this, and handle the deduplication and hashing for all the object + files. */ + +static void +write_strings_table (void) +{ + codeview_string *string; + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, DEBUG_S_STRINGTABLE); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + asm_fprintf (asm_out_file, "%LLcv_strings_end - %LLcv_strings_start\n"); + + asm_fprintf (asm_out_file, "%LLcv_strings_start:\n"); + + /* The first entry is always an empty string. */ + fputs (integer_asm_op (1, false), asm_out_file); + fprint_whex (asm_out_file, 0); + putc ('\n', asm_out_file); + + string = strings; + while (string) + { + ASM_OUTPUT_ASCII (asm_out_file, string->string, + strlen (string->string) + 1); + + string = string->next; + } + + delete strings_htab; + + asm_fprintf (asm_out_file, "%LLcv_strings_end:\n"); + + ASM_OUTPUT_ALIGN (asm_out_file, 2); +} + +/* Write out the file checksums data into the .debug$S section. */ + +static void +write_source_files (void) +{ + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, DEBUG_S_FILECHKSMS); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + asm_fprintf (asm_out_file, + "%LLcv_filechksms_end - %LLcv_filechksms_start\n"); + + asm_fprintf (asm_out_file, "%LLcv_filechksms_start:\n"); + + while (files) + { + codeview_source_file *next = files->next; + + /* This is struct file_checksum in binutils, or filedata in Microsoft's + dumpsym7.cpp: + + struct file_checksum + { + uint32_t file_id; + uint8_t checksum_length; + uint8_t checksum_type; + } ATTRIBUTE_PACKED; + + followed then by the bytes of the hash, padded to the next 4 bytes. + file_id here is actually the offset in the strings table. */ + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, files->string_offset); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (1, false), asm_out_file); + fprint_whex (asm_out_file, HASH_SIZE); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (1, false), asm_out_file); + fprint_whex (asm_out_file, CHKSUM_TYPE_MD5); + putc ('\n', asm_out_file); + + for (unsigned int i = 0; i < HASH_SIZE; i++) + { + fputs (integer_asm_op (1, false), asm_out_file); + fprint_whex (asm_out_file, files->hash[i]); + putc ('\n', asm_out_file); + } + + ASM_OUTPUT_ALIGN (asm_out_file, 2); + + free (files->filename); + free (files); + + files = next; + } + + asm_fprintf (asm_out_file, "%LLcv_filechksms_end:\n"); +} + /* Finish CodeView debug info emission. */ void @@ -49,6 +300,9 @@ codeview_debug_finish (void) fputs (integer_asm_op (4, false), asm_out_file); fprint_whex (asm_out_file, CV_SIGNATURE_C13); putc ('\n', asm_out_file); + + write_strings_table (); + write_source_files (); } #endif diff --git a/gcc/dwarf2codeview.h b/gcc/dwarf2codeview.h index efda148eb49..e2d732bb9b6 100644 --- a/gcc/dwarf2codeview.h +++ b/gcc/dwarf2codeview.h @@ -26,5 +26,6 @@ along with GCC; see the file COPYING3. If not see /* Debug Format Interface. Used in dwarf2out.cc. */ extern void codeview_debug_finish (void); +extern void codeview_start_source_file (const char *); #endif /* GCC_DWARF2CODEVIEW_H */ diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index e987a8e9a3d..dfff6e88804 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -28825,6 +28825,11 @@ dwarf2out_set_ignored_loc (unsigned int line, unsigned int column, static void dwarf2out_start_source_file (unsigned int lineno, const char *filename) { +#ifdef CODEVIEW_DEBUGGING_INFO + if (codeview_debuginfo_p ()) + codeview_start_source_file (filename); +#endif + if (debug_info_level >= DINFO_LEVEL_VERBOSE) { macinfo_entry e; From patchwork Tue Oct 31 00:28:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Harmstone X-Patchwork-Id: 1857282 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=harmstone.com header.i=@harmstone.com header.a=rsa-sha256 header.s=mail header.b=pU5aYOvS; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SK9xf730wz1yQ5 for ; Tue, 31 Oct 2023 11:29:25 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2115F3858431 for ; Tue, 31 Oct 2023 00:29:23 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail.burntcomma.com (mail2.burntcomma.com [217.169.27.34]) by sourceware.org (Postfix) with ESMTPS id D76D43858D20 for ; Tue, 31 Oct 2023 00:29:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D76D43858D20 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=harmstone.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=harmstone.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D76D43858D20 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=217.169.27.34 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698712150; cv=none; b=uOXCS0Wd6nLWRrvWtQayMg0ElAYWl0qhCDN0O5gawTSaPxbl4Nnbnwqr530O18s9Me69u6i6knyWQBKE+wBz1xss6OD2HP3NuisBfiw0dO+EZIMSUuxQ+Bm9JlNXXW3WoYanNItflX+MuiNsWnlws5k3HKmOjKss44tCnKrsUzE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698712150; c=relaxed/simple; bh=iSyDhV2tJjpZp14pHIFTdp4TgwE4GTisJhJNf03VL/8=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:Mime-Version; b=xEjstTEDIFK5n7v5LPCGn8n+A/h0xyX2DTpa4l2VnA/sTToJO+C0ZIayJmzV+5LxPmSctVHoJ4vQ9d5LcgKu6TvIWNfa6kRmTttzpLX40kTO4wtL5vMlxzJtuMoaStDLqNf/Er55vRi3Rr4PaT5CY/iGVSvPimTj6soAtQKxl/E= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from localhost.localdomain (beren.burntcomma.com [IPv6:2a02:8012:8cf0:0:b62e:99ff:fee9:ad9f]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (Client did not present a certificate) by mail.burntcomma.com (Postfix) with ESMTPSA id 8475116B3C0D3; Tue, 31 Oct 2023 00:29:06 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=harmstone.com; s=mail; t=1698712146; bh=SnusWKsfwv3ylp+njBq/iGZrG8rvX0fH8T4Oxzs5oqM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=pU5aYOvSFV588y38vfKjJ5tE8Aqo25FKkXvApDQUxmz6z8+/L/3OI1mZ5RglyCN53 b5Rv6zFfyeFpEcSUTbewZ6DTgM6BAWwBuJ7QI1KG6wVzKrSGnEqp7LDQ08rIzMnTXS oIElY/bWQQCtANF5WtIKSPh92PlVrNn2e4+HZ+6Y= From: Mark Harmstone To: gcc-patches@gcc.gnu.org Cc: Mark Harmstone Subject: [PATCH v2 3/4] Output line numbers in CodeView section Date: Tue, 31 Oct 2023 00:28:18 +0000 Message-ID: <20231031002859.18892-4-mark@harmstone.com> In-Reply-To: <20231031002859.18892-1-mark@harmstone.com> References: <20231031002859.18892-1-mark@harmstone.com> Mime-Version: 1.0 X-Spam-Status: No, score=-12.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Outputs the DEBUG_S_LINES block in the CodeView .debug$S section, which maps between line numbers and addresses. You'll need a fairly recent version of GAS for the .secidx directive to be recognized. --- gcc/dwarf2codeview.cc | 303 ++++++++++++++++++++++++++++++++++++++++++ gcc/dwarf2codeview.h | 3 + gcc/dwarf2out.cc | 15 +++ gcc/opts.cc | 2 +- 4 files changed, 322 insertions(+), 1 deletion(-) diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index da8315310b5..9c69ebf8998 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -39,11 +39,15 @@ along with GCC; see the file COPYING3. If not see #define CV_SIGNATURE_C13 4 +#define DEBUG_S_LINES 0xf2 #define DEBUG_S_STRINGTABLE 0xf3 #define DEBUG_S_FILECHKSMS 0xf4 #define CHKSUM_TYPE_MD5 1 +#define LINE_LABEL "Lcvline" +#define END_FUNC_LABEL "Lcvendfunc" + #define HASH_SIZE 16 struct codeview_string @@ -91,11 +95,128 @@ struct codeview_source_file uint8_t hash[HASH_SIZE]; }; +struct codeview_line +{ + codeview_line *next; + unsigned int line_no; + unsigned int label_num; +}; + +struct codeview_line_block +{ + codeview_line_block *next; + uint32_t file_id; + unsigned int num_lines; + codeview_line *lines, *last_line; +}; + +struct codeview_function +{ + codeview_function *next; + function *func; + unsigned int end_label; + codeview_line_block *blocks, *last_block; +}; + +static unsigned int line_label_num; +static unsigned int func_label_num; static codeview_source_file *files, *last_file; static unsigned int num_files; static uint32_t string_offset = 1; static hash_table *strings_htab; static codeview_string *strings, *last_string; +static codeview_function *funcs, *last_func; +static const char* last_filename; +static uint32_t last_file_id; + +/* Record new line number against the current function. */ + +void +codeview_source_line (unsigned int line_no, const char *filename) +{ + codeview_line *l; + uint32_t file_id = last_file_id; + unsigned int label_num = ++line_label_num; + + targetm.asm_out.internal_label (asm_out_file, LINE_LABEL, label_num); + + if (!last_func || last_func->func != cfun) + { + codeview_function *f = (codeview_function *) + xmalloc (sizeof (codeview_function)); + + f->next = NULL; + f->func = cfun; + f->end_label = 0; + f->blocks = f->last_block = NULL; + + if (!funcs) + funcs = f; + else + last_func->next = f; + + last_func = f; + } + + if (filename != last_filename) + { + codeview_source_file *sf = files; + + while (sf) + { + if (!strcmp (sf->filename, filename)) + { + /* 0x18 is the size of the checksum entry for each file. + 0x6 bytes for the header, plus 0x10 bytes for the hash, + then padded to a multiple of 4. */ + + file_id = sf->file_num * 0x18; + last_filename = filename; + last_file_id = file_id; + break; + } + + sf = sf->next; + } + } + + if (!last_func->last_block || last_func->last_block->file_id != file_id) + { + codeview_line_block *b; + + b = (codeview_line_block *) xmalloc (sizeof (codeview_line_block)); + + b->next = NULL; + b->file_id = file_id; + b->num_lines = 0; + b->lines = b->last_line = NULL; + + if (!last_func->blocks) + last_func->blocks = b; + else + last_func->last_block->next = b; + + last_func->last_block = b; + } + + if (last_func->last_block->last_line + && last_func->last_block->last_line->line_no == line_no) + return; + + l = (codeview_line *) xmalloc (sizeof (codeview_line)); + + l->next = NULL; + l->line_no = line_no; + l->label_num = label_num; + + if (!last_func->last_block->lines) + last_func->last_block->lines = l; + else + last_func->last_block->last_line->next = l; + + last_func->last_block->last_line = l; + last_func->last_block->num_lines++; +} /* Adds string to the string table, returning its offset. If already present, this returns the offset of the existing string. */ @@ -290,6 +411,187 @@ write_source_files (void) asm_fprintf (asm_out_file, "%LLcv_filechksms_end:\n"); } +/* Write out the line number information for each function into the + .debug$S section. */ + +static void +write_line_numbers (void) +{ + unsigned int func_num = 0; + + while (funcs) + { + codeview_function *next = funcs->next; + unsigned int first_label_num; + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, DEBUG_S_LINES); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + asm_fprintf (asm_out_file, "%LLcv_lines%u_end - %LLcv_lines%u_start\n", + func_num, func_num); + + asm_fprintf (asm_out_file, "%LLcv_lines%u_start:\n", func_num); + + /* Output the header (struct cv_lines_header in binutils or + CV_DebugSLinesHeader_t in Microsoft's cvinfo.h): + + struct cv_lines_header + { + uint32_t offset; + uint16_t section; + uint16_t flags; + uint32_t length; + }; + */ + + asm_fprintf (asm_out_file, "\t.secrel32\t%L" LINE_LABEL "%u\n", + funcs->blocks->lines->label_num); + asm_fprintf (asm_out_file, "\t.secidx\t%L" LINE_LABEL "%u\n", + funcs->blocks->lines->label_num); + + /* flags */ + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, 0); + putc ('\n', asm_out_file); + + first_label_num = funcs->blocks->lines->label_num; + + /* length */ + fputs (integer_asm_op (4, false), asm_out_file); + asm_fprintf (asm_out_file, + "%L" END_FUNC_LABEL "%u - %L" LINE_LABEL "%u\n", + funcs->end_label, first_label_num); + + while (funcs->blocks) + { + codeview_line_block *next = funcs->blocks->next; + + /* Next comes the blocks, each block being a part of a function + within the same source file (struct cv_lines_block in binutils or + CV_DebugSLinesFileBlockHeader_t in Microsoft's cvinfo.h): + + struct cv_lines_block + { + uint32_t file_id; + uint32_t num_lines; + uint32_t length; + }; + */ + + /* file ID */ + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, funcs->blocks->file_id); + putc ('\n', asm_out_file); + + /* number of lines */ + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, funcs->blocks->num_lines); + putc ('\n', asm_out_file); + + /* length of code block: (num_lines * sizeof (struct cv_line)) + + sizeof (struct cv_lines_block) */ + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, (funcs->blocks->num_lines * 0x8) + 0xc); + putc ('\n', asm_out_file); + + while (funcs->blocks->lines) + { + codeview_line *next = funcs->blocks->lines->next; + + /* Finally comes the line number information (struct cv_line in + binutils or CV_Line_t in Microsoft's cvinfo.h): + + struct cv_line + { + uint32_t offset; + uint32_t line_no; + }; + + Strictly speaking line_no is a bitfield: the bottom 24 bits + are the line number, and the top bit means "is a statement". + */ + + fputs (integer_asm_op (4, false), asm_out_file); + asm_fprintf (asm_out_file, + "%L" LINE_LABEL "%u - %L" LINE_LABEL "%u\n", + funcs->blocks->lines->label_num, first_label_num); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, + 0x80000000 + | (funcs->blocks->lines->line_no & 0xffffff)); + putc ('\n', asm_out_file); + + free (funcs->blocks->lines); + + funcs->blocks->lines = next; + } + + free (funcs->blocks); + + funcs->blocks = next; + } + + free (funcs); + + asm_fprintf (asm_out_file, "%LLcv_lines%u_end:\n", func_num); + func_num++; + + funcs = next; + } +} + +/* Treat cold sections as separate functions, for the purposes of line + numbers. */ + +void +codeview_switch_text_section (void) +{ + codeview_function *f; + + if (last_func && last_func->end_label == 0) + { + unsigned int label_num = ++func_label_num; + + targetm.asm_out.internal_label (asm_out_file, END_FUNC_LABEL, + label_num); + + last_func->end_label = label_num; + } + + f = (codeview_function *) xmalloc (sizeof (codeview_function)); + + f->next = NULL; + f->func = cfun; + f->end_label = 0; + f->blocks = f->last_block = NULL; + + if (!funcs) + funcs = f; + else + last_func->next = f; + + last_func = f; +} + +/* Mark the end of the current function. */ + +void +codeview_end_epilogue (void) +{ + if (last_func && last_func->end_label == 0) + { + unsigned int label_num = ++func_label_num; + + targetm.asm_out.internal_label (asm_out_file, END_FUNC_LABEL, + label_num); + + last_func->end_label = label_num; + } +} + /* Finish CodeView debug info emission. */ void @@ -303,6 +605,7 @@ codeview_debug_finish (void) write_strings_table (); write_source_files (); + write_line_numbers (); } #endif diff --git a/gcc/dwarf2codeview.h b/gcc/dwarf2codeview.h index e2d732bb9b6..b6421b62d2e 100644 --- a/gcc/dwarf2codeview.h +++ b/gcc/dwarf2codeview.h @@ -26,6 +26,9 @@ along with GCC; see the file COPYING3. If not see /* Debug Format Interface. Used in dwarf2out.cc. */ extern void codeview_debug_finish (void); +extern void codeview_source_line (unsigned int, const char *); extern void codeview_start_source_file (const char *); +extern void codeview_switch_text_section (); +extern void codeview_end_epilogue (void); #endif /* GCC_DWARF2CODEVIEW_H */ diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index dfff6e88804..04ccb702180 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -1253,6 +1253,11 @@ dwarf2out_end_epilogue (unsigned int line ATTRIBUTE_UNUSED, if (dwarf2out_do_cfi_asm ()) fprintf (asm_out_file, "\t.cfi_endproc\n"); +#ifdef CODEVIEW_DEBUGGING_INFO + if (codeview_debuginfo_p ()) + codeview_end_epilogue (); +#endif + /* Output a label to mark the endpoint of the code generated for this function. */ ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, @@ -1306,6 +1311,11 @@ dwarf2out_switch_text_section (void) } have_multiple_function_sections = true; +#ifdef CODEVIEW_DEBUGGING_INFO + if (codeview_debuginfo_p ()) + codeview_switch_text_section (); +#endif + if (dwarf2out_do_cfi_asm ()) fprintf (asm_out_file, "\t.cfi_endproc\n"); @@ -28605,6 +28615,11 @@ dwarf2out_source_line (unsigned int line, unsigned int column, dw_line_info_table *table; static var_loc_view lvugid; +#ifdef CODEVIEW_DEBUGGING_INFO + if (codeview_debuginfo_p ()) + codeview_source_line (line, filename); +#endif + /* 'line_info_table' information gathering is not needed when the debug info level is set to the lowest value. Also, the current DWARF-based debug formats do not use this info. */ diff --git a/gcc/opts.cc b/gcc/opts.cc index f02101ceea3..6e91b1e0ff9 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -1364,7 +1364,7 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, opts->x_debug_nonbind_markers_p = (opts->x_optimize && opts->x_debug_info_level >= DINFO_LEVEL_NORMAL - && dwarf_debuginfo_p (opts) + && (dwarf_debuginfo_p (opts) || codeview_debuginfo_p ()) && !(opts->x_flag_selective_scheduling || opts->x_flag_selective_scheduling2)); From patchwork Tue Oct 31 00:28:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Harmstone X-Patchwork-Id: 1857284 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=harmstone.com header.i=@harmstone.com header.a=rsa-sha256 header.s=mail header.b=4oS5Gi33; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SK9y9429Zz1yQ5 for ; Tue, 31 Oct 2023 11:29:53 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A037F3858433 for ; Tue, 31 Oct 2023 00:29:51 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail.burntcomma.com (mail.burntcomma.com [IPv6:2a02:8012:8cf0:250::6d61:696c]) by sourceware.org (Postfix) with ESMTPS id DDA253858D33 for ; Tue, 31 Oct 2023 00:29:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DDA253858D33 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=harmstone.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=harmstone.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org DDA253858D33 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a02:8012:8cf0:250::6d61:696c ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698712150; cv=none; b=EHu3W7rEYL7hVPG705gHAqcms4tMEBSrq2kz94x/mbGrAOG0omfQYJv6uXcn/FQ1556wIpWXTIxF5r4QqiJ+Y+KU05L9ljjpYgXcVzzF/tXfrmkEoff9XNG2rK7Hn+eJ3efAP7k+3A0BbJ2qNpn5jwWF/FDSX1SuPPfr/3h561w= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698712150; c=relaxed/simple; bh=jh++aZn912IUMGmAtQGUMuTGRMKFQ35VAE+umdRilNk=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:Mime-Version; b=JV9ts+MWIlKE+R7FKD63ThSp1124J/wm82aZzE4y9kTKz4fvw1OlskGSEQAS/gXV4oR8tujR3ODEQu+pIs3o+oZwF5o5g39kRbptA+93jLDZf9sjadlsXsar320nLPgSjrg8BMWxsIc+R07jxZET4SvAPWWZVliRay72JzSUVtI= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from localhost.localdomain (beren.burntcomma.com [IPv6:2a02:8012:8cf0:0:b62e:99ff:fee9:ad9f]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (Client did not present a certificate) by mail.burntcomma.com (Postfix) with ESMTPSA id 98BF316B3C0D6; Tue, 31 Oct 2023 00:29:06 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=harmstone.com; s=mail; t=1698712146; bh=mO2BwVzapblGVPPgfbKr6Tj0Sk0nwNSd9Zy7i+Vtj5k=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=4oS5Gi33iYvHyEg6nCm1QWzwzQt5bhKbHvRAs7kFSLj1lyp6P/2fcNQlprDaSWSO7 dLFRoI/PNK77wTcPdt1TSR8252ZD77lCKkcEumVM1p8nmbfrr19GHMokcSeUd4VSRB mFdGCnDJlDpthvUORoNSRPIa0umfMn9F4IAY5I34= From: Mark Harmstone To: gcc-patches@gcc.gnu.org Cc: Mark Harmstone Subject: [PATCH v4 4/4] Output S_COMPILE3 symbol in CodeView debug section Date: Tue, 31 Oct 2023 00:28:19 +0000 Message-ID: <20231031002859.18892-5-mark@harmstone.com> In-Reply-To: <20231031002859.18892-1-mark@harmstone.com> References: <20231031002859.18892-1-mark@harmstone.com> Mime-Version: 1.0 X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_STOCKGEN, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Outputs the S_COMPILE3 symbol in the CodeView .debug$S debug section. The DEBUG_S_SYMBOLS block added here makes up pretty much everything that isn't data structures or line numbers; we add the S_COMPILE3 symbol here to start it off. This is a descriptive bit, the most interesting part of which is the version of the compiler used. --- gcc/dwarf2codeview.cc | 126 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index 9c69ebf8998..db776d79be4 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -39,14 +39,25 @@ along with GCC; see the file COPYING3. If not see #define CV_SIGNATURE_C13 4 +#define DEBUG_S_SYMBOLS 0xf1 #define DEBUG_S_LINES 0xf2 #define DEBUG_S_STRINGTABLE 0xf3 #define DEBUG_S_FILECHKSMS 0xf4 #define CHKSUM_TYPE_MD5 1 +#define S_COMPILE3 0x113c + +#define CV_CFL_80386 0x03 +#define CV_CFL_X64 0xD0 + +#define CV_CFL_C 0x00 +#define CV_CFL_CXX 0x01 + #define LINE_LABEL "Lcvline" #define END_FUNC_LABEL "Lcvendfunc" +#define SYMBOL_START_LABEL "Lcvsymstart" +#define SYMBOL_END_LABEL "Lcvsymend" #define HASH_SIZE 16 @@ -120,6 +131,7 @@ struct codeview_function static unsigned int line_label_num; static unsigned int func_label_num; +static unsigned int sym_label_num; static codeview_source_file *files, *last_file; static unsigned int num_files; static uint32_t string_offset = 1; @@ -592,6 +604,119 @@ codeview_end_epilogue (void) } } +/* Return the CodeView constant for the selected architecture. */ + +static uint16_t +target_processor (void) +{ + if (TARGET_64BIT) + return CV_CFL_X64; + else + return CV_CFL_80386; +} + +/* Return the CodeView constant for the language being used. */ + +static uint32_t +language_constant (void) +{ + const char *language_string = lang_hooks.name; + + if (startswith (language_string, "GNU C++")) + return CV_CFL_CXX; + else if (startswith (language_string, "GNU C")) + return CV_CFL_C; + + return 0; +} + +/* Write a S_COMPILE3 symbol, which records the details of the compiler + being used. */ + +static void +write_compile3_symbol (void) +{ + unsigned int label_num = ++sym_label_num; + + static const char compiler_name[] = "GCC "; + + /* This is struct COMPILESYM3 in binutils and Microsoft's cvinfo.h: + + struct COMPILESYM3 + { + uint16_t length; + uint16_t type; + uint32_t flags; + uint16_t machine; + uint16_t frontend_major; + uint16_t frontend_minor; + uint16_t frontend_build; + uint16_t frontend_qfe; + uint16_t backend_major; + uint16_t backend_minor; + uint16_t backend_build; + uint16_t backend_qfe; + } ATTRIBUTE_PACKED; + */ + + fputs (integer_asm_op (2, false), asm_out_file); + asm_fprintf (asm_out_file, + "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n", + label_num, label_num); + + targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num); + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, S_COMPILE3); + putc ('\n', asm_out_file); + + /* Microsoft has the flags as a bitfield, with the bottom 8 bits being the + language constant, and the reset being MSVC-specific stuff. */ + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, language_constant ()); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, target_processor ()); + putc ('\n', asm_out_file); + + /* Write 8 uint16_ts for the frontend and backend versions. As with GAS, we + zero these, as it's easier to record the version in the compiler + string. */ + for (unsigned int i = 0; i < 8; i++) + { + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, 0); + putc ('\n', asm_out_file); + } + + ASM_OUTPUT_ASCII (asm_out_file, compiler_name, sizeof (compiler_name) - 1); + ASM_OUTPUT_ASCII (asm_out_file, version_string, strlen (version_string) + 1); + + ASM_OUTPUT_ALIGN (asm_out_file, 2); + + targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num); +} + +/* Write the CodeView symbols into the .debug$S section. */ + +static void +write_codeview_symbols (void) +{ + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, DEBUG_S_SYMBOLS); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + asm_fprintf (asm_out_file, "%LLcv_syms_end - %LLcv_syms_start\n"); + + asm_fprintf (asm_out_file, "%LLcv_syms_start:\n"); + + write_compile3_symbol (); + + asm_fprintf (asm_out_file, "%LLcv_syms_end:\n"); +} + /* Finish CodeView debug info emission. */ void @@ -606,6 +731,7 @@ codeview_debug_finish (void) write_strings_table (); write_source_files (); write_line_numbers (); + write_codeview_symbols (); } #endif