public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Bruno Larsen <blarsen@redhat.com>
To: gdb-patches@sourceware.org, Bruno Larsen <blarsen@redhat.com>
Cc: simark@simark.ca
Subject: [PING][PATCH v3] gdb: Fix issue with Clang CLI macros
Date: Wed, 2 Nov 2022 09:19:05 +0100	[thread overview]
Message-ID: <8240e463-4800-7a48-33fa-79351bc8f7eb@redhat.com> (raw)
In-Reply-To: <20221018132215.2593111-1-blarsen@redhat.com>

Ping

Cheers,
Bruno

On 18/10/2022 15:22, Bruno Larsen wrote:
> Clang up to version 15 (current) adds macros that were defined in the
> command line or by "other means", according to the Dwarf specification,
> after the last DW_MACRO_end_file, instead of before the first
> DW_MACRO_start_file, as the specification dictates.  When GDB reads the
> macros after the last file is closed, the macros never end up "in scope"
> and so we can't print them.  This has been submitted as a bug to Clang
> developers (https://github.com/llvm/llvm-project/issues/54506), and PR
> macros/29034 was opened for GDB to keep track of this.
>
> Seeing as there is no expected date for it to be fixed, add a workaround
> for all current versions of Clang.  The workaround detects when
> the main file would be closed and if the producer is Clang, and turns
> that operation into a noop, so we keep a reference to the current_file
> as those macros are read.
>
> A test case was added to confirm the functionality, and the KFAIL for
> running gdb.base/macro-source-path when using clang.
>
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29034
> ---
>   gdb/dwarf2/cu.h                              |  1 +
>   gdb/dwarf2/macro.c                           | 19 +++-
>   gdb/dwarf2/macro.h                           |  2 +-
>   gdb/dwarf2/read.c                            | 13 ++-
>   gdb/dwarf2/read.h                            |  2 +
>   gdb/producer.c                               | 24 +++++
>   gdb/producer.h                               |  4 +
>   gdb/testsuite/gdb.base/macro-source-path.exp |  5 -
>   gdb/testsuite/gdb.dwarf2/clang-cli-macro.c   | 20 ++++
>   gdb/testsuite/gdb.dwarf2/clang-cli-macro.exp | 98 ++++++++++++++++++++
>   10 files changed, 177 insertions(+), 11 deletions(-)
>   create mode 100644 gdb/testsuite/gdb.dwarf2/clang-cli-macro.c
>   create mode 100644 gdb/testsuite/gdb.dwarf2/clang-cli-macro.exp
>
> diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h
> index 23cb3d21b2e..51638e71b19 100644
> --- a/gdb/dwarf2/cu.h
> +++ b/gdb/dwarf2/cu.h
> @@ -264,6 +264,7 @@ struct dwarf2_cu
>     bool producer_is_icc : 1;
>     bool producer_is_icc_lt_14 : 1;
>     bool producer_is_codewarrior : 1;
> +  bool producer_is_clang : 1;
>   
>     /* When true, the file that we're processing is known to have
>        debugging info for C++ namespaces.  GCC 3.3.x did not produce
> diff --git a/gdb/dwarf2/macro.c b/gdb/dwarf2/macro.c
> index 38c0fdfec73..7224c45682a 100644
> --- a/gdb/dwarf2/macro.c
> +++ b/gdb/dwarf2/macro.c
> @@ -445,7 +445,7 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile,
>   			  struct dwarf2_section_info *str_section,
>   			  struct dwarf2_section_info *str_offsets_section,
>   			  gdb::optional<ULONGEST> str_offsets_base,
> -			  htab_t include_hash)
> +			  htab_t include_hash, struct dwarf2_cu *cu)
>   {
>     struct objfile *objfile = per_objfile->objfile;
>     enum dwarf_macro_record_type macinfo_type;
> @@ -672,6 +672,17 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile,
>   	  if (! current_file)
>   	    complaint (_("macro debug info has an unmatched "
>   			 "`close_file' directive"));
> +	  else if (current_file->included_by == nullptr
> +		   && producer_is_clang (cu))
> +	    {
> +	      /* Clang, until the current version, misplaces some macro
> +		 definitions - such as ones defined in the command line,
> +		 putting them after the last DW_MACRO_end_file instead of
> +		 before the first DW_MACRO_start_file.  Since at the time
> +		 of writing there is no clang version with this bug fixed,
> +		 we check for any clang producer.  This should be changed
> +		 to producer_is_clang_lt_XX when possible. */
> +	    }
>   	  else
>   	    {
>   	      current_file = current_file->included_by;
> @@ -751,7 +762,7 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile,
>   					  current_file, lh, section,
>   					  section_is_gnu, is_dwz, offset_size,
>   					  str_section, str_offsets_section,
> -					  str_offsets_base, include_hash);
> +					  str_offsets_base, include_hash, cu);
>   
>   		htab_remove_elt (include_hash, (void *) new_mac_ptr);
>   	      }
> @@ -795,7 +806,7 @@ dwarf_decode_macros (dwarf2_per_objfile *per_objfile,
>   		     unsigned int offset, struct dwarf2_section_info *str_section,
>   		     struct dwarf2_section_info *str_offsets_section,
>   		     gdb::optional<ULONGEST> str_offsets_base,
> -		     int section_is_gnu)
> +		     int section_is_gnu, struct dwarf2_cu *cu)
>   {
>     bfd *abfd;
>     const gdb_byte *mac_ptr, *mac_end;
> @@ -956,5 +967,5 @@ dwarf_decode_macros (dwarf2_per_objfile *per_objfile,
>     dwarf_decode_macro_bytes (per_objfile, builder, abfd, mac_ptr, mac_end,
>   			    current_file, lh, section, section_is_gnu, 0,
>   			    offset_size, str_section, str_offsets_section,
> -			    str_offsets_base, include_hash.get ());
> +			    str_offsets_base, include_hash.get (), cu);
>   }
> diff --git a/gdb/dwarf2/macro.h b/gdb/dwarf2/macro.h
> index e8c33a34a8d..02753ef377a 100644
> --- a/gdb/dwarf2/macro.h
> +++ b/gdb/dwarf2/macro.h
> @@ -31,6 +31,6 @@ extern void dwarf_decode_macros (dwarf2_per_objfile *per_objfile,
>   				 dwarf2_section_info *str_section,
>   				 dwarf2_section_info *str_offsets_section,
>   				 gdb::optional<ULONGEST> str_offsets_base,
> -				 int section_is_gnu);
> +				 int section_is_gnu, struct dwarf2_cu *cu);
>   
>   #endif /* GDB_DWARF2_MACRO_H */
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index 78f4cc1f60d..b3b2c70b1c3 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -9484,6 +9484,15 @@ producer_is_gcc_lt_4_3 (struct dwarf2_cu *cu)
>     return cu->producer_is_gcc_lt_4_3;
>   }
>   
> +bool
> +producer_is_clang (struct dwarf2_cu *cu)
> +{
> +  if (!cu->checked_producer)
> +    check_producer (cu);
> +
> +  return cu->producer_is_clang;
> +}
> +
>   static file_and_directory &
>   find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu)
>   {
> @@ -13343,6 +13352,8 @@ check_producer (struct dwarf2_cu *cu)
>       }
>     else if (startswith (cu->producer, "CodeWarrior S12/L-ISA"))
>       cu->producer_is_codewarrior = true;
> +  else if (producer_is_clang (cu->producer, &major, &minor))
> +    cu->producer_is_clang = true;
>     else
>       {
>         /* For other non-GCC compilers, expect their behavior is DWARF version
> @@ -23363,7 +23374,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
>   
>     dwarf_decode_macros (per_objfile, builder, section, lh,
>   		       offset_size, offset, str_section, str_offsets_section,
> -		       str_offsets_base, section_is_gnu);
> +		       str_offsets_base, section_is_gnu, cu);
>   }
>   
>   /* Return the .debug_loc section to use for CU.
> diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
> index 5f01fbc1025..a47e6bf5144 100644
> --- a/gdb/dwarf2/read.h
> +++ b/gdb/dwarf2/read.h
> @@ -761,4 +761,6 @@ extern void dwarf2_get_section_info (struct objfile *,
>   				     asection **, const gdb_byte **,
>   				     bfd_size_type *);
>   
> +extern bool producer_is_clang (struct dwarf2_cu *cu);
> +
>   #endif /* DWARF2READ_H */
> diff --git a/gdb/producer.c b/gdb/producer.c
> index ef1dd93afbc..f65823426d1 100644
> --- a/gdb/producer.c
> +++ b/gdb/producer.c
> @@ -127,6 +127,30 @@ producer_is_llvm (const char *producer)
>   				 || startswith (producer, " F90 Flang ")));
>   }
>   
> +/* See producer.h.  */
> +
> +bool
> +producer_is_clang (const char *producer, int *major, int *minor)
> +{
> +  if (producer != nullptr && startswith (producer, "clang version "))
> +    {
> +      int maj, min;
> +      if (major == nullptr)
> +	major = &maj;
> +      if (minor == nullptr)
> +	minor = &min;
> +
> +      /* The full producer string will look something like
> +	 "clang version XX.X.X ..."
> +	 So we can safely ignore all characters before the first digit.  */
> +      const char *cs = producer + strlen ("clang version ");
> +
> +      if (sscanf (cs, "%d.%d", major, minor) == 2)
> +	return true;
> +    }
> +  return false;
> +}
> +
>   #if defined GDB_SELF_TEST
>   namespace selftests {
>   namespace producer {
> diff --git a/gdb/producer.h b/gdb/producer.h
> index f7c19368bc6..b75cfae6569 100644
> --- a/gdb/producer.h
> +++ b/gdb/producer.h
> @@ -41,4 +41,8 @@ extern bool producer_is_icc (const char *producer, int *major, int *minor);
>      false otherwise.*/
>   extern bool producer_is_llvm (const char *producer);
>   
> +/* Returns true if the given PRODUCER string is clang, false otherwise.
> +   Sets MAJOR and MINOR accordingly, if not NULL.  */
> +extern bool producer_is_clang (const char *producer, int *major, int *minor);
> +
>   #endif
> diff --git a/gdb/testsuite/gdb.base/macro-source-path.exp b/gdb/testsuite/gdb.base/macro-source-path.exp
> index edbb4aee8e9..b553d088d09 100644
> --- a/gdb/testsuite/gdb.base/macro-source-path.exp
> +++ b/gdb/testsuite/gdb.base/macro-source-path.exp
> @@ -62,11 +62,6 @@ proc test { src name } {
>   	}
>   
>   	# Print the macro that is defined on the command-line.
> -	if { [test_compiler_info "clang-*"] } {
> -	    # This is really a clang bug, it puts the macros defined on the command
> -	    # line after the main source file, in the macro table.
> -	    setup_kfail "gdb/29034" "*-*-*"
> -	}
>   	gdb_test "print ONE" " = 1"
>   
>   	# Print the macro that is defined in the main file.
> diff --git a/gdb/testsuite/gdb.dwarf2/clang-cli-macro.c b/gdb/testsuite/gdb.dwarf2/clang-cli-macro.c
> new file mode 100644
> index 00000000000..749bcc1580e
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/clang-cli-macro.c
> @@ -0,0 +1,20 @@
> +/* Copyright 2022 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 this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +int
> +main (void)
> +{
> +  asm ("main_label: .globl main_label");
> +}
> diff --git a/gdb/testsuite/gdb.dwarf2/clang-cli-macro.exp b/gdb/testsuite/gdb.dwarf2/clang-cli-macro.exp
> new file mode 100644
> index 00000000000..ea701468cdb
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/clang-cli-macro.exp
> @@ -0,0 +1,98 @@
> +# This testcase is part of GDB, the GNU debugger.
> +
> +# Copyright 2022 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 this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +# Clang has this bug where it puts the macros defined on the command-line
> +# after the main file portion (see PR 29034) and:
> +# https://github.com/llvm/llvm-project/issues/54506
> +# Test that GDB is still able to print macros in clang versions that
> +# have this bug.
> +
> +load_lib dwarf.exp
> +
> +if {![dwarf2_support]} {
> +    return 0
> +}
> +if {![test_compiler_info gcc-*-*]} {
> +    untested "dwarf assembler needs GCC"
> +}
> +
> +standard_testfile .c .S
> +
> +lassign [function_range main $srcdir/$subdir/$srcfile] \
> +    main_start main_len
> +
> +set asm_file [standard_output_file $srcfile2]
> +
> +Dwarf::assemble $asm_file {
> +    declare_labels L cu_macros
> +
> +    cu {} {
> +	DW_TAG_compile_unit {
> +	    {DW_AT_producer "clang version 15.0.0"}
> +	    {DW_AT_language @DW_LANG_C11}
> +	    {DW_AT_name $::srcfile}
> +	    {DW_AT_macros $cu_macros DW_FORM_sec_offset}
> +	    {DW_AT_stmt_list $L DW_FORM_sec_offset}
> +	} {
> +	    declare_labels int_type
> +
> +	    int_type: DW_TAG_base_type {
> +		{DW_AT_byte_size 4 DW_FORM_sdata}
> +		{DW_AT_encoding  @DW_ATE_signed}
> +		{DW_AT_name int}
> +	    }
> +	    DW_TAG_subprogram {
> +		{MACRO_AT_func {main}}
> +		{type :$int_type}
> +	    }
> +	}
> +    }
> +    lines {version 2} L {
> +	file_name $::srcfile 1
> +	program {
> +	    DW_LNE_set_address $::main_start
> +	    line 10
> +	    DW_LNS_copy
> +	    DW_LNE_set_address "$::main_start + $::main_len"
> +	    DW_LNE_end_sequence
> +	}
> +    }
> +
> +    # Define the .debug_macro section.
> +    macro {
> +	cu_macros: unit {
> +	    "debug-line-offset-label" $L
> +	} {
> +	    start_file 0 1
> +		# A macro defined at line 1 of the main file.
> +		define 1 "TWO 2"
> +	    end_file
> +	    define 0 "ONE 1"
> +	}
> +    }
> +}
> +
> +if {[prepare_for_testing "failed to prepare" $testfile [list $srcfile $asm_file] {nodebug}]} {
> +    return
> +}
> +
> +if {![runto_main]} {
> +    return
> +}
> +
> +gdb_test "print TWO" "= 2" "print simple macro"
> +gdb_test "print ONE" "= 1" "print defined from CLI"


  reply	other threads:[~2022-11-02  8:19 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-18 13:22 [PATCH " Bruno Larsen
2022-11-02  8:19 ` Bruno Larsen [this message]
2022-11-02 12:36 ` Simon Marchi
2022-11-03 12:58   ` Bruno Larsen
2022-11-03 13:07     ` Simon Marchi
2022-11-03 13:08       ` Bruno Larsen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8240e463-4800-7a48-33fa-79351bc8f7eb@redhat.com \
    --to=blarsen@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=simark@simark.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).