From 61f0636eca17b87e3ff5f8f19dafc21247640fac Mon Sep 17 00:00:00 2001 From: Alex Borcan Date: Tue, 10 Jun 2025 22:25:05 -0700 Subject: [PATCH] [dsymutil] Fix line table sequence mapping for stmt_sequence attributes --- llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp | 33 +++++++++++++++++-- .../tools/dsymutil/ARM/stmt-seq-macho.test | 7 +++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp index ae4cc6d85c120..6cd06b6173c29 100644 --- a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp @@ -2297,8 +2297,37 @@ void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) { // Create a map of stmt sequence offsets to original row indices. DenseMap SeqOffToOrigRow; - for (const DWARFDebugLine::Sequence &Seq : LT->Sequences) - SeqOffToOrigRow[Seq.StmtSeqOffset] = Seq.FirstRowIndex; + // The DWARF parser's discovery of sequences can be incomplete. To + // ensure all DW_AT_LLVM_stmt_sequence attributes can be patched, we + // build a map from both the parser's results and a manual + // reconstruction. + if (!LT->Rows.empty()) { + // First, trust the sequences that the DWARF parser did identify. + for (const DWARFDebugLine::Sequence &Seq : LT->Sequences) + SeqOffToOrigRow.try_emplace(Seq.StmtSeqOffset, Seq.FirstRowIndex); + + // Second, manually find sequence boundaries and match them to the + // sorted attributes to handle sequences the parser might have missed. + auto StmtAttrs = Unit.getStmtSeqListAttributes(); + llvm::sort(StmtAttrs, + [](const PatchLocation &A, const PatchLocation &B) { + return A.get() < B.get(); + }); + + std::vector SeqStartRows; + SeqStartRows.push_back(0); + for (size_t i = 0; i < LT->Rows.size() - 1; ++i) + if (LT->Rows[i].EndSequence) + SeqStartRows.push_back(i + 1); + + // Correlate the sorted attributes with the reconstructed sequence + // starts. This provides a partial mapping if counts are mismatched, + // maximizing the number of correctly patched attributes. + size_t NumMappings = std::min(StmtAttrs.size(), SeqStartRows.size()); + for (size_t i = 0; i < NumMappings; ++i) { + SeqOffToOrigRow.try_emplace(StmtAttrs[i].get(), SeqStartRows[i]); + } + } // Create a map of original row indices to new row indices. DenseMap OrigRowToNewRow; diff --git a/llvm/test/tools/dsymutil/ARM/stmt-seq-macho.test b/llvm/test/tools/dsymutil/ARM/stmt-seq-macho.test index f2fe794e1b484..b6ad216bc0be3 100644 --- a/llvm/test/tools/dsymutil/ARM/stmt-seq-macho.test +++ b/llvm/test/tools/dsymutil/ARM/stmt-seq-macho.test @@ -4,7 +4,12 @@ # RUN: yaml2obj %t/stmt_seq_macho.exe.yaml -o %t/stmt_seq_macho.exe # RUN: yaml2obj %t/stmt_seq_macho.o.yaml -o %t/stmt_seq_macho.o # RUN: dsymutil --flat --verify-dwarf=none -oso-prepend-path %t %t/stmt_seq_macho.exe -o %t/stmt_seq_macho.dSYM -# RUN: llvm-dwarfdump --debug-info --debug-line -v %t/stmt_seq_macho.dSYM | sort | FileCheck %s -check-prefix=CHECK_DSYM +# RUN: llvm-dwarfdump --debug-info --debug-line -v %t/stmt_seq_macho.dSYM > %t/stmt_seq_macho.dSYM.txt +# RUN: cat %t/stmt_seq_macho.dSYM.txt | sort | FileCheck %s -check-prefix=CHECK_DSYM +# RUN: cat %t/stmt_seq_macho.dSYM.txt | FileCheck %s -check-prefix=CHECK_NO_INVALID_OFFSET + +# CHECK_NO_INVALID_OFFSET-NOT: DW_AT_LLVM_stmt_sequence{{.*}}0xffffffff + # CHECK_DSYM: DW_AT_LLVM_stmt_sequence [DW_FORM_sec_offset] ([[OFFSET1:(0x[0-9a-f]+)]]) # CHECK_DSYM: DW_AT_LLVM_stmt_sequence [DW_FORM_sec_offset] ([[OFFSET2:(0x[0-9a-f]+)]])