From eaeeeaca5f5d28ace4545a963866cd4e8f8a3666 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 20 Oct 2025 09:49:13 +0100 Subject: [PATCH 1/5] [llvm][dwarfdump] Pretty-print DW_AT_language_version in non-verbose dwarfdump --- llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 25 ++++++++++++++- .../X86/DW_AT_language_version-pretty.s | 32 +++++++++++++++++++ .../X86/DW_AT_language_version.s | 21 +++++++----- 3 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index 212a0c039298b..5c4fbfad4e8d5 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -107,6 +107,27 @@ static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) { return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference(); } +static llvm::StringRef +prettyLanguageVersionString(const DWARFAttribute &AttrValue, + const DWARFDie &Die) { + assert(AttrValue.Attr == DW_AT_language_version); + + auto NameForm = Die.find(DW_AT_language_name); + if (!NameForm) + return {}; + + auto LName = NameForm->getAsUnsignedConstant(); + if (!LName) + return {}; + + auto LVersion = AttrValue.Value.getAsUnsignedConstant(); + if (!LVersion) + return {}; + + return llvm::dwarf::LanguageDescription( + static_cast(*LName), *LVersion); +} + static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, const DWARFAttribute &AttrValue, unsigned Indent, DIDumpOptions DumpOpts) { @@ -143,7 +164,9 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, } } } - } else if (std::optional Val = FormValue.getAsUnsignedConstant()) + } else if (Attr == llvm::dwarf::DW_AT_language_version && !DumpOpts.Verbose) + Name = prettyLanguageVersionString(AttrValue, Die); + else if (std::optional Val = FormValue.getAsUnsignedConstant()) Name = AttributeValueString(Attr, *Val); if (!Name.empty()) diff --git a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s new file mode 100644 index 0000000000000..f9986a9cf2fb0 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s @@ -0,0 +1,32 @@ +# Demonstrate dumping DW_AT_language_version in human-readable form. +# RUN: llvm-mc -triple=x86_64--linux -filetype=obj < %s | \ +# RUN: llvm-dwarfdump - | FileCheck %s --implicit-check-not "DW_AT_language_version" + +# CHECK: .debug_info contents: +# CHECK: DW_AT_language_name (DW_LNAME_C) +# CHECK: DW_AT_language_version (C11) + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_no + .ascii "\220\001" # DW_AT_language_name + .byte 5 # DW_FORM_data2 + .ascii "\221\001" # DW_AT_language_version + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section .debug_info,"",@progbits + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # Unit type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] DW_TAG_compile_unit + .short 3 # DW_AT_language_name + .long 201112 # DW_AT_language_version + .byte 0 +.Ldebug_info_end0: diff --git a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s index f1be8fdf6cd3e..e9bcfdedd346d 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s @@ -1,13 +1,18 @@ # Demonstrate dumping DW_AT_language_version. -# RUN: llvm-mc -triple=x86_64--linux -filetype=obj < %s | \ -# RUN: llvm-dwarfdump -v - | FileCheck %s +# RUN: llvm-mc -triple=x86_64--linux -filetype=obj -o %t.o < %s +# RUN: llvm-dwarfdump -v %t.o | FileCheck %s --check-prefix=VERBOSE +# RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=NO-VERBOSE -# CHECK: .debug_abbrev contents: -# CHECK: DW_AT_language_version DW_FORM_data4 -# CHECK: DW_AT_language_version DW_FORM_data2 -# CHECK: .debug_info contents: -# CHECK: DW_AT_language_version [DW_FORM_data4] (201402) -# CHECK: DW_AT_language_version [DW_FORM_data2] (0) +# VERBOSE: .debug_abbrev contents: +# VERBOSE: DW_AT_language_version DW_FORM_data4 +# VERBOSE: DW_AT_language_version DW_FORM_data2 +# VERBOSE: .debug_info contents: +# VERBOSE: DW_AT_language_version [DW_FORM_data4] (201402) +# VERBOSE: DW_AT_language_version [DW_FORM_data2] (0) + +# NO-VERBOSE: .debug_info contents: +# NO-VERBOSE: DW_AT_language_version (201402) +# NO-VERBOSE: DW_AT_language_version (0) .section .debug_abbrev,"",@progbits .byte 1 # Abbreviation Code From 662b7e6e417d0aec84fb1b84603d80cb5236e404 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 20 Oct 2025 12:56:58 +0100 Subject: [PATCH 2/5] fixup! fix test --- .../Generic/compileunit-source-language-name.ll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll b/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll index f5dcf01c7e89f..90e0daf7648f3 100644 --- a/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll +++ b/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll @@ -1,11 +1,11 @@ ; AIX doesn't have support for DWARF 6 DW_AT_language_name ; XFAIL: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}} -; RUN: %llc_dwarf -filetype=obj -O0 < %s | llvm-dwarfdump -debug-info - | FileCheck %s --implicit-check-not "DW_AT_language" +; RUN: %llc_dwarf -filetype=obj -O0 < %s | llvm-dwarfdump -debug-info -v - | FileCheck %s --implicit-check-not "DW_AT_language" -; CHECK: DW_AT_language_name (DW_LNAME_ObjC_plus_plus) -; CHECK: DW_AT_language_name (DW_LNAME_C_plus_plus) -; CHECK: DW_AT_language_version (201100) -; CHECK: DW_AT_language_name (DW_LNAME_Rust) +; CHECK: DW_AT_language_name [DW_FORM_data2] (DW_LNAME_ObjC_plus_plus) +; CHECK: DW_AT_language_name [DW_FORM_data2] (DW_LNAME_C_plus_plus) +; CHECK: DW_AT_language_version [DW_FORM_data4] (201100) +; CHECK: DW_AT_language_name [DW_FORM_data2] (DW_LNAME_Rust) ; CHECK-NOT: DW_AT_language_version @x = global i32 0, align 4, !dbg !0 From 9deb8f4a3eb1e6fb5e805ca81c3c77ca05e3e404 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 20 Oct 2025 15:09:56 +0100 Subject: [PATCH 3/5] fixup! print prettfied name in verbose mode too --- llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 34 ++++++++++++++----- .../compileunit-source-language-name.ll | 2 +- .../X86/DW_AT_language_version-pretty.s | 15 +++++--- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index 5c4fbfad4e8d5..73217511f1b34 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -110,7 +110,8 @@ static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) { static llvm::StringRef prettyLanguageVersionString(const DWARFAttribute &AttrValue, const DWARFDie &Die) { - assert(AttrValue.Attr == DW_AT_language_version); + if (AttrValue.Attr != DW_AT_language_version) + return {}; auto NameForm = Die.find(DW_AT_language_name); if (!NameForm) @@ -164,20 +165,31 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, } } } - } else if (Attr == llvm::dwarf::DW_AT_language_version && !DumpOpts.Verbose) - Name = prettyLanguageVersionString(AttrValue, Die); - else if (std::optional Val = FormValue.getAsUnsignedConstant()) + } else if (std::optional Val = FormValue.getAsUnsignedConstant()) Name = AttributeValueString(Attr, *Val); - if (!Name.empty()) - WithColor(OS, Color) << Name; - else if (Attr == DW_AT_decl_line || Attr == DW_AT_decl_column || - Attr == DW_AT_call_line || Attr == DW_AT_call_column || - Attr == DW_AT_language_version) { + auto DumpUnsignedConstant = [&OS, + &DumpOpts](const DWARFFormValue &FormValue) { if (std::optional Val = FormValue.getAsUnsignedConstant()) OS << *Val; else FormValue.dump(OS, DumpOpts); + }; + + llvm::StringRef PrettyVersionName = + prettyLanguageVersionString(AttrValue, Die); + const bool ShouldDumpRawLanguageVersion = + Attr == DW_AT_language_version && + (DumpOpts.Verbose || PrettyVersionName.empty()); + + if (!Name.empty()) + WithColor(OS, Color) << Name; + else if (Attr == DW_AT_decl_line || Attr == DW_AT_decl_column || + Attr == DW_AT_call_line || Attr == DW_AT_call_column) { + DumpUnsignedConstant(FormValue); + } else if (Attr == DW_AT_language_version) { + if (ShouldDumpRawLanguageVersion) + DumpUnsignedConstant(FormValue); } else if (Attr == DW_AT_low_pc && (FormValue.getAsAddress() == dwarf::computeTombstoneAddress(U->getAddressByteSize()))) { @@ -249,6 +261,10 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, DumpOpts.RecoverableErrorHandler(createStringError( errc::invalid_argument, "decoding address ranges: %s", toString(RangesOrError.takeError()).c_str())); + } else if (Attr == DW_AT_language_version) { + if (!PrettyVersionName.empty()) + WithColor(OS, Color) << (ShouldDumpRawLanguageVersion ? " " : "") + << PrettyVersionName; } OS << ")\n"; diff --git a/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll b/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll index 90e0daf7648f3..58b5104592931 100644 --- a/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll +++ b/llvm/test/DebugInfo/Generic/compileunit-source-language-name.ll @@ -4,7 +4,7 @@ ; CHECK: DW_AT_language_name [DW_FORM_data2] (DW_LNAME_ObjC_plus_plus) ; CHECK: DW_AT_language_name [DW_FORM_data2] (DW_LNAME_C_plus_plus) -; CHECK: DW_AT_language_version [DW_FORM_data4] (201100) +; CHECK: DW_AT_language_version [DW_FORM_data4] (201100 C++11) ; CHECK: DW_AT_language_name [DW_FORM_data2] (DW_LNAME_Rust) ; CHECK-NOT: DW_AT_language_version diff --git a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s index f9986a9cf2fb0..3af6fa922ae99 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s @@ -1,10 +1,15 @@ # Demonstrate dumping DW_AT_language_version in human-readable form. -# RUN: llvm-mc -triple=x86_64--linux -filetype=obj < %s | \ -# RUN: llvm-dwarfdump - | FileCheck %s --implicit-check-not "DW_AT_language_version" +# RUN: llvm-mc -triple=x86_64--linux -filetype=obj -o %t.o < %s +# RUN: llvm-dwarfdump %t.o -v | FileCheck %s --check-prefix=VERBOSE +# RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=NO-VERBOSE -# CHECK: .debug_info contents: -# CHECK: DW_AT_language_name (DW_LNAME_C) -# CHECK: DW_AT_language_version (C11) +# VERBOSE: .debug_info contents: +# VERBOSE: DW_AT_language_name [DW_FORM_data2] (DW_LNAME_C) +# VERBOSE: DW_AT_language_version [DW_FORM_data4] (201112 C11) + +# NO-VERBOSE: .debug_info contents: +# NO-VERBOSE: DW_AT_language_name (DW_LNAME_C) +# NO-VERBOSE: DW_AT_language_version (C11) .section .debug_abbrev,"",@progbits .byte 1 # Abbreviation Code From 16ee162d5d8b090ae3fc10081837e8240d8715f5 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 21 Oct 2025 08:19:39 +0100 Subject: [PATCH 4/5] fixup! no const local --- llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index 73217511f1b34..db5cc37c93f90 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -178,7 +178,7 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, llvm::StringRef PrettyVersionName = prettyLanguageVersionString(AttrValue, Die); - const bool ShouldDumpRawLanguageVersion = + bool ShouldDumpRawLanguageVersion = Attr == DW_AT_language_version && (DumpOpts.Verbose || PrettyVersionName.empty()); From 20e041148f5008572f1197ee029545e680f57187 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 21 Oct 2025 08:29:05 +0100 Subject: [PATCH 5/5] fixup! add test explanation; add test-case for invalid DW_AT_language_name --- .../llvm-dwarfdump/X86/DW_AT_language_version-pretty.s | 7 +++++++ .../test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s index 3af6fa922ae99..b889ce5cfdcc3 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version-pretty.s @@ -6,10 +6,14 @@ # VERBOSE: .debug_info contents: # VERBOSE: DW_AT_language_name [DW_FORM_data2] (DW_LNAME_C) # VERBOSE: DW_AT_language_version [DW_FORM_data4] (201112 C11) +# VERBOSE: DW_AT_language_name [DW_FORM_data2] (0x0000) +# VERBOSE: DW_AT_language_version [DW_FORM_data4] (12 Unknown) # NO-VERBOSE: .debug_info contents: # NO-VERBOSE: DW_AT_language_name (DW_LNAME_C) # NO-VERBOSE: DW_AT_language_version (C11) +# NO-VERBOSE: DW_AT_language_name (0x0000) +# NO-VERBOSE: DW_AT_language_version (Unknown) .section .debug_abbrev,"",@progbits .byte 1 # Abbreviation Code @@ -33,5 +37,8 @@ .byte 1 # Abbrev [1] DW_TAG_compile_unit .short 3 # DW_AT_language_name .long 201112 # DW_AT_language_version + .byte 1 # Abbrev [1] DW_TAG_compile_unit + .short 0 # DW_AT_language_name + .long 12 # DW_AT_language_version .byte 0 .Ldebug_info_end0: diff --git a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s index e9bcfdedd346d..985836fcd1ef5 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s @@ -1,4 +1,5 @@ -# Demonstrate dumping DW_AT_language_version. +# Demonstrate dumping DW_AT_language_version without an +# accompanying DW_AT_language_name. # RUN: llvm-mc -triple=x86_64--linux -filetype=obj -o %t.o < %s # RUN: llvm-dwarfdump -v %t.o | FileCheck %s --check-prefix=VERBOSE # RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=NO-VERBOSE