[PING] [PATCH] gdb: Fix issue with Clang CLI macros
Bruno Larsen
blarsen@redhat.com
Wed May 4 12:50:58 GMT 2022
ping
Cheers!
Bruno Larsen
On 4/20/22 14:41, Bruno Larsen wrote:
> Clang up to the current version 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. This has been
> submitted as a bug to Clang developers, but seeing as there is no
> expected date for it to be fixed, a workaround was added 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.
>
> This patch fixes PR macros/29034, and can be tested by running
> gdb.base/macscp.exp using clang, the test printing FROM_COMMANDLINE
> should be fixed.
> ---
> gdb/dwarf2/cu.h | 1 +
> gdb/dwarf2/macro.c | 17 +++++++++++++----
> gdb/dwarf2/macro.h | 2 +-
> gdb/dwarf2/read.c | 15 ++++++++++++++-
> gdb/dwarf2/read.h | 2 ++
> gdb/producer.c | 26 ++++++++++++++++++++++++++
> gdb/producer.h | 4 ++++
> 7 files changed, 61 insertions(+), 6 deletions(-)
>
> diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h
> index 6b72ec234bf..3b7f92be406 100644
> --- a/gdb/dwarf2/cu.h
> +++ b/gdb/dwarf2/cu.h
> @@ -257,6 +257,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_le_14 : 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 99c3653a2c3..305af1a7f47 100644
> --- a/gdb/dwarf2/macro.c
> +++ b/gdb/dwarf2/macro.c
> @@ -431,7 +431,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;
> @@ -658,6 +658,15 @@ 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_le_14 (cu))
> + {
> + /* Clang, until the current version, misplaces macro definitions,
> + putting them after the last DW_MACRO_end_file instead of
> + before the first DW_MACRO_start_file. This condition should be
> + removed once we can reasonably expect most clang users to have
> + updated to a fixed version. */
> + }
> else
> {
> current_file = current_file->included_by;
> @@ -737,7 +746,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);
> }
> @@ -781,7 +790,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;
> @@ -942,5 +951,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 698720276a9..1fc5d5d3dd8 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -9454,6 +9454,15 @@ producer_is_gcc_lt_4_3 (struct dwarf2_cu *cu)
> return cu->producer_is_gcc_lt_4_3;
> }
>
> +bool
> +producer_is_clang_le_14 (struct dwarf2_cu *cu)
> +{
> + if (!cu->checked_producer)
> + check_producer (cu);
> +
> + return cu->producer_is_clang_le_14;
> +}
> +
> static file_and_directory &
> find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu)
> {
> @@ -13295,6 +13304,10 @@ 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_le_14 = major <= 14;
> + }
> else
> {
> /* For other non-GCC compilers, expect their behavior is DWARF version
> @@ -23218,7 +23231,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 be3b9d19601..23f040a6ca8 100644
> --- a/gdb/dwarf2/read.h
> +++ b/gdb/dwarf2/read.h
> @@ -677,4 +677,6 @@ extern void dwarf2_get_section_info (struct objfile *,
> asection **, const gdb_byte **,
> bfd_size_type *);
>
> +extern bool producer_is_clang_le_14(struct dwarf2_cu *cu);
> +
> #endif /* DWARF2READ_H */
> diff --git a/gdb/producer.c b/gdb/producer.c
> index ef1dd93afbc..a9fb7dd8245 100644
> --- a/gdb/producer.c
> +++ b/gdb/producer.c
> @@ -127,6 +127,32 @@ producer_is_llvm (const char *producer)
> || startswith (producer, " F90 Flang ")));
> }
>
> +/* see producer.h */
> +
> +bool
> +producer_is_clang (const char* producer, int *major, int* minor)
> +{
> + const char *cs;
> +
> + if (producer != nullptr && startswith (producer, "clang "))
> + {
> + int maj, min;
> + if (major == nullptr)
> + major = &maj;
> + if (minor == nullptr)
> + minor = &min;
> +
> + /* The full producer sting will look something like
> + "clang version XX.X.X ..."
> + So we can safely ignore all characters before the first digit. */
> + 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
More information about the Gdb-patches
mailing list