[llvm] [llvm-debuginfo-analyzer] Fix crash with WebAssembly dead code (PR #141616)

Carlos Alberto Enciso via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 11 08:14:53 PDT 2025


https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/141616

>From 4d1a2ebcefb7a1d5cdb032db95bcc96bd33038d4 Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <Carlos.Enciso at sony.com>
Date: Tue, 27 May 2025 15:44:50 +0100
Subject: [PATCH 1/5] [llvm-debuginfo-analyzer] Fix crash with WebAssembly dead
 code

https://github.com/llvm/llvm-project/issues/136772
Incorrect handling of 'tombstone' value for WebAssembly.

llvm-debuginfo-analyzer already uses the tombstone approach
to identify dead code. Currently, the tombstone value is
evaluated as std::numeric_limits<uint64_t>::max(). Which is
wrong as it does not take into account the 'Address Byte Size'
from the Compile Unit header.
---
 .../llvm/DebugInfo/LogicalView/Core/LVRange.h |   9 +-
 .../DebugInfo/LogicalView/Core/LVReader.h     |   7 +
 .../LogicalView/Readers/LVDWARFReader.cpp     |  15 +-
 .../WebAssembly/Inputs/test-clang-tombstone.s | 366 ++++++++++++++++++
 .../WebAssembly/wasm-crash-tombstone.test     |  44 +++
 5 files changed, 434 insertions(+), 7 deletions(-)
 create mode 100644 llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s
 create mode 100644 llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test

diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
index 07d5813e5b19b..ecd5d524a195c 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
@@ -55,11 +55,14 @@ class LLVM_ABI LVRange final : public LVObject {
   LVAllocator Allocator;
   LVRangesTree RangesTree;
   LVRangeEntries RangeEntries;
-  LVAddress Lower = MaxAddress;
+  LVAddress TombstoneAddress;
+  LVAddress Lower;
   LVAddress Upper = 0;
 
 public:
-  LVRange() : LVObject(), RangesTree(Allocator) {}
+  LVRange(LVAddress Address = MaxAddress)
+      : LVObject(),
+        RangesTree(Allocator), TombstoneAddress(Address), Lower(Address) {}
   LVRange(const LVRange &) = delete;
   LVRange &operator=(const LVRange &) = delete;
   ~LVRange() = default;
@@ -76,7 +79,7 @@ class LLVM_ABI LVRange final : public LVObject {
 
   void clear() {
     RangeEntries.clear();
-    Lower = MaxAddress;
+    Lower = TombstoneAddress;
     Upper = 0;
   }
   bool empty() const { return RangeEntries.empty(); }
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
index 371bffb2ed163..a3140df627848 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
@@ -156,6 +156,10 @@ class LLVM_ABI LVReader {
                        LVAddress LowerAddress, LVAddress UpperAddress);
   LVRange *getSectionRanges(LVSectionIndex SectionIndex);
 
+  // Tombstone value. Assume 64 bits. The value is updated for each
+  // Compile Unit that is processed.
+  LVAddress TombstoneAddress = MaxAddress;
+
   // Record Compilation Unit entry.
   void addCompileUnitOffset(LVOffset Offset, LVScopeCompileUnit *CompileUnit) {
     CompileUnits.emplace(Offset, CompileUnit);
@@ -282,6 +286,9 @@ class LLVM_ABI LVReader {
     return CompileUnit->getCPUType();
   }
 
+  void setTombstoneAddress(LVAddress Address) { TombstoneAddress = Address; }
+  LVAddress getTombstoneAddress() const { return TombstoneAddress; }
+
   // Access to the scopes root.
   LVScopeRoot *getScopesRoot() const { return Root; }
 
diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
index 7ff96ae90a7fd..95b7007d119bc 100644
--- a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
@@ -214,10 +214,11 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
         }
       }
       if (FoundLowPC) {
-        if (CurrentLowPC == MaxAddress)
+        if (CurrentLowPC == getTombstoneAddress())
           CurrentElement->setIsDiscarded();
-        // Consider the case of WebAssembly.
-        CurrentLowPC += WasmCodeSectionOffset;
+        else
+          // Consider the case of WebAssembly.
+          CurrentLowPC += WasmCodeSectionOffset;
         if (CurrentElement->isCompileUnit())
           setCUBaseAddress(CurrentLowPC);
       }
@@ -271,7 +272,8 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die,
       DWARFAddressRangesVector Ranges = RangesOrError.get();
       for (DWARFAddressRange &Range : Ranges) {
         // This seems to be a tombstone for empty ranges.
-        if (Range.LowPC == Range.HighPC)
+        if ((Range.LowPC == Range.HighPC) ||
+            (Range.LowPC = getTombstoneAddress()))
           continue;
         // Store the real upper limit for the address range.
         if (UpdateHighAddress && Range.HighPC > 0)
@@ -629,6 +631,11 @@ Error LVDWARFReader::createScopes() {
                                          : DwarfContext->dwo_compile_units();
   for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) {
 
+    // Take into account the address byte size for a correct 'tombstone'
+    // value identification.
+    setTombstoneAddress(
+        dwarf::computeTombstoneAddress(CU->getAddressByteSize()));
+
     // Deduction of index used for the line records.
     //
     // For the following test case: test.cpp
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s
new file mode 100644
index 0000000000000..f7e85420b89dd
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s
@@ -0,0 +1,366 @@
+	.text
+	.file	"test.cpp"
+	.globaltype	__stack_pointer, i32
+	.functype	_Z3fooPKijb (i32, i32, i32) -> (i32)
+	.section	.text._Z3fooPKijb,"",@
+	.hidden	_Z3fooPKijb                     # -- Begin function _Z3fooPKijb
+	.globl	_Z3fooPKijb
+	.type	_Z3fooPKijb, at function
+_Z3fooPKijb:                            # @_Z3fooPKijb
+.Lfunc_begin0:
+	.file	1 "/data/projects/scripts/regression-suite/input/general" "test.cpp"
+	.loc	1 2 0                           # test.cpp:2:0
+	.functype	_Z3fooPKijb (i32, i32, i32) -> (i32)
+	.local  	i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32
+# %bb.0:                                # %entry
+	global.get	__stack_pointer
+	local.set	3
+	i32.const	32
+	local.set	4
+	local.get	3
+	local.get	4
+	i32.sub
+	local.set	5
+	local.get	5
+	local.get	0
+	i32.store	24
+	local.get	5
+	local.get	1
+	i32.store	20
+	local.get	2
+	local.set	6
+	local.get	5
+	local.get	6
+	i32.store8	19
+.Ltmp0:
+	.loc	1 3 7 prologue_end              # test.cpp:3:7
+	local.get	5
+	i32.load8_u	19
+	local.set	7
+.Ltmp1:
+	.loc	1 3 7 is_stmt 0                 # test.cpp:3:7
+	i32.const	1
+	local.set	8
+	local.get	7
+	local.get	8
+	i32.and
+	local.set	9
+	block
+	block
+	local.get	9
+	i32.eqz
+	br_if   	0                               # 0: down to label1
+# %bb.1:                                # %if.then
+.Ltmp2:
+	.loc	1 5 19 is_stmt 1                # test.cpp:5:19
+	i32.const	7
+	local.set	10
+	local.get	5
+	local.get	10
+	i32.store	12
+	.loc	1 6 5                           # test.cpp:6:5
+	i32.const	7
+	local.set	11
+	local.get	5
+	local.get	11
+	i32.store	28
+	br      	1                               # 1: down to label0
+.Ltmp3:
+.LBB0_2:                                # %if.end
+	.loc	1 0 5 is_stmt 0                 # test.cpp:0:5
+	end_block                               # label1:
+	.loc	1 8 10 is_stmt 1                # test.cpp:8:10
+	local.get	5
+	i32.load	20
+	local.set	12
+	.loc	1 8 3 is_stmt 0                 # test.cpp:8:3
+	local.get	5
+	local.get	12
+	i32.store	28
+.LBB0_3:                                # %return
+	.loc	1 0 3                           # test.cpp:0:3
+	end_block                               # label0:
+	.loc	1 9 1 is_stmt 1                 # test.cpp:9:1
+	local.get	5
+	i32.load	28
+	local.set	13
+	local.get	13
+	return
+	end_function
+.Ltmp4:
+.Lfunc_end0:
+                                        # -- End function
+	.section	.debug_abbrev,"",@
+	.int8	1                               # Abbreviation Code
+	.int8	17                              # DW_TAG_compile_unit
+	.int8	1                               # DW_CHILDREN_yes
+	.int8	37                              # DW_AT_producer
+	.int8	14                              # DW_FORM_strp
+	.int8	19                              # DW_AT_language
+	.int8	5                               # DW_FORM_data2
+	.int8	3                               # DW_AT_name
+	.int8	14                              # DW_FORM_strp
+	.int8	16                              # DW_AT_stmt_list
+	.int8	23                              # DW_FORM_sec_offset
+	.int8	27                              # DW_AT_comp_dir
+	.int8	14                              # DW_FORM_strp
+	.int8	17                              # DW_AT_low_pc
+	.int8	1                               # DW_FORM_addr
+	.int8	18                              # DW_AT_high_pc
+	.int8	6                               # DW_FORM_data4
+	.int8	0                               # EOM(1)
+	.int8	0                               # EOM(2)
+	.int8	2                               # Abbreviation Code
+	.int8	46                              # DW_TAG_subprogram
+	.int8	1                               # DW_CHILDREN_yes
+	.int8	17                              # DW_AT_low_pc
+	.int8	1                               # DW_FORM_addr
+	.int8	18                              # DW_AT_high_pc
+	.int8	6                               # DW_FORM_data4
+	.int8	64                              # DW_AT_frame_base
+	.int8	24                              # DW_FORM_exprloc
+	.int8	110                             # DW_AT_linkage_name
+	.int8	14                              # DW_FORM_strp
+	.int8	3                               # DW_AT_name
+	.int8	14                              # DW_FORM_strp
+	.int8	58                              # DW_AT_decl_file
+	.int8	11                              # DW_FORM_data1
+	.int8	59                              # DW_AT_decl_line
+	.int8	11                              # DW_FORM_data1
+	.int8	73                              # DW_AT_type
+	.int8	19                              # DW_FORM_ref4
+	.int8	63                              # DW_AT_external
+	.int8	25                              # DW_FORM_flag_present
+	.int8	0                               # EOM(1)
+	.int8	0                               # EOM(2)
+	.int8	3                               # Abbreviation Code
+	.int8	5                               # DW_TAG_formal_parameter
+	.int8	0                               # DW_CHILDREN_no
+	.int8	2                               # DW_AT_location
+	.int8	24                              # DW_FORM_exprloc
+	.int8	3                               # DW_AT_name
+	.int8	14                              # DW_FORM_strp
+	.int8	58                              # DW_AT_decl_file
+	.int8	11                              # DW_FORM_data1
+	.int8	59                              # DW_AT_decl_line
+	.int8	11                              # DW_FORM_data1
+	.int8	73                              # DW_AT_type
+	.int8	19                              # DW_FORM_ref4
+	.int8	0                               # EOM(1)
+	.int8	0                               # EOM(2)
+	.int8	4                               # Abbreviation Code
+	.int8	11                              # DW_TAG_lexical_block
+	.int8	1                               # DW_CHILDREN_yes
+	.int8	17                              # DW_AT_low_pc
+	.int8	1                               # DW_FORM_addr
+	.int8	18                              # DW_AT_high_pc
+	.int8	6                               # DW_FORM_data4
+	.int8	0                               # EOM(1)
+	.int8	0                               # EOM(2)
+	.int8	5                               # Abbreviation Code
+	.int8	52                              # DW_TAG_variable
+	.int8	0                               # DW_CHILDREN_no
+	.int8	2                               # DW_AT_location
+	.int8	24                              # DW_FORM_exprloc
+	.int8	3                               # DW_AT_name
+	.int8	14                              # DW_FORM_strp
+	.int8	58                              # DW_AT_decl_file
+	.int8	11                              # DW_FORM_data1
+	.int8	59                              # DW_AT_decl_line
+	.int8	11                              # DW_FORM_data1
+	.int8	73                              # DW_AT_type
+	.int8	19                              # DW_FORM_ref4
+	.int8	0                               # EOM(1)
+	.int8	0                               # EOM(2)
+	.int8	6                               # Abbreviation Code
+	.int8	22                              # DW_TAG_typedef
+	.int8	0                               # DW_CHILDREN_no
+	.int8	73                              # DW_AT_type
+	.int8	19                              # DW_FORM_ref4
+	.int8	3                               # DW_AT_name
+	.int8	14                              # DW_FORM_strp
+	.int8	58                              # DW_AT_decl_file
+	.int8	11                              # DW_FORM_data1
+	.int8	59                              # DW_AT_decl_line
+	.int8	11                              # DW_FORM_data1
+	.int8	0                               # EOM(1)
+	.int8	0                               # EOM(2)
+	.int8	7                               # Abbreviation Code
+	.int8	36                              # DW_TAG_base_type
+	.int8	0                               # DW_CHILDREN_no
+	.int8	3                               # DW_AT_name
+	.int8	14                              # DW_FORM_strp
+	.int8	62                              # DW_AT_encoding
+	.int8	11                              # DW_FORM_data1
+	.int8	11                              # DW_AT_byte_size
+	.int8	11                              # DW_FORM_data1
+	.int8	0                               # EOM(1)
+	.int8	0                               # EOM(2)
+	.int8	8                               # Abbreviation Code
+	.int8	15                              # DW_TAG_pointer_type
+	.int8	0                               # DW_CHILDREN_no
+	.int8	73                              # DW_AT_type
+	.int8	19                              # DW_FORM_ref4
+	.int8	0                               # EOM(1)
+	.int8	0                               # EOM(2)
+	.int8	9                               # Abbreviation Code
+	.int8	38                              # DW_TAG_const_type
+	.int8	0                               # DW_CHILDREN_no
+	.int8	73                              # DW_AT_type
+	.int8	19                              # DW_FORM_ref4
+	.int8	0                               # EOM(1)
+	.int8	0                               # EOM(2)
+	.int8	0                               # EOM(3)
+	.section	.debug_info,"",@
+.Lcu_begin0:
+	.int32	.Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+	.int16	4                               # DWARF version number
+	.int32	.debug_abbrev0                  # Offset Into Abbrev. Section
+	.int8	4                               # Address Size (in bytes)
+	.int8	1                               # Abbrev [1] 0xb:0xb5 DW_TAG_compile_unit
+	.int32	.Linfo_string0                  # DW_AT_producer
+	.int16	33                              # DW_AT_language
+	.int32	.Linfo_string1                  # DW_AT_name
+	.int32	.Lline_table_start0             # DW_AT_stmt_list
+	.int32	.Linfo_string2                  # DW_AT_comp_dir
+	.int32	.Lfunc_begin0                   # DW_AT_low_pc
+	.int32	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+	.int8	2                               # Abbrev [2] 0x26:0x6a DW_TAG_subprogram
+	.int32	0xffffffff                   # DW_AT_low_pc
+	.int32	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
+	.int8	4                               # DW_AT_frame_base
+	.int8	237
+	.int8	0
+	.int8	5
+	.int8	159
+	.int32	.Linfo_string3                  # DW_AT_linkage_name
+	.int32	.Linfo_string4                  # DW_AT_name
+	.int8	1                               # DW_AT_decl_file
+	.int8	2                               # DW_AT_decl_line
+	.int32	144                             # DW_AT_type
+                                        # DW_AT_external
+	.int8	3                               # Abbrev [3] 0x42:0xe DW_TAG_formal_parameter
+	.int8	2                               # DW_AT_location
+	.int8	145
+	.int8	24
+	.int32	.Linfo_string6                  # DW_AT_name
+	.int8	1                               # DW_AT_decl_file
+	.int8	2                               # DW_AT_decl_line
+	.int32	151                             # DW_AT_type
+	.int8	3                               # Abbrev [3] 0x50:0xe DW_TAG_formal_parameter
+	.int8	2                               # DW_AT_location
+	.int8	145
+	.int8	20
+	.int32	.Linfo_string8                  # DW_AT_name
+	.int8	1                               # DW_AT_decl_file
+	.int8	2                               # DW_AT_decl_line
+	.int32	172                             # DW_AT_type
+	.int8	3                               # Abbrev [3] 0x5e:0xe DW_TAG_formal_parameter
+	.int8	2                               # DW_AT_location
+	.int8	145
+	.int8	19
+	.int32	.Linfo_string10                 # DW_AT_name
+	.int8	1                               # DW_AT_decl_file
+	.int8	2                               # DW_AT_decl_line
+	.int32	179                             # DW_AT_type
+	.int8	4                               # Abbrev [4] 0x6c:0x18 DW_TAG_lexical_block
+	.int32	.Ltmp2                          # DW_AT_low_pc
+	.int32	.Ltmp3-.Ltmp2                   # DW_AT_high_pc
+	.int8	5                               # Abbrev [5] 0x75:0xe DW_TAG_variable
+	.int8	2                               # DW_AT_location
+	.int8	145
+	.int8	12
+	.int32	.Linfo_string12                 # DW_AT_name
+	.int8	1                               # DW_AT_decl_file
+	.int8	5                               # DW_AT_decl_line
+	.int32	186                             # DW_AT_type
+	.int8	0                               # End Of Children Mark
+	.int8	6                               # Abbrev [6] 0x84:0xb DW_TAG_typedef
+	.int32	144                             # DW_AT_type
+	.int32	.Linfo_string13                 # DW_AT_name
+	.int8	1                               # DW_AT_decl_file
+	.int8	4                               # DW_AT_decl_line
+	.int8	0                               # End Of Children Mark
+	.int8	7                               # Abbrev [7] 0x90:0x7 DW_TAG_base_type
+	.int32	.Linfo_string5                  # DW_AT_name
+	.int8	5                               # DW_AT_encoding
+	.int8	4                               # DW_AT_byte_size
+	.int8	6                               # Abbrev [6] 0x97:0xb DW_TAG_typedef
+	.int32	162                             # DW_AT_type
+	.int32	.Linfo_string7                  # DW_AT_name
+	.int8	1                               # DW_AT_decl_file
+	.int8	1                               # DW_AT_decl_line
+	.int8	8                               # Abbrev [8] 0xa2:0x5 DW_TAG_pointer_type
+	.int32	167                             # DW_AT_type
+	.int8	9                               # Abbrev [9] 0xa7:0x5 DW_TAG_const_type
+	.int32	144                             # DW_AT_type
+	.int8	7                               # Abbrev [7] 0xac:0x7 DW_TAG_base_type
+	.int32	.Linfo_string9                  # DW_AT_name
+	.int8	7                               # DW_AT_encoding
+	.int8	4                               # DW_AT_byte_size
+	.int8	7                               # Abbrev [7] 0xb3:0x7 DW_TAG_base_type
+	.int32	.Linfo_string11                 # DW_AT_name
+	.int8	2                               # DW_AT_encoding
+	.int8	1                               # DW_AT_byte_size
+	.int8	9                               # Abbrev [9] 0xba:0x5 DW_TAG_const_type
+	.int32	132                             # DW_AT_type
+	.int8	0                               # End Of Children Mark
+.Ldebug_info_end0:
+	.section	.debug_str,"S",@
+.Linfo_string0:
+	.asciz	"clang version 19.0.0"        # string offset=0
+.Linfo_string1:
+	.asciz	"test.cpp"                      # string offset=111
+.Linfo_string2:
+	.asciz	"general"                       # string offset=120
+.Linfo_string3:
+	.asciz	"_Z3fooPKijb"                   # string offset=174
+.Linfo_string4:
+	.asciz	"foo"                           # string offset=186
+.Linfo_string5:
+	.asciz	"int"                           # string offset=190
+.Linfo_string6:
+	.asciz	"ParamPtr"                      # string offset=194
+.Linfo_string7:
+	.asciz	"INTPTR"                        # string offset=203
+.Linfo_string8:
+	.asciz	"ParamUnsigned"                 # string offset=210
+.Linfo_string9:
+	.asciz	"unsigned int"                  # string offset=224
+.Linfo_string10:
+	.asciz	"ParamBool"                     # string offset=237
+.Linfo_string11:
+	.asciz	"bool"                          # string offset=247
+.Linfo_string12:
+	.asciz	"CONSTANT"                      # string offset=252
+.Linfo_string13:
+	.asciz	"INTEGER"                       # string offset=261
+	.ident	"clang version 19.0.0"
+	.section	.custom_section.producers,"",@
+	.int8	2
+	.int8	8
+	.ascii	"language"
+	.int8	1
+	.int8	14
+	.ascii	"C_plus_plus_14"
+	.int8	0
+	.int8	12
+	.ascii	"processed-by"
+	.int8	1
+	.int8	5
+	.ascii	"clang"
+	.int8	96
+	.ascii	"19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)"
+	.section	.debug_str,"S",@
+	.section	.custom_section.target_features,"",@
+	.int8	2
+	.int8	43
+	.int8	15
+	.ascii	"mutable-globals"
+	.int8	43
+	.int8	8
+	.ascii	"sign-ext"
+	.section	.debug_str,"S",@
+	.section	.debug_line,"",@
+.Lline_table_start0:
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test
new file mode 100644
index 0000000000000..35e152c878b8c
--- /dev/null
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test
@@ -0,0 +1,44 @@
+; REQUIRES: x86-registered-target
+
+; llvm-debuginfo-analyzer crashes on dead code
+; https://github.com/llvm/llvm-project/issues/136772
+
+; For the attached reproducer:
+; llvm-dwarfdump out/lzma-lzmadec.wasm --all shows:
+;
+; 0x000002b3:   DW_TAG_subprogram
+;                 DW_AT_low_pc	(dead code)
+;                 DW_AT_high_pc	(0x00000362)
+;                 DW_AT_frame_base	(DW_OP_WASM_location 0x0 0x6, DW_OP_stack_value)
+;
+; llvm-debuginfo-analyzer out/lzma-lzmadec.wasm --print=instructions
+;
+; crashes and shows a stack dump.
+;
+; The llvm-debuginfo-analyzer crashes when producing a logical view for
+; the object file generated using the following commands:
+
+; RUN: llvm-mc -arch=wasm32 -filetype=obj       \
+; RUN:         %p/Inputs/test-clang-tombstone.s \
+; RUN:         -o %t.test-clang-tombstone.o
+
+; llvm-debuginfo-analyzer --select-elements=Discarde  \
+;                         --print=elements \
+;                         %t.test-clang-tombstone.o 2>&1 | \
+; FileCheck --strict-whitespace -check-prefix=ONE %s
+
+; ONE: Logical View:
+; ONE-NEXT:           {File} '{{.*}}test-clang-tombstone.o'
+; ONE-EMPTY:
+; ONE-NEXT:           {CompileUnit} 'test.cpp'
+; ONE-NEXT:     2     {Function} extern not_inlined 'foo' -> 'int'
+
+; RUN: llvm-dwarfdump --debug-info %t.test-clang-tombstone.o  | \
+; RUN: FileCheck %s --check-prefix=TWO
+
+; TWO:      DW_TAG_subprogram
+; TWO-NEXT:   DW_AT_low_pc	(dead code)
+; TWO-NEXT:   DW_AT_high_pc
+; TWO-NEXT:   DW_AT_frame_base
+; TWO-NEXT:   DW_AT_linkage_name
+; TWO-NEXT:   DW_AT_name	("foo")

>From 036b1e60efc6dcf4b8e8c202613a130bbb31cb8b Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <Carlos.Enciso at sony.com>
Date: Tue, 27 May 2025 16:21:59 +0100
Subject: [PATCH 2/5] [llvm-debuginfo-analyzer] Fix crash with WebAssembly dead
 code

https://github.com/llvm/llvm-project/issues/136772
Incorrect handling of 'tombstone' value for WebAssembly.

Fix clang-format issue.
---
 llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
index ecd5d524a195c..d77cea37c638d 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
@@ -61,8 +61,8 @@ class LLVM_ABI LVRange final : public LVObject {
 
 public:
   LVRange(LVAddress Address = MaxAddress)
-      : LVObject(),
-        RangesTree(Allocator), TombstoneAddress(Address), Lower(Address) {}
+      : LVObject(), RangesTree(Allocator), TombstoneAddress(Address),
+        Lower(Address) {}
   LVRange(const LVRange &) = delete;
   LVRange &operator=(const LVRange &) = delete;
   ~LVRange() = default;

>From ab09f83cd56d446f02563d35ca05376e8f3dba3f Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <Carlos.Enciso at sony.com>
Date: Fri, 30 May 2025 08:27:53 +0100
Subject: [PATCH 3/5] [llvm-debuginfo-analyzer] Fix crash with WebAssembly dead
 code

https://github.com/llvm/llvm-project/issues/136772
Incorrect handling of 'tombstone' value for WebAssembly.

Address comments from reviewers:
- Combine test and .s file.
- Introduce the concept of a meta-tombstone value, to
  be able to check for an invalid tombstone value.
---
 .../DebugInfo/LogicalView/Core/LVObject.h     | 10 +++
 .../llvm/DebugInfo/LogicalView/Core/LVRange.h |  2 +-
 .../DebugInfo/LogicalView/Core/LVReader.h     | 10 +--
 .../LogicalView/Readers/LVCodeViewReader.h    | 10 ++-
 ...ang-tombstone.s => wasm-crash-tombstone.s} | 63 +++++++++++++++++++
 .../WebAssembly/wasm-crash-tombstone.test     | 44 -------------
 6 files changed, 88 insertions(+), 51 deletions(-)
 rename llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/{Inputs/test-clang-tombstone.s => wasm-crash-tombstone.s} (86%)
 delete mode 100644 llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test

diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
index ec02120e69b73..3319a608803b9 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
@@ -84,7 +84,17 @@ using LVTypes = SmallVector<LVType *, 8>;
 
 using LVOffsets = SmallVector<LVOffset, 8>;
 
+// The following DWARF documents detail the 'tombstone' concept:
+//   https://dwarfstd.org/issues/231013.1.html
+//   https://dwarfstd.org/issues/200609.1.html
+//
+// The value of the largest representable address offset (for example,
+// 0xffffffff when the size of an address is 32 bits).
+//
+// -1 (0xffffffff) => Valid tombstone
+// -2 (0xfffffffe) => Undefined tomstone
 const LVAddress MaxAddress = std::numeric_limits<uint64_t>::max();
+const LVAddress InvalidTombstone = MaxAddress - 1;
 
 enum class LVBinaryType { NONE, ELF, COFF };
 enum class LVComparePass { Missing, Added };
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
index d77cea37c638d..afa7e2a7ae8bb 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
@@ -60,7 +60,7 @@ class LLVM_ABI LVRange final : public LVObject {
   LVAddress Upper = 0;
 
 public:
-  LVRange(LVAddress Address = MaxAddress)
+  LVRange(LVAddress Address = InvalidTombstone)
       : LVObject(), RangesTree(Allocator), TombstoneAddress(Address),
         Lower(Address) {}
   LVRange(const LVRange &) = delete;
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
index a3140df627848..e97d8243fd521 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
@@ -156,9 +156,8 @@ class LLVM_ABI LVReader {
                        LVAddress LowerAddress, LVAddress UpperAddress);
   LVRange *getSectionRanges(LVSectionIndex SectionIndex);
 
-  // Tombstone value. Assume 64 bits. The value is updated for each
-  // Compile Unit that is processed.
-  LVAddress TombstoneAddress = MaxAddress;
+  // The value is updated for each Compile Unit that is processed.
+  LVAddress TombstoneAddress = InvalidTombstone;
 
   // Record Compilation Unit entry.
   void addCompileUnitOffset(LVOffset Offset, LVScopeCompileUnit *CompileUnit) {
@@ -287,7 +286,10 @@ class LLVM_ABI LVReader {
   }
 
   void setTombstoneAddress(LVAddress Address) { TombstoneAddress = Address; }
-  LVAddress getTombstoneAddress() const { return TombstoneAddress; }
+  LVAddress getTombstoneAddress() const {
+    assert(TombstoneAddress != InvalidTombstone && "Invalid tombstone value");
+    return TombstoneAddress;
+  }
 
   // Access to the scopes root.
   LVScopeRoot *getScopesRoot() const { return Root; }
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h
index 4dd7c967ddc17..612c6fc68f09c 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h
@@ -193,11 +193,17 @@ class LVCodeViewReader final : public LVBinaryReader {
                    llvm::object::COFFObjectFile &Obj, ScopedPrinter &W,
                    StringRef ExePath)
       : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF),
-        Input(&Obj), ExePath(ExePath), LogicalVisitor(this, W, Input) {}
+        Input(&Obj), ExePath(ExePath), LogicalVisitor(this, W, Input) {
+    // CodeView does not have the concept of 'tombstone' address.
+    setTombstoneAddress(MaxAddress);
+  }
   LVCodeViewReader(StringRef Filename, StringRef FileFormatName,
                    llvm::pdb::PDBFile &Pdb, ScopedPrinter &W, StringRef ExePath)
       : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::COFF),
-        Input(&Pdb), ExePath(ExePath), LogicalVisitor(this, W, Input) {}
+        Input(&Pdb), ExePath(ExePath), LogicalVisitor(this, W, Input) {
+    // CodeView does not have the concept of 'tombstone' address.
+    setTombstoneAddress(MaxAddress);
+  }
   LVCodeViewReader(const LVCodeViewReader &) = delete;
   LVCodeViewReader &operator=(const LVCodeViewReader &) = delete;
   ~LVCodeViewReader() = default;
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
similarity index 86%
rename from llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s
rename to llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
index f7e85420b89dd..92a5e023c9464 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang-tombstone.s
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
@@ -1,3 +1,66 @@
+# REQUIRES: x86-registered-target
+
+# llvm-debuginfo-analyzer crashes on dead code
+# https://github.com/llvm/llvm-project/issues/136772
+
+# For the attached reproducer:
+# llvm-dwarfdump out/lzma-lzmadec.wasm --all
+#
+# shows:
+#
+# 0x000002b3:   DW_TAG_subprogram
+#                 DW_AT_low_pc	(dead code)
+#                 DW_AT_high_pc	(0x00000362)
+#                 DW_AT_frame_base	(DW_OP_WASM_location 0x0 0x6, DW_OP_stack_value)
+
+# llvm-debuginfo-analyzer out/lzma-lzmadec.wasm --print=instructions
+#
+# crashes and shows a stack dump:
+#
+# PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/
+# and include the crash backtrace.
+# Stack dump:
+# 0. Program arguments: llvm-debuginfo-analyzer out/lzma-lzmadec.wasm --print=instructions
+
+# The test-clang-tombstone.s was produced by the following steps:
+# 1) clang --target=wasm32 -S -g Inputs/test-clang.cpp
+#                             -o Inputs/wasm-crash-tombstone.s
+# 2) Manually changing the DW_AT_low_pc for the DW_TAG_subprogram, from
+#    .Lfunc_begin0 to 0xffffffff to mark the function as dead code:
+#
+#	   .int8	2                          # Abbrev [2] 0x26:0x6a DW_TAG_subprogram
+#	   .int32	.Lfunc_begin0              # DW_AT_low_pc  <---------
+#	   .int32	.Lfunc_end0-.Lfunc_begin0  # DW_AT_high_pc
+
+#	   .int8	2                          # Abbrev [2] 0x26:0x6a DW_TAG_subprogram
+#	   .int32	0xffffffff                 # DW_AT_low_pc  <---------
+#	   .int32	.Lfunc_end0-.Lfunc_begin0  # DW_AT_high_pc
+
+# RUN: llvm-mc -arch=wasm32 -filetype=obj       \
+# RUN:         %p/wasm-crash-tombstone.s        \
+# RUN:         -o %t.wasm-crash-tombstone.wasm
+
+# llvm-debuginfo-analyzer --select-elements=Discarde          \
+#                         --print=elements                    \
+#                         %t.wasm-crash-tombstone.wasm 2>&1 | \
+# FileCheck --strict-whitespace -check-prefix=ONE %s
+
+# ONE: Logical View:
+# ONE-NEXT:           {File} '{{.*}}wasm-crash-tombstone.wasm'
+# ONE-EMPTY:
+# ONE-NEXT:           {CompileUnit} 'test.cpp'
+# ONE-NEXT:     2     {Function} extern not_inlined 'foo' -> 'int'
+
+# RUN: llvm-dwarfdump --debug-info %t.wasm-crash-tombstone.wasm | \
+# RUN: FileCheck %s --check-prefix=TWO
+
+# TWO:      DW_TAG_subprogram
+# TWO-NEXT:   DW_AT_low_pc	(dead code)
+# TWO-NEXT:   DW_AT_high_pc
+# TWO-NEXT:   DW_AT_frame_base
+# TWO-NEXT:   DW_AT_linkage_name
+# TWO-NEXT:   DW_AT_name	("foo")
+
 	.text
 	.file	"test.cpp"
 	.globaltype	__stack_pointer, i32
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test
deleted file mode 100644
index 35e152c878b8c..0000000000000
--- a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.test
+++ /dev/null
@@ -1,44 +0,0 @@
-; REQUIRES: x86-registered-target
-
-; llvm-debuginfo-analyzer crashes on dead code
-; https://github.com/llvm/llvm-project/issues/136772
-
-; For the attached reproducer:
-; llvm-dwarfdump out/lzma-lzmadec.wasm --all shows:
-;
-; 0x000002b3:   DW_TAG_subprogram
-;                 DW_AT_low_pc	(dead code)
-;                 DW_AT_high_pc	(0x00000362)
-;                 DW_AT_frame_base	(DW_OP_WASM_location 0x0 0x6, DW_OP_stack_value)
-;
-; llvm-debuginfo-analyzer out/lzma-lzmadec.wasm --print=instructions
-;
-; crashes and shows a stack dump.
-;
-; The llvm-debuginfo-analyzer crashes when producing a logical view for
-; the object file generated using the following commands:
-
-; RUN: llvm-mc -arch=wasm32 -filetype=obj       \
-; RUN:         %p/Inputs/test-clang-tombstone.s \
-; RUN:         -o %t.test-clang-tombstone.o
-
-; llvm-debuginfo-analyzer --select-elements=Discarde  \
-;                         --print=elements \
-;                         %t.test-clang-tombstone.o 2>&1 | \
-; FileCheck --strict-whitespace -check-prefix=ONE %s
-
-; ONE: Logical View:
-; ONE-NEXT:           {File} '{{.*}}test-clang-tombstone.o'
-; ONE-EMPTY:
-; ONE-NEXT:           {CompileUnit} 'test.cpp'
-; ONE-NEXT:     2     {Function} extern not_inlined 'foo' -> 'int'
-
-; RUN: llvm-dwarfdump --debug-info %t.test-clang-tombstone.o  | \
-; RUN: FileCheck %s --check-prefix=TWO
-
-; TWO:      DW_TAG_subprogram
-; TWO-NEXT:   DW_AT_low_pc	(dead code)
-; TWO-NEXT:   DW_AT_high_pc
-; TWO-NEXT:   DW_AT_frame_base
-; TWO-NEXT:   DW_AT_linkage_name
-; TWO-NEXT:   DW_AT_name	("foo")

>From a563faa2c89ec2b1132c24123b9dfa519473fbbf Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <Carlos.Enciso at sony.com>
Date: Fri, 30 May 2025 08:54:57 +0100
Subject: [PATCH 4/5] [llvm-debuginfo-analyzer] Fix crash with WebAssembly dead
 code

https://github.com/llvm/llvm-project/issues/136772
Incorrect handling of 'tombstone' value for WebAssembly.

Minor comments change in test case.
---
 .../WebAssembly/wasm-crash-tombstone.s                       | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
index 92a5e023c9464..50adaaa9cfec4 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
@@ -22,10 +22,11 @@
 # Stack dump:
 # 0. Program arguments: llvm-debuginfo-analyzer out/lzma-lzmadec.wasm --print=instructions
 
-# The test-clang-tombstone.s was produced by the following steps:
+# The test case was produced by the following steps:
+#
 # 1) clang --target=wasm32 -S -g Inputs/test-clang.cpp
 #                             -o Inputs/wasm-crash-tombstone.s
-# 2) Manually changing the DW_AT_low_pc for the DW_TAG_subprogram, from
+# 2) Manually changing the DW_AT_low_pc for the DW_TAG_subprogram:
 #    .Lfunc_begin0 to 0xffffffff to mark the function as dead code:
 #
 #	   .int8	2                          # Abbrev [2] 0x26:0x6a DW_TAG_subprogram

>From a93d7f63f3f3afae39a86ffbaaf671ab06dc29d3 Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <Carlos.Enciso at sony.com>
Date: Wed, 11 Jun 2025 15:57:44 +0100
Subject: [PATCH 5/5] [llvm-debuginfo-analyzer] Fix crash with WebAssembly dead
 code

https://github.com/llvm/llvm-project/issues/136772
Incorrect handling of 'tombstone' value for WebAssembly.

Address reviewes comments:
- Reduce the test case.
- Use std::optional to illustrate the set/unset state.
- Rebase with main branch.
---
 .../DebugInfo/LogicalView/Core/LVObject.h     |   2 -
 .../llvm/DebugInfo/LogicalView/Core/LVRange.h |  10 +-
 .../DebugInfo/LogicalView/Core/LVReader.h     |   6 +-
 .../WebAssembly/wasm-crash-tombstone.s        | 350 ++----------------
 4 files changed, 30 insertions(+), 338 deletions(-)

diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
index 3319a608803b9..42a22039c870f 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
@@ -92,9 +92,7 @@ using LVOffsets = SmallVector<LVOffset, 8>;
 // 0xffffffff when the size of an address is 32 bits).
 //
 // -1 (0xffffffff) => Valid tombstone
-// -2 (0xfffffffe) => Undefined tomstone
 const LVAddress MaxAddress = std::numeric_limits<uint64_t>::max();
-const LVAddress InvalidTombstone = MaxAddress - 1;
 
 enum class LVBinaryType { NONE, ELF, COFF };
 enum class LVComparePass { Missing, Added };
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
index afa7e2a7ae8bb..ca3e89faf5e29 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVRange.h
@@ -55,14 +55,14 @@ class LLVM_ABI LVRange final : public LVObject {
   LVAllocator Allocator;
   LVRangesTree RangesTree;
   LVRangeEntries RangeEntries;
-  LVAddress TombstoneAddress;
-  LVAddress Lower;
+  std::optional<LVAddress> TombstoneAddress;
+  LVAddress Lower = 0;
   LVAddress Upper = 0;
 
 public:
-  LVRange(LVAddress Address = InvalidTombstone)
+  LVRange(std::optional<LVAddress> Address = std::nullopt)
       : LVObject(), RangesTree(Allocator), TombstoneAddress(Address),
-        Lower(Address) {}
+        Lower(Address ? Address.value() : MaxAddress) {}
   LVRange(const LVRange &) = delete;
   LVRange &operator=(const LVRange &) = delete;
   ~LVRange() = default;
@@ -79,7 +79,7 @@ class LLVM_ABI LVRange final : public LVObject {
 
   void clear() {
     RangeEntries.clear();
-    Lower = TombstoneAddress;
+    Lower = TombstoneAddress ? TombstoneAddress.value() : MaxAddress;
     Upper = 0;
   }
   bool empty() const { return RangeEntries.empty(); }
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
index e97d8243fd521..20261418791d3 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
@@ -157,7 +157,7 @@ class LLVM_ABI LVReader {
   LVRange *getSectionRanges(LVSectionIndex SectionIndex);
 
   // The value is updated for each Compile Unit that is processed.
-  LVAddress TombstoneAddress = InvalidTombstone;
+  std::optional<LVAddress> TombstoneAddress;
 
   // Record Compilation Unit entry.
   void addCompileUnitOffset(LVOffset Offset, LVScopeCompileUnit *CompileUnit) {
@@ -287,8 +287,8 @@ class LLVM_ABI LVReader {
 
   void setTombstoneAddress(LVAddress Address) { TombstoneAddress = Address; }
   LVAddress getTombstoneAddress() const {
-    assert(TombstoneAddress != InvalidTombstone && "Invalid tombstone value");
-    return TombstoneAddress;
+    assert(TombstoneAddress && "Unset tombstone value");
+    return TombstoneAddress.value();
   }
 
   // Access to the scopes root.
diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
index 50adaaa9cfec4..7d833b841af99 100644
--- a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
+++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/wasm-crash-tombstone.s
@@ -24,16 +24,20 @@
 
 # The test case was produced by the following steps:
 #
-# 1) clang --target=wasm32 -S -g Inputs/test-clang.cpp
+# // test-clang.cpp
+# void foo() {
+# }
+#
+# 1) clang --target=wasm32 -S -g test-clang.cpp
 #                             -o Inputs/wasm-crash-tombstone.s
 # 2) Manually changing the DW_AT_low_pc for the DW_TAG_subprogram:
 #    .Lfunc_begin0 to 0xffffffff to mark the function as dead code:
 #
-#	   .int8	2                          # Abbrev [2] 0x26:0x6a DW_TAG_subprogram
+#	   .int8	2                          # Abbrev [2] 0x26:0x1b DW_TAG_subprogram
 #	   .int32	.Lfunc_begin0              # DW_AT_low_pc  <---------
 #	   .int32	.Lfunc_end0-.Lfunc_begin0  # DW_AT_high_pc
 
-#	   .int8	2                          # Abbrev [2] 0x26:0x6a DW_TAG_subprogram
+#	   .int8	2                          # Abbrev [2] 0x26:0x1b DW_TAG_subprogram
 #	   .int32	0xffffffff                 # DW_AT_low_pc  <---------
 #	   .int32	.Lfunc_end0-.Lfunc_begin0  # DW_AT_high_pc
 
@@ -41,16 +45,16 @@
 # RUN:         %p/wasm-crash-tombstone.s        \
 # RUN:         -o %t.wasm-crash-tombstone.wasm
 
-# llvm-debuginfo-analyzer --select-elements=Discarde          \
-#                         --print=elements                    \
-#                         %t.wasm-crash-tombstone.wasm 2>&1 | \
-# FileCheck --strict-whitespace -check-prefix=ONE %s
+# RUN: llvm-debuginfo-analyzer --select-elements=Discarded         \
+# RUN:                         --print=elements                    \
+# RUN:                         %t.wasm-crash-tombstone.wasm 2>&1 | \
+# RUN: FileCheck --strict-whitespace -check-prefix=ONE %s
 
 # ONE: Logical View:
 # ONE-NEXT:           {File} '{{.*}}wasm-crash-tombstone.wasm'
 # ONE-EMPTY:
-# ONE-NEXT:           {CompileUnit} 'test.cpp'
-# ONE-NEXT:     2     {Function} extern not_inlined 'foo' -> 'int'
+# ONE-NEXT:           {CompileUnit} 'test-clang.cpp'
+# ONE-NEXT:           {Function} not_inlined 'foo' -> 'void'
 
 # RUN: llvm-dwarfdump --debug-info %t.wasm-crash-tombstone.wasm | \
 # RUN: FileCheck %s --check-prefix=TWO
@@ -58,116 +62,25 @@
 # TWO:      DW_TAG_subprogram
 # TWO-NEXT:   DW_AT_low_pc	(dead code)
 # TWO-NEXT:   DW_AT_high_pc
-# TWO-NEXT:   DW_AT_frame_base
-# TWO-NEXT:   DW_AT_linkage_name
 # TWO-NEXT:   DW_AT_name	("foo")
 
 	.text
-	.file	"test.cpp"
-	.globaltype	__stack_pointer, i32
-	.functype	_Z3fooPKijb (i32, i32, i32) -> (i32)
-	.section	.text._Z3fooPKijb,"",@
-	.hidden	_Z3fooPKijb                     # -- Begin function _Z3fooPKijb
-	.globl	_Z3fooPKijb
-	.type	_Z3fooPKijb, at function
-_Z3fooPKijb:                            # @_Z3fooPKijb
+	.file	"test-clang.cpp"
+	.functype	_Z3foov () -> ()
+	.section	.text._Z3foov,"",@
+_Z3foov:                                # @_Z3foov
 .Lfunc_begin0:
-	.file	1 "/data/projects/scripts/regression-suite/input/general" "test.cpp"
-	.loc	1 2 0                           # test.cpp:2:0
-	.functype	_Z3fooPKijb (i32, i32, i32) -> (i32)
-	.local  	i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32
-# %bb.0:                                # %entry
-	global.get	__stack_pointer
-	local.set	3
-	i32.const	32
-	local.set	4
-	local.get	3
-	local.get	4
-	i32.sub
-	local.set	5
-	local.get	5
-	local.get	0
-	i32.store	24
-	local.get	5
-	local.get	1
-	i32.store	20
-	local.get	2
-	local.set	6
-	local.get	5
-	local.get	6
-	i32.store8	19
-.Ltmp0:
-	.loc	1 3 7 prologue_end              # test.cpp:3:7
-	local.get	5
-	i32.load8_u	19
-	local.set	7
-.Ltmp1:
-	.loc	1 3 7 is_stmt 0                 # test.cpp:3:7
-	i32.const	1
-	local.set	8
-	local.get	7
-	local.get	8
-	i32.and
-	local.set	9
-	block
-	block
-	local.get	9
-	i32.eqz
-	br_if   	0                               # 0: down to label1
-# %bb.1:                                # %if.then
-.Ltmp2:
-	.loc	1 5 19 is_stmt 1                # test.cpp:5:19
-	i32.const	7
-	local.set	10
-	local.get	5
-	local.get	10
-	i32.store	12
-	.loc	1 6 5                           # test.cpp:6:5
-	i32.const	7
-	local.set	11
-	local.get	5
-	local.get	11
-	i32.store	28
-	br      	1                               # 1: down to label0
-.Ltmp3:
-.LBB0_2:                                # %if.end
-	.loc	1 0 5 is_stmt 0                 # test.cpp:0:5
-	end_block                               # label1:
-	.loc	1 8 10 is_stmt 1                # test.cpp:8:10
-	local.get	5
-	i32.load	20
-	local.set	12
-	.loc	1 8 3 is_stmt 0                 # test.cpp:8:3
-	local.get	5
-	local.get	12
-	i32.store	28
-.LBB0_3:                                # %return
-	.loc	1 0 3                           # test.cpp:0:3
-	end_block                               # label0:
-	.loc	1 9 1 is_stmt 1                 # test.cpp:9:1
-	local.get	5
-	i32.load	28
-	local.set	13
-	local.get	13
+	.functype	_Z3foov () -> ()
 	return
 	end_function
-.Ltmp4:
 .Lfunc_end0:
                                         # -- End function
 	.section	.debug_abbrev,"",@
 	.int8	1                               # Abbreviation Code
 	.int8	17                              # DW_TAG_compile_unit
 	.int8	1                               # DW_CHILDREN_yes
-	.int8	37                              # DW_AT_producer
-	.int8	14                              # DW_FORM_strp
-	.int8	19                              # DW_AT_language
-	.int8	5                               # DW_FORM_data2
 	.int8	3                               # DW_AT_name
 	.int8	14                              # DW_FORM_strp
-	.int8	16                              # DW_AT_stmt_list
-	.int8	23                              # DW_FORM_sec_offset
-	.int8	27                              # DW_AT_comp_dir
-	.int8	14                              # DW_FORM_strp
 	.int8	17                              # DW_AT_low_pc
 	.int8	1                               # DW_FORM_addr
 	.int8	18                              # DW_AT_high_pc
@@ -176,102 +89,13 @@ _Z3fooPKijb:                            # @_Z3fooPKijb
 	.int8	0                               # EOM(2)
 	.int8	2                               # Abbreviation Code
 	.int8	46                              # DW_TAG_subprogram
-	.int8	1                               # DW_CHILDREN_yes
-	.int8	17                              # DW_AT_low_pc
-	.int8	1                               # DW_FORM_addr
-	.int8	18                              # DW_AT_high_pc
-	.int8	6                               # DW_FORM_data4
-	.int8	64                              # DW_AT_frame_base
-	.int8	24                              # DW_FORM_exprloc
-	.int8	110                             # DW_AT_linkage_name
-	.int8	14                              # DW_FORM_strp
-	.int8	3                               # DW_AT_name
-	.int8	14                              # DW_FORM_strp
-	.int8	58                              # DW_AT_decl_file
-	.int8	11                              # DW_FORM_data1
-	.int8	59                              # DW_AT_decl_line
-	.int8	11                              # DW_FORM_data1
-	.int8	73                              # DW_AT_type
-	.int8	19                              # DW_FORM_ref4
-	.int8	63                              # DW_AT_external
-	.int8	25                              # DW_FORM_flag_present
-	.int8	0                               # EOM(1)
-	.int8	0                               # EOM(2)
-	.int8	3                               # Abbreviation Code
-	.int8	5                               # DW_TAG_formal_parameter
 	.int8	0                               # DW_CHILDREN_no
-	.int8	2                               # DW_AT_location
-	.int8	24                              # DW_FORM_exprloc
-	.int8	3                               # DW_AT_name
-	.int8	14                              # DW_FORM_strp
-	.int8	58                              # DW_AT_decl_file
-	.int8	11                              # DW_FORM_data1
-	.int8	59                              # DW_AT_decl_line
-	.int8	11                              # DW_FORM_data1
-	.int8	73                              # DW_AT_type
-	.int8	19                              # DW_FORM_ref4
-	.int8	0                               # EOM(1)
-	.int8	0                               # EOM(2)
-	.int8	4                               # Abbreviation Code
-	.int8	11                              # DW_TAG_lexical_block
-	.int8	1                               # DW_CHILDREN_yes
 	.int8	17                              # DW_AT_low_pc
 	.int8	1                               # DW_FORM_addr
 	.int8	18                              # DW_AT_high_pc
 	.int8	6                               # DW_FORM_data4
-	.int8	0                               # EOM(1)
-	.int8	0                               # EOM(2)
-	.int8	5                               # Abbreviation Code
-	.int8	52                              # DW_TAG_variable
-	.int8	0                               # DW_CHILDREN_no
-	.int8	2                               # DW_AT_location
-	.int8	24                              # DW_FORM_exprloc
 	.int8	3                               # DW_AT_name
 	.int8	14                              # DW_FORM_strp
-	.int8	58                              # DW_AT_decl_file
-	.int8	11                              # DW_FORM_data1
-	.int8	59                              # DW_AT_decl_line
-	.int8	11                              # DW_FORM_data1
-	.int8	73                              # DW_AT_type
-	.int8	19                              # DW_FORM_ref4
-	.int8	0                               # EOM(1)
-	.int8	0                               # EOM(2)
-	.int8	6                               # Abbreviation Code
-	.int8	22                              # DW_TAG_typedef
-	.int8	0                               # DW_CHILDREN_no
-	.int8	73                              # DW_AT_type
-	.int8	19                              # DW_FORM_ref4
-	.int8	3                               # DW_AT_name
-	.int8	14                              # DW_FORM_strp
-	.int8	58                              # DW_AT_decl_file
-	.int8	11                              # DW_FORM_data1
-	.int8	59                              # DW_AT_decl_line
-	.int8	11                              # DW_FORM_data1
-	.int8	0                               # EOM(1)
-	.int8	0                               # EOM(2)
-	.int8	7                               # Abbreviation Code
-	.int8	36                              # DW_TAG_base_type
-	.int8	0                               # DW_CHILDREN_no
-	.int8	3                               # DW_AT_name
-	.int8	14                              # DW_FORM_strp
-	.int8	62                              # DW_AT_encoding
-	.int8	11                              # DW_FORM_data1
-	.int8	11                              # DW_AT_byte_size
-	.int8	11                              # DW_FORM_data1
-	.int8	0                               # EOM(1)
-	.int8	0                               # EOM(2)
-	.int8	8                               # Abbreviation Code
-	.int8	15                              # DW_TAG_pointer_type
-	.int8	0                               # DW_CHILDREN_no
-	.int8	73                              # DW_AT_type
-	.int8	19                              # DW_FORM_ref4
-	.int8	0                               # EOM(1)
-	.int8	0                               # EOM(2)
-	.int8	9                               # Abbreviation Code
-	.int8	38                              # DW_TAG_const_type
-	.int8	0                               # DW_CHILDREN_no
-	.int8	73                              # DW_AT_type
-	.int8	19                              # DW_FORM_ref4
 	.int8	0                               # EOM(1)
 	.int8	0                               # EOM(2)
 	.int8	0                               # EOM(3)
@@ -282,149 +106,19 @@ _Z3fooPKijb:                            # @_Z3fooPKijb
 	.int16	4                               # DWARF version number
 	.int32	.debug_abbrev0                  # Offset Into Abbrev. Section
 	.int8	4                               # Address Size (in bytes)
-	.int8	1                               # Abbrev [1] 0xb:0xb5 DW_TAG_compile_unit
-	.int32	.Linfo_string0                  # DW_AT_producer
-	.int16	33                              # DW_AT_language
+	.int8	1                               # Abbrev [1] 0xb:0x37 DW_TAG_compile_unit
 	.int32	.Linfo_string1                  # DW_AT_name
-	.int32	.Lline_table_start0             # DW_AT_stmt_list
-	.int32	.Linfo_string2                  # DW_AT_comp_dir
 	.int32	.Lfunc_begin0                   # DW_AT_low_pc
 	.int32	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
-	.int8	2                               # Abbrev [2] 0x26:0x6a DW_TAG_subprogram
+	.int8	2                               # Abbrev [2] 0x26:0x1b DW_TAG_subprogram
 	.int32	0xffffffff                   # DW_AT_low_pc
 	.int32	.Lfunc_end0-.Lfunc_begin0       # DW_AT_high_pc
-	.int8	4                               # DW_AT_frame_base
-	.int8	237
-	.int8	0
-	.int8	5
-	.int8	159
-	.int32	.Linfo_string3                  # DW_AT_linkage_name
 	.int32	.Linfo_string4                  # DW_AT_name
-	.int8	1                               # DW_AT_decl_file
-	.int8	2                               # DW_AT_decl_line
-	.int32	144                             # DW_AT_type
-                                        # DW_AT_external
-	.int8	3                               # Abbrev [3] 0x42:0xe DW_TAG_formal_parameter
-	.int8	2                               # DW_AT_location
-	.int8	145
-	.int8	24
-	.int32	.Linfo_string6                  # DW_AT_name
-	.int8	1                               # DW_AT_decl_file
-	.int8	2                               # DW_AT_decl_line
-	.int32	151                             # DW_AT_type
-	.int8	3                               # Abbrev [3] 0x50:0xe DW_TAG_formal_parameter
-	.int8	2                               # DW_AT_location
-	.int8	145
-	.int8	20
-	.int32	.Linfo_string8                  # DW_AT_name
-	.int8	1                               # DW_AT_decl_file
-	.int8	2                               # DW_AT_decl_line
-	.int32	172                             # DW_AT_type
-	.int8	3                               # Abbrev [3] 0x5e:0xe DW_TAG_formal_parameter
-	.int8	2                               # DW_AT_location
-	.int8	145
-	.int8	19
-	.int32	.Linfo_string10                 # DW_AT_name
-	.int8	1                               # DW_AT_decl_file
-	.int8	2                               # DW_AT_decl_line
-	.int32	179                             # DW_AT_type
-	.int8	4                               # Abbrev [4] 0x6c:0x18 DW_TAG_lexical_block
-	.int32	.Ltmp2                          # DW_AT_low_pc
-	.int32	.Ltmp3-.Ltmp2                   # DW_AT_high_pc
-	.int8	5                               # Abbrev [5] 0x75:0xe DW_TAG_variable
-	.int8	2                               # DW_AT_location
-	.int8	145
-	.int8	12
-	.int32	.Linfo_string12                 # DW_AT_name
-	.int8	1                               # DW_AT_decl_file
-	.int8	5                               # DW_AT_decl_line
-	.int32	186                             # DW_AT_type
-	.int8	0                               # End Of Children Mark
-	.int8	6                               # Abbrev [6] 0x84:0xb DW_TAG_typedef
-	.int32	144                             # DW_AT_type
-	.int32	.Linfo_string13                 # DW_AT_name
-	.int8	1                               # DW_AT_decl_file
-	.int8	4                               # DW_AT_decl_line
-	.int8	0                               # End Of Children Mark
-	.int8	7                               # Abbrev [7] 0x90:0x7 DW_TAG_base_type
-	.int32	.Linfo_string5                  # DW_AT_name
-	.int8	5                               # DW_AT_encoding
-	.int8	4                               # DW_AT_byte_size
-	.int8	6                               # Abbrev [6] 0x97:0xb DW_TAG_typedef
-	.int32	162                             # DW_AT_type
-	.int32	.Linfo_string7                  # DW_AT_name
-	.int8	1                               # DW_AT_decl_file
-	.int8	1                               # DW_AT_decl_line
-	.int8	8                               # Abbrev [8] 0xa2:0x5 DW_TAG_pointer_type
-	.int32	167                             # DW_AT_type
-	.int8	9                               # Abbrev [9] 0xa7:0x5 DW_TAG_const_type
-	.int32	144                             # DW_AT_type
-	.int8	7                               # Abbrev [7] 0xac:0x7 DW_TAG_base_type
-	.int32	.Linfo_string9                  # DW_AT_name
-	.int8	7                               # DW_AT_encoding
-	.int8	4                               # DW_AT_byte_size
-	.int8	7                               # Abbrev [7] 0xb3:0x7 DW_TAG_base_type
-	.int32	.Linfo_string11                 # DW_AT_name
-	.int8	2                               # DW_AT_encoding
-	.int8	1                               # DW_AT_byte_size
-	.int8	9                               # Abbrev [9] 0xba:0x5 DW_TAG_const_type
-	.int32	132                             # DW_AT_type
 	.int8	0                               # End Of Children Mark
 .Ldebug_info_end0:
 	.section	.debug_str,"S",@
-.Linfo_string0:
-	.asciz	"clang version 19.0.0"        # string offset=0
 .Linfo_string1:
-	.asciz	"test.cpp"                      # string offset=111
-.Linfo_string2:
-	.asciz	"general"                       # string offset=120
-.Linfo_string3:
-	.asciz	"_Z3fooPKijb"                   # string offset=174
+	.asciz	"test-clang.cpp"                # string offset=176
 .Linfo_string4:
-	.asciz	"foo"                           # string offset=186
-.Linfo_string5:
-	.asciz	"int"                           # string offset=190
-.Linfo_string6:
-	.asciz	"ParamPtr"                      # string offset=194
-.Linfo_string7:
-	.asciz	"INTPTR"                        # string offset=203
-.Linfo_string8:
-	.asciz	"ParamUnsigned"                 # string offset=210
-.Linfo_string9:
-	.asciz	"unsigned int"                  # string offset=224
-.Linfo_string10:
-	.asciz	"ParamBool"                     # string offset=237
-.Linfo_string11:
-	.asciz	"bool"                          # string offset=247
-.Linfo_string12:
-	.asciz	"CONSTANT"                      # string offset=252
-.Linfo_string13:
-	.asciz	"INTEGER"                       # string offset=261
+	.asciz	"foo"                           # string offset=241
 	.ident	"clang version 19.0.0"
-	.section	.custom_section.producers,"",@
-	.int8	2
-	.int8	8
-	.ascii	"language"
-	.int8	1
-	.int8	14
-	.ascii	"C_plus_plus_14"
-	.int8	0
-	.int8	12
-	.ascii	"processed-by"
-	.int8	1
-	.int8	5
-	.ascii	"clang"
-	.int8	96
-	.ascii	"19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)"
-	.section	.debug_str,"S",@
-	.section	.custom_section.target_features,"",@
-	.int8	2
-	.int8	43
-	.int8	15
-	.ascii	"mutable-globals"
-	.int8	43
-	.int8	8
-	.ascii	"sign-ext"
-	.section	.debug_str,"S",@
-	.section	.debug_line,"",@
-.Lline_table_start0:



More information about the llvm-commits mailing list